Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dom/bindings/OfflineAudioContextBinding.cpp
Line
Count
Source (jump to first uncovered line)
1
/* THIS FILE IS AUTOGENERATED FROM OfflineAudioContext.webidl BY Codegen.py - DO NOT EDIT */
2
3
#include "AtomList.h"
4
#include "BaseAudioContextBinding.h"
5
#include "EventHandlerBinding.h"
6
#include "OfflineAudioContextBinding.h"
7
#include "WrapperFactory.h"
8
#include "mozilla/FloatingPoint.h"
9
#include "mozilla/OwningNonNull.h"
10
#include "mozilla/Preferences.h"
11
#include "mozilla/dom/AudioContext.h"
12
#include "mozilla/dom/BindingUtils.h"
13
#include "mozilla/dom/DOMJSClass.h"
14
#include "mozilla/dom/NonRefcountedDOMObject.h"
15
#include "mozilla/dom/Nullable.h"
16
#include "mozilla/dom/PrimitiveConversions.h"
17
#include "mozilla/dom/Promise.h"
18
#include "mozilla/dom/ScriptSettings.h"
19
#include "mozilla/dom/SimpleGlobalObject.h"
20
#include "mozilla/dom/ToJSValue.h"
21
#include "mozilla/dom/XrayExpandoClass.h"
22
23
namespace mozilla {
24
namespace dom {
25
26
namespace binding_detail {}; // Just to make sure it's known as a namespace
27
using namespace mozilla::dom::binding_detail;
28
29
30
31
OfflineAudioContextOptions::OfflineAudioContextOptions()
32
0
{
33
0
  // Safe to pass a null context if we pass a null value
34
0
  Init(nullptr, JS::NullHandleValue);
35
0
}
36
37
38
39
bool
40
OfflineAudioContextOptions::InitIds(JSContext* cx, OfflineAudioContextOptionsAtoms* atomsCache)
41
0
{
42
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
43
0
44
0
  // Initialize these in reverse order so that any failure leaves the first one
45
0
  // uninitialized.
46
0
  if (!atomsCache->sampleRate_id.init(cx, "sampleRate") ||
47
0
      !atomsCache->numberOfChannels_id.init(cx, "numberOfChannels") ||
48
0
      !atomsCache->length_id.init(cx, "length")) {
49
0
    return false;
50
0
  }
51
0
  return true;
52
0
}
53
54
bool
55
OfflineAudioContextOptions::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
56
0
{
57
0
  // Passing a null JSContext is OK only if we're initing from null,
58
0
  // Since in that case we will not have to do any property gets
59
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
60
0
  // checkers by static analysis tools
61
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
62
0
  OfflineAudioContextOptionsAtoms* atomsCache = nullptr;
63
0
  if (cx) {
64
0
    atomsCache = GetAtomCache<OfflineAudioContextOptionsAtoms>(cx);
65
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
66
0
      return false;
67
0
    }
68
0
  }
69
0
70
0
  if (!IsConvertibleToDictionary(val)) {
71
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
72
0
  }
73
0
74
0
  bool isNull = val.isNullOrUndefined();
75
0
  // We only need these if !isNull, in which case we have |cx|.
76
0
  Maybe<JS::Rooted<JSObject *> > object;
77
0
  Maybe<JS::Rooted<JS::Value> > temp;
78
0
  if (!isNull) {
79
0
    MOZ_ASSERT(cx);
80
0
    object.emplace(cx, &val.toObject());
81
0
    temp.emplace(cx);
82
0
  }
83
0
  if (!isNull) {
84
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->length_id, temp.ptr())) {
85
0
      return false;
86
0
    }
87
0
  }
88
0
  if (!isNull && !temp->isUndefined()) {
89
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mLength)) {
90
0
      return false;
91
0
    }
92
0
    mIsAnyMemberPresent = true;
93
0
  } else if (cx) {
94
0
    // Don't error out if we have no cx.  In that
95
0
    // situation the caller is default-constructing us and we'll
96
0
    // just assume they know what they're doing.
97
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
98
0
                             "'length' member of OfflineAudioContextOptions");
99
0
  }
100
0
101
0
  if (!isNull) {
102
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->numberOfChannels_id, temp.ptr())) {
103
0
      return false;
104
0
    }
105
0
  }
106
0
  if (!isNull && !temp->isUndefined()) {
107
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mNumberOfChannels)) {
108
0
      return false;
109
0
    }
110
0
  } else {
111
0
    mNumberOfChannels = 1U;
112
0
  }
113
0
  mIsAnyMemberPresent = true;
114
0
115
0
  if (!isNull) {
116
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->sampleRate_id, temp.ptr())) {
117
0
      return false;
118
0
    }
119
0
  }
120
0
  if (!isNull && !temp->isUndefined()) {
121
0
    if (!ValueToPrimitive<float, eDefault>(cx, temp.ref(), &mSampleRate)) {
122
0
      return false;
123
0
    } else if (!mozilla::IsFinite(mSampleRate)) {
124
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'sampleRate' member of OfflineAudioContextOptions");
125
0
      return false;
126
0
    }
127
0
    mIsAnyMemberPresent = true;
128
0
  } else if (cx) {
129
0
    // Don't error out if we have no cx.  In that
130
0
    // situation the caller is default-constructing us and we'll
131
0
    // just assume they know what they're doing.
132
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
133
0
                             "'sampleRate' member of OfflineAudioContextOptions");
134
0
  }
135
0
  return true;
136
0
}
137
138
bool
139
OfflineAudioContextOptions::Init(const nsAString& aJSON)
140
0
{
141
0
  AutoJSAPI jsapi;
142
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
143
0
  if (!cleanGlobal) {
144
0
    return false;
145
0
  }
146
0
  if (!jsapi.Init(cleanGlobal)) {
147
0
    return false;
148
0
  }
149
0
  JSContext* cx = jsapi.cx();
150
0
  JS::Rooted<JS::Value> json(cx);
151
0
  bool ok = ParseJSON(cx, aJSON, &json);
152
0
  NS_ENSURE_TRUE(ok, false);
153
0
  return Init(cx, json);
154
0
}
155
156
bool
157
OfflineAudioContextOptions::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
158
0
{
159
0
  OfflineAudioContextOptionsAtoms* atomsCache = GetAtomCache<OfflineAudioContextOptionsAtoms>(cx);
160
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
161
0
    return false;
162
0
  }
163
0
164
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
165
0
  if (!obj) {
166
0
    return false;
167
0
  }
168
0
  rval.set(JS::ObjectValue(*obj));
169
0
170
0
  do {
171
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
172
0
    JS::Rooted<JS::Value> temp(cx);
173
0
    uint32_t const & currentValue = mLength;
174
0
    temp.setNumber(currentValue);
175
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->length_id, temp, JSPROP_ENUMERATE)) {
176
0
      return false;
177
0
    }
178
0
    break;
179
0
  } while(false);
180
0
181
0
  do {
182
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
183
0
    JS::Rooted<JS::Value> temp(cx);
184
0
    uint32_t const & currentValue = mNumberOfChannels;
185
0
    temp.setNumber(currentValue);
186
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->numberOfChannels_id, temp, JSPROP_ENUMERATE)) {
187
0
      return false;
188
0
    }
189
0
    break;
190
0
  } while(false);
191
0
192
0
  do {
193
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
194
0
    JS::Rooted<JS::Value> temp(cx);
195
0
    float const & currentValue = mSampleRate;
196
0
    temp.set(JS_NumberValue(double(currentValue)));
197
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->sampleRate_id, temp, JSPROP_ENUMERATE)) {
198
0
      return false;
199
0
    }
200
0
    break;
201
0
  } while(false);
202
0
203
0
  return true;
204
0
}
205
206
bool
207
OfflineAudioContextOptions::ToJSON(nsAString& aJSON) const
208
0
{
209
0
  AutoJSAPI jsapi;
210
0
  jsapi.Init();
211
0
  JSContext *cx = jsapi.cx();
212
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
213
0
  // because we'll only be creating objects, in ways that have no
214
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
215
0
  // which likewise guarantees no side-effects for the sorts of
216
0
  // things we will pass it.
217
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
218
0
  JS::Rooted<JS::Value> val(cx);
219
0
  if (!ToObjectInternal(cx, &val)) {
220
0
    return false;
221
0
  }
222
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
223
0
  return StringifyToJSON(cx, obj, aJSON);
224
0
}
225
226
void
227
OfflineAudioContextOptions::TraceDictionary(JSTracer* trc)
228
0
{
229
0
}
230
231
OfflineAudioContextOptions&
232
OfflineAudioContextOptions::operator=(const OfflineAudioContextOptions& aOther)
233
0
{
234
0
  DictionaryBase::operator=(aOther);
235
0
  mLength = aOther.mLength;
236
0
  mNumberOfChannels = aOther.mNumberOfChannels;
237
0
  mSampleRate = aOther.mSampleRate;
238
0
  return *this;
239
0
}
240
241
namespace binding_detail {
242
} // namespace binding_detail
243
244
245
namespace OfflineAudioContext_Binding {
246
247
static_assert(IsRefcounted<NativeType>::value == IsRefcounted<BaseAudioContext_Binding::NativeType>::value,
248
              "Can't inherit from an interface with a different ownership model.");
249
250
MOZ_CAN_RUN_SCRIPT static bool
251
startRendering(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::AudioContext* self, const JSJitMethodCallArgs& args)
252
0
{
253
0
  AUTO_PROFILER_LABEL_FAST("OfflineAudioContext.startRendering", DOM, cx);
254
0
255
0
  FastErrorResult rv;
256
0
  auto result(StrongOrRawPtr<Promise>(self->StartRendering(rv)));
257
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
258
0
    return false;
259
0
  }
260
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
261
0
  if (!ToJSValue(cx, result, args.rval())) {
262
0
    return false;
263
0
  }
264
0
  return true;
265
0
}
266
267
MOZ_CAN_RUN_SCRIPT static bool
268
startRendering_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::AudioContext* self, const JSJitMethodCallArgs& args)
269
0
{
270
0
  bool ok = startRendering(cx, obj, self, args);
271
0
  if (ok) {
272
0
    return true;
273
0
  }
274
0
  return ConvertExceptionToPromise(cx, args.rval());
275
0
}
276
277
static const JSJitInfo startRendering_methodinfo = {
278
  { (JSJitGetterOp)startRendering_promiseWrapper },
279
  { prototypes::id::OfflineAudioContext },
280
  { PrototypeTraits<prototypes::id::OfflineAudioContext>::Depth },
281
  JSJitInfo::Method,
282
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
283
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
284
  false,  /* isInfallible. False in setters. */
285
  false,  /* isMovable.  Not relevant for setters. */
286
  false, /* isEliminatable.  Not relevant for setters. */
287
  false, /* isAlwaysInSlot.  Only relevant for getters. */
288
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
289
  false,  /* isTypedMethod.  Only relevant for methods. */
290
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
291
};
292
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
293
static_assert(0 < 1, "There is no slot for us");
294
295
MOZ_CAN_RUN_SCRIPT static bool
296
get_length(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::AudioContext* self, JSJitGetterCallArgs args)
297
0
{
298
0
  AUTO_PROFILER_LABEL_FAST("get OfflineAudioContext.length", DOM, cx);
299
0
300
0
  uint32_t result(self->Length());
301
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
302
0
  args.rval().setNumber(result);
303
0
  return true;
304
0
}
305
306
static const JSJitInfo length_getterinfo = {
307
  { (JSJitGetterOp)get_length },
308
  { prototypes::id::OfflineAudioContext },
309
  { PrototypeTraits<prototypes::id::OfflineAudioContext>::Depth },
310
  JSJitInfo::Getter,
311
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
312
  JSVAL_TYPE_DOUBLE,  /* returnType.  Not relevant for setters. */
313
  true,  /* isInfallible. False in setters. */
314
  false,  /* isMovable.  Not relevant for setters. */
315
  false, /* isEliminatable.  Not relevant for setters. */
316
  false, /* isAlwaysInSlot.  Only relevant for getters. */
317
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
318
  false,  /* isTypedMethod.  Only relevant for methods. */
319
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
320
};
321
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
322
static_assert(0 < 1, "There is no slot for us");
323
324
MOZ_CAN_RUN_SCRIPT static bool
325
get_oncomplete(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::AudioContext* self, JSJitGetterCallArgs args)
326
0
{
327
0
  AUTO_PROFILER_LABEL_FAST("get OfflineAudioContext.oncomplete", DOM, cx);
328
0
329
0
  RefPtr<EventHandlerNonNull> result(self->GetOncomplete());
330
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
331
0
  if (result) {
332
0
    args.rval().setObjectOrNull(GetCallbackFromCallbackObject(cx, result));
333
0
    if (!MaybeWrapObjectOrNullValue(cx, args.rval())) {
334
0
      return false;
335
0
    }
336
0
    return true;
337
0
  } else {
338
0
    args.rval().setNull();
339
0
    return true;
340
0
  }
341
0
}
342
343
MOZ_CAN_RUN_SCRIPT static bool
344
set_oncomplete(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::AudioContext* self, JSJitSetterCallArgs args)
345
0
{
346
0
  AUTO_PROFILER_LABEL_FAST("set OfflineAudioContext.oncomplete", DOM, cx);
347
0
348
0
  RootedCallback<RefPtr<binding_detail::FastEventHandlerNonNull>> arg0(cx);
349
0
  if (args[0].isObject()) {
350
0
    { // scope for tempRoot and tempGlobalRoot if needed
351
0
      arg0 = new binding_detail::FastEventHandlerNonNull(&args[0].toObject(), JS::CurrentGlobalOrNull(cx));
352
0
    }
353
0
  } else {
354
0
    arg0 = nullptr;
355
0
  }
356
0
  self->SetOncomplete(Constify(arg0));
357
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
358
0
359
0
  return true;
360
0
}
361
362
static const JSJitInfo oncomplete_getterinfo = {
363
  { (JSJitGetterOp)get_oncomplete },
364
  { prototypes::id::OfflineAudioContext },
365
  { PrototypeTraits<prototypes::id::OfflineAudioContext>::Depth },
366
  JSJitInfo::Getter,
367
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
368
  JSVAL_TYPE_UNKNOWN,  /* returnType.  Not relevant for setters. */
369
  false,  /* isInfallible. False in setters. */
370
  false,  /* isMovable.  Not relevant for setters. */
371
  false, /* isEliminatable.  Not relevant for setters. */
372
  false, /* isAlwaysInSlot.  Only relevant for getters. */
373
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
374
  false,  /* isTypedMethod.  Only relevant for methods. */
375
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
376
};
377
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
378
static_assert(0 < 1, "There is no slot for us");
379
static const JSJitInfo oncomplete_setterinfo = {
380
  { (JSJitGetterOp)set_oncomplete },
381
  { prototypes::id::OfflineAudioContext },
382
  { PrototypeTraits<prototypes::id::OfflineAudioContext>::Depth },
383
  JSJitInfo::Setter,
384
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
385
  JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
386
  false,  /* isInfallible. False in setters. */
387
  false,  /* isMovable.  Not relevant for setters. */
388
  false, /* isEliminatable.  Not relevant for setters. */
389
  false, /* isAlwaysInSlot.  Only relevant for getters. */
390
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
391
  false,  /* isTypedMethod.  Only relevant for methods. */
392
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
393
};
394
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
395
static_assert(0 < 1, "There is no slot for us");
396
397
static bool
398
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
399
0
{
400
0
  mozilla::dom::AudioContext* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AudioContext>(obj);
401
0
  // We don't want to preserve if we don't have a wrapper, and we
402
0
  // obviously can't preserve if we're not initialized.
403
0
  if (self && self->GetWrapperPreserveColor()) {
404
0
    PreserveWrapper(self);
405
0
  }
406
0
  return true;
407
0
}
408
409
static void
410
_finalize(js::FreeOp* fop, JSObject* obj)
411
0
{
412
0
  mozilla::dom::AudioContext* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AudioContext>(obj);
413
0
  if (self) {
414
0
    ClearWrapper(self, self, obj);
415
0
    AddForDeferredFinalization<mozilla::dom::AudioContext>(self);
416
0
  }
417
0
}
418
419
static size_t
420
_objectMoved(JSObject* obj, JSObject* old)
421
0
{
422
0
  mozilla::dom::AudioContext* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AudioContext>(obj);
423
0
  if (self) {
424
0
    UpdateWrapper(self, self, obj, old);
425
0
  }
426
0
427
0
  return 0;
428
0
}
429
430
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
431
#if defined(__clang__)
432
#pragma clang diagnostic push
433
#pragma clang diagnostic ignored "-Wmissing-braces"
434
#endif
435
static const JSFunctionSpec sMethods_specs[] = {
436
  JS_FNSPEC("startRendering", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&startRendering_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
437
  JS_FS_END
438
};
439
#if defined(__clang__)
440
#pragma clang diagnostic pop
441
#endif
442
443
444
static const Prefable<const JSFunctionSpec> sMethods[] = {
445
  { nullptr, &sMethods_specs[0] },
446
  { nullptr, nullptr }
447
};
448
449
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
450
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
451
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
452
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
453
454
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
455
#if defined(__clang__)
456
#pragma clang diagnostic push
457
#pragma clang diagnostic ignored "-Wmissing-braces"
458
#endif
459
static const JSPropertySpec sAttributes_specs[] = {
460
  { "length", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &length_getterinfo, nullptr, nullptr },
461
  { "oncomplete", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &oncomplete_getterinfo, GenericSetter<NormalThisPolicy>, &oncomplete_setterinfo },
462
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
463
};
464
#if defined(__clang__)
465
#pragma clang diagnostic pop
466
#endif
467
468
469
static const Prefable<const JSPropertySpec> sAttributes[] = {
470
  { nullptr, &sAttributes_specs[0] },
471
  { nullptr, nullptr }
472
};
473
474
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
475
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
476
static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
477
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
478
479
480
static uint16_t sNativeProperties_sortedPropertyIndices[3];
481
static PropertyInfo sNativeProperties_propertyInfos[3];
482
483
static const NativePropertiesN<2> sNativeProperties = {
484
  false, 0,
485
  false, 0,
486
  true,  0 /* sMethods */,
487
  true,  1 /* sAttributes */,
488
  false, 0,
489
  false, 0,
490
  false, 0,
491
  -1,
492
  3,
493
  sNativeProperties_sortedPropertyIndices,
494
  {
495
    { sMethods, &sNativeProperties_propertyInfos[0] },
496
    { sAttributes, &sNativeProperties_propertyInfos[1] }
497
  }
498
};
499
static_assert(3 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
500
    "We have a property info count that is oversized");
501
502
static bool
503
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
504
0
{
505
0
  AUTO_PROFILER_LABEL_FAST("OfflineAudioContext constructor", DOM, cx);
506
0
507
0
  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
508
0
  JS::Rooted<JSObject*> obj(cx, &args.callee());
509
0
  if (!args.isConstructing()) {
510
0
    // XXXbz wish I could get the name from the callee instead of
511
0
    // Adding more relocations
512
0
    return ThrowConstructorWithoutNew(cx, "OfflineAudioContext");
513
0
  }
514
0
515
0
  JS::Rooted<JSObject*> desiredProto(cx);
516
0
  if (!GetDesiredProto(cx, args, &desiredProto)) {
517
0
    return false;
518
0
  }
519
0
520
0
  unsigned argcount = std::min(args.length(), 3u);
521
0
  switch (argcount) {
522
0
    case 1: {
523
0
      GlobalObject global(cx, obj);
524
0
      if (global.Failed()) {
525
0
        return false;
526
0
      }
527
0
528
0
      bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
529
0
      binding_detail::FastOfflineAudioContextOptions arg0;
530
0
      if (!arg0.Init(cx, args[0],  "Argument 1 of OfflineAudioContext.constructor", false)) {
531
0
        return false;
532
0
      }
533
0
      Maybe<JSAutoRealm> ar;
534
0
      if (objIsXray) {
535
0
        obj = js::CheckedUnwrap(obj);
536
0
        if (!obj) {
537
0
          return false;
538
0
        }
539
0
        ar.emplace(cx, obj);
540
0
        if (!JS_WrapObject(cx, &desiredProto)) {
541
0
          return false;
542
0
        }
543
0
      }
544
0
      FastErrorResult rv;
545
0
      auto result(StrongOrRawPtr<mozilla::dom::AudioContext>(mozilla::dom::AudioContext::Constructor(global, Constify(arg0), rv)));
546
0
      if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
547
0
        return false;
548
0
      }
549
0
      MOZ_ASSERT(!JS_IsExceptionPending(cx));
550
0
      static_assert(!IsPointer<decltype(result)>::value,
551
0
                    "NewObject implies that we need to keep the object alive with a strong reference.");
552
0
      if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
553
0
        MOZ_ASSERT(JS_IsExceptionPending(cx));
554
0
        return false;
555
0
      }
556
0
      return true;
557
0
      break;
558
0
    }
559
0
    case 3: {
560
0
      GlobalObject global(cx, obj);
561
0
      if (global.Failed()) {
562
0
        return false;
563
0
      }
564
0
565
0
      bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
566
0
      uint32_t arg0;
567
0
      if (!ValueToPrimitive<uint32_t, eDefault>(cx, args[0], &arg0)) {
568
0
        return false;
569
0
      }
570
0
      uint32_t arg1;
571
0
      if (!ValueToPrimitive<uint32_t, eDefault>(cx, args[1], &arg1)) {
572
0
        return false;
573
0
      }
574
0
      float arg2;
575
0
      if (!ValueToPrimitive<float, eDefault>(cx, args[2], &arg2)) {
576
0
        return false;
577
0
      } else if (!mozilla::IsFinite(arg2)) {
578
0
        ThrowErrorMessage(cx, MSG_NOT_FINITE, "Argument 3 of OfflineAudioContext.constructor");
579
0
        return false;
580
0
      }
581
0
      Maybe<JSAutoRealm> ar;
582
0
      if (objIsXray) {
583
0
        obj = js::CheckedUnwrap(obj);
584
0
        if (!obj) {
585
0
          return false;
586
0
        }
587
0
        ar.emplace(cx, obj);
588
0
        if (!JS_WrapObject(cx, &desiredProto)) {
589
0
          return false;
590
0
        }
591
0
      }
592
0
      FastErrorResult rv;
593
0
      auto result(StrongOrRawPtr<mozilla::dom::AudioContext>(mozilla::dom::AudioContext::Constructor(global, arg0, arg1, arg2, rv)));
594
0
      if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
595
0
        return false;
596
0
      }
597
0
      MOZ_ASSERT(!JS_IsExceptionPending(cx));
598
0
      static_assert(!IsPointer<decltype(result)>::value,
599
0
                    "NewObject implies that we need to keep the object alive with a strong reference.");
600
0
      if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
601
0
        MOZ_ASSERT(JS_IsExceptionPending(cx));
602
0
        return false;
603
0
      }
604
0
      return true;
605
0
      break;
606
0
    }
607
0
    default: {
608
0
      return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "OfflineAudioContext");
609
0
      break;
610
0
    }
611
0
  }
612
0
  MOZ_CRASH("We have an always-returning default case");
613
0
  return false;
614
0
}
615
616
static const js::ClassOps sInterfaceObjectClassOps = {
617
    nullptr,               /* addProperty */
618
    nullptr,               /* delProperty */
619
    nullptr,               /* enumerate */
620
    nullptr,               /* newEnumerate */
621
    nullptr,               /* resolve */
622
    nullptr,               /* mayResolve */
623
    nullptr,               /* finalize */
624
    _constructor, /* call */
625
    nullptr,               /* hasInstance */
626
    _constructor, /* construct */
627
    nullptr,               /* trace */
628
};
629
630
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
631
  {
632
    "Function",
633
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
634
    &sInterfaceObjectClassOps,
635
    JS_NULL_CLASS_SPEC,
636
    JS_NULL_CLASS_EXT,
637
    &sInterfaceObjectClassObjectOps
638
  },
639
  eInterface,
640
  true,
641
  prototypes::id::OfflineAudioContext,
642
  PrototypeTraits<prototypes::id::OfflineAudioContext>::Depth,
643
  sNativePropertyHooks,
644
  "function OfflineAudioContext() {\n    [native code]\n}",
645
  BaseAudioContext_Binding::GetConstructorObject
646
};
647
648
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
649
  {
650
    "OfflineAudioContextPrototype",
651
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
652
    JS_NULL_CLASS_OPS,
653
    JS_NULL_CLASS_SPEC,
654
    JS_NULL_CLASS_EXT,
655
    JS_NULL_OBJECT_OPS
656
  },
657
  eInterfacePrototype,
658
  false,
659
  prototypes::id::OfflineAudioContext,
660
  PrototypeTraits<prototypes::id::OfflineAudioContext>::Depth,
661
  sNativePropertyHooks,
662
  "[object OfflineAudioContextPrototype]",
663
  BaseAudioContext_Binding::GetProtoObject
664
};
665
666
bool
667
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
668
0
{
669
0
  static bool sPrefValue;
670
0
  static bool sPrefCacheSetUp = false;
671
0
  if (!sPrefCacheSetUp) {
672
0
    sPrefCacheSetUp = true;
673
0
    Preferences::AddBoolVarCache(&sPrefValue, "dom.webaudio.enabled");
674
0
  }
675
0
676
0
  return sPrefValue;
677
0
}
678
679
static const js::ClassOps sClassOps = {
680
  _addProperty, /* addProperty */
681
  nullptr,               /* delProperty */
682
  nullptr,               /* enumerate */
683
  nullptr, /* newEnumerate */
684
  nullptr, /* resolve */
685
  nullptr, /* mayResolve */
686
  _finalize, /* finalize */
687
  nullptr, /* call */
688
  nullptr,               /* hasInstance */
689
  nullptr,               /* construct */
690
  nullptr, /* trace */
691
};
692
693
static const js::ClassExtension sClassExtension = {
694
  nullptr, /* weakmapKeyDelegateOp */
695
  _objectMoved /* objectMovedOp */
696
};
697
698
static const DOMJSClass sClass = {
699
  { "OfflineAudioContext",
700
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
701
    &sClassOps,
702
    JS_NULL_CLASS_SPEC,
703
    &sClassExtension,
704
    JS_NULL_OBJECT_OPS
705
  },
706
  { prototypes::id::EventTarget, prototypes::id::BaseAudioContext, prototypes::id::OfflineAudioContext, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
707
  IsBaseOf<nsISupports, mozilla::dom::AudioContext >::value,
708
  sNativePropertyHooks,
709
  FindAssociatedGlobalForNative<mozilla::dom::AudioContext>::Get,
710
  GetProtoObjectHandle,
711
  GetCCParticipant<mozilla::dom::AudioContext>::Get()
712
};
713
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
714
              "Must have the right minimal number of reserved slots.");
715
static_assert(1 >= 1,
716
              "Must have enough reserved slots.");
717
718
const JSClass*
719
GetJSClass()
720
0
{
721
0
  return sClass.ToJSClass();
722
0
}
723
724
bool
725
Wrap(JSContext* aCx, mozilla::dom::AudioContext* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
726
0
{
727
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, mozilla::dom::AudioContext>::value,
728
0
                "Shouldn't have wrappercached things that are not refcounted.");
729
0
  MOZ_ASSERT(static_cast<mozilla::dom::AudioContext*>(aObject) ==
730
0
             reinterpret_cast<mozilla::dom::AudioContext*>(aObject),
731
0
             "Multiple inheritance for mozilla::dom::AudioContext is broken.");
732
0
  MOZ_ASSERT(static_cast<mozilla::dom::AudioContext*>(aObject) ==
733
0
             reinterpret_cast<mozilla::dom::AudioContext*>(aObject),
734
0
             "Multiple inheritance for mozilla::dom::AudioContext is broken.");
735
0
  MOZ_ASSERT(static_cast<mozilla::dom::EventTarget*>(aObject) ==
736
0
             reinterpret_cast<mozilla::dom::EventTarget*>(aObject),
737
0
             "Multiple inheritance for mozilla::dom::EventTarget is broken.");
738
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
739
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
740
0
  MOZ_ASSERT(!aCache->GetWrapper(),
741
0
             "You should probably not be using Wrap() directly; use "
742
0
             "GetOrCreateDOMReflector instead");
743
0
744
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
745
0
             "nsISupports must be on our primary inheritance chain");
746
0
747
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
748
0
  if (!global) {
749
0
    return false;
750
0
  }
751
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
752
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
753
0
754
0
  // That might have ended up wrapping us already, due to the wonders
755
0
  // of XBL.  Check for that, and bail out as needed.
756
0
  aReflector.set(aCache->GetWrapper());
757
0
  if (aReflector) {
758
#ifdef DEBUG
759
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
760
#endif // DEBUG
761
    return true;
762
0
  }
763
0
764
0
  JSAutoRealm ar(aCx, global);
765
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
766
0
  if (!canonicalProto) {
767
0
    return false;
768
0
  }
769
0
  JS::Rooted<JSObject*> proto(aCx);
770
0
  if (aGivenProto) {
771
0
    proto = aGivenProto;
772
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
773
0
    // coming in, we changed compartments to that of "parent" so may need
774
0
    // to wrap the proto here.
775
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
776
0
      if (!JS_WrapObject(aCx, &proto)) {
777
0
        return false;
778
0
      }
779
0
    }
780
0
  } else {
781
0
    proto = canonicalProto;
782
0
  }
783
0
784
0
  BindingJSObjectCreator<mozilla::dom::AudioContext> creator(aCx);
785
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
786
0
  if (!aReflector) {
787
0
    return false;
788
0
  }
789
0
790
0
  aCache->SetWrapper(aReflector);
791
0
  creator.InitializationSucceeded();
792
0
793
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
794
0
             aCache->GetWrapperPreserveColor() == aReflector);
795
0
  // If proto != canonicalProto, we have to preserve our wrapper;
796
0
  // otherwise we won't be able to properly recreate it later, since
797
0
  // we won't know what proto to use.  Note that we don't check
798
0
  // aGivenProto here, since it's entirely possible (and even
799
0
  // somewhat common) to have a non-null aGivenProto which is the
800
0
  // same as canonicalProto.
801
0
  if (proto != canonicalProto) {
802
0
    PreserveWrapper(aObject);
803
0
  }
804
0
805
0
  return true;
806
0
}
807
808
const NativePropertyHooks sNativePropertyHooks[] = { {
809
  nullptr,
810
  nullptr,
811
  nullptr,
812
  { sNativeProperties.Upcast(), nullptr },
813
  prototypes::id::OfflineAudioContext,
814
  constructors::id::OfflineAudioContext,
815
  BaseAudioContext_Binding::sNativePropertyHooks,
816
  &DefaultXrayExpandoObjectClass
817
} };
818
819
void
820
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
821
0
{
822
0
  JS::Handle<JSObject*> parentProto(BaseAudioContext_Binding::GetProtoObjectHandle(aCx));
823
0
  if (!parentProto) {
824
0
    return;
825
0
  }
826
0
827
0
  JS::Handle<JSObject*> constructorProto(BaseAudioContext_Binding::GetConstructorObjectHandle(aCx));
828
0
  if (!constructorProto) {
829
0
    return;
830
0
  }
831
0
832
0
  static bool sIdsInited = false;
833
0
  if (!sIdsInited && NS_IsMainThread()) {
834
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
835
0
      return;
836
0
    }
837
0
    sIdsInited = true;
838
0
  }
839
0
840
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::OfflineAudioContext);
841
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::OfflineAudioContext);
842
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
843
0
                              &sPrototypeClass.mBase, protoCache,
844
0
                              nullptr,
845
0
                              constructorProto, &sInterfaceObjectClass.mBase, 1, nullptr,
846
0
                              interfaceCache,
847
0
                              sNativeProperties.Upcast(),
848
0
                              nullptr,
849
0
                              "OfflineAudioContext", aDefineOnGlobal,
850
0
                              nullptr,
851
0
                              false);
852
0
}
853
854
JSObject*
855
GetConstructorObject(JSContext* aCx)
856
0
{
857
0
  return GetConstructorObjectHandle(aCx);
858
0
}
859
860
} // namespace OfflineAudioContext_Binding
861
862
863
864
} // namespace dom
865
} // namespace mozilla