Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dom/bindings/MutationObserverBinding.cpp
Line
Count
Source (jump to first uncovered line)
1
/* THIS FILE IS AUTOGENERATED FROM MutationObserver.webidl BY Codegen.py - DO NOT EDIT */
2
3
#include "AtomList.h"
4
#include "MutationObserverBinding.h"
5
#include "WrapperFactory.h"
6
#include "XrayWrapper.h"
7
#include "mozilla/OwningNonNull.h"
8
#include "mozilla/dom/Animation.h"
9
#include "mozilla/dom/BindingUtils.h"
10
#include "mozilla/dom/DOMJSClass.h"
11
#include "mozilla/dom/NonRefcountedDOMObject.h"
12
#include "mozilla/dom/Nullable.h"
13
#include "mozilla/dom/PrimitiveConversions.h"
14
#include "mozilla/dom/ScriptSettings.h"
15
#include "mozilla/dom/SimpleGlobalObject.h"
16
#include "mozilla/dom/XrayExpandoClass.h"
17
#include "nsContentUtils.h"
18
#include "nsDOMMutationObserver.h"
19
#include "nsINode.h"
20
#include "nsINodeList.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
30
MutationObserverInit::MutationObserverInit()
31
0
{
32
0
  // Safe to pass a null context if we pass a null value
33
0
  Init(nullptr, JS::NullHandleValue);
34
0
}
35
36
37
38
bool
39
MutationObserverInit::InitIds(JSContext* cx, MutationObserverInitAtoms* atomsCache)
40
0
{
41
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
42
0
43
0
  // Initialize these in reverse order so that any failure leaves the first one
44
0
  // uninitialized.
45
0
  if (!atomsCache->subtree_id.init(cx, "subtree") ||
46
0
      !atomsCache->nativeAnonymousChildList_id.init(cx, "nativeAnonymousChildList") ||
47
0
      !atomsCache->childList_id.init(cx, "childList") ||
48
0
      !atomsCache->characterDataOldValue_id.init(cx, "characterDataOldValue") ||
49
0
      !atomsCache->characterData_id.init(cx, "characterData") ||
50
0
      !atomsCache->attributes_id.init(cx, "attributes") ||
51
0
      !atomsCache->attributeOldValue_id.init(cx, "attributeOldValue") ||
52
0
      !atomsCache->attributeFilter_id.init(cx, "attributeFilter") ||
53
0
      !atomsCache->animations_id.init(cx, "animations")) {
54
0
    return false;
55
0
  }
56
0
  return true;
57
0
}
58
59
bool
60
MutationObserverInit::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
61
0
{
62
0
  // Passing a null JSContext is OK only if we're initing from null,
63
0
  // Since in that case we will not have to do any property gets
64
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
65
0
  // checkers by static analysis tools
66
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
67
0
  MutationObserverInitAtoms* atomsCache = nullptr;
68
0
  if (cx) {
69
0
    atomsCache = GetAtomCache<MutationObserverInitAtoms>(cx);
70
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
71
0
      return false;
72
0
    }
73
0
  }
74
0
75
0
  if (!IsConvertibleToDictionary(val)) {
76
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
77
0
  }
78
0
79
0
  bool isNull = val.isNullOrUndefined();
80
0
  // We only need these if !isNull, in which case we have |cx|.
81
0
  Maybe<JS::Rooted<JSObject *> > object;
82
0
  Maybe<JS::Rooted<JS::Value> > temp;
83
0
  if (!isNull) {
84
0
    MOZ_ASSERT(cx);
85
0
    object.emplace(cx, &val.toObject());
86
0
    temp.emplace(cx);
87
0
  }
88
0
  if (!isNull) {
89
0
    if (nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
90
0
      if (!JS_GetPropertyById(cx, *object, atomsCache->animations_id, temp.ptr())) {
91
0
        return false;
92
0
      }
93
0
    } else {
94
0
      temp->setUndefined();
95
0
    }
96
0
  }
97
0
  if (!isNull && !temp->isUndefined()) {
98
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mAnimations)) {
99
0
      return false;
100
0
    }
101
0
  } else {
102
0
    mAnimations = false;
103
0
  }
104
0
  mIsAnyMemberPresent = true;
105
0
106
0
  if (!isNull) {
107
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->attributeFilter_id, temp.ptr())) {
108
0
      return false;
109
0
    }
110
0
  }
111
0
  if (!isNull && !temp->isUndefined()) {
112
0
    mAttributeFilter.Construct();
113
0
    if (temp.ref().isObject()) {
114
0
      JS::ForOfIterator iter(cx);
115
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
116
0
        return false;
117
0
      }
118
0
      if (!iter.valueIsIterable()) {
119
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'attributeFilter' member of MutationObserverInit");
120
0
        return false;
121
0
      }
122
0
      Sequence<nsString> &arr = (mAttributeFilter.Value());
123
0
      JS::Rooted<JS::Value> temp(cx);
124
0
      while (true) {
125
0
        bool done;
126
0
        if (!iter.next(&temp, &done)) {
127
0
          return false;
128
0
        }
129
0
        if (done) {
130
0
          break;
131
0
        }
132
0
        nsString* slotPtr = arr.AppendElement(mozilla::fallible);
133
0
        if (!slotPtr) {
134
0
          JS_ReportOutOfMemory(cx);
135
0
          return false;
136
0
        }
137
0
        nsString& slot = *slotPtr;
138
0
        if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
139
0
          return false;
140
0
        }
141
0
      }
142
0
    } else {
143
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'attributeFilter' member of MutationObserverInit");
144
0
      return false;
145
0
    }
146
0
    mIsAnyMemberPresent = true;
147
0
  }
148
0
149
0
  if (!isNull) {
150
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->attributeOldValue_id, temp.ptr())) {
151
0
      return false;
152
0
    }
153
0
  }
154
0
  if (!isNull && !temp->isUndefined()) {
155
0
    mAttributeOldValue.Construct();
156
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mAttributeOldValue.Value()))) {
157
0
      return false;
158
0
    }
159
0
    mIsAnyMemberPresent = true;
160
0
  }
161
0
162
0
  if (!isNull) {
163
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->attributes_id, temp.ptr())) {
164
0
      return false;
165
0
    }
166
0
  }
167
0
  if (!isNull && !temp->isUndefined()) {
168
0
    mAttributes.Construct();
169
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mAttributes.Value()))) {
170
0
      return false;
171
0
    }
172
0
    mIsAnyMemberPresent = true;
173
0
  }
174
0
175
0
  if (!isNull) {
176
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->characterData_id, temp.ptr())) {
177
0
      return false;
178
0
    }
179
0
  }
180
0
  if (!isNull && !temp->isUndefined()) {
181
0
    mCharacterData.Construct();
182
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mCharacterData.Value()))) {
183
0
      return false;
184
0
    }
185
0
    mIsAnyMemberPresent = true;
186
0
  }
187
0
188
0
  if (!isNull) {
189
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->characterDataOldValue_id, temp.ptr())) {
190
0
      return false;
191
0
    }
192
0
  }
193
0
  if (!isNull && !temp->isUndefined()) {
194
0
    mCharacterDataOldValue.Construct();
195
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mCharacterDataOldValue.Value()))) {
196
0
      return false;
197
0
    }
198
0
    mIsAnyMemberPresent = true;
199
0
  }
200
0
201
0
  if (!isNull) {
202
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->childList_id, temp.ptr())) {
203
0
      return false;
204
0
    }
205
0
  }
206
0
  if (!isNull && !temp->isUndefined()) {
207
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mChildList)) {
208
0
      return false;
209
0
    }
210
0
  } else {
211
0
    mChildList = false;
212
0
  }
213
0
  mIsAnyMemberPresent = true;
214
0
215
0
  if (!isNull) {
216
0
    if (nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
217
0
      if (!JS_GetPropertyById(cx, *object, atomsCache->nativeAnonymousChildList_id, temp.ptr())) {
218
0
        return false;
219
0
      }
220
0
    } else {
221
0
      temp->setUndefined();
222
0
    }
223
0
  }
224
0
  if (!isNull && !temp->isUndefined()) {
225
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mNativeAnonymousChildList)) {
226
0
      return false;
227
0
    }
228
0
  } else {
229
0
    mNativeAnonymousChildList = false;
230
0
  }
231
0
  mIsAnyMemberPresent = true;
232
0
233
0
  if (!isNull) {
234
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->subtree_id, temp.ptr())) {
235
0
      return false;
236
0
    }
237
0
  }
238
0
  if (!isNull && !temp->isUndefined()) {
239
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mSubtree)) {
240
0
      return false;
241
0
    }
242
0
  } else {
243
0
    mSubtree = false;
244
0
  }
245
0
  mIsAnyMemberPresent = true;
246
0
  return true;
247
0
}
248
249
bool
250
MutationObserverInit::Init(const nsAString& aJSON)
251
0
{
252
0
  AutoJSAPI jsapi;
253
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
254
0
  if (!cleanGlobal) {
255
0
    return false;
256
0
  }
257
0
  if (!jsapi.Init(cleanGlobal)) {
258
0
    return false;
259
0
  }
260
0
  JSContext* cx = jsapi.cx();
261
0
  JS::Rooted<JS::Value> json(cx);
262
0
  bool ok = ParseJSON(cx, aJSON, &json);
263
0
  NS_ENSURE_TRUE(ok, false);
264
0
  return Init(cx, json);
265
0
}
266
267
bool
268
MutationObserverInit::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
269
0
{
270
0
  MutationObserverInitAtoms* atomsCache = GetAtomCache<MutationObserverInitAtoms>(cx);
271
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
272
0
    return false;
273
0
  }
274
0
275
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
276
0
  if (!obj) {
277
0
    return false;
278
0
  }
279
0
  rval.set(JS::ObjectValue(*obj));
280
0
281
0
  if (nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
282
0
    do {
283
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
284
0
      JS::Rooted<JS::Value> temp(cx);
285
0
      bool const & currentValue = mAnimations;
286
0
      temp.setBoolean(currentValue);
287
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->animations_id, temp, JSPROP_ENUMERATE)) {
288
0
        return false;
289
0
      }
290
0
      break;
291
0
    } while(false);
292
0
  }
293
0
294
0
  if (mAttributeFilter.WasPassed()) {
295
0
    do {
296
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
297
0
      JS::Rooted<JS::Value> temp(cx);
298
0
      Sequence<nsString> const & currentValue = mAttributeFilter.InternalValue();
299
0
300
0
      uint32_t length = currentValue.Length();
301
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
302
0
      if (!returnArray) {
303
0
        return false;
304
0
      }
305
0
      // Scope for 'tmp'
306
0
      {
307
0
        JS::Rooted<JS::Value> tmp(cx);
308
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
309
0
          // Control block to let us common up the JS_DefineElement calls when there
310
0
          // are different ways to succeed at wrapping the object.
311
0
          do {
312
0
            if (!xpc::NonVoidStringToJsval(cx, currentValue[sequenceIdx0], &tmp)) {
313
0
              return false;
314
0
            }
315
0
            break;
316
0
          } while (false);
317
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
318
0
                                JSPROP_ENUMERATE)) {
319
0
            return false;
320
0
          }
321
0
        }
322
0
      }
323
0
      temp.setObject(*returnArray);
324
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->attributeFilter_id, temp, JSPROP_ENUMERATE)) {
325
0
        return false;
326
0
      }
327
0
      break;
328
0
    } while(false);
329
0
  }
330
0
331
0
  if (mAttributeOldValue.WasPassed()) {
332
0
    do {
333
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
334
0
      JS::Rooted<JS::Value> temp(cx);
335
0
      bool const & currentValue = mAttributeOldValue.InternalValue();
336
0
      temp.setBoolean(currentValue);
337
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->attributeOldValue_id, temp, JSPROP_ENUMERATE)) {
338
0
        return false;
339
0
      }
340
0
      break;
341
0
    } while(false);
342
0
  }
343
0
344
0
  if (mAttributes.WasPassed()) {
345
0
    do {
346
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
347
0
      JS::Rooted<JS::Value> temp(cx);
348
0
      bool const & currentValue = mAttributes.InternalValue();
349
0
      temp.setBoolean(currentValue);
350
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->attributes_id, temp, JSPROP_ENUMERATE)) {
351
0
        return false;
352
0
      }
353
0
      break;
354
0
    } while(false);
355
0
  }
356
0
357
0
  if (mCharacterData.WasPassed()) {
358
0
    do {
359
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
360
0
      JS::Rooted<JS::Value> temp(cx);
361
0
      bool const & currentValue = mCharacterData.InternalValue();
362
0
      temp.setBoolean(currentValue);
363
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->characterData_id, temp, JSPROP_ENUMERATE)) {
364
0
        return false;
365
0
      }
366
0
      break;
367
0
    } while(false);
368
0
  }
369
0
370
0
  if (mCharacterDataOldValue.WasPassed()) {
371
0
    do {
372
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
373
0
      JS::Rooted<JS::Value> temp(cx);
374
0
      bool const & currentValue = mCharacterDataOldValue.InternalValue();
375
0
      temp.setBoolean(currentValue);
376
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->characterDataOldValue_id, temp, JSPROP_ENUMERATE)) {
377
0
        return false;
378
0
      }
379
0
      break;
380
0
    } while(false);
381
0
  }
382
0
383
0
  do {
384
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
385
0
    JS::Rooted<JS::Value> temp(cx);
386
0
    bool const & currentValue = mChildList;
387
0
    temp.setBoolean(currentValue);
388
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->childList_id, temp, JSPROP_ENUMERATE)) {
389
0
      return false;
390
0
    }
391
0
    break;
392
0
  } while(false);
393
0
394
0
  if (nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
395
0
    do {
396
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
397
0
      JS::Rooted<JS::Value> temp(cx);
398
0
      bool const & currentValue = mNativeAnonymousChildList;
399
0
      temp.setBoolean(currentValue);
400
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->nativeAnonymousChildList_id, temp, JSPROP_ENUMERATE)) {
401
0
        return false;
402
0
      }
403
0
      break;
404
0
    } while(false);
405
0
  }
406
0
407
0
  do {
408
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
409
0
    JS::Rooted<JS::Value> temp(cx);
410
0
    bool const & currentValue = mSubtree;
411
0
    temp.setBoolean(currentValue);
412
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->subtree_id, temp, JSPROP_ENUMERATE)) {
413
0
      return false;
414
0
    }
415
0
    break;
416
0
  } while(false);
417
0
418
0
  return true;
419
0
}
420
421
bool
422
MutationObserverInit::ToJSON(nsAString& aJSON) const
423
0
{
424
0
  AutoJSAPI jsapi;
425
0
  jsapi.Init();
426
0
  JSContext *cx = jsapi.cx();
427
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
428
0
  // because we'll only be creating objects, in ways that have no
429
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
430
0
  // which likewise guarantees no side-effects for the sorts of
431
0
  // things we will pass it.
432
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
433
0
  JS::Rooted<JS::Value> val(cx);
434
0
  if (!ToObjectInternal(cx, &val)) {
435
0
    return false;
436
0
  }
437
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
438
0
  return StringifyToJSON(cx, obj, aJSON);
439
0
}
440
441
void
442
MutationObserverInit::TraceDictionary(JSTracer* trc)
443
0
{
444
0
}
445
446
MutationObserverInit&
447
MutationObserverInit::operator=(const MutationObserverInit& aOther)
448
0
{
449
0
  DictionaryBase::operator=(aOther);
450
0
  mAnimations = aOther.mAnimations;
451
0
  mAttributeFilter.Reset();
452
0
  if (aOther.mAttributeFilter.WasPassed()) {
453
0
    mAttributeFilter.Construct(aOther.mAttributeFilter.Value());
454
0
  }
455
0
  mAttributeOldValue.Reset();
456
0
  if (aOther.mAttributeOldValue.WasPassed()) {
457
0
    mAttributeOldValue.Construct(aOther.mAttributeOldValue.Value());
458
0
  }
459
0
  mAttributes.Reset();
460
0
  if (aOther.mAttributes.WasPassed()) {
461
0
    mAttributes.Construct(aOther.mAttributes.Value());
462
0
  }
463
0
  mCharacterData.Reset();
464
0
  if (aOther.mCharacterData.WasPassed()) {
465
0
    mCharacterData.Construct(aOther.mCharacterData.Value());
466
0
  }
467
0
  mCharacterDataOldValue.Reset();
468
0
  if (aOther.mCharacterDataOldValue.WasPassed()) {
469
0
    mCharacterDataOldValue.Construct(aOther.mCharacterDataOldValue.Value());
470
0
  }
471
0
  mChildList = aOther.mChildList;
472
0
  mNativeAnonymousChildList = aOther.mNativeAnonymousChildList;
473
0
  mSubtree = aOther.mSubtree;
474
0
  return *this;
475
0
}
476
477
namespace binding_detail {
478
} // namespace binding_detail
479
480
481
482
MutationObservingInfo::MutationObservingInfo()
483
  : MutationObserverInit(FastDictionaryInitializer())
484
0
{
485
0
  // Safe to pass a null context if we pass a null value
486
0
  Init(nullptr, JS::NullHandleValue);
487
0
}
488
489
490
491
bool
492
MutationObservingInfo::InitIds(JSContext* cx, MutationObservingInfoAtoms* atomsCache)
493
0
{
494
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
495
0
496
0
  // Initialize these in reverse order so that any failure leaves the first one
497
0
  // uninitialized.
498
0
  if (!atomsCache->observedNode_id.init(cx, "observedNode")) {
499
0
    return false;
500
0
  }
501
0
  return true;
502
0
}
503
504
bool
505
MutationObservingInfo::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
506
0
{
507
0
  // Passing a null JSContext is OK only if we're initing from null,
508
0
  // Since in that case we will not have to do any property gets
509
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
510
0
  // checkers by static analysis tools
511
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
512
0
  MutationObservingInfoAtoms* atomsCache = nullptr;
513
0
  if (cx) {
514
0
    atomsCache = GetAtomCache<MutationObservingInfoAtoms>(cx);
515
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
516
0
      return false;
517
0
    }
518
0
  }
519
0
520
0
  // Per spec, we init the parent's members first
521
0
  if (!MutationObserverInit::Init(cx, val)) {
522
0
    return false;
523
0
  }
524
0
525
0
  bool isNull = val.isNullOrUndefined();
526
0
  // We only need these if !isNull, in which case we have |cx|.
527
0
  Maybe<JS::Rooted<JSObject *> > object;
528
0
  Maybe<JS::Rooted<JS::Value> > temp;
529
0
  if (!isNull) {
530
0
    MOZ_ASSERT(cx);
531
0
    object.emplace(cx, &val.toObject());
532
0
    temp.emplace(cx);
533
0
  }
534
0
  if (!isNull) {
535
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->observedNode_id, temp.ptr())) {
536
0
      return false;
537
0
    }
538
0
  }
539
0
  if (!isNull && !temp->isUndefined()) {
540
0
    if (temp.ref().isObject()) {
541
0
      static_assert(IsRefcounted<nsINode>::value, "We can only store refcounted classes.");{
542
0
        nsresult rv = UnwrapObject<prototypes::id::Node, nsINode>(temp.ptr(), mObservedNode);
543
0
        if (NS_FAILED(rv)) {
544
0
          ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "'observedNode' member of MutationObservingInfo", "Node");
545
0
          return false;
546
0
        }
547
0
      }
548
0
    } else if (temp.ref().isNullOrUndefined()) {
549
0
      mObservedNode = nullptr;
550
0
    } else {
551
0
      ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'observedNode' member of MutationObservingInfo");
552
0
      return false;
553
0
    }
554
0
  } else {
555
0
    mObservedNode = nullptr;
556
0
  }
557
0
  mIsAnyMemberPresent = true;
558
0
  return true;
559
0
}
560
561
bool
562
MutationObservingInfo::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
563
0
{
564
0
  MutationObservingInfoAtoms* atomsCache = GetAtomCache<MutationObservingInfoAtoms>(cx);
565
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
566
0
    return false;
567
0
  }
568
0
569
0
  // Per spec, we define the parent's members first
570
0
  if (!MutationObserverInit::ToObjectInternal(cx, rval)) {
571
0
    return false;
572
0
  }
573
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
574
0
575
0
  do {
576
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
577
0
    JS::Rooted<JS::Value> temp(cx);
578
0
    RefPtr<nsINode> const & currentValue = mObservedNode;
579
0
    if (!currentValue) {
580
0
      temp.setNull();
581
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->observedNode_id, temp, JSPROP_ENUMERATE)) {
582
0
        return false;
583
0
      }
584
0
      break;
585
0
    }
586
0
    if (!GetOrCreateDOMReflector(cx, currentValue, &temp)) {
587
0
      MOZ_ASSERT(JS_IsExceptionPending(cx));
588
0
      return false;
589
0
    }
590
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->observedNode_id, temp, JSPROP_ENUMERATE)) {
591
0
      return false;
592
0
    }
593
0
    break;
594
0
  } while(false);
595
0
596
0
  return true;
597
0
}
598
599
void
600
MutationObservingInfo::TraceDictionary(JSTracer* trc)
601
0
{
602
0
  MutationObserverInit::TraceDictionary(trc);
603
0
}
604
605
606
607
MutationObservingInfo&
608
MutationObservingInfo::operator=(const MutationObservingInfo& aOther)
609
0
{
610
0
  MutationObserverInit::operator=(aOther);
611
0
  mObservedNode = aOther.mObservedNode;
612
0
  return *this;
613
0
}
614
615
namespace binding_detail {
616
} // namespace binding_detail
617
618
619
void
620
MutationCallback::Call(JSContext* cx, JS::Handle<JS::Value> aThisVal, const Sequence<OwningNonNull<nsDOMMutationRecord>>& mutations, nsDOMMutationObserver& observer, ErrorResult& aRv)
621
0
{
622
0
  JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
623
0
  JS::AutoValueVector argv(cx);
624
0
  if (!argv.resize(2)) {
625
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
626
0
    return;
627
0
  }
628
0
  unsigned argc = 2;
629
0
630
0
  do {
631
0
    if (!GetOrCreateDOMReflector(cx, observer, argv[1])) {
632
0
      MOZ_ASSERT(JS_IsExceptionPending(cx));
633
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
634
0
      return;
635
0
    }
636
0
    break;
637
0
  } while (false);
638
0
639
0
  do {
640
0
641
0
    uint32_t length = mutations.Length();
642
0
    JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
643
0
    if (!returnArray) {
644
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
645
0
      return;
646
0
    }
647
0
    // Scope for 'tmp'
648
0
    {
649
0
      JS::Rooted<JS::Value> tmp(cx);
650
0
      for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
651
0
        // Control block to let us common up the JS_DefineElement calls when there
652
0
        // are different ways to succeed at wrapping the object.
653
0
        do {
654
0
          if (!GetOrCreateDOMReflector(cx, mutations[sequenceIdx0], &tmp)) {
655
0
            MOZ_ASSERT(JS_IsExceptionPending(cx));
656
0
            aRv.Throw(NS_ERROR_UNEXPECTED);
657
0
            return;
658
0
          }
659
0
          break;
660
0
        } while (false);
661
0
        if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
662
0
                              JSPROP_ENUMERATE)) {
663
0
          aRv.Throw(NS_ERROR_UNEXPECTED);
664
0
          return;
665
0
        }
666
0
      }
667
0
    }
668
0
    argv[0].setObject(*returnArray);
669
0
    break;
670
0
  } while (false);
671
0
672
0
  JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
673
0
  if (!JS::Call(cx, aThisVal, callable,
674
0
                JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
675
0
    aRv.NoteJSContextException(cx);
676
0
    return;
677
0
  }
678
0
}
679
680
681
682
namespace binding_detail {
683
} // namespace binding_detail
684
685
686
namespace MutationObserver_Binding {
687
688
MOZ_CAN_RUN_SCRIPT static bool
689
observe(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationObserver* self, const JSJitMethodCallArgs& args)
690
0
{
691
0
  AUTO_PROFILER_LABEL_FAST("MutationObserver.observe", DOM, cx);
692
0
693
0
  if (MOZ_UNLIKELY(args.length() < 1)) {
694
0
    return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "MutationObserver.observe");
695
0
  }
696
0
  NonNull<nsINode> arg0;
697
0
  if (args[0].isObject()) {
698
0
    {
699
0
      nsresult rv = UnwrapObject<prototypes::id::Node, nsINode>(args[0], arg0);
700
0
      if (NS_FAILED(rv)) {
701
0
        ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 1 of MutationObserver.observe", "Node");
702
0
        return false;
703
0
      }
704
0
    }
705
0
  } else {
706
0
    ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of MutationObserver.observe");
707
0
    return false;
708
0
  }
709
0
  binding_detail::FastMutationObserverInit arg1;
710
0
  if (!arg1.Init(cx, (args.hasDefined(1)) ? args[1] : JS::NullHandleValue,  "Argument 2 of MutationObserver.observe", false)) {
711
0
    return false;
712
0
  }
713
0
  FastErrorResult rv;
714
0
  self->Observe(MOZ_KnownLive(NonNullHelper(arg0)), Constify(arg1), rv);
715
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
716
0
    return false;
717
0
  }
718
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
719
0
  args.rval().setUndefined();
720
0
  return true;
721
0
}
722
723
static const JSJitInfo observe_methodinfo = {
724
  { (JSJitGetterOp)observe },
725
  { prototypes::id::MutationObserver },
726
  { PrototypeTraits<prototypes::id::MutationObserver>::Depth },
727
  JSJitInfo::Method,
728
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
729
  JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
730
  false,  /* isInfallible. False in setters. */
731
  false,  /* isMovable.  Not relevant for setters. */
732
  false, /* isEliminatable.  Not relevant for setters. */
733
  false, /* isAlwaysInSlot.  Only relevant for getters. */
734
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
735
  false,  /* isTypedMethod.  Only relevant for methods. */
736
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
737
};
738
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
739
static_assert(0 < 1, "There is no slot for us");
740
741
MOZ_CAN_RUN_SCRIPT static bool
742
disconnect(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationObserver* self, const JSJitMethodCallArgs& args)
743
0
{
744
0
  AUTO_PROFILER_LABEL_FAST("MutationObserver.disconnect", DOM, cx);
745
0
746
0
  self->Disconnect();
747
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
748
0
  args.rval().setUndefined();
749
0
  return true;
750
0
}
751
752
static const JSJitInfo disconnect_methodinfo = {
753
  { (JSJitGetterOp)disconnect },
754
  { prototypes::id::MutationObserver },
755
  { PrototypeTraits<prototypes::id::MutationObserver>::Depth },
756
  JSJitInfo::Method,
757
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
758
  JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
759
  true,  /* isInfallible. False in setters. */
760
  false,  /* isMovable.  Not relevant for setters. */
761
  false, /* isEliminatable.  Not relevant for setters. */
762
  false, /* isAlwaysInSlot.  Only relevant for getters. */
763
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
764
  false,  /* isTypedMethod.  Only relevant for methods. */
765
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
766
};
767
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
768
static_assert(0 < 1, "There is no slot for us");
769
770
MOZ_CAN_RUN_SCRIPT static bool
771
takeRecords(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationObserver* self, const JSJitMethodCallArgs& args)
772
0
{
773
0
  AUTO_PROFILER_LABEL_FAST("MutationObserver.takeRecords", DOM, cx);
774
0
775
0
  nsTArray<StrongPtrForMember<nsDOMMutationRecord>::Type> result;
776
0
  self->TakeRecords(result);
777
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
778
0
779
0
  uint32_t length = result.Length();
780
0
  JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
781
0
  if (!returnArray) {
782
0
    return false;
783
0
  }
784
0
  // Scope for 'tmp'
785
0
  {
786
0
    JS::Rooted<JS::Value> tmp(cx);
787
0
    for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
788
0
      // Control block to let us common up the JS_DefineElement calls when there
789
0
      // are different ways to succeed at wrapping the object.
790
0
      do {
791
0
        if (!GetOrCreateDOMReflector(cx, result[sequenceIdx0], &tmp)) {
792
0
          MOZ_ASSERT(JS_IsExceptionPending(cx));
793
0
          return false;
794
0
        }
795
0
        break;
796
0
      } while (false);
797
0
      if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
798
0
                            JSPROP_ENUMERATE)) {
799
0
        return false;
800
0
      }
801
0
    }
802
0
  }
803
0
  args.rval().setObject(*returnArray);
804
0
  return true;
805
0
}
806
807
static const JSJitInfo takeRecords_methodinfo = {
808
  { (JSJitGetterOp)takeRecords },
809
  { prototypes::id::MutationObserver },
810
  { PrototypeTraits<prototypes::id::MutationObserver>::Depth },
811
  JSJitInfo::Method,
812
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
813
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
814
  false,  /* isInfallible. False in setters. */
815
  false,  /* isMovable.  Not relevant for setters. */
816
  false, /* isEliminatable.  Not relevant for setters. */
817
  false, /* isAlwaysInSlot.  Only relevant for getters. */
818
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
819
  false,  /* isTypedMethod.  Only relevant for methods. */
820
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
821
};
822
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
823
static_assert(0 < 1, "There is no slot for us");
824
825
MOZ_CAN_RUN_SCRIPT static bool
826
getObservingInfo(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationObserver* self, const JSJitMethodCallArgs& args)
827
0
{
828
0
  AUTO_PROFILER_LABEL_FAST("MutationObserver.getObservingInfo", DOM, cx);
829
0
830
0
  FastErrorResult rv;
831
0
  nsTArray<Nullable<MutationObservingInfo>> result;
832
0
  self->GetObservingInfo(result, rv);
833
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
834
0
    return false;
835
0
  }
836
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
837
0
838
0
  uint32_t length = result.Length();
839
0
  JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
840
0
  if (!returnArray) {
841
0
    return false;
842
0
  }
843
0
  // Scope for 'tmp'
844
0
  {
845
0
    JS::Rooted<JS::Value> tmp(cx);
846
0
    for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
847
0
      // Control block to let us common up the JS_DefineElement calls when there
848
0
      // are different ways to succeed at wrapping the object.
849
0
      do {
850
0
        if (result[sequenceIdx0].IsNull()) {
851
0
          tmp.setNull();
852
0
          break;
853
0
        }
854
0
        if (!result[sequenceIdx0].Value().ToObjectInternal(cx, &tmp)) {
855
0
          return false;
856
0
        }
857
0
        break;
858
0
      } while (false);
859
0
      if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
860
0
                            JSPROP_ENUMERATE)) {
861
0
        return false;
862
0
      }
863
0
    }
864
0
  }
865
0
  args.rval().setObject(*returnArray);
866
0
  return true;
867
0
}
868
869
static const JSJitInfo getObservingInfo_methodinfo = {
870
  { (JSJitGetterOp)getObservingInfo },
871
  { prototypes::id::MutationObserver },
872
  { PrototypeTraits<prototypes::id::MutationObserver>::Depth },
873
  JSJitInfo::Method,
874
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
875
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
876
  false,  /* isInfallible. False in setters. */
877
  false,  /* isMovable.  Not relevant for setters. */
878
  false, /* isEliminatable.  Not relevant for setters. */
879
  false, /* isAlwaysInSlot.  Only relevant for getters. */
880
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
881
  false,  /* isTypedMethod.  Only relevant for methods. */
882
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
883
};
884
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
885
static_assert(0 < 1, "There is no slot for us");
886
887
MOZ_CAN_RUN_SCRIPT static bool
888
get_mutationCallback(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationObserver* self, JSJitGetterCallArgs args)
889
0
{
890
0
  AUTO_PROFILER_LABEL_FAST("get MutationObserver.mutationCallback", DOM, cx);
891
0
892
0
  RefPtr<MutationCallback> result(self->MutationCallback());
893
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
894
0
  args.rval().setObjectOrNull(GetCallbackFromCallbackObject(cx, result));
895
0
  if (!MaybeWrapObjectValue(cx, args.rval())) {
896
0
    return false;
897
0
  }
898
0
  return true;
899
0
}
900
901
static const JSJitInfo mutationCallback_getterinfo = {
902
  { (JSJitGetterOp)get_mutationCallback },
903
  { prototypes::id::MutationObserver },
904
  { PrototypeTraits<prototypes::id::MutationObserver>::Depth },
905
  JSJitInfo::Getter,
906
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
907
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
908
  false,  /* isInfallible. False in setters. */
909
  false,  /* isMovable.  Not relevant for setters. */
910
  false, /* isEliminatable.  Not relevant for setters. */
911
  false, /* isAlwaysInSlot.  Only relevant for getters. */
912
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
913
  false,  /* isTypedMethod.  Only relevant for methods. */
914
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
915
};
916
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
917
static_assert(0 < 1, "There is no slot for us");
918
919
MOZ_CAN_RUN_SCRIPT static bool
920
get_mergeAttributeRecords(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationObserver* self, JSJitGetterCallArgs args)
921
0
{
922
0
  AUTO_PROFILER_LABEL_FAST("get MutationObserver.mergeAttributeRecords", DOM, cx);
923
0
924
0
  bool result(self->MergeAttributeRecords());
925
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
926
0
  args.rval().setBoolean(result);
927
0
  return true;
928
0
}
929
930
MOZ_CAN_RUN_SCRIPT static bool
931
set_mergeAttributeRecords(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationObserver* self, JSJitSetterCallArgs args)
932
0
{
933
0
  AUTO_PROFILER_LABEL_FAST("set MutationObserver.mergeAttributeRecords", DOM, cx);
934
0
935
0
  bool arg0;
936
0
  if (!ValueToPrimitive<bool, eDefault>(cx, args[0], &arg0)) {
937
0
    return false;
938
0
  }
939
0
  self->SetMergeAttributeRecords(arg0);
940
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
941
0
942
0
  return true;
943
0
}
944
945
static const JSJitInfo mergeAttributeRecords_getterinfo = {
946
  { (JSJitGetterOp)get_mergeAttributeRecords },
947
  { prototypes::id::MutationObserver },
948
  { PrototypeTraits<prototypes::id::MutationObserver>::Depth },
949
  JSJitInfo::Getter,
950
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
951
  JSVAL_TYPE_BOOLEAN,  /* returnType.  Not relevant for setters. */
952
  true,  /* isInfallible. False in setters. */
953
  false,  /* isMovable.  Not relevant for setters. */
954
  false, /* isEliminatable.  Not relevant for setters. */
955
  false, /* isAlwaysInSlot.  Only relevant for getters. */
956
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
957
  false,  /* isTypedMethod.  Only relevant for methods. */
958
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
959
};
960
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
961
static_assert(0 < 1, "There is no slot for us");
962
static const JSJitInfo mergeAttributeRecords_setterinfo = {
963
  { (JSJitGetterOp)set_mergeAttributeRecords },
964
  { prototypes::id::MutationObserver },
965
  { PrototypeTraits<prototypes::id::MutationObserver>::Depth },
966
  JSJitInfo::Setter,
967
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
968
  JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
969
  false,  /* isInfallible. False in setters. */
970
  false,  /* isMovable.  Not relevant for setters. */
971
  false, /* isEliminatable.  Not relevant for setters. */
972
  false, /* isAlwaysInSlot.  Only relevant for getters. */
973
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
974
  false,  /* isTypedMethod.  Only relevant for methods. */
975
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
976
};
977
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
978
static_assert(0 < 1, "There is no slot for us");
979
980
static bool
981
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
982
0
{
983
0
  nsDOMMutationObserver* self = UnwrapPossiblyNotInitializedDOMObject<nsDOMMutationObserver>(obj);
984
0
  // We don't want to preserve if we don't have a wrapper, and we
985
0
  // obviously can't preserve if we're not initialized.
986
0
  if (self && self->GetWrapperPreserveColor()) {
987
0
    PreserveWrapper(self);
988
0
  }
989
0
  return true;
990
0
}
991
992
static void
993
_finalize(js::FreeOp* fop, JSObject* obj)
994
0
{
995
0
  nsDOMMutationObserver* self = UnwrapPossiblyNotInitializedDOMObject<nsDOMMutationObserver>(obj);
996
0
  if (self) {
997
0
    ClearWrapper(self, self, obj);
998
0
    AddForDeferredFinalization<nsDOMMutationObserver>(self);
999
0
  }
1000
0
}
1001
1002
static size_t
1003
_objectMoved(JSObject* obj, JSObject* old)
1004
0
{
1005
0
  nsDOMMutationObserver* self = UnwrapPossiblyNotInitializedDOMObject<nsDOMMutationObserver>(obj);
1006
0
  if (self) {
1007
0
    UpdateWrapper(self, self, obj, old);
1008
0
  }
1009
0
1010
0
  return 0;
1011
0
}
1012
1013
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
1014
#if defined(__clang__)
1015
#pragma clang diagnostic push
1016
#pragma clang diagnostic ignored "-Wmissing-braces"
1017
#endif
1018
static const JSFunctionSpec sMethods_specs[] = {
1019
  JS_FNSPEC("observe", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&observe_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
1020
  JS_FNSPEC("disconnect", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&disconnect_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
1021
  JS_FNSPEC("takeRecords", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&takeRecords_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
1022
  JS_FS_END
1023
};
1024
#if defined(__clang__)
1025
#pragma clang diagnostic pop
1026
#endif
1027
1028
1029
static const Prefable<const JSFunctionSpec> sMethods[] = {
1030
  { nullptr, &sMethods_specs[0] },
1031
  { nullptr, nullptr }
1032
};
1033
1034
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
1035
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
1036
static_assert(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
1037
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
1038
1039
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
1040
#if defined(__clang__)
1041
#pragma clang diagnostic push
1042
#pragma clang diagnostic ignored "-Wmissing-braces"
1043
#endif
1044
static const JSFunctionSpec sChromeMethods_specs[] = {
1045
  JS_FNSPEC("getObservingInfo", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&getObservingInfo_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
1046
  JS_FS_END
1047
};
1048
#if defined(__clang__)
1049
#pragma clang diagnostic pop
1050
#endif
1051
1052
1053
static const Prefable<const JSFunctionSpec> sChromeMethods[] = {
1054
  { nullptr, &sChromeMethods_specs[0] },
1055
  { nullptr, nullptr }
1056
};
1057
1058
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
1059
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
1060
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
1061
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
1062
1063
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
1064
#if defined(__clang__)
1065
#pragma clang diagnostic push
1066
#pragma clang diagnostic ignored "-Wmissing-braces"
1067
#endif
1068
static const JSPropertySpec sChromeAttributes_specs[] = {
1069
  { "mutationCallback", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &mutationCallback_getterinfo, nullptr, nullptr },
1070
  { "mergeAttributeRecords", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &mergeAttributeRecords_getterinfo, GenericSetter<NormalThisPolicy>, &mergeAttributeRecords_setterinfo },
1071
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
1072
};
1073
#if defined(__clang__)
1074
#pragma clang diagnostic pop
1075
#endif
1076
1077
1078
static const Prefable<const JSPropertySpec> sChromeAttributes[] = {
1079
  { nullptr, &sChromeAttributes_specs[0] },
1080
  { nullptr, nullptr }
1081
};
1082
1083
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
1084
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
1085
static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
1086
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
1087
1088
1089
static uint16_t sNativeProperties_sortedPropertyIndices[3];
1090
static PropertyInfo sNativeProperties_propertyInfos[3];
1091
1092
static const NativePropertiesN<1> sNativeProperties = {
1093
  false, 0,
1094
  false, 0,
1095
  true,  0 /* sMethods */,
1096
  false, 0,
1097
  false, 0,
1098
  false, 0,
1099
  false, 0,
1100
  -1,
1101
  3,
1102
  sNativeProperties_sortedPropertyIndices,
1103
  {
1104
    { sMethods, &sNativeProperties_propertyInfos[0] }
1105
  }
1106
};
1107
static_assert(3 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
1108
    "We have a property info count that is oversized");
1109
1110
static uint16_t sChromeOnlyNativeProperties_sortedPropertyIndices[3];
1111
static PropertyInfo sChromeOnlyNativeProperties_propertyInfos[3];
1112
1113
static const NativePropertiesN<2> sChromeOnlyNativeProperties = {
1114
  false, 0,
1115
  false, 0,
1116
  true,  0 /* sChromeMethods */,
1117
  true,  1 /* sChromeAttributes */,
1118
  false, 0,
1119
  false, 0,
1120
  false, 0,
1121
  -1,
1122
  3,
1123
  sChromeOnlyNativeProperties_sortedPropertyIndices,
1124
  {
1125
    { sChromeMethods, &sChromeOnlyNativeProperties_propertyInfos[0] },
1126
    { sChromeAttributes, &sChromeOnlyNativeProperties_propertyInfos[1] }
1127
  }
1128
};
1129
static_assert(3 < 1ull << CHAR_BIT * sizeof(sChromeOnlyNativeProperties.propertyInfoCount),
1130
    "We have a property info count that is oversized");
1131
1132
static bool
1133
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
1134
0
{
1135
0
  AUTO_PROFILER_LABEL_FAST("MutationObserver constructor", DOM, cx);
1136
0
1137
0
  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
1138
0
  JS::Rooted<JSObject*> obj(cx, &args.callee());
1139
0
  if (!args.isConstructing()) {
1140
0
    // XXXbz wish I could get the name from the callee instead of
1141
0
    // Adding more relocations
1142
0
    return ThrowConstructorWithoutNew(cx, "MutationObserver");
1143
0
  }
1144
0
1145
0
  JS::Rooted<JSObject*> desiredProto(cx);
1146
0
  if (!GetDesiredProto(cx, args, &desiredProto)) {
1147
0
    return false;
1148
0
  }
1149
0
1150
0
  if (MOZ_UNLIKELY(args.length() < 1)) {
1151
0
    return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "MutationObserver");
1152
0
  }
1153
0
  GlobalObject global(cx, obj);
1154
0
  if (global.Failed()) {
1155
0
    return false;
1156
0
  }
1157
0
1158
0
  bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
1159
0
  RootedCallback<OwningNonNull<binding_detail::FastMutationCallback>> arg0(cx);
1160
0
  if (args[0].isObject()) {
1161
0
    if (JS::IsCallable(&args[0].toObject())) {
1162
0
    { // scope for tempRoot and tempGlobalRoot if needed
1163
0
      arg0 = new binding_detail::FastMutationCallback(&args[0].toObject(), JS::CurrentGlobalOrNull(cx));
1164
0
    }
1165
0
    } else {
1166
0
      ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "Argument 1 of MutationObserver.constructor");
1167
0
      return false;
1168
0
    }
1169
0
  } else {
1170
0
    ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of MutationObserver.constructor");
1171
0
    return false;
1172
0
  }
1173
0
  Maybe<JSAutoRealm> ar;
1174
0
  if (objIsXray) {
1175
0
    obj = js::CheckedUnwrap(obj);
1176
0
    if (!obj) {
1177
0
      return false;
1178
0
    }
1179
0
    ar.emplace(cx, obj);
1180
0
    if (!JS_WrapObject(cx, &desiredProto)) {
1181
0
      return false;
1182
0
    }
1183
0
  }
1184
0
  FastErrorResult rv;
1185
0
  auto result(StrongOrRawPtr<nsDOMMutationObserver>(nsDOMMutationObserver::Constructor(global, NonNullHelper(arg0), rv)));
1186
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
1187
0
    return false;
1188
0
  }
1189
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1190
0
  static_assert(!IsPointer<decltype(result)>::value,
1191
0
                "NewObject implies that we need to keep the object alive with a strong reference.");
1192
0
  if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
1193
0
    MOZ_ASSERT(JS_IsExceptionPending(cx));
1194
0
    return false;
1195
0
  }
1196
0
  return true;
1197
0
}
1198
1199
static const js::ClassOps sInterfaceObjectClassOps = {
1200
    nullptr,               /* addProperty */
1201
    nullptr,               /* delProperty */
1202
    nullptr,               /* enumerate */
1203
    nullptr,               /* newEnumerate */
1204
    nullptr,               /* resolve */
1205
    nullptr,               /* mayResolve */
1206
    nullptr,               /* finalize */
1207
    _constructor, /* call */
1208
    nullptr,               /* hasInstance */
1209
    _constructor, /* construct */
1210
    nullptr,               /* trace */
1211
};
1212
1213
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
1214
  {
1215
    "Function",
1216
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
1217
    &sInterfaceObjectClassOps,
1218
    JS_NULL_CLASS_SPEC,
1219
    JS_NULL_CLASS_EXT,
1220
    &sInterfaceObjectClassObjectOps
1221
  },
1222
  eInterface,
1223
  true,
1224
  prototypes::id::MutationObserver,
1225
  PrototypeTraits<prototypes::id::MutationObserver>::Depth,
1226
  sNativePropertyHooks,
1227
  "function MutationObserver() {\n    [native code]\n}",
1228
  JS::GetRealmFunctionPrototype
1229
};
1230
1231
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
1232
  {
1233
    "MutationObserverPrototype",
1234
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
1235
    JS_NULL_CLASS_OPS,
1236
    JS_NULL_CLASS_SPEC,
1237
    JS_NULL_CLASS_EXT,
1238
    JS_NULL_OBJECT_OPS
1239
  },
1240
  eInterfacePrototype,
1241
  false,
1242
  prototypes::id::MutationObserver,
1243
  PrototypeTraits<prototypes::id::MutationObserver>::Depth,
1244
  sNativePropertyHooks,
1245
  "[object MutationObserverPrototype]",
1246
  JS::GetRealmObjectPrototype
1247
};
1248
1249
static const js::ClassOps sClassOps = {
1250
  _addProperty, /* addProperty */
1251
  nullptr,               /* delProperty */
1252
  nullptr,               /* enumerate */
1253
  nullptr, /* newEnumerate */
1254
  nullptr, /* resolve */
1255
  nullptr, /* mayResolve */
1256
  _finalize, /* finalize */
1257
  nullptr, /* call */
1258
  nullptr,               /* hasInstance */
1259
  nullptr,               /* construct */
1260
  nullptr, /* trace */
1261
};
1262
1263
static const js::ClassExtension sClassExtension = {
1264
  nullptr, /* weakmapKeyDelegateOp */
1265
  _objectMoved /* objectMovedOp */
1266
};
1267
1268
static const DOMJSClass sClass = {
1269
  { "MutationObserver",
1270
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
1271
    &sClassOps,
1272
    JS_NULL_CLASS_SPEC,
1273
    &sClassExtension,
1274
    JS_NULL_OBJECT_OPS
1275
  },
1276
  { prototypes::id::MutationObserver, 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 },
1277
  IsBaseOf<nsISupports, nsDOMMutationObserver >::value,
1278
  sNativePropertyHooks,
1279
  FindAssociatedGlobalForNative<nsDOMMutationObserver>::Get,
1280
  GetProtoObjectHandle,
1281
  GetCCParticipant<nsDOMMutationObserver>::Get()
1282
};
1283
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
1284
              "Must have the right minimal number of reserved slots.");
1285
static_assert(1 >= 1,
1286
              "Must have enough reserved slots.");
1287
1288
const JSClass*
1289
GetJSClass()
1290
0
{
1291
0
  return sClass.ToJSClass();
1292
0
}
1293
1294
bool
1295
Wrap(JSContext* aCx, nsDOMMutationObserver* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
1296
0
{
1297
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, nsDOMMutationObserver>::value,
1298
0
                "Shouldn't have wrappercached things that are not refcounted.");
1299
0
  MOZ_ASSERT(static_cast<nsDOMMutationObserver*>(aObject) ==
1300
0
             reinterpret_cast<nsDOMMutationObserver*>(aObject),
1301
0
             "Multiple inheritance for nsDOMMutationObserver is broken.");
1302
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
1303
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
1304
0
  MOZ_ASSERT(!aCache->GetWrapper(),
1305
0
             "You should probably not be using Wrap() directly; use "
1306
0
             "GetOrCreateDOMReflector instead");
1307
0
1308
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
1309
0
             "nsISupports must be on our primary inheritance chain");
1310
0
1311
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
1312
0
  if (!global) {
1313
0
    return false;
1314
0
  }
1315
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
1316
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
1317
0
1318
0
  // That might have ended up wrapping us already, due to the wonders
1319
0
  // of XBL.  Check for that, and bail out as needed.
1320
0
  aReflector.set(aCache->GetWrapper());
1321
0
  if (aReflector) {
1322
#ifdef DEBUG
1323
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
1324
#endif // DEBUG
1325
    return true;
1326
0
  }
1327
0
1328
0
  JSAutoRealm ar(aCx, global);
1329
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
1330
0
  if (!canonicalProto) {
1331
0
    return false;
1332
0
  }
1333
0
  JS::Rooted<JSObject*> proto(aCx);
1334
0
  if (aGivenProto) {
1335
0
    proto = aGivenProto;
1336
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
1337
0
    // coming in, we changed compartments to that of "parent" so may need
1338
0
    // to wrap the proto here.
1339
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
1340
0
      if (!JS_WrapObject(aCx, &proto)) {
1341
0
        return false;
1342
0
      }
1343
0
    }
1344
0
  } else {
1345
0
    proto = canonicalProto;
1346
0
  }
1347
0
1348
0
  BindingJSObjectCreator<nsDOMMutationObserver> creator(aCx);
1349
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
1350
0
  if (!aReflector) {
1351
0
    return false;
1352
0
  }
1353
0
1354
0
  aCache->SetWrapper(aReflector);
1355
0
  creator.InitializationSucceeded();
1356
0
1357
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
1358
0
             aCache->GetWrapperPreserveColor() == aReflector);
1359
0
  // If proto != canonicalProto, we have to preserve our wrapper;
1360
0
  // otherwise we won't be able to properly recreate it later, since
1361
0
  // we won't know what proto to use.  Note that we don't check
1362
0
  // aGivenProto here, since it's entirely possible (and even
1363
0
  // somewhat common) to have a non-null aGivenProto which is the
1364
0
  // same as canonicalProto.
1365
0
  if (proto != canonicalProto) {
1366
0
    PreserveWrapper(aObject);
1367
0
  }
1368
0
1369
0
  return true;
1370
0
}
1371
1372
const NativePropertyHooks sNativePropertyHooks[] = { {
1373
  nullptr,
1374
  nullptr,
1375
  nullptr,
1376
  { sNativeProperties.Upcast(), sChromeOnlyNativeProperties.Upcast() },
1377
  prototypes::id::MutationObserver,
1378
  constructors::id::MutationObserver,
1379
  nullptr,
1380
  &DefaultXrayExpandoObjectClass
1381
} };
1382
1383
void
1384
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
1385
0
{
1386
0
  JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
1387
0
  if (!parentProto) {
1388
0
    return;
1389
0
  }
1390
0
1391
0
  JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
1392
0
  if (!constructorProto) {
1393
0
    return;
1394
0
  }
1395
0
1396
0
  static bool sIdsInited = false;
1397
0
  if (!sIdsInited && NS_IsMainThread()) {
1398
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
1399
0
      return;
1400
0
    }
1401
0
    if (!InitIds(aCx, sChromeOnlyNativeProperties.Upcast())) {
1402
0
      return;
1403
0
    }
1404
0
    sIdsInited = true;
1405
0
  }
1406
0
1407
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::MutationObserver);
1408
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::MutationObserver);
1409
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
1410
0
                              &sPrototypeClass.mBase, protoCache,
1411
0
                              nullptr,
1412
0
                              constructorProto, &sInterfaceObjectClass.mBase, 1, nullptr,
1413
0
                              interfaceCache,
1414
0
                              sNativeProperties.Upcast(),
1415
0
                              sChromeOnlyNativeProperties.Upcast(),
1416
0
                              "MutationObserver", aDefineOnGlobal,
1417
0
                              nullptr,
1418
0
                              false);
1419
0
}
1420
1421
JSObject*
1422
GetConstructorObject(JSContext* aCx)
1423
0
{
1424
0
  return GetConstructorObjectHandle(aCx);
1425
0
}
1426
1427
} // namespace MutationObserver_Binding
1428
1429
1430
1431
namespace MutationRecord_Binding {
1432
1433
MOZ_CAN_RUN_SCRIPT static bool
1434
get_type(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationRecord* self, JSJitGetterCallArgs args)
1435
0
{
1436
0
  AUTO_PROFILER_LABEL_FAST("get MutationRecord.type", DOM, cx);
1437
0
1438
0
  DOMString result;
1439
0
  self->GetType(result);
1440
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1441
0
  if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
1442
0
    return false;
1443
0
  }
1444
0
  return true;
1445
0
}
1446
1447
static const JSJitInfo type_getterinfo = {
1448
  { (JSJitGetterOp)get_type },
1449
  { prototypes::id::MutationRecord },
1450
  { PrototypeTraits<prototypes::id::MutationRecord>::Depth },
1451
  JSJitInfo::Getter,
1452
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
1453
  JSVAL_TYPE_STRING,  /* returnType.  Not relevant for setters. */
1454
  false,  /* isInfallible. False in setters. */
1455
  true,  /* isMovable.  Not relevant for setters. */
1456
  true, /* isEliminatable.  Not relevant for setters. */
1457
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1458
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1459
  false,  /* isTypedMethod.  Only relevant for methods. */
1460
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1461
};
1462
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1463
static_assert(0 < 4, "There is no slot for us");
1464
1465
MOZ_CAN_RUN_SCRIPT static bool
1466
get_target(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationRecord* self, JSJitGetterCallArgs args)
1467
0
{
1468
0
  AUTO_PROFILER_LABEL_FAST("get MutationRecord.target", DOM, cx);
1469
0
1470
0
  auto result(StrongOrRawPtr<nsINode>(self->GetTarget()));
1471
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1472
0
  if (!result) {
1473
0
    args.rval().setNull();
1474
0
    return true;
1475
0
  }
1476
0
  if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
1477
0
    MOZ_ASSERT(JS_IsExceptionPending(cx));
1478
0
    return false;
1479
0
  }
1480
0
  return true;
1481
0
}
1482
1483
static const JSJitInfo target_getterinfo = {
1484
  { (JSJitGetterOp)get_target },
1485
  { prototypes::id::MutationRecord },
1486
  { PrototypeTraits<prototypes::id::MutationRecord>::Depth },
1487
  JSJitInfo::Getter,
1488
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
1489
  JSVAL_TYPE_UNKNOWN,  /* returnType.  Not relevant for setters. */
1490
  false,  /* isInfallible. False in setters. */
1491
  true,  /* isMovable.  Not relevant for setters. */
1492
  true, /* isEliminatable.  Not relevant for setters. */
1493
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1494
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1495
  false,  /* isTypedMethod.  Only relevant for methods. */
1496
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1497
};
1498
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1499
static_assert(0 < 4, "There is no slot for us");
1500
1501
MOZ_CAN_RUN_SCRIPT static bool
1502
get_addedNodes(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationRecord* self, JSJitGetterCallArgs args)
1503
0
{
1504
0
  AUTO_PROFILER_LABEL_FAST("get MutationRecord.addedNodes", DOM, cx);
1505
0
1506
0
  auto result(StrongOrRawPtr<nsINodeList>(self->AddedNodes()));
1507
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1508
0
  if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
1509
0
    MOZ_ASSERT(JS_IsExceptionPending(cx));
1510
0
    return false;
1511
0
  }
1512
0
  return true;
1513
0
}
1514
1515
static const JSJitInfo addedNodes_getterinfo = {
1516
  { (JSJitGetterOp)get_addedNodes },
1517
  { prototypes::id::MutationRecord },
1518
  { PrototypeTraits<prototypes::id::MutationRecord>::Depth },
1519
  JSJitInfo::Getter,
1520
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
1521
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
1522
  false,  /* isInfallible. False in setters. */
1523
  true,  /* isMovable.  Not relevant for setters. */
1524
  true, /* isEliminatable.  Not relevant for setters. */
1525
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1526
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1527
  false,  /* isTypedMethod.  Only relevant for methods. */
1528
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1529
};
1530
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1531
static_assert(0 < 4, "There is no slot for us");
1532
1533
MOZ_CAN_RUN_SCRIPT static bool
1534
get_removedNodes(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationRecord* self, JSJitGetterCallArgs args)
1535
0
{
1536
0
  AUTO_PROFILER_LABEL_FAST("get MutationRecord.removedNodes", DOM, cx);
1537
0
1538
0
  auto result(StrongOrRawPtr<nsINodeList>(self->RemovedNodes()));
1539
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1540
0
  if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
1541
0
    MOZ_ASSERT(JS_IsExceptionPending(cx));
1542
0
    return false;
1543
0
  }
1544
0
  return true;
1545
0
}
1546
1547
static const JSJitInfo removedNodes_getterinfo = {
1548
  { (JSJitGetterOp)get_removedNodes },
1549
  { prototypes::id::MutationRecord },
1550
  { PrototypeTraits<prototypes::id::MutationRecord>::Depth },
1551
  JSJitInfo::Getter,
1552
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
1553
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
1554
  false,  /* isInfallible. False in setters. */
1555
  true,  /* isMovable.  Not relevant for setters. */
1556
  true, /* isEliminatable.  Not relevant for setters. */
1557
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1558
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1559
  false,  /* isTypedMethod.  Only relevant for methods. */
1560
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1561
};
1562
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1563
static_assert(0 < 4, "There is no slot for us");
1564
1565
MOZ_CAN_RUN_SCRIPT static bool
1566
get_previousSibling(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationRecord* self, JSJitGetterCallArgs args)
1567
0
{
1568
0
  AUTO_PROFILER_LABEL_FAST("get MutationRecord.previousSibling", DOM, cx);
1569
0
1570
0
  auto result(StrongOrRawPtr<nsINode>(self->GetPreviousSibling()));
1571
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1572
0
  if (!result) {
1573
0
    args.rval().setNull();
1574
0
    return true;
1575
0
  }
1576
0
  if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
1577
0
    MOZ_ASSERT(JS_IsExceptionPending(cx));
1578
0
    return false;
1579
0
  }
1580
0
  return true;
1581
0
}
1582
1583
static const JSJitInfo previousSibling_getterinfo = {
1584
  { (JSJitGetterOp)get_previousSibling },
1585
  { prototypes::id::MutationRecord },
1586
  { PrototypeTraits<prototypes::id::MutationRecord>::Depth },
1587
  JSJitInfo::Getter,
1588
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
1589
  JSVAL_TYPE_UNKNOWN,  /* returnType.  Not relevant for setters. */
1590
  false,  /* isInfallible. False in setters. */
1591
  true,  /* isMovable.  Not relevant for setters. */
1592
  true, /* isEliminatable.  Not relevant for setters. */
1593
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1594
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1595
  false,  /* isTypedMethod.  Only relevant for methods. */
1596
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1597
};
1598
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1599
static_assert(0 < 4, "There is no slot for us");
1600
1601
MOZ_CAN_RUN_SCRIPT static bool
1602
get_nextSibling(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationRecord* self, JSJitGetterCallArgs args)
1603
0
{
1604
0
  AUTO_PROFILER_LABEL_FAST("get MutationRecord.nextSibling", DOM, cx);
1605
0
1606
0
  auto result(StrongOrRawPtr<nsINode>(self->GetNextSibling()));
1607
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1608
0
  if (!result) {
1609
0
    args.rval().setNull();
1610
0
    return true;
1611
0
  }
1612
0
  if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
1613
0
    MOZ_ASSERT(JS_IsExceptionPending(cx));
1614
0
    return false;
1615
0
  }
1616
0
  return true;
1617
0
}
1618
1619
static const JSJitInfo nextSibling_getterinfo = {
1620
  { (JSJitGetterOp)get_nextSibling },
1621
  { prototypes::id::MutationRecord },
1622
  { PrototypeTraits<prototypes::id::MutationRecord>::Depth },
1623
  JSJitInfo::Getter,
1624
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
1625
  JSVAL_TYPE_UNKNOWN,  /* returnType.  Not relevant for setters. */
1626
  false,  /* isInfallible. False in setters. */
1627
  true,  /* isMovable.  Not relevant for setters. */
1628
  true, /* isEliminatable.  Not relevant for setters. */
1629
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1630
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1631
  false,  /* isTypedMethod.  Only relevant for methods. */
1632
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1633
};
1634
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1635
static_assert(0 < 4, "There is no slot for us");
1636
1637
MOZ_CAN_RUN_SCRIPT static bool
1638
get_attributeName(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationRecord* self, JSJitGetterCallArgs args)
1639
0
{
1640
0
  AUTO_PROFILER_LABEL_FAST("get MutationRecord.attributeName", DOM, cx);
1641
0
1642
0
  DOMString result;
1643
0
  self->GetAttributeName(result);
1644
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1645
0
  if (!xpc::StringToJsval(cx, result, args.rval())) {
1646
0
    return false;
1647
0
  }
1648
0
  return true;
1649
0
}
1650
1651
static const JSJitInfo attributeName_getterinfo = {
1652
  { (JSJitGetterOp)get_attributeName },
1653
  { prototypes::id::MutationRecord },
1654
  { PrototypeTraits<prototypes::id::MutationRecord>::Depth },
1655
  JSJitInfo::Getter,
1656
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
1657
  JSVAL_TYPE_UNKNOWN,  /* returnType.  Not relevant for setters. */
1658
  false,  /* isInfallible. False in setters. */
1659
  true,  /* isMovable.  Not relevant for setters. */
1660
  true, /* isEliminatable.  Not relevant for setters. */
1661
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1662
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1663
  false,  /* isTypedMethod.  Only relevant for methods. */
1664
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1665
};
1666
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1667
static_assert(0 < 4, "There is no slot for us");
1668
1669
MOZ_CAN_RUN_SCRIPT static bool
1670
get_attributeNamespace(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationRecord* self, JSJitGetterCallArgs args)
1671
0
{
1672
0
  AUTO_PROFILER_LABEL_FAST("get MutationRecord.attributeNamespace", DOM, cx);
1673
0
1674
0
  DOMString result;
1675
0
  self->GetAttributeNamespace(result);
1676
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1677
0
  if (!xpc::StringToJsval(cx, result, args.rval())) {
1678
0
    return false;
1679
0
  }
1680
0
  return true;
1681
0
}
1682
1683
static const JSJitInfo attributeNamespace_getterinfo = {
1684
  { (JSJitGetterOp)get_attributeNamespace },
1685
  { prototypes::id::MutationRecord },
1686
  { PrototypeTraits<prototypes::id::MutationRecord>::Depth },
1687
  JSJitInfo::Getter,
1688
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
1689
  JSVAL_TYPE_UNKNOWN,  /* returnType.  Not relevant for setters. */
1690
  false,  /* isInfallible. False in setters. */
1691
  true,  /* isMovable.  Not relevant for setters. */
1692
  true, /* isEliminatable.  Not relevant for setters. */
1693
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1694
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1695
  false,  /* isTypedMethod.  Only relevant for methods. */
1696
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1697
};
1698
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1699
static_assert(0 < 4, "There is no slot for us");
1700
1701
MOZ_CAN_RUN_SCRIPT static bool
1702
get_oldValue(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationRecord* self, JSJitGetterCallArgs args)
1703
0
{
1704
0
  AUTO_PROFILER_LABEL_FAST("get MutationRecord.oldValue", DOM, cx);
1705
0
1706
0
  DOMString result;
1707
0
  self->GetOldValue(result);
1708
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1709
0
  if (!xpc::StringToJsval(cx, result, args.rval())) {
1710
0
    return false;
1711
0
  }
1712
0
  return true;
1713
0
}
1714
1715
static const JSJitInfo oldValue_getterinfo = {
1716
  { (JSJitGetterOp)get_oldValue },
1717
  { prototypes::id::MutationRecord },
1718
  { PrototypeTraits<prototypes::id::MutationRecord>::Depth },
1719
  JSJitInfo::Getter,
1720
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
1721
  JSVAL_TYPE_UNKNOWN,  /* returnType.  Not relevant for setters. */
1722
  false,  /* isInfallible. False in setters. */
1723
  true,  /* isMovable.  Not relevant for setters. */
1724
  true, /* isEliminatable.  Not relevant for setters. */
1725
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1726
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1727
  false,  /* isTypedMethod.  Only relevant for methods. */
1728
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1729
};
1730
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1731
static_assert(0 < 4, "There is no slot for us");
1732
1733
MOZ_CAN_RUN_SCRIPT static bool
1734
get_addedAnimations(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationRecord* self, JSJitGetterCallArgs args)
1735
0
{
1736
0
  AUTO_PROFILER_LABEL_FAST("get MutationRecord.addedAnimations", DOM, cx);
1737
0
1738
0
  // Have to either root across the getter call or reget after.
1739
0
  bool isXray;
1740
0
  JS::Rooted<JSObject*> slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray));
1741
0
  if (!slotStorage) {
1742
0
    return false;
1743
0
  }
1744
0
  const size_t slotIndex = isXray ? (xpc::JSSLOT_EXPANDO_COUNT + 0) : (DOM_INSTANCE_RESERVED_SLOTS + 0);
1745
0
  MOZ_ASSERT(JSCLASS_RESERVED_SLOTS(js::GetObjectClass(slotStorage)) > slotIndex);
1746
0
  {
1747
0
    // Scope for cachedVal
1748
0
    JS::Value cachedVal = js::GetReservedSlot(slotStorage, slotIndex);
1749
0
    if (!cachedVal.isUndefined()) {
1750
0
      args.rval().set(cachedVal);
1751
0
      // The cached value is in the compartment of slotStorage,
1752
0
      // so wrap into the caller compartment as needed.
1753
0
      if (MaybeWrapNonDOMObjectValue(cx, args.rval())) {
1754
0
        return true;
1755
0
      }
1756
0
      return false;
1757
0
    }
1758
0
  }
1759
0
1760
0
  nsTArray<StrongPtrForMember<mozilla::dom::Animation>::Type> result;
1761
0
  self->GetAddedAnimations(result);
1762
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1763
0
  {
1764
0
    JS::Rooted<JSObject*> conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage);
1765
0
    JSAutoRealm ar(cx, conversionScope);
1766
0
    do { // block we break out of when done wrapping
1767
0
1768
0
      uint32_t length = result.Length();
1769
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
1770
0
      if (!returnArray) {
1771
0
        return false;
1772
0
      }
1773
0
      // Scope for 'tmp'
1774
0
      {
1775
0
        JS::Rooted<JS::Value> tmp(cx);
1776
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
1777
0
          // Control block to let us common up the JS_DefineElement calls when there
1778
0
          // are different ways to succeed at wrapping the object.
1779
0
          do {
1780
0
            if (!GetOrCreateDOMReflector(cx, result[sequenceIdx0], &tmp)) {
1781
0
              MOZ_ASSERT(JS_IsExceptionPending(cx));
1782
0
              return false;
1783
0
            }
1784
0
            break;
1785
0
          } while (false);
1786
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
1787
0
                                JSPROP_ENUMERATE)) {
1788
0
            return false;
1789
0
          }
1790
0
        }
1791
0
      }
1792
0
      args.rval().setObject(*returnArray);
1793
0
      break;
1794
0
    } while (false);
1795
0
  }
1796
0
  { // And now store things in the realm of our slotStorage.
1797
0
    JSAutoRealm ar(cx, slotStorage);
1798
0
    // Make a copy so that we don't do unnecessary wrapping on args.rval().
1799
0
    JS::Rooted<JS::Value> storedVal(cx, args.rval());
1800
0
    if (!MaybeWrapNonDOMObjectValue(cx, &storedVal)) {
1801
0
      return false;
1802
0
    }
1803
0
    js::SetReservedSlot(slotStorage, slotIndex, storedVal);
1804
0
    if (!isXray) {
1805
0
      // In the Xray case we don't need to do this, because getting the
1806
0
      // expando object already preserved our wrapper.
1807
0
      PreserveWrapper(self);
1808
0
    }
1809
0
  }
1810
0
  // And now make sure args.rval() is in the caller realm.
1811
0
  if (MaybeWrapNonDOMObjectValue(cx, args.rval())) {
1812
0
    return true;
1813
0
  }
1814
0
  return false;
1815
0
}
1816
1817
static const JSJitInfo addedAnimations_getterinfo = {
1818
  { (JSJitGetterOp)get_addedAnimations },
1819
  { prototypes::id::MutationRecord },
1820
  { PrototypeTraits<prototypes::id::MutationRecord>::Depth },
1821
  JSJitInfo::Getter,
1822
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
1823
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
1824
  false,  /* isInfallible. False in setters. */
1825
  true,  /* isMovable.  Not relevant for setters. */
1826
  true, /* isEliminatable.  Not relevant for setters. */
1827
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1828
  true, /* isLazilyCachedInSlot.  Only relevant for getters. */
1829
  false,  /* isTypedMethod.  Only relevant for methods. */
1830
  (DOM_INSTANCE_RESERVED_SLOTS + 0)   /* Reserved slot index, if we're stored in a slot, else 0. */
1831
};
1832
static_assert((DOM_INSTANCE_RESERVED_SLOTS + 0) <= JSJitInfo::maxSlotIndex, "We won't fit");
1833
static_assert((DOM_INSTANCE_RESERVED_SLOTS + 0) < 4, "There is no slot for us");
1834
1835
MOZ_CAN_RUN_SCRIPT static bool
1836
get_changedAnimations(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationRecord* self, JSJitGetterCallArgs args)
1837
0
{
1838
0
  AUTO_PROFILER_LABEL_FAST("get MutationRecord.changedAnimations", DOM, cx);
1839
0
1840
0
  // Have to either root across the getter call or reget after.
1841
0
  bool isXray;
1842
0
  JS::Rooted<JSObject*> slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray));
1843
0
  if (!slotStorage) {
1844
0
    return false;
1845
0
  }
1846
0
  const size_t slotIndex = isXray ? (xpc::JSSLOT_EXPANDO_COUNT + 1) : (DOM_INSTANCE_RESERVED_SLOTS + 1);
1847
0
  MOZ_ASSERT(JSCLASS_RESERVED_SLOTS(js::GetObjectClass(slotStorage)) > slotIndex);
1848
0
  {
1849
0
    // Scope for cachedVal
1850
0
    JS::Value cachedVal = js::GetReservedSlot(slotStorage, slotIndex);
1851
0
    if (!cachedVal.isUndefined()) {
1852
0
      args.rval().set(cachedVal);
1853
0
      // The cached value is in the compartment of slotStorage,
1854
0
      // so wrap into the caller compartment as needed.
1855
0
      if (MaybeWrapNonDOMObjectValue(cx, args.rval())) {
1856
0
        return true;
1857
0
      }
1858
0
      return false;
1859
0
    }
1860
0
  }
1861
0
1862
0
  nsTArray<StrongPtrForMember<mozilla::dom::Animation>::Type> result;
1863
0
  self->GetChangedAnimations(result);
1864
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1865
0
  {
1866
0
    JS::Rooted<JSObject*> conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage);
1867
0
    JSAutoRealm ar(cx, conversionScope);
1868
0
    do { // block we break out of when done wrapping
1869
0
1870
0
      uint32_t length = result.Length();
1871
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
1872
0
      if (!returnArray) {
1873
0
        return false;
1874
0
      }
1875
0
      // Scope for 'tmp'
1876
0
      {
1877
0
        JS::Rooted<JS::Value> tmp(cx);
1878
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
1879
0
          // Control block to let us common up the JS_DefineElement calls when there
1880
0
          // are different ways to succeed at wrapping the object.
1881
0
          do {
1882
0
            if (!GetOrCreateDOMReflector(cx, result[sequenceIdx0], &tmp)) {
1883
0
              MOZ_ASSERT(JS_IsExceptionPending(cx));
1884
0
              return false;
1885
0
            }
1886
0
            break;
1887
0
          } while (false);
1888
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
1889
0
                                JSPROP_ENUMERATE)) {
1890
0
            return false;
1891
0
          }
1892
0
        }
1893
0
      }
1894
0
      args.rval().setObject(*returnArray);
1895
0
      break;
1896
0
    } while (false);
1897
0
  }
1898
0
  { // And now store things in the realm of our slotStorage.
1899
0
    JSAutoRealm ar(cx, slotStorage);
1900
0
    // Make a copy so that we don't do unnecessary wrapping on args.rval().
1901
0
    JS::Rooted<JS::Value> storedVal(cx, args.rval());
1902
0
    if (!MaybeWrapNonDOMObjectValue(cx, &storedVal)) {
1903
0
      return false;
1904
0
    }
1905
0
    js::SetReservedSlot(slotStorage, slotIndex, storedVal);
1906
0
    if (!isXray) {
1907
0
      // In the Xray case we don't need to do this, because getting the
1908
0
      // expando object already preserved our wrapper.
1909
0
      PreserveWrapper(self);
1910
0
    }
1911
0
  }
1912
0
  // And now make sure args.rval() is in the caller realm.
1913
0
  if (MaybeWrapNonDOMObjectValue(cx, args.rval())) {
1914
0
    return true;
1915
0
  }
1916
0
  return false;
1917
0
}
1918
1919
static const JSJitInfo changedAnimations_getterinfo = {
1920
  { (JSJitGetterOp)get_changedAnimations },
1921
  { prototypes::id::MutationRecord },
1922
  { PrototypeTraits<prototypes::id::MutationRecord>::Depth },
1923
  JSJitInfo::Getter,
1924
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
1925
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
1926
  false,  /* isInfallible. False in setters. */
1927
  true,  /* isMovable.  Not relevant for setters. */
1928
  true, /* isEliminatable.  Not relevant for setters. */
1929
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1930
  true, /* isLazilyCachedInSlot.  Only relevant for getters. */
1931
  false,  /* isTypedMethod.  Only relevant for methods. */
1932
  (DOM_INSTANCE_RESERVED_SLOTS + 1)   /* Reserved slot index, if we're stored in a slot, else 0. */
1933
};
1934
static_assert((DOM_INSTANCE_RESERVED_SLOTS + 1) <= JSJitInfo::maxSlotIndex, "We won't fit");
1935
static_assert((DOM_INSTANCE_RESERVED_SLOTS + 1) < 4, "There is no slot for us");
1936
1937
MOZ_CAN_RUN_SCRIPT static bool
1938
get_removedAnimations(JSContext* cx, JS::Handle<JSObject*> obj, nsDOMMutationRecord* self, JSJitGetterCallArgs args)
1939
0
{
1940
0
  AUTO_PROFILER_LABEL_FAST("get MutationRecord.removedAnimations", DOM, cx);
1941
0
1942
0
  // Have to either root across the getter call or reget after.
1943
0
  bool isXray;
1944
0
  JS::Rooted<JSObject*> slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray));
1945
0
  if (!slotStorage) {
1946
0
    return false;
1947
0
  }
1948
0
  const size_t slotIndex = isXray ? (xpc::JSSLOT_EXPANDO_COUNT + 2) : (DOM_INSTANCE_RESERVED_SLOTS + 2);
1949
0
  MOZ_ASSERT(JSCLASS_RESERVED_SLOTS(js::GetObjectClass(slotStorage)) > slotIndex);
1950
0
  {
1951
0
    // Scope for cachedVal
1952
0
    JS::Value cachedVal = js::GetReservedSlot(slotStorage, slotIndex);
1953
0
    if (!cachedVal.isUndefined()) {
1954
0
      args.rval().set(cachedVal);
1955
0
      // The cached value is in the compartment of slotStorage,
1956
0
      // so wrap into the caller compartment as needed.
1957
0
      if (MaybeWrapNonDOMObjectValue(cx, args.rval())) {
1958
0
        return true;
1959
0
      }
1960
0
      return false;
1961
0
    }
1962
0
  }
1963
0
1964
0
  nsTArray<StrongPtrForMember<mozilla::dom::Animation>::Type> result;
1965
0
  self->GetRemovedAnimations(result);
1966
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1967
0
  {
1968
0
    JS::Rooted<JSObject*> conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage);
1969
0
    JSAutoRealm ar(cx, conversionScope);
1970
0
    do { // block we break out of when done wrapping
1971
0
1972
0
      uint32_t length = result.Length();
1973
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
1974
0
      if (!returnArray) {
1975
0
        return false;
1976
0
      }
1977
0
      // Scope for 'tmp'
1978
0
      {
1979
0
        JS::Rooted<JS::Value> tmp(cx);
1980
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
1981
0
          // Control block to let us common up the JS_DefineElement calls when there
1982
0
          // are different ways to succeed at wrapping the object.
1983
0
          do {
1984
0
            if (!GetOrCreateDOMReflector(cx, result[sequenceIdx0], &tmp)) {
1985
0
              MOZ_ASSERT(JS_IsExceptionPending(cx));
1986
0
              return false;
1987
0
            }
1988
0
            break;
1989
0
          } while (false);
1990
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
1991
0
                                JSPROP_ENUMERATE)) {
1992
0
            return false;
1993
0
          }
1994
0
        }
1995
0
      }
1996
0
      args.rval().setObject(*returnArray);
1997
0
      break;
1998
0
    } while (false);
1999
0
  }
2000
0
  { // And now store things in the realm of our slotStorage.
2001
0
    JSAutoRealm ar(cx, slotStorage);
2002
0
    // Make a copy so that we don't do unnecessary wrapping on args.rval().
2003
0
    JS::Rooted<JS::Value> storedVal(cx, args.rval());
2004
0
    if (!MaybeWrapNonDOMObjectValue(cx, &storedVal)) {
2005
0
      return false;
2006
0
    }
2007
0
    js::SetReservedSlot(slotStorage, slotIndex, storedVal);
2008
0
    if (!isXray) {
2009
0
      // In the Xray case we don't need to do this, because getting the
2010
0
      // expando object already preserved our wrapper.
2011
0
      PreserveWrapper(self);
2012
0
    }
2013
0
  }
2014
0
  // And now make sure args.rval() is in the caller realm.
2015
0
  if (MaybeWrapNonDOMObjectValue(cx, args.rval())) {
2016
0
    return true;
2017
0
  }
2018
0
  return false;
2019
0
}
2020
2021
static const JSJitInfo removedAnimations_getterinfo = {
2022
  { (JSJitGetterOp)get_removedAnimations },
2023
  { prototypes::id::MutationRecord },
2024
  { PrototypeTraits<prototypes::id::MutationRecord>::Depth },
2025
  JSJitInfo::Getter,
2026
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
2027
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
2028
  false,  /* isInfallible. False in setters. */
2029
  true,  /* isMovable.  Not relevant for setters. */
2030
  true, /* isEliminatable.  Not relevant for setters. */
2031
  false, /* isAlwaysInSlot.  Only relevant for getters. */
2032
  true, /* isLazilyCachedInSlot.  Only relevant for getters. */
2033
  false,  /* isTypedMethod.  Only relevant for methods. */
2034
  (DOM_INSTANCE_RESERVED_SLOTS + 2)   /* Reserved slot index, if we're stored in a slot, else 0. */
2035
};
2036
static_assert((DOM_INSTANCE_RESERVED_SLOTS + 2) <= JSJitInfo::maxSlotIndex, "We won't fit");
2037
static_assert((DOM_INSTANCE_RESERVED_SLOTS + 2) < 4, "There is no slot for us");
2038
2039
static bool
2040
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
2041
0
{
2042
0
  nsDOMMutationRecord* self = UnwrapPossiblyNotInitializedDOMObject<nsDOMMutationRecord>(obj);
2043
0
  // We don't want to preserve if we don't have a wrapper, and we
2044
0
  // obviously can't preserve if we're not initialized.
2045
0
  if (self && self->GetWrapperPreserveColor()) {
2046
0
    PreserveWrapper(self);
2047
0
  }
2048
0
  return true;
2049
0
}
2050
2051
static void
2052
_finalize(js::FreeOp* fop, JSObject* obj)
2053
0
{
2054
0
  nsDOMMutationRecord* self = UnwrapPossiblyNotInitializedDOMObject<nsDOMMutationRecord>(obj);
2055
0
  if (self) {
2056
0
    ClearWrapper(self, self, obj);
2057
0
    AddForDeferredFinalization<nsDOMMutationRecord>(self);
2058
0
  }
2059
0
}
2060
2061
static size_t
2062
_objectMoved(JSObject* obj, JSObject* old)
2063
0
{
2064
0
  nsDOMMutationRecord* self = UnwrapPossiblyNotInitializedDOMObject<nsDOMMutationRecord>(obj);
2065
0
  if (self) {
2066
0
    UpdateWrapper(self, self, obj, old);
2067
0
  }
2068
0
2069
0
  return 0;
2070
0
}
2071
2072
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
2073
#if defined(__clang__)
2074
#pragma clang diagnostic push
2075
#pragma clang diagnostic ignored "-Wmissing-braces"
2076
#endif
2077
static const JSPropertySpec sAttributes_specs[] = {
2078
  { "type", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &type_getterinfo, nullptr, nullptr },
2079
  { "target", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &target_getterinfo, nullptr, nullptr },
2080
  { "addedNodes", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &addedNodes_getterinfo, nullptr, nullptr },
2081
  { "removedNodes", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &removedNodes_getterinfo, nullptr, nullptr },
2082
  { "previousSibling", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &previousSibling_getterinfo, nullptr, nullptr },
2083
  { "nextSibling", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &nextSibling_getterinfo, nullptr, nullptr },
2084
  { "attributeName", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &attributeName_getterinfo, nullptr, nullptr },
2085
  { "attributeNamespace", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &attributeNamespace_getterinfo, nullptr, nullptr },
2086
  { "oldValue", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &oldValue_getterinfo, nullptr, nullptr },
2087
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
2088
};
2089
#if defined(__clang__)
2090
#pragma clang diagnostic pop
2091
#endif
2092
2093
2094
static const Prefable<const JSPropertySpec> sAttributes[] = {
2095
  { nullptr, &sAttributes_specs[0] },
2096
  { nullptr, nullptr }
2097
};
2098
2099
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
2100
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
2101
static_assert(9 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
2102
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
2103
2104
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
2105
#if defined(__clang__)
2106
#pragma clang diagnostic push
2107
#pragma clang diagnostic ignored "-Wmissing-braces"
2108
#endif
2109
static const JSPropertySpec sChromeAttributes_specs[] = {
2110
  { "addedAnimations", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &addedAnimations_getterinfo, nullptr, nullptr },
2111
  { "changedAnimations", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &changedAnimations_getterinfo, nullptr, nullptr },
2112
  { "removedAnimations", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &removedAnimations_getterinfo, nullptr, nullptr },
2113
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
2114
};
2115
#if defined(__clang__)
2116
#pragma clang diagnostic pop
2117
#endif
2118
2119
2120
static const Prefable<const JSPropertySpec> sChromeAttributes[] = {
2121
  { nullptr, &sChromeAttributes_specs[0] },
2122
  { nullptr, nullptr }
2123
};
2124
2125
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
2126
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
2127
static_assert(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
2128
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
2129
2130
2131
static uint16_t sNativeProperties_sortedPropertyIndices[9];
2132
static PropertyInfo sNativeProperties_propertyInfos[9];
2133
2134
static const NativePropertiesN<1> sNativeProperties = {
2135
  false, 0,
2136
  false, 0,
2137
  false, 0,
2138
  true,  0 /* sAttributes */,
2139
  false, 0,
2140
  false, 0,
2141
  false, 0,
2142
  -1,
2143
  9,
2144
  sNativeProperties_sortedPropertyIndices,
2145
  {
2146
    { sAttributes, &sNativeProperties_propertyInfos[0] }
2147
  }
2148
};
2149
static_assert(9 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
2150
    "We have a property info count that is oversized");
2151
2152
static uint16_t sChromeOnlyNativeProperties_sortedPropertyIndices[3];
2153
static PropertyInfo sChromeOnlyNativeProperties_propertyInfos[3];
2154
2155
static const NativePropertiesN<1> sChromeOnlyNativeProperties = {
2156
  false, 0,
2157
  false, 0,
2158
  false, 0,
2159
  true,  0 /* sChromeAttributes */,
2160
  false, 0,
2161
  false, 0,
2162
  false, 0,
2163
  -1,
2164
  3,
2165
  sChromeOnlyNativeProperties_sortedPropertyIndices,
2166
  {
2167
    { sChromeAttributes, &sChromeOnlyNativeProperties_propertyInfos[0] }
2168
  }
2169
};
2170
static_assert(3 < 1ull << CHAR_BIT * sizeof(sChromeOnlyNativeProperties.propertyInfoCount),
2171
    "We have a property info count that is oversized");
2172
2173
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
2174
  {
2175
    "Function",
2176
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
2177
    &sBoringInterfaceObjectClassClassOps,
2178
    JS_NULL_CLASS_SPEC,
2179
    JS_NULL_CLASS_EXT,
2180
    &sInterfaceObjectClassObjectOps
2181
  },
2182
  eInterface,
2183
  true,
2184
  prototypes::id::MutationRecord,
2185
  PrototypeTraits<prototypes::id::MutationRecord>::Depth,
2186
  sNativePropertyHooks,
2187
  "function MutationRecord() {\n    [native code]\n}",
2188
  JS::GetRealmFunctionPrototype
2189
};
2190
2191
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
2192
  {
2193
    "MutationRecordPrototype",
2194
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
2195
    JS_NULL_CLASS_OPS,
2196
    JS_NULL_CLASS_SPEC,
2197
    JS_NULL_CLASS_EXT,
2198
    JS_NULL_OBJECT_OPS
2199
  },
2200
  eInterfacePrototype,
2201
  false,
2202
  prototypes::id::MutationRecord,
2203
  PrototypeTraits<prototypes::id::MutationRecord>::Depth,
2204
  sNativePropertyHooks,
2205
  "[object MutationRecordPrototype]",
2206
  JS::GetRealmObjectPrototype
2207
};
2208
2209
static const js::ClassOps sClassOps = {
2210
  _addProperty, /* addProperty */
2211
  nullptr,               /* delProperty */
2212
  nullptr,               /* enumerate */
2213
  nullptr, /* newEnumerate */
2214
  nullptr, /* resolve */
2215
  nullptr, /* mayResolve */
2216
  _finalize, /* finalize */
2217
  nullptr, /* call */
2218
  nullptr,               /* hasInstance */
2219
  nullptr,               /* construct */
2220
  nullptr, /* trace */
2221
};
2222
2223
static const js::ClassExtension sClassExtension = {
2224
  nullptr, /* weakmapKeyDelegateOp */
2225
  _objectMoved /* objectMovedOp */
2226
};
2227
2228
static const DOMJSClass sClass = {
2229
  { "MutationRecord",
2230
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(4) | JSCLASS_SKIP_NURSERY_FINALIZE,
2231
    &sClassOps,
2232
    JS_NULL_CLASS_SPEC,
2233
    &sClassExtension,
2234
    JS_NULL_OBJECT_OPS
2235
  },
2236
  { prototypes::id::MutationRecord, 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 },
2237
  IsBaseOf<nsISupports, nsDOMMutationRecord >::value,
2238
  sNativePropertyHooks,
2239
  FindAssociatedGlobalForNative<nsDOMMutationRecord>::Get,
2240
  GetProtoObjectHandle,
2241
  GetCCParticipant<nsDOMMutationRecord>::Get()
2242
};
2243
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
2244
              "Must have the right minimal number of reserved slots.");
2245
static_assert(4 >= 4,
2246
              "Must have enough reserved slots.");
2247
2248
const JSClass*
2249
GetJSClass()
2250
0
{
2251
0
  return sClass.ToJSClass();
2252
0
}
2253
2254
bool
2255
Wrap(JSContext* aCx, nsDOMMutationRecord* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
2256
0
{
2257
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, nsDOMMutationRecord>::value,
2258
0
                "Shouldn't have wrappercached things that are not refcounted.");
2259
0
  MOZ_ASSERT(static_cast<nsDOMMutationRecord*>(aObject) ==
2260
0
             reinterpret_cast<nsDOMMutationRecord*>(aObject),
2261
0
             "Multiple inheritance for nsDOMMutationRecord is broken.");
2262
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
2263
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
2264
0
  MOZ_ASSERT(!aCache->GetWrapper(),
2265
0
             "You should probably not be using Wrap() directly; use "
2266
0
             "GetOrCreateDOMReflector instead");
2267
0
2268
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
2269
0
             "nsISupports must be on our primary inheritance chain");
2270
0
2271
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
2272
0
  if (!global) {
2273
0
    return false;
2274
0
  }
2275
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
2276
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
2277
0
2278
0
  // That might have ended up wrapping us already, due to the wonders
2279
0
  // of XBL.  Check for that, and bail out as needed.
2280
0
  aReflector.set(aCache->GetWrapper());
2281
0
  if (aReflector) {
2282
#ifdef DEBUG
2283
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
2284
#endif // DEBUG
2285
    return true;
2286
0
  }
2287
0
2288
0
  JSAutoRealm ar(aCx, global);
2289
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
2290
0
  if (!canonicalProto) {
2291
0
    return false;
2292
0
  }
2293
0
  JS::Rooted<JSObject*> proto(aCx);
2294
0
  if (aGivenProto) {
2295
0
    proto = aGivenProto;
2296
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
2297
0
    // coming in, we changed compartments to that of "parent" so may need
2298
0
    // to wrap the proto here.
2299
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
2300
0
      if (!JS_WrapObject(aCx, &proto)) {
2301
0
        return false;
2302
0
      }
2303
0
    }
2304
0
  } else {
2305
0
    proto = canonicalProto;
2306
0
  }
2307
0
2308
0
  BindingJSObjectCreator<nsDOMMutationRecord> creator(aCx);
2309
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
2310
0
  if (!aReflector) {
2311
0
    return false;
2312
0
  }
2313
0
2314
0
  aCache->SetWrapper(aReflector);
2315
0
  creator.InitializationSucceeded();
2316
0
2317
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
2318
0
             aCache->GetWrapperPreserveColor() == aReflector);
2319
0
  // If proto != canonicalProto, we have to preserve our wrapper;
2320
0
  // otherwise we won't be able to properly recreate it later, since
2321
0
  // we won't know what proto to use.  Note that we don't check
2322
0
  // aGivenProto here, since it's entirely possible (and even
2323
0
  // somewhat common) to have a non-null aGivenProto which is the
2324
0
  // same as canonicalProto.
2325
0
  if (proto != canonicalProto) {
2326
0
    PreserveWrapper(aObject);
2327
0
  }
2328
0
2329
0
  return true;
2330
0
}
2331
2332
// This may allocate too many slots, because we only really need
2333
// slots for our non-interface-typed members that we cache.  But
2334
// allocating slots only for those would make the slot index
2335
// computations much more complicated, so let's do this the simple
2336
// way for now.
2337
DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 3);
2338
2339
const NativePropertyHooks sNativePropertyHooks[] = { {
2340
  nullptr,
2341
  nullptr,
2342
  nullptr,
2343
  { sNativeProperties.Upcast(), sChromeOnlyNativeProperties.Upcast() },
2344
  prototypes::id::MutationRecord,
2345
  constructors::id::MutationRecord,
2346
  nullptr,
2347
  &sXrayExpandoObjectClass
2348
} };
2349
2350
void
2351
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
2352
0
{
2353
0
  JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
2354
0
  if (!parentProto) {
2355
0
    return;
2356
0
  }
2357
0
2358
0
  JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
2359
0
  if (!constructorProto) {
2360
0
    return;
2361
0
  }
2362
0
2363
0
  static bool sIdsInited = false;
2364
0
  if (!sIdsInited && NS_IsMainThread()) {
2365
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
2366
0
      return;
2367
0
    }
2368
0
    if (!InitIds(aCx, sChromeOnlyNativeProperties.Upcast())) {
2369
0
      return;
2370
0
    }
2371
0
    sIdsInited = true;
2372
0
  }
2373
0
2374
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::MutationRecord);
2375
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::MutationRecord);
2376
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
2377
0
                              &sPrototypeClass.mBase, protoCache,
2378
0
                              nullptr,
2379
0
                              constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
2380
0
                              interfaceCache,
2381
0
                              sNativeProperties.Upcast(),
2382
0
                              sChromeOnlyNativeProperties.Upcast(),
2383
0
                              "MutationRecord", aDefineOnGlobal,
2384
0
                              nullptr,
2385
0
                              false);
2386
0
}
2387
2388
JSObject*
2389
GetConstructorObject(JSContext* aCx)
2390
0
{
2391
0
  return GetConstructorObjectHandle(aCx);
2392
0
}
2393
2394
} // namespace MutationRecord_Binding
2395
2396
2397
2398
} // namespace dom
2399
} // namespace mozilla