LCOV - code coverage report
Current view: top level - obj-x86_64-pc-linux-gnu/dom/bindings - MutationObserverBinding.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 162 863 18.8 %
Date: 2017-07-14 16:53:18 Functions: 9 55 16.4 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.13