Line data Source code
1 : /* THIS FILE IS AUTOGENERATED FROM Blob.webidl BY Codegen.py - DO NOT EDIT */
2 :
3 : #include "AtomList.h"
4 : #include "BlobBinding.h"
5 : #include "WrapperFactory.h"
6 : #include "jsapi.h"
7 : #include "mozilla/OwningNonNull.h"
8 : #include "mozilla/dom/BindingUtils.h"
9 : #include "mozilla/dom/Blob.h"
10 : #include "mozilla/dom/DOMJSClass.h"
11 : #include "mozilla/dom/NonRefcountedDOMObject.h"
12 : #include "mozilla/dom/PrimitiveConversions.h"
13 : #include "mozilla/dom/ScriptSettings.h"
14 : #include "mozilla/dom/SimpleGlobalObject.h"
15 : #include "mozilla/dom/UnionConversions.h"
16 : #include "mozilla/dom/XrayExpandoClass.h"
17 :
18 : namespace mozilla {
19 : namespace dom {
20 :
21 : namespace EndingTypesValues {
22 : extern const EnumEntry strings[3] = {
23 : {"transparent", 11},
24 : {"native", 6},
25 : { nullptr, 0 }
26 : };
27 : } // namespace EndingTypesValues
28 :
29 : bool
30 0 : ToJSValue(JSContext* aCx, EndingTypes aArgument, JS::MutableHandle<JS::Value> aValue)
31 : {
32 0 : MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(EndingTypesValues::strings));
33 : JSString* resultStr =
34 0 : JS_NewStringCopyN(aCx, EndingTypesValues::strings[uint32_t(aArgument)].value,
35 0 : EndingTypesValues::strings[uint32_t(aArgument)].length);
36 0 : if (!resultStr) {
37 0 : return false;
38 : }
39 0 : aValue.setString(resultStr);
40 0 : return true;
41 : }
42 :
43 :
44 : void
45 0 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString& aUnion, const char* aName, uint32_t aFlags)
46 : {
47 0 : if (aUnion.IsBlob()) {
48 0 : ImplCycleCollectionTraverse(aCallback, aUnion.GetAsBlob(), "mBlob", aFlags);
49 : }
50 0 : }
51 :
52 :
53 : void
54 0 : ImplCycleCollectionUnlink(OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString& aUnion)
55 : {
56 0 : aUnion.Uninit();
57 0 : }
58 :
59 :
60 : bool
61 0 : ArrayBufferViewOrArrayBufferOrBlobOrUSVString::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
62 : {
63 0 : switch (mType) {
64 : case eUninitialized: {
65 0 : return false;
66 : break;
67 : }
68 : case eArrayBufferView: {
69 0 : rval.setObject(*mValue.mArrayBufferView.Value().Obj());
70 0 : if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
71 0 : return false;
72 : }
73 0 : return true;
74 : break;
75 : }
76 : case eArrayBuffer: {
77 0 : rval.setObject(*mValue.mArrayBuffer.Value().Obj());
78 0 : if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
79 0 : return false;
80 : }
81 0 : return true;
82 : break;
83 : }
84 : case eBlob: {
85 0 : if (!GetOrCreateDOMReflector(cx, mValue.mBlob.Value(), rval)) {
86 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
87 0 : return false;
88 : }
89 0 : return true;
90 : break;
91 : }
92 : case eUSVString: {
93 0 : if (!xpc::NonVoidStringToJsval(cx, mValue.mUSVString.Value(), rval)) {
94 0 : return false;
95 : }
96 0 : return true;
97 : break;
98 : }
99 : default: {
100 0 : return false;
101 : break;
102 : }
103 : }
104 :
105 : return false;
106 : }
107 :
108 :
109 : ArrayBufferView&
110 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::RawSetAsArrayBufferView()
111 : {
112 0 : if (mType == eArrayBufferView) {
113 0 : return mValue.mArrayBufferView.Value();
114 : }
115 0 : MOZ_ASSERT(mType == eUninitialized);
116 0 : mType = eArrayBufferView;
117 0 : return mValue.mArrayBufferView.SetValue();
118 : }
119 :
120 : ArrayBufferView&
121 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::SetAsArrayBufferView()
122 : {
123 0 : if (mType == eArrayBufferView) {
124 0 : return mValue.mArrayBufferView.Value();
125 : }
126 0 : Uninit();
127 0 : mType = eArrayBufferView;
128 0 : return mValue.mArrayBufferView.SetValue();
129 : }
130 :
131 : bool
132 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::TrySetToArrayBufferView(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
133 : {
134 0 : tryNext = false;
135 : { // scope for memberSlot
136 0 : ArrayBufferView& memberSlot = RawSetAsArrayBufferView();
137 0 : if (!memberSlot.Init(&value.toObject())) {
138 0 : DestroyArrayBufferView();
139 0 : tryNext = true;
140 0 : return true;
141 : }
142 : }
143 0 : return true;
144 : }
145 :
146 : void
147 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::DestroyArrayBufferView()
148 : {
149 0 : MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
150 0 : mValue.mArrayBufferView.Destroy();
151 0 : mType = eUninitialized;
152 0 : }
153 :
154 :
155 :
156 :
157 : ArrayBuffer&
158 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::RawSetAsArrayBuffer()
159 : {
160 0 : if (mType == eArrayBuffer) {
161 0 : return mValue.mArrayBuffer.Value();
162 : }
163 0 : MOZ_ASSERT(mType == eUninitialized);
164 0 : mType = eArrayBuffer;
165 0 : return mValue.mArrayBuffer.SetValue();
166 : }
167 :
168 : ArrayBuffer&
169 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::SetAsArrayBuffer()
170 : {
171 0 : if (mType == eArrayBuffer) {
172 0 : return mValue.mArrayBuffer.Value();
173 : }
174 0 : Uninit();
175 0 : mType = eArrayBuffer;
176 0 : return mValue.mArrayBuffer.SetValue();
177 : }
178 :
179 : bool
180 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::TrySetToArrayBuffer(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
181 : {
182 0 : tryNext = false;
183 : { // scope for memberSlot
184 0 : ArrayBuffer& memberSlot = RawSetAsArrayBuffer();
185 0 : if (!memberSlot.Init(&value.toObject())) {
186 0 : DestroyArrayBuffer();
187 0 : tryNext = true;
188 0 : return true;
189 : }
190 : }
191 0 : return true;
192 : }
193 :
194 : void
195 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::DestroyArrayBuffer()
196 : {
197 0 : MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
198 0 : mValue.mArrayBuffer.Destroy();
199 0 : mType = eUninitialized;
200 0 : }
201 :
202 :
203 :
204 :
205 : OwningNonNull<mozilla::dom::Blob>&
206 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::RawSetAsBlob()
207 : {
208 0 : if (mType == eBlob) {
209 0 : return mValue.mBlob.Value();
210 : }
211 0 : MOZ_ASSERT(mType == eUninitialized);
212 0 : mType = eBlob;
213 0 : return mValue.mBlob.SetValue();
214 : }
215 :
216 : OwningNonNull<mozilla::dom::Blob>&
217 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::SetAsBlob()
218 : {
219 0 : if (mType == eBlob) {
220 0 : return mValue.mBlob.Value();
221 : }
222 0 : Uninit();
223 0 : mType = eBlob;
224 0 : return mValue.mBlob.SetValue();
225 : }
226 :
227 : bool
228 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::TrySetToBlob(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
229 : {
230 0 : tryNext = false;
231 : { // scope for memberSlot
232 0 : OwningNonNull<mozilla::dom::Blob>& memberSlot = RawSetAsBlob();
233 : static_assert(IsRefcounted<mozilla::dom::Blob>::value, "We can only store refcounted classes.");{
234 0 : nsresult rv = UnwrapObject<prototypes::id::Blob, mozilla::dom::Blob>(value, memberSlot);
235 0 : if (NS_FAILED(rv)) {
236 0 : DestroyBlob();
237 0 : tryNext = true;
238 0 : return true;
239 : }
240 : }
241 : }
242 0 : return true;
243 : }
244 :
245 : void
246 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::DestroyBlob()
247 : {
248 0 : MOZ_ASSERT(IsBlob(), "Wrong type!");
249 0 : mValue.mBlob.Destroy();
250 0 : mType = eUninitialized;
251 0 : }
252 :
253 :
254 :
255 :
256 : nsString&
257 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::RawSetAsUSVString()
258 : {
259 0 : if (mType == eUSVString) {
260 0 : return mValue.mUSVString.Value();
261 : }
262 0 : MOZ_ASSERT(mType == eUninitialized);
263 0 : mType = eUSVString;
264 0 : return mValue.mUSVString.SetValue();
265 : }
266 :
267 : nsString&
268 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::SetAsUSVString()
269 : {
270 0 : if (mType == eUSVString) {
271 0 : return mValue.mUSVString.Value();
272 : }
273 0 : Uninit();
274 0 : mType = eUSVString;
275 0 : return mValue.mUSVString.SetValue();
276 : }
277 :
278 : bool
279 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::TrySetToUSVString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
280 : {
281 0 : tryNext = false;
282 : { // scope for memberSlot
283 0 : nsString& memberSlot = RawSetAsUSVString();
284 0 : if (!ConvertJSValueToString(cx, value, eStringify, eStringify, memberSlot)) {
285 0 : return false;
286 : }
287 0 : NormalizeUSVString(memberSlot);
288 : }
289 0 : return true;
290 : }
291 :
292 :
293 : void
294 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::DestroyUSVString()
295 : {
296 0 : MOZ_ASSERT(IsUSVString(), "Wrong type!");
297 0 : mValue.mUSVString.Destroy();
298 0 : mType = eUninitialized;
299 0 : }
300 :
301 :
302 :
303 :
304 : void
305 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::Uninit()
306 : {
307 0 : switch (mType) {
308 : case eUninitialized: {
309 0 : break;
310 : }
311 : case eArrayBufferView: {
312 0 : DestroyArrayBufferView();
313 0 : break;
314 : }
315 : case eArrayBuffer: {
316 0 : DestroyArrayBuffer();
317 0 : break;
318 : }
319 : case eBlob: {
320 0 : DestroyBlob();
321 0 : break;
322 : }
323 : case eUSVString: {
324 0 : DestroyUSVString();
325 0 : break;
326 : }
327 : }
328 0 : }
329 :
330 : bool
331 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
332 : {
333 0 : switch (mType) {
334 : case eUninitialized: {
335 0 : return false;
336 : break;
337 : }
338 : case eArrayBufferView: {
339 0 : rval.setObject(*mValue.mArrayBufferView.Value().Obj());
340 0 : if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
341 0 : return false;
342 : }
343 0 : return true;
344 : break;
345 : }
346 : case eArrayBuffer: {
347 0 : rval.setObject(*mValue.mArrayBuffer.Value().Obj());
348 0 : if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
349 0 : return false;
350 : }
351 0 : return true;
352 : break;
353 : }
354 : case eBlob: {
355 0 : if (!GetOrCreateDOMReflector(cx, mValue.mBlob.Value(), rval)) {
356 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
357 0 : return false;
358 : }
359 0 : return true;
360 : break;
361 : }
362 : case eUSVString: {
363 0 : if (!xpc::NonVoidStringToJsval(cx, mValue.mUSVString.Value(), rval)) {
364 0 : return false;
365 : }
366 0 : return true;
367 : break;
368 : }
369 : default: {
370 0 : return false;
371 : break;
372 : }
373 : }
374 :
375 : return false;
376 : }
377 :
378 : void
379 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString::TraceUnion(JSTracer* trc)
380 : {
381 0 : switch (mType) {
382 : case eArrayBufferView: {
383 0 : mValue.mArrayBufferView.Value().TraceSelf(trc);
384 0 : break;
385 : }
386 : case eArrayBuffer: {
387 0 : mValue.mArrayBuffer.Value().TraceSelf(trc);
388 0 : break;
389 : }
390 : default: {
391 0 : break;
392 : }
393 : }
394 0 : }
395 :
396 :
397 :
398 0 : BlobPropertyBag::BlobPropertyBag()
399 : {
400 : // Safe to pass a null context if we pass a null value
401 0 : Init(nullptr, JS::NullHandleValue);
402 0 : }
403 :
404 :
405 :
406 : bool
407 0 : BlobPropertyBag::InitIds(JSContext* cx, BlobPropertyBagAtoms* atomsCache)
408 : {
409 0 : MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
410 :
411 : // Initialize these in reverse order so that any failure leaves the first one
412 : // uninitialized.
413 0 : if (!atomsCache->type_id.init(cx, "type") ||
414 0 : !atomsCache->endings_id.init(cx, "endings")) {
415 0 : return false;
416 : }
417 0 : return true;
418 : }
419 :
420 : bool
421 0 : BlobPropertyBag::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
422 : {
423 : // Passing a null JSContext is OK only if we're initing from null,
424 : // Since in that case we will not have to do any property gets
425 : // Also evaluate isNullOrUndefined in order to avoid false-positive
426 : // checkers by static analysis tools
427 0 : MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
428 0 : BlobPropertyBagAtoms* atomsCache = nullptr;
429 0 : if (cx) {
430 0 : atomsCache = GetAtomCache<BlobPropertyBagAtoms>(cx);
431 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
432 0 : return false;
433 : }
434 : }
435 :
436 0 : if (!IsConvertibleToDictionary(val)) {
437 0 : return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
438 : }
439 :
440 0 : bool isNull = val.isNullOrUndefined();
441 : // We only need these if !isNull, in which case we have |cx|.
442 0 : Maybe<JS::Rooted<JSObject *> > object;
443 0 : Maybe<JS::Rooted<JS::Value> > temp;
444 0 : if (!isNull) {
445 0 : MOZ_ASSERT(cx);
446 0 : object.emplace(cx, &val.toObject());
447 0 : temp.emplace(cx);
448 : }
449 0 : if (!isNull) {
450 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->endings_id, temp.ptr())) {
451 0 : return false;
452 : }
453 : }
454 0 : if (!isNull && !temp->isUndefined()) {
455 : {
456 : int index;
457 0 : if (!FindEnumStringIndex<true>(cx, temp.ref(), EndingTypesValues::strings, "EndingTypes", "'endings' member of BlobPropertyBag", &index)) {
458 0 : return false;
459 : }
460 0 : MOZ_ASSERT(index >= 0);
461 0 : mEndings = static_cast<EndingTypes>(index);
462 : }
463 : } else {
464 0 : mEndings = EndingTypes::Transparent;
465 : }
466 0 : mIsAnyMemberPresent = true;
467 :
468 0 : if (!isNull) {
469 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->type_id, temp.ptr())) {
470 0 : return false;
471 : }
472 : }
473 0 : if (!isNull && !temp->isUndefined()) {
474 0 : if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mType)) {
475 0 : return false;
476 : }
477 : } else {
478 : static const char16_t data[] = { 0 };
479 0 : mType.Rebind(data, ArrayLength(data) - 1);
480 : }
481 0 : mIsAnyMemberPresent = true;
482 0 : return true;
483 : }
484 :
485 : bool
486 0 : BlobPropertyBag::Init(const nsAString& aJSON)
487 : {
488 0 : AutoJSAPI jsapi;
489 0 : JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
490 0 : if (!cleanGlobal) {
491 0 : return false;
492 : }
493 0 : if (!jsapi.Init(cleanGlobal)) {
494 0 : return false;
495 : }
496 0 : JSContext* cx = jsapi.cx();
497 0 : JS::Rooted<JS::Value> json(cx);
498 0 : bool ok = ParseJSON(cx, aJSON, &json);
499 0 : NS_ENSURE_TRUE(ok, false);
500 0 : return Init(cx, json);
501 : }
502 :
503 : bool
504 0 : BlobPropertyBag::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
505 : {
506 0 : BlobPropertyBagAtoms* atomsCache = GetAtomCache<BlobPropertyBagAtoms>(cx);
507 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
508 0 : return false;
509 : }
510 :
511 0 : JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
512 0 : if (!obj) {
513 0 : return false;
514 : }
515 0 : rval.set(JS::ObjectValue(*obj));
516 :
517 : do {
518 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
519 0 : JS::Rooted<JS::Value> temp(cx);
520 0 : EndingTypes const & currentValue = mEndings;
521 0 : if (!ToJSValue(cx, currentValue, &temp)) {
522 0 : return false;
523 : }
524 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->endings_id, temp, JSPROP_ENUMERATE)) {
525 0 : return false;
526 : }
527 0 : break;
528 : } while(0);
529 :
530 : do {
531 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
532 0 : JS::Rooted<JS::Value> temp(cx);
533 0 : nsString const & currentValue = mType;
534 0 : if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
535 0 : return false;
536 : }
537 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->type_id, temp, JSPROP_ENUMERATE)) {
538 0 : return false;
539 : }
540 0 : break;
541 : } while(0);
542 :
543 0 : return true;
544 : }
545 :
546 : bool
547 0 : BlobPropertyBag::ToJSON(nsAString& aJSON) const
548 : {
549 0 : AutoJSAPI jsapi;
550 0 : jsapi.Init();
551 0 : JSContext *cx = jsapi.cx();
552 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
553 : // because we'll only be creating objects, in ways that have no
554 : // side-effects, followed by a call to JS::ToJSONMaybeSafely,
555 : // which likewise guarantees no side-effects for the sorts of
556 : // things we will pass it.
557 0 : JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
558 0 : JS::Rooted<JS::Value> val(cx);
559 0 : if (!ToObjectInternal(cx, &val)) {
560 0 : return false;
561 : }
562 0 : JS::Rooted<JSObject*> obj(cx, &val.toObject());
563 0 : return StringifyToJSON(cx, obj, aJSON);
564 : }
565 :
566 : void
567 0 : BlobPropertyBag::TraceDictionary(JSTracer* trc)
568 : {
569 0 : }
570 :
571 : BlobPropertyBag&
572 0 : BlobPropertyBag::operator=(const BlobPropertyBag& aOther)
573 : {
574 0 : mEndings = aOther.mEndings;
575 0 : mType = aOther.mType;
576 0 : return *this;
577 : }
578 :
579 : namespace binding_detail {
580 : } // namespace binding_detail
581 :
582 :
583 : namespace BlobBinding {
584 :
585 : static bool
586 0 : get_size(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Blob* self, JSJitGetterCallArgs args)
587 : {
588 0 : binding_detail::FastErrorResult rv;
589 0 : uint64_t result(self->GetSize(rv));
590 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
591 0 : return false;
592 : }
593 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
594 0 : args.rval().set(JS_NumberValue(double(result)));
595 0 : return true;
596 : }
597 :
598 : static const JSJitInfo size_getterinfo = {
599 : { (JSJitGetterOp)get_size },
600 : { prototypes::id::Blob },
601 : { PrototypeTraits<prototypes::id::Blob>::Depth },
602 : JSJitInfo::Getter,
603 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
604 : JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
605 : false, /* isInfallible. False in setters. */
606 : false, /* isMovable. Not relevant for setters. */
607 : false, /* isEliminatable. Not relevant for setters. */
608 : false, /* isAlwaysInSlot. Only relevant for getters. */
609 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
610 : false, /* isTypedMethod. Only relevant for methods. */
611 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
612 : };
613 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
614 : static_assert(0 < 1, "There is no slot for us");
615 :
616 : static bool
617 0 : get_type(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Blob* self, JSJitGetterCallArgs args)
618 : {
619 0 : DOMString result;
620 0 : self->GetType(result);
621 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
622 0 : if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
623 0 : return false;
624 : }
625 0 : return true;
626 : }
627 :
628 : static const JSJitInfo type_getterinfo = {
629 : { (JSJitGetterOp)get_type },
630 : { prototypes::id::Blob },
631 : { PrototypeTraits<prototypes::id::Blob>::Depth },
632 : JSJitInfo::Getter,
633 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
634 : JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */
635 : false, /* isInfallible. False in setters. */
636 : false, /* isMovable. Not relevant for setters. */
637 : false, /* isEliminatable. Not relevant for setters. */
638 : false, /* isAlwaysInSlot. Only relevant for getters. */
639 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
640 : false, /* isTypedMethod. Only relevant for methods. */
641 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
642 : };
643 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
644 : static_assert(0 < 1, "There is no slot for us");
645 :
646 : static bool
647 0 : slice(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Blob* self, const JSJitMethodCallArgs& args)
648 : {
649 0 : Optional<int64_t> arg0;
650 0 : if (args.hasDefined(0)) {
651 0 : arg0.Construct();
652 0 : if (!ValueToPrimitive<int64_t, eClamp>(cx, args[0], &arg0.Value())) {
653 0 : return false;
654 : }
655 : }
656 0 : Optional<int64_t> arg1;
657 0 : if (args.hasDefined(1)) {
658 0 : arg1.Construct();
659 0 : if (!ValueToPrimitive<int64_t, eClamp>(cx, args[1], &arg1.Value())) {
660 0 : return false;
661 : }
662 : }
663 0 : binding_detail::FakeString arg2;
664 0 : if (args.hasDefined(2)) {
665 0 : if (!ConvertJSValueToString(cx, args[2], eStringify, eStringify, arg2)) {
666 0 : return false;
667 : }
668 : } else {
669 : static const char16_t data[] = { 0 };
670 0 : arg2.Rebind(data, ArrayLength(data) - 1);
671 : }
672 0 : binding_detail::FastErrorResult rv;
673 0 : auto result(StrongOrRawPtr<mozilla::dom::Blob>(self->Slice(Constify(arg0), Constify(arg1), NonNullHelper(Constify(arg2)), rv)));
674 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
675 0 : return false;
676 : }
677 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
678 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
679 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
680 0 : return false;
681 : }
682 0 : return true;
683 : }
684 :
685 : static const JSJitInfo slice_methodinfo = {
686 : { (JSJitGetterOp)slice },
687 : { prototypes::id::Blob },
688 : { PrototypeTraits<prototypes::id::Blob>::Depth },
689 : JSJitInfo::Method,
690 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
691 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
692 : false, /* isInfallible. False in setters. */
693 : false, /* isMovable. Not relevant for setters. */
694 : false, /* isEliminatable. Not relevant for setters. */
695 : false, /* isAlwaysInSlot. Only relevant for getters. */
696 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
697 : false, /* isTypedMethod. Only relevant for methods. */
698 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
699 : };
700 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
701 : static_assert(0 < 1, "There is no slot for us");
702 :
703 : static bool
704 0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
705 : {
706 0 : mozilla::dom::Blob* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Blob>(obj);
707 : // We don't want to preserve if we don't have a wrapper, and we
708 : // obviously can't preserve if we're not initialized.
709 0 : if (self && self->GetWrapperPreserveColor()) {
710 0 : PreserveWrapper(self);
711 : }
712 0 : return true;
713 : }
714 :
715 : static void
716 0 : _finalize(js::FreeOp* fop, JSObject* obj)
717 : {
718 0 : mozilla::dom::Blob* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Blob>(obj);
719 0 : if (self) {
720 0 : ClearWrapper(self, self, obj);
721 0 : AddForDeferredFinalization<mozilla::dom::Blob>(self);
722 : }
723 0 : }
724 :
725 : static void
726 0 : _objectMoved(JSObject* obj, const JSObject* old)
727 : {
728 0 : mozilla::dom::Blob* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Blob>(obj);
729 0 : if (self) {
730 0 : UpdateWrapper(self, self, obj, old);
731 : }
732 0 : }
733 :
734 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
735 : #if defined(__clang__)
736 : #pragma clang diagnostic push
737 : #pragma clang diagnostic ignored "-Wmissing-braces"
738 : #endif
739 : static const JSFunctionSpec sMethods_specs[] = {
740 : JS_FNSPEC("slice", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&slice_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
741 : JS_FS_END
742 : };
743 : #if defined(__clang__)
744 : #pragma clang diagnostic pop
745 : #endif
746 :
747 :
748 : // Can't be const because the pref-enabled boolean needs to be writable
749 : static Prefable<const JSFunctionSpec> sMethods[] = {
750 : { nullptr, &sMethods_specs[0] },
751 : { nullptr, nullptr }
752 : };
753 :
754 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
755 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
756 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
757 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
758 :
759 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
760 : #if defined(__clang__)
761 : #pragma clang diagnostic push
762 : #pragma clang diagnostic ignored "-Wmissing-braces"
763 : #endif
764 : static const JSPropertySpec sAttributes_specs[] = {
765 : { "size", JSPROP_SHARED | JSPROP_ENUMERATE, GenericBindingGetter, &size_getterinfo, nullptr, nullptr },
766 : { "type", JSPROP_SHARED | JSPROP_ENUMERATE, GenericBindingGetter, &type_getterinfo, nullptr, nullptr },
767 : { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
768 : };
769 : #if defined(__clang__)
770 : #pragma clang diagnostic pop
771 : #endif
772 :
773 :
774 : // Can't be const because the pref-enabled boolean needs to be writable
775 : static Prefable<const JSPropertySpec> sAttributes[] = {
776 : { nullptr, &sAttributes_specs[0] },
777 : { nullptr, nullptr }
778 : };
779 :
780 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
781 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
782 : static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
783 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
784 :
785 :
786 : static uint16_t sNativeProperties_sortedPropertyIndices[3];
787 : static PropertyInfo sNativeProperties_propertyInfos[3];
788 :
789 : static const NativePropertiesN<2> sNativeProperties = {
790 : false, 0,
791 : false, 0,
792 : true, 0 /* sMethods */,
793 : true, 1 /* sAttributes */,
794 : false, 0,
795 : false, 0,
796 : false, 0,
797 : -1,
798 : 3,
799 : sNativeProperties_sortedPropertyIndices,
800 : {
801 : { sMethods, &sNativeProperties_propertyInfos[0] },
802 : { sAttributes, &sNativeProperties_propertyInfos[1] }
803 : }
804 : };
805 : static_assert(3 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
806 : "We have a property info count that is oversized");
807 :
808 : static bool
809 0 : _constructor(JSContext* cx, unsigned argc, JS::Value* vp)
810 : {
811 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
812 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
813 0 : if (!args.isConstructing()) {
814 : // XXXbz wish I could get the name from the callee instead of
815 : // Adding more relocations
816 0 : return ThrowConstructorWithoutNew(cx, "Blob");
817 : }
818 :
819 0 : GlobalObject global(cx, obj);
820 0 : if (global.Failed()) {
821 0 : return false;
822 : }
823 :
824 0 : JS::Rooted<JSObject*> desiredProto(cx);
825 0 : if (!GetDesiredProto(cx, args, &desiredProto)) {
826 0 : return false;
827 : }
828 :
829 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
830 0 : Optional<Sequence<OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString>> arg0;
831 0 : Maybe<SequenceRooter<OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString>> arg0_holder;
832 0 : if (args.hasDefined(0)) {
833 0 : arg0.Construct();
834 0 : arg0_holder.emplace(cx, &arg0.Value());
835 0 : if (args[0].isObject()) {
836 0 : JS::ForOfIterator iter(cx);
837 0 : if (!iter.init(args[0], JS::ForOfIterator::AllowNonIterable)) {
838 0 : return false;
839 : }
840 0 : if (!iter.valueIsIterable()) {
841 0 : ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 1 of Blob.constructor");
842 0 : return false;
843 : }
844 0 : Sequence<OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString> &arr = arg0.Value();
845 0 : JS::Rooted<JS::Value> temp(cx);
846 : while (true) {
847 : bool done;
848 0 : if (!iter.next(&temp, &done)) {
849 0 : return false;
850 : }
851 0 : if (done) {
852 0 : break;
853 : }
854 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString* slotPtr = arr.AppendElement(mozilla::fallible);
855 0 : if (!slotPtr) {
856 0 : JS_ReportOutOfMemory(cx);
857 0 : return false;
858 : }
859 0 : OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString& slot = *slotPtr;
860 : {
861 0 : bool done = false, failed = false, tryNext;
862 0 : if (temp.isObject()) {
863 0 : done = (failed = !slot.TrySetToArrayBufferView(cx, temp, tryNext, false)) || !tryNext ||
864 0 : (failed = !slot.TrySetToArrayBuffer(cx, temp, tryNext, false)) || !tryNext ||
865 0 : (failed = !slot.TrySetToBlob(cx, temp, tryNext, false)) || !tryNext;
866 :
867 : }
868 0 : if (!done) {
869 : do {
870 0 : done = (failed = !slot.TrySetToUSVString(cx, temp, tryNext)) || !tryNext;
871 0 : break;
872 : } while (0);
873 : }
874 0 : if (failed) {
875 0 : return false;
876 : }
877 0 : if (!done) {
878 0 : ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Element of argument 1 of Blob.constructor", "ArrayBufferView, ArrayBuffer, Blob");
879 0 : return false;
880 : }
881 : }
882 0 : }
883 : } else {
884 0 : ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 1 of Blob.constructor");
885 0 : return false;
886 : }
887 : }
888 0 : binding_detail::FastBlobPropertyBag arg1;
889 0 : if (!arg1.Init(cx, (args.hasDefined(1)) ? args[1] : JS::NullHandleValue, "Argument 2 of Blob.constructor", false)) {
890 0 : return false;
891 : }
892 0 : Maybe<JSAutoCompartment> ac;
893 0 : if (objIsXray) {
894 0 : obj = js::CheckedUnwrap(obj);
895 0 : if (!obj) {
896 0 : return false;
897 : }
898 0 : ac.emplace(cx, obj);
899 0 : if (!JS_WrapObject(cx, &desiredProto)) {
900 0 : return false;
901 : }
902 0 : if (arg0.WasPassed()) {
903 0 : for (uint32_t indexName0 = 0; indexName0 < arg0.Value().Length(); ++indexName0) {
904 0 : if (arg0.Value()[indexName0].IsArrayBufferView()) {
905 0 : if (!arg0.Value()[indexName0].GetAsArrayBufferView().WrapIntoNewCompartment(cx)) {
906 0 : return false;
907 : }
908 : }
909 0 : else if (arg0.Value()[indexName0].IsArrayBuffer()) {
910 0 : if (!arg0.Value()[indexName0].GetAsArrayBuffer().WrapIntoNewCompartment(cx)) {
911 0 : return false;
912 : }
913 : }
914 : }
915 : }
916 : }
917 0 : binding_detail::FastErrorResult rv;
918 0 : auto result(StrongOrRawPtr<mozilla::dom::Blob>(mozilla::dom::Blob::Constructor(global, Constify(arg0), Constify(arg1), rv)));
919 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
920 0 : return false;
921 : }
922 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
923 : static_assert(!IsPointer<decltype(result)>::value,
924 : "NewObject implies that we need to keep the object alive with a strong reference.");
925 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
926 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
927 0 : return false;
928 : }
929 0 : return true;
930 : }
931 :
932 : static const js::ClassOps sInterfaceObjectClassOps = {
933 : nullptr, /* addProperty */
934 : nullptr, /* delProperty */
935 : nullptr, /* getProperty */
936 : nullptr, /* setProperty */
937 : nullptr, /* enumerate */
938 : nullptr, /* newEnumerate */
939 : nullptr, /* resolve */
940 : nullptr, /* mayResolve */
941 : nullptr, /* finalize */
942 : _constructor, /* call */
943 : nullptr, /* hasInstance */
944 : _constructor, /* construct */
945 : nullptr, /* trace */
946 : };
947 :
948 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
949 : {
950 : "Function",
951 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
952 : &sInterfaceObjectClassOps,
953 : JS_NULL_CLASS_SPEC,
954 : JS_NULL_CLASS_EXT,
955 : &sInterfaceObjectClassObjectOps
956 : },
957 : eInterface,
958 : true,
959 : prototypes::id::Blob,
960 : PrototypeTraits<prototypes::id::Blob>::Depth,
961 : sNativePropertyHooks,
962 : "function Blob() {\n [native code]\n}",
963 : JS::GetRealmFunctionPrototype
964 : };
965 :
966 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
967 : {
968 : "BlobPrototype",
969 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
970 : JS_NULL_CLASS_OPS,
971 : JS_NULL_CLASS_SPEC,
972 : JS_NULL_CLASS_EXT,
973 : JS_NULL_OBJECT_OPS
974 : },
975 : eInterfacePrototype,
976 : false,
977 : prototypes::id::Blob,
978 : PrototypeTraits<prototypes::id::Blob>::Depth,
979 : sNativePropertyHooks,
980 : "[object BlobPrototype]",
981 : JS::GetRealmObjectPrototype
982 : };
983 :
984 : JSObject*
985 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
986 : {
987 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
988 : }
989 :
990 : static const js::ClassOps sClassOps = {
991 : _addProperty, /* addProperty */
992 : nullptr, /* delProperty */
993 : nullptr, /* getProperty */
994 : nullptr, /* setProperty */
995 : nullptr, /* enumerate */
996 : nullptr, /* newEnumerate */
997 : nullptr, /* resolve */
998 : nullptr, /* mayResolve */
999 : _finalize, /* finalize */
1000 : nullptr, /* call */
1001 : nullptr, /* hasInstance */
1002 : nullptr, /* construct */
1003 : nullptr, /* trace */
1004 : };
1005 :
1006 : static const js::ClassExtension sClassExtension = {
1007 : nullptr, /* weakmapKeyDelegateOp */
1008 : _objectMoved /* objectMovedOp */
1009 : };
1010 :
1011 : static const DOMJSClass sClass = {
1012 : { "Blob",
1013 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
1014 : &sClassOps,
1015 : JS_NULL_CLASS_SPEC,
1016 : &sClassExtension,
1017 : JS_NULL_OBJECT_OPS
1018 : },
1019 : { prototypes::id::Blob, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
1020 : IsBaseOf<nsISupports, mozilla::dom::Blob >::value,
1021 : sNativePropertyHooks,
1022 : FindAssociatedGlobalForNative<mozilla::dom::Blob>::Get,
1023 : GetProtoObjectHandle,
1024 : GetCCParticipant<mozilla::dom::Blob>::Get()
1025 : };
1026 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
1027 : "Must have the right minimal number of reserved slots.");
1028 : static_assert(1 >= 1,
1029 : "Must have enough reserved slots.");
1030 :
1031 : const JSClass*
1032 0 : GetJSClass()
1033 : {
1034 0 : return sClass.ToJSClass();
1035 : }
1036 :
1037 : bool
1038 0 : Wrap(JSContext* aCx, mozilla::dom::Blob* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
1039 : {
1040 : MOZ_ASSERT(static_cast<mozilla::dom::Blob*>(aObject) ==
1041 : reinterpret_cast<mozilla::dom::Blob*>(aObject),
1042 : "Multiple inheritance for mozilla::dom::Blob is broken.");
1043 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
1044 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
1045 0 : MOZ_ASSERT(!aCache->GetWrapper(),
1046 : "You should probably not be using Wrap() directly; use "
1047 : "GetOrCreateDOMReflector instead");
1048 :
1049 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
1050 : "nsISupports must be on our primary inheritance chain");
1051 :
1052 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
1053 0 : if (!global) {
1054 0 : return false;
1055 : }
1056 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
1057 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
1058 :
1059 : // That might have ended up wrapping us already, due to the wonders
1060 : // of XBL. Check for that, and bail out as needed.
1061 0 : aReflector.set(aCache->GetWrapper());
1062 0 : if (aReflector) {
1063 : #ifdef DEBUG
1064 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
1065 : #endif // DEBUG
1066 0 : return true;
1067 : }
1068 :
1069 0 : JSAutoCompartment ac(aCx, global);
1070 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
1071 0 : if (!canonicalProto) {
1072 0 : return false;
1073 : }
1074 0 : JS::Rooted<JSObject*> proto(aCx);
1075 0 : if (aGivenProto) {
1076 0 : proto = aGivenProto;
1077 : // Unfortunately, while aGivenProto was in the compartment of aCx
1078 : // coming in, we changed compartments to that of "parent" so may need
1079 : // to wrap the proto here.
1080 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
1081 0 : if (!JS_WrapObject(aCx, &proto)) {
1082 0 : return false;
1083 : }
1084 : }
1085 : } else {
1086 0 : proto = canonicalProto;
1087 : }
1088 :
1089 0 : BindingJSObjectCreator<mozilla::dom::Blob> creator(aCx);
1090 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
1091 0 : if (!aReflector) {
1092 0 : return false;
1093 : }
1094 :
1095 0 : aCache->SetWrapper(aReflector);
1096 0 : creator.InitializationSucceeded();
1097 :
1098 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
1099 : aCache->GetWrapperPreserveColor() == aReflector);
1100 : // If proto != canonicalProto, we have to preserve our wrapper;
1101 : // otherwise we won't be able to properly recreate it later, since
1102 : // we won't know what proto to use. Note that we don't check
1103 : // aGivenProto here, since it's entirely possible (and even
1104 : // somewhat common) to have a non-null aGivenProto which is the
1105 : // same as canonicalProto.
1106 0 : if (proto != canonicalProto) {
1107 0 : PreserveWrapper(aObject);
1108 : }
1109 :
1110 0 : return true;
1111 : }
1112 :
1113 : const NativePropertyHooks sNativePropertyHooks[] = { {
1114 : nullptr,
1115 : nullptr,
1116 : nullptr,
1117 : { sNativeProperties.Upcast(), nullptr },
1118 : prototypes::id::Blob,
1119 : constructors::id::Blob,
1120 : nullptr,
1121 : &DefaultXrayExpandoObjectClass
1122 : } };
1123 :
1124 : void
1125 2 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
1126 : {
1127 4 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
1128 2 : if (!parentProto) {
1129 0 : return;
1130 : }
1131 :
1132 4 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
1133 2 : if (!constructorProto) {
1134 0 : return;
1135 : }
1136 :
1137 : static bool sIdsInited = false;
1138 2 : if (!sIdsInited && NS_IsMainThread()) {
1139 1 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
1140 0 : return;
1141 : }
1142 1 : sIdsInited = true;
1143 : }
1144 :
1145 2 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::Blob);
1146 2 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::Blob);
1147 4 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
1148 : &sPrototypeClass.mBase, protoCache,
1149 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
1150 : interfaceCache,
1151 : sNativeProperties.Upcast(),
1152 : nullptr,
1153 : "Blob", aDefineOnGlobal,
1154 : nullptr,
1155 2 : false);
1156 : }
1157 :
1158 : JS::Handle<JSObject*>
1159 2 : GetProtoObjectHandle(JSContext* aCx)
1160 : {
1161 : /* Get the interface prototype object for this class. This will create the
1162 : object as needed. */
1163 2 : bool aDefineOnGlobal = true;
1164 :
1165 : /* Make sure our global is sane. Hopefully we can remove this sometime */
1166 2 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
1167 2 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
1168 0 : return nullptr;
1169 : }
1170 :
1171 : /* Check to see whether the interface objects are already installed */
1172 2 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
1173 2 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::Blob)) {
1174 2 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
1175 1 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
1176 : }
1177 :
1178 : /*
1179 : * The object might _still_ be null, but that's OK.
1180 : *
1181 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
1182 : * traced by TraceProtoAndIfaceCache() and its contents are never
1183 : * changed after they have been set.
1184 : *
1185 : * Calling address() avoids the read read barrier that does gray
1186 : * unmarking, but it's not possible for the object to be gray here.
1187 : */
1188 :
1189 2 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::Blob);
1190 2 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
1191 2 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
1192 : }
1193 :
1194 : JSObject*
1195 0 : GetProtoObject(JSContext* aCx)
1196 : {
1197 0 : return GetProtoObjectHandle(aCx);
1198 : }
1199 :
1200 : JS::Handle<JSObject*>
1201 3 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
1202 : {
1203 : /* Get the interface object for this class. This will create the object as
1204 : needed. */
1205 :
1206 : /* Make sure our global is sane. Hopefully we can remove this sometime */
1207 3 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
1208 3 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
1209 0 : return nullptr;
1210 : }
1211 :
1212 : /* Check to see whether the interface objects are already installed */
1213 3 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
1214 3 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::Blob)) {
1215 2 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
1216 1 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
1217 : }
1218 :
1219 : /*
1220 : * The object might _still_ be null, but that's OK.
1221 : *
1222 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
1223 : * traced by TraceProtoAndIfaceCache() and its contents are never
1224 : * changed after they have been set.
1225 : *
1226 : * Calling address() avoids the read read barrier that does gray
1227 : * unmarking, but it's not possible for the object to be gray here.
1228 : */
1229 :
1230 3 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::Blob);
1231 3 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
1232 3 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
1233 : }
1234 :
1235 : JSObject*
1236 1 : GetConstructorObject(JSContext* aCx)
1237 : {
1238 1 : return GetConstructorObjectHandle(aCx);
1239 : }
1240 :
1241 : } // namespace BlobBinding
1242 :
1243 :
1244 :
1245 : } // namespace dom
1246 : } // namespace mozilla
|