Coverage Report

Created: 2018-09-25 14:53

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