Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dom/bindings/RTCStatsReportBinding.cpp
Line
Count
Source (jump to first uncovered line)
1
/* THIS FILE IS AUTOGENERATED FROM RTCStatsReport.webidl BY Codegen.py - DO NOT EDIT */
2
3
#include "AtomList.h"
4
#include "RTCStatsReportBinding.h"
5
#include "WrapperFactory.h"
6
#include "XrayWrapper.h"
7
#include "jsapi.h"
8
#include "mozilla/FloatingPoint.h"
9
#include "mozilla/OwningNonNull.h"
10
#include "mozilla/Preferences.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/ToJSValue.h"
18
#include "mozilla/dom/XrayExpandoClass.h"
19
#include "nsContentUtils.h"
20
#include "nsIGlobalObject.h"
21
22
namespace mozilla {
23
namespace dom {
24
25
namespace binding_detail {}; // Just to make sure it's known as a namespace
26
using namespace mozilla::dom::binding_detail;
27
28
29
namespace RTCStatsTypeValues {
30
extern const EnumEntry strings[10] = {
31
  {"inbound-rtp", 11},
32
  {"outbound-rtp", 12},
33
  {"csrc", 4},
34
  {"session", 7},
35
  {"track", 5},
36
  {"transport", 9},
37
  {"candidate-pair", 14},
38
  {"local-candidate", 15},
39
  {"remote-candidate", 16},
40
  { nullptr, 0 }
41
};
42
} // namespace RTCStatsTypeValues
43
44
bool
45
ToJSValue(JSContext* aCx, RTCStatsType aArgument, JS::MutableHandle<JS::Value> aValue)
46
0
{
47
0
  MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(RTCStatsTypeValues::strings));
48
0
  JSString* resultStr =
49
0
    JS_NewStringCopyN(aCx, RTCStatsTypeValues::strings[uint32_t(aArgument)].value,
50
0
                      RTCStatsTypeValues::strings[uint32_t(aArgument)].length);
51
0
  if (!resultStr) {
52
0
    return false;
53
0
  }
54
0
  aValue.setString(resultStr);
55
0
  return true;
56
0
}
57
58
59
namespace RTCStatsIceCandidatePairStateValues {
60
extern const EnumEntry strings[7] = {
61
  {"frozen", 6},
62
  {"waiting", 7},
63
  {"inprogress", 10},
64
  {"failed", 6},
65
  {"succeeded", 9},
66
  {"cancelled", 9},
67
  { nullptr, 0 }
68
};
69
} // namespace RTCStatsIceCandidatePairStateValues
70
71
bool
72
ToJSValue(JSContext* aCx, RTCStatsIceCandidatePairState aArgument, JS::MutableHandle<JS::Value> aValue)
73
0
{
74
0
  MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(RTCStatsIceCandidatePairStateValues::strings));
75
0
  JSString* resultStr =
76
0
    JS_NewStringCopyN(aCx, RTCStatsIceCandidatePairStateValues::strings[uint32_t(aArgument)].value,
77
0
                      RTCStatsIceCandidatePairStateValues::strings[uint32_t(aArgument)].length);
78
0
  if (!resultStr) {
79
0
    return false;
80
0
  }
81
0
  aValue.setString(resultStr);
82
0
  return true;
83
0
}
84
85
86
namespace RTCStatsIceCandidateTypeValues {
87
extern const EnumEntry strings[5] = {
88
  {"host", 4},
89
  {"serverreflexive", 15},
90
  {"peerreflexive", 13},
91
  {"relayed", 7},
92
  { nullptr, 0 }
93
};
94
} // namespace RTCStatsIceCandidateTypeValues
95
96
bool
97
ToJSValue(JSContext* aCx, RTCStatsIceCandidateType aArgument, JS::MutableHandle<JS::Value> aValue)
98
0
{
99
0
  MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(RTCStatsIceCandidateTypeValues::strings));
100
0
  JSString* resultStr =
101
0
    JS_NewStringCopyN(aCx, RTCStatsIceCandidateTypeValues::strings[uint32_t(aArgument)].value,
102
0
                      RTCStatsIceCandidateTypeValues::strings[uint32_t(aArgument)].length);
103
0
  if (!resultStr) {
104
0
    return false;
105
0
  }
106
0
  aValue.setString(resultStr);
107
0
  return true;
108
0
}
109
110
111
112
RTCStats::RTCStats()
113
0
{
114
0
  // Safe to pass a null context if we pass a null value
115
0
  Init(nullptr, JS::NullHandleValue);
116
0
}
117
118
119
120
bool
121
RTCStats::InitIds(JSContext* cx, RTCStatsAtoms* atomsCache)
122
0
{
123
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
124
0
125
0
  // Initialize these in reverse order so that any failure leaves the first one
126
0
  // uninitialized.
127
0
  if (!atomsCache->type_id.init(cx, "type") ||
128
0
      !atomsCache->timestamp_id.init(cx, "timestamp") ||
129
0
      !atomsCache->id_id.init(cx, "id")) {
130
0
    return false;
131
0
  }
132
0
  return true;
133
0
}
134
135
bool
136
RTCStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
137
0
{
138
0
  // Passing a null JSContext is OK only if we're initing from null,
139
0
  // Since in that case we will not have to do any property gets
140
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
141
0
  // checkers by static analysis tools
142
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
143
0
  RTCStatsAtoms* atomsCache = nullptr;
144
0
  if (cx) {
145
0
    atomsCache = GetAtomCache<RTCStatsAtoms>(cx);
146
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
147
0
      return false;
148
0
    }
149
0
  }
150
0
151
0
  if (!IsConvertibleToDictionary(val)) {
152
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
153
0
  }
154
0
155
0
  bool isNull = val.isNullOrUndefined();
156
0
  // We only need these if !isNull, in which case we have |cx|.
157
0
  Maybe<JS::Rooted<JSObject *> > object;
158
0
  Maybe<JS::Rooted<JS::Value> > temp;
159
0
  if (!isNull) {
160
0
    MOZ_ASSERT(cx);
161
0
    object.emplace(cx, &val.toObject());
162
0
    temp.emplace(cx);
163
0
  }
164
0
  if (!isNull) {
165
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->id_id, temp.ptr())) {
166
0
      return false;
167
0
    }
168
0
  }
169
0
  if (!isNull && !temp->isUndefined()) {
170
0
    mId.Construct();
171
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mId.Value()))) {
172
0
      return false;
173
0
    }
174
0
    mIsAnyMemberPresent = true;
175
0
  }
176
0
177
0
  if (!isNull) {
178
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->timestamp_id, temp.ptr())) {
179
0
      return false;
180
0
    }
181
0
  }
182
0
  if (!isNull && !temp->isUndefined()) {
183
0
    mTimestamp.Construct();
184
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mTimestamp.Value()))) {
185
0
      return false;
186
0
    } else if (!mozilla::IsFinite((mTimestamp.Value()))) {
187
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'timestamp' member of RTCStats");
188
0
      return false;
189
0
    }
190
0
    mIsAnyMemberPresent = true;
191
0
  }
192
0
193
0
  if (!isNull) {
194
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->type_id, temp.ptr())) {
195
0
      return false;
196
0
    }
197
0
  }
198
0
  if (!isNull && !temp->isUndefined()) {
199
0
    mType.Construct();
200
0
    {
201
0
      int index;
202
0
      if (!FindEnumStringIndex<true>(cx, temp.ref(), RTCStatsTypeValues::strings, "RTCStatsType", "'type' member of RTCStats", &index)) {
203
0
        return false;
204
0
      }
205
0
      MOZ_ASSERT(index >= 0);
206
0
      (mType.Value()) = static_cast<RTCStatsType>(index);
207
0
    }
208
0
    mIsAnyMemberPresent = true;
209
0
  }
210
0
  return true;
211
0
}
212
213
bool
214
RTCStats::Init(const nsAString& aJSON)
215
0
{
216
0
  AutoJSAPI jsapi;
217
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
218
0
  if (!cleanGlobal) {
219
0
    return false;
220
0
  }
221
0
  if (!jsapi.Init(cleanGlobal)) {
222
0
    return false;
223
0
  }
224
0
  JSContext* cx = jsapi.cx();
225
0
  JS::Rooted<JS::Value> json(cx);
226
0
  bool ok = ParseJSON(cx, aJSON, &json);
227
0
  NS_ENSURE_TRUE(ok, false);
228
0
  return Init(cx, json);
229
0
}
230
231
bool
232
RTCStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
233
0
{
234
0
  RTCStatsAtoms* atomsCache = GetAtomCache<RTCStatsAtoms>(cx);
235
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
236
0
    return false;
237
0
  }
238
0
239
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
240
0
  if (!obj) {
241
0
    return false;
242
0
  }
243
0
  rval.set(JS::ObjectValue(*obj));
244
0
245
0
  if (mId.WasPassed()) {
246
0
    do {
247
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
248
0
      JS::Rooted<JS::Value> temp(cx);
249
0
      nsString const & currentValue = mId.InternalValue();
250
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
251
0
        return false;
252
0
      }
253
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->id_id, temp, JSPROP_ENUMERATE)) {
254
0
        return false;
255
0
      }
256
0
      break;
257
0
    } while(false);
258
0
  }
259
0
260
0
  if (mTimestamp.WasPassed()) {
261
0
    do {
262
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
263
0
      JS::Rooted<JS::Value> temp(cx);
264
0
      double const & currentValue = mTimestamp.InternalValue();
265
0
      temp.set(JS_NumberValue(double(currentValue)));
266
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->timestamp_id, temp, JSPROP_ENUMERATE)) {
267
0
        return false;
268
0
      }
269
0
      break;
270
0
    } while(false);
271
0
  }
272
0
273
0
  if (mType.WasPassed()) {
274
0
    do {
275
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
276
0
      JS::Rooted<JS::Value> temp(cx);
277
0
      RTCStatsType const & currentValue = mType.InternalValue();
278
0
      if (!ToJSValue(cx, currentValue, &temp)) {
279
0
        return false;
280
0
      }
281
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->type_id, temp, JSPROP_ENUMERATE)) {
282
0
        return false;
283
0
      }
284
0
      break;
285
0
    } while(false);
286
0
  }
287
0
288
0
  return true;
289
0
}
290
291
bool
292
RTCStats::ToJSON(nsAString& aJSON) const
293
0
{
294
0
  AutoJSAPI jsapi;
295
0
  jsapi.Init();
296
0
  JSContext *cx = jsapi.cx();
297
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
298
0
  // because we'll only be creating objects, in ways that have no
299
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
300
0
  // which likewise guarantees no side-effects for the sorts of
301
0
  // things we will pass it.
302
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
303
0
  JS::Rooted<JS::Value> val(cx);
304
0
  if (!ToObjectInternal(cx, &val)) {
305
0
    return false;
306
0
  }
307
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
308
0
  return StringifyToJSON(cx, obj, aJSON);
309
0
}
310
311
void
312
RTCStats::TraceDictionary(JSTracer* trc)
313
0
{
314
0
}
315
316
RTCStats&
317
RTCStats::operator=(const RTCStats& aOther)
318
0
{
319
0
  DictionaryBase::operator=(aOther);
320
0
  mId.Reset();
321
0
  if (aOther.mId.WasPassed()) {
322
0
    mId.Construct(aOther.mId.Value());
323
0
  }
324
0
  mTimestamp.Reset();
325
0
  if (aOther.mTimestamp.WasPassed()) {
326
0
    mTimestamp.Construct(aOther.mTimestamp.Value());
327
0
  }
328
0
  mType.Reset();
329
0
  if (aOther.mType.WasPassed()) {
330
0
    mType.Construct(aOther.mType.Value());
331
0
  }
332
0
  return *this;
333
0
}
334
335
namespace binding_detail {
336
} // namespace binding_detail
337
338
339
340
RTCCodecStats::RTCCodecStats()
341
  : RTCStats(FastDictionaryInitializer())
342
0
{
343
0
  // Safe to pass a null context if we pass a null value
344
0
  Init(nullptr, JS::NullHandleValue);
345
0
}
346
347
348
349
bool
350
RTCCodecStats::InitIds(JSContext* cx, RTCCodecStatsAtoms* atomsCache)
351
0
{
352
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
353
0
354
0
  // Initialize these in reverse order so that any failure leaves the first one
355
0
  // uninitialized.
356
0
  if (!atomsCache->payloadType_id.init(cx, "payloadType") ||
357
0
      !atomsCache->parameters_id.init(cx, "parameters") ||
358
0
      !atomsCache->codec_id.init(cx, "codec") ||
359
0
      !atomsCache->clockRate_id.init(cx, "clockRate") ||
360
0
      !atomsCache->channels_id.init(cx, "channels")) {
361
0
    return false;
362
0
  }
363
0
  return true;
364
0
}
365
366
bool
367
RTCCodecStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
368
0
{
369
0
  // Passing a null JSContext is OK only if we're initing from null,
370
0
  // Since in that case we will not have to do any property gets
371
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
372
0
  // checkers by static analysis tools
373
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
374
0
  RTCCodecStatsAtoms* atomsCache = nullptr;
375
0
  if (cx) {
376
0
    atomsCache = GetAtomCache<RTCCodecStatsAtoms>(cx);
377
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
378
0
      return false;
379
0
    }
380
0
  }
381
0
382
0
  // Per spec, we init the parent's members first
383
0
  if (!RTCStats::Init(cx, val)) {
384
0
    return false;
385
0
  }
386
0
387
0
  bool isNull = val.isNullOrUndefined();
388
0
  // We only need these if !isNull, in which case we have |cx|.
389
0
  Maybe<JS::Rooted<JSObject *> > object;
390
0
  Maybe<JS::Rooted<JS::Value> > temp;
391
0
  if (!isNull) {
392
0
    MOZ_ASSERT(cx);
393
0
    object.emplace(cx, &val.toObject());
394
0
    temp.emplace(cx);
395
0
  }
396
0
  if (!isNull) {
397
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->channels_id, temp.ptr())) {
398
0
      return false;
399
0
    }
400
0
  }
401
0
  if (!isNull && !temp->isUndefined()) {
402
0
    mChannels.Construct();
403
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mChannels.Value()))) {
404
0
      return false;
405
0
    }
406
0
    mIsAnyMemberPresent = true;
407
0
  }
408
0
409
0
  if (!isNull) {
410
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->clockRate_id, temp.ptr())) {
411
0
      return false;
412
0
    }
413
0
  }
414
0
  if (!isNull && !temp->isUndefined()) {
415
0
    mClockRate.Construct();
416
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mClockRate.Value()))) {
417
0
      return false;
418
0
    }
419
0
    mIsAnyMemberPresent = true;
420
0
  }
421
0
422
0
  if (!isNull) {
423
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->codec_id, temp.ptr())) {
424
0
      return false;
425
0
    }
426
0
  }
427
0
  if (!isNull && !temp->isUndefined()) {
428
0
    mCodec.Construct();
429
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mCodec.Value()))) {
430
0
      return false;
431
0
    }
432
0
    mIsAnyMemberPresent = true;
433
0
  }
434
0
435
0
  if (!isNull) {
436
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->parameters_id, temp.ptr())) {
437
0
      return false;
438
0
    }
439
0
  }
440
0
  if (!isNull && !temp->isUndefined()) {
441
0
    mParameters.Construct();
442
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mParameters.Value()))) {
443
0
      return false;
444
0
    }
445
0
    mIsAnyMemberPresent = true;
446
0
  }
447
0
448
0
  if (!isNull) {
449
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->payloadType_id, temp.ptr())) {
450
0
      return false;
451
0
    }
452
0
  }
453
0
  if (!isNull && !temp->isUndefined()) {
454
0
    mPayloadType.Construct();
455
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mPayloadType.Value()))) {
456
0
      return false;
457
0
    }
458
0
    mIsAnyMemberPresent = true;
459
0
  }
460
0
  return true;
461
0
}
462
463
bool
464
RTCCodecStats::Init(const nsAString& aJSON)
465
0
{
466
0
  AutoJSAPI jsapi;
467
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
468
0
  if (!cleanGlobal) {
469
0
    return false;
470
0
  }
471
0
  if (!jsapi.Init(cleanGlobal)) {
472
0
    return false;
473
0
  }
474
0
  JSContext* cx = jsapi.cx();
475
0
  JS::Rooted<JS::Value> json(cx);
476
0
  bool ok = ParseJSON(cx, aJSON, &json);
477
0
  NS_ENSURE_TRUE(ok, false);
478
0
  return Init(cx, json);
479
0
}
480
481
bool
482
RTCCodecStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
483
0
{
484
0
  RTCCodecStatsAtoms* atomsCache = GetAtomCache<RTCCodecStatsAtoms>(cx);
485
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
486
0
    return false;
487
0
  }
488
0
489
0
  // Per spec, we define the parent's members first
490
0
  if (!RTCStats::ToObjectInternal(cx, rval)) {
491
0
    return false;
492
0
  }
493
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
494
0
495
0
  if (mChannels.WasPassed()) {
496
0
    do {
497
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
498
0
      JS::Rooted<JS::Value> temp(cx);
499
0
      uint32_t const & currentValue = mChannels.InternalValue();
500
0
      temp.setNumber(currentValue);
501
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->channels_id, temp, JSPROP_ENUMERATE)) {
502
0
        return false;
503
0
      }
504
0
      break;
505
0
    } while(false);
506
0
  }
507
0
508
0
  if (mClockRate.WasPassed()) {
509
0
    do {
510
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
511
0
      JS::Rooted<JS::Value> temp(cx);
512
0
      uint32_t const & currentValue = mClockRate.InternalValue();
513
0
      temp.setNumber(currentValue);
514
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->clockRate_id, temp, JSPROP_ENUMERATE)) {
515
0
        return false;
516
0
      }
517
0
      break;
518
0
    } while(false);
519
0
  }
520
0
521
0
  if (mCodec.WasPassed()) {
522
0
    do {
523
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
524
0
      JS::Rooted<JS::Value> temp(cx);
525
0
      nsString const & currentValue = mCodec.InternalValue();
526
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
527
0
        return false;
528
0
      }
529
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->codec_id, temp, JSPROP_ENUMERATE)) {
530
0
        return false;
531
0
      }
532
0
      break;
533
0
    } while(false);
534
0
  }
535
0
536
0
  if (mParameters.WasPassed()) {
537
0
    do {
538
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
539
0
      JS::Rooted<JS::Value> temp(cx);
540
0
      nsString const & currentValue = mParameters.InternalValue();
541
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
542
0
        return false;
543
0
      }
544
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->parameters_id, temp, JSPROP_ENUMERATE)) {
545
0
        return false;
546
0
      }
547
0
      break;
548
0
    } while(false);
549
0
  }
550
0
551
0
  if (mPayloadType.WasPassed()) {
552
0
    do {
553
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
554
0
      JS::Rooted<JS::Value> temp(cx);
555
0
      uint32_t const & currentValue = mPayloadType.InternalValue();
556
0
      temp.setNumber(currentValue);
557
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->payloadType_id, temp, JSPROP_ENUMERATE)) {
558
0
        return false;
559
0
      }
560
0
      break;
561
0
    } while(false);
562
0
  }
563
0
564
0
  return true;
565
0
}
566
567
bool
568
RTCCodecStats::ToJSON(nsAString& aJSON) const
569
0
{
570
0
  AutoJSAPI jsapi;
571
0
  jsapi.Init();
572
0
  JSContext *cx = jsapi.cx();
573
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
574
0
  // because we'll only be creating objects, in ways that have no
575
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
576
0
  // which likewise guarantees no side-effects for the sorts of
577
0
  // things we will pass it.
578
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
579
0
  JS::Rooted<JS::Value> val(cx);
580
0
  if (!ToObjectInternal(cx, &val)) {
581
0
    return false;
582
0
  }
583
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
584
0
  return StringifyToJSON(cx, obj, aJSON);
585
0
}
586
587
void
588
RTCCodecStats::TraceDictionary(JSTracer* trc)
589
0
{
590
0
  RTCStats::TraceDictionary(trc);
591
0
}
592
593
RTCCodecStats&
594
RTCCodecStats::operator=(const RTCCodecStats& aOther)
595
0
{
596
0
  RTCStats::operator=(aOther);
597
0
  mChannels.Reset();
598
0
  if (aOther.mChannels.WasPassed()) {
599
0
    mChannels.Construct(aOther.mChannels.Value());
600
0
  }
601
0
  mClockRate.Reset();
602
0
  if (aOther.mClockRate.WasPassed()) {
603
0
    mClockRate.Construct(aOther.mClockRate.Value());
604
0
  }
605
0
  mCodec.Reset();
606
0
  if (aOther.mCodec.WasPassed()) {
607
0
    mCodec.Construct(aOther.mCodec.Value());
608
0
  }
609
0
  mParameters.Reset();
610
0
  if (aOther.mParameters.WasPassed()) {
611
0
    mParameters.Construct(aOther.mParameters.Value());
612
0
  }
613
0
  mPayloadType.Reset();
614
0
  if (aOther.mPayloadType.WasPassed()) {
615
0
    mPayloadType.Construct(aOther.mPayloadType.Value());
616
0
  }
617
0
  return *this;
618
0
}
619
620
namespace binding_detail {
621
} // namespace binding_detail
622
623
624
625
RTCIceCandidatePairStats::RTCIceCandidatePairStats()
626
  : RTCStats(FastDictionaryInitializer())
627
0
{
628
0
  // Safe to pass a null context if we pass a null value
629
0
  Init(nullptr, JS::NullHandleValue);
630
0
}
631
632
633
634
bool
635
RTCIceCandidatePairStats::InitIds(JSContext* cx, RTCIceCandidatePairStatsAtoms* atomsCache)
636
0
{
637
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
638
0
639
0
  // Initialize these in reverse order so that any failure leaves the first one
640
0
  // uninitialized.
641
0
  if (!atomsCache->writable_id.init(cx, "writable") ||
642
0
      !atomsCache->transportId_id.init(cx, "transportId") ||
643
0
      !atomsCache->state_id.init(cx, "state") ||
644
0
      !atomsCache->selected_id.init(cx, "selected") ||
645
0
      !atomsCache->remoteCandidateId_id.init(cx, "remoteCandidateId") ||
646
0
      !atomsCache->readable_id.init(cx, "readable") ||
647
0
      !atomsCache->priority_id.init(cx, "priority") ||
648
0
      !atomsCache->nominated_id.init(cx, "nominated") ||
649
0
      !atomsCache->localCandidateId_id.init(cx, "localCandidateId") ||
650
0
      !atomsCache->lastPacketSentTimestamp_id.init(cx, "lastPacketSentTimestamp") ||
651
0
      !atomsCache->lastPacketReceivedTimestamp_id.init(cx, "lastPacketReceivedTimestamp") ||
652
0
      !atomsCache->componentId_id.init(cx, "componentId") ||
653
0
      !atomsCache->bytesSent_id.init(cx, "bytesSent") ||
654
0
      !atomsCache->bytesReceived_id.init(cx, "bytesReceived")) {
655
0
    return false;
656
0
  }
657
0
  return true;
658
0
}
659
660
bool
661
RTCIceCandidatePairStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
662
0
{
663
0
  // Passing a null JSContext is OK only if we're initing from null,
664
0
  // Since in that case we will not have to do any property gets
665
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
666
0
  // checkers by static analysis tools
667
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
668
0
  RTCIceCandidatePairStatsAtoms* atomsCache = nullptr;
669
0
  if (cx) {
670
0
    atomsCache = GetAtomCache<RTCIceCandidatePairStatsAtoms>(cx);
671
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
672
0
      return false;
673
0
    }
674
0
  }
675
0
676
0
  // Per spec, we init the parent's members first
677
0
  if (!RTCStats::Init(cx, val)) {
678
0
    return false;
679
0
  }
680
0
681
0
  bool isNull = val.isNullOrUndefined();
682
0
  // We only need these if !isNull, in which case we have |cx|.
683
0
  Maybe<JS::Rooted<JSObject *> > object;
684
0
  Maybe<JS::Rooted<JS::Value> > temp;
685
0
  if (!isNull) {
686
0
    MOZ_ASSERT(cx);
687
0
    object.emplace(cx, &val.toObject());
688
0
    temp.emplace(cx);
689
0
  }
690
0
  if (!isNull) {
691
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->bytesReceived_id, temp.ptr())) {
692
0
      return false;
693
0
    }
694
0
  }
695
0
  if (!isNull && !temp->isUndefined()) {
696
0
    mBytesReceived.Construct();
697
0
    if (!ValueToPrimitive<uint64_t, eDefault>(cx, temp.ref(), &(mBytesReceived.Value()))) {
698
0
      return false;
699
0
    }
700
0
    mIsAnyMemberPresent = true;
701
0
  }
702
0
703
0
  if (!isNull) {
704
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->bytesSent_id, temp.ptr())) {
705
0
      return false;
706
0
    }
707
0
  }
708
0
  if (!isNull && !temp->isUndefined()) {
709
0
    mBytesSent.Construct();
710
0
    if (!ValueToPrimitive<uint64_t, eDefault>(cx, temp.ref(), &(mBytesSent.Value()))) {
711
0
      return false;
712
0
    }
713
0
    mIsAnyMemberPresent = true;
714
0
  }
715
0
716
0
  if (!isNull) {
717
0
    if (nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
718
0
      if (!JS_GetPropertyById(cx, *object, atomsCache->componentId_id, temp.ptr())) {
719
0
        return false;
720
0
      }
721
0
    } else {
722
0
      temp->setUndefined();
723
0
    }
724
0
  }
725
0
  if (!isNull && !temp->isUndefined()) {
726
0
    mComponentId.Construct();
727
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mComponentId.Value()))) {
728
0
      return false;
729
0
    }
730
0
    mIsAnyMemberPresent = true;
731
0
  }
732
0
733
0
  if (!isNull) {
734
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->lastPacketReceivedTimestamp_id, temp.ptr())) {
735
0
      return false;
736
0
    }
737
0
  }
738
0
  if (!isNull && !temp->isUndefined()) {
739
0
    mLastPacketReceivedTimestamp.Construct();
740
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mLastPacketReceivedTimestamp.Value()))) {
741
0
      return false;
742
0
    } else if (!mozilla::IsFinite((mLastPacketReceivedTimestamp.Value()))) {
743
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'lastPacketReceivedTimestamp' member of RTCIceCandidatePairStats");
744
0
      return false;
745
0
    }
746
0
    mIsAnyMemberPresent = true;
747
0
  }
748
0
749
0
  if (!isNull) {
750
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->lastPacketSentTimestamp_id, temp.ptr())) {
751
0
      return false;
752
0
    }
753
0
  }
754
0
  if (!isNull && !temp->isUndefined()) {
755
0
    mLastPacketSentTimestamp.Construct();
756
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mLastPacketSentTimestamp.Value()))) {
757
0
      return false;
758
0
    } else if (!mozilla::IsFinite((mLastPacketSentTimestamp.Value()))) {
759
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'lastPacketSentTimestamp' member of RTCIceCandidatePairStats");
760
0
      return false;
761
0
    }
762
0
    mIsAnyMemberPresent = true;
763
0
  }
764
0
765
0
  if (!isNull) {
766
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->localCandidateId_id, temp.ptr())) {
767
0
      return false;
768
0
    }
769
0
  }
770
0
  if (!isNull && !temp->isUndefined()) {
771
0
    mLocalCandidateId.Construct();
772
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mLocalCandidateId.Value()))) {
773
0
      return false;
774
0
    }
775
0
    mIsAnyMemberPresent = true;
776
0
  }
777
0
778
0
  if (!isNull) {
779
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->nominated_id, temp.ptr())) {
780
0
      return false;
781
0
    }
782
0
  }
783
0
  if (!isNull && !temp->isUndefined()) {
784
0
    mNominated.Construct();
785
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mNominated.Value()))) {
786
0
      return false;
787
0
    }
788
0
    mIsAnyMemberPresent = true;
789
0
  }
790
0
791
0
  if (!isNull) {
792
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->priority_id, temp.ptr())) {
793
0
      return false;
794
0
    }
795
0
  }
796
0
  if (!isNull && !temp->isUndefined()) {
797
0
    mPriority.Construct();
798
0
    if (!ValueToPrimitive<uint64_t, eDefault>(cx, temp.ref(), &(mPriority.Value()))) {
799
0
      return false;
800
0
    }
801
0
    mIsAnyMemberPresent = true;
802
0
  }
803
0
804
0
  if (!isNull) {
805
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->readable_id, temp.ptr())) {
806
0
      return false;
807
0
    }
808
0
  }
809
0
  if (!isNull && !temp->isUndefined()) {
810
0
    mReadable.Construct();
811
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mReadable.Value()))) {
812
0
      return false;
813
0
    }
814
0
    mIsAnyMemberPresent = true;
815
0
  }
816
0
817
0
  if (!isNull) {
818
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->remoteCandidateId_id, temp.ptr())) {
819
0
      return false;
820
0
    }
821
0
  }
822
0
  if (!isNull && !temp->isUndefined()) {
823
0
    mRemoteCandidateId.Construct();
824
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mRemoteCandidateId.Value()))) {
825
0
      return false;
826
0
    }
827
0
    mIsAnyMemberPresent = true;
828
0
  }
829
0
830
0
  if (!isNull) {
831
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->selected_id, temp.ptr())) {
832
0
      return false;
833
0
    }
834
0
  }
835
0
  if (!isNull && !temp->isUndefined()) {
836
0
    mSelected.Construct();
837
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mSelected.Value()))) {
838
0
      return false;
839
0
    }
840
0
    mIsAnyMemberPresent = true;
841
0
  }
842
0
843
0
  if (!isNull) {
844
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->state_id, temp.ptr())) {
845
0
      return false;
846
0
    }
847
0
  }
848
0
  if (!isNull && !temp->isUndefined()) {
849
0
    mState.Construct();
850
0
    {
851
0
      int index;
852
0
      if (!FindEnumStringIndex<true>(cx, temp.ref(), RTCStatsIceCandidatePairStateValues::strings, "RTCStatsIceCandidatePairState", "'state' member of RTCIceCandidatePairStats", &index)) {
853
0
        return false;
854
0
      }
855
0
      MOZ_ASSERT(index >= 0);
856
0
      (mState.Value()) = static_cast<RTCStatsIceCandidatePairState>(index);
857
0
    }
858
0
    mIsAnyMemberPresent = true;
859
0
  }
860
0
861
0
  if (!isNull) {
862
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->transportId_id, temp.ptr())) {
863
0
      return false;
864
0
    }
865
0
  }
866
0
  if (!isNull && !temp->isUndefined()) {
867
0
    mTransportId.Construct();
868
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mTransportId.Value()))) {
869
0
      return false;
870
0
    }
871
0
    mIsAnyMemberPresent = true;
872
0
  }
873
0
874
0
  if (!isNull) {
875
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->writable_id, temp.ptr())) {
876
0
      return false;
877
0
    }
878
0
  }
879
0
  if (!isNull && !temp->isUndefined()) {
880
0
    mWritable.Construct();
881
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mWritable.Value()))) {
882
0
      return false;
883
0
    }
884
0
    mIsAnyMemberPresent = true;
885
0
  }
886
0
  return true;
887
0
}
888
889
bool
890
RTCIceCandidatePairStats::Init(const nsAString& aJSON)
891
0
{
892
0
  AutoJSAPI jsapi;
893
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
894
0
  if (!cleanGlobal) {
895
0
    return false;
896
0
  }
897
0
  if (!jsapi.Init(cleanGlobal)) {
898
0
    return false;
899
0
  }
900
0
  JSContext* cx = jsapi.cx();
901
0
  JS::Rooted<JS::Value> json(cx);
902
0
  bool ok = ParseJSON(cx, aJSON, &json);
903
0
  NS_ENSURE_TRUE(ok, false);
904
0
  return Init(cx, json);
905
0
}
906
907
bool
908
RTCIceCandidatePairStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
909
0
{
910
0
  RTCIceCandidatePairStatsAtoms* atomsCache = GetAtomCache<RTCIceCandidatePairStatsAtoms>(cx);
911
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
912
0
    return false;
913
0
  }
914
0
915
0
  // Per spec, we define the parent's members first
916
0
  if (!RTCStats::ToObjectInternal(cx, rval)) {
917
0
    return false;
918
0
  }
919
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
920
0
921
0
  if (mBytesReceived.WasPassed()) {
922
0
    do {
923
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
924
0
      JS::Rooted<JS::Value> temp(cx);
925
0
      uint64_t const & currentValue = mBytesReceived.InternalValue();
926
0
      temp.set(JS_NumberValue(double(currentValue)));
927
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->bytesReceived_id, temp, JSPROP_ENUMERATE)) {
928
0
        return false;
929
0
      }
930
0
      break;
931
0
    } while(false);
932
0
  }
933
0
934
0
  if (mBytesSent.WasPassed()) {
935
0
    do {
936
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
937
0
      JS::Rooted<JS::Value> temp(cx);
938
0
      uint64_t const & currentValue = mBytesSent.InternalValue();
939
0
      temp.set(JS_NumberValue(double(currentValue)));
940
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->bytesSent_id, temp, JSPROP_ENUMERATE)) {
941
0
        return false;
942
0
      }
943
0
      break;
944
0
    } while(false);
945
0
  }
946
0
947
0
  if (nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
948
0
    if (mComponentId.WasPassed()) {
949
0
      do {
950
0
        // block for our 'break' successCode and scope for 'temp' and 'currentValue'
951
0
        JS::Rooted<JS::Value> temp(cx);
952
0
        uint32_t const & currentValue = mComponentId.InternalValue();
953
0
        temp.setNumber(currentValue);
954
0
        if (!JS_DefinePropertyById(cx, obj, atomsCache->componentId_id, temp, JSPROP_ENUMERATE)) {
955
0
          return false;
956
0
        }
957
0
        break;
958
0
      } while(false);
959
0
    }
960
0
  }
961
0
962
0
  if (mLastPacketReceivedTimestamp.WasPassed()) {
963
0
    do {
964
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
965
0
      JS::Rooted<JS::Value> temp(cx);
966
0
      double const & currentValue = mLastPacketReceivedTimestamp.InternalValue();
967
0
      temp.set(JS_NumberValue(double(currentValue)));
968
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->lastPacketReceivedTimestamp_id, temp, JSPROP_ENUMERATE)) {
969
0
        return false;
970
0
      }
971
0
      break;
972
0
    } while(false);
973
0
  }
974
0
975
0
  if (mLastPacketSentTimestamp.WasPassed()) {
976
0
    do {
977
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
978
0
      JS::Rooted<JS::Value> temp(cx);
979
0
      double const & currentValue = mLastPacketSentTimestamp.InternalValue();
980
0
      temp.set(JS_NumberValue(double(currentValue)));
981
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->lastPacketSentTimestamp_id, temp, JSPROP_ENUMERATE)) {
982
0
        return false;
983
0
      }
984
0
      break;
985
0
    } while(false);
986
0
  }
987
0
988
0
  if (mLocalCandidateId.WasPassed()) {
989
0
    do {
990
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
991
0
      JS::Rooted<JS::Value> temp(cx);
992
0
      nsString const & currentValue = mLocalCandidateId.InternalValue();
993
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
994
0
        return false;
995
0
      }
996
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->localCandidateId_id, temp, JSPROP_ENUMERATE)) {
997
0
        return false;
998
0
      }
999
0
      break;
1000
0
    } while(false);
1001
0
  }
1002
0
1003
0
  if (mNominated.WasPassed()) {
1004
0
    do {
1005
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1006
0
      JS::Rooted<JS::Value> temp(cx);
1007
0
      bool const & currentValue = mNominated.InternalValue();
1008
0
      temp.setBoolean(currentValue);
1009
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->nominated_id, temp, JSPROP_ENUMERATE)) {
1010
0
        return false;
1011
0
      }
1012
0
      break;
1013
0
    } while(false);
1014
0
  }
1015
0
1016
0
  if (mPriority.WasPassed()) {
1017
0
    do {
1018
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1019
0
      JS::Rooted<JS::Value> temp(cx);
1020
0
      uint64_t const & currentValue = mPriority.InternalValue();
1021
0
      temp.set(JS_NumberValue(double(currentValue)));
1022
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->priority_id, temp, JSPROP_ENUMERATE)) {
1023
0
        return false;
1024
0
      }
1025
0
      break;
1026
0
    } while(false);
1027
0
  }
1028
0
1029
0
  if (mReadable.WasPassed()) {
1030
0
    do {
1031
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1032
0
      JS::Rooted<JS::Value> temp(cx);
1033
0
      bool const & currentValue = mReadable.InternalValue();
1034
0
      temp.setBoolean(currentValue);
1035
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->readable_id, temp, JSPROP_ENUMERATE)) {
1036
0
        return false;
1037
0
      }
1038
0
      break;
1039
0
    } while(false);
1040
0
  }
1041
0
1042
0
  if (mRemoteCandidateId.WasPassed()) {
1043
0
    do {
1044
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1045
0
      JS::Rooted<JS::Value> temp(cx);
1046
0
      nsString const & currentValue = mRemoteCandidateId.InternalValue();
1047
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1048
0
        return false;
1049
0
      }
1050
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->remoteCandidateId_id, temp, JSPROP_ENUMERATE)) {
1051
0
        return false;
1052
0
      }
1053
0
      break;
1054
0
    } while(false);
1055
0
  }
1056
0
1057
0
  if (mSelected.WasPassed()) {
1058
0
    do {
1059
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1060
0
      JS::Rooted<JS::Value> temp(cx);
1061
0
      bool const & currentValue = mSelected.InternalValue();
1062
0
      temp.setBoolean(currentValue);
1063
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->selected_id, temp, JSPROP_ENUMERATE)) {
1064
0
        return false;
1065
0
      }
1066
0
      break;
1067
0
    } while(false);
1068
0
  }
1069
0
1070
0
  if (mState.WasPassed()) {
1071
0
    do {
1072
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1073
0
      JS::Rooted<JS::Value> temp(cx);
1074
0
      RTCStatsIceCandidatePairState const & currentValue = mState.InternalValue();
1075
0
      if (!ToJSValue(cx, currentValue, &temp)) {
1076
0
        return false;
1077
0
      }
1078
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->state_id, temp, JSPROP_ENUMERATE)) {
1079
0
        return false;
1080
0
      }
1081
0
      break;
1082
0
    } while(false);
1083
0
  }
1084
0
1085
0
  if (mTransportId.WasPassed()) {
1086
0
    do {
1087
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1088
0
      JS::Rooted<JS::Value> temp(cx);
1089
0
      nsString const & currentValue = mTransportId.InternalValue();
1090
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1091
0
        return false;
1092
0
      }
1093
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->transportId_id, temp, JSPROP_ENUMERATE)) {
1094
0
        return false;
1095
0
      }
1096
0
      break;
1097
0
    } while(false);
1098
0
  }
1099
0
1100
0
  if (mWritable.WasPassed()) {
1101
0
    do {
1102
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1103
0
      JS::Rooted<JS::Value> temp(cx);
1104
0
      bool const & currentValue = mWritable.InternalValue();
1105
0
      temp.setBoolean(currentValue);
1106
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->writable_id, temp, JSPROP_ENUMERATE)) {
1107
0
        return false;
1108
0
      }
1109
0
      break;
1110
0
    } while(false);
1111
0
  }
1112
0
1113
0
  return true;
1114
0
}
1115
1116
bool
1117
RTCIceCandidatePairStats::ToJSON(nsAString& aJSON) const
1118
0
{
1119
0
  AutoJSAPI jsapi;
1120
0
  jsapi.Init();
1121
0
  JSContext *cx = jsapi.cx();
1122
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
1123
0
  // because we'll only be creating objects, in ways that have no
1124
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
1125
0
  // which likewise guarantees no side-effects for the sorts of
1126
0
  // things we will pass it.
1127
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
1128
0
  JS::Rooted<JS::Value> val(cx);
1129
0
  if (!ToObjectInternal(cx, &val)) {
1130
0
    return false;
1131
0
  }
1132
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
1133
0
  return StringifyToJSON(cx, obj, aJSON);
1134
0
}
1135
1136
void
1137
RTCIceCandidatePairStats::TraceDictionary(JSTracer* trc)
1138
0
{
1139
0
  RTCStats::TraceDictionary(trc);
1140
0
}
1141
1142
RTCIceCandidatePairStats&
1143
RTCIceCandidatePairStats::operator=(const RTCIceCandidatePairStats& aOther)
1144
0
{
1145
0
  RTCStats::operator=(aOther);
1146
0
  mBytesReceived.Reset();
1147
0
  if (aOther.mBytesReceived.WasPassed()) {
1148
0
    mBytesReceived.Construct(aOther.mBytesReceived.Value());
1149
0
  }
1150
0
  mBytesSent.Reset();
1151
0
  if (aOther.mBytesSent.WasPassed()) {
1152
0
    mBytesSent.Construct(aOther.mBytesSent.Value());
1153
0
  }
1154
0
  mComponentId.Reset();
1155
0
  if (aOther.mComponentId.WasPassed()) {
1156
0
    mComponentId.Construct(aOther.mComponentId.Value());
1157
0
  }
1158
0
  mLastPacketReceivedTimestamp.Reset();
1159
0
  if (aOther.mLastPacketReceivedTimestamp.WasPassed()) {
1160
0
    mLastPacketReceivedTimestamp.Construct(aOther.mLastPacketReceivedTimestamp.Value());
1161
0
  }
1162
0
  mLastPacketSentTimestamp.Reset();
1163
0
  if (aOther.mLastPacketSentTimestamp.WasPassed()) {
1164
0
    mLastPacketSentTimestamp.Construct(aOther.mLastPacketSentTimestamp.Value());
1165
0
  }
1166
0
  mLocalCandidateId.Reset();
1167
0
  if (aOther.mLocalCandidateId.WasPassed()) {
1168
0
    mLocalCandidateId.Construct(aOther.mLocalCandidateId.Value());
1169
0
  }
1170
0
  mNominated.Reset();
1171
0
  if (aOther.mNominated.WasPassed()) {
1172
0
    mNominated.Construct(aOther.mNominated.Value());
1173
0
  }
1174
0
  mPriority.Reset();
1175
0
  if (aOther.mPriority.WasPassed()) {
1176
0
    mPriority.Construct(aOther.mPriority.Value());
1177
0
  }
1178
0
  mReadable.Reset();
1179
0
  if (aOther.mReadable.WasPassed()) {
1180
0
    mReadable.Construct(aOther.mReadable.Value());
1181
0
  }
1182
0
  mRemoteCandidateId.Reset();
1183
0
  if (aOther.mRemoteCandidateId.WasPassed()) {
1184
0
    mRemoteCandidateId.Construct(aOther.mRemoteCandidateId.Value());
1185
0
  }
1186
0
  mSelected.Reset();
1187
0
  if (aOther.mSelected.WasPassed()) {
1188
0
    mSelected.Construct(aOther.mSelected.Value());
1189
0
  }
1190
0
  mState.Reset();
1191
0
  if (aOther.mState.WasPassed()) {
1192
0
    mState.Construct(aOther.mState.Value());
1193
0
  }
1194
0
  mTransportId.Reset();
1195
0
  if (aOther.mTransportId.WasPassed()) {
1196
0
    mTransportId.Construct(aOther.mTransportId.Value());
1197
0
  }
1198
0
  mWritable.Reset();
1199
0
  if (aOther.mWritable.WasPassed()) {
1200
0
    mWritable.Construct(aOther.mWritable.Value());
1201
0
  }
1202
0
  return *this;
1203
0
}
1204
1205
namespace binding_detail {
1206
} // namespace binding_detail
1207
1208
1209
1210
RTCIceCandidateStats::RTCIceCandidateStats()
1211
  : RTCStats(FastDictionaryInitializer())
1212
0
{
1213
0
  // Safe to pass a null context if we pass a null value
1214
0
  Init(nullptr, JS::NullHandleValue);
1215
0
}
1216
1217
1218
1219
bool
1220
RTCIceCandidateStats::InitIds(JSContext* cx, RTCIceCandidateStatsAtoms* atomsCache)
1221
0
{
1222
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
1223
0
1224
0
  // Initialize these in reverse order so that any failure leaves the first one
1225
0
  // uninitialized.
1226
0
  if (!atomsCache->transport_id.init(cx, "transport") ||
1227
0
      !atomsCache->portNumber_id.init(cx, "portNumber") ||
1228
0
      !atomsCache->mozLocalTransport_id.init(cx, "mozLocalTransport") ||
1229
0
      !atomsCache->ipAddress_id.init(cx, "ipAddress") ||
1230
0
      !atomsCache->componentId_id.init(cx, "componentId") ||
1231
0
      !atomsCache->candidateType_id.init(cx, "candidateType") ||
1232
0
      !atomsCache->candidateId_id.init(cx, "candidateId")) {
1233
0
    return false;
1234
0
  }
1235
0
  return true;
1236
0
}
1237
1238
bool
1239
RTCIceCandidateStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
1240
0
{
1241
0
  // Passing a null JSContext is OK only if we're initing from null,
1242
0
  // Since in that case we will not have to do any property gets
1243
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
1244
0
  // checkers by static analysis tools
1245
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
1246
0
  RTCIceCandidateStatsAtoms* atomsCache = nullptr;
1247
0
  if (cx) {
1248
0
    atomsCache = GetAtomCache<RTCIceCandidateStatsAtoms>(cx);
1249
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1250
0
      return false;
1251
0
    }
1252
0
  }
1253
0
1254
0
  // Per spec, we init the parent's members first
1255
0
  if (!RTCStats::Init(cx, val)) {
1256
0
    return false;
1257
0
  }
1258
0
1259
0
  bool isNull = val.isNullOrUndefined();
1260
0
  // We only need these if !isNull, in which case we have |cx|.
1261
0
  Maybe<JS::Rooted<JSObject *> > object;
1262
0
  Maybe<JS::Rooted<JS::Value> > temp;
1263
0
  if (!isNull) {
1264
0
    MOZ_ASSERT(cx);
1265
0
    object.emplace(cx, &val.toObject());
1266
0
    temp.emplace(cx);
1267
0
  }
1268
0
  if (!isNull) {
1269
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->candidateId_id, temp.ptr())) {
1270
0
      return false;
1271
0
    }
1272
0
  }
1273
0
  if (!isNull && !temp->isUndefined()) {
1274
0
    mCandidateId.Construct();
1275
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mCandidateId.Value()))) {
1276
0
      return false;
1277
0
    }
1278
0
    mIsAnyMemberPresent = true;
1279
0
  }
1280
0
1281
0
  if (!isNull) {
1282
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->candidateType_id, temp.ptr())) {
1283
0
      return false;
1284
0
    }
1285
0
  }
1286
0
  if (!isNull && !temp->isUndefined()) {
1287
0
    mCandidateType.Construct();
1288
0
    {
1289
0
      int index;
1290
0
      if (!FindEnumStringIndex<true>(cx, temp.ref(), RTCStatsIceCandidateTypeValues::strings, "RTCStatsIceCandidateType", "'candidateType' member of RTCIceCandidateStats", &index)) {
1291
0
        return false;
1292
0
      }
1293
0
      MOZ_ASSERT(index >= 0);
1294
0
      (mCandidateType.Value()) = static_cast<RTCStatsIceCandidateType>(index);
1295
0
    }
1296
0
    mIsAnyMemberPresent = true;
1297
0
  }
1298
0
1299
0
  if (!isNull) {
1300
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->componentId_id, temp.ptr())) {
1301
0
      return false;
1302
0
    }
1303
0
  }
1304
0
  if (!isNull && !temp->isUndefined()) {
1305
0
    mComponentId.Construct();
1306
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mComponentId.Value()))) {
1307
0
      return false;
1308
0
    }
1309
0
    mIsAnyMemberPresent = true;
1310
0
  }
1311
0
1312
0
  if (!isNull) {
1313
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->ipAddress_id, temp.ptr())) {
1314
0
      return false;
1315
0
    }
1316
0
  }
1317
0
  if (!isNull && !temp->isUndefined()) {
1318
0
    mIpAddress.Construct();
1319
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mIpAddress.Value()))) {
1320
0
      return false;
1321
0
    }
1322
0
    mIsAnyMemberPresent = true;
1323
0
  }
1324
0
1325
0
  if (!isNull) {
1326
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->mozLocalTransport_id, temp.ptr())) {
1327
0
      return false;
1328
0
    }
1329
0
  }
1330
0
  if (!isNull && !temp->isUndefined()) {
1331
0
    mMozLocalTransport.Construct();
1332
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mMozLocalTransport.Value()))) {
1333
0
      return false;
1334
0
    }
1335
0
    mIsAnyMemberPresent = true;
1336
0
  }
1337
0
1338
0
  if (!isNull) {
1339
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->portNumber_id, temp.ptr())) {
1340
0
      return false;
1341
0
    }
1342
0
  }
1343
0
  if (!isNull && !temp->isUndefined()) {
1344
0
    mPortNumber.Construct();
1345
0
    if (!ValueToPrimitive<int32_t, eDefault>(cx, temp.ref(), &(mPortNumber.Value()))) {
1346
0
      return false;
1347
0
    }
1348
0
    mIsAnyMemberPresent = true;
1349
0
  }
1350
0
1351
0
  if (!isNull) {
1352
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->transport_id, temp.ptr())) {
1353
0
      return false;
1354
0
    }
1355
0
  }
1356
0
  if (!isNull && !temp->isUndefined()) {
1357
0
    mTransport.Construct();
1358
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mTransport.Value()))) {
1359
0
      return false;
1360
0
    }
1361
0
    mIsAnyMemberPresent = true;
1362
0
  }
1363
0
  return true;
1364
0
}
1365
1366
bool
1367
RTCIceCandidateStats::Init(const nsAString& aJSON)
1368
0
{
1369
0
  AutoJSAPI jsapi;
1370
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
1371
0
  if (!cleanGlobal) {
1372
0
    return false;
1373
0
  }
1374
0
  if (!jsapi.Init(cleanGlobal)) {
1375
0
    return false;
1376
0
  }
1377
0
  JSContext* cx = jsapi.cx();
1378
0
  JS::Rooted<JS::Value> json(cx);
1379
0
  bool ok = ParseJSON(cx, aJSON, &json);
1380
0
  NS_ENSURE_TRUE(ok, false);
1381
0
  return Init(cx, json);
1382
0
}
1383
1384
bool
1385
RTCIceCandidateStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1386
0
{
1387
0
  RTCIceCandidateStatsAtoms* atomsCache = GetAtomCache<RTCIceCandidateStatsAtoms>(cx);
1388
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1389
0
    return false;
1390
0
  }
1391
0
1392
0
  // Per spec, we define the parent's members first
1393
0
  if (!RTCStats::ToObjectInternal(cx, rval)) {
1394
0
    return false;
1395
0
  }
1396
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
1397
0
1398
0
  if (mCandidateId.WasPassed()) {
1399
0
    do {
1400
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1401
0
      JS::Rooted<JS::Value> temp(cx);
1402
0
      nsString const & currentValue = mCandidateId.InternalValue();
1403
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1404
0
        return false;
1405
0
      }
1406
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->candidateId_id, temp, JSPROP_ENUMERATE)) {
1407
0
        return false;
1408
0
      }
1409
0
      break;
1410
0
    } while(false);
1411
0
  }
1412
0
1413
0
  if (mCandidateType.WasPassed()) {
1414
0
    do {
1415
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1416
0
      JS::Rooted<JS::Value> temp(cx);
1417
0
      RTCStatsIceCandidateType const & currentValue = mCandidateType.InternalValue();
1418
0
      if (!ToJSValue(cx, currentValue, &temp)) {
1419
0
        return false;
1420
0
      }
1421
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->candidateType_id, temp, JSPROP_ENUMERATE)) {
1422
0
        return false;
1423
0
      }
1424
0
      break;
1425
0
    } while(false);
1426
0
  }
1427
0
1428
0
  if (mComponentId.WasPassed()) {
1429
0
    do {
1430
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1431
0
      JS::Rooted<JS::Value> temp(cx);
1432
0
      nsString const & currentValue = mComponentId.InternalValue();
1433
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1434
0
        return false;
1435
0
      }
1436
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->componentId_id, temp, JSPROP_ENUMERATE)) {
1437
0
        return false;
1438
0
      }
1439
0
      break;
1440
0
    } while(false);
1441
0
  }
1442
0
1443
0
  if (mIpAddress.WasPassed()) {
1444
0
    do {
1445
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1446
0
      JS::Rooted<JS::Value> temp(cx);
1447
0
      nsString const & currentValue = mIpAddress.InternalValue();
1448
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1449
0
        return false;
1450
0
      }
1451
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->ipAddress_id, temp, JSPROP_ENUMERATE)) {
1452
0
        return false;
1453
0
      }
1454
0
      break;
1455
0
    } while(false);
1456
0
  }
1457
0
1458
0
  if (mMozLocalTransport.WasPassed()) {
1459
0
    do {
1460
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1461
0
      JS::Rooted<JS::Value> temp(cx);
1462
0
      nsString const & currentValue = mMozLocalTransport.InternalValue();
1463
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1464
0
        return false;
1465
0
      }
1466
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->mozLocalTransport_id, temp, JSPROP_ENUMERATE)) {
1467
0
        return false;
1468
0
      }
1469
0
      break;
1470
0
    } while(false);
1471
0
  }
1472
0
1473
0
  if (mPortNumber.WasPassed()) {
1474
0
    do {
1475
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1476
0
      JS::Rooted<JS::Value> temp(cx);
1477
0
      int32_t const & currentValue = mPortNumber.InternalValue();
1478
0
      temp.setInt32(int32_t(currentValue));
1479
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->portNumber_id, temp, JSPROP_ENUMERATE)) {
1480
0
        return false;
1481
0
      }
1482
0
      break;
1483
0
    } while(false);
1484
0
  }
1485
0
1486
0
  if (mTransport.WasPassed()) {
1487
0
    do {
1488
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1489
0
      JS::Rooted<JS::Value> temp(cx);
1490
0
      nsString const & currentValue = mTransport.InternalValue();
1491
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1492
0
        return false;
1493
0
      }
1494
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->transport_id, temp, JSPROP_ENUMERATE)) {
1495
0
        return false;
1496
0
      }
1497
0
      break;
1498
0
    } while(false);
1499
0
  }
1500
0
1501
0
  return true;
1502
0
}
1503
1504
bool
1505
RTCIceCandidateStats::ToJSON(nsAString& aJSON) const
1506
0
{
1507
0
  AutoJSAPI jsapi;
1508
0
  jsapi.Init();
1509
0
  JSContext *cx = jsapi.cx();
1510
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
1511
0
  // because we'll only be creating objects, in ways that have no
1512
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
1513
0
  // which likewise guarantees no side-effects for the sorts of
1514
0
  // things we will pass it.
1515
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
1516
0
  JS::Rooted<JS::Value> val(cx);
1517
0
  if (!ToObjectInternal(cx, &val)) {
1518
0
    return false;
1519
0
  }
1520
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
1521
0
  return StringifyToJSON(cx, obj, aJSON);
1522
0
}
1523
1524
void
1525
RTCIceCandidateStats::TraceDictionary(JSTracer* trc)
1526
0
{
1527
0
  RTCStats::TraceDictionary(trc);
1528
0
}
1529
1530
RTCIceCandidateStats&
1531
RTCIceCandidateStats::operator=(const RTCIceCandidateStats& aOther)
1532
0
{
1533
0
  RTCStats::operator=(aOther);
1534
0
  mCandidateId.Reset();
1535
0
  if (aOther.mCandidateId.WasPassed()) {
1536
0
    mCandidateId.Construct(aOther.mCandidateId.Value());
1537
0
  }
1538
0
  mCandidateType.Reset();
1539
0
  if (aOther.mCandidateType.WasPassed()) {
1540
0
    mCandidateType.Construct(aOther.mCandidateType.Value());
1541
0
  }
1542
0
  mComponentId.Reset();
1543
0
  if (aOther.mComponentId.WasPassed()) {
1544
0
    mComponentId.Construct(aOther.mComponentId.Value());
1545
0
  }
1546
0
  mIpAddress.Reset();
1547
0
  if (aOther.mIpAddress.WasPassed()) {
1548
0
    mIpAddress.Construct(aOther.mIpAddress.Value());
1549
0
  }
1550
0
  mMozLocalTransport.Reset();
1551
0
  if (aOther.mMozLocalTransport.WasPassed()) {
1552
0
    mMozLocalTransport.Construct(aOther.mMozLocalTransport.Value());
1553
0
  }
1554
0
  mPortNumber.Reset();
1555
0
  if (aOther.mPortNumber.WasPassed()) {
1556
0
    mPortNumber.Construct(aOther.mPortNumber.Value());
1557
0
  }
1558
0
  mTransport.Reset();
1559
0
  if (aOther.mTransport.WasPassed()) {
1560
0
    mTransport.Construct(aOther.mTransport.Value());
1561
0
  }
1562
0
  return *this;
1563
0
}
1564
1565
namespace binding_detail {
1566
} // namespace binding_detail
1567
1568
1569
1570
RTCIceComponentStats::RTCIceComponentStats()
1571
  : RTCStats(FastDictionaryInitializer())
1572
0
{
1573
0
  // Safe to pass a null context if we pass a null value
1574
0
  Init(nullptr, JS::NullHandleValue);
1575
0
}
1576
1577
1578
1579
bool
1580
RTCIceComponentStats::InitIds(JSContext* cx, RTCIceComponentStatsAtoms* atomsCache)
1581
0
{
1582
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
1583
0
1584
0
  // Initialize these in reverse order so that any failure leaves the first one
1585
0
  // uninitialized.
1586
0
  if (!atomsCache->transportId_id.init(cx, "transportId") ||
1587
0
      !atomsCache->component_id.init(cx, "component") ||
1588
0
      !atomsCache->bytesSent_id.init(cx, "bytesSent") ||
1589
0
      !atomsCache->bytesReceived_id.init(cx, "bytesReceived") ||
1590
0
      !atomsCache->activeConnection_id.init(cx, "activeConnection")) {
1591
0
    return false;
1592
0
  }
1593
0
  return true;
1594
0
}
1595
1596
bool
1597
RTCIceComponentStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
1598
0
{
1599
0
  // Passing a null JSContext is OK only if we're initing from null,
1600
0
  // Since in that case we will not have to do any property gets
1601
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
1602
0
  // checkers by static analysis tools
1603
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
1604
0
  RTCIceComponentStatsAtoms* atomsCache = nullptr;
1605
0
  if (cx) {
1606
0
    atomsCache = GetAtomCache<RTCIceComponentStatsAtoms>(cx);
1607
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1608
0
      return false;
1609
0
    }
1610
0
  }
1611
0
1612
0
  // Per spec, we init the parent's members first
1613
0
  if (!RTCStats::Init(cx, val)) {
1614
0
    return false;
1615
0
  }
1616
0
1617
0
  bool isNull = val.isNullOrUndefined();
1618
0
  // We only need these if !isNull, in which case we have |cx|.
1619
0
  Maybe<JS::Rooted<JSObject *> > object;
1620
0
  Maybe<JS::Rooted<JS::Value> > temp;
1621
0
  if (!isNull) {
1622
0
    MOZ_ASSERT(cx);
1623
0
    object.emplace(cx, &val.toObject());
1624
0
    temp.emplace(cx);
1625
0
  }
1626
0
  if (!isNull) {
1627
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->activeConnection_id, temp.ptr())) {
1628
0
      return false;
1629
0
    }
1630
0
  }
1631
0
  if (!isNull && !temp->isUndefined()) {
1632
0
    mActiveConnection.Construct();
1633
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mActiveConnection.Value()))) {
1634
0
      return false;
1635
0
    }
1636
0
    mIsAnyMemberPresent = true;
1637
0
  }
1638
0
1639
0
  if (!isNull) {
1640
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->bytesReceived_id, temp.ptr())) {
1641
0
      return false;
1642
0
    }
1643
0
  }
1644
0
  if (!isNull && !temp->isUndefined()) {
1645
0
    mBytesReceived.Construct();
1646
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mBytesReceived.Value()))) {
1647
0
      return false;
1648
0
    }
1649
0
    mIsAnyMemberPresent = true;
1650
0
  }
1651
0
1652
0
  if (!isNull) {
1653
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->bytesSent_id, temp.ptr())) {
1654
0
      return false;
1655
0
    }
1656
0
  }
1657
0
  if (!isNull && !temp->isUndefined()) {
1658
0
    mBytesSent.Construct();
1659
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mBytesSent.Value()))) {
1660
0
      return false;
1661
0
    }
1662
0
    mIsAnyMemberPresent = true;
1663
0
  }
1664
0
1665
0
  if (!isNull) {
1666
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->component_id, temp.ptr())) {
1667
0
      return false;
1668
0
    }
1669
0
  }
1670
0
  if (!isNull && !temp->isUndefined()) {
1671
0
    mComponent.Construct();
1672
0
    if (!ValueToPrimitive<int32_t, eDefault>(cx, temp.ref(), &(mComponent.Value()))) {
1673
0
      return false;
1674
0
    }
1675
0
    mIsAnyMemberPresent = true;
1676
0
  }
1677
0
1678
0
  if (!isNull) {
1679
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->transportId_id, temp.ptr())) {
1680
0
      return false;
1681
0
    }
1682
0
  }
1683
0
  if (!isNull && !temp->isUndefined()) {
1684
0
    mTransportId.Construct();
1685
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mTransportId.Value()))) {
1686
0
      return false;
1687
0
    }
1688
0
    mIsAnyMemberPresent = true;
1689
0
  }
1690
0
  return true;
1691
0
}
1692
1693
bool
1694
RTCIceComponentStats::Init(const nsAString& aJSON)
1695
0
{
1696
0
  AutoJSAPI jsapi;
1697
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
1698
0
  if (!cleanGlobal) {
1699
0
    return false;
1700
0
  }
1701
0
  if (!jsapi.Init(cleanGlobal)) {
1702
0
    return false;
1703
0
  }
1704
0
  JSContext* cx = jsapi.cx();
1705
0
  JS::Rooted<JS::Value> json(cx);
1706
0
  bool ok = ParseJSON(cx, aJSON, &json);
1707
0
  NS_ENSURE_TRUE(ok, false);
1708
0
  return Init(cx, json);
1709
0
}
1710
1711
bool
1712
RTCIceComponentStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1713
0
{
1714
0
  RTCIceComponentStatsAtoms* atomsCache = GetAtomCache<RTCIceComponentStatsAtoms>(cx);
1715
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1716
0
    return false;
1717
0
  }
1718
0
1719
0
  // Per spec, we define the parent's members first
1720
0
  if (!RTCStats::ToObjectInternal(cx, rval)) {
1721
0
    return false;
1722
0
  }
1723
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
1724
0
1725
0
  if (mActiveConnection.WasPassed()) {
1726
0
    do {
1727
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1728
0
      JS::Rooted<JS::Value> temp(cx);
1729
0
      bool const & currentValue = mActiveConnection.InternalValue();
1730
0
      temp.setBoolean(currentValue);
1731
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->activeConnection_id, temp, JSPROP_ENUMERATE)) {
1732
0
        return false;
1733
0
      }
1734
0
      break;
1735
0
    } while(false);
1736
0
  }
1737
0
1738
0
  if (mBytesReceived.WasPassed()) {
1739
0
    do {
1740
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1741
0
      JS::Rooted<JS::Value> temp(cx);
1742
0
      uint32_t const & currentValue = mBytesReceived.InternalValue();
1743
0
      temp.setNumber(currentValue);
1744
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->bytesReceived_id, temp, JSPROP_ENUMERATE)) {
1745
0
        return false;
1746
0
      }
1747
0
      break;
1748
0
    } while(false);
1749
0
  }
1750
0
1751
0
  if (mBytesSent.WasPassed()) {
1752
0
    do {
1753
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1754
0
      JS::Rooted<JS::Value> temp(cx);
1755
0
      uint32_t const & currentValue = mBytesSent.InternalValue();
1756
0
      temp.setNumber(currentValue);
1757
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->bytesSent_id, temp, JSPROP_ENUMERATE)) {
1758
0
        return false;
1759
0
      }
1760
0
      break;
1761
0
    } while(false);
1762
0
  }
1763
0
1764
0
  if (mComponent.WasPassed()) {
1765
0
    do {
1766
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1767
0
      JS::Rooted<JS::Value> temp(cx);
1768
0
      int32_t const & currentValue = mComponent.InternalValue();
1769
0
      temp.setInt32(int32_t(currentValue));
1770
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->component_id, temp, JSPROP_ENUMERATE)) {
1771
0
        return false;
1772
0
      }
1773
0
      break;
1774
0
    } while(false);
1775
0
  }
1776
0
1777
0
  if (mTransportId.WasPassed()) {
1778
0
    do {
1779
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1780
0
      JS::Rooted<JS::Value> temp(cx);
1781
0
      nsString const & currentValue = mTransportId.InternalValue();
1782
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1783
0
        return false;
1784
0
      }
1785
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->transportId_id, temp, JSPROP_ENUMERATE)) {
1786
0
        return false;
1787
0
      }
1788
0
      break;
1789
0
    } while(false);
1790
0
  }
1791
0
1792
0
  return true;
1793
0
}
1794
1795
bool
1796
RTCIceComponentStats::ToJSON(nsAString& aJSON) const
1797
0
{
1798
0
  AutoJSAPI jsapi;
1799
0
  jsapi.Init();
1800
0
  JSContext *cx = jsapi.cx();
1801
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
1802
0
  // because we'll only be creating objects, in ways that have no
1803
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
1804
0
  // which likewise guarantees no side-effects for the sorts of
1805
0
  // things we will pass it.
1806
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
1807
0
  JS::Rooted<JS::Value> val(cx);
1808
0
  if (!ToObjectInternal(cx, &val)) {
1809
0
    return false;
1810
0
  }
1811
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
1812
0
  return StringifyToJSON(cx, obj, aJSON);
1813
0
}
1814
1815
void
1816
RTCIceComponentStats::TraceDictionary(JSTracer* trc)
1817
0
{
1818
0
  RTCStats::TraceDictionary(trc);
1819
0
}
1820
1821
RTCIceComponentStats&
1822
RTCIceComponentStats::operator=(const RTCIceComponentStats& aOther)
1823
0
{
1824
0
  RTCStats::operator=(aOther);
1825
0
  mActiveConnection.Reset();
1826
0
  if (aOther.mActiveConnection.WasPassed()) {
1827
0
    mActiveConnection.Construct(aOther.mActiveConnection.Value());
1828
0
  }
1829
0
  mBytesReceived.Reset();
1830
0
  if (aOther.mBytesReceived.WasPassed()) {
1831
0
    mBytesReceived.Construct(aOther.mBytesReceived.Value());
1832
0
  }
1833
0
  mBytesSent.Reset();
1834
0
  if (aOther.mBytesSent.WasPassed()) {
1835
0
    mBytesSent.Construct(aOther.mBytesSent.Value());
1836
0
  }
1837
0
  mComponent.Reset();
1838
0
  if (aOther.mComponent.WasPassed()) {
1839
0
    mComponent.Construct(aOther.mComponent.Value());
1840
0
  }
1841
0
  mTransportId.Reset();
1842
0
  if (aOther.mTransportId.WasPassed()) {
1843
0
    mTransportId.Construct(aOther.mTransportId.Value());
1844
0
  }
1845
0
  return *this;
1846
0
}
1847
1848
namespace binding_detail {
1849
} // namespace binding_detail
1850
1851
1852
1853
RTCMediaStreamStats::RTCMediaStreamStats()
1854
  : RTCStats(FastDictionaryInitializer())
1855
0
{
1856
0
  // Safe to pass a null context if we pass a null value
1857
0
  Init(nullptr, JS::NullHandleValue);
1858
0
}
1859
1860
1861
1862
bool
1863
RTCMediaStreamStats::InitIds(JSContext* cx, RTCMediaStreamStatsAtoms* atomsCache)
1864
0
{
1865
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
1866
0
1867
0
  // Initialize these in reverse order so that any failure leaves the first one
1868
0
  // uninitialized.
1869
0
  if (!atomsCache->trackIds_id.init(cx, "trackIds") ||
1870
0
      !atomsCache->streamIdentifier_id.init(cx, "streamIdentifier")) {
1871
0
    return false;
1872
0
  }
1873
0
  return true;
1874
0
}
1875
1876
bool
1877
RTCMediaStreamStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
1878
0
{
1879
0
  // Passing a null JSContext is OK only if we're initing from null,
1880
0
  // Since in that case we will not have to do any property gets
1881
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
1882
0
  // checkers by static analysis tools
1883
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
1884
0
  RTCMediaStreamStatsAtoms* atomsCache = nullptr;
1885
0
  if (cx) {
1886
0
    atomsCache = GetAtomCache<RTCMediaStreamStatsAtoms>(cx);
1887
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1888
0
      return false;
1889
0
    }
1890
0
  }
1891
0
1892
0
  // Per spec, we init the parent's members first
1893
0
  if (!RTCStats::Init(cx, val)) {
1894
0
    return false;
1895
0
  }
1896
0
1897
0
  bool isNull = val.isNullOrUndefined();
1898
0
  // We only need these if !isNull, in which case we have |cx|.
1899
0
  Maybe<JS::Rooted<JSObject *> > object;
1900
0
  Maybe<JS::Rooted<JS::Value> > temp;
1901
0
  if (!isNull) {
1902
0
    MOZ_ASSERT(cx);
1903
0
    object.emplace(cx, &val.toObject());
1904
0
    temp.emplace(cx);
1905
0
  }
1906
0
  if (!isNull) {
1907
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->streamIdentifier_id, temp.ptr())) {
1908
0
      return false;
1909
0
    }
1910
0
  }
1911
0
  if (!isNull && !temp->isUndefined()) {
1912
0
    mStreamIdentifier.Construct();
1913
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mStreamIdentifier.Value()))) {
1914
0
      return false;
1915
0
    }
1916
0
    mIsAnyMemberPresent = true;
1917
0
  }
1918
0
1919
0
  if (!isNull) {
1920
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->trackIds_id, temp.ptr())) {
1921
0
      return false;
1922
0
    }
1923
0
  }
1924
0
  if (!isNull && !temp->isUndefined()) {
1925
0
    mTrackIds.Construct();
1926
0
    if (temp.ref().isObject()) {
1927
0
      JS::ForOfIterator iter(cx);
1928
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
1929
0
        return false;
1930
0
      }
1931
0
      if (!iter.valueIsIterable()) {
1932
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'trackIds' member of RTCMediaStreamStats");
1933
0
        return false;
1934
0
      }
1935
0
      Sequence<nsString> &arr = (mTrackIds.Value());
1936
0
      JS::Rooted<JS::Value> temp(cx);
1937
0
      while (true) {
1938
0
        bool done;
1939
0
        if (!iter.next(&temp, &done)) {
1940
0
          return false;
1941
0
        }
1942
0
        if (done) {
1943
0
          break;
1944
0
        }
1945
0
        nsString* slotPtr = arr.AppendElement(mozilla::fallible);
1946
0
        if (!slotPtr) {
1947
0
          JS_ReportOutOfMemory(cx);
1948
0
          return false;
1949
0
        }
1950
0
        nsString& slot = *slotPtr;
1951
0
        if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
1952
0
          return false;
1953
0
        }
1954
0
      }
1955
0
    } else {
1956
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'trackIds' member of RTCMediaStreamStats");
1957
0
      return false;
1958
0
    }
1959
0
    mIsAnyMemberPresent = true;
1960
0
  }
1961
0
  return true;
1962
0
}
1963
1964
bool
1965
RTCMediaStreamStats::Init(const nsAString& aJSON)
1966
0
{
1967
0
  AutoJSAPI jsapi;
1968
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
1969
0
  if (!cleanGlobal) {
1970
0
    return false;
1971
0
  }
1972
0
  if (!jsapi.Init(cleanGlobal)) {
1973
0
    return false;
1974
0
  }
1975
0
  JSContext* cx = jsapi.cx();
1976
0
  JS::Rooted<JS::Value> json(cx);
1977
0
  bool ok = ParseJSON(cx, aJSON, &json);
1978
0
  NS_ENSURE_TRUE(ok, false);
1979
0
  return Init(cx, json);
1980
0
}
1981
1982
bool
1983
RTCMediaStreamStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1984
0
{
1985
0
  RTCMediaStreamStatsAtoms* atomsCache = GetAtomCache<RTCMediaStreamStatsAtoms>(cx);
1986
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1987
0
    return false;
1988
0
  }
1989
0
1990
0
  // Per spec, we define the parent's members first
1991
0
  if (!RTCStats::ToObjectInternal(cx, rval)) {
1992
0
    return false;
1993
0
  }
1994
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
1995
0
1996
0
  if (mStreamIdentifier.WasPassed()) {
1997
0
    do {
1998
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1999
0
      JS::Rooted<JS::Value> temp(cx);
2000
0
      nsString const & currentValue = mStreamIdentifier.InternalValue();
2001
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
2002
0
        return false;
2003
0
      }
2004
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->streamIdentifier_id, temp, JSPROP_ENUMERATE)) {
2005
0
        return false;
2006
0
      }
2007
0
      break;
2008
0
    } while(false);
2009
0
  }
2010
0
2011
0
  if (mTrackIds.WasPassed()) {
2012
0
    do {
2013
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2014
0
      JS::Rooted<JS::Value> temp(cx);
2015
0
      Sequence<nsString> const & currentValue = mTrackIds.InternalValue();
2016
0
2017
0
      uint32_t length = currentValue.Length();
2018
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
2019
0
      if (!returnArray) {
2020
0
        return false;
2021
0
      }
2022
0
      // Scope for 'tmp'
2023
0
      {
2024
0
        JS::Rooted<JS::Value> tmp(cx);
2025
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
2026
0
          // Control block to let us common up the JS_DefineElement calls when there
2027
0
          // are different ways to succeed at wrapping the object.
2028
0
          do {
2029
0
            if (!xpc::NonVoidStringToJsval(cx, currentValue[sequenceIdx0], &tmp)) {
2030
0
              return false;
2031
0
            }
2032
0
            break;
2033
0
          } while (false);
2034
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
2035
0
                                JSPROP_ENUMERATE)) {
2036
0
            return false;
2037
0
          }
2038
0
        }
2039
0
      }
2040
0
      temp.setObject(*returnArray);
2041
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->trackIds_id, temp, JSPROP_ENUMERATE)) {
2042
0
        return false;
2043
0
      }
2044
0
      break;
2045
0
    } while(false);
2046
0
  }
2047
0
2048
0
  return true;
2049
0
}
2050
2051
bool
2052
RTCMediaStreamStats::ToJSON(nsAString& aJSON) const
2053
0
{
2054
0
  AutoJSAPI jsapi;
2055
0
  jsapi.Init();
2056
0
  JSContext *cx = jsapi.cx();
2057
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
2058
0
  // because we'll only be creating objects, in ways that have no
2059
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
2060
0
  // which likewise guarantees no side-effects for the sorts of
2061
0
  // things we will pass it.
2062
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
2063
0
  JS::Rooted<JS::Value> val(cx);
2064
0
  if (!ToObjectInternal(cx, &val)) {
2065
0
    return false;
2066
0
  }
2067
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
2068
0
  return StringifyToJSON(cx, obj, aJSON);
2069
0
}
2070
2071
void
2072
RTCMediaStreamStats::TraceDictionary(JSTracer* trc)
2073
0
{
2074
0
  RTCStats::TraceDictionary(trc);
2075
0
}
2076
2077
RTCMediaStreamStats&
2078
RTCMediaStreamStats::operator=(const RTCMediaStreamStats& aOther)
2079
0
{
2080
0
  RTCStats::operator=(aOther);
2081
0
  mStreamIdentifier.Reset();
2082
0
  if (aOther.mStreamIdentifier.WasPassed()) {
2083
0
    mStreamIdentifier.Construct(aOther.mStreamIdentifier.Value());
2084
0
  }
2085
0
  mTrackIds.Reset();
2086
0
  if (aOther.mTrackIds.WasPassed()) {
2087
0
    mTrackIds.Construct(aOther.mTrackIds.Value());
2088
0
  }
2089
0
  return *this;
2090
0
}
2091
2092
namespace binding_detail {
2093
} // namespace binding_detail
2094
2095
2096
2097
RTCMediaStreamTrackStats::RTCMediaStreamTrackStats()
2098
  : RTCStats(FastDictionaryInitializer())
2099
0
{
2100
0
  // Safe to pass a null context if we pass a null value
2101
0
  Init(nullptr, JS::NullHandleValue);
2102
0
}
2103
2104
2105
2106
bool
2107
RTCMediaStreamTrackStats::InitIds(JSContext* cx, RTCMediaStreamTrackStatsAtoms* atomsCache)
2108
0
{
2109
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
2110
0
2111
0
  // Initialize these in reverse order so that any failure leaves the first one
2112
0
  // uninitialized.
2113
0
  if (!atomsCache->trackIdentifier_id.init(cx, "trackIdentifier") ||
2114
0
      !atomsCache->ssrcIds_id.init(cx, "ssrcIds") ||
2115
0
      !atomsCache->remoteSource_id.init(cx, "remoteSource") ||
2116
0
      !atomsCache->framesSent_id.init(cx, "framesSent") ||
2117
0
      !atomsCache->framesReceived_id.init(cx, "framesReceived") ||
2118
0
      !atomsCache->framesPerSecond_id.init(cx, "framesPerSecond") ||
2119
0
      !atomsCache->framesDropped_id.init(cx, "framesDropped") ||
2120
0
      !atomsCache->framesDecoded_id.init(cx, "framesDecoded") ||
2121
0
      !atomsCache->framesCorrupted_id.init(cx, "framesCorrupted") ||
2122
0
      !atomsCache->frameWidth_id.init(cx, "frameWidth") ||
2123
0
      !atomsCache->frameHeight_id.init(cx, "frameHeight") ||
2124
0
      !atomsCache->echoReturnLossEnhancement_id.init(cx, "echoReturnLossEnhancement") ||
2125
0
      !atomsCache->echoReturnLoss_id.init(cx, "echoReturnLoss") ||
2126
0
      !atomsCache->audioLevel_id.init(cx, "audioLevel")) {
2127
0
    return false;
2128
0
  }
2129
0
  return true;
2130
0
}
2131
2132
bool
2133
RTCMediaStreamTrackStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
2134
0
{
2135
0
  // Passing a null JSContext is OK only if we're initing from null,
2136
0
  // Since in that case we will not have to do any property gets
2137
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
2138
0
  // checkers by static analysis tools
2139
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
2140
0
  RTCMediaStreamTrackStatsAtoms* atomsCache = nullptr;
2141
0
  if (cx) {
2142
0
    atomsCache = GetAtomCache<RTCMediaStreamTrackStatsAtoms>(cx);
2143
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2144
0
      return false;
2145
0
    }
2146
0
  }
2147
0
2148
0
  // Per spec, we init the parent's members first
2149
0
  if (!RTCStats::Init(cx, val)) {
2150
0
    return false;
2151
0
  }
2152
0
2153
0
  bool isNull = val.isNullOrUndefined();
2154
0
  // We only need these if !isNull, in which case we have |cx|.
2155
0
  Maybe<JS::Rooted<JSObject *> > object;
2156
0
  Maybe<JS::Rooted<JS::Value> > temp;
2157
0
  if (!isNull) {
2158
0
    MOZ_ASSERT(cx);
2159
0
    object.emplace(cx, &val.toObject());
2160
0
    temp.emplace(cx);
2161
0
  }
2162
0
  if (!isNull) {
2163
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->audioLevel_id, temp.ptr())) {
2164
0
      return false;
2165
0
    }
2166
0
  }
2167
0
  if (!isNull && !temp->isUndefined()) {
2168
0
    mAudioLevel.Construct();
2169
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mAudioLevel.Value()))) {
2170
0
      return false;
2171
0
    } else if (!mozilla::IsFinite((mAudioLevel.Value()))) {
2172
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'audioLevel' member of RTCMediaStreamTrackStats");
2173
0
      return false;
2174
0
    }
2175
0
    mIsAnyMemberPresent = true;
2176
0
  }
2177
0
2178
0
  if (!isNull) {
2179
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->echoReturnLoss_id, temp.ptr())) {
2180
0
      return false;
2181
0
    }
2182
0
  }
2183
0
  if (!isNull && !temp->isUndefined()) {
2184
0
    mEchoReturnLoss.Construct();
2185
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mEchoReturnLoss.Value()))) {
2186
0
      return false;
2187
0
    } else if (!mozilla::IsFinite((mEchoReturnLoss.Value()))) {
2188
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'echoReturnLoss' member of RTCMediaStreamTrackStats");
2189
0
      return false;
2190
0
    }
2191
0
    mIsAnyMemberPresent = true;
2192
0
  }
2193
0
2194
0
  if (!isNull) {
2195
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->echoReturnLossEnhancement_id, temp.ptr())) {
2196
0
      return false;
2197
0
    }
2198
0
  }
2199
0
  if (!isNull && !temp->isUndefined()) {
2200
0
    mEchoReturnLossEnhancement.Construct();
2201
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mEchoReturnLossEnhancement.Value()))) {
2202
0
      return false;
2203
0
    } else if (!mozilla::IsFinite((mEchoReturnLossEnhancement.Value()))) {
2204
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'echoReturnLossEnhancement' member of RTCMediaStreamTrackStats");
2205
0
      return false;
2206
0
    }
2207
0
    mIsAnyMemberPresent = true;
2208
0
  }
2209
0
2210
0
  if (!isNull) {
2211
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->frameHeight_id, temp.ptr())) {
2212
0
      return false;
2213
0
    }
2214
0
  }
2215
0
  if (!isNull && !temp->isUndefined()) {
2216
0
    mFrameHeight.Construct();
2217
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mFrameHeight.Value()))) {
2218
0
      return false;
2219
0
    }
2220
0
    mIsAnyMemberPresent = true;
2221
0
  }
2222
0
2223
0
  if (!isNull) {
2224
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->frameWidth_id, temp.ptr())) {
2225
0
      return false;
2226
0
    }
2227
0
  }
2228
0
  if (!isNull && !temp->isUndefined()) {
2229
0
    mFrameWidth.Construct();
2230
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mFrameWidth.Value()))) {
2231
0
      return false;
2232
0
    }
2233
0
    mIsAnyMemberPresent = true;
2234
0
  }
2235
0
2236
0
  if (!isNull) {
2237
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->framesCorrupted_id, temp.ptr())) {
2238
0
      return false;
2239
0
    }
2240
0
  }
2241
0
  if (!isNull && !temp->isUndefined()) {
2242
0
    mFramesCorrupted.Construct();
2243
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mFramesCorrupted.Value()))) {
2244
0
      return false;
2245
0
    }
2246
0
    mIsAnyMemberPresent = true;
2247
0
  }
2248
0
2249
0
  if (!isNull) {
2250
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->framesDecoded_id, temp.ptr())) {
2251
0
      return false;
2252
0
    }
2253
0
  }
2254
0
  if (!isNull && !temp->isUndefined()) {
2255
0
    mFramesDecoded.Construct();
2256
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mFramesDecoded.Value()))) {
2257
0
      return false;
2258
0
    }
2259
0
    mIsAnyMemberPresent = true;
2260
0
  }
2261
0
2262
0
  if (!isNull) {
2263
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->framesDropped_id, temp.ptr())) {
2264
0
      return false;
2265
0
    }
2266
0
  }
2267
0
  if (!isNull && !temp->isUndefined()) {
2268
0
    mFramesDropped.Construct();
2269
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mFramesDropped.Value()))) {
2270
0
      return false;
2271
0
    }
2272
0
    mIsAnyMemberPresent = true;
2273
0
  }
2274
0
2275
0
  if (!isNull) {
2276
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->framesPerSecond_id, temp.ptr())) {
2277
0
      return false;
2278
0
    }
2279
0
  }
2280
0
  if (!isNull && !temp->isUndefined()) {
2281
0
    mFramesPerSecond.Construct();
2282
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mFramesPerSecond.Value()))) {
2283
0
      return false;
2284
0
    } else if (!mozilla::IsFinite((mFramesPerSecond.Value()))) {
2285
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'framesPerSecond' member of RTCMediaStreamTrackStats");
2286
0
      return false;
2287
0
    }
2288
0
    mIsAnyMemberPresent = true;
2289
0
  }
2290
0
2291
0
  if (!isNull) {
2292
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->framesReceived_id, temp.ptr())) {
2293
0
      return false;
2294
0
    }
2295
0
  }
2296
0
  if (!isNull && !temp->isUndefined()) {
2297
0
    mFramesReceived.Construct();
2298
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mFramesReceived.Value()))) {
2299
0
      return false;
2300
0
    }
2301
0
    mIsAnyMemberPresent = true;
2302
0
  }
2303
0
2304
0
  if (!isNull) {
2305
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->framesSent_id, temp.ptr())) {
2306
0
      return false;
2307
0
    }
2308
0
  }
2309
0
  if (!isNull && !temp->isUndefined()) {
2310
0
    mFramesSent.Construct();
2311
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mFramesSent.Value()))) {
2312
0
      return false;
2313
0
    }
2314
0
    mIsAnyMemberPresent = true;
2315
0
  }
2316
0
2317
0
  if (!isNull) {
2318
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->remoteSource_id, temp.ptr())) {
2319
0
      return false;
2320
0
    }
2321
0
  }
2322
0
  if (!isNull && !temp->isUndefined()) {
2323
0
    mRemoteSource.Construct();
2324
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mRemoteSource.Value()))) {
2325
0
      return false;
2326
0
    }
2327
0
    mIsAnyMemberPresent = true;
2328
0
  }
2329
0
2330
0
  if (!isNull) {
2331
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->ssrcIds_id, temp.ptr())) {
2332
0
      return false;
2333
0
    }
2334
0
  }
2335
0
  if (!isNull && !temp->isUndefined()) {
2336
0
    mSsrcIds.Construct();
2337
0
    if (temp.ref().isObject()) {
2338
0
      JS::ForOfIterator iter(cx);
2339
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
2340
0
        return false;
2341
0
      }
2342
0
      if (!iter.valueIsIterable()) {
2343
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'ssrcIds' member of RTCMediaStreamTrackStats");
2344
0
        return false;
2345
0
      }
2346
0
      Sequence<nsString> &arr = (mSsrcIds.Value());
2347
0
      JS::Rooted<JS::Value> temp(cx);
2348
0
      while (true) {
2349
0
        bool done;
2350
0
        if (!iter.next(&temp, &done)) {
2351
0
          return false;
2352
0
        }
2353
0
        if (done) {
2354
0
          break;
2355
0
        }
2356
0
        nsString* slotPtr = arr.AppendElement(mozilla::fallible);
2357
0
        if (!slotPtr) {
2358
0
          JS_ReportOutOfMemory(cx);
2359
0
          return false;
2360
0
        }
2361
0
        nsString& slot = *slotPtr;
2362
0
        if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
2363
0
          return false;
2364
0
        }
2365
0
      }
2366
0
    } else {
2367
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'ssrcIds' member of RTCMediaStreamTrackStats");
2368
0
      return false;
2369
0
    }
2370
0
    mIsAnyMemberPresent = true;
2371
0
  }
2372
0
2373
0
  if (!isNull) {
2374
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->trackIdentifier_id, temp.ptr())) {
2375
0
      return false;
2376
0
    }
2377
0
  }
2378
0
  if (!isNull && !temp->isUndefined()) {
2379
0
    mTrackIdentifier.Construct();
2380
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mTrackIdentifier.Value()))) {
2381
0
      return false;
2382
0
    }
2383
0
    mIsAnyMemberPresent = true;
2384
0
  }
2385
0
  return true;
2386
0
}
2387
2388
bool
2389
RTCMediaStreamTrackStats::Init(const nsAString& aJSON)
2390
0
{
2391
0
  AutoJSAPI jsapi;
2392
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
2393
0
  if (!cleanGlobal) {
2394
0
    return false;
2395
0
  }
2396
0
  if (!jsapi.Init(cleanGlobal)) {
2397
0
    return false;
2398
0
  }
2399
0
  JSContext* cx = jsapi.cx();
2400
0
  JS::Rooted<JS::Value> json(cx);
2401
0
  bool ok = ParseJSON(cx, aJSON, &json);
2402
0
  NS_ENSURE_TRUE(ok, false);
2403
0
  return Init(cx, json);
2404
0
}
2405
2406
bool
2407
RTCMediaStreamTrackStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
2408
0
{
2409
0
  RTCMediaStreamTrackStatsAtoms* atomsCache = GetAtomCache<RTCMediaStreamTrackStatsAtoms>(cx);
2410
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2411
0
    return false;
2412
0
  }
2413
0
2414
0
  // Per spec, we define the parent's members first
2415
0
  if (!RTCStats::ToObjectInternal(cx, rval)) {
2416
0
    return false;
2417
0
  }
2418
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
2419
0
2420
0
  if (mAudioLevel.WasPassed()) {
2421
0
    do {
2422
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2423
0
      JS::Rooted<JS::Value> temp(cx);
2424
0
      double const & currentValue = mAudioLevel.InternalValue();
2425
0
      temp.set(JS_NumberValue(double(currentValue)));
2426
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->audioLevel_id, temp, JSPROP_ENUMERATE)) {
2427
0
        return false;
2428
0
      }
2429
0
      break;
2430
0
    } while(false);
2431
0
  }
2432
0
2433
0
  if (mEchoReturnLoss.WasPassed()) {
2434
0
    do {
2435
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2436
0
      JS::Rooted<JS::Value> temp(cx);
2437
0
      double const & currentValue = mEchoReturnLoss.InternalValue();
2438
0
      temp.set(JS_NumberValue(double(currentValue)));
2439
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->echoReturnLoss_id, temp, JSPROP_ENUMERATE)) {
2440
0
        return false;
2441
0
      }
2442
0
      break;
2443
0
    } while(false);
2444
0
  }
2445
0
2446
0
  if (mEchoReturnLossEnhancement.WasPassed()) {
2447
0
    do {
2448
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2449
0
      JS::Rooted<JS::Value> temp(cx);
2450
0
      double const & currentValue = mEchoReturnLossEnhancement.InternalValue();
2451
0
      temp.set(JS_NumberValue(double(currentValue)));
2452
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->echoReturnLossEnhancement_id, temp, JSPROP_ENUMERATE)) {
2453
0
        return false;
2454
0
      }
2455
0
      break;
2456
0
    } while(false);
2457
0
  }
2458
0
2459
0
  if (mFrameHeight.WasPassed()) {
2460
0
    do {
2461
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2462
0
      JS::Rooted<JS::Value> temp(cx);
2463
0
      uint32_t const & currentValue = mFrameHeight.InternalValue();
2464
0
      temp.setNumber(currentValue);
2465
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->frameHeight_id, temp, JSPROP_ENUMERATE)) {
2466
0
        return false;
2467
0
      }
2468
0
      break;
2469
0
    } while(false);
2470
0
  }
2471
0
2472
0
  if (mFrameWidth.WasPassed()) {
2473
0
    do {
2474
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2475
0
      JS::Rooted<JS::Value> temp(cx);
2476
0
      uint32_t const & currentValue = mFrameWidth.InternalValue();
2477
0
      temp.setNumber(currentValue);
2478
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->frameWidth_id, temp, JSPROP_ENUMERATE)) {
2479
0
        return false;
2480
0
      }
2481
0
      break;
2482
0
    } while(false);
2483
0
  }
2484
0
2485
0
  if (mFramesCorrupted.WasPassed()) {
2486
0
    do {
2487
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2488
0
      JS::Rooted<JS::Value> temp(cx);
2489
0
      uint32_t const & currentValue = mFramesCorrupted.InternalValue();
2490
0
      temp.setNumber(currentValue);
2491
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->framesCorrupted_id, temp, JSPROP_ENUMERATE)) {
2492
0
        return false;
2493
0
      }
2494
0
      break;
2495
0
    } while(false);
2496
0
  }
2497
0
2498
0
  if (mFramesDecoded.WasPassed()) {
2499
0
    do {
2500
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2501
0
      JS::Rooted<JS::Value> temp(cx);
2502
0
      uint32_t const & currentValue = mFramesDecoded.InternalValue();
2503
0
      temp.setNumber(currentValue);
2504
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->framesDecoded_id, temp, JSPROP_ENUMERATE)) {
2505
0
        return false;
2506
0
      }
2507
0
      break;
2508
0
    } while(false);
2509
0
  }
2510
0
2511
0
  if (mFramesDropped.WasPassed()) {
2512
0
    do {
2513
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2514
0
      JS::Rooted<JS::Value> temp(cx);
2515
0
      uint32_t const & currentValue = mFramesDropped.InternalValue();
2516
0
      temp.setNumber(currentValue);
2517
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->framesDropped_id, temp, JSPROP_ENUMERATE)) {
2518
0
        return false;
2519
0
      }
2520
0
      break;
2521
0
    } while(false);
2522
0
  }
2523
0
2524
0
  if (mFramesPerSecond.WasPassed()) {
2525
0
    do {
2526
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2527
0
      JS::Rooted<JS::Value> temp(cx);
2528
0
      double const & currentValue = mFramesPerSecond.InternalValue();
2529
0
      temp.set(JS_NumberValue(double(currentValue)));
2530
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->framesPerSecond_id, temp, JSPROP_ENUMERATE)) {
2531
0
        return false;
2532
0
      }
2533
0
      break;
2534
0
    } while(false);
2535
0
  }
2536
0
2537
0
  if (mFramesReceived.WasPassed()) {
2538
0
    do {
2539
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2540
0
      JS::Rooted<JS::Value> temp(cx);
2541
0
      uint32_t const & currentValue = mFramesReceived.InternalValue();
2542
0
      temp.setNumber(currentValue);
2543
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->framesReceived_id, temp, JSPROP_ENUMERATE)) {
2544
0
        return false;
2545
0
      }
2546
0
      break;
2547
0
    } while(false);
2548
0
  }
2549
0
2550
0
  if (mFramesSent.WasPassed()) {
2551
0
    do {
2552
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2553
0
      JS::Rooted<JS::Value> temp(cx);
2554
0
      uint32_t const & currentValue = mFramesSent.InternalValue();
2555
0
      temp.setNumber(currentValue);
2556
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->framesSent_id, temp, JSPROP_ENUMERATE)) {
2557
0
        return false;
2558
0
      }
2559
0
      break;
2560
0
    } while(false);
2561
0
  }
2562
0
2563
0
  if (mRemoteSource.WasPassed()) {
2564
0
    do {
2565
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2566
0
      JS::Rooted<JS::Value> temp(cx);
2567
0
      bool const & currentValue = mRemoteSource.InternalValue();
2568
0
      temp.setBoolean(currentValue);
2569
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->remoteSource_id, temp, JSPROP_ENUMERATE)) {
2570
0
        return false;
2571
0
      }
2572
0
      break;
2573
0
    } while(false);
2574
0
  }
2575
0
2576
0
  if (mSsrcIds.WasPassed()) {
2577
0
    do {
2578
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2579
0
      JS::Rooted<JS::Value> temp(cx);
2580
0
      Sequence<nsString> const & currentValue = mSsrcIds.InternalValue();
2581
0
2582
0
      uint32_t length = currentValue.Length();
2583
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
2584
0
      if (!returnArray) {
2585
0
        return false;
2586
0
      }
2587
0
      // Scope for 'tmp'
2588
0
      {
2589
0
        JS::Rooted<JS::Value> tmp(cx);
2590
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
2591
0
          // Control block to let us common up the JS_DefineElement calls when there
2592
0
          // are different ways to succeed at wrapping the object.
2593
0
          do {
2594
0
            if (!xpc::NonVoidStringToJsval(cx, currentValue[sequenceIdx0], &tmp)) {
2595
0
              return false;
2596
0
            }
2597
0
            break;
2598
0
          } while (false);
2599
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
2600
0
                                JSPROP_ENUMERATE)) {
2601
0
            return false;
2602
0
          }
2603
0
        }
2604
0
      }
2605
0
      temp.setObject(*returnArray);
2606
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->ssrcIds_id, temp, JSPROP_ENUMERATE)) {
2607
0
        return false;
2608
0
      }
2609
0
      break;
2610
0
    } while(false);
2611
0
  }
2612
0
2613
0
  if (mTrackIdentifier.WasPassed()) {
2614
0
    do {
2615
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2616
0
      JS::Rooted<JS::Value> temp(cx);
2617
0
      nsString const & currentValue = mTrackIdentifier.InternalValue();
2618
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
2619
0
        return false;
2620
0
      }
2621
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->trackIdentifier_id, temp, JSPROP_ENUMERATE)) {
2622
0
        return false;
2623
0
      }
2624
0
      break;
2625
0
    } while(false);
2626
0
  }
2627
0
2628
0
  return true;
2629
0
}
2630
2631
bool
2632
RTCMediaStreamTrackStats::ToJSON(nsAString& aJSON) const
2633
0
{
2634
0
  AutoJSAPI jsapi;
2635
0
  jsapi.Init();
2636
0
  JSContext *cx = jsapi.cx();
2637
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
2638
0
  // because we'll only be creating objects, in ways that have no
2639
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
2640
0
  // which likewise guarantees no side-effects for the sorts of
2641
0
  // things we will pass it.
2642
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
2643
0
  JS::Rooted<JS::Value> val(cx);
2644
0
  if (!ToObjectInternal(cx, &val)) {
2645
0
    return false;
2646
0
  }
2647
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
2648
0
  return StringifyToJSON(cx, obj, aJSON);
2649
0
}
2650
2651
void
2652
RTCMediaStreamTrackStats::TraceDictionary(JSTracer* trc)
2653
0
{
2654
0
  RTCStats::TraceDictionary(trc);
2655
0
}
2656
2657
RTCMediaStreamTrackStats&
2658
RTCMediaStreamTrackStats::operator=(const RTCMediaStreamTrackStats& aOther)
2659
0
{
2660
0
  RTCStats::operator=(aOther);
2661
0
  mAudioLevel.Reset();
2662
0
  if (aOther.mAudioLevel.WasPassed()) {
2663
0
    mAudioLevel.Construct(aOther.mAudioLevel.Value());
2664
0
  }
2665
0
  mEchoReturnLoss.Reset();
2666
0
  if (aOther.mEchoReturnLoss.WasPassed()) {
2667
0
    mEchoReturnLoss.Construct(aOther.mEchoReturnLoss.Value());
2668
0
  }
2669
0
  mEchoReturnLossEnhancement.Reset();
2670
0
  if (aOther.mEchoReturnLossEnhancement.WasPassed()) {
2671
0
    mEchoReturnLossEnhancement.Construct(aOther.mEchoReturnLossEnhancement.Value());
2672
0
  }
2673
0
  mFrameHeight.Reset();
2674
0
  if (aOther.mFrameHeight.WasPassed()) {
2675
0
    mFrameHeight.Construct(aOther.mFrameHeight.Value());
2676
0
  }
2677
0
  mFrameWidth.Reset();
2678
0
  if (aOther.mFrameWidth.WasPassed()) {
2679
0
    mFrameWidth.Construct(aOther.mFrameWidth.Value());
2680
0
  }
2681
0
  mFramesCorrupted.Reset();
2682
0
  if (aOther.mFramesCorrupted.WasPassed()) {
2683
0
    mFramesCorrupted.Construct(aOther.mFramesCorrupted.Value());
2684
0
  }
2685
0
  mFramesDecoded.Reset();
2686
0
  if (aOther.mFramesDecoded.WasPassed()) {
2687
0
    mFramesDecoded.Construct(aOther.mFramesDecoded.Value());
2688
0
  }
2689
0
  mFramesDropped.Reset();
2690
0
  if (aOther.mFramesDropped.WasPassed()) {
2691
0
    mFramesDropped.Construct(aOther.mFramesDropped.Value());
2692
0
  }
2693
0
  mFramesPerSecond.Reset();
2694
0
  if (aOther.mFramesPerSecond.WasPassed()) {
2695
0
    mFramesPerSecond.Construct(aOther.mFramesPerSecond.Value());
2696
0
  }
2697
0
  mFramesReceived.Reset();
2698
0
  if (aOther.mFramesReceived.WasPassed()) {
2699
0
    mFramesReceived.Construct(aOther.mFramesReceived.Value());
2700
0
  }
2701
0
  mFramesSent.Reset();
2702
0
  if (aOther.mFramesSent.WasPassed()) {
2703
0
    mFramesSent.Construct(aOther.mFramesSent.Value());
2704
0
  }
2705
0
  mRemoteSource.Reset();
2706
0
  if (aOther.mRemoteSource.WasPassed()) {
2707
0
    mRemoteSource.Construct(aOther.mRemoteSource.Value());
2708
0
  }
2709
0
  mSsrcIds.Reset();
2710
0
  if (aOther.mSsrcIds.WasPassed()) {
2711
0
    mSsrcIds.Construct(aOther.mSsrcIds.Value());
2712
0
  }
2713
0
  mTrackIdentifier.Reset();
2714
0
  if (aOther.mTrackIdentifier.WasPassed()) {
2715
0
    mTrackIdentifier.Construct(aOther.mTrackIdentifier.Value());
2716
0
  }
2717
0
  return *this;
2718
0
}
2719
2720
namespace binding_detail {
2721
} // namespace binding_detail
2722
2723
2724
2725
RTCRTPContributingSourceStats::RTCRTPContributingSourceStats()
2726
  : RTCStats(FastDictionaryInitializer())
2727
0
{
2728
0
  // Safe to pass a null context if we pass a null value
2729
0
  Init(nullptr, JS::NullHandleValue);
2730
0
}
2731
2732
2733
2734
bool
2735
RTCRTPContributingSourceStats::InitIds(JSContext* cx, RTCRTPContributingSourceStatsAtoms* atomsCache)
2736
0
{
2737
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
2738
0
2739
0
  // Initialize these in reverse order so that any failure leaves the first one
2740
0
  // uninitialized.
2741
0
  if (!atomsCache->inboundRtpStreamId_id.init(cx, "inboundRtpStreamId") ||
2742
0
      !atomsCache->contributorSsrc_id.init(cx, "contributorSsrc")) {
2743
0
    return false;
2744
0
  }
2745
0
  return true;
2746
0
}
2747
2748
bool
2749
RTCRTPContributingSourceStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
2750
0
{
2751
0
  // Passing a null JSContext is OK only if we're initing from null,
2752
0
  // Since in that case we will not have to do any property gets
2753
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
2754
0
  // checkers by static analysis tools
2755
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
2756
0
  RTCRTPContributingSourceStatsAtoms* atomsCache = nullptr;
2757
0
  if (cx) {
2758
0
    atomsCache = GetAtomCache<RTCRTPContributingSourceStatsAtoms>(cx);
2759
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2760
0
      return false;
2761
0
    }
2762
0
  }
2763
0
2764
0
  // Per spec, we init the parent's members first
2765
0
  if (!RTCStats::Init(cx, val)) {
2766
0
    return false;
2767
0
  }
2768
0
2769
0
  bool isNull = val.isNullOrUndefined();
2770
0
  // We only need these if !isNull, in which case we have |cx|.
2771
0
  Maybe<JS::Rooted<JSObject *> > object;
2772
0
  Maybe<JS::Rooted<JS::Value> > temp;
2773
0
  if (!isNull) {
2774
0
    MOZ_ASSERT(cx);
2775
0
    object.emplace(cx, &val.toObject());
2776
0
    temp.emplace(cx);
2777
0
  }
2778
0
  if (!isNull) {
2779
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->contributorSsrc_id, temp.ptr())) {
2780
0
      return false;
2781
0
    }
2782
0
  }
2783
0
  if (!isNull && !temp->isUndefined()) {
2784
0
    mContributorSsrc.Construct();
2785
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mContributorSsrc.Value()))) {
2786
0
      return false;
2787
0
    }
2788
0
    mIsAnyMemberPresent = true;
2789
0
  }
2790
0
2791
0
  if (!isNull) {
2792
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->inboundRtpStreamId_id, temp.ptr())) {
2793
0
      return false;
2794
0
    }
2795
0
  }
2796
0
  if (!isNull && !temp->isUndefined()) {
2797
0
    mInboundRtpStreamId.Construct();
2798
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mInboundRtpStreamId.Value()))) {
2799
0
      return false;
2800
0
    }
2801
0
    mIsAnyMemberPresent = true;
2802
0
  }
2803
0
  return true;
2804
0
}
2805
2806
bool
2807
RTCRTPContributingSourceStats::Init(const nsAString& aJSON)
2808
0
{
2809
0
  AutoJSAPI jsapi;
2810
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
2811
0
  if (!cleanGlobal) {
2812
0
    return false;
2813
0
  }
2814
0
  if (!jsapi.Init(cleanGlobal)) {
2815
0
    return false;
2816
0
  }
2817
0
  JSContext* cx = jsapi.cx();
2818
0
  JS::Rooted<JS::Value> json(cx);
2819
0
  bool ok = ParseJSON(cx, aJSON, &json);
2820
0
  NS_ENSURE_TRUE(ok, false);
2821
0
  return Init(cx, json);
2822
0
}
2823
2824
bool
2825
RTCRTPContributingSourceStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
2826
0
{
2827
0
  RTCRTPContributingSourceStatsAtoms* atomsCache = GetAtomCache<RTCRTPContributingSourceStatsAtoms>(cx);
2828
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2829
0
    return false;
2830
0
  }
2831
0
2832
0
  // Per spec, we define the parent's members first
2833
0
  if (!RTCStats::ToObjectInternal(cx, rval)) {
2834
0
    return false;
2835
0
  }
2836
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
2837
0
2838
0
  if (mContributorSsrc.WasPassed()) {
2839
0
    do {
2840
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2841
0
      JS::Rooted<JS::Value> temp(cx);
2842
0
      uint32_t const & currentValue = mContributorSsrc.InternalValue();
2843
0
      temp.setNumber(currentValue);
2844
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->contributorSsrc_id, temp, JSPROP_ENUMERATE)) {
2845
0
        return false;
2846
0
      }
2847
0
      break;
2848
0
    } while(false);
2849
0
  }
2850
0
2851
0
  if (mInboundRtpStreamId.WasPassed()) {
2852
0
    do {
2853
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2854
0
      JS::Rooted<JS::Value> temp(cx);
2855
0
      nsString const & currentValue = mInboundRtpStreamId.InternalValue();
2856
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
2857
0
        return false;
2858
0
      }
2859
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->inboundRtpStreamId_id, temp, JSPROP_ENUMERATE)) {
2860
0
        return false;
2861
0
      }
2862
0
      break;
2863
0
    } while(false);
2864
0
  }
2865
0
2866
0
  return true;
2867
0
}
2868
2869
bool
2870
RTCRTPContributingSourceStats::ToJSON(nsAString& aJSON) const
2871
0
{
2872
0
  AutoJSAPI jsapi;
2873
0
  jsapi.Init();
2874
0
  JSContext *cx = jsapi.cx();
2875
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
2876
0
  // because we'll only be creating objects, in ways that have no
2877
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
2878
0
  // which likewise guarantees no side-effects for the sorts of
2879
0
  // things we will pass it.
2880
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
2881
0
  JS::Rooted<JS::Value> val(cx);
2882
0
  if (!ToObjectInternal(cx, &val)) {
2883
0
    return false;
2884
0
  }
2885
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
2886
0
  return StringifyToJSON(cx, obj, aJSON);
2887
0
}
2888
2889
void
2890
RTCRTPContributingSourceStats::TraceDictionary(JSTracer* trc)
2891
0
{
2892
0
  RTCStats::TraceDictionary(trc);
2893
0
}
2894
2895
RTCRTPContributingSourceStats&
2896
RTCRTPContributingSourceStats::operator=(const RTCRTPContributingSourceStats& aOther)
2897
0
{
2898
0
  RTCStats::operator=(aOther);
2899
0
  mContributorSsrc.Reset();
2900
0
  if (aOther.mContributorSsrc.WasPassed()) {
2901
0
    mContributorSsrc.Construct(aOther.mContributorSsrc.Value());
2902
0
  }
2903
0
  mInboundRtpStreamId.Reset();
2904
0
  if (aOther.mInboundRtpStreamId.WasPassed()) {
2905
0
    mInboundRtpStreamId.Construct(aOther.mInboundRtpStreamId.Value());
2906
0
  }
2907
0
  return *this;
2908
0
}
2909
2910
namespace binding_detail {
2911
} // namespace binding_detail
2912
2913
2914
2915
RTCRtpStreamStats::RTCRtpStreamStats()
2916
  : RTCStats(FastDictionaryInitializer())
2917
0
{
2918
0
  // Safe to pass a null context if we pass a null value
2919
0
  Init(nullptr, JS::NullHandleValue);
2920
0
}
2921
2922
2923
2924
bool
2925
RTCRtpStreamStats::InitIds(JSContext* cx, RTCRtpStreamStatsAtoms* atomsCache)
2926
0
{
2927
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
2928
0
2929
0
  // Initialize these in reverse order so that any failure leaves the first one
2930
0
  // uninitialized.
2931
0
  if (!atomsCache->transportId_id.init(cx, "transportId") ||
2932
0
      !atomsCache->ssrc_id.init(cx, "ssrc") ||
2933
0
      !atomsCache->remoteId_id.init(cx, "remoteId") ||
2934
0
      !atomsCache->pliCount_id.init(cx, "pliCount") ||
2935
0
      !atomsCache->nackCount_id.init(cx, "nackCount") ||
2936
0
      !atomsCache->mediaType_id.init(cx, "mediaType") ||
2937
0
      !atomsCache->mediaTrackId_id.init(cx, "mediaTrackId") ||
2938
0
      !atomsCache->kind_id.init(cx, "kind") ||
2939
0
      !atomsCache->isRemote_id.init(cx, "isRemote") ||
2940
0
      !atomsCache->framerateStdDev_id.init(cx, "framerateStdDev") ||
2941
0
      !atomsCache->framerateMean_id.init(cx, "framerateMean") ||
2942
0
      !atomsCache->firCount_id.init(cx, "firCount") ||
2943
0
      !atomsCache->codecId_id.init(cx, "codecId") ||
2944
0
      !atomsCache->bitrateStdDev_id.init(cx, "bitrateStdDev") ||
2945
0
      !atomsCache->bitrateMean_id.init(cx, "bitrateMean")) {
2946
0
    return false;
2947
0
  }
2948
0
  return true;
2949
0
}
2950
2951
bool
2952
RTCRtpStreamStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
2953
0
{
2954
0
  // Passing a null JSContext is OK only if we're initing from null,
2955
0
  // Since in that case we will not have to do any property gets
2956
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
2957
0
  // checkers by static analysis tools
2958
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
2959
0
  RTCRtpStreamStatsAtoms* atomsCache = nullptr;
2960
0
  if (cx) {
2961
0
    atomsCache = GetAtomCache<RTCRtpStreamStatsAtoms>(cx);
2962
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2963
0
      return false;
2964
0
    }
2965
0
  }
2966
0
2967
0
  // Per spec, we init the parent's members first
2968
0
  if (!RTCStats::Init(cx, val)) {
2969
0
    return false;
2970
0
  }
2971
0
2972
0
  bool isNull = val.isNullOrUndefined();
2973
0
  // We only need these if !isNull, in which case we have |cx|.
2974
0
  Maybe<JS::Rooted<JSObject *> > object;
2975
0
  Maybe<JS::Rooted<JS::Value> > temp;
2976
0
  if (!isNull) {
2977
0
    MOZ_ASSERT(cx);
2978
0
    object.emplace(cx, &val.toObject());
2979
0
    temp.emplace(cx);
2980
0
  }
2981
0
  if (!isNull) {
2982
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->bitrateMean_id, temp.ptr())) {
2983
0
      return false;
2984
0
    }
2985
0
  }
2986
0
  if (!isNull && !temp->isUndefined()) {
2987
0
    mBitrateMean.Construct();
2988
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mBitrateMean.Value()))) {
2989
0
      return false;
2990
0
    } else if (!mozilla::IsFinite((mBitrateMean.Value()))) {
2991
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'bitrateMean' member of RTCRtpStreamStats");
2992
0
      return false;
2993
0
    }
2994
0
    mIsAnyMemberPresent = true;
2995
0
  }
2996
0
2997
0
  if (!isNull) {
2998
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->bitrateStdDev_id, temp.ptr())) {
2999
0
      return false;
3000
0
    }
3001
0
  }
3002
0
  if (!isNull && !temp->isUndefined()) {
3003
0
    mBitrateStdDev.Construct();
3004
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mBitrateStdDev.Value()))) {
3005
0
      return false;
3006
0
    } else if (!mozilla::IsFinite((mBitrateStdDev.Value()))) {
3007
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'bitrateStdDev' member of RTCRtpStreamStats");
3008
0
      return false;
3009
0
    }
3010
0
    mIsAnyMemberPresent = true;
3011
0
  }
3012
0
3013
0
  if (!isNull) {
3014
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->codecId_id, temp.ptr())) {
3015
0
      return false;
3016
0
    }
3017
0
  }
3018
0
  if (!isNull && !temp->isUndefined()) {
3019
0
    mCodecId.Construct();
3020
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mCodecId.Value()))) {
3021
0
      return false;
3022
0
    }
3023
0
    mIsAnyMemberPresent = true;
3024
0
  }
3025
0
3026
0
  if (!isNull) {
3027
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->firCount_id, temp.ptr())) {
3028
0
      return false;
3029
0
    }
3030
0
  }
3031
0
  if (!isNull && !temp->isUndefined()) {
3032
0
    mFirCount.Construct();
3033
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mFirCount.Value()))) {
3034
0
      return false;
3035
0
    }
3036
0
    mIsAnyMemberPresent = true;
3037
0
  }
3038
0
3039
0
  if (!isNull) {
3040
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->framerateMean_id, temp.ptr())) {
3041
0
      return false;
3042
0
    }
3043
0
  }
3044
0
  if (!isNull && !temp->isUndefined()) {
3045
0
    mFramerateMean.Construct();
3046
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mFramerateMean.Value()))) {
3047
0
      return false;
3048
0
    } else if (!mozilla::IsFinite((mFramerateMean.Value()))) {
3049
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'framerateMean' member of RTCRtpStreamStats");
3050
0
      return false;
3051
0
    }
3052
0
    mIsAnyMemberPresent = true;
3053
0
  }
3054
0
3055
0
  if (!isNull) {
3056
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->framerateStdDev_id, temp.ptr())) {
3057
0
      return false;
3058
0
    }
3059
0
  }
3060
0
  if (!isNull && !temp->isUndefined()) {
3061
0
    mFramerateStdDev.Construct();
3062
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mFramerateStdDev.Value()))) {
3063
0
      return false;
3064
0
    } else if (!mozilla::IsFinite((mFramerateStdDev.Value()))) {
3065
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'framerateStdDev' member of RTCRtpStreamStats");
3066
0
      return false;
3067
0
    }
3068
0
    mIsAnyMemberPresent = true;
3069
0
  }
3070
0
3071
0
  if (!isNull) {
3072
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->isRemote_id, temp.ptr())) {
3073
0
      return false;
3074
0
    }
3075
0
  }
3076
0
  if (!isNull && !temp->isUndefined()) {
3077
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mIsRemote)) {
3078
0
      return false;
3079
0
    }
3080
0
  } else {
3081
0
    mIsRemote = false;
3082
0
  }
3083
0
  mIsAnyMemberPresent = true;
3084
0
3085
0
  if (!isNull) {
3086
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->kind_id, temp.ptr())) {
3087
0
      return false;
3088
0
    }
3089
0
  }
3090
0
  if (!isNull && !temp->isUndefined()) {
3091
0
    mKind.Construct();
3092
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mKind.Value()))) {
3093
0
      return false;
3094
0
    }
3095
0
    mIsAnyMemberPresent = true;
3096
0
  }
3097
0
3098
0
  if (!isNull) {
3099
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->mediaTrackId_id, temp.ptr())) {
3100
0
      return false;
3101
0
    }
3102
0
  }
3103
0
  if (!isNull && !temp->isUndefined()) {
3104
0
    mMediaTrackId.Construct();
3105
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mMediaTrackId.Value()))) {
3106
0
      return false;
3107
0
    }
3108
0
    mIsAnyMemberPresent = true;
3109
0
  }
3110
0
3111
0
  if (!isNull) {
3112
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->mediaType_id, temp.ptr())) {
3113
0
      return false;
3114
0
    }
3115
0
  }
3116
0
  if (!isNull && !temp->isUndefined()) {
3117
0
    mMediaType.Construct();
3118
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mMediaType.Value()))) {
3119
0
      return false;
3120
0
    }
3121
0
    mIsAnyMemberPresent = true;
3122
0
  }
3123
0
3124
0
  if (!isNull) {
3125
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->nackCount_id, temp.ptr())) {
3126
0
      return false;
3127
0
    }
3128
0
  }
3129
0
  if (!isNull && !temp->isUndefined()) {
3130
0
    mNackCount.Construct();
3131
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mNackCount.Value()))) {
3132
0
      return false;
3133
0
    }
3134
0
    mIsAnyMemberPresent = true;
3135
0
  }
3136
0
3137
0
  if (!isNull) {
3138
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->pliCount_id, temp.ptr())) {
3139
0
      return false;
3140
0
    }
3141
0
  }
3142
0
  if (!isNull && !temp->isUndefined()) {
3143
0
    mPliCount.Construct();
3144
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mPliCount.Value()))) {
3145
0
      return false;
3146
0
    }
3147
0
    mIsAnyMemberPresent = true;
3148
0
  }
3149
0
3150
0
  if (!isNull) {
3151
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->remoteId_id, temp.ptr())) {
3152
0
      return false;
3153
0
    }
3154
0
  }
3155
0
  if (!isNull && !temp->isUndefined()) {
3156
0
    mRemoteId.Construct();
3157
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mRemoteId.Value()))) {
3158
0
      return false;
3159
0
    }
3160
0
    mIsAnyMemberPresent = true;
3161
0
  }
3162
0
3163
0
  if (!isNull) {
3164
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->ssrc_id, temp.ptr())) {
3165
0
      return false;
3166
0
    }
3167
0
  }
3168
0
  if (!isNull && !temp->isUndefined()) {
3169
0
    mSsrc.Construct();
3170
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mSsrc.Value()))) {
3171
0
      return false;
3172
0
    }
3173
0
    mIsAnyMemberPresent = true;
3174
0
  }
3175
0
3176
0
  if (!isNull) {
3177
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->transportId_id, temp.ptr())) {
3178
0
      return false;
3179
0
    }
3180
0
  }
3181
0
  if (!isNull && !temp->isUndefined()) {
3182
0
    mTransportId.Construct();
3183
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mTransportId.Value()))) {
3184
0
      return false;
3185
0
    }
3186
0
    mIsAnyMemberPresent = true;
3187
0
  }
3188
0
  return true;
3189
0
}
3190
3191
bool
3192
RTCRtpStreamStats::Init(const nsAString& aJSON)
3193
0
{
3194
0
  AutoJSAPI jsapi;
3195
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
3196
0
  if (!cleanGlobal) {
3197
0
    return false;
3198
0
  }
3199
0
  if (!jsapi.Init(cleanGlobal)) {
3200
0
    return false;
3201
0
  }
3202
0
  JSContext* cx = jsapi.cx();
3203
0
  JS::Rooted<JS::Value> json(cx);
3204
0
  bool ok = ParseJSON(cx, aJSON, &json);
3205
0
  NS_ENSURE_TRUE(ok, false);
3206
0
  return Init(cx, json);
3207
0
}
3208
3209
bool
3210
RTCRtpStreamStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
3211
0
{
3212
0
  RTCRtpStreamStatsAtoms* atomsCache = GetAtomCache<RTCRtpStreamStatsAtoms>(cx);
3213
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
3214
0
    return false;
3215
0
  }
3216
0
3217
0
  // Per spec, we define the parent's members first
3218
0
  if (!RTCStats::ToObjectInternal(cx, rval)) {
3219
0
    return false;
3220
0
  }
3221
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
3222
0
3223
0
  if (mBitrateMean.WasPassed()) {
3224
0
    do {
3225
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3226
0
      JS::Rooted<JS::Value> temp(cx);
3227
0
      double const & currentValue = mBitrateMean.InternalValue();
3228
0
      temp.set(JS_NumberValue(double(currentValue)));
3229
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->bitrateMean_id, temp, JSPROP_ENUMERATE)) {
3230
0
        return false;
3231
0
      }
3232
0
      break;
3233
0
    } while(false);
3234
0
  }
3235
0
3236
0
  if (mBitrateStdDev.WasPassed()) {
3237
0
    do {
3238
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3239
0
      JS::Rooted<JS::Value> temp(cx);
3240
0
      double const & currentValue = mBitrateStdDev.InternalValue();
3241
0
      temp.set(JS_NumberValue(double(currentValue)));
3242
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->bitrateStdDev_id, temp, JSPROP_ENUMERATE)) {
3243
0
        return false;
3244
0
      }
3245
0
      break;
3246
0
    } while(false);
3247
0
  }
3248
0
3249
0
  if (mCodecId.WasPassed()) {
3250
0
    do {
3251
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3252
0
      JS::Rooted<JS::Value> temp(cx);
3253
0
      nsString const & currentValue = mCodecId.InternalValue();
3254
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
3255
0
        return false;
3256
0
      }
3257
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->codecId_id, temp, JSPROP_ENUMERATE)) {
3258
0
        return false;
3259
0
      }
3260
0
      break;
3261
0
    } while(false);
3262
0
  }
3263
0
3264
0
  if (mFirCount.WasPassed()) {
3265
0
    do {
3266
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3267
0
      JS::Rooted<JS::Value> temp(cx);
3268
0
      uint32_t const & currentValue = mFirCount.InternalValue();
3269
0
      temp.setNumber(currentValue);
3270
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->firCount_id, temp, JSPROP_ENUMERATE)) {
3271
0
        return false;
3272
0
      }
3273
0
      break;
3274
0
    } while(false);
3275
0
  }
3276
0
3277
0
  if (mFramerateMean.WasPassed()) {
3278
0
    do {
3279
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3280
0
      JS::Rooted<JS::Value> temp(cx);
3281
0
      double const & currentValue = mFramerateMean.InternalValue();
3282
0
      temp.set(JS_NumberValue(double(currentValue)));
3283
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->framerateMean_id, temp, JSPROP_ENUMERATE)) {
3284
0
        return false;
3285
0
      }
3286
0
      break;
3287
0
    } while(false);
3288
0
  }
3289
0
3290
0
  if (mFramerateStdDev.WasPassed()) {
3291
0
    do {
3292
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3293
0
      JS::Rooted<JS::Value> temp(cx);
3294
0
      double const & currentValue = mFramerateStdDev.InternalValue();
3295
0
      temp.set(JS_NumberValue(double(currentValue)));
3296
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->framerateStdDev_id, temp, JSPROP_ENUMERATE)) {
3297
0
        return false;
3298
0
      }
3299
0
      break;
3300
0
    } while(false);
3301
0
  }
3302
0
3303
0
  do {
3304
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3305
0
    JS::Rooted<JS::Value> temp(cx);
3306
0
    bool const & currentValue = mIsRemote;
3307
0
    temp.setBoolean(currentValue);
3308
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->isRemote_id, temp, JSPROP_ENUMERATE)) {
3309
0
      return false;
3310
0
    }
3311
0
    break;
3312
0
  } while(false);
3313
0
3314
0
  if (mKind.WasPassed()) {
3315
0
    do {
3316
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3317
0
      JS::Rooted<JS::Value> temp(cx);
3318
0
      nsString const & currentValue = mKind.InternalValue();
3319
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
3320
0
        return false;
3321
0
      }
3322
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->kind_id, temp, JSPROP_ENUMERATE)) {
3323
0
        return false;
3324
0
      }
3325
0
      break;
3326
0
    } while(false);
3327
0
  }
3328
0
3329
0
  if (mMediaTrackId.WasPassed()) {
3330
0
    do {
3331
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3332
0
      JS::Rooted<JS::Value> temp(cx);
3333
0
      nsString const & currentValue = mMediaTrackId.InternalValue();
3334
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
3335
0
        return false;
3336
0
      }
3337
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->mediaTrackId_id, temp, JSPROP_ENUMERATE)) {
3338
0
        return false;
3339
0
      }
3340
0
      break;
3341
0
    } while(false);
3342
0
  }
3343
0
3344
0
  if (mMediaType.WasPassed()) {
3345
0
    do {
3346
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3347
0
      JS::Rooted<JS::Value> temp(cx);
3348
0
      nsString const & currentValue = mMediaType.InternalValue();
3349
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
3350
0
        return false;
3351
0
      }
3352
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->mediaType_id, temp, JSPROP_ENUMERATE)) {
3353
0
        return false;
3354
0
      }
3355
0
      break;
3356
0
    } while(false);
3357
0
  }
3358
0
3359
0
  if (mNackCount.WasPassed()) {
3360
0
    do {
3361
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3362
0
      JS::Rooted<JS::Value> temp(cx);
3363
0
      uint32_t const & currentValue = mNackCount.InternalValue();
3364
0
      temp.setNumber(currentValue);
3365
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->nackCount_id, temp, JSPROP_ENUMERATE)) {
3366
0
        return false;
3367
0
      }
3368
0
      break;
3369
0
    } while(false);
3370
0
  }
3371
0
3372
0
  if (mPliCount.WasPassed()) {
3373
0
    do {
3374
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3375
0
      JS::Rooted<JS::Value> temp(cx);
3376
0
      uint32_t const & currentValue = mPliCount.InternalValue();
3377
0
      temp.setNumber(currentValue);
3378
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->pliCount_id, temp, JSPROP_ENUMERATE)) {
3379
0
        return false;
3380
0
      }
3381
0
      break;
3382
0
    } while(false);
3383
0
  }
3384
0
3385
0
  if (mRemoteId.WasPassed()) {
3386
0
    do {
3387
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3388
0
      JS::Rooted<JS::Value> temp(cx);
3389
0
      nsString const & currentValue = mRemoteId.InternalValue();
3390
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
3391
0
        return false;
3392
0
      }
3393
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->remoteId_id, temp, JSPROP_ENUMERATE)) {
3394
0
        return false;
3395
0
      }
3396
0
      break;
3397
0
    } while(false);
3398
0
  }
3399
0
3400
0
  if (mSsrc.WasPassed()) {
3401
0
    do {
3402
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3403
0
      JS::Rooted<JS::Value> temp(cx);
3404
0
      uint32_t const & currentValue = mSsrc.InternalValue();
3405
0
      temp.setNumber(currentValue);
3406
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->ssrc_id, temp, JSPROP_ENUMERATE)) {
3407
0
        return false;
3408
0
      }
3409
0
      break;
3410
0
    } while(false);
3411
0
  }
3412
0
3413
0
  if (mTransportId.WasPassed()) {
3414
0
    do {
3415
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3416
0
      JS::Rooted<JS::Value> temp(cx);
3417
0
      nsString const & currentValue = mTransportId.InternalValue();
3418
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
3419
0
        return false;
3420
0
      }
3421
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->transportId_id, temp, JSPROP_ENUMERATE)) {
3422
0
        return false;
3423
0
      }
3424
0
      break;
3425
0
    } while(false);
3426
0
  }
3427
0
3428
0
  return true;
3429
0
}
3430
3431
bool
3432
RTCRtpStreamStats::ToJSON(nsAString& aJSON) const
3433
0
{
3434
0
  AutoJSAPI jsapi;
3435
0
  jsapi.Init();
3436
0
  JSContext *cx = jsapi.cx();
3437
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
3438
0
  // because we'll only be creating objects, in ways that have no
3439
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
3440
0
  // which likewise guarantees no side-effects for the sorts of
3441
0
  // things we will pass it.
3442
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
3443
0
  JS::Rooted<JS::Value> val(cx);
3444
0
  if (!ToObjectInternal(cx, &val)) {
3445
0
    return false;
3446
0
  }
3447
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
3448
0
  return StringifyToJSON(cx, obj, aJSON);
3449
0
}
3450
3451
void
3452
RTCRtpStreamStats::TraceDictionary(JSTracer* trc)
3453
0
{
3454
0
  RTCStats::TraceDictionary(trc);
3455
0
}
3456
3457
RTCRtpStreamStats&
3458
RTCRtpStreamStats::operator=(const RTCRtpStreamStats& aOther)
3459
0
{
3460
0
  RTCStats::operator=(aOther);
3461
0
  mBitrateMean.Reset();
3462
0
  if (aOther.mBitrateMean.WasPassed()) {
3463
0
    mBitrateMean.Construct(aOther.mBitrateMean.Value());
3464
0
  }
3465
0
  mBitrateStdDev.Reset();
3466
0
  if (aOther.mBitrateStdDev.WasPassed()) {
3467
0
    mBitrateStdDev.Construct(aOther.mBitrateStdDev.Value());
3468
0
  }
3469
0
  mCodecId.Reset();
3470
0
  if (aOther.mCodecId.WasPassed()) {
3471
0
    mCodecId.Construct(aOther.mCodecId.Value());
3472
0
  }
3473
0
  mFirCount.Reset();
3474
0
  if (aOther.mFirCount.WasPassed()) {
3475
0
    mFirCount.Construct(aOther.mFirCount.Value());
3476
0
  }
3477
0
  mFramerateMean.Reset();
3478
0
  if (aOther.mFramerateMean.WasPassed()) {
3479
0
    mFramerateMean.Construct(aOther.mFramerateMean.Value());
3480
0
  }
3481
0
  mFramerateStdDev.Reset();
3482
0
  if (aOther.mFramerateStdDev.WasPassed()) {
3483
0
    mFramerateStdDev.Construct(aOther.mFramerateStdDev.Value());
3484
0
  }
3485
0
  mIsRemote = aOther.mIsRemote;
3486
0
  mKind.Reset();
3487
0
  if (aOther.mKind.WasPassed()) {
3488
0
    mKind.Construct(aOther.mKind.Value());
3489
0
  }
3490
0
  mMediaTrackId.Reset();
3491
0
  if (aOther.mMediaTrackId.WasPassed()) {
3492
0
    mMediaTrackId.Construct(aOther.mMediaTrackId.Value());
3493
0
  }
3494
0
  mMediaType.Reset();
3495
0
  if (aOther.mMediaType.WasPassed()) {
3496
0
    mMediaType.Construct(aOther.mMediaType.Value());
3497
0
  }
3498
0
  mNackCount.Reset();
3499
0
  if (aOther.mNackCount.WasPassed()) {
3500
0
    mNackCount.Construct(aOther.mNackCount.Value());
3501
0
  }
3502
0
  mPliCount.Reset();
3503
0
  if (aOther.mPliCount.WasPassed()) {
3504
0
    mPliCount.Construct(aOther.mPliCount.Value());
3505
0
  }
3506
0
  mRemoteId.Reset();
3507
0
  if (aOther.mRemoteId.WasPassed()) {
3508
0
    mRemoteId.Construct(aOther.mRemoteId.Value());
3509
0
  }
3510
0
  mSsrc.Reset();
3511
0
  if (aOther.mSsrc.WasPassed()) {
3512
0
    mSsrc.Construct(aOther.mSsrc.Value());
3513
0
  }
3514
0
  mTransportId.Reset();
3515
0
  if (aOther.mTransportId.WasPassed()) {
3516
0
    mTransportId.Construct(aOther.mTransportId.Value());
3517
0
  }
3518
0
  return *this;
3519
0
}
3520
3521
namespace binding_detail {
3522
} // namespace binding_detail
3523
3524
3525
3526
RTCTransportStats::RTCTransportStats()
3527
  : RTCStats(FastDictionaryInitializer())
3528
0
{
3529
0
  // Safe to pass a null context if we pass a null value
3530
0
  Init(nullptr, JS::NullHandleValue);
3531
0
}
3532
3533
3534
3535
bool
3536
RTCTransportStats::InitIds(JSContext* cx, RTCTransportStatsAtoms* atomsCache)
3537
0
{
3538
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
3539
0
3540
0
  // Initialize these in reverse order so that any failure leaves the first one
3541
0
  // uninitialized.
3542
0
  if (!atomsCache->bytesSent_id.init(cx, "bytesSent") ||
3543
0
      !atomsCache->bytesReceived_id.init(cx, "bytesReceived")) {
3544
0
    return false;
3545
0
  }
3546
0
  return true;
3547
0
}
3548
3549
bool
3550
RTCTransportStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
3551
0
{
3552
0
  // Passing a null JSContext is OK only if we're initing from null,
3553
0
  // Since in that case we will not have to do any property gets
3554
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
3555
0
  // checkers by static analysis tools
3556
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
3557
0
  RTCTransportStatsAtoms* atomsCache = nullptr;
3558
0
  if (cx) {
3559
0
    atomsCache = GetAtomCache<RTCTransportStatsAtoms>(cx);
3560
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
3561
0
      return false;
3562
0
    }
3563
0
  }
3564
0
3565
0
  // Per spec, we init the parent's members first
3566
0
  if (!RTCStats::Init(cx, val)) {
3567
0
    return false;
3568
0
  }
3569
0
3570
0
  bool isNull = val.isNullOrUndefined();
3571
0
  // We only need these if !isNull, in which case we have |cx|.
3572
0
  Maybe<JS::Rooted<JSObject *> > object;
3573
0
  Maybe<JS::Rooted<JS::Value> > temp;
3574
0
  if (!isNull) {
3575
0
    MOZ_ASSERT(cx);
3576
0
    object.emplace(cx, &val.toObject());
3577
0
    temp.emplace(cx);
3578
0
  }
3579
0
  if (!isNull) {
3580
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->bytesReceived_id, temp.ptr())) {
3581
0
      return false;
3582
0
    }
3583
0
  }
3584
0
  if (!isNull && !temp->isUndefined()) {
3585
0
    mBytesReceived.Construct();
3586
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mBytesReceived.Value()))) {
3587
0
      return false;
3588
0
    }
3589
0
    mIsAnyMemberPresent = true;
3590
0
  }
3591
0
3592
0
  if (!isNull) {
3593
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->bytesSent_id, temp.ptr())) {
3594
0
      return false;
3595
0
    }
3596
0
  }
3597
0
  if (!isNull && !temp->isUndefined()) {
3598
0
    mBytesSent.Construct();
3599
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mBytesSent.Value()))) {
3600
0
      return false;
3601
0
    }
3602
0
    mIsAnyMemberPresent = true;
3603
0
  }
3604
0
  return true;
3605
0
}
3606
3607
bool
3608
RTCTransportStats::Init(const nsAString& aJSON)
3609
0
{
3610
0
  AutoJSAPI jsapi;
3611
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
3612
0
  if (!cleanGlobal) {
3613
0
    return false;
3614
0
  }
3615
0
  if (!jsapi.Init(cleanGlobal)) {
3616
0
    return false;
3617
0
  }
3618
0
  JSContext* cx = jsapi.cx();
3619
0
  JS::Rooted<JS::Value> json(cx);
3620
0
  bool ok = ParseJSON(cx, aJSON, &json);
3621
0
  NS_ENSURE_TRUE(ok, false);
3622
0
  return Init(cx, json);
3623
0
}
3624
3625
bool
3626
RTCTransportStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
3627
0
{
3628
0
  RTCTransportStatsAtoms* atomsCache = GetAtomCache<RTCTransportStatsAtoms>(cx);
3629
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
3630
0
    return false;
3631
0
  }
3632
0
3633
0
  // Per spec, we define the parent's members first
3634
0
  if (!RTCStats::ToObjectInternal(cx, rval)) {
3635
0
    return false;
3636
0
  }
3637
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
3638
0
3639
0
  if (mBytesReceived.WasPassed()) {
3640
0
    do {
3641
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3642
0
      JS::Rooted<JS::Value> temp(cx);
3643
0
      uint32_t const & currentValue = mBytesReceived.InternalValue();
3644
0
      temp.setNumber(currentValue);
3645
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->bytesReceived_id, temp, JSPROP_ENUMERATE)) {
3646
0
        return false;
3647
0
      }
3648
0
      break;
3649
0
    } while(false);
3650
0
  }
3651
0
3652
0
  if (mBytesSent.WasPassed()) {
3653
0
    do {
3654
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3655
0
      JS::Rooted<JS::Value> temp(cx);
3656
0
      uint32_t const & currentValue = mBytesSent.InternalValue();
3657
0
      temp.setNumber(currentValue);
3658
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->bytesSent_id, temp, JSPROP_ENUMERATE)) {
3659
0
        return false;
3660
0
      }
3661
0
      break;
3662
0
    } while(false);
3663
0
  }
3664
0
3665
0
  return true;
3666
0
}
3667
3668
bool
3669
RTCTransportStats::ToJSON(nsAString& aJSON) const
3670
0
{
3671
0
  AutoJSAPI jsapi;
3672
0
  jsapi.Init();
3673
0
  JSContext *cx = jsapi.cx();
3674
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
3675
0
  // because we'll only be creating objects, in ways that have no
3676
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
3677
0
  // which likewise guarantees no side-effects for the sorts of
3678
0
  // things we will pass it.
3679
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
3680
0
  JS::Rooted<JS::Value> val(cx);
3681
0
  if (!ToObjectInternal(cx, &val)) {
3682
0
    return false;
3683
0
  }
3684
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
3685
0
  return StringifyToJSON(cx, obj, aJSON);
3686
0
}
3687
3688
void
3689
RTCTransportStats::TraceDictionary(JSTracer* trc)
3690
0
{
3691
0
  RTCStats::TraceDictionary(trc);
3692
0
}
3693
3694
RTCTransportStats&
3695
RTCTransportStats::operator=(const RTCTransportStats& aOther)
3696
0
{
3697
0
  RTCStats::operator=(aOther);
3698
0
  mBytesReceived.Reset();
3699
0
  if (aOther.mBytesReceived.WasPassed()) {
3700
0
    mBytesReceived.Construct(aOther.mBytesReceived.Value());
3701
0
  }
3702
0
  mBytesSent.Reset();
3703
0
  if (aOther.mBytesSent.WasPassed()) {
3704
0
    mBytesSent.Construct(aOther.mBytesSent.Value());
3705
0
  }
3706
0
  return *this;
3707
0
}
3708
3709
namespace binding_detail {
3710
} // namespace binding_detail
3711
3712
3713
3714
RTCInboundRTPStreamStats::RTCInboundRTPStreamStats()
3715
  : RTCRtpStreamStats(FastDictionaryInitializer())
3716
0
{
3717
0
  // Safe to pass a null context if we pass a null value
3718
0
  Init(nullptr, JS::NullHandleValue);
3719
0
}
3720
3721
3722
3723
bool
3724
RTCInboundRTPStreamStats::InitIds(JSContext* cx, RTCInboundRTPStreamStatsAtoms* atomsCache)
3725
0
{
3726
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
3727
0
3728
0
  // Initialize these in reverse order so that any failure leaves the first one
3729
0
  // uninitialized.
3730
0
  if (!atomsCache->roundTripTime_id.init(cx, "roundTripTime") ||
3731
0
      !atomsCache->packetsReceived_id.init(cx, "packetsReceived") ||
3732
0
      !atomsCache->packetsLost_id.init(cx, "packetsLost") ||
3733
0
      !atomsCache->mozJitterBufferDelay_id.init(cx, "mozJitterBufferDelay") ||
3734
0
      !atomsCache->mozAvSyncDelay_id.init(cx, "mozAvSyncDelay") ||
3735
0
      !atomsCache->jitter_id.init(cx, "jitter") ||
3736
0
      !atomsCache->framesDecoded_id.init(cx, "framesDecoded") ||
3737
0
      !atomsCache->discardedPackets_id.init(cx, "discardedPackets") ||
3738
0
      !atomsCache->bytesReceived_id.init(cx, "bytesReceived")) {
3739
0
    return false;
3740
0
  }
3741
0
  return true;
3742
0
}
3743
3744
bool
3745
RTCInboundRTPStreamStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
3746
0
{
3747
0
  // Passing a null JSContext is OK only if we're initing from null,
3748
0
  // Since in that case we will not have to do any property gets
3749
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
3750
0
  // checkers by static analysis tools
3751
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
3752
0
  RTCInboundRTPStreamStatsAtoms* atomsCache = nullptr;
3753
0
  if (cx) {
3754
0
    atomsCache = GetAtomCache<RTCInboundRTPStreamStatsAtoms>(cx);
3755
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
3756
0
      return false;
3757
0
    }
3758
0
  }
3759
0
3760
0
  // Per spec, we init the parent's members first
3761
0
  if (!RTCRtpStreamStats::Init(cx, val)) {
3762
0
    return false;
3763
0
  }
3764
0
3765
0
  bool isNull = val.isNullOrUndefined();
3766
0
  // We only need these if !isNull, in which case we have |cx|.
3767
0
  Maybe<JS::Rooted<JSObject *> > object;
3768
0
  Maybe<JS::Rooted<JS::Value> > temp;
3769
0
  if (!isNull) {
3770
0
    MOZ_ASSERT(cx);
3771
0
    object.emplace(cx, &val.toObject());
3772
0
    temp.emplace(cx);
3773
0
  }
3774
0
  if (!isNull) {
3775
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->bytesReceived_id, temp.ptr())) {
3776
0
      return false;
3777
0
    }
3778
0
  }
3779
0
  if (!isNull && !temp->isUndefined()) {
3780
0
    mBytesReceived.Construct();
3781
0
    if (!ValueToPrimitive<uint64_t, eDefault>(cx, temp.ref(), &(mBytesReceived.Value()))) {
3782
0
      return false;
3783
0
    }
3784
0
    mIsAnyMemberPresent = true;
3785
0
  }
3786
0
3787
0
  if (!isNull) {
3788
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->discardedPackets_id, temp.ptr())) {
3789
0
      return false;
3790
0
    }
3791
0
  }
3792
0
  if (!isNull && !temp->isUndefined()) {
3793
0
    mDiscardedPackets.Construct();
3794
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mDiscardedPackets.Value()))) {
3795
0
      return false;
3796
0
    }
3797
0
    mIsAnyMemberPresent = true;
3798
0
  }
3799
0
3800
0
  if (!isNull) {
3801
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->framesDecoded_id, temp.ptr())) {
3802
0
      return false;
3803
0
    }
3804
0
  }
3805
0
  if (!isNull && !temp->isUndefined()) {
3806
0
    mFramesDecoded.Construct();
3807
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mFramesDecoded.Value()))) {
3808
0
      return false;
3809
0
    }
3810
0
    mIsAnyMemberPresent = true;
3811
0
  }
3812
0
3813
0
  if (!isNull) {
3814
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->jitter_id, temp.ptr())) {
3815
0
      return false;
3816
0
    }
3817
0
  }
3818
0
  if (!isNull && !temp->isUndefined()) {
3819
0
    mJitter.Construct();
3820
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mJitter.Value()))) {
3821
0
      return false;
3822
0
    } else if (!mozilla::IsFinite((mJitter.Value()))) {
3823
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'jitter' member of RTCInboundRTPStreamStats");
3824
0
      return false;
3825
0
    }
3826
0
    mIsAnyMemberPresent = true;
3827
0
  }
3828
0
3829
0
  if (!isNull) {
3830
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->mozAvSyncDelay_id, temp.ptr())) {
3831
0
      return false;
3832
0
    }
3833
0
  }
3834
0
  if (!isNull && !temp->isUndefined()) {
3835
0
    mMozAvSyncDelay.Construct();
3836
0
    if (!ValueToPrimitive<int32_t, eDefault>(cx, temp.ref(), &(mMozAvSyncDelay.Value()))) {
3837
0
      return false;
3838
0
    }
3839
0
    mIsAnyMemberPresent = true;
3840
0
  }
3841
0
3842
0
  if (!isNull) {
3843
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->mozJitterBufferDelay_id, temp.ptr())) {
3844
0
      return false;
3845
0
    }
3846
0
  }
3847
0
  if (!isNull && !temp->isUndefined()) {
3848
0
    mMozJitterBufferDelay.Construct();
3849
0
    if (!ValueToPrimitive<int32_t, eDefault>(cx, temp.ref(), &(mMozJitterBufferDelay.Value()))) {
3850
0
      return false;
3851
0
    }
3852
0
    mIsAnyMemberPresent = true;
3853
0
  }
3854
0
3855
0
  if (!isNull) {
3856
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->packetsLost_id, temp.ptr())) {
3857
0
      return false;
3858
0
    }
3859
0
  }
3860
0
  if (!isNull && !temp->isUndefined()) {
3861
0
    mPacketsLost.Construct();
3862
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mPacketsLost.Value()))) {
3863
0
      return false;
3864
0
    }
3865
0
    mIsAnyMemberPresent = true;
3866
0
  }
3867
0
3868
0
  if (!isNull) {
3869
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->packetsReceived_id, temp.ptr())) {
3870
0
      return false;
3871
0
    }
3872
0
  }
3873
0
  if (!isNull && !temp->isUndefined()) {
3874
0
    mPacketsReceived.Construct();
3875
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mPacketsReceived.Value()))) {
3876
0
      return false;
3877
0
    }
3878
0
    mIsAnyMemberPresent = true;
3879
0
  }
3880
0
3881
0
  if (!isNull) {
3882
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->roundTripTime_id, temp.ptr())) {
3883
0
      return false;
3884
0
    }
3885
0
  }
3886
0
  if (!isNull && !temp->isUndefined()) {
3887
0
    mRoundTripTime.Construct();
3888
0
    if (!ValueToPrimitive<int32_t, eDefault>(cx, temp.ref(), &(mRoundTripTime.Value()))) {
3889
0
      return false;
3890
0
    }
3891
0
    mIsAnyMemberPresent = true;
3892
0
  }
3893
0
  return true;
3894
0
}
3895
3896
bool
3897
RTCInboundRTPStreamStats::Init(const nsAString& aJSON)
3898
0
{
3899
0
  AutoJSAPI jsapi;
3900
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
3901
0
  if (!cleanGlobal) {
3902
0
    return false;
3903
0
  }
3904
0
  if (!jsapi.Init(cleanGlobal)) {
3905
0
    return false;
3906
0
  }
3907
0
  JSContext* cx = jsapi.cx();
3908
0
  JS::Rooted<JS::Value> json(cx);
3909
0
  bool ok = ParseJSON(cx, aJSON, &json);
3910
0
  NS_ENSURE_TRUE(ok, false);
3911
0
  return Init(cx, json);
3912
0
}
3913
3914
bool
3915
RTCInboundRTPStreamStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
3916
0
{
3917
0
  RTCInboundRTPStreamStatsAtoms* atomsCache = GetAtomCache<RTCInboundRTPStreamStatsAtoms>(cx);
3918
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
3919
0
    return false;
3920
0
  }
3921
0
3922
0
  // Per spec, we define the parent's members first
3923
0
  if (!RTCRtpStreamStats::ToObjectInternal(cx, rval)) {
3924
0
    return false;
3925
0
  }
3926
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
3927
0
3928
0
  if (mBytesReceived.WasPassed()) {
3929
0
    do {
3930
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3931
0
      JS::Rooted<JS::Value> temp(cx);
3932
0
      uint64_t const & currentValue = mBytesReceived.InternalValue();
3933
0
      temp.set(JS_NumberValue(double(currentValue)));
3934
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->bytesReceived_id, temp, JSPROP_ENUMERATE)) {
3935
0
        return false;
3936
0
      }
3937
0
      break;
3938
0
    } while(false);
3939
0
  }
3940
0
3941
0
  if (mDiscardedPackets.WasPassed()) {
3942
0
    do {
3943
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3944
0
      JS::Rooted<JS::Value> temp(cx);
3945
0
      uint32_t const & currentValue = mDiscardedPackets.InternalValue();
3946
0
      temp.setNumber(currentValue);
3947
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->discardedPackets_id, temp, JSPROP_ENUMERATE)) {
3948
0
        return false;
3949
0
      }
3950
0
      break;
3951
0
    } while(false);
3952
0
  }
3953
0
3954
0
  if (mFramesDecoded.WasPassed()) {
3955
0
    do {
3956
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3957
0
      JS::Rooted<JS::Value> temp(cx);
3958
0
      uint32_t const & currentValue = mFramesDecoded.InternalValue();
3959
0
      temp.setNumber(currentValue);
3960
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->framesDecoded_id, temp, JSPROP_ENUMERATE)) {
3961
0
        return false;
3962
0
      }
3963
0
      break;
3964
0
    } while(false);
3965
0
  }
3966
0
3967
0
  if (mJitter.WasPassed()) {
3968
0
    do {
3969
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3970
0
      JS::Rooted<JS::Value> temp(cx);
3971
0
      double const & currentValue = mJitter.InternalValue();
3972
0
      temp.set(JS_NumberValue(double(currentValue)));
3973
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->jitter_id, temp, JSPROP_ENUMERATE)) {
3974
0
        return false;
3975
0
      }
3976
0
      break;
3977
0
    } while(false);
3978
0
  }
3979
0
3980
0
  if (mMozAvSyncDelay.WasPassed()) {
3981
0
    do {
3982
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3983
0
      JS::Rooted<JS::Value> temp(cx);
3984
0
      int32_t const & currentValue = mMozAvSyncDelay.InternalValue();
3985
0
      temp.setInt32(int32_t(currentValue));
3986
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->mozAvSyncDelay_id, temp, JSPROP_ENUMERATE)) {
3987
0
        return false;
3988
0
      }
3989
0
      break;
3990
0
    } while(false);
3991
0
  }
3992
0
3993
0
  if (mMozJitterBufferDelay.WasPassed()) {
3994
0
    do {
3995
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3996
0
      JS::Rooted<JS::Value> temp(cx);
3997
0
      int32_t const & currentValue = mMozJitterBufferDelay.InternalValue();
3998
0
      temp.setInt32(int32_t(currentValue));
3999
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->mozJitterBufferDelay_id, temp, JSPROP_ENUMERATE)) {
4000
0
        return false;
4001
0
      }
4002
0
      break;
4003
0
    } while(false);
4004
0
  }
4005
0
4006
0
  if (mPacketsLost.WasPassed()) {
4007
0
    do {
4008
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
4009
0
      JS::Rooted<JS::Value> temp(cx);
4010
0
      uint32_t const & currentValue = mPacketsLost.InternalValue();
4011
0
      temp.setNumber(currentValue);
4012
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->packetsLost_id, temp, JSPROP_ENUMERATE)) {
4013
0
        return false;
4014
0
      }
4015
0
      break;
4016
0
    } while(false);
4017
0
  }
4018
0
4019
0
  if (mPacketsReceived.WasPassed()) {
4020
0
    do {
4021
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
4022
0
      JS::Rooted<JS::Value> temp(cx);
4023
0
      uint32_t const & currentValue = mPacketsReceived.InternalValue();
4024
0
      temp.setNumber(currentValue);
4025
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->packetsReceived_id, temp, JSPROP_ENUMERATE)) {
4026
0
        return false;
4027
0
      }
4028
0
      break;
4029
0
    } while(false);
4030
0
  }
4031
0
4032
0
  if (mRoundTripTime.WasPassed()) {
4033
0
    do {
4034
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
4035
0
      JS::Rooted<JS::Value> temp(cx);
4036
0
      int32_t const & currentValue = mRoundTripTime.InternalValue();
4037
0
      temp.setInt32(int32_t(currentValue));
4038
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->roundTripTime_id, temp, JSPROP_ENUMERATE)) {
4039
0
        return false;
4040
0
      }
4041
0
      break;
4042
0
    } while(false);
4043
0
  }
4044
0
4045
0
  return true;
4046
0
}
4047
4048
bool
4049
RTCInboundRTPStreamStats::ToJSON(nsAString& aJSON) const
4050
0
{
4051
0
  AutoJSAPI jsapi;
4052
0
  jsapi.Init();
4053
0
  JSContext *cx = jsapi.cx();
4054
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
4055
0
  // because we'll only be creating objects, in ways that have no
4056
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
4057
0
  // which likewise guarantees no side-effects for the sorts of
4058
0
  // things we will pass it.
4059
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
4060
0
  JS::Rooted<JS::Value> val(cx);
4061
0
  if (!ToObjectInternal(cx, &val)) {
4062
0
    return false;
4063
0
  }
4064
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
4065
0
  return StringifyToJSON(cx, obj, aJSON);
4066
0
}
4067
4068
void
4069
RTCInboundRTPStreamStats::TraceDictionary(JSTracer* trc)
4070
0
{
4071
0
  RTCRtpStreamStats::TraceDictionary(trc);
4072
0
}
4073
4074
RTCInboundRTPStreamStats&
4075
RTCInboundRTPStreamStats::operator=(const RTCInboundRTPStreamStats& aOther)
4076
0
{
4077
0
  RTCRtpStreamStats::operator=(aOther);
4078
0
  mBytesReceived.Reset();
4079
0
  if (aOther.mBytesReceived.WasPassed()) {
4080
0
    mBytesReceived.Construct(aOther.mBytesReceived.Value());
4081
0
  }
4082
0
  mDiscardedPackets.Reset();
4083
0
  if (aOther.mDiscardedPackets.WasPassed()) {
4084
0
    mDiscardedPackets.Construct(aOther.mDiscardedPackets.Value());
4085
0
  }
4086
0
  mFramesDecoded.Reset();
4087
0
  if (aOther.mFramesDecoded.WasPassed()) {
4088
0
    mFramesDecoded.Construct(aOther.mFramesDecoded.Value());
4089
0
  }
4090
0
  mJitter.Reset();
4091
0
  if (aOther.mJitter.WasPassed()) {
4092
0
    mJitter.Construct(aOther.mJitter.Value());
4093
0
  }
4094
0
  mMozAvSyncDelay.Reset();
4095
0
  if (aOther.mMozAvSyncDelay.WasPassed()) {
4096
0
    mMozAvSyncDelay.Construct(aOther.mMozAvSyncDelay.Value());
4097
0
  }
4098
0
  mMozJitterBufferDelay.Reset();
4099
0
  if (aOther.mMozJitterBufferDelay.WasPassed()) {
4100
0
    mMozJitterBufferDelay.Construct(aOther.mMozJitterBufferDelay.Value());
4101
0
  }
4102
0
  mPacketsLost.Reset();
4103
0
  if (aOther.mPacketsLost.WasPassed()) {
4104
0
    mPacketsLost.Construct(aOther.mPacketsLost.Value());
4105
0
  }
4106
0
  mPacketsReceived.Reset();
4107
0
  if (aOther.mPacketsReceived.WasPassed()) {
4108
0
    mPacketsReceived.Construct(aOther.mPacketsReceived.Value());
4109
0
  }
4110
0
  mRoundTripTime.Reset();
4111
0
  if (aOther.mRoundTripTime.WasPassed()) {
4112
0
    mRoundTripTime.Construct(aOther.mRoundTripTime.Value());
4113
0
  }
4114
0
  return *this;
4115
0
}
4116
4117
namespace binding_detail {
4118
} // namespace binding_detail
4119
4120
4121
4122
RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats()
4123
  : RTCRtpStreamStats(FastDictionaryInitializer())
4124
0
{
4125
0
  // Safe to pass a null context if we pass a null value
4126
0
  Init(nullptr, JS::NullHandleValue);
4127
0
}
4128
4129
4130
4131
bool
4132
RTCOutboundRTPStreamStats::InitIds(JSContext* cx, RTCOutboundRTPStreamStatsAtoms* atomsCache)
4133
0
{
4134
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
4135
0
4136
0
  // Initialize these in reverse order so that any failure leaves the first one
4137
0
  // uninitialized.
4138
0
  if (!atomsCache->targetBitrate_id.init(cx, "targetBitrate") ||
4139
0
      !atomsCache->packetsSent_id.init(cx, "packetsSent") ||
4140
0
      !atomsCache->framesEncoded_id.init(cx, "framesEncoded") ||
4141
0
      !atomsCache->droppedFrames_id.init(cx, "droppedFrames") ||
4142
0
      !atomsCache->bytesSent_id.init(cx, "bytesSent")) {
4143
0
    return false;
4144
0
  }
4145
0
  return true;
4146
0
}
4147
4148
bool
4149
RTCOutboundRTPStreamStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
4150
0
{
4151
0
  // Passing a null JSContext is OK only if we're initing from null,
4152
0
  // Since in that case we will not have to do any property gets
4153
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
4154
0
  // checkers by static analysis tools
4155
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
4156
0
  RTCOutboundRTPStreamStatsAtoms* atomsCache = nullptr;
4157
0
  if (cx) {
4158
0
    atomsCache = GetAtomCache<RTCOutboundRTPStreamStatsAtoms>(cx);
4159
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
4160
0
      return false;
4161
0
    }
4162
0
  }
4163
0
4164
0
  // Per spec, we init the parent's members first
4165
0
  if (!RTCRtpStreamStats::Init(cx, val)) {
4166
0
    return false;
4167
0
  }
4168
0
4169
0
  bool isNull = val.isNullOrUndefined();
4170
0
  // We only need these if !isNull, in which case we have |cx|.
4171
0
  Maybe<JS::Rooted<JSObject *> > object;
4172
0
  Maybe<JS::Rooted<JS::Value> > temp;
4173
0
  if (!isNull) {
4174
0
    MOZ_ASSERT(cx);
4175
0
    object.emplace(cx, &val.toObject());
4176
0
    temp.emplace(cx);
4177
0
  }
4178
0
  if (!isNull) {
4179
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->bytesSent_id, temp.ptr())) {
4180
0
      return false;
4181
0
    }
4182
0
  }
4183
0
  if (!isNull && !temp->isUndefined()) {
4184
0
    mBytesSent.Construct();
4185
0
    if (!ValueToPrimitive<uint64_t, eDefault>(cx, temp.ref(), &(mBytesSent.Value()))) {
4186
0
      return false;
4187
0
    }
4188
0
    mIsAnyMemberPresent = true;
4189
0
  }
4190
0
4191
0
  if (!isNull) {
4192
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->droppedFrames_id, temp.ptr())) {
4193
0
      return false;
4194
0
    }
4195
0
  }
4196
0
  if (!isNull && !temp->isUndefined()) {
4197
0
    mDroppedFrames.Construct();
4198
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mDroppedFrames.Value()))) {
4199
0
      return false;
4200
0
    }
4201
0
    mIsAnyMemberPresent = true;
4202
0
  }
4203
0
4204
0
  if (!isNull) {
4205
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->framesEncoded_id, temp.ptr())) {
4206
0
      return false;
4207
0
    }
4208
0
  }
4209
0
  if (!isNull && !temp->isUndefined()) {
4210
0
    mFramesEncoded.Construct();
4211
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mFramesEncoded.Value()))) {
4212
0
      return false;
4213
0
    }
4214
0
    mIsAnyMemberPresent = true;
4215
0
  }
4216
0
4217
0
  if (!isNull) {
4218
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->packetsSent_id, temp.ptr())) {
4219
0
      return false;
4220
0
    }
4221
0
  }
4222
0
  if (!isNull && !temp->isUndefined()) {
4223
0
    mPacketsSent.Construct();
4224
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mPacketsSent.Value()))) {
4225
0
      return false;
4226
0
    }
4227
0
    mIsAnyMemberPresent = true;
4228
0
  }
4229
0
4230
0
  if (!isNull) {
4231
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->targetBitrate_id, temp.ptr())) {
4232
0
      return false;
4233
0
    }
4234
0
  }
4235
0
  if (!isNull && !temp->isUndefined()) {
4236
0
    mTargetBitrate.Construct();
4237
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mTargetBitrate.Value()))) {
4238
0
      return false;
4239
0
    } else if (!mozilla::IsFinite((mTargetBitrate.Value()))) {
4240
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'targetBitrate' member of RTCOutboundRTPStreamStats");
4241
0
      return false;
4242
0
    }
4243
0
    mIsAnyMemberPresent = true;
4244
0
  }
4245
0
  return true;
4246
0
}
4247
4248
bool
4249
RTCOutboundRTPStreamStats::Init(const nsAString& aJSON)
4250
0
{
4251
0
  AutoJSAPI jsapi;
4252
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
4253
0
  if (!cleanGlobal) {
4254
0
    return false;
4255
0
  }
4256
0
  if (!jsapi.Init(cleanGlobal)) {
4257
0
    return false;
4258
0
  }
4259
0
  JSContext* cx = jsapi.cx();
4260
0
  JS::Rooted<JS::Value> json(cx);
4261
0
  bool ok = ParseJSON(cx, aJSON, &json);
4262
0
  NS_ENSURE_TRUE(ok, false);
4263
0
  return Init(cx, json);
4264
0
}
4265
4266
bool
4267
RTCOutboundRTPStreamStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
4268
0
{
4269
0
  RTCOutboundRTPStreamStatsAtoms* atomsCache = GetAtomCache<RTCOutboundRTPStreamStatsAtoms>(cx);
4270
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
4271
0
    return false;
4272
0
  }
4273
0
4274
0
  // Per spec, we define the parent's members first
4275
0
  if (!RTCRtpStreamStats::ToObjectInternal(cx, rval)) {
4276
0
    return false;
4277
0
  }
4278
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
4279
0
4280
0
  if (mBytesSent.WasPassed()) {
4281
0
    do {
4282
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
4283
0
      JS::Rooted<JS::Value> temp(cx);
4284
0
      uint64_t const & currentValue = mBytesSent.InternalValue();
4285
0
      temp.set(JS_NumberValue(double(currentValue)));
4286
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->bytesSent_id, temp, JSPROP_ENUMERATE)) {
4287
0
        return false;
4288
0
      }
4289
0
      break;
4290
0
    } while(false);
4291
0
  }
4292
0
4293
0
  if (mDroppedFrames.WasPassed()) {
4294
0
    do {
4295
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
4296
0
      JS::Rooted<JS::Value> temp(cx);
4297
0
      uint32_t const & currentValue = mDroppedFrames.InternalValue();
4298
0
      temp.setNumber(currentValue);
4299
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->droppedFrames_id, temp, JSPROP_ENUMERATE)) {
4300
0
        return false;
4301
0
      }
4302
0
      break;
4303
0
    } while(false);
4304
0
  }
4305
0
4306
0
  if (mFramesEncoded.WasPassed()) {
4307
0
    do {
4308
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
4309
0
      JS::Rooted<JS::Value> temp(cx);
4310
0
      uint32_t const & currentValue = mFramesEncoded.InternalValue();
4311
0
      temp.setNumber(currentValue);
4312
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->framesEncoded_id, temp, JSPROP_ENUMERATE)) {
4313
0
        return false;
4314
0
      }
4315
0
      break;
4316
0
    } while(false);
4317
0
  }
4318
0
4319
0
  if (mPacketsSent.WasPassed()) {
4320
0
    do {
4321
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
4322
0
      JS::Rooted<JS::Value> temp(cx);
4323
0
      uint32_t const & currentValue = mPacketsSent.InternalValue();
4324
0
      temp.setNumber(currentValue);
4325
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->packetsSent_id, temp, JSPROP_ENUMERATE)) {
4326
0
        return false;
4327
0
      }
4328
0
      break;
4329
0
    } while(false);
4330
0
  }
4331
0
4332
0
  if (mTargetBitrate.WasPassed()) {
4333
0
    do {
4334
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
4335
0
      JS::Rooted<JS::Value> temp(cx);
4336
0
      double const & currentValue = mTargetBitrate.InternalValue();
4337
0
      temp.set(JS_NumberValue(double(currentValue)));
4338
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->targetBitrate_id, temp, JSPROP_ENUMERATE)) {
4339
0
        return false;
4340
0
      }
4341
0
      break;
4342
0
    } while(false);
4343
0
  }
4344
0
4345
0
  return true;
4346
0
}
4347
4348
bool
4349
RTCOutboundRTPStreamStats::ToJSON(nsAString& aJSON) const
4350
0
{
4351
0
  AutoJSAPI jsapi;
4352
0
  jsapi.Init();
4353
0
  JSContext *cx = jsapi.cx();
4354
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
4355
0
  // because we'll only be creating objects, in ways that have no
4356
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
4357
0
  // which likewise guarantees no side-effects for the sorts of
4358
0
  // things we will pass it.
4359
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
4360
0
  JS::Rooted<JS::Value> val(cx);
4361
0
  if (!ToObjectInternal(cx, &val)) {
4362
0
    return false;
4363
0
  }
4364
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
4365
0
  return StringifyToJSON(cx, obj, aJSON);
4366
0
}
4367
4368
void
4369
RTCOutboundRTPStreamStats::TraceDictionary(JSTracer* trc)
4370
0
{
4371
0
  RTCRtpStreamStats::TraceDictionary(trc);
4372
0
}
4373
4374
RTCOutboundRTPStreamStats&
4375
RTCOutboundRTPStreamStats::operator=(const RTCOutboundRTPStreamStats& aOther)
4376
0
{
4377
0
  RTCRtpStreamStats::operator=(aOther);
4378
0
  mBytesSent.Reset();
4379
0
  if (aOther.mBytesSent.WasPassed()) {
4380
0
    mBytesSent.Construct(aOther.mBytesSent.Value());
4381
0
  }
4382
0
  mDroppedFrames.Reset();
4383
0
  if (aOther.mDroppedFrames.WasPassed()) {
4384
0
    mDroppedFrames.Construct(aOther.mDroppedFrames.Value());
4385
0
  }
4386
0
  mFramesEncoded.Reset();
4387
0
  if (aOther.mFramesEncoded.WasPassed()) {
4388
0
    mFramesEncoded.Construct(aOther.mFramesEncoded.Value());
4389
0
  }
4390
0
  mPacketsSent.Reset();
4391
0
  if (aOther.mPacketsSent.WasPassed()) {
4392
0
    mPacketsSent.Construct(aOther.mPacketsSent.Value());
4393
0
  }
4394
0
  mTargetBitrate.Reset();
4395
0
  if (aOther.mTargetBitrate.WasPassed()) {
4396
0
    mTargetBitrate.Construct(aOther.mTargetBitrate.Value());
4397
0
  }
4398
0
  return *this;
4399
0
}
4400
4401
namespace binding_detail {
4402
} // namespace binding_detail
4403
4404
4405
4406
RTCStatsReportInternal::RTCStatsReportInternal()
4407
0
{
4408
0
  // Safe to pass a null context if we pass a null value
4409
0
  Init(nullptr, JS::NullHandleValue);
4410
0
}
4411
4412
4413
4414
bool
4415
RTCStatsReportInternal::InitIds(JSContext* cx, RTCStatsReportInternalAtoms* atomsCache)
4416
0
{
4417
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
4418
0
4419
0
  // Initialize these in reverse order so that any failure leaves the first one
4420
0
  // uninitialized.
4421
0
  if (!atomsCache->trickledIceCandidateStats_id.init(cx, "trickledIceCandidateStats") ||
4422
0
      !atomsCache->transportStats_id.init(cx, "transportStats") ||
4423
0
      !atomsCache->timestamp_id.init(cx, "timestamp") ||
4424
0
      !atomsCache->rtpContributingSourceStats_id.init(cx, "rtpContributingSourceStats") ||
4425
0
      !atomsCache->remoteSdp_id.init(cx, "remoteSdp") ||
4426
0
      !atomsCache->rawRemoteCandidates_id.init(cx, "rawRemoteCandidates") ||
4427
0
      !atomsCache->rawLocalCandidates_id.init(cx, "rawLocalCandidates") ||
4428
0
      !atomsCache->pcid_id.init(cx, "pcid") ||
4429
0
      !atomsCache->outboundRTPStreamStats_id.init(cx, "outboundRTPStreamStats") ||
4430
0
      !atomsCache->offerer_id.init(cx, "offerer") ||
4431
0
      !atomsCache->mediaStreamTrackStats_id.init(cx, "mediaStreamTrackStats") ||
4432
0
      !atomsCache->mediaStreamStats_id.init(cx, "mediaStreamStats") ||
4433
0
      !atomsCache->localSdp_id.init(cx, "localSdp") ||
4434
0
      !atomsCache->inboundRTPStreamStats_id.init(cx, "inboundRTPStreamStats") ||
4435
0
      !atomsCache->iceRollbacks_id.init(cx, "iceRollbacks") ||
4436
0
      !atomsCache->iceRestarts_id.init(cx, "iceRestarts") ||
4437
0
      !atomsCache->iceComponentStats_id.init(cx, "iceComponentStats") ||
4438
0
      !atomsCache->iceCandidateStats_id.init(cx, "iceCandidateStats") ||
4439
0
      !atomsCache->iceCandidatePairStats_id.init(cx, "iceCandidatePairStats") ||
4440
0
      !atomsCache->codecStats_id.init(cx, "codecStats") ||
4441
0
      !atomsCache->closed_id.init(cx, "closed")) {
4442
0
    return false;
4443
0
  }
4444
0
  return true;
4445
0
}
4446
4447
bool
4448
RTCStatsReportInternal::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
4449
0
{
4450
0
  // Passing a null JSContext is OK only if we're initing from null,
4451
0
  // Since in that case we will not have to do any property gets
4452
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
4453
0
  // checkers by static analysis tools
4454
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
4455
0
  RTCStatsReportInternalAtoms* atomsCache = nullptr;
4456
0
  if (cx) {
4457
0
    atomsCache = GetAtomCache<RTCStatsReportInternalAtoms>(cx);
4458
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
4459
0
      return false;
4460
0
    }
4461
0
  }
4462
0
4463
0
  if (!IsConvertibleToDictionary(val)) {
4464
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
4465
0
  }
4466
0
4467
0
  bool isNull = val.isNullOrUndefined();
4468
0
  // We only need these if !isNull, in which case we have |cx|.
4469
0
  Maybe<JS::Rooted<JSObject *> > object;
4470
0
  Maybe<JS::Rooted<JS::Value> > temp;
4471
0
  if (!isNull) {
4472
0
    MOZ_ASSERT(cx);
4473
0
    object.emplace(cx, &val.toObject());
4474
0
    temp.emplace(cx);
4475
0
  }
4476
0
  if (!isNull) {
4477
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->closed_id, temp.ptr())) {
4478
0
      return false;
4479
0
    }
4480
0
  }
4481
0
  if (!isNull && !temp->isUndefined()) {
4482
0
    mClosed.Construct();
4483
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mClosed.Value()))) {
4484
0
      return false;
4485
0
    }
4486
0
    mIsAnyMemberPresent = true;
4487
0
  }
4488
0
4489
0
  if (!isNull) {
4490
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->codecStats_id, temp.ptr())) {
4491
0
      return false;
4492
0
    }
4493
0
  }
4494
0
  if (!isNull && !temp->isUndefined()) {
4495
0
    mCodecStats.Construct();
4496
0
    if (temp.ref().isObject()) {
4497
0
      JS::ForOfIterator iter(cx);
4498
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
4499
0
        return false;
4500
0
      }
4501
0
      if (!iter.valueIsIterable()) {
4502
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'codecStats' member of RTCStatsReportInternal");
4503
0
        return false;
4504
0
      }
4505
0
      Sequence<RTCCodecStats> &arr = (mCodecStats.Value());
4506
0
      JS::Rooted<JS::Value> temp(cx);
4507
0
      while (true) {
4508
0
        bool done;
4509
0
        if (!iter.next(&temp, &done)) {
4510
0
          return false;
4511
0
        }
4512
0
        if (done) {
4513
0
          break;
4514
0
        }
4515
0
        RTCCodecStats* slotPtr = arr.AppendElement(mozilla::fallible);
4516
0
        if (!slotPtr) {
4517
0
          JS_ReportOutOfMemory(cx);
4518
0
          return false;
4519
0
        }
4520
0
        RTCCodecStats& slot = *slotPtr;
4521
0
        if (!slot.Init(cx, temp,  "Element of 'codecStats' member of RTCStatsReportInternal", passedToJSImpl)) {
4522
0
          return false;
4523
0
        }
4524
0
      }
4525
0
    } else {
4526
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'codecStats' member of RTCStatsReportInternal");
4527
0
      return false;
4528
0
    }
4529
0
    mIsAnyMemberPresent = true;
4530
0
  }
4531
0
4532
0
  if (!isNull) {
4533
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->iceCandidatePairStats_id, temp.ptr())) {
4534
0
      return false;
4535
0
    }
4536
0
  }
4537
0
  if (!isNull && !temp->isUndefined()) {
4538
0
    mIceCandidatePairStats.Construct();
4539
0
    if (temp.ref().isObject()) {
4540
0
      JS::ForOfIterator iter(cx);
4541
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
4542
0
        return false;
4543
0
      }
4544
0
      if (!iter.valueIsIterable()) {
4545
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'iceCandidatePairStats' member of RTCStatsReportInternal");
4546
0
        return false;
4547
0
      }
4548
0
      Sequence<RTCIceCandidatePairStats> &arr = (mIceCandidatePairStats.Value());
4549
0
      JS::Rooted<JS::Value> temp(cx);
4550
0
      while (true) {
4551
0
        bool done;
4552
0
        if (!iter.next(&temp, &done)) {
4553
0
          return false;
4554
0
        }
4555
0
        if (done) {
4556
0
          break;
4557
0
        }
4558
0
        RTCIceCandidatePairStats* slotPtr = arr.AppendElement(mozilla::fallible);
4559
0
        if (!slotPtr) {
4560
0
          JS_ReportOutOfMemory(cx);
4561
0
          return false;
4562
0
        }
4563
0
        RTCIceCandidatePairStats& slot = *slotPtr;
4564
0
        if (!slot.Init(cx, temp,  "Element of 'iceCandidatePairStats' member of RTCStatsReportInternal", passedToJSImpl)) {
4565
0
          return false;
4566
0
        }
4567
0
      }
4568
0
    } else {
4569
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'iceCandidatePairStats' member of RTCStatsReportInternal");
4570
0
      return false;
4571
0
    }
4572
0
    mIsAnyMemberPresent = true;
4573
0
  }
4574
0
4575
0
  if (!isNull) {
4576
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->iceCandidateStats_id, temp.ptr())) {
4577
0
      return false;
4578
0
    }
4579
0
  }
4580
0
  if (!isNull && !temp->isUndefined()) {
4581
0
    mIceCandidateStats.Construct();
4582
0
    if (temp.ref().isObject()) {
4583
0
      JS::ForOfIterator iter(cx);
4584
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
4585
0
        return false;
4586
0
      }
4587
0
      if (!iter.valueIsIterable()) {
4588
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'iceCandidateStats' member of RTCStatsReportInternal");
4589
0
        return false;
4590
0
      }
4591
0
      Sequence<RTCIceCandidateStats> &arr = (mIceCandidateStats.Value());
4592
0
      JS::Rooted<JS::Value> temp(cx);
4593
0
      while (true) {
4594
0
        bool done;
4595
0
        if (!iter.next(&temp, &done)) {
4596
0
          return false;
4597
0
        }
4598
0
        if (done) {
4599
0
          break;
4600
0
        }
4601
0
        RTCIceCandidateStats* slotPtr = arr.AppendElement(mozilla::fallible);
4602
0
        if (!slotPtr) {
4603
0
          JS_ReportOutOfMemory(cx);
4604
0
          return false;
4605
0
        }
4606
0
        RTCIceCandidateStats& slot = *slotPtr;
4607
0
        if (!slot.Init(cx, temp,  "Element of 'iceCandidateStats' member of RTCStatsReportInternal", passedToJSImpl)) {
4608
0
          return false;
4609
0
        }
4610
0
      }
4611
0
    } else {
4612
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'iceCandidateStats' member of RTCStatsReportInternal");
4613
0
      return false;
4614
0
    }
4615
0
    mIsAnyMemberPresent = true;
4616
0
  }
4617
0
4618
0
  if (!isNull) {
4619
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->iceComponentStats_id, temp.ptr())) {
4620
0
      return false;
4621
0
    }
4622
0
  }
4623
0
  if (!isNull && !temp->isUndefined()) {
4624
0
    mIceComponentStats.Construct();
4625
0
    if (temp.ref().isObject()) {
4626
0
      JS::ForOfIterator iter(cx);
4627
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
4628
0
        return false;
4629
0
      }
4630
0
      if (!iter.valueIsIterable()) {
4631
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'iceComponentStats' member of RTCStatsReportInternal");
4632
0
        return false;
4633
0
      }
4634
0
      Sequence<RTCIceComponentStats> &arr = (mIceComponentStats.Value());
4635
0
      JS::Rooted<JS::Value> temp(cx);
4636
0
      while (true) {
4637
0
        bool done;
4638
0
        if (!iter.next(&temp, &done)) {
4639
0
          return false;
4640
0
        }
4641
0
        if (done) {
4642
0
          break;
4643
0
        }
4644
0
        RTCIceComponentStats* slotPtr = arr.AppendElement(mozilla::fallible);
4645
0
        if (!slotPtr) {
4646
0
          JS_ReportOutOfMemory(cx);
4647
0
          return false;
4648
0
        }
4649
0
        RTCIceComponentStats& slot = *slotPtr;
4650
0
        if (!slot.Init(cx, temp,  "Element of 'iceComponentStats' member of RTCStatsReportInternal", passedToJSImpl)) {
4651
0
          return false;
4652
0
        }
4653
0
      }
4654
0
    } else {
4655
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'iceComponentStats' member of RTCStatsReportInternal");
4656
0
      return false;
4657
0
    }
4658
0
    mIsAnyMemberPresent = true;
4659
0
  }
4660
0
4661
0
  if (!isNull) {
4662
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->iceRestarts_id, temp.ptr())) {
4663
0
      return false;
4664
0
    }
4665
0
  }
4666
0
  if (!isNull && !temp->isUndefined()) {
4667
0
    mIceRestarts.Construct();
4668
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mIceRestarts.Value()))) {
4669
0
      return false;
4670
0
    }
4671
0
    mIsAnyMemberPresent = true;
4672
0
  }
4673
0
4674
0
  if (!isNull) {
4675
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->iceRollbacks_id, temp.ptr())) {
4676
0
      return false;
4677
0
    }
4678
0
  }
4679
0
  if (!isNull && !temp->isUndefined()) {
4680
0
    mIceRollbacks.Construct();
4681
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mIceRollbacks.Value()))) {
4682
0
      return false;
4683
0
    }
4684
0
    mIsAnyMemberPresent = true;
4685
0
  }
4686
0
4687
0
  if (!isNull) {
4688
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->inboundRTPStreamStats_id, temp.ptr())) {
4689
0
      return false;
4690
0
    }
4691
0
  }
4692
0
  if (!isNull && !temp->isUndefined()) {
4693
0
    mInboundRTPStreamStats.Construct();
4694
0
    if (temp.ref().isObject()) {
4695
0
      JS::ForOfIterator iter(cx);
4696
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
4697
0
        return false;
4698
0
      }
4699
0
      if (!iter.valueIsIterable()) {
4700
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'inboundRTPStreamStats' member of RTCStatsReportInternal");
4701
0
        return false;
4702
0
      }
4703
0
      Sequence<RTCInboundRTPStreamStats> &arr = (mInboundRTPStreamStats.Value());
4704
0
      JS::Rooted<JS::Value> temp(cx);
4705
0
      while (true) {
4706
0
        bool done;
4707
0
        if (!iter.next(&temp, &done)) {
4708
0
          return false;
4709
0
        }
4710
0
        if (done) {
4711
0
          break;
4712
0
        }
4713
0
        RTCInboundRTPStreamStats* slotPtr = arr.AppendElement(mozilla::fallible);
4714
0
        if (!slotPtr) {
4715
0
          JS_ReportOutOfMemory(cx);
4716
0
          return false;
4717
0
        }
4718
0
        RTCInboundRTPStreamStats& slot = *slotPtr;
4719
0
        if (!slot.Init(cx, temp,  "Element of 'inboundRTPStreamStats' member of RTCStatsReportInternal", passedToJSImpl)) {
4720
0
          return false;
4721
0
        }
4722
0
      }
4723
0
    } else {
4724
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'inboundRTPStreamStats' member of RTCStatsReportInternal");
4725
0
      return false;
4726
0
    }
4727
0
    mIsAnyMemberPresent = true;
4728
0
  }
4729
0
4730
0
  if (!isNull) {
4731
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->localSdp_id, temp.ptr())) {
4732
0
      return false;
4733
0
    }
4734
0
  }
4735
0
  if (!isNull && !temp->isUndefined()) {
4736
0
    mLocalSdp.Construct();
4737
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mLocalSdp.Value()))) {
4738
0
      return false;
4739
0
    }
4740
0
    mIsAnyMemberPresent = true;
4741
0
  }
4742
0
4743
0
  if (!isNull) {
4744
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->mediaStreamStats_id, temp.ptr())) {
4745
0
      return false;
4746
0
    }
4747
0
  }
4748
0
  if (!isNull && !temp->isUndefined()) {
4749
0
    mMediaStreamStats.Construct();
4750
0
    if (temp.ref().isObject()) {
4751
0
      JS::ForOfIterator iter(cx);
4752
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
4753
0
        return false;
4754
0
      }
4755
0
      if (!iter.valueIsIterable()) {
4756
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'mediaStreamStats' member of RTCStatsReportInternal");
4757
0
        return false;
4758
0
      }
4759
0
      Sequence<RTCMediaStreamStats> &arr = (mMediaStreamStats.Value());
4760
0
      JS::Rooted<JS::Value> temp(cx);
4761
0
      while (true) {
4762
0
        bool done;
4763
0
        if (!iter.next(&temp, &done)) {
4764
0
          return false;
4765
0
        }
4766
0
        if (done) {
4767
0
          break;
4768
0
        }
4769
0
        RTCMediaStreamStats* slotPtr = arr.AppendElement(mozilla::fallible);
4770
0
        if (!slotPtr) {
4771
0
          JS_ReportOutOfMemory(cx);
4772
0
          return false;
4773
0
        }
4774
0
        RTCMediaStreamStats& slot = *slotPtr;
4775
0
        if (!slot.Init(cx, temp,  "Element of 'mediaStreamStats' member of RTCStatsReportInternal", passedToJSImpl)) {
4776
0
          return false;
4777
0
        }
4778
0
      }
4779
0
    } else {
4780
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'mediaStreamStats' member of RTCStatsReportInternal");
4781
0
      return false;
4782
0
    }
4783
0
    mIsAnyMemberPresent = true;
4784
0
  }
4785
0
4786
0
  if (!isNull) {
4787
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->mediaStreamTrackStats_id, temp.ptr())) {
4788
0
      return false;
4789
0
    }
4790
0
  }
4791
0
  if (!isNull && !temp->isUndefined()) {
4792
0
    mMediaStreamTrackStats.Construct();
4793
0
    if (temp.ref().isObject()) {
4794
0
      JS::ForOfIterator iter(cx);
4795
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
4796
0
        return false;
4797
0
      }
4798
0
      if (!iter.valueIsIterable()) {
4799
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'mediaStreamTrackStats' member of RTCStatsReportInternal");
4800
0
        return false;
4801
0
      }
4802
0
      Sequence<RTCMediaStreamTrackStats> &arr = (mMediaStreamTrackStats.Value());
4803
0
      JS::Rooted<JS::Value> temp(cx);
4804
0
      while (true) {
4805
0
        bool done;
4806
0
        if (!iter.next(&temp, &done)) {
4807
0
          return false;
4808
0
        }
4809
0
        if (done) {
4810
0
          break;
4811
0
        }
4812
0
        RTCMediaStreamTrackStats* slotPtr = arr.AppendElement(mozilla::fallible);
4813
0
        if (!slotPtr) {
4814
0
          JS_ReportOutOfMemory(cx);
4815
0
          return false;
4816
0
        }
4817
0
        RTCMediaStreamTrackStats& slot = *slotPtr;
4818
0
        if (!slot.Init(cx, temp,  "Element of 'mediaStreamTrackStats' member of RTCStatsReportInternal", passedToJSImpl)) {
4819
0
          return false;
4820
0
        }
4821
0
      }
4822
0
    } else {
4823
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'mediaStreamTrackStats' member of RTCStatsReportInternal");
4824
0
      return false;
4825
0
    }
4826
0
    mIsAnyMemberPresent = true;
4827
0
  }
4828
0
4829
0
  if (!isNull) {
4830
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->offerer_id, temp.ptr())) {
4831
0
      return false;
4832
0
    }
4833
0
  }
4834
0
  if (!isNull && !temp->isUndefined()) {
4835
0
    mOfferer.Construct();
4836
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mOfferer.Value()))) {
4837
0
      return false;
4838
0
    }
4839
0
    mIsAnyMemberPresent = true;
4840
0
  }
4841
0
4842
0
  if (!isNull) {
4843
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->outboundRTPStreamStats_id, temp.ptr())) {
4844
0
      return false;
4845
0
    }
4846
0
  }
4847
0
  if (!isNull && !temp->isUndefined()) {
4848
0
    mOutboundRTPStreamStats.Construct();
4849
0
    if (temp.ref().isObject()) {
4850
0
      JS::ForOfIterator iter(cx);
4851
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
4852
0
        return false;
4853
0
      }
4854
0
      if (!iter.valueIsIterable()) {
4855
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'outboundRTPStreamStats' member of RTCStatsReportInternal");
4856
0
        return false;
4857
0
      }
4858
0
      Sequence<RTCOutboundRTPStreamStats> &arr = (mOutboundRTPStreamStats.Value());
4859
0
      JS::Rooted<JS::Value> temp(cx);
4860
0
      while (true) {
4861
0
        bool done;
4862
0
        if (!iter.next(&temp, &done)) {
4863
0
          return false;
4864
0
        }
4865
0
        if (done) {
4866
0
          break;
4867
0
        }
4868
0
        RTCOutboundRTPStreamStats* slotPtr = arr.AppendElement(mozilla::fallible);
4869
0
        if (!slotPtr) {
4870
0
          JS_ReportOutOfMemory(cx);
4871
0
          return false;
4872
0
        }
4873
0
        RTCOutboundRTPStreamStats& slot = *slotPtr;
4874
0
        if (!slot.Init(cx, temp,  "Element of 'outboundRTPStreamStats' member of RTCStatsReportInternal", passedToJSImpl)) {
4875
0
          return false;
4876
0
        }
4877
0
      }
4878
0
    } else {
4879
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'outboundRTPStreamStats' member of RTCStatsReportInternal");
4880
0
      return false;
4881
0
    }
4882
0
    mIsAnyMemberPresent = true;
4883
0
  }
4884
0
4885
0
  if (!isNull) {
4886
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->pcid_id, temp.ptr())) {
4887
0
      return false;
4888
0
    }
4889
0
  }
4890
0
  if (!isNull && !temp->isUndefined()) {
4891
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mPcid)) {
4892
0
      return false;
4893
0
    }
4894
0
  } else {
4895
0
    static const char16_t data[] = { 0 };
4896
0
    mPcid.Rebind(data, ArrayLength(data) - 1);
4897
0
  }
4898
0
  mIsAnyMemberPresent = true;
4899
0
4900
0
  if (!isNull) {
4901
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->rawLocalCandidates_id, temp.ptr())) {
4902
0
      return false;
4903
0
    }
4904
0
  }
4905
0
  if (!isNull && !temp->isUndefined()) {
4906
0
    mRawLocalCandidates.Construct();
4907
0
    if (temp.ref().isObject()) {
4908
0
      JS::ForOfIterator iter(cx);
4909
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
4910
0
        return false;
4911
0
      }
4912
0
      if (!iter.valueIsIterable()) {
4913
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'rawLocalCandidates' member of RTCStatsReportInternal");
4914
0
        return false;
4915
0
      }
4916
0
      Sequence<nsString> &arr = (mRawLocalCandidates.Value());
4917
0
      JS::Rooted<JS::Value> temp(cx);
4918
0
      while (true) {
4919
0
        bool done;
4920
0
        if (!iter.next(&temp, &done)) {
4921
0
          return false;
4922
0
        }
4923
0
        if (done) {
4924
0
          break;
4925
0
        }
4926
0
        nsString* slotPtr = arr.AppendElement(mozilla::fallible);
4927
0
        if (!slotPtr) {
4928
0
          JS_ReportOutOfMemory(cx);
4929
0
          return false;
4930
0
        }
4931
0
        nsString& slot = *slotPtr;
4932
0
        if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
4933
0
          return false;
4934
0
        }
4935
0
      }
4936
0
    } else {
4937
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'rawLocalCandidates' member of RTCStatsReportInternal");
4938
0
      return false;
4939
0
    }
4940
0
    mIsAnyMemberPresent = true;
4941
0
  }
4942
0
4943
0
  if (!isNull) {
4944
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->rawRemoteCandidates_id, temp.ptr())) {
4945
0
      return false;
4946
0
    }
4947
0
  }
4948
0
  if (!isNull && !temp->isUndefined()) {
4949
0
    mRawRemoteCandidates.Construct();
4950
0
    if (temp.ref().isObject()) {
4951
0
      JS::ForOfIterator iter(cx);
4952
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
4953
0
        return false;
4954
0
      }
4955
0
      if (!iter.valueIsIterable()) {
4956
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'rawRemoteCandidates' member of RTCStatsReportInternal");
4957
0
        return false;
4958
0
      }
4959
0
      Sequence<nsString> &arr = (mRawRemoteCandidates.Value());
4960
0
      JS::Rooted<JS::Value> temp(cx);
4961
0
      while (true) {
4962
0
        bool done;
4963
0
        if (!iter.next(&temp, &done)) {
4964
0
          return false;
4965
0
        }
4966
0
        if (done) {
4967
0
          break;
4968
0
        }
4969
0
        nsString* slotPtr = arr.AppendElement(mozilla::fallible);
4970
0
        if (!slotPtr) {
4971
0
          JS_ReportOutOfMemory(cx);
4972
0
          return false;
4973
0
        }
4974
0
        nsString& slot = *slotPtr;
4975
0
        if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
4976
0
          return false;
4977
0
        }
4978
0
      }
4979
0
    } else {
4980
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'rawRemoteCandidates' member of RTCStatsReportInternal");
4981
0
      return false;
4982
0
    }
4983
0
    mIsAnyMemberPresent = true;
4984
0
  }
4985
0
4986
0
  if (!isNull) {
4987
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->remoteSdp_id, temp.ptr())) {
4988
0
      return false;
4989
0
    }
4990
0
  }
4991
0
  if (!isNull && !temp->isUndefined()) {
4992
0
    mRemoteSdp.Construct();
4993
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mRemoteSdp.Value()))) {
4994
0
      return false;
4995
0
    }
4996
0
    mIsAnyMemberPresent = true;
4997
0
  }
4998
0
4999
0
  if (!isNull) {
5000
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->rtpContributingSourceStats_id, temp.ptr())) {
5001
0
      return false;
5002
0
    }
5003
0
  }
5004
0
  if (!isNull && !temp->isUndefined()) {
5005
0
    mRtpContributingSourceStats.Construct();
5006
0
    if (temp.ref().isObject()) {
5007
0
      JS::ForOfIterator iter(cx);
5008
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
5009
0
        return false;
5010
0
      }
5011
0
      if (!iter.valueIsIterable()) {
5012
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'rtpContributingSourceStats' member of RTCStatsReportInternal");
5013
0
        return false;
5014
0
      }
5015
0
      Sequence<RTCRTPContributingSourceStats> &arr = (mRtpContributingSourceStats.Value());
5016
0
      JS::Rooted<JS::Value> temp(cx);
5017
0
      while (true) {
5018
0
        bool done;
5019
0
        if (!iter.next(&temp, &done)) {
5020
0
          return false;
5021
0
        }
5022
0
        if (done) {
5023
0
          break;
5024
0
        }
5025
0
        RTCRTPContributingSourceStats* slotPtr = arr.AppendElement(mozilla::fallible);
5026
0
        if (!slotPtr) {
5027
0
          JS_ReportOutOfMemory(cx);
5028
0
          return false;
5029
0
        }
5030
0
        RTCRTPContributingSourceStats& slot = *slotPtr;
5031
0
        if (!slot.Init(cx, temp,  "Element of 'rtpContributingSourceStats' member of RTCStatsReportInternal", passedToJSImpl)) {
5032
0
          return false;
5033
0
        }
5034
0
      }
5035
0
    } else {
5036
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'rtpContributingSourceStats' member of RTCStatsReportInternal");
5037
0
      return false;
5038
0
    }
5039
0
    mIsAnyMemberPresent = true;
5040
0
  }
5041
0
5042
0
  if (!isNull) {
5043
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->timestamp_id, temp.ptr())) {
5044
0
      return false;
5045
0
    }
5046
0
  }
5047
0
  if (!isNull && !temp->isUndefined()) {
5048
0
    mTimestamp.Construct();
5049
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &(mTimestamp.Value()))) {
5050
0
      return false;
5051
0
    } else if (!mozilla::IsFinite((mTimestamp.Value()))) {
5052
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'timestamp' member of RTCStatsReportInternal");
5053
0
      return false;
5054
0
    }
5055
0
    mIsAnyMemberPresent = true;
5056
0
  }
5057
0
5058
0
  if (!isNull) {
5059
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->transportStats_id, temp.ptr())) {
5060
0
      return false;
5061
0
    }
5062
0
  }
5063
0
  if (!isNull && !temp->isUndefined()) {
5064
0
    mTransportStats.Construct();
5065
0
    if (temp.ref().isObject()) {
5066
0
      JS::ForOfIterator iter(cx);
5067
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
5068
0
        return false;
5069
0
      }
5070
0
      if (!iter.valueIsIterable()) {
5071
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'transportStats' member of RTCStatsReportInternal");
5072
0
        return false;
5073
0
      }
5074
0
      Sequence<RTCTransportStats> &arr = (mTransportStats.Value());
5075
0
      JS::Rooted<JS::Value> temp(cx);
5076
0
      while (true) {
5077
0
        bool done;
5078
0
        if (!iter.next(&temp, &done)) {
5079
0
          return false;
5080
0
        }
5081
0
        if (done) {
5082
0
          break;
5083
0
        }
5084
0
        RTCTransportStats* slotPtr = arr.AppendElement(mozilla::fallible);
5085
0
        if (!slotPtr) {
5086
0
          JS_ReportOutOfMemory(cx);
5087
0
          return false;
5088
0
        }
5089
0
        RTCTransportStats& slot = *slotPtr;
5090
0
        if (!slot.Init(cx, temp,  "Element of 'transportStats' member of RTCStatsReportInternal", passedToJSImpl)) {
5091
0
          return false;
5092
0
        }
5093
0
      }
5094
0
    } else {
5095
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'transportStats' member of RTCStatsReportInternal");
5096
0
      return false;
5097
0
    }
5098
0
    mIsAnyMemberPresent = true;
5099
0
  }
5100
0
5101
0
  if (!isNull) {
5102
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->trickledIceCandidateStats_id, temp.ptr())) {
5103
0
      return false;
5104
0
    }
5105
0
  }
5106
0
  if (!isNull && !temp->isUndefined()) {
5107
0
    mTrickledIceCandidateStats.Construct();
5108
0
    if (temp.ref().isObject()) {
5109
0
      JS::ForOfIterator iter(cx);
5110
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
5111
0
        return false;
5112
0
      }
5113
0
      if (!iter.valueIsIterable()) {
5114
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'trickledIceCandidateStats' member of RTCStatsReportInternal");
5115
0
        return false;
5116
0
      }
5117
0
      Sequence<RTCIceCandidateStats> &arr = (mTrickledIceCandidateStats.Value());
5118
0
      JS::Rooted<JS::Value> temp(cx);
5119
0
      while (true) {
5120
0
        bool done;
5121
0
        if (!iter.next(&temp, &done)) {
5122
0
          return false;
5123
0
        }
5124
0
        if (done) {
5125
0
          break;
5126
0
        }
5127
0
        RTCIceCandidateStats* slotPtr = arr.AppendElement(mozilla::fallible);
5128
0
        if (!slotPtr) {
5129
0
          JS_ReportOutOfMemory(cx);
5130
0
          return false;
5131
0
        }
5132
0
        RTCIceCandidateStats& slot = *slotPtr;
5133
0
        if (!slot.Init(cx, temp,  "Element of 'trickledIceCandidateStats' member of RTCStatsReportInternal", passedToJSImpl)) {
5134
0
          return false;
5135
0
        }
5136
0
      }
5137
0
    } else {
5138
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'trickledIceCandidateStats' member of RTCStatsReportInternal");
5139
0
      return false;
5140
0
    }
5141
0
    mIsAnyMemberPresent = true;
5142
0
  }
5143
0
  return true;
5144
0
}
5145
5146
bool
5147
RTCStatsReportInternal::Init(const nsAString& aJSON)
5148
0
{
5149
0
  AutoJSAPI jsapi;
5150
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
5151
0
  if (!cleanGlobal) {
5152
0
    return false;
5153
0
  }
5154
0
  if (!jsapi.Init(cleanGlobal)) {
5155
0
    return false;
5156
0
  }
5157
0
  JSContext* cx = jsapi.cx();
5158
0
  JS::Rooted<JS::Value> json(cx);
5159
0
  bool ok = ParseJSON(cx, aJSON, &json);
5160
0
  NS_ENSURE_TRUE(ok, false);
5161
0
  return Init(cx, json);
5162
0
}
5163
5164
bool
5165
RTCStatsReportInternal::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
5166
0
{
5167
0
  RTCStatsReportInternalAtoms* atomsCache = GetAtomCache<RTCStatsReportInternalAtoms>(cx);
5168
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
5169
0
    return false;
5170
0
  }
5171
0
5172
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
5173
0
  if (!obj) {
5174
0
    return false;
5175
0
  }
5176
0
  rval.set(JS::ObjectValue(*obj));
5177
0
5178
0
  if (mClosed.WasPassed()) {
5179
0
    do {
5180
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5181
0
      JS::Rooted<JS::Value> temp(cx);
5182
0
      bool const & currentValue = mClosed.InternalValue();
5183
0
      temp.setBoolean(currentValue);
5184
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->closed_id, temp, JSPROP_ENUMERATE)) {
5185
0
        return false;
5186
0
      }
5187
0
      break;
5188
0
    } while(false);
5189
0
  }
5190
0
5191
0
  if (mCodecStats.WasPassed()) {
5192
0
    do {
5193
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5194
0
      JS::Rooted<JS::Value> temp(cx);
5195
0
      Sequence<RTCCodecStats> const & currentValue = mCodecStats.InternalValue();
5196
0
5197
0
      uint32_t length = currentValue.Length();
5198
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5199
0
      if (!returnArray) {
5200
0
        return false;
5201
0
      }
5202
0
      // Scope for 'tmp'
5203
0
      {
5204
0
        JS::Rooted<JS::Value> tmp(cx);
5205
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5206
0
          // Control block to let us common up the JS_DefineElement calls when there
5207
0
          // are different ways to succeed at wrapping the object.
5208
0
          do {
5209
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
5210
0
              return false;
5211
0
            }
5212
0
            break;
5213
0
          } while (false);
5214
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5215
0
                                JSPROP_ENUMERATE)) {
5216
0
            return false;
5217
0
          }
5218
0
        }
5219
0
      }
5220
0
      temp.setObject(*returnArray);
5221
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->codecStats_id, temp, JSPROP_ENUMERATE)) {
5222
0
        return false;
5223
0
      }
5224
0
      break;
5225
0
    } while(false);
5226
0
  }
5227
0
5228
0
  if (mIceCandidatePairStats.WasPassed()) {
5229
0
    do {
5230
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5231
0
      JS::Rooted<JS::Value> temp(cx);
5232
0
      Sequence<RTCIceCandidatePairStats> const & currentValue = mIceCandidatePairStats.InternalValue();
5233
0
5234
0
      uint32_t length = currentValue.Length();
5235
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5236
0
      if (!returnArray) {
5237
0
        return false;
5238
0
      }
5239
0
      // Scope for 'tmp'
5240
0
      {
5241
0
        JS::Rooted<JS::Value> tmp(cx);
5242
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5243
0
          // Control block to let us common up the JS_DefineElement calls when there
5244
0
          // are different ways to succeed at wrapping the object.
5245
0
          do {
5246
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
5247
0
              return false;
5248
0
            }
5249
0
            break;
5250
0
          } while (false);
5251
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5252
0
                                JSPROP_ENUMERATE)) {
5253
0
            return false;
5254
0
          }
5255
0
        }
5256
0
      }
5257
0
      temp.setObject(*returnArray);
5258
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->iceCandidatePairStats_id, temp, JSPROP_ENUMERATE)) {
5259
0
        return false;
5260
0
      }
5261
0
      break;
5262
0
    } while(false);
5263
0
  }
5264
0
5265
0
  if (mIceCandidateStats.WasPassed()) {
5266
0
    do {
5267
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5268
0
      JS::Rooted<JS::Value> temp(cx);
5269
0
      Sequence<RTCIceCandidateStats> const & currentValue = mIceCandidateStats.InternalValue();
5270
0
5271
0
      uint32_t length = currentValue.Length();
5272
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5273
0
      if (!returnArray) {
5274
0
        return false;
5275
0
      }
5276
0
      // Scope for 'tmp'
5277
0
      {
5278
0
        JS::Rooted<JS::Value> tmp(cx);
5279
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5280
0
          // Control block to let us common up the JS_DefineElement calls when there
5281
0
          // are different ways to succeed at wrapping the object.
5282
0
          do {
5283
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
5284
0
              return false;
5285
0
            }
5286
0
            break;
5287
0
          } while (false);
5288
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5289
0
                                JSPROP_ENUMERATE)) {
5290
0
            return false;
5291
0
          }
5292
0
        }
5293
0
      }
5294
0
      temp.setObject(*returnArray);
5295
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->iceCandidateStats_id, temp, JSPROP_ENUMERATE)) {
5296
0
        return false;
5297
0
      }
5298
0
      break;
5299
0
    } while(false);
5300
0
  }
5301
0
5302
0
  if (mIceComponentStats.WasPassed()) {
5303
0
    do {
5304
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5305
0
      JS::Rooted<JS::Value> temp(cx);
5306
0
      Sequence<RTCIceComponentStats> const & currentValue = mIceComponentStats.InternalValue();
5307
0
5308
0
      uint32_t length = currentValue.Length();
5309
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5310
0
      if (!returnArray) {
5311
0
        return false;
5312
0
      }
5313
0
      // Scope for 'tmp'
5314
0
      {
5315
0
        JS::Rooted<JS::Value> tmp(cx);
5316
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5317
0
          // Control block to let us common up the JS_DefineElement calls when there
5318
0
          // are different ways to succeed at wrapping the object.
5319
0
          do {
5320
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
5321
0
              return false;
5322
0
            }
5323
0
            break;
5324
0
          } while (false);
5325
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5326
0
                                JSPROP_ENUMERATE)) {
5327
0
            return false;
5328
0
          }
5329
0
        }
5330
0
      }
5331
0
      temp.setObject(*returnArray);
5332
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->iceComponentStats_id, temp, JSPROP_ENUMERATE)) {
5333
0
        return false;
5334
0
      }
5335
0
      break;
5336
0
    } while(false);
5337
0
  }
5338
0
5339
0
  if (mIceRestarts.WasPassed()) {
5340
0
    do {
5341
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5342
0
      JS::Rooted<JS::Value> temp(cx);
5343
0
      uint32_t const & currentValue = mIceRestarts.InternalValue();
5344
0
      temp.setNumber(currentValue);
5345
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->iceRestarts_id, temp, JSPROP_ENUMERATE)) {
5346
0
        return false;
5347
0
      }
5348
0
      break;
5349
0
    } while(false);
5350
0
  }
5351
0
5352
0
  if (mIceRollbacks.WasPassed()) {
5353
0
    do {
5354
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5355
0
      JS::Rooted<JS::Value> temp(cx);
5356
0
      uint32_t const & currentValue = mIceRollbacks.InternalValue();
5357
0
      temp.setNumber(currentValue);
5358
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->iceRollbacks_id, temp, JSPROP_ENUMERATE)) {
5359
0
        return false;
5360
0
      }
5361
0
      break;
5362
0
    } while(false);
5363
0
  }
5364
0
5365
0
  if (mInboundRTPStreamStats.WasPassed()) {
5366
0
    do {
5367
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5368
0
      JS::Rooted<JS::Value> temp(cx);
5369
0
      Sequence<RTCInboundRTPStreamStats> const & currentValue = mInboundRTPStreamStats.InternalValue();
5370
0
5371
0
      uint32_t length = currentValue.Length();
5372
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5373
0
      if (!returnArray) {
5374
0
        return false;
5375
0
      }
5376
0
      // Scope for 'tmp'
5377
0
      {
5378
0
        JS::Rooted<JS::Value> tmp(cx);
5379
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5380
0
          // Control block to let us common up the JS_DefineElement calls when there
5381
0
          // are different ways to succeed at wrapping the object.
5382
0
          do {
5383
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
5384
0
              return false;
5385
0
            }
5386
0
            break;
5387
0
          } while (false);
5388
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5389
0
                                JSPROP_ENUMERATE)) {
5390
0
            return false;
5391
0
          }
5392
0
        }
5393
0
      }
5394
0
      temp.setObject(*returnArray);
5395
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->inboundRTPStreamStats_id, temp, JSPROP_ENUMERATE)) {
5396
0
        return false;
5397
0
      }
5398
0
      break;
5399
0
    } while(false);
5400
0
  }
5401
0
5402
0
  if (mLocalSdp.WasPassed()) {
5403
0
    do {
5404
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5405
0
      JS::Rooted<JS::Value> temp(cx);
5406
0
      nsString const & currentValue = mLocalSdp.InternalValue();
5407
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
5408
0
        return false;
5409
0
      }
5410
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->localSdp_id, temp, JSPROP_ENUMERATE)) {
5411
0
        return false;
5412
0
      }
5413
0
      break;
5414
0
    } while(false);
5415
0
  }
5416
0
5417
0
  if (mMediaStreamStats.WasPassed()) {
5418
0
    do {
5419
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5420
0
      JS::Rooted<JS::Value> temp(cx);
5421
0
      Sequence<RTCMediaStreamStats> const & currentValue = mMediaStreamStats.InternalValue();
5422
0
5423
0
      uint32_t length = currentValue.Length();
5424
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5425
0
      if (!returnArray) {
5426
0
        return false;
5427
0
      }
5428
0
      // Scope for 'tmp'
5429
0
      {
5430
0
        JS::Rooted<JS::Value> tmp(cx);
5431
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5432
0
          // Control block to let us common up the JS_DefineElement calls when there
5433
0
          // are different ways to succeed at wrapping the object.
5434
0
          do {
5435
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
5436
0
              return false;
5437
0
            }
5438
0
            break;
5439
0
          } while (false);
5440
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5441
0
                                JSPROP_ENUMERATE)) {
5442
0
            return false;
5443
0
          }
5444
0
        }
5445
0
      }
5446
0
      temp.setObject(*returnArray);
5447
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->mediaStreamStats_id, temp, JSPROP_ENUMERATE)) {
5448
0
        return false;
5449
0
      }
5450
0
      break;
5451
0
    } while(false);
5452
0
  }
5453
0
5454
0
  if (mMediaStreamTrackStats.WasPassed()) {
5455
0
    do {
5456
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5457
0
      JS::Rooted<JS::Value> temp(cx);
5458
0
      Sequence<RTCMediaStreamTrackStats> const & currentValue = mMediaStreamTrackStats.InternalValue();
5459
0
5460
0
      uint32_t length = currentValue.Length();
5461
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5462
0
      if (!returnArray) {
5463
0
        return false;
5464
0
      }
5465
0
      // Scope for 'tmp'
5466
0
      {
5467
0
        JS::Rooted<JS::Value> tmp(cx);
5468
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5469
0
          // Control block to let us common up the JS_DefineElement calls when there
5470
0
          // are different ways to succeed at wrapping the object.
5471
0
          do {
5472
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
5473
0
              return false;
5474
0
            }
5475
0
            break;
5476
0
          } while (false);
5477
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5478
0
                                JSPROP_ENUMERATE)) {
5479
0
            return false;
5480
0
          }
5481
0
        }
5482
0
      }
5483
0
      temp.setObject(*returnArray);
5484
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->mediaStreamTrackStats_id, temp, JSPROP_ENUMERATE)) {
5485
0
        return false;
5486
0
      }
5487
0
      break;
5488
0
    } while(false);
5489
0
  }
5490
0
5491
0
  if (mOfferer.WasPassed()) {
5492
0
    do {
5493
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5494
0
      JS::Rooted<JS::Value> temp(cx);
5495
0
      bool const & currentValue = mOfferer.InternalValue();
5496
0
      temp.setBoolean(currentValue);
5497
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->offerer_id, temp, JSPROP_ENUMERATE)) {
5498
0
        return false;
5499
0
      }
5500
0
      break;
5501
0
    } while(false);
5502
0
  }
5503
0
5504
0
  if (mOutboundRTPStreamStats.WasPassed()) {
5505
0
    do {
5506
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5507
0
      JS::Rooted<JS::Value> temp(cx);
5508
0
      Sequence<RTCOutboundRTPStreamStats> const & currentValue = mOutboundRTPStreamStats.InternalValue();
5509
0
5510
0
      uint32_t length = currentValue.Length();
5511
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5512
0
      if (!returnArray) {
5513
0
        return false;
5514
0
      }
5515
0
      // Scope for 'tmp'
5516
0
      {
5517
0
        JS::Rooted<JS::Value> tmp(cx);
5518
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5519
0
          // Control block to let us common up the JS_DefineElement calls when there
5520
0
          // are different ways to succeed at wrapping the object.
5521
0
          do {
5522
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
5523
0
              return false;
5524
0
            }
5525
0
            break;
5526
0
          } while (false);
5527
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5528
0
                                JSPROP_ENUMERATE)) {
5529
0
            return false;
5530
0
          }
5531
0
        }
5532
0
      }
5533
0
      temp.setObject(*returnArray);
5534
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->outboundRTPStreamStats_id, temp, JSPROP_ENUMERATE)) {
5535
0
        return false;
5536
0
      }
5537
0
      break;
5538
0
    } while(false);
5539
0
  }
5540
0
5541
0
  do {
5542
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5543
0
    JS::Rooted<JS::Value> temp(cx);
5544
0
    nsString const & currentValue = mPcid;
5545
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
5546
0
      return false;
5547
0
    }
5548
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->pcid_id, temp, JSPROP_ENUMERATE)) {
5549
0
      return false;
5550
0
    }
5551
0
    break;
5552
0
  } while(false);
5553
0
5554
0
  if (mRawLocalCandidates.WasPassed()) {
5555
0
    do {
5556
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5557
0
      JS::Rooted<JS::Value> temp(cx);
5558
0
      Sequence<nsString> const & currentValue = mRawLocalCandidates.InternalValue();
5559
0
5560
0
      uint32_t length = currentValue.Length();
5561
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5562
0
      if (!returnArray) {
5563
0
        return false;
5564
0
      }
5565
0
      // Scope for 'tmp'
5566
0
      {
5567
0
        JS::Rooted<JS::Value> tmp(cx);
5568
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5569
0
          // Control block to let us common up the JS_DefineElement calls when there
5570
0
          // are different ways to succeed at wrapping the object.
5571
0
          do {
5572
0
            if (!xpc::NonVoidStringToJsval(cx, currentValue[sequenceIdx0], &tmp)) {
5573
0
              return false;
5574
0
            }
5575
0
            break;
5576
0
          } while (false);
5577
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5578
0
                                JSPROP_ENUMERATE)) {
5579
0
            return false;
5580
0
          }
5581
0
        }
5582
0
      }
5583
0
      temp.setObject(*returnArray);
5584
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->rawLocalCandidates_id, temp, JSPROP_ENUMERATE)) {
5585
0
        return false;
5586
0
      }
5587
0
      break;
5588
0
    } while(false);
5589
0
  }
5590
0
5591
0
  if (mRawRemoteCandidates.WasPassed()) {
5592
0
    do {
5593
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5594
0
      JS::Rooted<JS::Value> temp(cx);
5595
0
      Sequence<nsString> const & currentValue = mRawRemoteCandidates.InternalValue();
5596
0
5597
0
      uint32_t length = currentValue.Length();
5598
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5599
0
      if (!returnArray) {
5600
0
        return false;
5601
0
      }
5602
0
      // Scope for 'tmp'
5603
0
      {
5604
0
        JS::Rooted<JS::Value> tmp(cx);
5605
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5606
0
          // Control block to let us common up the JS_DefineElement calls when there
5607
0
          // are different ways to succeed at wrapping the object.
5608
0
          do {
5609
0
            if (!xpc::NonVoidStringToJsval(cx, currentValue[sequenceIdx0], &tmp)) {
5610
0
              return false;
5611
0
            }
5612
0
            break;
5613
0
          } while (false);
5614
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5615
0
                                JSPROP_ENUMERATE)) {
5616
0
            return false;
5617
0
          }
5618
0
        }
5619
0
      }
5620
0
      temp.setObject(*returnArray);
5621
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->rawRemoteCandidates_id, temp, JSPROP_ENUMERATE)) {
5622
0
        return false;
5623
0
      }
5624
0
      break;
5625
0
    } while(false);
5626
0
  }
5627
0
5628
0
  if (mRemoteSdp.WasPassed()) {
5629
0
    do {
5630
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5631
0
      JS::Rooted<JS::Value> temp(cx);
5632
0
      nsString const & currentValue = mRemoteSdp.InternalValue();
5633
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
5634
0
        return false;
5635
0
      }
5636
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->remoteSdp_id, temp, JSPROP_ENUMERATE)) {
5637
0
        return false;
5638
0
      }
5639
0
      break;
5640
0
    } while(false);
5641
0
  }
5642
0
5643
0
  if (mRtpContributingSourceStats.WasPassed()) {
5644
0
    do {
5645
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5646
0
      JS::Rooted<JS::Value> temp(cx);
5647
0
      Sequence<RTCRTPContributingSourceStats> const & currentValue = mRtpContributingSourceStats.InternalValue();
5648
0
5649
0
      uint32_t length = currentValue.Length();
5650
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5651
0
      if (!returnArray) {
5652
0
        return false;
5653
0
      }
5654
0
      // Scope for 'tmp'
5655
0
      {
5656
0
        JS::Rooted<JS::Value> tmp(cx);
5657
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5658
0
          // Control block to let us common up the JS_DefineElement calls when there
5659
0
          // are different ways to succeed at wrapping the object.
5660
0
          do {
5661
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
5662
0
              return false;
5663
0
            }
5664
0
            break;
5665
0
          } while (false);
5666
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5667
0
                                JSPROP_ENUMERATE)) {
5668
0
            return false;
5669
0
          }
5670
0
        }
5671
0
      }
5672
0
      temp.setObject(*returnArray);
5673
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->rtpContributingSourceStats_id, temp, JSPROP_ENUMERATE)) {
5674
0
        return false;
5675
0
      }
5676
0
      break;
5677
0
    } while(false);
5678
0
  }
5679
0
5680
0
  if (mTimestamp.WasPassed()) {
5681
0
    do {
5682
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5683
0
      JS::Rooted<JS::Value> temp(cx);
5684
0
      double const & currentValue = mTimestamp.InternalValue();
5685
0
      temp.set(JS_NumberValue(double(currentValue)));
5686
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->timestamp_id, temp, JSPROP_ENUMERATE)) {
5687
0
        return false;
5688
0
      }
5689
0
      break;
5690
0
    } while(false);
5691
0
  }
5692
0
5693
0
  if (mTransportStats.WasPassed()) {
5694
0
    do {
5695
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5696
0
      JS::Rooted<JS::Value> temp(cx);
5697
0
      Sequence<RTCTransportStats> const & currentValue = mTransportStats.InternalValue();
5698
0
5699
0
      uint32_t length = currentValue.Length();
5700
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5701
0
      if (!returnArray) {
5702
0
        return false;
5703
0
      }
5704
0
      // Scope for 'tmp'
5705
0
      {
5706
0
        JS::Rooted<JS::Value> tmp(cx);
5707
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5708
0
          // Control block to let us common up the JS_DefineElement calls when there
5709
0
          // are different ways to succeed at wrapping the object.
5710
0
          do {
5711
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
5712
0
              return false;
5713
0
            }
5714
0
            break;
5715
0
          } while (false);
5716
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5717
0
                                JSPROP_ENUMERATE)) {
5718
0
            return false;
5719
0
          }
5720
0
        }
5721
0
      }
5722
0
      temp.setObject(*returnArray);
5723
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->transportStats_id, temp, JSPROP_ENUMERATE)) {
5724
0
        return false;
5725
0
      }
5726
0
      break;
5727
0
    } while(false);
5728
0
  }
5729
0
5730
0
  if (mTrickledIceCandidateStats.WasPassed()) {
5731
0
    do {
5732
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
5733
0
      JS::Rooted<JS::Value> temp(cx);
5734
0
      Sequence<RTCIceCandidateStats> const & currentValue = mTrickledIceCandidateStats.InternalValue();
5735
0
5736
0
      uint32_t length = currentValue.Length();
5737
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
5738
0
      if (!returnArray) {
5739
0
        return false;
5740
0
      }
5741
0
      // Scope for 'tmp'
5742
0
      {
5743
0
        JS::Rooted<JS::Value> tmp(cx);
5744
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
5745
0
          // Control block to let us common up the JS_DefineElement calls when there
5746
0
          // are different ways to succeed at wrapping the object.
5747
0
          do {
5748
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
5749
0
              return false;
5750
0
            }
5751
0
            break;
5752
0
          } while (false);
5753
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
5754
0
                                JSPROP_ENUMERATE)) {
5755
0
            return false;
5756
0
          }
5757
0
        }
5758
0
      }
5759
0
      temp.setObject(*returnArray);
5760
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->trickledIceCandidateStats_id, temp, JSPROP_ENUMERATE)) {
5761
0
        return false;
5762
0
      }
5763
0
      break;
5764
0
    } while(false);
5765
0
  }
5766
0
5767
0
  return true;
5768
0
}
5769
5770
bool
5771
RTCStatsReportInternal::ToJSON(nsAString& aJSON) const
5772
0
{
5773
0
  AutoJSAPI jsapi;
5774
0
  jsapi.Init();
5775
0
  JSContext *cx = jsapi.cx();
5776
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
5777
0
  // because we'll only be creating objects, in ways that have no
5778
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
5779
0
  // which likewise guarantees no side-effects for the sorts of
5780
0
  // things we will pass it.
5781
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
5782
0
  JS::Rooted<JS::Value> val(cx);
5783
0
  if (!ToObjectInternal(cx, &val)) {
5784
0
    return false;
5785
0
  }
5786
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
5787
0
  return StringifyToJSON(cx, obj, aJSON);
5788
0
}
5789
5790
void
5791
RTCStatsReportInternal::TraceDictionary(JSTracer* trc)
5792
0
{
5793
0
}
5794
5795
RTCStatsReportInternal&
5796
RTCStatsReportInternal::operator=(const RTCStatsReportInternal& aOther)
5797
0
{
5798
0
  DictionaryBase::operator=(aOther);
5799
0
  mClosed.Reset();
5800
0
  if (aOther.mClosed.WasPassed()) {
5801
0
    mClosed.Construct(aOther.mClosed.Value());
5802
0
  }
5803
0
  mCodecStats.Reset();
5804
0
  if (aOther.mCodecStats.WasPassed()) {
5805
0
    mCodecStats.Construct(aOther.mCodecStats.Value());
5806
0
  }
5807
0
  mIceCandidatePairStats.Reset();
5808
0
  if (aOther.mIceCandidatePairStats.WasPassed()) {
5809
0
    mIceCandidatePairStats.Construct(aOther.mIceCandidatePairStats.Value());
5810
0
  }
5811
0
  mIceCandidateStats.Reset();
5812
0
  if (aOther.mIceCandidateStats.WasPassed()) {
5813
0
    mIceCandidateStats.Construct(aOther.mIceCandidateStats.Value());
5814
0
  }
5815
0
  mIceComponentStats.Reset();
5816
0
  if (aOther.mIceComponentStats.WasPassed()) {
5817
0
    mIceComponentStats.Construct(aOther.mIceComponentStats.Value());
5818
0
  }
5819
0
  mIceRestarts.Reset();
5820
0
  if (aOther.mIceRestarts.WasPassed()) {
5821
0
    mIceRestarts.Construct(aOther.mIceRestarts.Value());
5822
0
  }
5823
0
  mIceRollbacks.Reset();
5824
0
  if (aOther.mIceRollbacks.WasPassed()) {
5825
0
    mIceRollbacks.Construct(aOther.mIceRollbacks.Value());
5826
0
  }
5827
0
  mInboundRTPStreamStats.Reset();
5828
0
  if (aOther.mInboundRTPStreamStats.WasPassed()) {
5829
0
    mInboundRTPStreamStats.Construct(aOther.mInboundRTPStreamStats.Value());
5830
0
  }
5831
0
  mLocalSdp.Reset();
5832
0
  if (aOther.mLocalSdp.WasPassed()) {
5833
0
    mLocalSdp.Construct(aOther.mLocalSdp.Value());
5834
0
  }
5835
0
  mMediaStreamStats.Reset();
5836
0
  if (aOther.mMediaStreamStats.WasPassed()) {
5837
0
    mMediaStreamStats.Construct(aOther.mMediaStreamStats.Value());
5838
0
  }
5839
0
  mMediaStreamTrackStats.Reset();
5840
0
  if (aOther.mMediaStreamTrackStats.WasPassed()) {
5841
0
    mMediaStreamTrackStats.Construct(aOther.mMediaStreamTrackStats.Value());
5842
0
  }
5843
0
  mOfferer.Reset();
5844
0
  if (aOther.mOfferer.WasPassed()) {
5845
0
    mOfferer.Construct(aOther.mOfferer.Value());
5846
0
  }
5847
0
  mOutboundRTPStreamStats.Reset();
5848
0
  if (aOther.mOutboundRTPStreamStats.WasPassed()) {
5849
0
    mOutboundRTPStreamStats.Construct(aOther.mOutboundRTPStreamStats.Value());
5850
0
  }
5851
0
  mPcid = aOther.mPcid;
5852
0
  mRawLocalCandidates.Reset();
5853
0
  if (aOther.mRawLocalCandidates.WasPassed()) {
5854
0
    mRawLocalCandidates.Construct(aOther.mRawLocalCandidates.Value());
5855
0
  }
5856
0
  mRawRemoteCandidates.Reset();
5857
0
  if (aOther.mRawRemoteCandidates.WasPassed()) {
5858
0
    mRawRemoteCandidates.Construct(aOther.mRawRemoteCandidates.Value());
5859
0
  }
5860
0
  mRemoteSdp.Reset();
5861
0
  if (aOther.mRemoteSdp.WasPassed()) {
5862
0
    mRemoteSdp.Construct(aOther.mRemoteSdp.Value());
5863
0
  }
5864
0
  mRtpContributingSourceStats.Reset();
5865
0
  if (aOther.mRtpContributingSourceStats.WasPassed()) {
5866
0
    mRtpContributingSourceStats.Construct(aOther.mRtpContributingSourceStats.Value());
5867
0
  }
5868
0
  mTimestamp.Reset();
5869
0
  if (aOther.mTimestamp.WasPassed()) {
5870
0
    mTimestamp.Construct(aOther.mTimestamp.Value());
5871
0
  }
5872
0
  mTransportStats.Reset();
5873
0
  if (aOther.mTransportStats.WasPassed()) {
5874
0
    mTransportStats.Construct(aOther.mTransportStats.Value());
5875
0
  }
5876
0
  mTrickledIceCandidateStats.Reset();
5877
0
  if (aOther.mTrickledIceCandidateStats.WasPassed()) {
5878
0
    mTrickledIceCandidateStats.Construct(aOther.mTrickledIceCandidateStats.Value());
5879
0
  }
5880
0
  return *this;
5881
0
}
5882
5883
namespace binding_detail {
5884
} // namespace binding_detail
5885
5886
5887
namespace RTCStatsReport_Binding {
5888
5889
namespace MaplikeHelpers {
5890
void
5891
Clear(mozilla::dom::RTCStatsReport* self, ErrorResult& aRv)
5892
0
{
5893
0
  MOZ_ASSERT(self);
5894
0
  AutoJSAPI jsapi;
5895
0
  jsapi.Init();
5896
0
  JSContext* cx = jsapi.cx();
5897
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
5898
0
  // all we want is to wrap into _some_ scope and then unwrap to find
5899
0
  // the reflector, and wrapping has no side-effects.
5900
0
  JSAutoRealm tempRealm(cx, UnprivilegedJunkScopeOrWorkerGlobal());
5901
0
  JS::Rooted<JS::Value> v(cx);
5902
0
  if(!ToJSValue(cx, self, &v)) {
5903
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
5904
0
    return;
5905
0
  }
5906
0
  // This is a reflector, but due to trying to name things
5907
0
  // similarly across method generators, it's called obj here.
5908
0
  JS::Rooted<JSObject*> obj(cx);
5909
0
  obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
5910
0
  JSAutoRealm reflectorRealm(cx, obj);
5911
0
5912
0
  JS::Rooted<JSObject*> backingObj(cx);
5913
0
  bool created = false;
5914
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
5915
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
5916
0
    return;
5917
0
  }
5918
0
  if (created) {
5919
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
5920
0
  }
5921
0
  if (!JS::MapClear(cx, backingObj)) {
5922
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
5923
0
    return;
5924
0
  }
5925
0
  return;
5926
0
}
5927
bool
5928
Delete(mozilla::dom::RTCStatsReport* self, const nsAString& aKey, ErrorResult& aRv)
5929
0
{
5930
0
  MOZ_ASSERT(self);
5931
0
  AutoJSAPI jsapi;
5932
0
  jsapi.Init();
5933
0
  JSContext* cx = jsapi.cx();
5934
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
5935
0
  // all we want is to wrap into _some_ scope and then unwrap to find
5936
0
  // the reflector, and wrapping has no side-effects.
5937
0
  JSAutoRealm tempRealm(cx, UnprivilegedJunkScopeOrWorkerGlobal());
5938
0
  JS::Rooted<JS::Value> v(cx);
5939
0
  if(!ToJSValue(cx, self, &v)) {
5940
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
5941
0
    return false;
5942
0
  }
5943
0
  // This is a reflector, but due to trying to name things
5944
0
  // similarly across method generators, it's called obj here.
5945
0
  JS::Rooted<JSObject*> obj(cx);
5946
0
  obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
5947
0
  JSAutoRealm reflectorRealm(cx, obj);
5948
0
  bool aRetVal;
5949
0
  JS::AutoValueVector argv(cx);
5950
0
  if (!argv.resize(1)) {
5951
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
5952
0
    return false;
5953
0
  }
5954
0
  do {
5955
0
    nsString mutableStr(aKey);
5956
0
    if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
5957
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
5958
0
      return false;
5959
0
    }
5960
0
    break;
5961
0
  } while (false);
5962
0
5963
0
  JS::Rooted<JSObject*> backingObj(cx);
5964
0
  bool created = false;
5965
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
5966
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
5967
0
    return false;
5968
0
  }
5969
0
  if (created) {
5970
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
5971
0
  }
5972
0
  if (!JS::MapDelete(cx, backingObj, argv[0], &aRetVal)) {
5973
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
5974
0
    return false;
5975
0
  }
5976
0
  return aRetVal;
5977
0
}
5978
bool
5979
Has(mozilla::dom::RTCStatsReport* self, const nsAString& aKey, ErrorResult& aRv)
5980
0
{
5981
0
  MOZ_ASSERT(self);
5982
0
  AutoJSAPI jsapi;
5983
0
  jsapi.Init();
5984
0
  JSContext* cx = jsapi.cx();
5985
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
5986
0
  // all we want is to wrap into _some_ scope and then unwrap to find
5987
0
  // the reflector, and wrapping has no side-effects.
5988
0
  JSAutoRealm tempRealm(cx, UnprivilegedJunkScopeOrWorkerGlobal());
5989
0
  JS::Rooted<JS::Value> v(cx);
5990
0
  if(!ToJSValue(cx, self, &v)) {
5991
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
5992
0
    return false;
5993
0
  }
5994
0
  // This is a reflector, but due to trying to name things
5995
0
  // similarly across method generators, it's called obj here.
5996
0
  JS::Rooted<JSObject*> obj(cx);
5997
0
  obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
5998
0
  JSAutoRealm reflectorRealm(cx, obj);
5999
0
  bool aRetVal;
6000
0
  JS::AutoValueVector argv(cx);
6001
0
  if (!argv.resize(1)) {
6002
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
6003
0
    return false;
6004
0
  }
6005
0
  do {
6006
0
    nsString mutableStr(aKey);
6007
0
    if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
6008
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
6009
0
      return false;
6010
0
    }
6011
0
    break;
6012
0
  } while (false);
6013
0
6014
0
  JS::Rooted<JSObject*> backingObj(cx);
6015
0
  bool created = false;
6016
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6017
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
6018
0
    return false;
6019
0
  }
6020
0
  if (created) {
6021
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
6022
0
  }
6023
0
  if (!JS::MapHas(cx, backingObj, argv[0], &aRetVal)) {
6024
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
6025
0
    return false;
6026
0
  }
6027
0
  return aRetVal;
6028
0
}
6029
void
6030
Set(mozilla::dom::RTCStatsReport* self, const nsAString& aKey, JS::Handle<JSObject*> aValue, ErrorResult& aRv)
6031
0
{
6032
0
  MOZ_ASSERT(self);
6033
0
  AutoJSAPI jsapi;
6034
0
  jsapi.Init();
6035
0
  JSContext* cx = jsapi.cx();
6036
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
6037
0
  // all we want is to wrap into _some_ scope and then unwrap to find
6038
0
  // the reflector, and wrapping has no side-effects.
6039
0
  JSAutoRealm tempRealm(cx, UnprivilegedJunkScopeOrWorkerGlobal());
6040
0
  JS::Rooted<JS::Value> v(cx);
6041
0
  if(!ToJSValue(cx, self, &v)) {
6042
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
6043
0
    return;
6044
0
  }
6045
0
  // This is a reflector, but due to trying to name things
6046
0
  // similarly across method generators, it's called obj here.
6047
0
  JS::Rooted<JSObject*> obj(cx);
6048
0
  obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
6049
0
  JSAutoRealm reflectorRealm(cx, obj);
6050
0
  JS::AutoValueVector argv(cx);
6051
0
  if (!argv.resize(2)) {
6052
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
6053
0
    return;
6054
0
  }
6055
0
  do {
6056
0
    JS::ExposeObjectToActiveJS(aValue);
6057
0
    argv[1].setObject(*aValue);
6058
0
    if (!MaybeWrapObjectValue(cx, argv[1])) {
6059
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
6060
0
      return;
6061
0
    }
6062
0
    break;
6063
0
  } while (false);
6064
0
6065
0
  do {
6066
0
    nsString mutableStr(aKey);
6067
0
    if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
6068
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
6069
0
      return;
6070
0
    }
6071
0
    break;
6072
0
  } while (false);
6073
0
6074
0
  JS::Rooted<JSObject*> backingObj(cx);
6075
0
  bool created = false;
6076
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6077
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
6078
0
    return;
6079
0
  }
6080
0
  if (created) {
6081
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
6082
0
  }
6083
0
  if (!JS::MapSet(cx, backingObj, argv[0], argv[1])) {
6084
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
6085
0
    return;
6086
0
  }
6087
0
  return;
6088
0
}
6089
} // namespace MaplikeHelpers
6090
6091
MOZ_CAN_RUN_SCRIPT static bool
6092
get_mozPcid(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCStatsReport* self, JSJitGetterCallArgs args)
6093
0
{
6094
0
  AUTO_PROFILER_LABEL_FAST("get RTCStatsReport.mozPcid", DOM, cx);
6095
0
6096
0
  Maybe<JS::Rooted<JSObject*> > unwrappedObj;
6097
0
  bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
6098
0
  if (objIsXray) {
6099
0
    unwrappedObj.emplace(cx, obj);
6100
0
  }
6101
0
  if (objIsXray) {
6102
0
    unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
6103
0
    if (!unwrappedObj.ref()) {
6104
0
      return false;
6105
0
    }
6106
0
  }
6107
0
  FastErrorResult rv;
6108
0
  DOMString result;
6109
0
  self->GetMozPcid(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)));
6110
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
6111
0
    return false;
6112
0
  }
6113
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
6114
0
  if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
6115
0
    return false;
6116
0
  }
6117
0
  return true;
6118
0
}
6119
6120
static const JSJitInfo mozPcid_getterinfo = {
6121
  { (JSJitGetterOp)get_mozPcid },
6122
  { prototypes::id::RTCStatsReport },
6123
  { PrototypeTraits<prototypes::id::RTCStatsReport>::Depth },
6124
  JSJitInfo::Getter,
6125
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
6126
  JSVAL_TYPE_STRING,  /* returnType.  Not relevant for setters. */
6127
  false,  /* isInfallible. False in setters. */
6128
  false,  /* isMovable.  Not relevant for setters. */
6129
  false, /* isEliminatable.  Not relevant for setters. */
6130
  false, /* isAlwaysInSlot.  Only relevant for getters. */
6131
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
6132
  false,  /* isTypedMethod.  Only relevant for methods. */
6133
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
6134
};
6135
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6136
static_assert(0 < 2, "There is no slot for us");
6137
6138
MOZ_CAN_RUN_SCRIPT static bool
6139
get_size(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCStatsReport* self, JSJitGetterCallArgs args)
6140
0
{
6141
0
  AUTO_PROFILER_LABEL_FAST("get RTCStatsReport.size", DOM, cx);
6142
0
6143
0
  JS::Rooted<JSObject*> backingObj(cx);
6144
0
  bool created = false;
6145
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6146
0
    return false;
6147
0
  }
6148
0
  if (created) {
6149
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
6150
0
  }
6151
0
  uint32_t result = JS::MapSize(cx, backingObj);
6152
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
6153
0
  args.rval().setNumber(result);
6154
0
  return true;
6155
0
}
6156
6157
static const JSJitInfo size_getterinfo = {
6158
  { (JSJitGetterOp)get_size },
6159
  { prototypes::id::RTCStatsReport },
6160
  { PrototypeTraits<prototypes::id::RTCStatsReport>::Depth },
6161
  JSJitInfo::Getter,
6162
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
6163
  JSVAL_TYPE_DOUBLE,  /* returnType.  Not relevant for setters. */
6164
  false,  /* isInfallible. False in setters. */
6165
  false,  /* isMovable.  Not relevant for setters. */
6166
  false, /* isEliminatable.  Not relevant for setters. */
6167
  false, /* isAlwaysInSlot.  Only relevant for getters. */
6168
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
6169
  false,  /* isTypedMethod.  Only relevant for methods. */
6170
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
6171
};
6172
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6173
static_assert(0 < 2, "There is no slot for us");
6174
6175
MOZ_CAN_RUN_SCRIPT static bool
6176
entries(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCStatsReport* self, const JSJitMethodCallArgs& args)
6177
0
{
6178
0
  AUTO_PROFILER_LABEL_FAST("RTCStatsReport.entries", DOM, cx);
6179
0
6180
0
  Maybe<JS::Rooted<JSObject*> > unwrappedObj;
6181
0
  bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
6182
0
  if (objIsXray) {
6183
0
    unwrappedObj.emplace(cx, obj);
6184
0
  }
6185
0
  if (objIsXray) {
6186
0
    unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
6187
0
    if (!unwrappedObj.ref()) {
6188
0
      return false;
6189
0
    }
6190
0
  }
6191
0
  JS::Rooted<JSObject*> backingObj(cx);
6192
0
  bool created = false;
6193
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6194
0
    return false;
6195
0
  }
6196
0
  if (created) {
6197
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
6198
0
  }
6199
0
  // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
6200
0
  // after bug 1023984 is fixed.
6201
0
  if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
6202
0
    JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
6203
0
    return false;
6204
0
  }
6205
0
  JS::Rooted<JSObject*> result(cx);
6206
0
  JS::Rooted<JS::Value> v(cx);
6207
0
  if (!JS::MapEntries(cx, backingObj, &v)) {
6208
0
    return false;
6209
0
  }
6210
0
  result = &v.toObject();
6211
0
  JS::ExposeObjectToActiveJS(result);
6212
0
  args.rval().setObject(*result);
6213
0
  if (!MaybeWrapObjectValue(cx, args.rval())) {
6214
0
    return false;
6215
0
  }
6216
0
  return true;
6217
0
}
6218
6219
static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
6220
static const JSTypedMethodJitInfo entries_methodinfo = {
6221
  {
6222
    { (JSJitGetterOp)entries },
6223
    { prototypes::id::RTCStatsReport },
6224
    { PrototypeTraits<prototypes::id::RTCStatsReport>::Depth },
6225
    JSJitInfo::Method,
6226
    JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
6227
    JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
6228
    false,  /* isInfallible. False in setters. */
6229
    false,  /* isMovable.  Not relevant for setters. */
6230
    false, /* isEliminatable.  Not relevant for setters. */
6231
    false, /* isAlwaysInSlot.  Only relevant for getters. */
6232
    false, /* isLazilyCachedInSlot.  Only relevant for getters. */
6233
    true,  /* isTypedMethod.  Only relevant for methods. */
6234
    0   /* Reserved slot index, if we're stored in a slot, else 0. */
6235
  },
6236
  entries_methodinfo_argTypes
6237
};
6238
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6239
static_assert(0 < 2, "There is no slot for us");
6240
6241
MOZ_CAN_RUN_SCRIPT static bool
6242
keys(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCStatsReport* self, const JSJitMethodCallArgs& args)
6243
0
{
6244
0
  AUTO_PROFILER_LABEL_FAST("RTCStatsReport.keys", DOM, cx);
6245
0
6246
0
  Maybe<JS::Rooted<JSObject*> > unwrappedObj;
6247
0
  bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
6248
0
  if (objIsXray) {
6249
0
    unwrappedObj.emplace(cx, obj);
6250
0
  }
6251
0
  if (objIsXray) {
6252
0
    unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
6253
0
    if (!unwrappedObj.ref()) {
6254
0
      return false;
6255
0
    }
6256
0
  }
6257
0
  JS::Rooted<JSObject*> backingObj(cx);
6258
0
  bool created = false;
6259
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6260
0
    return false;
6261
0
  }
6262
0
  if (created) {
6263
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
6264
0
  }
6265
0
  // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
6266
0
  // after bug 1023984 is fixed.
6267
0
  if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
6268
0
    JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
6269
0
    return false;
6270
0
  }
6271
0
  JS::Rooted<JSObject*> result(cx);
6272
0
  JS::Rooted<JS::Value> v(cx);
6273
0
  if (!JS::MapKeys(cx, backingObj, &v)) {
6274
0
    return false;
6275
0
  }
6276
0
  result = &v.toObject();
6277
0
  JS::ExposeObjectToActiveJS(result);
6278
0
  args.rval().setObject(*result);
6279
0
  if (!MaybeWrapObjectValue(cx, args.rval())) {
6280
0
    return false;
6281
0
  }
6282
0
  return true;
6283
0
}
6284
6285
static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
6286
static const JSTypedMethodJitInfo keys_methodinfo = {
6287
  {
6288
    { (JSJitGetterOp)keys },
6289
    { prototypes::id::RTCStatsReport },
6290
    { PrototypeTraits<prototypes::id::RTCStatsReport>::Depth },
6291
    JSJitInfo::Method,
6292
    JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
6293
    JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
6294
    false,  /* isInfallible. False in setters. */
6295
    false,  /* isMovable.  Not relevant for setters. */
6296
    false, /* isEliminatable.  Not relevant for setters. */
6297
    false, /* isAlwaysInSlot.  Only relevant for getters. */
6298
    false, /* isLazilyCachedInSlot.  Only relevant for getters. */
6299
    true,  /* isTypedMethod.  Only relevant for methods. */
6300
    0   /* Reserved slot index, if we're stored in a slot, else 0. */
6301
  },
6302
  keys_methodinfo_argTypes
6303
};
6304
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6305
static_assert(0 < 2, "There is no slot for us");
6306
6307
MOZ_CAN_RUN_SCRIPT static bool
6308
values(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCStatsReport* self, const JSJitMethodCallArgs& args)
6309
0
{
6310
0
  AUTO_PROFILER_LABEL_FAST("RTCStatsReport.values", DOM, cx);
6311
0
6312
0
  Maybe<JS::Rooted<JSObject*> > unwrappedObj;
6313
0
  bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
6314
0
  if (objIsXray) {
6315
0
    unwrappedObj.emplace(cx, obj);
6316
0
  }
6317
0
  if (objIsXray) {
6318
0
    unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
6319
0
    if (!unwrappedObj.ref()) {
6320
0
      return false;
6321
0
    }
6322
0
  }
6323
0
  JS::Rooted<JSObject*> backingObj(cx);
6324
0
  bool created = false;
6325
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6326
0
    return false;
6327
0
  }
6328
0
  if (created) {
6329
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
6330
0
  }
6331
0
  // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
6332
0
  // after bug 1023984 is fixed.
6333
0
  if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
6334
0
    JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
6335
0
    return false;
6336
0
  }
6337
0
  JS::Rooted<JSObject*> result(cx);
6338
0
  JS::Rooted<JS::Value> v(cx);
6339
0
  if (!JS::MapValues(cx, backingObj, &v)) {
6340
0
    return false;
6341
0
  }
6342
0
  result = &v.toObject();
6343
0
  JS::ExposeObjectToActiveJS(result);
6344
0
  args.rval().setObject(*result);
6345
0
  if (!MaybeWrapObjectValue(cx, args.rval())) {
6346
0
    return false;
6347
0
  }
6348
0
  return true;
6349
0
}
6350
6351
static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
6352
static const JSTypedMethodJitInfo values_methodinfo = {
6353
  {
6354
    { (JSJitGetterOp)values },
6355
    { prototypes::id::RTCStatsReport },
6356
    { PrototypeTraits<prototypes::id::RTCStatsReport>::Depth },
6357
    JSJitInfo::Method,
6358
    JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
6359
    JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
6360
    false,  /* isInfallible. False in setters. */
6361
    false,  /* isMovable.  Not relevant for setters. */
6362
    false, /* isEliminatable.  Not relevant for setters. */
6363
    false, /* isAlwaysInSlot.  Only relevant for getters. */
6364
    false, /* isLazilyCachedInSlot.  Only relevant for getters. */
6365
    true,  /* isTypedMethod.  Only relevant for methods. */
6366
    0   /* Reserved slot index, if we're stored in a slot, else 0. */
6367
  },
6368
  values_methodinfo_argTypes
6369
};
6370
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6371
static_assert(0 < 2, "There is no slot for us");
6372
6373
MOZ_CAN_RUN_SCRIPT static bool
6374
forEach(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCStatsReport* self, const JSJitMethodCallArgs& args)
6375
0
{
6376
0
  AUTO_PROFILER_LABEL_FAST("RTCStatsReport.forEach", DOM, cx);
6377
0
6378
0
  Maybe<JS::Rooted<JSObject*> > unwrappedObj;
6379
0
  bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
6380
0
  if (objIsXray) {
6381
0
    unwrappedObj.emplace(cx, obj);
6382
0
  }
6383
0
  JS::Rooted<JSObject*> arg0(cx);
6384
0
  if (args.get(0).isObject()) {
6385
0
#ifdef __clang__
6386
0
#pragma clang diagnostic push
6387
0
#pragma clang diagnostic ignored "-Wunreachable-code"
6388
0
#pragma clang diagnostic ignored "-Wunreachable-code-return"
6389
0
#endif // __clang__
6390
0
    if ((true) && !CallerSubsumes(args.get(0))) {
6391
0
      ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "argument 1 of RTCStatsReport.forEach");
6392
0
      return false;
6393
0
    }
6394
0
#ifdef __clang__
6395
0
#pragma clang diagnostic pop
6396
0
#endif // __clang__
6397
0
    arg0 = &args.get(0).toObject();
6398
0
  } else {
6399
0
    ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of RTCStatsReport.forEach");
6400
0
    return false;
6401
0
  }
6402
0
  JS::Rooted<JS::Value> arg1(cx);
6403
0
  if (args.hasDefined(1)) {
6404
0
#ifdef __clang__
6405
0
#pragma clang diagnostic push
6406
0
#pragma clang diagnostic ignored "-Wunreachable-code"
6407
0
#pragma clang diagnostic ignored "-Wunreachable-code-return"
6408
0
#endif // __clang__
6409
0
    if ((true) && !CallerSubsumes(args.get(1))) {
6410
0
      ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "argument 2 of RTCStatsReport.forEach");
6411
0
      return false;
6412
0
    }
6413
0
#ifdef __clang__
6414
0
#pragma clang diagnostic pop
6415
0
#endif // __clang__
6416
0
    arg1 = args.get(1);
6417
0
  } else {
6418
0
    arg1 = JS::UndefinedValue();
6419
0
  }
6420
0
  if (objIsXray) {
6421
0
    unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
6422
0
    if (!unwrappedObj.ref()) {
6423
0
      return false;
6424
0
    }
6425
0
  }
6426
0
  JS::Rooted<JSObject*> backingObj(cx);
6427
0
  bool created = false;
6428
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6429
0
    return false;
6430
0
  }
6431
0
  if (created) {
6432
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
6433
0
  }
6434
0
  // Create a wrapper function.
6435
0
  JSFunction* func = js::NewFunctionWithReserved(cx, ForEachHandler, 3, 0, nullptr);
6436
0
  if (!func) {
6437
0
    return false;
6438
0
  }
6439
0
  JS::Rooted<JSObject*> funcObj(cx, JS_GetFunctionObject(func));
6440
0
  JS::Rooted<JS::Value> funcVal(cx, JS::ObjectValue(*funcObj));
6441
0
  js::SetFunctionNativeReserved(funcObj, FOREACH_CALLBACK_SLOT,
6442
0
                                JS::ObjectValue(*arg0));
6443
0
  js::SetFunctionNativeReserved(funcObj, FOREACH_MAPLIKEORSETLIKEOBJ_SLOT,
6444
0
                                JS::ObjectValue(*obj));
6445
0
  if (!JS::MapForEach(cx, backingObj, funcVal, arg1)) {
6446
0
    return false;
6447
0
  }
6448
0
  args.rval().setUndefined();
6449
0
  return true;
6450
0
}
6451
6452
static const JSJitInfo forEach_methodinfo = {
6453
  { (JSJitGetterOp)forEach },
6454
  { prototypes::id::RTCStatsReport },
6455
  { PrototypeTraits<prototypes::id::RTCStatsReport>::Depth },
6456
  JSJitInfo::Method,
6457
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
6458
  JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
6459
  false,  /* isInfallible. False in setters. */
6460
  false,  /* isMovable.  Not relevant for setters. */
6461
  false, /* isEliminatable.  Not relevant for setters. */
6462
  false, /* isAlwaysInSlot.  Only relevant for getters. */
6463
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
6464
  false,  /* isTypedMethod.  Only relevant for methods. */
6465
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
6466
};
6467
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6468
static_assert(0 < 2, "There is no slot for us");
6469
6470
MOZ_CAN_RUN_SCRIPT static bool
6471
has(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCStatsReport* self, const JSJitMethodCallArgs& args)
6472
0
{
6473
0
  AUTO_PROFILER_LABEL_FAST("RTCStatsReport.has", DOM, cx);
6474
0
6475
0
  Maybe<JS::Rooted<JSObject*> > unwrappedObj;
6476
0
  bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
6477
0
  if (objIsXray) {
6478
0
    unwrappedObj.emplace(cx, obj);
6479
0
  }
6480
0
  binding_detail::FakeString arg0;
6481
0
  if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
6482
0
    return false;
6483
0
  }
6484
0
  if (objIsXray) {
6485
0
    unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
6486
0
    if (!unwrappedObj.ref()) {
6487
0
      return false;
6488
0
    }
6489
0
  }
6490
0
  JS::Rooted<JSObject*> backingObj(cx);
6491
0
  bool created = false;
6492
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6493
0
    return false;
6494
0
  }
6495
0
  if (created) {
6496
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
6497
0
  }
6498
0
  JS::Rooted<JS::Value> arg0Val(cx);
6499
0
  if (!ToJSValue(cx, arg0, &arg0Val)) {
6500
0
    return false;
6501
0
  }
6502
0
  bool result;
6503
0
  if (!JS::MapHas(cx, backingObj, arg0Val, &result)) {
6504
0
    return false;
6505
0
  }
6506
0
  args.rval().setBoolean(result);
6507
0
  return true;
6508
0
}
6509
6510
static const JSJitInfo::ArgType has_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
6511
static const JSTypedMethodJitInfo has_methodinfo = {
6512
  {
6513
    { (JSJitGetterOp)has },
6514
    { prototypes::id::RTCStatsReport },
6515
    { PrototypeTraits<prototypes::id::RTCStatsReport>::Depth },
6516
    JSJitInfo::Method,
6517
    JSJitInfo::AliasDOMSets, /* aliasSet.  Not relevant for setters. */
6518
    JSVAL_TYPE_BOOLEAN,  /* returnType.  Not relevant for setters. */
6519
    false,  /* isInfallible. False in setters. */
6520
    false,  /* isMovable.  Not relevant for setters. */
6521
    false, /* isEliminatable.  Not relevant for setters. */
6522
    false, /* isAlwaysInSlot.  Only relevant for getters. */
6523
    false, /* isLazilyCachedInSlot.  Only relevant for getters. */
6524
    true,  /* isTypedMethod.  Only relevant for methods. */
6525
    0   /* Reserved slot index, if we're stored in a slot, else 0. */
6526
  },
6527
  has_methodinfo_argTypes
6528
};
6529
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6530
static_assert(0 < 2, "There is no slot for us");
6531
6532
MOZ_CAN_RUN_SCRIPT static bool
6533
__clear(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCStatsReport* self, const JSJitMethodCallArgs& args)
6534
0
{
6535
0
  AUTO_PROFILER_LABEL_FAST("RTCStatsReport.__clear", DOM, cx);
6536
0
6537
0
  Maybe<JS::Rooted<JSObject*> > unwrappedObj;
6538
0
  bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
6539
0
  if (objIsXray) {
6540
0
    unwrappedObj.emplace(cx, obj);
6541
0
  }
6542
0
  if (objIsXray) {
6543
0
    unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
6544
0
    if (!unwrappedObj.ref()) {
6545
0
      return false;
6546
0
    }
6547
0
  }
6548
0
  JS::Rooted<JSObject*> backingObj(cx);
6549
0
  bool created = false;
6550
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6551
0
    return false;
6552
0
  }
6553
0
  if (created) {
6554
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
6555
0
  }
6556
0
  if (!JS::MapClear(cx, backingObj)) {
6557
0
    return false;
6558
0
  }
6559
0
  args.rval().setUndefined();
6560
0
  return true;
6561
0
}
6562
6563
static const JSJitInfo __clear_methodinfo = {
6564
  { (JSJitGetterOp)__clear },
6565
  { prototypes::id::RTCStatsReport },
6566
  { PrototypeTraits<prototypes::id::RTCStatsReport>::Depth },
6567
  JSJitInfo::Method,
6568
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
6569
  JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
6570
  false,  /* isInfallible. False in setters. */
6571
  false,  /* isMovable.  Not relevant for setters. */
6572
  false, /* isEliminatable.  Not relevant for setters. */
6573
  false, /* isAlwaysInSlot.  Only relevant for getters. */
6574
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
6575
  false,  /* isTypedMethod.  Only relevant for methods. */
6576
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
6577
};
6578
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6579
static_assert(0 < 2, "There is no slot for us");
6580
6581
MOZ_CAN_RUN_SCRIPT static bool
6582
__delete(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCStatsReport* self, const JSJitMethodCallArgs& args)
6583
0
{
6584
0
  AUTO_PROFILER_LABEL_FAST("RTCStatsReport.__delete", DOM, cx);
6585
0
6586
0
  Maybe<JS::Rooted<JSObject*> > unwrappedObj;
6587
0
  bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
6588
0
  if (objIsXray) {
6589
0
    unwrappedObj.emplace(cx, obj);
6590
0
  }
6591
0
  binding_detail::FakeString arg0;
6592
0
  if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
6593
0
    return false;
6594
0
  }
6595
0
  if (objIsXray) {
6596
0
    unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
6597
0
    if (!unwrappedObj.ref()) {
6598
0
      return false;
6599
0
    }
6600
0
  }
6601
0
  JS::Rooted<JSObject*> backingObj(cx);
6602
0
  bool created = false;
6603
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6604
0
    return false;
6605
0
  }
6606
0
  if (created) {
6607
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
6608
0
  }
6609
0
  JS::Rooted<JS::Value> arg0Val(cx);
6610
0
  if (!ToJSValue(cx, arg0, &arg0Val)) {
6611
0
    return false;
6612
0
  }
6613
0
  bool result;
6614
0
  if (!JS::MapDelete(cx, backingObj, arg0Val, &result)) {
6615
0
    return false;
6616
0
  }
6617
0
  args.rval().setBoolean(result);
6618
0
  return true;
6619
0
}
6620
6621
static const JSJitInfo __delete_methodinfo = {
6622
  { (JSJitGetterOp)__delete },
6623
  { prototypes::id::RTCStatsReport },
6624
  { PrototypeTraits<prototypes::id::RTCStatsReport>::Depth },
6625
  JSJitInfo::Method,
6626
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
6627
  JSVAL_TYPE_BOOLEAN,  /* returnType.  Not relevant for setters. */
6628
  false,  /* isInfallible. False in setters. */
6629
  false,  /* isMovable.  Not relevant for setters. */
6630
  false, /* isEliminatable.  Not relevant for setters. */
6631
  false, /* isAlwaysInSlot.  Only relevant for getters. */
6632
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
6633
  false,  /* isTypedMethod.  Only relevant for methods. */
6634
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
6635
};
6636
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6637
static_assert(0 < 2, "There is no slot for us");
6638
6639
MOZ_CAN_RUN_SCRIPT static bool
6640
get(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCStatsReport* self, const JSJitMethodCallArgs& args)
6641
0
{
6642
0
  AUTO_PROFILER_LABEL_FAST("RTCStatsReport.get", DOM, cx);
6643
0
6644
0
  Maybe<JS::Rooted<JSObject*> > unwrappedObj;
6645
0
  bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
6646
0
  if (objIsXray) {
6647
0
    unwrappedObj.emplace(cx, obj);
6648
0
  }
6649
0
  binding_detail::FakeString arg0;
6650
0
  if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
6651
0
    return false;
6652
0
  }
6653
0
  if (objIsXray) {
6654
0
    unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
6655
0
    if (!unwrappedObj.ref()) {
6656
0
      return false;
6657
0
    }
6658
0
  }
6659
0
  JS::Rooted<JSObject*> backingObj(cx);
6660
0
  bool created = false;
6661
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6662
0
    return false;
6663
0
  }
6664
0
  if (created) {
6665
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
6666
0
  }
6667
0
  JS::Rooted<JS::Value> arg0Val(cx);
6668
0
  if (!ToJSValue(cx, arg0, &arg0Val)) {
6669
0
    return false;
6670
0
  }
6671
0
  JS::Rooted<JS::Value> result(cx);
6672
0
  if (!JS::MapGet(cx, backingObj, arg0Val, &result)) {
6673
0
    return false;
6674
0
  }
6675
0
  {
6676
0
    JS::ExposeValueToActiveJS(result);
6677
0
    ErrorResult onGetResult;
6678
0
    self->__OnGet(arg0Val, result, onGetResult);
6679
0
    if (onGetResult.MaybeSetPendingException(cx)) {
6680
0
      return false;
6681
0
    }
6682
0
  }
6683
0
  JS::ExposeValueToActiveJS(result);
6684
0
  args.rval().set(result);
6685
0
  if (!MaybeWrapValue(cx, args.rval())) {
6686
0
    return false;
6687
0
  }
6688
0
  return true;
6689
0
}
6690
6691
static const JSJitInfo::ArgType get_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
6692
static const JSTypedMethodJitInfo get_methodinfo = {
6693
  {
6694
    { (JSJitGetterOp)get },
6695
    { prototypes::id::RTCStatsReport },
6696
    { PrototypeTraits<prototypes::id::RTCStatsReport>::Depth },
6697
    JSJitInfo::Method,
6698
    JSJitInfo::AliasDOMSets, /* aliasSet.  Not relevant for setters. */
6699
    JSVAL_TYPE_UNKNOWN,  /* returnType.  Not relevant for setters. */
6700
    false,  /* isInfallible. False in setters. */
6701
    false,  /* isMovable.  Not relevant for setters. */
6702
    false, /* isEliminatable.  Not relevant for setters. */
6703
    false, /* isAlwaysInSlot.  Only relevant for getters. */
6704
    false, /* isLazilyCachedInSlot.  Only relevant for getters. */
6705
    true,  /* isTypedMethod.  Only relevant for methods. */
6706
    0   /* Reserved slot index, if we're stored in a slot, else 0. */
6707
  },
6708
  get_methodinfo_argTypes
6709
};
6710
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6711
static_assert(0 < 2, "There is no slot for us");
6712
6713
MOZ_CAN_RUN_SCRIPT static bool
6714
__set(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCStatsReport* self, const JSJitMethodCallArgs& args)
6715
0
{
6716
0
  AUTO_PROFILER_LABEL_FAST("RTCStatsReport.__set", DOM, cx);
6717
0
6718
0
  Maybe<JS::Rooted<JSObject*> > unwrappedObj;
6719
0
  bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
6720
0
  if (objIsXray) {
6721
0
    unwrappedObj.emplace(cx, obj);
6722
0
  }
6723
0
  binding_detail::FakeString arg0;
6724
0
  if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
6725
0
    return false;
6726
0
  }
6727
0
  JS::Rooted<JSObject*> arg1(cx);
6728
0
  if (args.get(1).isObject()) {
6729
0
#ifdef __clang__
6730
0
#pragma clang diagnostic push
6731
0
#pragma clang diagnostic ignored "-Wunreachable-code"
6732
0
#pragma clang diagnostic ignored "-Wunreachable-code-return"
6733
0
#endif // __clang__
6734
0
    if ((true) && !CallerSubsumes(args.get(1))) {
6735
0
      ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "argument 2 of RTCStatsReport.__set");
6736
0
      return false;
6737
0
    }
6738
0
#ifdef __clang__
6739
0
#pragma clang diagnostic pop
6740
0
#endif // __clang__
6741
0
    arg1 = &args.get(1).toObject();
6742
0
  } else {
6743
0
    ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of RTCStatsReport.__set");
6744
0
    return false;
6745
0
  }
6746
0
  if (objIsXray) {
6747
0
    unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
6748
0
    if (!unwrappedObj.ref()) {
6749
0
      return false;
6750
0
    }
6751
0
  }
6752
0
  JS::Rooted<JSObject*> backingObj(cx);
6753
0
  bool created = false;
6754
0
  if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6755
0
    return false;
6756
0
  }
6757
0
  if (created) {
6758
0
    PreserveWrapper<mozilla::dom::RTCStatsReport>(self);
6759
0
  }
6760
0
  JS::Rooted<JS::Value> arg0Val(cx);
6761
0
  if (!ToJSValue(cx, arg0, &arg0Val)) {
6762
0
    return false;
6763
0
  }
6764
0
  JS::Rooted<JS::Value> arg1Val(cx);
6765
0
  if (!ToJSValue(cx, arg1, &arg1Val)) {
6766
0
    return false;
6767
0
  }
6768
0
  JS::Rooted<JSObject*> result(cx);
6769
0
  if (!JS::MapSet(cx, backingObj, arg0Val, arg1Val)) {
6770
0
    return false;
6771
0
  }
6772
0
  result = obj;
6773
0
  JS::ExposeObjectToActiveJS(result);
6774
0
  args.rval().setObject(*result);
6775
0
  if (!MaybeWrapObjectValue(cx, args.rval())) {
6776
0
    return false;
6777
0
  }
6778
0
  return true;
6779
0
}
6780
6781
static const JSJitInfo __set_methodinfo = {
6782
  { (JSJitGetterOp)__set },
6783
  { prototypes::id::RTCStatsReport },
6784
  { PrototypeTraits<prototypes::id::RTCStatsReport>::Depth },
6785
  JSJitInfo::Method,
6786
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
6787
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
6788
  false,  /* isInfallible. False in setters. */
6789
  false,  /* isMovable.  Not relevant for setters. */
6790
  false, /* isEliminatable.  Not relevant for setters. */
6791
  false, /* isAlwaysInSlot.  Only relevant for getters. */
6792
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
6793
  false,  /* isTypedMethod.  Only relevant for methods. */
6794
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
6795
};
6796
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6797
static_assert(0 < 2, "There is no slot for us");
6798
6799
static bool
6800
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
6801
0
{
6802
0
  mozilla::dom::RTCStatsReport* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::RTCStatsReport>(obj);
6803
0
  // We don't want to preserve if we don't have a wrapper, and we
6804
0
  // obviously can't preserve if we're not initialized.
6805
0
  if (self && self->GetWrapperPreserveColor()) {
6806
0
    PreserveWrapper(self);
6807
0
  }
6808
0
  return true;
6809
0
}
6810
6811
static void
6812
_finalize(js::FreeOp* fop, JSObject* obj)
6813
0
{
6814
0
  mozilla::dom::RTCStatsReport* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::RTCStatsReport>(obj);
6815
0
  if (self) {
6816
0
    ClearWrapper(self, self, obj);
6817
0
    AddForDeferredFinalization<mozilla::dom::RTCStatsReport>(self);
6818
0
  }
6819
0
}
6820
6821
static size_t
6822
_objectMoved(JSObject* obj, JSObject* old)
6823
0
{
6824
0
  mozilla::dom::RTCStatsReport* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::RTCStatsReport>(obj);
6825
0
  if (self) {
6826
0
    UpdateWrapper(self, self, obj, old);
6827
0
  }
6828
0
6829
0
  return 0;
6830
0
}
6831
6832
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
6833
#if defined(__clang__)
6834
#pragma clang diagnostic push
6835
#pragma clang diagnostic ignored "-Wmissing-braces"
6836
#endif
6837
static const JSFunctionSpec sChromeStaticMethods_specs[] = {
6838
  JS_FNSPEC("_create", RTCStatsReport::_Create, nullptr, 2, 0, nullptr),
6839
  JS_FS_END
6840
};
6841
#if defined(__clang__)
6842
#pragma clang diagnostic pop
6843
#endif
6844
6845
6846
static const Prefable<const JSFunctionSpec> sChromeStaticMethods[] = {
6847
  { nullptr, &sChromeStaticMethods_specs[0] },
6848
  { nullptr, nullptr }
6849
};
6850
6851
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
6852
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
6853
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
6854
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
6855
6856
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
6857
#if defined(__clang__)
6858
#pragma clang diagnostic push
6859
#pragma clang diagnostic ignored "-Wmissing-braces"
6860
#endif
6861
static const JSFunctionSpec sMethods_specs[] = {
6862
  JS_FNSPEC("entries", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, 0, nullptr),
6863
  JS_FNSPEC("keys", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, 0, nullptr),
6864
  JS_FNSPEC("values", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, 0, nullptr),
6865
  JS_FNSPEC("forEach", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, 0, nullptr),
6866
  JS_FNSPEC("has", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&has_methodinfo), 1, 0, nullptr),
6867
  JS_FNSPEC("get", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&get_methodinfo), 1, 0, nullptr),
6868
  JS_FS_END
6869
};
6870
#if defined(__clang__)
6871
#pragma clang diagnostic pop
6872
#endif
6873
6874
6875
static const Prefable<const JSFunctionSpec> sMethods[] = {
6876
  { nullptr, &sMethods_specs[0] },
6877
  { nullptr, nullptr }
6878
};
6879
6880
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
6881
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
6882
static_assert(6 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
6883
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
6884
6885
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
6886
#if defined(__clang__)
6887
#pragma clang diagnostic push
6888
#pragma clang diagnostic ignored "-Wmissing-braces"
6889
#endif
6890
static const JSFunctionSpec sChromeMethods_specs[] = {
6891
  JS_FNSPEC("__clear", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&__clear_methodinfo), 0, 0, nullptr),
6892
  JS_FNSPEC("__delete", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&__delete_methodinfo), 1, 0, nullptr),
6893
  JS_FNSPEC("__set", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&__set_methodinfo), 2, 0, nullptr),
6894
  JS_FS_END
6895
};
6896
#if defined(__clang__)
6897
#pragma clang diagnostic pop
6898
#endif
6899
6900
6901
static const Prefable<const JSFunctionSpec> sChromeMethods[] = {
6902
  { nullptr, &sChromeMethods_specs[0] },
6903
  { nullptr, nullptr }
6904
};
6905
6906
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
6907
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
6908
static_assert(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
6909
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
6910
6911
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
6912
#if defined(__clang__)
6913
#pragma clang diagnostic push
6914
#pragma clang diagnostic ignored "-Wmissing-braces"
6915
#endif
6916
static const JSPropertySpec sAttributes_specs[] = {
6917
  { "size", 0, GenericGetter<NormalThisPolicy, ThrowExceptions>, &size_getterinfo, nullptr, nullptr },
6918
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
6919
};
6920
#if defined(__clang__)
6921
#pragma clang diagnostic pop
6922
#endif
6923
6924
6925
static const Prefable<const JSPropertySpec> sAttributes[] = {
6926
  { nullptr, &sAttributes_specs[0] },
6927
  { nullptr, nullptr }
6928
};
6929
6930
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
6931
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
6932
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
6933
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
6934
6935
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
6936
#if defined(__clang__)
6937
#pragma clang diagnostic push
6938
#pragma clang diagnostic ignored "-Wmissing-braces"
6939
#endif
6940
static const JSPropertySpec sChromeAttributes_specs[] = {
6941
  { "mozPcid", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &mozPcid_getterinfo, nullptr, nullptr },
6942
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
6943
};
6944
#if defined(__clang__)
6945
#pragma clang diagnostic pop
6946
#endif
6947
6948
6949
static const Prefable<const JSPropertySpec> sChromeAttributes[] = {
6950
  { nullptr, &sChromeAttributes_specs[0] },
6951
  { nullptr, nullptr }
6952
};
6953
6954
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
6955
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
6956
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
6957
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
6958
6959
6960
static uint16_t sNativeProperties_sortedPropertyIndices[7];
6961
static PropertyInfo sNativeProperties_propertyInfos[7];
6962
6963
static const NativePropertiesN<2> sNativeProperties = {
6964
  false, 0,
6965
  false, 0,
6966
  true,  0 /* sMethods */,
6967
  true,  1 /* sAttributes */,
6968
  false, 0,
6969
  false, 0,
6970
  false, 0,
6971
  0,
6972
  7,
6973
  sNativeProperties_sortedPropertyIndices,
6974
  {
6975
    { sMethods, &sNativeProperties_propertyInfos[0] },
6976
    { sAttributes, &sNativeProperties_propertyInfos[6] }
6977
  }
6978
};
6979
static_assert(7 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
6980
    "We have a property info count that is oversized");
6981
6982
static uint16_t sChromeOnlyNativeProperties_sortedPropertyIndices[5];
6983
static PropertyInfo sChromeOnlyNativeProperties_propertyInfos[5];
6984
6985
static const NativePropertiesN<3> sChromeOnlyNativeProperties = {
6986
  true,  0 /* sChromeStaticMethods */,
6987
  false, 0,
6988
  true,  1 /* sChromeMethods */,
6989
  true,  2 /* sChromeAttributes */,
6990
  false, 0,
6991
  false, 0,
6992
  false, 0,
6993
  0,
6994
  5,
6995
  sChromeOnlyNativeProperties_sortedPropertyIndices,
6996
  {
6997
    { sChromeStaticMethods, &sChromeOnlyNativeProperties_propertyInfos[0] },
6998
    { sChromeMethods, &sChromeOnlyNativeProperties_propertyInfos[1] },
6999
    { sChromeAttributes, &sChromeOnlyNativeProperties_propertyInfos[4] }
7000
  }
7001
};
7002
static_assert(5 < 1ull << CHAR_BIT * sizeof(sChromeOnlyNativeProperties.propertyInfoCount),
7003
    "We have a property info count that is oversized");
7004
7005
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
7006
  {
7007
    "Function",
7008
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
7009
    &sBoringInterfaceObjectClassClassOps,
7010
    JS_NULL_CLASS_SPEC,
7011
    JS_NULL_CLASS_EXT,
7012
    &sInterfaceObjectClassObjectOps
7013
  },
7014
  eInterface,
7015
  true,
7016
  prototypes::id::RTCStatsReport,
7017
  PrototypeTraits<prototypes::id::RTCStatsReport>::Depth,
7018
  sNativePropertyHooks,
7019
  "function RTCStatsReport() {\n    [native code]\n}",
7020
  JS::GetRealmFunctionPrototype
7021
};
7022
7023
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
7024
  {
7025
    "RTCStatsReportPrototype",
7026
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
7027
    JS_NULL_CLASS_OPS,
7028
    JS_NULL_CLASS_SPEC,
7029
    JS_NULL_CLASS_EXT,
7030
    JS_NULL_OBJECT_OPS
7031
  },
7032
  eInterfacePrototype,
7033
  false,
7034
  prototypes::id::RTCStatsReport,
7035
  PrototypeTraits<prototypes::id::RTCStatsReport>::Depth,
7036
  sNativePropertyHooks,
7037
  "[object RTCStatsReportPrototype]",
7038
  JS::GetRealmObjectPrototype
7039
};
7040
7041
bool
7042
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
7043
0
{
7044
0
  static bool sPrefValue;
7045
0
  static bool sPrefCacheSetUp = false;
7046
0
  if (!sPrefCacheSetUp) {
7047
0
    sPrefCacheSetUp = true;
7048
0
    Preferences::AddBoolVarCache(&sPrefValue, "media.peerconnection.enabled");
7049
0
  }
7050
0
7051
0
  return sPrefValue;
7052
0
}
7053
7054
static const js::ClassOps sClassOps = {
7055
  _addProperty, /* addProperty */
7056
  nullptr,               /* delProperty */
7057
  nullptr,               /* enumerate */
7058
  nullptr, /* newEnumerate */
7059
  nullptr, /* resolve */
7060
  nullptr, /* mayResolve */
7061
  _finalize, /* finalize */
7062
  nullptr, /* call */
7063
  nullptr,               /* hasInstance */
7064
  nullptr,               /* construct */
7065
  nullptr, /* trace */
7066
};
7067
7068
static const js::ClassExtension sClassExtension = {
7069
  nullptr, /* weakmapKeyDelegateOp */
7070
  _objectMoved /* objectMovedOp */
7071
};
7072
7073
static const DOMJSClass sClass = {
7074
  { "RTCStatsReport",
7075
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(2),
7076
    &sClassOps,
7077
    JS_NULL_CLASS_SPEC,
7078
    &sClassExtension,
7079
    JS_NULL_OBJECT_OPS
7080
  },
7081
  { prototypes::id::RTCStatsReport, 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 },
7082
  IsBaseOf<nsISupports, mozilla::dom::RTCStatsReport >::value,
7083
  sNativePropertyHooks,
7084
  FindAssociatedGlobalForNative<mozilla::dom::RTCStatsReport>::Get,
7085
  GetProtoObjectHandle,
7086
  GetCCParticipant<mozilla::dom::RTCStatsReport>::Get()
7087
};
7088
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
7089
              "Must have the right minimal number of reserved slots.");
7090
static_assert(2 >= 2,
7091
              "Must have enough reserved slots.");
7092
7093
const JSClass*
7094
GetJSClass()
7095
0
{
7096
0
  return sClass.ToJSClass();
7097
0
}
7098
7099
bool
7100
Wrap(JSContext* aCx, mozilla::dom::RTCStatsReport* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
7101
0
{
7102
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, mozilla::dom::RTCStatsReport>::value,
7103
0
                "Shouldn't have wrappercached things that are not refcounted.");
7104
0
  MOZ_ASSERT(static_cast<mozilla::dom::RTCStatsReport*>(aObject) ==
7105
0
             reinterpret_cast<mozilla::dom::RTCStatsReport*>(aObject),
7106
0
             "Multiple inheritance for mozilla::dom::RTCStatsReport is broken.");
7107
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
7108
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
7109
0
  MOZ_ASSERT(!aCache->GetWrapper(),
7110
0
             "You should probably not be using Wrap() directly; use "
7111
0
             "GetOrCreateDOMReflector instead");
7112
0
7113
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
7114
0
             "nsISupports must be on our primary inheritance chain");
7115
0
7116
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
7117
0
  if (!global) {
7118
0
    return false;
7119
0
  }
7120
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
7121
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
7122
0
7123
0
  // That might have ended up wrapping us already, due to the wonders
7124
0
  // of XBL.  Check for that, and bail out as needed.
7125
0
  aReflector.set(aCache->GetWrapper());
7126
0
  if (aReflector) {
7127
#ifdef DEBUG
7128
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
7129
#endif // DEBUG
7130
    return true;
7131
0
  }
7132
0
7133
0
  JSAutoRealm ar(aCx, global);
7134
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
7135
0
  if (!canonicalProto) {
7136
0
    return false;
7137
0
  }
7138
0
  JS::Rooted<JSObject*> proto(aCx);
7139
0
  if (aGivenProto) {
7140
0
    proto = aGivenProto;
7141
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
7142
0
    // coming in, we changed compartments to that of "parent" so may need
7143
0
    // to wrap the proto here.
7144
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
7145
0
      if (!JS_WrapObject(aCx, &proto)) {
7146
0
        return false;
7147
0
      }
7148
0
    }
7149
0
  } else {
7150
0
    proto = canonicalProto;
7151
0
  }
7152
0
7153
0
  BindingJSObjectCreator<mozilla::dom::RTCStatsReport> creator(aCx);
7154
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
7155
0
  if (!aReflector) {
7156
0
    return false;
7157
0
  }
7158
0
7159
0
  aCache->SetWrapper(aReflector);
7160
0
  creator.InitializationSucceeded();
7161
0
7162
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
7163
0
             aCache->GetWrapperPreserveColor() == aReflector);
7164
0
  // If proto != canonicalProto, we have to preserve our wrapper;
7165
0
  // otherwise we won't be able to properly recreate it later, since
7166
0
  // we won't know what proto to use.  Note that we don't check
7167
0
  // aGivenProto here, since it's entirely possible (and even
7168
0
  // somewhat common) to have a non-null aGivenProto which is the
7169
0
  // same as canonicalProto.
7170
0
  if (proto != canonicalProto) {
7171
0
    PreserveWrapper(aObject);
7172
0
  }
7173
0
7174
0
  return true;
7175
0
}
7176
7177
// This may allocate too many slots, because we only really need
7178
// slots for our non-interface-typed members that we cache.  But
7179
// allocating slots only for those would make the slot index
7180
// computations much more complicated, so let's do this the simple
7181
// way for now.
7182
DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 1);
7183
7184
const NativePropertyHooks sNativePropertyHooks[] = { {
7185
  nullptr,
7186
  nullptr,
7187
  nullptr,
7188
  { sNativeProperties.Upcast(), sChromeOnlyNativeProperties.Upcast() },
7189
  prototypes::id::RTCStatsReport,
7190
  constructors::id::RTCStatsReport,
7191
  nullptr,
7192
  &sXrayExpandoObjectClass
7193
} };
7194
7195
void
7196
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
7197
0
{
7198
0
  JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
7199
0
  if (!parentProto) {
7200
0
    return;
7201
0
  }
7202
0
7203
0
  JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
7204
0
  if (!constructorProto) {
7205
0
    return;
7206
0
  }
7207
0
7208
0
  static bool sIdsInited = false;
7209
0
  if (!sIdsInited && NS_IsMainThread()) {
7210
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
7211
0
      return;
7212
0
    }
7213
0
    if (!InitIds(aCx, sChromeOnlyNativeProperties.Upcast())) {
7214
0
      return;
7215
0
    }
7216
0
    sIdsInited = true;
7217
0
  }
7218
0
7219
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::RTCStatsReport);
7220
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::RTCStatsReport);
7221
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
7222
0
                              &sPrototypeClass.mBase, protoCache,
7223
0
                              nullptr,
7224
0
                              constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
7225
0
                              interfaceCache,
7226
0
                              sNativeProperties.Upcast(),
7227
0
                              sChromeOnlyNativeProperties.Upcast(),
7228
0
                              "RTCStatsReport", aDefineOnGlobal,
7229
0
                              nullptr,
7230
0
                              false);
7231
0
7232
0
  // Set up aliases on the interface prototype object we just created.
7233
0
  JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
7234
0
  if (!proto) {
7235
0
    *protoCache = nullptr;
7236
0
    if (interfaceCache) {
7237
0
      *interfaceCache = nullptr;
7238
0
    }
7239
0
    return;
7240
0
  }
7241
0
7242
0
  JS::Rooted<JS::Value> aliasedVal(aCx);
7243
0
7244
0
  if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
7245
0
    *protoCache = nullptr;
7246
0
    if (interfaceCache) {
7247
0
      *interfaceCache = nullptr;
7248
0
    }
7249
0
    return;
7250
0
  }
7251
0
  JS::Rooted<jsid> iteratorId(aCx, SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::iterator)));
7252
0
  if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
7253
0
    *protoCache = nullptr;
7254
0
    if (interfaceCache) {
7255
0
      *interfaceCache = nullptr;
7256
0
    }
7257
0
    return;
7258
0
  }
7259
0
}
7260
7261
JSObject*
7262
GetConstructorObject(JSContext* aCx)
7263
0
{
7264
0
  return GetConstructorObjectHandle(aCx);
7265
0
}
7266
7267
} // namespace RTCStatsReport_Binding
7268
7269
7270
7271
void
7272
RTCStatsReportJSImpl::__OnGet(JS::Handle<JS::Value> key, JS::Handle<JS::Value> value, ErrorResult& aRv, JS::Realm* aRealm)
7273
0
{
7274
0
  CallSetup s(this, aRv, "__onget", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
7275
0
  JSContext* cx = s.GetContext();
7276
0
  if (!cx) {
7277
0
    MOZ_ASSERT(aRv.Failed());
7278
0
    return;
7279
0
  }
7280
0
  JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
7281
0
  JS::AutoValueVector argv(cx);
7282
0
  if (!argv.resize(2)) {
7283
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
7284
0
    return;
7285
0
  }
7286
0
  unsigned argc = 2;
7287
0
7288
0
  do {
7289
0
    JS::ExposeValueToActiveJS(value);
7290
0
    argv[1].set(value);
7291
0
    if (!MaybeWrapValue(cx, argv[1])) {
7292
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
7293
0
      return;
7294
0
    }
7295
0
    break;
7296
0
  } while (false);
7297
0
7298
0
  do {
7299
0
    JS::ExposeValueToActiveJS(key);
7300
0
    argv[0].set(key);
7301
0
    if (!MaybeWrapValue(cx, argv[0])) {
7302
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
7303
0
      return;
7304
0
    }
7305
0
    break;
7306
0
  } while (false);
7307
0
7308
0
  JS::Rooted<JS::Value> callable(cx);
7309
0
  RTCStatsReportAtoms* atomsCache = GetAtomCache<RTCStatsReportAtoms>(cx);
7310
0
  if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
7311
0
      !GetCallableProperty(cx, atomsCache->__onget_id, &callable)) {
7312
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
7313
0
    return;
7314
0
  }
7315
0
  JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
7316
0
  if (!JS::Call(cx, thisValue, callable,
7317
0
                JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
7318
0
    aRv.NoteJSContextException(cx);
7319
0
    return;
7320
0
  }
7321
0
}
7322
7323
bool
7324
RTCStatsReportJSImpl::InitIds(JSContext* cx, RTCStatsReportAtoms* atomsCache)
7325
0
{
7326
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
7327
0
7328
0
  // Initialize these in reverse order so that any failure leaves the first one
7329
0
  // uninitialized.
7330
0
  if (!atomsCache->__onget_id.init(cx, "__onget") ||
7331
0
      !atomsCache->__set_id.init(cx, "__set") ||
7332
0
      !atomsCache->get_id.init(cx, "get") ||
7333
0
      !atomsCache->__delete_id.init(cx, "__delete") ||
7334
0
      !atomsCache->__clear_id.init(cx, "__clear") ||
7335
0
      !atomsCache->has_id.init(cx, "has") ||
7336
0
      !atomsCache->forEach_id.init(cx, "forEach") ||
7337
0
      !atomsCache->values_id.init(cx, "values") ||
7338
0
      !atomsCache->keys_id.init(cx, "keys") ||
7339
0
      !atomsCache->entries_id.init(cx, "entries") ||
7340
0
      !atomsCache->size_id.init(cx, "size") ||
7341
0
      !atomsCache->mozPcid_id.init(cx, "mozPcid")) {
7342
0
    return false;
7343
0
  }
7344
0
  return true;
7345
0
}
7346
7347
7348
void
7349
RTCStatsReportJSImpl::GetMozPcid(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm)
7350
0
{
7351
0
  CallSetup s(this, aRv, "RTCStatsReport.mozPcid", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
7352
0
  JSContext* cx = s.GetContext();
7353
0
  if (!cx) {
7354
0
    MOZ_ASSERT(aRv.Failed());
7355
0
    return;
7356
0
  }
7357
0
  JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
7358
0
7359
0
  JS::Rooted<JSObject *> callback(cx, mCallback);
7360
0
  RTCStatsReportAtoms* atomsCache = GetAtomCache<RTCStatsReportAtoms>(cx);
7361
0
  if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
7362
0
      !JS_GetPropertyById(cx, callback, atomsCache->mozPcid_id, &rval)) {
7363
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
7364
0
    return;
7365
0
  }
7366
0
  binding_detail::FakeString rvalDecl;
7367
0
  if (!ConvertJSValueToString(cx, rval, eStringify, eStringify, rvalDecl)) {
7368
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
7369
0
    return;
7370
0
  }
7371
0
  aRetVal = rvalDecl;
7372
0
}
7373
7374
7375
NS_IMPL_CYCLE_COLLECTION_CLASS(RTCStatsReport)
7376
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(RTCStatsReport)
7377
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mImpl)
7378
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
7379
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
7380
0
  tmp->ClearWeakReferences();
7381
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
7382
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(RTCStatsReport)
7383
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImpl)
7384
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
7385
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
7386
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(RTCStatsReport)
7387
NS_IMPL_CYCLE_COLLECTING_ADDREF(RTCStatsReport)
7388
NS_IMPL_CYCLE_COLLECTING_RELEASE(RTCStatsReport)
7389
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RTCStatsReport)
7390
0
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
7391
0
  NS_INTERFACE_MAP_ENTRY(nsISupports)
7392
0
  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
7393
0
NS_INTERFACE_MAP_END
7394
7395
RTCStatsReport::RTCStatsReport(JS::Handle<JSObject*> aJSImplObject, JS::Handle<JSObject*> aJSImplGlobal, nsIGlobalObject* aParent)
7396
  : mImpl(new RTCStatsReportJSImpl(nullptr, aJSImplObject, aJSImplGlobal, /* aIncumbentGlobal = */ nullptr)),
7397
    mParent(aParent)
7398
0
{
7399
0
}
7400
7401
7402
RTCStatsReport::~RTCStatsReport()
7403
0
{
7404
0
}
7405
7406
nsISupports*
7407
RTCStatsReport::GetParentObject() const
7408
0
{
7409
0
  return mParent;
7410
0
}
7411
7412
JSObject*
7413
RTCStatsReport::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
7414
0
{
7415
0
  JS::Rooted<JSObject*> obj(aCx, RTCStatsReport_Binding::Wrap(aCx, this, aGivenProto));
7416
0
  if (!obj) {
7417
0
    return nullptr;
7418
0
  }
7419
0
7420
0
  // Now define it on our chrome object
7421
0
  JSAutoRealm ar(aCx, mImpl->CallbackGlobalOrNull());
7422
0
  if (!JS_WrapObject(aCx, &obj)) {
7423
0
    return nullptr;
7424
0
  }
7425
0
  if (!JS_DefineProperty(aCx, mImpl->CallbackOrNull(), "__DOM_IMPL__", obj, 0)) {
7426
0
    return nullptr;
7427
0
  }
7428
0
  return obj;
7429
0
}
7430
7431
void
7432
RTCStatsReport::GetMozPcid(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm) const
7433
0
{
7434
0
  return mImpl->GetMozPcid(aRetVal, aRv, aRealm);
7435
0
}
7436
7437
bool
7438
RTCStatsReport::_Create(JSContext* cx, unsigned argc, JS::Value* vp)
7439
0
{
7440
0
  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
7441
0
  if (args.length() < 2) {
7442
0
    return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "RTCStatsReport._create");
7443
0
  }
7444
0
  if (!args[0].isObject()) {
7445
0
    return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of RTCStatsReport._create");
7446
0
  }
7447
0
  if (!args[1].isObject()) {
7448
0
    return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of RTCStatsReport._create");
7449
0
  }
7450
0
7451
0
  // GlobalObject will go through wrappers as needed for us, and
7452
0
  // is simpler than the right UnwrapArg incantation.
7453
0
  GlobalObject global(cx, &args[0].toObject());
7454
0
  if (global.Failed()) {
7455
0
    return false;
7456
0
  }
7457
0
  nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(global.GetAsSupports());
7458
0
  MOZ_ASSERT(globalHolder);
7459
0
  JS::Rooted<JSObject*> arg(cx, &args[1].toObject());
7460
0
  JS::Rooted<JSObject*> argGlobal(cx, JS::CurrentGlobalOrNull(cx));
7461
0
  RefPtr<RTCStatsReport> impl = new RTCStatsReport(arg, argGlobal, globalHolder);
7462
0
  MOZ_ASSERT(js::IsObjectInContextCompartment(arg, cx));
7463
0
  return GetOrCreateDOMReflector(cx, impl, args.rval());
7464
0
}
7465
7466
void
7467
RTCStatsReport::__OnGet(JS::Handle<JS::Value> aKey, JS::Handle<JS::Value> aValue, ErrorResult& aRv)
7468
0
{
7469
0
  mImpl->__OnGet(aKey, aValue, aRv);
7470
0
}
7471
7472
7473
} // namespace dom
7474
} // namespace mozilla