Coverage Report

Created: 2018-09-25 14:53

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