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