Coverage Report

Created: 2018-09-25 14:53

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