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