LCOV - code coverage report
Current view: top level - obj-x86_64-pc-linux-gnu/dom/bindings - NetDashboardBinding.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 1941 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 112 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* THIS FILE IS AUTOGENERATED FROM NetDashboard.webidl BY Codegen.py - DO NOT EDIT */
       2             : 
       3             : #include "AtomList.h"
       4             : #include "NetDashboardBinding.h"
       5             : #include "mozilla/FloatingPoint.h"
       6             : #include "mozilla/OwningNonNull.h"
       7             : #include "mozilla/dom/BindingUtils.h"
       8             : #include "mozilla/dom/NonRefcountedDOMObject.h"
       9             : #include "mozilla/dom/PrimitiveConversions.h"
      10             : #include "mozilla/dom/ScriptSettings.h"
      11             : #include "mozilla/dom/SimpleGlobalObject.h"
      12             : 
      13             : namespace mozilla {
      14             : namespace dom {
      15             : 
      16             : 
      17           0 : ConnStatusDict::ConnStatusDict()
      18             : {
      19             :   // Safe to pass a null context if we pass a null value
      20           0 :   Init(nullptr, JS::NullHandleValue);
      21           0 : }
      22             : 
      23             : 
      24             : 
      25             : bool
      26           0 : ConnStatusDict::InitIds(JSContext* cx, ConnStatusDictAtoms* atomsCache)
      27             : {
      28           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
      29             : 
      30             :   // Initialize these in reverse order so that any failure leaves the first one
      31             :   // uninitialized.
      32           0 :   if (!atomsCache->status_id.init(cx, "status")) {
      33           0 :     return false;
      34             :   }
      35           0 :   return true;
      36             : }
      37             : 
      38             : bool
      39           0 : ConnStatusDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
      40             : {
      41             :   // Passing a null JSContext is OK only if we're initing from null,
      42             :   // Since in that case we will not have to do any property gets
      43             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
      44             :   // checkers by static analysis tools
      45           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
      46           0 :   ConnStatusDictAtoms* atomsCache = nullptr;
      47           0 :   if (cx) {
      48           0 :     atomsCache = GetAtomCache<ConnStatusDictAtoms>(cx);
      49           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
      50           0 :       return false;
      51             :     }
      52             :   }
      53             : 
      54           0 :   if (!IsConvertibleToDictionary(val)) {
      55           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
      56             :   }
      57             : 
      58           0 :   bool isNull = val.isNullOrUndefined();
      59             :   // We only need these if !isNull, in which case we have |cx|.
      60           0 :   Maybe<JS::Rooted<JSObject *> > object;
      61           0 :   Maybe<JS::Rooted<JS::Value> > temp;
      62           0 :   if (!isNull) {
      63           0 :     MOZ_ASSERT(cx);
      64           0 :     object.emplace(cx, &val.toObject());
      65           0 :     temp.emplace(cx);
      66             :   }
      67           0 :   if (!isNull) {
      68           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->status_id, temp.ptr())) {
      69           0 :       return false;
      70             :     }
      71             :   }
      72           0 :   if (!isNull && !temp->isUndefined()) {
      73           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mStatus)) {
      74           0 :       return false;
      75             :     }
      76             :   } else {
      77             :     static const char16_t data[] = { 0 };
      78           0 :     mStatus.Rebind(data, ArrayLength(data) - 1);
      79             :   }
      80           0 :   mIsAnyMemberPresent = true;
      81           0 :   return true;
      82             : }
      83             : 
      84             : bool
      85           0 : ConnStatusDict::Init(const nsAString& aJSON)
      86             : {
      87           0 :   AutoJSAPI jsapi;
      88           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
      89           0 :   if (!cleanGlobal) {
      90           0 :     return false;
      91             :   }
      92           0 :   if (!jsapi.Init(cleanGlobal)) {
      93           0 :     return false;
      94             :   }
      95           0 :   JSContext* cx = jsapi.cx();
      96           0 :   JS::Rooted<JS::Value> json(cx);
      97           0 :   bool ok = ParseJSON(cx, aJSON, &json);
      98           0 :   NS_ENSURE_TRUE(ok, false);
      99           0 :   return Init(cx, json);
     100             : }
     101             : 
     102             : bool
     103           0 : ConnStatusDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     104             : {
     105           0 :   ConnStatusDictAtoms* atomsCache = GetAtomCache<ConnStatusDictAtoms>(cx);
     106           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     107           0 :     return false;
     108             :   }
     109             : 
     110           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     111           0 :   if (!obj) {
     112           0 :     return false;
     113             :   }
     114           0 :   rval.set(JS::ObjectValue(*obj));
     115             : 
     116             :   do {
     117             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     118           0 :     JS::Rooted<JS::Value> temp(cx);
     119           0 :     nsString const & currentValue = mStatus;
     120           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     121           0 :       return false;
     122             :     }
     123           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->status_id, temp, JSPROP_ENUMERATE)) {
     124           0 :       return false;
     125             :     }
     126           0 :     break;
     127             :   } while(0);
     128             : 
     129           0 :   return true;
     130             : }
     131             : 
     132             : bool
     133           0 : ConnStatusDict::ToJSON(nsAString& aJSON) const
     134             : {
     135           0 :   AutoJSAPI jsapi;
     136           0 :   jsapi.Init();
     137           0 :   JSContext *cx = jsapi.cx();
     138             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     139             :   // because we'll only be creating objects, in ways that have no
     140             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     141             :   // which likewise guarantees no side-effects for the sorts of
     142             :   // things we will pass it.
     143           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     144           0 :   JS::Rooted<JS::Value> val(cx);
     145           0 :   if (!ToObjectInternal(cx, &val)) {
     146           0 :     return false;
     147             :   }
     148           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     149           0 :   return StringifyToJSON(cx, obj, aJSON);
     150             : }
     151             : 
     152             : void
     153           0 : ConnStatusDict::TraceDictionary(JSTracer* trc)
     154             : {
     155           0 : }
     156             : 
     157             : ConnStatusDict&
     158           0 : ConnStatusDict::operator=(const ConnStatusDict& aOther)
     159             : {
     160           0 :   mStatus = aOther.mStatus;
     161           0 :   return *this;
     162             : }
     163             : 
     164             : namespace binding_detail {
     165             : } // namespace binding_detail
     166             : 
     167             : 
     168             : 
     169           0 : DNSLookupDict::DNSLookupDict()
     170             : {
     171             :   // Safe to pass a null context if we pass a null value
     172           0 :   Init(nullptr, JS::NullHandleValue);
     173           0 : }
     174             : 
     175             : 
     176             : 
     177             : bool
     178           0 : DNSLookupDict::InitIds(JSContext* cx, DNSLookupDictAtoms* atomsCache)
     179             : {
     180           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     181             : 
     182             :   // Initialize these in reverse order so that any failure leaves the first one
     183             :   // uninitialized.
     184           0 :   if (!atomsCache->error_id.init(cx, "error") ||
     185           0 :       !atomsCache->answer_id.init(cx, "answer") ||
     186           0 :       !atomsCache->address_id.init(cx, "address")) {
     187           0 :     return false;
     188             :   }
     189           0 :   return true;
     190             : }
     191             : 
     192             : bool
     193           0 : DNSLookupDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     194             : {
     195             :   // Passing a null JSContext is OK only if we're initing from null,
     196             :   // Since in that case we will not have to do any property gets
     197             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     198             :   // checkers by static analysis tools
     199           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     200           0 :   DNSLookupDictAtoms* atomsCache = nullptr;
     201           0 :   if (cx) {
     202           0 :     atomsCache = GetAtomCache<DNSLookupDictAtoms>(cx);
     203           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     204           0 :       return false;
     205             :     }
     206             :   }
     207             : 
     208           0 :   if (!IsConvertibleToDictionary(val)) {
     209           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     210             :   }
     211             : 
     212           0 :   bool isNull = val.isNullOrUndefined();
     213             :   // We only need these if !isNull, in which case we have |cx|.
     214           0 :   Maybe<JS::Rooted<JSObject *> > object;
     215           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     216           0 :   if (!isNull) {
     217           0 :     MOZ_ASSERT(cx);
     218           0 :     object.emplace(cx, &val.toObject());
     219           0 :     temp.emplace(cx);
     220             :   }
     221           0 :   if (!isNull) {
     222           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->address_id, temp.ptr())) {
     223           0 :       return false;
     224             :     }
     225             :   }
     226           0 :   if (!isNull && !temp->isUndefined()) {
     227           0 :     mAddress.Construct();
     228           0 :     if (temp.ref().isObject()) {
     229           0 :       JS::ForOfIterator iter(cx);
     230           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
     231           0 :         return false;
     232             :       }
     233           0 :       if (!iter.valueIsIterable()) {
     234           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'address' member of DNSLookupDict");
     235           0 :         return false;
     236             :       }
     237           0 :       Sequence<nsString> &arr = (mAddress.Value());
     238           0 :       JS::Rooted<JS::Value> temp(cx);
     239             :       while (true) {
     240             :         bool done;
     241           0 :         if (!iter.next(&temp, &done)) {
     242           0 :           return false;
     243             :         }
     244           0 :         if (done) {
     245           0 :           break;
     246             :         }
     247           0 :         nsString* slotPtr = arr.AppendElement(mozilla::fallible);
     248           0 :         if (!slotPtr) {
     249           0 :           JS_ReportOutOfMemory(cx);
     250           0 :           return false;
     251             :         }
     252           0 :         nsString& slot = *slotPtr;
     253           0 :         if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
     254           0 :           return false;
     255             :         }
     256           0 :       }
     257             :     } else {
     258           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'address' member of DNSLookupDict");
     259           0 :       return false;
     260             :     }
     261           0 :     mIsAnyMemberPresent = true;
     262             :   }
     263             : 
     264           0 :   if (!isNull) {
     265           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->answer_id, temp.ptr())) {
     266           0 :       return false;
     267             :     }
     268             :   }
     269           0 :   if (!isNull && !temp->isUndefined()) {
     270           0 :     if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mAnswer)) {
     271           0 :       return false;
     272             :     }
     273             :   } else {
     274           0 :     mAnswer = false;
     275             :   }
     276           0 :   mIsAnyMemberPresent = true;
     277             : 
     278           0 :   if (!isNull) {
     279           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->error_id, temp.ptr())) {
     280           0 :       return false;
     281             :     }
     282             :   }
     283           0 :   if (!isNull && !temp->isUndefined()) {
     284           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mError)) {
     285           0 :       return false;
     286             :     }
     287             :   } else {
     288             :     static const char16_t data[] = { 0 };
     289           0 :     mError.Rebind(data, ArrayLength(data) - 1);
     290             :   }
     291           0 :   mIsAnyMemberPresent = true;
     292           0 :   return true;
     293             : }
     294             : 
     295             : bool
     296           0 : DNSLookupDict::Init(const nsAString& aJSON)
     297             : {
     298           0 :   AutoJSAPI jsapi;
     299           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     300           0 :   if (!cleanGlobal) {
     301           0 :     return false;
     302             :   }
     303           0 :   if (!jsapi.Init(cleanGlobal)) {
     304           0 :     return false;
     305             :   }
     306           0 :   JSContext* cx = jsapi.cx();
     307           0 :   JS::Rooted<JS::Value> json(cx);
     308           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     309           0 :   NS_ENSURE_TRUE(ok, false);
     310           0 :   return Init(cx, json);
     311             : }
     312             : 
     313             : bool
     314           0 : DNSLookupDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     315             : {
     316           0 :   DNSLookupDictAtoms* atomsCache = GetAtomCache<DNSLookupDictAtoms>(cx);
     317           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     318           0 :     return false;
     319             :   }
     320             : 
     321           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     322           0 :   if (!obj) {
     323           0 :     return false;
     324             :   }
     325           0 :   rval.set(JS::ObjectValue(*obj));
     326             : 
     327           0 :   if (mAddress.WasPassed()) {
     328             :     do {
     329             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     330           0 :       JS::Rooted<JS::Value> temp(cx);
     331           0 :       Sequence<nsString> const & currentValue = mAddress.InternalValue();
     332             : 
     333           0 :       uint32_t length = currentValue.Length();
     334           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
     335           0 :       if (!returnArray) {
     336           0 :         return false;
     337             :       }
     338             :       // Scope for 'tmp'
     339             :       {
     340           0 :         JS::Rooted<JS::Value> tmp(cx);
     341           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
     342             :           // Control block to let us common up the JS_DefineElement calls when there
     343             :           // are different ways to succeed at wrapping the object.
     344             :           do {
     345           0 :             if (!xpc::NonVoidStringToJsval(cx, currentValue[sequenceIdx0], &tmp)) {
     346           0 :               return false;
     347             :             }
     348           0 :             break;
     349             :           } while (0);
     350           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
     351             :                                 JSPROP_ENUMERATE)) {
     352           0 :             return false;
     353             :           }
     354             :         }
     355             :       }
     356           0 :       temp.setObject(*returnArray);
     357           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->address_id, temp, JSPROP_ENUMERATE)) {
     358           0 :         return false;
     359             :       }
     360           0 :       break;
     361             :     } while(0);
     362             :   }
     363             : 
     364             :   do {
     365             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     366           0 :     JS::Rooted<JS::Value> temp(cx);
     367           0 :     bool const & currentValue = mAnswer;
     368           0 :     temp.setBoolean(currentValue);
     369           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->answer_id, temp, JSPROP_ENUMERATE)) {
     370           0 :       return false;
     371             :     }
     372           0 :     break;
     373             :   } while(0);
     374             : 
     375             :   do {
     376             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     377           0 :     JS::Rooted<JS::Value> temp(cx);
     378           0 :     nsString const & currentValue = mError;
     379           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     380           0 :       return false;
     381             :     }
     382           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->error_id, temp, JSPROP_ENUMERATE)) {
     383           0 :       return false;
     384             :     }
     385           0 :     break;
     386             :   } while(0);
     387             : 
     388           0 :   return true;
     389             : }
     390             : 
     391             : bool
     392           0 : DNSLookupDict::ToJSON(nsAString& aJSON) const
     393             : {
     394           0 :   AutoJSAPI jsapi;
     395           0 :   jsapi.Init();
     396           0 :   JSContext *cx = jsapi.cx();
     397             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     398             :   // because we'll only be creating objects, in ways that have no
     399             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     400             :   // which likewise guarantees no side-effects for the sorts of
     401             :   // things we will pass it.
     402           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     403           0 :   JS::Rooted<JS::Value> val(cx);
     404           0 :   if (!ToObjectInternal(cx, &val)) {
     405           0 :     return false;
     406             :   }
     407           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     408           0 :   return StringifyToJSON(cx, obj, aJSON);
     409             : }
     410             : 
     411             : void
     412           0 : DNSLookupDict::TraceDictionary(JSTracer* trc)
     413             : {
     414           0 : }
     415             : 
     416             : DNSLookupDict&
     417           0 : DNSLookupDict::operator=(const DNSLookupDict& aOther)
     418             : {
     419           0 :   mAddress.Reset();
     420           0 :   if (aOther.mAddress.WasPassed()) {
     421           0 :     mAddress.Construct(aOther.mAddress.Value());
     422             :   }
     423           0 :   mAnswer = aOther.mAnswer;
     424           0 :   mError = aOther.mError;
     425           0 :   return *this;
     426             : }
     427             : 
     428             : namespace binding_detail {
     429             : } // namespace binding_detail
     430             : 
     431             : 
     432             : 
     433           0 : DnsCacheEntry::DnsCacheEntry()
     434             : {
     435             :   // Safe to pass a null context if we pass a null value
     436           0 :   Init(nullptr, JS::NullHandleValue);
     437           0 : }
     438             : 
     439             : 
     440             : 
     441             : bool
     442           0 : DnsCacheEntry::InitIds(JSContext* cx, DnsCacheEntryAtoms* atomsCache)
     443             : {
     444           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     445             : 
     446             :   // Initialize these in reverse order so that any failure leaves the first one
     447             :   // uninitialized.
     448           0 :   if (!atomsCache->hostname_id.init(cx, "hostname") ||
     449           0 :       !atomsCache->hostaddr_id.init(cx, "hostaddr") ||
     450           0 :       !atomsCache->family_id.init(cx, "family") ||
     451           0 :       !atomsCache->expiration_id.init(cx, "expiration")) {
     452           0 :     return false;
     453             :   }
     454           0 :   return true;
     455             : }
     456             : 
     457             : bool
     458           0 : DnsCacheEntry::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     459             : {
     460             :   // Passing a null JSContext is OK only if we're initing from null,
     461             :   // Since in that case we will not have to do any property gets
     462             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     463             :   // checkers by static analysis tools
     464           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     465           0 :   DnsCacheEntryAtoms* atomsCache = nullptr;
     466           0 :   if (cx) {
     467           0 :     atomsCache = GetAtomCache<DnsCacheEntryAtoms>(cx);
     468           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     469           0 :       return false;
     470             :     }
     471             :   }
     472             : 
     473           0 :   if (!IsConvertibleToDictionary(val)) {
     474           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     475             :   }
     476             : 
     477           0 :   bool isNull = val.isNullOrUndefined();
     478             :   // We only need these if !isNull, in which case we have |cx|.
     479           0 :   Maybe<JS::Rooted<JSObject *> > object;
     480           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     481           0 :   if (!isNull) {
     482           0 :     MOZ_ASSERT(cx);
     483           0 :     object.emplace(cx, &val.toObject());
     484           0 :     temp.emplace(cx);
     485             :   }
     486           0 :   if (!isNull) {
     487           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->expiration_id, temp.ptr())) {
     488           0 :       return false;
     489             :     }
     490             :   }
     491           0 :   if (!isNull && !temp->isUndefined()) {
     492           0 :     if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mExpiration)) {
     493           0 :       return false;
     494           0 :     } else if (!mozilla::IsFinite(mExpiration)) {
     495           0 :       ThrowErrorMessage(cx, MSG_NOT_FINITE, "'expiration' member of DnsCacheEntry");
     496           0 :       return false;
     497             :     }
     498             :   } else {
     499           0 :     mExpiration = 0.0;
     500             :   }
     501           0 :   mIsAnyMemberPresent = true;
     502             : 
     503           0 :   if (!isNull) {
     504           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->family_id, temp.ptr())) {
     505           0 :       return false;
     506             :     }
     507             :   }
     508           0 :   if (!isNull && !temp->isUndefined()) {
     509           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mFamily)) {
     510           0 :       return false;
     511             :     }
     512             :   } else {
     513             :     static const char16_t data[] = { 0 };
     514           0 :     mFamily.Rebind(data, ArrayLength(data) - 1);
     515             :   }
     516           0 :   mIsAnyMemberPresent = true;
     517             : 
     518           0 :   if (!isNull) {
     519           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->hostaddr_id, temp.ptr())) {
     520           0 :       return false;
     521             :     }
     522             :   }
     523           0 :   if (!isNull && !temp->isUndefined()) {
     524           0 :     mHostaddr.Construct();
     525           0 :     if (temp.ref().isObject()) {
     526           0 :       JS::ForOfIterator iter(cx);
     527           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
     528           0 :         return false;
     529             :       }
     530           0 :       if (!iter.valueIsIterable()) {
     531           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'hostaddr' member of DnsCacheEntry");
     532           0 :         return false;
     533             :       }
     534           0 :       Sequence<nsString> &arr = (mHostaddr.Value());
     535           0 :       JS::Rooted<JS::Value> temp(cx);
     536             :       while (true) {
     537             :         bool done;
     538           0 :         if (!iter.next(&temp, &done)) {
     539           0 :           return false;
     540             :         }
     541           0 :         if (done) {
     542           0 :           break;
     543             :         }
     544           0 :         nsString* slotPtr = arr.AppendElement(mozilla::fallible);
     545           0 :         if (!slotPtr) {
     546           0 :           JS_ReportOutOfMemory(cx);
     547           0 :           return false;
     548             :         }
     549           0 :         nsString& slot = *slotPtr;
     550           0 :         if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
     551           0 :           return false;
     552             :         }
     553           0 :       }
     554             :     } else {
     555           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'hostaddr' member of DnsCacheEntry");
     556           0 :       return false;
     557             :     }
     558           0 :     mIsAnyMemberPresent = true;
     559             :   }
     560             : 
     561           0 :   if (!isNull) {
     562           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->hostname_id, temp.ptr())) {
     563           0 :       return false;
     564             :     }
     565             :   }
     566           0 :   if (!isNull && !temp->isUndefined()) {
     567           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mHostname)) {
     568           0 :       return false;
     569             :     }
     570             :   } else {
     571             :     static const char16_t data[] = { 0 };
     572           0 :     mHostname.Rebind(data, ArrayLength(data) - 1);
     573             :   }
     574           0 :   mIsAnyMemberPresent = true;
     575           0 :   return true;
     576             : }
     577             : 
     578             : bool
     579           0 : DnsCacheEntry::Init(const nsAString& aJSON)
     580             : {
     581           0 :   AutoJSAPI jsapi;
     582           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     583           0 :   if (!cleanGlobal) {
     584           0 :     return false;
     585             :   }
     586           0 :   if (!jsapi.Init(cleanGlobal)) {
     587           0 :     return false;
     588             :   }
     589           0 :   JSContext* cx = jsapi.cx();
     590           0 :   JS::Rooted<JS::Value> json(cx);
     591           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     592           0 :   NS_ENSURE_TRUE(ok, false);
     593           0 :   return Init(cx, json);
     594             : }
     595             : 
     596             : bool
     597           0 : DnsCacheEntry::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     598             : {
     599           0 :   DnsCacheEntryAtoms* atomsCache = GetAtomCache<DnsCacheEntryAtoms>(cx);
     600           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     601           0 :     return false;
     602             :   }
     603             : 
     604           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     605           0 :   if (!obj) {
     606           0 :     return false;
     607             :   }
     608           0 :   rval.set(JS::ObjectValue(*obj));
     609             : 
     610             :   do {
     611             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     612           0 :     JS::Rooted<JS::Value> temp(cx);
     613           0 :     double const & currentValue = mExpiration;
     614           0 :     temp.set(JS_NumberValue(double(currentValue)));
     615           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->expiration_id, temp, JSPROP_ENUMERATE)) {
     616           0 :       return false;
     617             :     }
     618           0 :     break;
     619             :   } while(0);
     620             : 
     621             :   do {
     622             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     623           0 :     JS::Rooted<JS::Value> temp(cx);
     624           0 :     nsString const & currentValue = mFamily;
     625           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     626           0 :       return false;
     627             :     }
     628           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->family_id, temp, JSPROP_ENUMERATE)) {
     629           0 :       return false;
     630             :     }
     631           0 :     break;
     632             :   } while(0);
     633             : 
     634           0 :   if (mHostaddr.WasPassed()) {
     635             :     do {
     636             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     637           0 :       JS::Rooted<JS::Value> temp(cx);
     638           0 :       Sequence<nsString> const & currentValue = mHostaddr.InternalValue();
     639             : 
     640           0 :       uint32_t length = currentValue.Length();
     641           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
     642           0 :       if (!returnArray) {
     643           0 :         return false;
     644             :       }
     645             :       // Scope for 'tmp'
     646             :       {
     647           0 :         JS::Rooted<JS::Value> tmp(cx);
     648           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
     649             :           // Control block to let us common up the JS_DefineElement calls when there
     650             :           // are different ways to succeed at wrapping the object.
     651             :           do {
     652           0 :             if (!xpc::NonVoidStringToJsval(cx, currentValue[sequenceIdx0], &tmp)) {
     653           0 :               return false;
     654             :             }
     655           0 :             break;
     656             :           } while (0);
     657           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
     658             :                                 JSPROP_ENUMERATE)) {
     659           0 :             return false;
     660             :           }
     661             :         }
     662             :       }
     663           0 :       temp.setObject(*returnArray);
     664           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->hostaddr_id, temp, JSPROP_ENUMERATE)) {
     665           0 :         return false;
     666             :       }
     667           0 :       break;
     668             :     } while(0);
     669             :   }
     670             : 
     671             :   do {
     672             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     673           0 :     JS::Rooted<JS::Value> temp(cx);
     674           0 :     nsString const & currentValue = mHostname;
     675           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     676           0 :       return false;
     677             :     }
     678           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->hostname_id, temp, JSPROP_ENUMERATE)) {
     679           0 :       return false;
     680             :     }
     681           0 :     break;
     682             :   } while(0);
     683             : 
     684           0 :   return true;
     685             : }
     686             : 
     687             : bool
     688           0 : DnsCacheEntry::ToJSON(nsAString& aJSON) const
     689             : {
     690           0 :   AutoJSAPI jsapi;
     691           0 :   jsapi.Init();
     692           0 :   JSContext *cx = jsapi.cx();
     693             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     694             :   // because we'll only be creating objects, in ways that have no
     695             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     696             :   // which likewise guarantees no side-effects for the sorts of
     697             :   // things we will pass it.
     698           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     699           0 :   JS::Rooted<JS::Value> val(cx);
     700           0 :   if (!ToObjectInternal(cx, &val)) {
     701           0 :     return false;
     702             :   }
     703           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     704           0 :   return StringifyToJSON(cx, obj, aJSON);
     705             : }
     706             : 
     707             : void
     708           0 : DnsCacheEntry::TraceDictionary(JSTracer* trc)
     709             : {
     710           0 : }
     711             : 
     712             : DnsCacheEntry&
     713           0 : DnsCacheEntry::operator=(const DnsCacheEntry& aOther)
     714             : {
     715           0 :   mExpiration = aOther.mExpiration;
     716           0 :   mFamily = aOther.mFamily;
     717           0 :   mHostaddr.Reset();
     718           0 :   if (aOther.mHostaddr.WasPassed()) {
     719           0 :     mHostaddr.Construct(aOther.mHostaddr.Value());
     720             :   }
     721           0 :   mHostname = aOther.mHostname;
     722           0 :   return *this;
     723             : }
     724             : 
     725             : namespace binding_detail {
     726             : } // namespace binding_detail
     727             : 
     728             : 
     729             : 
     730           0 : HalfOpenInfoDict::HalfOpenInfoDict()
     731             : {
     732             :   // Safe to pass a null context if we pass a null value
     733           0 :   Init(nullptr, JS::NullHandleValue);
     734           0 : }
     735             : 
     736             : 
     737             : 
     738             : bool
     739           0 : HalfOpenInfoDict::InitIds(JSContext* cx, HalfOpenInfoDictAtoms* atomsCache)
     740             : {
     741           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     742             : 
     743             :   // Initialize these in reverse order so that any failure leaves the first one
     744             :   // uninitialized.
     745           0 :   if (!atomsCache->speculative_id.init(cx, "speculative")) {
     746           0 :     return false;
     747             :   }
     748           0 :   return true;
     749             : }
     750             : 
     751             : bool
     752           0 : HalfOpenInfoDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     753             : {
     754             :   // Passing a null JSContext is OK only if we're initing from null,
     755             :   // Since in that case we will not have to do any property gets
     756             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     757             :   // checkers by static analysis tools
     758           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     759           0 :   HalfOpenInfoDictAtoms* atomsCache = nullptr;
     760           0 :   if (cx) {
     761           0 :     atomsCache = GetAtomCache<HalfOpenInfoDictAtoms>(cx);
     762           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     763           0 :       return false;
     764             :     }
     765             :   }
     766             : 
     767           0 :   if (!IsConvertibleToDictionary(val)) {
     768           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     769             :   }
     770             : 
     771           0 :   bool isNull = val.isNullOrUndefined();
     772             :   // We only need these if !isNull, in which case we have |cx|.
     773           0 :   Maybe<JS::Rooted<JSObject *> > object;
     774           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     775           0 :   if (!isNull) {
     776           0 :     MOZ_ASSERT(cx);
     777           0 :     object.emplace(cx, &val.toObject());
     778           0 :     temp.emplace(cx);
     779             :   }
     780           0 :   if (!isNull) {
     781           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->speculative_id, temp.ptr())) {
     782           0 :       return false;
     783             :     }
     784             :   }
     785           0 :   if (!isNull && !temp->isUndefined()) {
     786           0 :     if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mSpeculative)) {
     787           0 :       return false;
     788             :     }
     789             :   } else {
     790           0 :     mSpeculative = false;
     791             :   }
     792           0 :   mIsAnyMemberPresent = true;
     793           0 :   return true;
     794             : }
     795             : 
     796             : bool
     797           0 : HalfOpenInfoDict::Init(const nsAString& aJSON)
     798             : {
     799           0 :   AutoJSAPI jsapi;
     800           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     801           0 :   if (!cleanGlobal) {
     802           0 :     return false;
     803             :   }
     804           0 :   if (!jsapi.Init(cleanGlobal)) {
     805           0 :     return false;
     806             :   }
     807           0 :   JSContext* cx = jsapi.cx();
     808           0 :   JS::Rooted<JS::Value> json(cx);
     809           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     810           0 :   NS_ENSURE_TRUE(ok, false);
     811           0 :   return Init(cx, json);
     812             : }
     813             : 
     814             : bool
     815           0 : HalfOpenInfoDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     816             : {
     817           0 :   HalfOpenInfoDictAtoms* atomsCache = GetAtomCache<HalfOpenInfoDictAtoms>(cx);
     818           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     819           0 :     return false;
     820             :   }
     821             : 
     822           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     823           0 :   if (!obj) {
     824           0 :     return false;
     825             :   }
     826           0 :   rval.set(JS::ObjectValue(*obj));
     827             : 
     828             :   do {
     829             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     830           0 :     JS::Rooted<JS::Value> temp(cx);
     831           0 :     bool const & currentValue = mSpeculative;
     832           0 :     temp.setBoolean(currentValue);
     833           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->speculative_id, temp, JSPROP_ENUMERATE)) {
     834           0 :       return false;
     835             :     }
     836           0 :     break;
     837             :   } while(0);
     838             : 
     839           0 :   return true;
     840             : }
     841             : 
     842             : bool
     843           0 : HalfOpenInfoDict::ToJSON(nsAString& aJSON) const
     844             : {
     845           0 :   AutoJSAPI jsapi;
     846           0 :   jsapi.Init();
     847           0 :   JSContext *cx = jsapi.cx();
     848             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     849             :   // because we'll only be creating objects, in ways that have no
     850             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     851             :   // which likewise guarantees no side-effects for the sorts of
     852             :   // things we will pass it.
     853           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     854           0 :   JS::Rooted<JS::Value> val(cx);
     855           0 :   if (!ToObjectInternal(cx, &val)) {
     856           0 :     return false;
     857             :   }
     858           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     859           0 :   return StringifyToJSON(cx, obj, aJSON);
     860             : }
     861             : 
     862             : void
     863           0 : HalfOpenInfoDict::TraceDictionary(JSTracer* trc)
     864             : {
     865           0 : }
     866             : 
     867             : HalfOpenInfoDict&
     868           0 : HalfOpenInfoDict::operator=(const HalfOpenInfoDict& aOther)
     869             : {
     870           0 :   mSpeculative = aOther.mSpeculative;
     871           0 :   return *this;
     872             : }
     873             : 
     874             : namespace binding_detail {
     875             : } // namespace binding_detail
     876             : 
     877             : 
     878             : 
     879           0 : HttpConnInfo::HttpConnInfo()
     880             : {
     881             :   // Safe to pass a null context if we pass a null value
     882           0 :   Init(nullptr, JS::NullHandleValue);
     883           0 : }
     884             : 
     885             : 
     886             : 
     887             : bool
     888           0 : HttpConnInfo::InitIds(JSContext* cx, HttpConnInfoAtoms* atomsCache)
     889             : {
     890           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     891             : 
     892             :   // Initialize these in reverse order so that any failure leaves the first one
     893             :   // uninitialized.
     894           0 :   if (!atomsCache->ttl_id.init(cx, "ttl") ||
     895           0 :       !atomsCache->rtt_id.init(cx, "rtt") ||
     896           0 :       !atomsCache->protocolVersion_id.init(cx, "protocolVersion")) {
     897           0 :     return false;
     898             :   }
     899           0 :   return true;
     900             : }
     901             : 
     902             : bool
     903           0 : HttpConnInfo::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     904             : {
     905             :   // Passing a null JSContext is OK only if we're initing from null,
     906             :   // Since in that case we will not have to do any property gets
     907             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     908             :   // checkers by static analysis tools
     909           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     910           0 :   HttpConnInfoAtoms* atomsCache = nullptr;
     911           0 :   if (cx) {
     912           0 :     atomsCache = GetAtomCache<HttpConnInfoAtoms>(cx);
     913           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     914           0 :       return false;
     915             :     }
     916             :   }
     917             : 
     918           0 :   if (!IsConvertibleToDictionary(val)) {
     919           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     920             :   }
     921             : 
     922           0 :   bool isNull = val.isNullOrUndefined();
     923             :   // We only need these if !isNull, in which case we have |cx|.
     924           0 :   Maybe<JS::Rooted<JSObject *> > object;
     925           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     926           0 :   if (!isNull) {
     927           0 :     MOZ_ASSERT(cx);
     928           0 :     object.emplace(cx, &val.toObject());
     929           0 :     temp.emplace(cx);
     930             :   }
     931           0 :   if (!isNull) {
     932           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->protocolVersion_id, temp.ptr())) {
     933           0 :       return false;
     934             :     }
     935             :   }
     936           0 :   if (!isNull && !temp->isUndefined()) {
     937           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mProtocolVersion)) {
     938           0 :       return false;
     939             :     }
     940             :   } else {
     941             :     static const char16_t data[] = { 0 };
     942           0 :     mProtocolVersion.Rebind(data, ArrayLength(data) - 1);
     943             :   }
     944           0 :   mIsAnyMemberPresent = true;
     945             : 
     946           0 :   if (!isNull) {
     947           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->rtt_id, temp.ptr())) {
     948           0 :       return false;
     949             :     }
     950             :   }
     951           0 :   if (!isNull && !temp->isUndefined()) {
     952           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mRtt)) {
     953           0 :       return false;
     954             :     }
     955             :   } else {
     956           0 :     mRtt = 0U;
     957             :   }
     958           0 :   mIsAnyMemberPresent = true;
     959             : 
     960           0 :   if (!isNull) {
     961           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->ttl_id, temp.ptr())) {
     962           0 :       return false;
     963             :     }
     964             :   }
     965           0 :   if (!isNull && !temp->isUndefined()) {
     966           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mTtl)) {
     967           0 :       return false;
     968             :     }
     969             :   } else {
     970           0 :     mTtl = 0U;
     971             :   }
     972           0 :   mIsAnyMemberPresent = true;
     973           0 :   return true;
     974             : }
     975             : 
     976             : bool
     977           0 : HttpConnInfo::Init(const nsAString& aJSON)
     978             : {
     979           0 :   AutoJSAPI jsapi;
     980           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     981           0 :   if (!cleanGlobal) {
     982           0 :     return false;
     983             :   }
     984           0 :   if (!jsapi.Init(cleanGlobal)) {
     985           0 :     return false;
     986             :   }
     987           0 :   JSContext* cx = jsapi.cx();
     988           0 :   JS::Rooted<JS::Value> json(cx);
     989           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     990           0 :   NS_ENSURE_TRUE(ok, false);
     991           0 :   return Init(cx, json);
     992             : }
     993             : 
     994             : bool
     995           0 : HttpConnInfo::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     996             : {
     997           0 :   HttpConnInfoAtoms* atomsCache = GetAtomCache<HttpConnInfoAtoms>(cx);
     998           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     999           0 :     return false;
    1000             :   }
    1001             : 
    1002           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    1003           0 :   if (!obj) {
    1004           0 :     return false;
    1005             :   }
    1006           0 :   rval.set(JS::ObjectValue(*obj));
    1007             : 
    1008             :   do {
    1009             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1010           0 :     JS::Rooted<JS::Value> temp(cx);
    1011           0 :     nsString const & currentValue = mProtocolVersion;
    1012           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    1013           0 :       return false;
    1014             :     }
    1015           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->protocolVersion_id, temp, JSPROP_ENUMERATE)) {
    1016           0 :       return false;
    1017             :     }
    1018           0 :     break;
    1019             :   } while(0);
    1020             : 
    1021             :   do {
    1022             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1023           0 :     JS::Rooted<JS::Value> temp(cx);
    1024           0 :     uint32_t const & currentValue = mRtt;
    1025           0 :     temp.setNumber(currentValue);
    1026           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->rtt_id, temp, JSPROP_ENUMERATE)) {
    1027           0 :       return false;
    1028             :     }
    1029           0 :     break;
    1030             :   } while(0);
    1031             : 
    1032             :   do {
    1033             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1034           0 :     JS::Rooted<JS::Value> temp(cx);
    1035           0 :     uint32_t const & currentValue = mTtl;
    1036           0 :     temp.setNumber(currentValue);
    1037           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->ttl_id, temp, JSPROP_ENUMERATE)) {
    1038           0 :       return false;
    1039             :     }
    1040           0 :     break;
    1041             :   } while(0);
    1042             : 
    1043           0 :   return true;
    1044             : }
    1045             : 
    1046             : bool
    1047           0 : HttpConnInfo::ToJSON(nsAString& aJSON) const
    1048             : {
    1049           0 :   AutoJSAPI jsapi;
    1050           0 :   jsapi.Init();
    1051           0 :   JSContext *cx = jsapi.cx();
    1052             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    1053             :   // because we'll only be creating objects, in ways that have no
    1054             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    1055             :   // which likewise guarantees no side-effects for the sorts of
    1056             :   // things we will pass it.
    1057           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    1058           0 :   JS::Rooted<JS::Value> val(cx);
    1059           0 :   if (!ToObjectInternal(cx, &val)) {
    1060           0 :     return false;
    1061             :   }
    1062           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    1063           0 :   return StringifyToJSON(cx, obj, aJSON);
    1064             : }
    1065             : 
    1066             : void
    1067           0 : HttpConnInfo::TraceDictionary(JSTracer* trc)
    1068             : {
    1069           0 : }
    1070             : 
    1071             : HttpConnInfo&
    1072           0 : HttpConnInfo::operator=(const HttpConnInfo& aOther)
    1073             : {
    1074           0 :   mProtocolVersion = aOther.mProtocolVersion;
    1075           0 :   mRtt = aOther.mRtt;
    1076           0 :   mTtl = aOther.mTtl;
    1077           0 :   return *this;
    1078             : }
    1079             : 
    1080             : namespace binding_detail {
    1081             : } // namespace binding_detail
    1082             : 
    1083             : 
    1084             : 
    1085           0 : RcwnPerfStats::RcwnPerfStats()
    1086             : {
    1087             :   // Safe to pass a null context if we pass a null value
    1088           0 :   Init(nullptr, JS::NullHandleValue);
    1089           0 : }
    1090             : 
    1091             : 
    1092             : 
    1093             : bool
    1094           0 : RcwnPerfStats::InitIds(JSContext* cx, RcwnPerfStatsAtoms* atomsCache)
    1095             : {
    1096           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1097             : 
    1098             :   // Initialize these in reverse order so that any failure leaves the first one
    1099             :   // uninitialized.
    1100           0 :   if (!atomsCache->stddevLong_id.init(cx, "stddevLong") ||
    1101           0 :       !atomsCache->avgShort_id.init(cx, "avgShort") ||
    1102           0 :       !atomsCache->avgLong_id.init(cx, "avgLong")) {
    1103           0 :     return false;
    1104             :   }
    1105           0 :   return true;
    1106             : }
    1107             : 
    1108             : bool
    1109           0 : RcwnPerfStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1110             : {
    1111             :   // Passing a null JSContext is OK only if we're initing from null,
    1112             :   // Since in that case we will not have to do any property gets
    1113             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1114             :   // checkers by static analysis tools
    1115           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1116           0 :   RcwnPerfStatsAtoms* atomsCache = nullptr;
    1117           0 :   if (cx) {
    1118           0 :     atomsCache = GetAtomCache<RcwnPerfStatsAtoms>(cx);
    1119           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1120           0 :       return false;
    1121             :     }
    1122             :   }
    1123             : 
    1124           0 :   if (!IsConvertibleToDictionary(val)) {
    1125           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    1126             :   }
    1127             : 
    1128           0 :   bool isNull = val.isNullOrUndefined();
    1129             :   // We only need these if !isNull, in which case we have |cx|.
    1130           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1131           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1132           0 :   if (!isNull) {
    1133           0 :     MOZ_ASSERT(cx);
    1134           0 :     object.emplace(cx, &val.toObject());
    1135           0 :     temp.emplace(cx);
    1136             :   }
    1137           0 :   if (!isNull) {
    1138           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->avgLong_id, temp.ptr())) {
    1139           0 :       return false;
    1140             :     }
    1141             :   }
    1142           0 :   if (!isNull && !temp->isUndefined()) {
    1143           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mAvgLong)) {
    1144           0 :       return false;
    1145             :     }
    1146             :   } else {
    1147           0 :     mAvgLong = 0U;
    1148             :   }
    1149           0 :   mIsAnyMemberPresent = true;
    1150             : 
    1151           0 :   if (!isNull) {
    1152           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->avgShort_id, temp.ptr())) {
    1153           0 :       return false;
    1154             :     }
    1155             :   }
    1156           0 :   if (!isNull && !temp->isUndefined()) {
    1157           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mAvgShort)) {
    1158           0 :       return false;
    1159             :     }
    1160             :   } else {
    1161           0 :     mAvgShort = 0U;
    1162             :   }
    1163           0 :   mIsAnyMemberPresent = true;
    1164             : 
    1165           0 :   if (!isNull) {
    1166           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->stddevLong_id, temp.ptr())) {
    1167           0 :       return false;
    1168             :     }
    1169             :   }
    1170           0 :   if (!isNull && !temp->isUndefined()) {
    1171           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mStddevLong)) {
    1172           0 :       return false;
    1173             :     }
    1174             :   } else {
    1175           0 :     mStddevLong = 0U;
    1176             :   }
    1177           0 :   mIsAnyMemberPresent = true;
    1178           0 :   return true;
    1179             : }
    1180             : 
    1181             : bool
    1182           0 : RcwnPerfStats::Init(const nsAString& aJSON)
    1183             : {
    1184           0 :   AutoJSAPI jsapi;
    1185           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    1186           0 :   if (!cleanGlobal) {
    1187           0 :     return false;
    1188             :   }
    1189           0 :   if (!jsapi.Init(cleanGlobal)) {
    1190           0 :     return false;
    1191             :   }
    1192           0 :   JSContext* cx = jsapi.cx();
    1193           0 :   JS::Rooted<JS::Value> json(cx);
    1194           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    1195           0 :   NS_ENSURE_TRUE(ok, false);
    1196           0 :   return Init(cx, json);
    1197             : }
    1198             : 
    1199             : bool
    1200           0 : RcwnPerfStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1201             : {
    1202           0 :   RcwnPerfStatsAtoms* atomsCache = GetAtomCache<RcwnPerfStatsAtoms>(cx);
    1203           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1204           0 :     return false;
    1205             :   }
    1206             : 
    1207           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    1208           0 :   if (!obj) {
    1209           0 :     return false;
    1210             :   }
    1211           0 :   rval.set(JS::ObjectValue(*obj));
    1212             : 
    1213             :   do {
    1214             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1215           0 :     JS::Rooted<JS::Value> temp(cx);
    1216           0 :     uint32_t const & currentValue = mAvgLong;
    1217           0 :     temp.setNumber(currentValue);
    1218           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->avgLong_id, temp, JSPROP_ENUMERATE)) {
    1219           0 :       return false;
    1220             :     }
    1221           0 :     break;
    1222             :   } while(0);
    1223             : 
    1224             :   do {
    1225             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1226           0 :     JS::Rooted<JS::Value> temp(cx);
    1227           0 :     uint32_t const & currentValue = mAvgShort;
    1228           0 :     temp.setNumber(currentValue);
    1229           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->avgShort_id, temp, JSPROP_ENUMERATE)) {
    1230           0 :       return false;
    1231             :     }
    1232           0 :     break;
    1233             :   } while(0);
    1234             : 
    1235             :   do {
    1236             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1237           0 :     JS::Rooted<JS::Value> temp(cx);
    1238           0 :     uint32_t const & currentValue = mStddevLong;
    1239           0 :     temp.setNumber(currentValue);
    1240           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->stddevLong_id, temp, JSPROP_ENUMERATE)) {
    1241           0 :       return false;
    1242             :     }
    1243           0 :     break;
    1244             :   } while(0);
    1245             : 
    1246           0 :   return true;
    1247             : }
    1248             : 
    1249             : bool
    1250           0 : RcwnPerfStats::ToJSON(nsAString& aJSON) const
    1251             : {
    1252           0 :   AutoJSAPI jsapi;
    1253           0 :   jsapi.Init();
    1254           0 :   JSContext *cx = jsapi.cx();
    1255             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    1256             :   // because we'll only be creating objects, in ways that have no
    1257             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    1258             :   // which likewise guarantees no side-effects for the sorts of
    1259             :   // things we will pass it.
    1260           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    1261           0 :   JS::Rooted<JS::Value> val(cx);
    1262           0 :   if (!ToObjectInternal(cx, &val)) {
    1263           0 :     return false;
    1264             :   }
    1265           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    1266           0 :   return StringifyToJSON(cx, obj, aJSON);
    1267             : }
    1268             : 
    1269             : void
    1270           0 : RcwnPerfStats::TraceDictionary(JSTracer* trc)
    1271             : {
    1272           0 : }
    1273             : 
    1274             : RcwnPerfStats&
    1275           0 : RcwnPerfStats::operator=(const RcwnPerfStats& aOther)
    1276             : {
    1277           0 :   mAvgLong = aOther.mAvgLong;
    1278           0 :   mAvgShort = aOther.mAvgShort;
    1279           0 :   mStddevLong = aOther.mStddevLong;
    1280           0 :   return *this;
    1281             : }
    1282             : 
    1283             : namespace binding_detail {
    1284             : } // namespace binding_detail
    1285             : 
    1286             : 
    1287             : 
    1288           0 : SocketElement::SocketElement()
    1289             : {
    1290             :   // Safe to pass a null context if we pass a null value
    1291           0 :   Init(nullptr, JS::NullHandleValue);
    1292           0 : }
    1293             : 
    1294             : 
    1295             : 
    1296             : bool
    1297           0 : SocketElement::InitIds(JSContext* cx, SocketElementAtoms* atomsCache)
    1298             : {
    1299           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1300             : 
    1301             :   // Initialize these in reverse order so that any failure leaves the first one
    1302             :   // uninitialized.
    1303           0 :   if (!atomsCache->tcp_id.init(cx, "tcp") ||
    1304           0 :       !atomsCache->sent_id.init(cx, "sent") ||
    1305           0 :       !atomsCache->received_id.init(cx, "received") ||
    1306           0 :       !atomsCache->port_id.init(cx, "port") ||
    1307           0 :       !atomsCache->host_id.init(cx, "host") ||
    1308           0 :       !atomsCache->active_id.init(cx, "active")) {
    1309           0 :     return false;
    1310             :   }
    1311           0 :   return true;
    1312             : }
    1313             : 
    1314             : bool
    1315           0 : SocketElement::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1316             : {
    1317             :   // Passing a null JSContext is OK only if we're initing from null,
    1318             :   // Since in that case we will not have to do any property gets
    1319             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1320             :   // checkers by static analysis tools
    1321           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1322           0 :   SocketElementAtoms* atomsCache = nullptr;
    1323           0 :   if (cx) {
    1324           0 :     atomsCache = GetAtomCache<SocketElementAtoms>(cx);
    1325           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1326           0 :       return false;
    1327             :     }
    1328             :   }
    1329             : 
    1330           0 :   if (!IsConvertibleToDictionary(val)) {
    1331           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    1332             :   }
    1333             : 
    1334           0 :   bool isNull = val.isNullOrUndefined();
    1335             :   // We only need these if !isNull, in which case we have |cx|.
    1336           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1337           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1338           0 :   if (!isNull) {
    1339           0 :     MOZ_ASSERT(cx);
    1340           0 :     object.emplace(cx, &val.toObject());
    1341           0 :     temp.emplace(cx);
    1342             :   }
    1343           0 :   if (!isNull) {
    1344           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->active_id, temp.ptr())) {
    1345           0 :       return false;
    1346             :     }
    1347             :   }
    1348           0 :   if (!isNull && !temp->isUndefined()) {
    1349           0 :     if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mActive)) {
    1350           0 :       return false;
    1351             :     }
    1352             :   } else {
    1353           0 :     mActive = false;
    1354             :   }
    1355           0 :   mIsAnyMemberPresent = true;
    1356             : 
    1357           0 :   if (!isNull) {
    1358           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->host_id, temp.ptr())) {
    1359           0 :       return false;
    1360             :     }
    1361             :   }
    1362           0 :   if (!isNull && !temp->isUndefined()) {
    1363           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mHost)) {
    1364           0 :       return false;
    1365             :     }
    1366             :   } else {
    1367             :     static const char16_t data[] = { 0 };
    1368           0 :     mHost.Rebind(data, ArrayLength(data) - 1);
    1369             :   }
    1370           0 :   mIsAnyMemberPresent = true;
    1371             : 
    1372           0 :   if (!isNull) {
    1373           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->port_id, temp.ptr())) {
    1374           0 :       return false;
    1375             :     }
    1376             :   }
    1377           0 :   if (!isNull && !temp->isUndefined()) {
    1378           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mPort)) {
    1379           0 :       return false;
    1380             :     }
    1381             :   } else {
    1382           0 :     mPort = 0U;
    1383             :   }
    1384           0 :   mIsAnyMemberPresent = true;
    1385             : 
    1386           0 :   if (!isNull) {
    1387           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->received_id, temp.ptr())) {
    1388           0 :       return false;
    1389             :     }
    1390             :   }
    1391           0 :   if (!isNull && !temp->isUndefined()) {
    1392           0 :     if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mReceived)) {
    1393           0 :       return false;
    1394           0 :     } else if (!mozilla::IsFinite(mReceived)) {
    1395           0 :       ThrowErrorMessage(cx, MSG_NOT_FINITE, "'received' member of SocketElement");
    1396           0 :       return false;
    1397             :     }
    1398             :   } else {
    1399           0 :     mReceived = 0.0;
    1400             :   }
    1401           0 :   mIsAnyMemberPresent = true;
    1402             : 
    1403           0 :   if (!isNull) {
    1404           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->sent_id, temp.ptr())) {
    1405           0 :       return false;
    1406             :     }
    1407             :   }
    1408           0 :   if (!isNull && !temp->isUndefined()) {
    1409           0 :     if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mSent)) {
    1410           0 :       return false;
    1411           0 :     } else if (!mozilla::IsFinite(mSent)) {
    1412           0 :       ThrowErrorMessage(cx, MSG_NOT_FINITE, "'sent' member of SocketElement");
    1413           0 :       return false;
    1414             :     }
    1415             :   } else {
    1416           0 :     mSent = 0.0;
    1417             :   }
    1418           0 :   mIsAnyMemberPresent = true;
    1419             : 
    1420           0 :   if (!isNull) {
    1421           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->tcp_id, temp.ptr())) {
    1422           0 :       return false;
    1423             :     }
    1424             :   }
    1425           0 :   if (!isNull && !temp->isUndefined()) {
    1426           0 :     if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mTcp)) {
    1427           0 :       return false;
    1428             :     }
    1429             :   } else {
    1430           0 :     mTcp = false;
    1431             :   }
    1432           0 :   mIsAnyMemberPresent = true;
    1433           0 :   return true;
    1434             : }
    1435             : 
    1436             : bool
    1437           0 : SocketElement::Init(const nsAString& aJSON)
    1438             : {
    1439           0 :   AutoJSAPI jsapi;
    1440           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    1441           0 :   if (!cleanGlobal) {
    1442           0 :     return false;
    1443             :   }
    1444           0 :   if (!jsapi.Init(cleanGlobal)) {
    1445           0 :     return false;
    1446             :   }
    1447           0 :   JSContext* cx = jsapi.cx();
    1448           0 :   JS::Rooted<JS::Value> json(cx);
    1449           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    1450           0 :   NS_ENSURE_TRUE(ok, false);
    1451           0 :   return Init(cx, json);
    1452             : }
    1453             : 
    1454             : bool
    1455           0 : SocketElement::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1456             : {
    1457           0 :   SocketElementAtoms* atomsCache = GetAtomCache<SocketElementAtoms>(cx);
    1458           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1459           0 :     return false;
    1460             :   }
    1461             : 
    1462           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    1463           0 :   if (!obj) {
    1464           0 :     return false;
    1465             :   }
    1466           0 :   rval.set(JS::ObjectValue(*obj));
    1467             : 
    1468             :   do {
    1469             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1470           0 :     JS::Rooted<JS::Value> temp(cx);
    1471           0 :     bool const & currentValue = mActive;
    1472           0 :     temp.setBoolean(currentValue);
    1473           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->active_id, temp, JSPROP_ENUMERATE)) {
    1474           0 :       return false;
    1475             :     }
    1476           0 :     break;
    1477             :   } while(0);
    1478             : 
    1479             :   do {
    1480             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1481           0 :     JS::Rooted<JS::Value> temp(cx);
    1482           0 :     nsString const & currentValue = mHost;
    1483           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    1484           0 :       return false;
    1485             :     }
    1486           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->host_id, temp, JSPROP_ENUMERATE)) {
    1487           0 :       return false;
    1488             :     }
    1489           0 :     break;
    1490             :   } while(0);
    1491             : 
    1492             :   do {
    1493             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1494           0 :     JS::Rooted<JS::Value> temp(cx);
    1495           0 :     uint32_t const & currentValue = mPort;
    1496           0 :     temp.setNumber(currentValue);
    1497           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->port_id, temp, JSPROP_ENUMERATE)) {
    1498           0 :       return false;
    1499             :     }
    1500           0 :     break;
    1501             :   } while(0);
    1502             : 
    1503             :   do {
    1504             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1505           0 :     JS::Rooted<JS::Value> temp(cx);
    1506           0 :     double const & currentValue = mReceived;
    1507           0 :     temp.set(JS_NumberValue(double(currentValue)));
    1508           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->received_id, temp, JSPROP_ENUMERATE)) {
    1509           0 :       return false;
    1510             :     }
    1511           0 :     break;
    1512             :   } while(0);
    1513             : 
    1514             :   do {
    1515             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1516           0 :     JS::Rooted<JS::Value> temp(cx);
    1517           0 :     double const & currentValue = mSent;
    1518           0 :     temp.set(JS_NumberValue(double(currentValue)));
    1519           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->sent_id, temp, JSPROP_ENUMERATE)) {
    1520           0 :       return false;
    1521             :     }
    1522           0 :     break;
    1523             :   } while(0);
    1524             : 
    1525             :   do {
    1526             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1527           0 :     JS::Rooted<JS::Value> temp(cx);
    1528           0 :     bool const & currentValue = mTcp;
    1529           0 :     temp.setBoolean(currentValue);
    1530           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->tcp_id, temp, JSPROP_ENUMERATE)) {
    1531           0 :       return false;
    1532             :     }
    1533           0 :     break;
    1534             :   } while(0);
    1535             : 
    1536           0 :   return true;
    1537             : }
    1538             : 
    1539             : bool
    1540           0 : SocketElement::ToJSON(nsAString& aJSON) const
    1541             : {
    1542           0 :   AutoJSAPI jsapi;
    1543           0 :   jsapi.Init();
    1544           0 :   JSContext *cx = jsapi.cx();
    1545             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    1546             :   // because we'll only be creating objects, in ways that have no
    1547             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    1548             :   // which likewise guarantees no side-effects for the sorts of
    1549             :   // things we will pass it.
    1550           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    1551           0 :   JS::Rooted<JS::Value> val(cx);
    1552           0 :   if (!ToObjectInternal(cx, &val)) {
    1553           0 :     return false;
    1554             :   }
    1555           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    1556           0 :   return StringifyToJSON(cx, obj, aJSON);
    1557             : }
    1558             : 
    1559             : void
    1560           0 : SocketElement::TraceDictionary(JSTracer* trc)
    1561             : {
    1562           0 : }
    1563             : 
    1564             : SocketElement&
    1565           0 : SocketElement::operator=(const SocketElement& aOther)
    1566             : {
    1567           0 :   mActive = aOther.mActive;
    1568           0 :   mHost = aOther.mHost;
    1569           0 :   mPort = aOther.mPort;
    1570           0 :   mReceived = aOther.mReceived;
    1571           0 :   mSent = aOther.mSent;
    1572           0 :   mTcp = aOther.mTcp;
    1573           0 :   return *this;
    1574             : }
    1575             : 
    1576             : namespace binding_detail {
    1577             : } // namespace binding_detail
    1578             : 
    1579             : 
    1580             : 
    1581           0 : WebSocketElement::WebSocketElement()
    1582             : {
    1583             :   // Safe to pass a null context if we pass a null value
    1584           0 :   Init(nullptr, JS::NullHandleValue);
    1585           0 : }
    1586             : 
    1587             : 
    1588             : 
    1589             : bool
    1590           0 : WebSocketElement::InitIds(JSContext* cx, WebSocketElementAtoms* atomsCache)
    1591             : {
    1592           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1593             : 
    1594             :   // Initialize these in reverse order so that any failure leaves the first one
    1595             :   // uninitialized.
    1596           0 :   if (!atomsCache->sentsize_id.init(cx, "sentsize") ||
    1597           0 :       !atomsCache->receivedsize_id.init(cx, "receivedsize") ||
    1598           0 :       !atomsCache->msgsent_id.init(cx, "msgsent") ||
    1599           0 :       !atomsCache->msgreceived_id.init(cx, "msgreceived") ||
    1600           0 :       !atomsCache->hostport_id.init(cx, "hostport") ||
    1601           0 :       !atomsCache->encrypted_id.init(cx, "encrypted")) {
    1602           0 :     return false;
    1603             :   }
    1604           0 :   return true;
    1605             : }
    1606             : 
    1607             : bool
    1608           0 : WebSocketElement::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1609             : {
    1610             :   // Passing a null JSContext is OK only if we're initing from null,
    1611             :   // Since in that case we will not have to do any property gets
    1612             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1613             :   // checkers by static analysis tools
    1614           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1615           0 :   WebSocketElementAtoms* atomsCache = nullptr;
    1616           0 :   if (cx) {
    1617           0 :     atomsCache = GetAtomCache<WebSocketElementAtoms>(cx);
    1618           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1619           0 :       return false;
    1620             :     }
    1621             :   }
    1622             : 
    1623           0 :   if (!IsConvertibleToDictionary(val)) {
    1624           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    1625             :   }
    1626             : 
    1627           0 :   bool isNull = val.isNullOrUndefined();
    1628             :   // We only need these if !isNull, in which case we have |cx|.
    1629           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1630           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1631           0 :   if (!isNull) {
    1632           0 :     MOZ_ASSERT(cx);
    1633           0 :     object.emplace(cx, &val.toObject());
    1634           0 :     temp.emplace(cx);
    1635             :   }
    1636           0 :   if (!isNull) {
    1637           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->encrypted_id, temp.ptr())) {
    1638           0 :       return false;
    1639             :     }
    1640             :   }
    1641           0 :   if (!isNull && !temp->isUndefined()) {
    1642           0 :     if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mEncrypted)) {
    1643           0 :       return false;
    1644             :     }
    1645             :   } else {
    1646           0 :     mEncrypted = false;
    1647             :   }
    1648           0 :   mIsAnyMemberPresent = true;
    1649             : 
    1650           0 :   if (!isNull) {
    1651           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->hostport_id, temp.ptr())) {
    1652           0 :       return false;
    1653             :     }
    1654             :   }
    1655           0 :   if (!isNull && !temp->isUndefined()) {
    1656           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mHostport)) {
    1657           0 :       return false;
    1658             :     }
    1659             :   } else {
    1660             :     static const char16_t data[] = { 0 };
    1661           0 :     mHostport.Rebind(data, ArrayLength(data) - 1);
    1662             :   }
    1663           0 :   mIsAnyMemberPresent = true;
    1664             : 
    1665           0 :   if (!isNull) {
    1666           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->msgreceived_id, temp.ptr())) {
    1667           0 :       return false;
    1668             :     }
    1669             :   }
    1670           0 :   if (!isNull && !temp->isUndefined()) {
    1671           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mMsgreceived)) {
    1672           0 :       return false;
    1673             :     }
    1674             :   } else {
    1675           0 :     mMsgreceived = 0U;
    1676             :   }
    1677           0 :   mIsAnyMemberPresent = true;
    1678             : 
    1679           0 :   if (!isNull) {
    1680           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->msgsent_id, temp.ptr())) {
    1681           0 :       return false;
    1682             :     }
    1683             :   }
    1684           0 :   if (!isNull && !temp->isUndefined()) {
    1685           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mMsgsent)) {
    1686           0 :       return false;
    1687             :     }
    1688             :   } else {
    1689           0 :     mMsgsent = 0U;
    1690             :   }
    1691           0 :   mIsAnyMemberPresent = true;
    1692             : 
    1693           0 :   if (!isNull) {
    1694           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->receivedsize_id, temp.ptr())) {
    1695           0 :       return false;
    1696             :     }
    1697             :   }
    1698           0 :   if (!isNull && !temp->isUndefined()) {
    1699           0 :     if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mReceivedsize)) {
    1700           0 :       return false;
    1701           0 :     } else if (!mozilla::IsFinite(mReceivedsize)) {
    1702           0 :       ThrowErrorMessage(cx, MSG_NOT_FINITE, "'receivedsize' member of WebSocketElement");
    1703           0 :       return false;
    1704             :     }
    1705             :   } else {
    1706           0 :     mReceivedsize = 0.0;
    1707             :   }
    1708           0 :   mIsAnyMemberPresent = true;
    1709             : 
    1710           0 :   if (!isNull) {
    1711           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->sentsize_id, temp.ptr())) {
    1712           0 :       return false;
    1713             :     }
    1714             :   }
    1715           0 :   if (!isNull && !temp->isUndefined()) {
    1716           0 :     if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mSentsize)) {
    1717           0 :       return false;
    1718           0 :     } else if (!mozilla::IsFinite(mSentsize)) {
    1719           0 :       ThrowErrorMessage(cx, MSG_NOT_FINITE, "'sentsize' member of WebSocketElement");
    1720           0 :       return false;
    1721             :     }
    1722             :   } else {
    1723           0 :     mSentsize = 0.0;
    1724             :   }
    1725           0 :   mIsAnyMemberPresent = true;
    1726           0 :   return true;
    1727             : }
    1728             : 
    1729             : bool
    1730           0 : WebSocketElement::Init(const nsAString& aJSON)
    1731             : {
    1732           0 :   AutoJSAPI jsapi;
    1733           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    1734           0 :   if (!cleanGlobal) {
    1735           0 :     return false;
    1736             :   }
    1737           0 :   if (!jsapi.Init(cleanGlobal)) {
    1738           0 :     return false;
    1739             :   }
    1740           0 :   JSContext* cx = jsapi.cx();
    1741           0 :   JS::Rooted<JS::Value> json(cx);
    1742           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    1743           0 :   NS_ENSURE_TRUE(ok, false);
    1744           0 :   return Init(cx, json);
    1745             : }
    1746             : 
    1747             : bool
    1748           0 : WebSocketElement::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1749             : {
    1750           0 :   WebSocketElementAtoms* atomsCache = GetAtomCache<WebSocketElementAtoms>(cx);
    1751           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1752           0 :     return false;
    1753             :   }
    1754             : 
    1755           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    1756           0 :   if (!obj) {
    1757           0 :     return false;
    1758             :   }
    1759           0 :   rval.set(JS::ObjectValue(*obj));
    1760             : 
    1761             :   do {
    1762             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1763           0 :     JS::Rooted<JS::Value> temp(cx);
    1764           0 :     bool const & currentValue = mEncrypted;
    1765           0 :     temp.setBoolean(currentValue);
    1766           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->encrypted_id, temp, JSPROP_ENUMERATE)) {
    1767           0 :       return false;
    1768             :     }
    1769           0 :     break;
    1770             :   } while(0);
    1771             : 
    1772             :   do {
    1773             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1774           0 :     JS::Rooted<JS::Value> temp(cx);
    1775           0 :     nsString const & currentValue = mHostport;
    1776           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    1777           0 :       return false;
    1778             :     }
    1779           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->hostport_id, temp, JSPROP_ENUMERATE)) {
    1780           0 :       return false;
    1781             :     }
    1782           0 :     break;
    1783             :   } while(0);
    1784             : 
    1785             :   do {
    1786             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1787           0 :     JS::Rooted<JS::Value> temp(cx);
    1788           0 :     uint32_t const & currentValue = mMsgreceived;
    1789           0 :     temp.setNumber(currentValue);
    1790           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->msgreceived_id, temp, JSPROP_ENUMERATE)) {
    1791           0 :       return false;
    1792             :     }
    1793           0 :     break;
    1794             :   } while(0);
    1795             : 
    1796             :   do {
    1797             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1798           0 :     JS::Rooted<JS::Value> temp(cx);
    1799           0 :     uint32_t const & currentValue = mMsgsent;
    1800           0 :     temp.setNumber(currentValue);
    1801           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->msgsent_id, temp, JSPROP_ENUMERATE)) {
    1802           0 :       return false;
    1803             :     }
    1804           0 :     break;
    1805             :   } while(0);
    1806             : 
    1807             :   do {
    1808             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1809           0 :     JS::Rooted<JS::Value> temp(cx);
    1810           0 :     double const & currentValue = mReceivedsize;
    1811           0 :     temp.set(JS_NumberValue(double(currentValue)));
    1812           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->receivedsize_id, temp, JSPROP_ENUMERATE)) {
    1813           0 :       return false;
    1814             :     }
    1815           0 :     break;
    1816             :   } while(0);
    1817             : 
    1818             :   do {
    1819             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1820           0 :     JS::Rooted<JS::Value> temp(cx);
    1821           0 :     double const & currentValue = mSentsize;
    1822           0 :     temp.set(JS_NumberValue(double(currentValue)));
    1823           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->sentsize_id, temp, JSPROP_ENUMERATE)) {
    1824           0 :       return false;
    1825             :     }
    1826           0 :     break;
    1827             :   } while(0);
    1828             : 
    1829           0 :   return true;
    1830             : }
    1831             : 
    1832             : bool
    1833           0 : WebSocketElement::ToJSON(nsAString& aJSON) const
    1834             : {
    1835           0 :   AutoJSAPI jsapi;
    1836           0 :   jsapi.Init();
    1837           0 :   JSContext *cx = jsapi.cx();
    1838             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    1839             :   // because we'll only be creating objects, in ways that have no
    1840             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    1841             :   // which likewise guarantees no side-effects for the sorts of
    1842             :   // things we will pass it.
    1843           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    1844           0 :   JS::Rooted<JS::Value> val(cx);
    1845           0 :   if (!ToObjectInternal(cx, &val)) {
    1846           0 :     return false;
    1847             :   }
    1848           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    1849           0 :   return StringifyToJSON(cx, obj, aJSON);
    1850             : }
    1851             : 
    1852             : void
    1853           0 : WebSocketElement::TraceDictionary(JSTracer* trc)
    1854             : {
    1855           0 : }
    1856             : 
    1857             : WebSocketElement&
    1858           0 : WebSocketElement::operator=(const WebSocketElement& aOther)
    1859             : {
    1860           0 :   mEncrypted = aOther.mEncrypted;
    1861           0 :   mHostport = aOther.mHostport;
    1862           0 :   mMsgreceived = aOther.mMsgreceived;
    1863           0 :   mMsgsent = aOther.mMsgsent;
    1864           0 :   mReceivedsize = aOther.mReceivedsize;
    1865           0 :   mSentsize = aOther.mSentsize;
    1866           0 :   return *this;
    1867             : }
    1868             : 
    1869             : namespace binding_detail {
    1870             : } // namespace binding_detail
    1871             : 
    1872             : 
    1873             : 
    1874           0 : DNSCacheDict::DNSCacheDict()
    1875             : {
    1876             :   // Safe to pass a null context if we pass a null value
    1877           0 :   Init(nullptr, JS::NullHandleValue);
    1878           0 : }
    1879             : 
    1880             : 
    1881             : 
    1882             : bool
    1883           0 : DNSCacheDict::InitIds(JSContext* cx, DNSCacheDictAtoms* atomsCache)
    1884             : {
    1885           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1886             : 
    1887             :   // Initialize these in reverse order so that any failure leaves the first one
    1888             :   // uninitialized.
    1889           0 :   if (!atomsCache->entries_id.init(cx, "entries")) {
    1890           0 :     return false;
    1891             :   }
    1892           0 :   return true;
    1893             : }
    1894             : 
    1895             : bool
    1896           0 : DNSCacheDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1897             : {
    1898             :   // Passing a null JSContext is OK only if we're initing from null,
    1899             :   // Since in that case we will not have to do any property gets
    1900             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1901             :   // checkers by static analysis tools
    1902           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1903           0 :   DNSCacheDictAtoms* atomsCache = nullptr;
    1904           0 :   if (cx) {
    1905           0 :     atomsCache = GetAtomCache<DNSCacheDictAtoms>(cx);
    1906           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1907           0 :       return false;
    1908             :     }
    1909             :   }
    1910             : 
    1911           0 :   if (!IsConvertibleToDictionary(val)) {
    1912           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    1913             :   }
    1914             : 
    1915           0 :   bool isNull = val.isNullOrUndefined();
    1916             :   // We only need these if !isNull, in which case we have |cx|.
    1917           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1918           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1919           0 :   if (!isNull) {
    1920           0 :     MOZ_ASSERT(cx);
    1921           0 :     object.emplace(cx, &val.toObject());
    1922           0 :     temp.emplace(cx);
    1923             :   }
    1924           0 :   if (!isNull) {
    1925           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->entries_id, temp.ptr())) {
    1926           0 :       return false;
    1927             :     }
    1928             :   }
    1929           0 :   if (!isNull && !temp->isUndefined()) {
    1930           0 :     mEntries.Construct();
    1931           0 :     if (temp.ref().isObject()) {
    1932           0 :       JS::ForOfIterator iter(cx);
    1933           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    1934           0 :         return false;
    1935             :       }
    1936           0 :       if (!iter.valueIsIterable()) {
    1937           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'entries' member of DNSCacheDict");
    1938           0 :         return false;
    1939             :       }
    1940           0 :       Sequence<DnsCacheEntry> &arr = (mEntries.Value());
    1941           0 :       JS::Rooted<JS::Value> temp(cx);
    1942             :       while (true) {
    1943             :         bool done;
    1944           0 :         if (!iter.next(&temp, &done)) {
    1945           0 :           return false;
    1946             :         }
    1947           0 :         if (done) {
    1948           0 :           break;
    1949             :         }
    1950           0 :         DnsCacheEntry* slotPtr = arr.AppendElement(mozilla::fallible);
    1951           0 :         if (!slotPtr) {
    1952           0 :           JS_ReportOutOfMemory(cx);
    1953           0 :           return false;
    1954             :         }
    1955           0 :         DnsCacheEntry& slot = *slotPtr;
    1956           0 :         if (!slot.Init(cx, temp,  "Element of 'entries' member of DNSCacheDict", passedToJSImpl)) {
    1957           0 :           return false;
    1958             :         }
    1959           0 :       }
    1960             :     } else {
    1961           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'entries' member of DNSCacheDict");
    1962           0 :       return false;
    1963             :     }
    1964           0 :     mIsAnyMemberPresent = true;
    1965             :   }
    1966           0 :   return true;
    1967             : }
    1968             : 
    1969             : bool
    1970           0 : DNSCacheDict::Init(const nsAString& aJSON)
    1971             : {
    1972           0 :   AutoJSAPI jsapi;
    1973           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    1974           0 :   if (!cleanGlobal) {
    1975           0 :     return false;
    1976             :   }
    1977           0 :   if (!jsapi.Init(cleanGlobal)) {
    1978           0 :     return false;
    1979             :   }
    1980           0 :   JSContext* cx = jsapi.cx();
    1981           0 :   JS::Rooted<JS::Value> json(cx);
    1982           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    1983           0 :   NS_ENSURE_TRUE(ok, false);
    1984           0 :   return Init(cx, json);
    1985             : }
    1986             : 
    1987             : bool
    1988           0 : DNSCacheDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1989             : {
    1990           0 :   DNSCacheDictAtoms* atomsCache = GetAtomCache<DNSCacheDictAtoms>(cx);
    1991           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1992           0 :     return false;
    1993             :   }
    1994             : 
    1995           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    1996           0 :   if (!obj) {
    1997           0 :     return false;
    1998             :   }
    1999           0 :   rval.set(JS::ObjectValue(*obj));
    2000             : 
    2001           0 :   if (mEntries.WasPassed()) {
    2002             :     do {
    2003             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2004           0 :       JS::Rooted<JS::Value> temp(cx);
    2005           0 :       Sequence<DnsCacheEntry> const & currentValue = mEntries.InternalValue();
    2006             : 
    2007           0 :       uint32_t length = currentValue.Length();
    2008           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    2009           0 :       if (!returnArray) {
    2010           0 :         return false;
    2011             :       }
    2012             :       // Scope for 'tmp'
    2013             :       {
    2014           0 :         JS::Rooted<JS::Value> tmp(cx);
    2015           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    2016             :           // Control block to let us common up the JS_DefineElement calls when there
    2017             :           // are different ways to succeed at wrapping the object.
    2018             :           do {
    2019           0 :             if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
    2020           0 :               return false;
    2021             :             }
    2022           0 :             break;
    2023             :           } while (0);
    2024           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    2025             :                                 JSPROP_ENUMERATE)) {
    2026           0 :             return false;
    2027             :           }
    2028             :         }
    2029             :       }
    2030           0 :       temp.setObject(*returnArray);
    2031           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->entries_id, temp, JSPROP_ENUMERATE)) {
    2032           0 :         return false;
    2033             :       }
    2034           0 :       break;
    2035             :     } while(0);
    2036             :   }
    2037             : 
    2038           0 :   return true;
    2039             : }
    2040             : 
    2041             : bool
    2042           0 : DNSCacheDict::ToJSON(nsAString& aJSON) const
    2043             : {
    2044           0 :   AutoJSAPI jsapi;
    2045           0 :   jsapi.Init();
    2046           0 :   JSContext *cx = jsapi.cx();
    2047             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    2048             :   // because we'll only be creating objects, in ways that have no
    2049             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    2050             :   // which likewise guarantees no side-effects for the sorts of
    2051             :   // things we will pass it.
    2052           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    2053           0 :   JS::Rooted<JS::Value> val(cx);
    2054           0 :   if (!ToObjectInternal(cx, &val)) {
    2055           0 :     return false;
    2056             :   }
    2057           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    2058           0 :   return StringifyToJSON(cx, obj, aJSON);
    2059             : }
    2060             : 
    2061             : void
    2062           0 : DNSCacheDict::TraceDictionary(JSTracer* trc)
    2063             : {
    2064           0 : }
    2065             : 
    2066             : DNSCacheDict&
    2067           0 : DNSCacheDict::operator=(const DNSCacheDict& aOther)
    2068             : {
    2069           0 :   mEntries.Reset();
    2070           0 :   if (aOther.mEntries.WasPassed()) {
    2071           0 :     mEntries.Construct(aOther.mEntries.Value());
    2072             :   }
    2073           0 :   return *this;
    2074             : }
    2075             : 
    2076             : namespace binding_detail {
    2077             : } // namespace binding_detail
    2078             : 
    2079             : 
    2080             : 
    2081           0 : HttpConnectionElement::HttpConnectionElement()
    2082             : {
    2083             :   // Safe to pass a null context if we pass a null value
    2084           0 :   Init(nullptr, JS::NullHandleValue);
    2085           0 : }
    2086             : 
    2087             : 
    2088             : 
    2089             : bool
    2090           0 : HttpConnectionElement::InitIds(JSContext* cx, HttpConnectionElementAtoms* atomsCache)
    2091             : {
    2092           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    2093             : 
    2094             :   // Initialize these in reverse order so that any failure leaves the first one
    2095             :   // uninitialized.
    2096           0 :   if (!atomsCache->ssl_id.init(cx, "ssl") ||
    2097           0 :       !atomsCache->spdy_id.init(cx, "spdy") ||
    2098           0 :       !atomsCache->port_id.init(cx, "port") ||
    2099           0 :       !atomsCache->idle_id.init(cx, "idle") ||
    2100           0 :       !atomsCache->host_id.init(cx, "host") ||
    2101           0 :       !atomsCache->halfOpens_id.init(cx, "halfOpens") ||
    2102           0 :       !atomsCache->active_id.init(cx, "active")) {
    2103           0 :     return false;
    2104             :   }
    2105           0 :   return true;
    2106             : }
    2107             : 
    2108             : bool
    2109           0 : HttpConnectionElement::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    2110             : {
    2111             :   // Passing a null JSContext is OK only if we're initing from null,
    2112             :   // Since in that case we will not have to do any property gets
    2113             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    2114             :   // checkers by static analysis tools
    2115           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    2116           0 :   HttpConnectionElementAtoms* atomsCache = nullptr;
    2117           0 :   if (cx) {
    2118           0 :     atomsCache = GetAtomCache<HttpConnectionElementAtoms>(cx);
    2119           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2120           0 :       return false;
    2121             :     }
    2122             :   }
    2123             : 
    2124           0 :   if (!IsConvertibleToDictionary(val)) {
    2125           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    2126             :   }
    2127             : 
    2128           0 :   bool isNull = val.isNullOrUndefined();
    2129             :   // We only need these if !isNull, in which case we have |cx|.
    2130           0 :   Maybe<JS::Rooted<JSObject *> > object;
    2131           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    2132           0 :   if (!isNull) {
    2133           0 :     MOZ_ASSERT(cx);
    2134           0 :     object.emplace(cx, &val.toObject());
    2135           0 :     temp.emplace(cx);
    2136             :   }
    2137           0 :   if (!isNull) {
    2138           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->active_id, temp.ptr())) {
    2139           0 :       return false;
    2140             :     }
    2141             :   }
    2142           0 :   if (!isNull && !temp->isUndefined()) {
    2143           0 :     mActive.Construct();
    2144           0 :     if (temp.ref().isObject()) {
    2145           0 :       JS::ForOfIterator iter(cx);
    2146           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    2147           0 :         return false;
    2148             :       }
    2149           0 :       if (!iter.valueIsIterable()) {
    2150           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'active' member of HttpConnectionElement");
    2151           0 :         return false;
    2152             :       }
    2153           0 :       Sequence<HttpConnInfo> &arr = (mActive.Value());
    2154           0 :       JS::Rooted<JS::Value> temp(cx);
    2155             :       while (true) {
    2156             :         bool done;
    2157           0 :         if (!iter.next(&temp, &done)) {
    2158           0 :           return false;
    2159             :         }
    2160           0 :         if (done) {
    2161           0 :           break;
    2162             :         }
    2163           0 :         HttpConnInfo* slotPtr = arr.AppendElement(mozilla::fallible);
    2164           0 :         if (!slotPtr) {
    2165           0 :           JS_ReportOutOfMemory(cx);
    2166           0 :           return false;
    2167             :         }
    2168           0 :         HttpConnInfo& slot = *slotPtr;
    2169           0 :         if (!slot.Init(cx, temp,  "Element of 'active' member of HttpConnectionElement", passedToJSImpl)) {
    2170           0 :           return false;
    2171             :         }
    2172           0 :       }
    2173             :     } else {
    2174           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'active' member of HttpConnectionElement");
    2175           0 :       return false;
    2176             :     }
    2177           0 :     mIsAnyMemberPresent = true;
    2178             :   }
    2179             : 
    2180           0 :   if (!isNull) {
    2181           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->halfOpens_id, temp.ptr())) {
    2182           0 :       return false;
    2183             :     }
    2184             :   }
    2185           0 :   if (!isNull && !temp->isUndefined()) {
    2186           0 :     mHalfOpens.Construct();
    2187           0 :     if (temp.ref().isObject()) {
    2188           0 :       JS::ForOfIterator iter(cx);
    2189           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    2190           0 :         return false;
    2191             :       }
    2192           0 :       if (!iter.valueIsIterable()) {
    2193           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'halfOpens' member of HttpConnectionElement");
    2194           0 :         return false;
    2195             :       }
    2196           0 :       Sequence<HalfOpenInfoDict> &arr = (mHalfOpens.Value());
    2197           0 :       JS::Rooted<JS::Value> temp(cx);
    2198             :       while (true) {
    2199             :         bool done;
    2200           0 :         if (!iter.next(&temp, &done)) {
    2201           0 :           return false;
    2202             :         }
    2203           0 :         if (done) {
    2204           0 :           break;
    2205             :         }
    2206           0 :         HalfOpenInfoDict* slotPtr = arr.AppendElement(mozilla::fallible);
    2207           0 :         if (!slotPtr) {
    2208           0 :           JS_ReportOutOfMemory(cx);
    2209           0 :           return false;
    2210             :         }
    2211           0 :         HalfOpenInfoDict& slot = *slotPtr;
    2212           0 :         if (!slot.Init(cx, temp,  "Element of 'halfOpens' member of HttpConnectionElement", passedToJSImpl)) {
    2213           0 :           return false;
    2214             :         }
    2215           0 :       }
    2216             :     } else {
    2217           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'halfOpens' member of HttpConnectionElement");
    2218           0 :       return false;
    2219             :     }
    2220           0 :     mIsAnyMemberPresent = true;
    2221             :   }
    2222             : 
    2223           0 :   if (!isNull) {
    2224           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->host_id, temp.ptr())) {
    2225           0 :       return false;
    2226             :     }
    2227             :   }
    2228           0 :   if (!isNull && !temp->isUndefined()) {
    2229           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mHost)) {
    2230           0 :       return false;
    2231             :     }
    2232             :   } else {
    2233             :     static const char16_t data[] = { 0 };
    2234           0 :     mHost.Rebind(data, ArrayLength(data) - 1);
    2235             :   }
    2236           0 :   mIsAnyMemberPresent = true;
    2237             : 
    2238           0 :   if (!isNull) {
    2239           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->idle_id, temp.ptr())) {
    2240           0 :       return false;
    2241             :     }
    2242             :   }
    2243           0 :   if (!isNull && !temp->isUndefined()) {
    2244           0 :     mIdle.Construct();
    2245           0 :     if (temp.ref().isObject()) {
    2246           0 :       JS::ForOfIterator iter(cx);
    2247           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    2248           0 :         return false;
    2249             :       }
    2250           0 :       if (!iter.valueIsIterable()) {
    2251           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'idle' member of HttpConnectionElement");
    2252           0 :         return false;
    2253             :       }
    2254           0 :       Sequence<HttpConnInfo> &arr = (mIdle.Value());
    2255           0 :       JS::Rooted<JS::Value> temp(cx);
    2256             :       while (true) {
    2257             :         bool done;
    2258           0 :         if (!iter.next(&temp, &done)) {
    2259           0 :           return false;
    2260             :         }
    2261           0 :         if (done) {
    2262           0 :           break;
    2263             :         }
    2264           0 :         HttpConnInfo* slotPtr = arr.AppendElement(mozilla::fallible);
    2265           0 :         if (!slotPtr) {
    2266           0 :           JS_ReportOutOfMemory(cx);
    2267           0 :           return false;
    2268             :         }
    2269           0 :         HttpConnInfo& slot = *slotPtr;
    2270           0 :         if (!slot.Init(cx, temp,  "Element of 'idle' member of HttpConnectionElement", passedToJSImpl)) {
    2271           0 :           return false;
    2272             :         }
    2273           0 :       }
    2274             :     } else {
    2275           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'idle' member of HttpConnectionElement");
    2276           0 :       return false;
    2277             :     }
    2278           0 :     mIsAnyMemberPresent = true;
    2279             :   }
    2280             : 
    2281           0 :   if (!isNull) {
    2282           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->port_id, temp.ptr())) {
    2283           0 :       return false;
    2284             :     }
    2285             :   }
    2286           0 :   if (!isNull && !temp->isUndefined()) {
    2287           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mPort)) {
    2288           0 :       return false;
    2289             :     }
    2290             :   } else {
    2291           0 :     mPort = 0U;
    2292             :   }
    2293           0 :   mIsAnyMemberPresent = true;
    2294             : 
    2295           0 :   if (!isNull) {
    2296           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->spdy_id, temp.ptr())) {
    2297           0 :       return false;
    2298             :     }
    2299             :   }
    2300           0 :   if (!isNull && !temp->isUndefined()) {
    2301           0 :     if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mSpdy)) {
    2302           0 :       return false;
    2303             :     }
    2304             :   } else {
    2305           0 :     mSpdy = false;
    2306             :   }
    2307           0 :   mIsAnyMemberPresent = true;
    2308             : 
    2309           0 :   if (!isNull) {
    2310           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->ssl_id, temp.ptr())) {
    2311           0 :       return false;
    2312             :     }
    2313             :   }
    2314           0 :   if (!isNull && !temp->isUndefined()) {
    2315           0 :     if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mSsl)) {
    2316           0 :       return false;
    2317             :     }
    2318             :   } else {
    2319           0 :     mSsl = false;
    2320             :   }
    2321           0 :   mIsAnyMemberPresent = true;
    2322           0 :   return true;
    2323             : }
    2324             : 
    2325             : bool
    2326           0 : HttpConnectionElement::Init(const nsAString& aJSON)
    2327             : {
    2328           0 :   AutoJSAPI jsapi;
    2329           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    2330           0 :   if (!cleanGlobal) {
    2331           0 :     return false;
    2332             :   }
    2333           0 :   if (!jsapi.Init(cleanGlobal)) {
    2334           0 :     return false;
    2335             :   }
    2336           0 :   JSContext* cx = jsapi.cx();
    2337           0 :   JS::Rooted<JS::Value> json(cx);
    2338           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    2339           0 :   NS_ENSURE_TRUE(ok, false);
    2340           0 :   return Init(cx, json);
    2341             : }
    2342             : 
    2343             : bool
    2344           0 : HttpConnectionElement::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    2345             : {
    2346           0 :   HttpConnectionElementAtoms* atomsCache = GetAtomCache<HttpConnectionElementAtoms>(cx);
    2347           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2348           0 :     return false;
    2349             :   }
    2350             : 
    2351           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    2352           0 :   if (!obj) {
    2353           0 :     return false;
    2354             :   }
    2355           0 :   rval.set(JS::ObjectValue(*obj));
    2356             : 
    2357           0 :   if (mActive.WasPassed()) {
    2358             :     do {
    2359             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2360           0 :       JS::Rooted<JS::Value> temp(cx);
    2361           0 :       Sequence<HttpConnInfo> const & currentValue = mActive.InternalValue();
    2362             : 
    2363           0 :       uint32_t length = currentValue.Length();
    2364           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    2365           0 :       if (!returnArray) {
    2366           0 :         return false;
    2367             :       }
    2368             :       // Scope for 'tmp'
    2369             :       {
    2370           0 :         JS::Rooted<JS::Value> tmp(cx);
    2371           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    2372             :           // Control block to let us common up the JS_DefineElement calls when there
    2373             :           // are different ways to succeed at wrapping the object.
    2374             :           do {
    2375           0 :             if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
    2376           0 :               return false;
    2377             :             }
    2378           0 :             break;
    2379             :           } while (0);
    2380           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    2381             :                                 JSPROP_ENUMERATE)) {
    2382           0 :             return false;
    2383             :           }
    2384             :         }
    2385             :       }
    2386           0 :       temp.setObject(*returnArray);
    2387           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->active_id, temp, JSPROP_ENUMERATE)) {
    2388           0 :         return false;
    2389             :       }
    2390           0 :       break;
    2391             :     } while(0);
    2392             :   }
    2393             : 
    2394           0 :   if (mHalfOpens.WasPassed()) {
    2395             :     do {
    2396             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2397           0 :       JS::Rooted<JS::Value> temp(cx);
    2398           0 :       Sequence<HalfOpenInfoDict> const & currentValue = mHalfOpens.InternalValue();
    2399             : 
    2400           0 :       uint32_t length = currentValue.Length();
    2401           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    2402           0 :       if (!returnArray) {
    2403           0 :         return false;
    2404             :       }
    2405             :       // Scope for 'tmp'
    2406             :       {
    2407           0 :         JS::Rooted<JS::Value> tmp(cx);
    2408           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    2409             :           // Control block to let us common up the JS_DefineElement calls when there
    2410             :           // are different ways to succeed at wrapping the object.
    2411             :           do {
    2412           0 :             if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
    2413           0 :               return false;
    2414             :             }
    2415           0 :             break;
    2416             :           } while (0);
    2417           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    2418             :                                 JSPROP_ENUMERATE)) {
    2419           0 :             return false;
    2420             :           }
    2421             :         }
    2422             :       }
    2423           0 :       temp.setObject(*returnArray);
    2424           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->halfOpens_id, temp, JSPROP_ENUMERATE)) {
    2425           0 :         return false;
    2426             :       }
    2427           0 :       break;
    2428             :     } while(0);
    2429             :   }
    2430             : 
    2431             :   do {
    2432             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2433           0 :     JS::Rooted<JS::Value> temp(cx);
    2434           0 :     nsString const & currentValue = mHost;
    2435           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    2436           0 :       return false;
    2437             :     }
    2438           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->host_id, temp, JSPROP_ENUMERATE)) {
    2439           0 :       return false;
    2440             :     }
    2441           0 :     break;
    2442             :   } while(0);
    2443             : 
    2444           0 :   if (mIdle.WasPassed()) {
    2445             :     do {
    2446             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2447           0 :       JS::Rooted<JS::Value> temp(cx);
    2448           0 :       Sequence<HttpConnInfo> const & currentValue = mIdle.InternalValue();
    2449             : 
    2450           0 :       uint32_t length = currentValue.Length();
    2451           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    2452           0 :       if (!returnArray) {
    2453           0 :         return false;
    2454             :       }
    2455             :       // Scope for 'tmp'
    2456             :       {
    2457           0 :         JS::Rooted<JS::Value> tmp(cx);
    2458           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    2459             :           // Control block to let us common up the JS_DefineElement calls when there
    2460             :           // are different ways to succeed at wrapping the object.
    2461             :           do {
    2462           0 :             if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
    2463           0 :               return false;
    2464             :             }
    2465           0 :             break;
    2466             :           } while (0);
    2467           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    2468             :                                 JSPROP_ENUMERATE)) {
    2469           0 :             return false;
    2470             :           }
    2471             :         }
    2472             :       }
    2473           0 :       temp.setObject(*returnArray);
    2474           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->idle_id, temp, JSPROP_ENUMERATE)) {
    2475           0 :         return false;
    2476             :       }
    2477           0 :       break;
    2478             :     } while(0);
    2479             :   }
    2480             : 
    2481             :   do {
    2482             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2483           0 :     JS::Rooted<JS::Value> temp(cx);
    2484           0 :     uint32_t const & currentValue = mPort;
    2485           0 :     temp.setNumber(currentValue);
    2486           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->port_id, temp, JSPROP_ENUMERATE)) {
    2487           0 :       return false;
    2488             :     }
    2489           0 :     break;
    2490             :   } while(0);
    2491             : 
    2492             :   do {
    2493             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2494           0 :     JS::Rooted<JS::Value> temp(cx);
    2495           0 :     bool const & currentValue = mSpdy;
    2496           0 :     temp.setBoolean(currentValue);
    2497           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->spdy_id, temp, JSPROP_ENUMERATE)) {
    2498           0 :       return false;
    2499             :     }
    2500           0 :     break;
    2501             :   } while(0);
    2502             : 
    2503             :   do {
    2504             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2505           0 :     JS::Rooted<JS::Value> temp(cx);
    2506           0 :     bool const & currentValue = mSsl;
    2507           0 :     temp.setBoolean(currentValue);
    2508           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->ssl_id, temp, JSPROP_ENUMERATE)) {
    2509           0 :       return false;
    2510             :     }
    2511           0 :     break;
    2512             :   } while(0);
    2513             : 
    2514           0 :   return true;
    2515             : }
    2516             : 
    2517             : bool
    2518           0 : HttpConnectionElement::ToJSON(nsAString& aJSON) const
    2519             : {
    2520           0 :   AutoJSAPI jsapi;
    2521           0 :   jsapi.Init();
    2522           0 :   JSContext *cx = jsapi.cx();
    2523             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    2524             :   // because we'll only be creating objects, in ways that have no
    2525             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    2526             :   // which likewise guarantees no side-effects for the sorts of
    2527             :   // things we will pass it.
    2528           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    2529           0 :   JS::Rooted<JS::Value> val(cx);
    2530           0 :   if (!ToObjectInternal(cx, &val)) {
    2531           0 :     return false;
    2532             :   }
    2533           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    2534           0 :   return StringifyToJSON(cx, obj, aJSON);
    2535             : }
    2536             : 
    2537             : void
    2538           0 : HttpConnectionElement::TraceDictionary(JSTracer* trc)
    2539             : {
    2540           0 : }
    2541             : 
    2542             : HttpConnectionElement&
    2543           0 : HttpConnectionElement::operator=(const HttpConnectionElement& aOther)
    2544             : {
    2545           0 :   mActive.Reset();
    2546           0 :   if (aOther.mActive.WasPassed()) {
    2547           0 :     mActive.Construct(aOther.mActive.Value());
    2548             :   }
    2549           0 :   mHalfOpens.Reset();
    2550           0 :   if (aOther.mHalfOpens.WasPassed()) {
    2551           0 :     mHalfOpens.Construct(aOther.mHalfOpens.Value());
    2552             :   }
    2553           0 :   mHost = aOther.mHost;
    2554           0 :   mIdle.Reset();
    2555           0 :   if (aOther.mIdle.WasPassed()) {
    2556           0 :     mIdle.Construct(aOther.mIdle.Value());
    2557             :   }
    2558           0 :   mPort = aOther.mPort;
    2559           0 :   mSpdy = aOther.mSpdy;
    2560           0 :   mSsl = aOther.mSsl;
    2561           0 :   return *this;
    2562             : }
    2563             : 
    2564             : namespace binding_detail {
    2565             : } // namespace binding_detail
    2566             : 
    2567             : 
    2568             : 
    2569           0 : RcwnStatus::RcwnStatus()
    2570             : {
    2571             :   // Safe to pass a null context if we pass a null value
    2572           0 :   Init(nullptr, JS::NullHandleValue);
    2573           0 : }
    2574             : 
    2575             : 
    2576             : 
    2577             : bool
    2578           0 : RcwnStatus::InitIds(JSContext* cx, RcwnStatusAtoms* atomsCache)
    2579             : {
    2580           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    2581             : 
    2582             :   // Initialize these in reverse order so that any failure leaves the first one
    2583             :   // uninitialized.
    2584           0 :   if (!atomsCache->totalNetworkRequests_id.init(cx, "totalNetworkRequests") ||
    2585           0 :       !atomsCache->rcwnNetWonCount_id.init(cx, "rcwnNetWonCount") ||
    2586           0 :       !atomsCache->rcwnCacheWonCount_id.init(cx, "rcwnCacheWonCount") ||
    2587           0 :       !atomsCache->perfStats_id.init(cx, "perfStats") ||
    2588           0 :       !atomsCache->cacheSlowCount_id.init(cx, "cacheSlowCount") ||
    2589           0 :       !atomsCache->cacheNotSlowCount_id.init(cx, "cacheNotSlowCount")) {
    2590           0 :     return false;
    2591             :   }
    2592           0 :   return true;
    2593             : }
    2594             : 
    2595             : bool
    2596           0 : RcwnStatus::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    2597             : {
    2598             :   // Passing a null JSContext is OK only if we're initing from null,
    2599             :   // Since in that case we will not have to do any property gets
    2600             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    2601             :   // checkers by static analysis tools
    2602           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    2603           0 :   RcwnStatusAtoms* atomsCache = nullptr;
    2604           0 :   if (cx) {
    2605           0 :     atomsCache = GetAtomCache<RcwnStatusAtoms>(cx);
    2606           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2607           0 :       return false;
    2608             :     }
    2609             :   }
    2610             : 
    2611           0 :   if (!IsConvertibleToDictionary(val)) {
    2612           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    2613             :   }
    2614             : 
    2615           0 :   bool isNull = val.isNullOrUndefined();
    2616             :   // We only need these if !isNull, in which case we have |cx|.
    2617           0 :   Maybe<JS::Rooted<JSObject *> > object;
    2618           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    2619           0 :   if (!isNull) {
    2620           0 :     MOZ_ASSERT(cx);
    2621           0 :     object.emplace(cx, &val.toObject());
    2622           0 :     temp.emplace(cx);
    2623             :   }
    2624           0 :   if (!isNull) {
    2625           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->cacheNotSlowCount_id, temp.ptr())) {
    2626           0 :       return false;
    2627             :     }
    2628             :   }
    2629           0 :   if (!isNull && !temp->isUndefined()) {
    2630           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mCacheNotSlowCount)) {
    2631           0 :       return false;
    2632             :     }
    2633             :   } else {
    2634           0 :     mCacheNotSlowCount = 0U;
    2635             :   }
    2636           0 :   mIsAnyMemberPresent = true;
    2637             : 
    2638           0 :   if (!isNull) {
    2639           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->cacheSlowCount_id, temp.ptr())) {
    2640           0 :       return false;
    2641             :     }
    2642             :   }
    2643           0 :   if (!isNull && !temp->isUndefined()) {
    2644           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mCacheSlowCount)) {
    2645           0 :       return false;
    2646             :     }
    2647             :   } else {
    2648           0 :     mCacheSlowCount = 0U;
    2649             :   }
    2650           0 :   mIsAnyMemberPresent = true;
    2651             : 
    2652           0 :   if (!isNull) {
    2653           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->perfStats_id, temp.ptr())) {
    2654           0 :       return false;
    2655             :     }
    2656             :   }
    2657           0 :   if (!isNull && !temp->isUndefined()) {
    2658           0 :     mPerfStats.Construct();
    2659           0 :     if (temp.ref().isObject()) {
    2660           0 :       JS::ForOfIterator iter(cx);
    2661           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    2662           0 :         return false;
    2663             :       }
    2664           0 :       if (!iter.valueIsIterable()) {
    2665           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'perfStats' member of RcwnStatus");
    2666           0 :         return false;
    2667             :       }
    2668           0 :       Sequence<RcwnPerfStats> &arr = (mPerfStats.Value());
    2669           0 :       JS::Rooted<JS::Value> temp(cx);
    2670             :       while (true) {
    2671             :         bool done;
    2672           0 :         if (!iter.next(&temp, &done)) {
    2673           0 :           return false;
    2674             :         }
    2675           0 :         if (done) {
    2676           0 :           break;
    2677             :         }
    2678           0 :         RcwnPerfStats* slotPtr = arr.AppendElement(mozilla::fallible);
    2679           0 :         if (!slotPtr) {
    2680           0 :           JS_ReportOutOfMemory(cx);
    2681           0 :           return false;
    2682             :         }
    2683           0 :         RcwnPerfStats& slot = *slotPtr;
    2684           0 :         if (!slot.Init(cx, temp,  "Element of 'perfStats' member of RcwnStatus", passedToJSImpl)) {
    2685           0 :           return false;
    2686             :         }
    2687           0 :       }
    2688             :     } else {
    2689           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'perfStats' member of RcwnStatus");
    2690           0 :       return false;
    2691             :     }
    2692           0 :     mIsAnyMemberPresent = true;
    2693             :   }
    2694             : 
    2695           0 :   if (!isNull) {
    2696           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->rcwnCacheWonCount_id, temp.ptr())) {
    2697           0 :       return false;
    2698             :     }
    2699             :   }
    2700           0 :   if (!isNull && !temp->isUndefined()) {
    2701           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mRcwnCacheWonCount)) {
    2702           0 :       return false;
    2703             :     }
    2704             :   } else {
    2705           0 :     mRcwnCacheWonCount = 0U;
    2706             :   }
    2707           0 :   mIsAnyMemberPresent = true;
    2708             : 
    2709           0 :   if (!isNull) {
    2710           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->rcwnNetWonCount_id, temp.ptr())) {
    2711           0 :       return false;
    2712             :     }
    2713             :   }
    2714           0 :   if (!isNull && !temp->isUndefined()) {
    2715           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mRcwnNetWonCount)) {
    2716           0 :       return false;
    2717             :     }
    2718             :   } else {
    2719           0 :     mRcwnNetWonCount = 0U;
    2720             :   }
    2721           0 :   mIsAnyMemberPresent = true;
    2722             : 
    2723           0 :   if (!isNull) {
    2724           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->totalNetworkRequests_id, temp.ptr())) {
    2725           0 :       return false;
    2726             :     }
    2727             :   }
    2728           0 :   if (!isNull && !temp->isUndefined()) {
    2729           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mTotalNetworkRequests)) {
    2730           0 :       return false;
    2731             :     }
    2732             :   } else {
    2733           0 :     mTotalNetworkRequests = 0U;
    2734             :   }
    2735           0 :   mIsAnyMemberPresent = true;
    2736           0 :   return true;
    2737             : }
    2738             : 
    2739             : bool
    2740           0 : RcwnStatus::Init(const nsAString& aJSON)
    2741             : {
    2742           0 :   AutoJSAPI jsapi;
    2743           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    2744           0 :   if (!cleanGlobal) {
    2745           0 :     return false;
    2746             :   }
    2747           0 :   if (!jsapi.Init(cleanGlobal)) {
    2748           0 :     return false;
    2749             :   }
    2750           0 :   JSContext* cx = jsapi.cx();
    2751           0 :   JS::Rooted<JS::Value> json(cx);
    2752           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    2753           0 :   NS_ENSURE_TRUE(ok, false);
    2754           0 :   return Init(cx, json);
    2755             : }
    2756             : 
    2757             : bool
    2758           0 : RcwnStatus::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    2759             : {
    2760           0 :   RcwnStatusAtoms* atomsCache = GetAtomCache<RcwnStatusAtoms>(cx);
    2761           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2762           0 :     return false;
    2763             :   }
    2764             : 
    2765           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    2766           0 :   if (!obj) {
    2767           0 :     return false;
    2768             :   }
    2769           0 :   rval.set(JS::ObjectValue(*obj));
    2770             : 
    2771             :   do {
    2772             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2773           0 :     JS::Rooted<JS::Value> temp(cx);
    2774           0 :     uint32_t const & currentValue = mCacheNotSlowCount;
    2775           0 :     temp.setNumber(currentValue);
    2776           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->cacheNotSlowCount_id, temp, JSPROP_ENUMERATE)) {
    2777           0 :       return false;
    2778             :     }
    2779           0 :     break;
    2780             :   } while(0);
    2781             : 
    2782             :   do {
    2783             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2784           0 :     JS::Rooted<JS::Value> temp(cx);
    2785           0 :     uint32_t const & currentValue = mCacheSlowCount;
    2786           0 :     temp.setNumber(currentValue);
    2787           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->cacheSlowCount_id, temp, JSPROP_ENUMERATE)) {
    2788           0 :       return false;
    2789             :     }
    2790           0 :     break;
    2791             :   } while(0);
    2792             : 
    2793           0 :   if (mPerfStats.WasPassed()) {
    2794             :     do {
    2795             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2796           0 :       JS::Rooted<JS::Value> temp(cx);
    2797           0 :       Sequence<RcwnPerfStats> const & currentValue = mPerfStats.InternalValue();
    2798             : 
    2799           0 :       uint32_t length = currentValue.Length();
    2800           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    2801           0 :       if (!returnArray) {
    2802           0 :         return false;
    2803             :       }
    2804             :       // Scope for 'tmp'
    2805             :       {
    2806           0 :         JS::Rooted<JS::Value> tmp(cx);
    2807           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    2808             :           // Control block to let us common up the JS_DefineElement calls when there
    2809             :           // are different ways to succeed at wrapping the object.
    2810             :           do {
    2811           0 :             if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
    2812           0 :               return false;
    2813             :             }
    2814           0 :             break;
    2815             :           } while (0);
    2816           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    2817             :                                 JSPROP_ENUMERATE)) {
    2818           0 :             return false;
    2819             :           }
    2820             :         }
    2821             :       }
    2822           0 :       temp.setObject(*returnArray);
    2823           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->perfStats_id, temp, JSPROP_ENUMERATE)) {
    2824           0 :         return false;
    2825             :       }
    2826           0 :       break;
    2827             :     } while(0);
    2828             :   }
    2829             : 
    2830             :   do {
    2831             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2832           0 :     JS::Rooted<JS::Value> temp(cx);
    2833           0 :     uint32_t const & currentValue = mRcwnCacheWonCount;
    2834           0 :     temp.setNumber(currentValue);
    2835           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->rcwnCacheWonCount_id, temp, JSPROP_ENUMERATE)) {
    2836           0 :       return false;
    2837             :     }
    2838           0 :     break;
    2839             :   } while(0);
    2840             : 
    2841             :   do {
    2842             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2843           0 :     JS::Rooted<JS::Value> temp(cx);
    2844           0 :     uint32_t const & currentValue = mRcwnNetWonCount;
    2845           0 :     temp.setNumber(currentValue);
    2846           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->rcwnNetWonCount_id, temp, JSPROP_ENUMERATE)) {
    2847           0 :       return false;
    2848             :     }
    2849           0 :     break;
    2850             :   } while(0);
    2851             : 
    2852             :   do {
    2853             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2854           0 :     JS::Rooted<JS::Value> temp(cx);
    2855           0 :     uint32_t const & currentValue = mTotalNetworkRequests;
    2856           0 :     temp.setNumber(currentValue);
    2857           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->totalNetworkRequests_id, temp, JSPROP_ENUMERATE)) {
    2858           0 :       return false;
    2859             :     }
    2860           0 :     break;
    2861             :   } while(0);
    2862             : 
    2863           0 :   return true;
    2864             : }
    2865             : 
    2866             : bool
    2867           0 : RcwnStatus::ToJSON(nsAString& aJSON) const
    2868             : {
    2869           0 :   AutoJSAPI jsapi;
    2870           0 :   jsapi.Init();
    2871           0 :   JSContext *cx = jsapi.cx();
    2872             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    2873             :   // because we'll only be creating objects, in ways that have no
    2874             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    2875             :   // which likewise guarantees no side-effects for the sorts of
    2876             :   // things we will pass it.
    2877           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    2878           0 :   JS::Rooted<JS::Value> val(cx);
    2879           0 :   if (!ToObjectInternal(cx, &val)) {
    2880           0 :     return false;
    2881             :   }
    2882           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    2883           0 :   return StringifyToJSON(cx, obj, aJSON);
    2884             : }
    2885             : 
    2886             : void
    2887           0 : RcwnStatus::TraceDictionary(JSTracer* trc)
    2888             : {
    2889           0 : }
    2890             : 
    2891             : RcwnStatus&
    2892           0 : RcwnStatus::operator=(const RcwnStatus& aOther)
    2893             : {
    2894           0 :   mCacheNotSlowCount = aOther.mCacheNotSlowCount;
    2895           0 :   mCacheSlowCount = aOther.mCacheSlowCount;
    2896           0 :   mPerfStats.Reset();
    2897           0 :   if (aOther.mPerfStats.WasPassed()) {
    2898           0 :     mPerfStats.Construct(aOther.mPerfStats.Value());
    2899             :   }
    2900           0 :   mRcwnCacheWonCount = aOther.mRcwnCacheWonCount;
    2901           0 :   mRcwnNetWonCount = aOther.mRcwnNetWonCount;
    2902           0 :   mTotalNetworkRequests = aOther.mTotalNetworkRequests;
    2903           0 :   return *this;
    2904             : }
    2905             : 
    2906             : namespace binding_detail {
    2907             : } // namespace binding_detail
    2908             : 
    2909             : 
    2910             : 
    2911           0 : SocketsDict::SocketsDict()
    2912             : {
    2913             :   // Safe to pass a null context if we pass a null value
    2914           0 :   Init(nullptr, JS::NullHandleValue);
    2915           0 : }
    2916             : 
    2917             : 
    2918             : 
    2919             : bool
    2920           0 : SocketsDict::InitIds(JSContext* cx, SocketsDictAtoms* atomsCache)
    2921             : {
    2922           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    2923             : 
    2924             :   // Initialize these in reverse order so that any failure leaves the first one
    2925             :   // uninitialized.
    2926           0 :   if (!atomsCache->sockets_id.init(cx, "sockets") ||
    2927           0 :       !atomsCache->sent_id.init(cx, "sent") ||
    2928           0 :       !atomsCache->received_id.init(cx, "received")) {
    2929           0 :     return false;
    2930             :   }
    2931           0 :   return true;
    2932             : }
    2933             : 
    2934             : bool
    2935           0 : SocketsDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    2936             : {
    2937             :   // Passing a null JSContext is OK only if we're initing from null,
    2938             :   // Since in that case we will not have to do any property gets
    2939             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    2940             :   // checkers by static analysis tools
    2941           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    2942           0 :   SocketsDictAtoms* atomsCache = nullptr;
    2943           0 :   if (cx) {
    2944           0 :     atomsCache = GetAtomCache<SocketsDictAtoms>(cx);
    2945           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2946           0 :       return false;
    2947             :     }
    2948             :   }
    2949             : 
    2950           0 :   if (!IsConvertibleToDictionary(val)) {
    2951           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    2952             :   }
    2953             : 
    2954           0 :   bool isNull = val.isNullOrUndefined();
    2955             :   // We only need these if !isNull, in which case we have |cx|.
    2956           0 :   Maybe<JS::Rooted<JSObject *> > object;
    2957           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    2958           0 :   if (!isNull) {
    2959           0 :     MOZ_ASSERT(cx);
    2960           0 :     object.emplace(cx, &val.toObject());
    2961           0 :     temp.emplace(cx);
    2962             :   }
    2963           0 :   if (!isNull) {
    2964           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->received_id, temp.ptr())) {
    2965           0 :       return false;
    2966             :     }
    2967             :   }
    2968           0 :   if (!isNull && !temp->isUndefined()) {
    2969           0 :     if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mReceived)) {
    2970           0 :       return false;
    2971           0 :     } else if (!mozilla::IsFinite(mReceived)) {
    2972           0 :       ThrowErrorMessage(cx, MSG_NOT_FINITE, "'received' member of SocketsDict");
    2973           0 :       return false;
    2974             :     }
    2975             :   } else {
    2976           0 :     mReceived = 0.0;
    2977             :   }
    2978           0 :   mIsAnyMemberPresent = true;
    2979             : 
    2980           0 :   if (!isNull) {
    2981           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->sent_id, temp.ptr())) {
    2982           0 :       return false;
    2983             :     }
    2984             :   }
    2985           0 :   if (!isNull && !temp->isUndefined()) {
    2986           0 :     if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mSent)) {
    2987           0 :       return false;
    2988           0 :     } else if (!mozilla::IsFinite(mSent)) {
    2989           0 :       ThrowErrorMessage(cx, MSG_NOT_FINITE, "'sent' member of SocketsDict");
    2990           0 :       return false;
    2991             :     }
    2992             :   } else {
    2993           0 :     mSent = 0.0;
    2994             :   }
    2995           0 :   mIsAnyMemberPresent = true;
    2996             : 
    2997           0 :   if (!isNull) {
    2998           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->sockets_id, temp.ptr())) {
    2999           0 :       return false;
    3000             :     }
    3001             :   }
    3002           0 :   if (!isNull && !temp->isUndefined()) {
    3003           0 :     mSockets.Construct();
    3004           0 :     if (temp.ref().isObject()) {
    3005           0 :       JS::ForOfIterator iter(cx);
    3006           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    3007           0 :         return false;
    3008             :       }
    3009           0 :       if (!iter.valueIsIterable()) {
    3010           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'sockets' member of SocketsDict");
    3011           0 :         return false;
    3012             :       }
    3013           0 :       Sequence<SocketElement> &arr = (mSockets.Value());
    3014           0 :       JS::Rooted<JS::Value> temp(cx);
    3015             :       while (true) {
    3016             :         bool done;
    3017           0 :         if (!iter.next(&temp, &done)) {
    3018           0 :           return false;
    3019             :         }
    3020           0 :         if (done) {
    3021           0 :           break;
    3022             :         }
    3023           0 :         SocketElement* slotPtr = arr.AppendElement(mozilla::fallible);
    3024           0 :         if (!slotPtr) {
    3025           0 :           JS_ReportOutOfMemory(cx);
    3026           0 :           return false;
    3027             :         }
    3028           0 :         SocketElement& slot = *slotPtr;
    3029           0 :         if (!slot.Init(cx, temp,  "Element of 'sockets' member of SocketsDict", passedToJSImpl)) {
    3030           0 :           return false;
    3031             :         }
    3032           0 :       }
    3033             :     } else {
    3034           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'sockets' member of SocketsDict");
    3035           0 :       return false;
    3036             :     }
    3037           0 :     mIsAnyMemberPresent = true;
    3038             :   }
    3039           0 :   return true;
    3040             : }
    3041             : 
    3042             : bool
    3043           0 : SocketsDict::Init(const nsAString& aJSON)
    3044             : {
    3045           0 :   AutoJSAPI jsapi;
    3046           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    3047           0 :   if (!cleanGlobal) {
    3048           0 :     return false;
    3049             :   }
    3050           0 :   if (!jsapi.Init(cleanGlobal)) {
    3051           0 :     return false;
    3052             :   }
    3053           0 :   JSContext* cx = jsapi.cx();
    3054           0 :   JS::Rooted<JS::Value> json(cx);
    3055           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    3056           0 :   NS_ENSURE_TRUE(ok, false);
    3057           0 :   return Init(cx, json);
    3058             : }
    3059             : 
    3060             : bool
    3061           0 : SocketsDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    3062             : {
    3063           0 :   SocketsDictAtoms* atomsCache = GetAtomCache<SocketsDictAtoms>(cx);
    3064           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    3065           0 :     return false;
    3066             :   }
    3067             : 
    3068           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    3069           0 :   if (!obj) {
    3070           0 :     return false;
    3071             :   }
    3072           0 :   rval.set(JS::ObjectValue(*obj));
    3073             : 
    3074             :   do {
    3075             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3076           0 :     JS::Rooted<JS::Value> temp(cx);
    3077           0 :     double const & currentValue = mReceived;
    3078           0 :     temp.set(JS_NumberValue(double(currentValue)));
    3079           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->received_id, temp, JSPROP_ENUMERATE)) {
    3080           0 :       return false;
    3081             :     }
    3082           0 :     break;
    3083             :   } while(0);
    3084             : 
    3085             :   do {
    3086             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3087           0 :     JS::Rooted<JS::Value> temp(cx);
    3088           0 :     double const & currentValue = mSent;
    3089           0 :     temp.set(JS_NumberValue(double(currentValue)));
    3090           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->sent_id, temp, JSPROP_ENUMERATE)) {
    3091           0 :       return false;
    3092             :     }
    3093           0 :     break;
    3094             :   } while(0);
    3095             : 
    3096           0 :   if (mSockets.WasPassed()) {
    3097             :     do {
    3098             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3099           0 :       JS::Rooted<JS::Value> temp(cx);
    3100           0 :       Sequence<SocketElement> const & currentValue = mSockets.InternalValue();
    3101             : 
    3102           0 :       uint32_t length = currentValue.Length();
    3103           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    3104           0 :       if (!returnArray) {
    3105           0 :         return false;
    3106             :       }
    3107             :       // Scope for 'tmp'
    3108             :       {
    3109           0 :         JS::Rooted<JS::Value> tmp(cx);
    3110           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    3111             :           // Control block to let us common up the JS_DefineElement calls when there
    3112             :           // are different ways to succeed at wrapping the object.
    3113             :           do {
    3114           0 :             if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
    3115           0 :               return false;
    3116             :             }
    3117           0 :             break;
    3118             :           } while (0);
    3119           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    3120             :                                 JSPROP_ENUMERATE)) {
    3121           0 :             return false;
    3122             :           }
    3123             :         }
    3124             :       }
    3125           0 :       temp.setObject(*returnArray);
    3126           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->sockets_id, temp, JSPROP_ENUMERATE)) {
    3127           0 :         return false;
    3128             :       }
    3129           0 :       break;
    3130             :     } while(0);
    3131             :   }
    3132             : 
    3133           0 :   return true;
    3134             : }
    3135             : 
    3136             : bool
    3137           0 : SocketsDict::ToJSON(nsAString& aJSON) const
    3138             : {
    3139           0 :   AutoJSAPI jsapi;
    3140           0 :   jsapi.Init();
    3141           0 :   JSContext *cx = jsapi.cx();
    3142             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    3143             :   // because we'll only be creating objects, in ways that have no
    3144             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    3145             :   // which likewise guarantees no side-effects for the sorts of
    3146             :   // things we will pass it.
    3147           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    3148           0 :   JS::Rooted<JS::Value> val(cx);
    3149           0 :   if (!ToObjectInternal(cx, &val)) {
    3150           0 :     return false;
    3151             :   }
    3152           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    3153           0 :   return StringifyToJSON(cx, obj, aJSON);
    3154             : }
    3155             : 
    3156             : void
    3157           0 : SocketsDict::TraceDictionary(JSTracer* trc)
    3158             : {
    3159           0 : }
    3160             : 
    3161             : SocketsDict&
    3162           0 : SocketsDict::operator=(const SocketsDict& aOther)
    3163             : {
    3164           0 :   mReceived = aOther.mReceived;
    3165           0 :   mSent = aOther.mSent;
    3166           0 :   mSockets.Reset();
    3167           0 :   if (aOther.mSockets.WasPassed()) {
    3168           0 :     mSockets.Construct(aOther.mSockets.Value());
    3169             :   }
    3170           0 :   return *this;
    3171             : }
    3172             : 
    3173             : namespace binding_detail {
    3174             : } // namespace binding_detail
    3175             : 
    3176             : 
    3177             : 
    3178           0 : WebSocketDict::WebSocketDict()
    3179             : {
    3180             :   // Safe to pass a null context if we pass a null value
    3181           0 :   Init(nullptr, JS::NullHandleValue);
    3182           0 : }
    3183             : 
    3184             : 
    3185             : 
    3186             : bool
    3187           0 : WebSocketDict::InitIds(JSContext* cx, WebSocketDictAtoms* atomsCache)
    3188             : {
    3189           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    3190             : 
    3191             :   // Initialize these in reverse order so that any failure leaves the first one
    3192             :   // uninitialized.
    3193           0 :   if (!atomsCache->websockets_id.init(cx, "websockets")) {
    3194           0 :     return false;
    3195             :   }
    3196           0 :   return true;
    3197             : }
    3198             : 
    3199             : bool
    3200           0 : WebSocketDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    3201             : {
    3202             :   // Passing a null JSContext is OK only if we're initing from null,
    3203             :   // Since in that case we will not have to do any property gets
    3204             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    3205             :   // checkers by static analysis tools
    3206           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    3207           0 :   WebSocketDictAtoms* atomsCache = nullptr;
    3208           0 :   if (cx) {
    3209           0 :     atomsCache = GetAtomCache<WebSocketDictAtoms>(cx);
    3210           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    3211           0 :       return false;
    3212             :     }
    3213             :   }
    3214             : 
    3215           0 :   if (!IsConvertibleToDictionary(val)) {
    3216           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    3217             :   }
    3218             : 
    3219           0 :   bool isNull = val.isNullOrUndefined();
    3220             :   // We only need these if !isNull, in which case we have |cx|.
    3221           0 :   Maybe<JS::Rooted<JSObject *> > object;
    3222           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    3223           0 :   if (!isNull) {
    3224           0 :     MOZ_ASSERT(cx);
    3225           0 :     object.emplace(cx, &val.toObject());
    3226           0 :     temp.emplace(cx);
    3227             :   }
    3228           0 :   if (!isNull) {
    3229           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->websockets_id, temp.ptr())) {
    3230           0 :       return false;
    3231             :     }
    3232             :   }
    3233           0 :   if (!isNull && !temp->isUndefined()) {
    3234           0 :     mWebsockets.Construct();
    3235           0 :     if (temp.ref().isObject()) {
    3236           0 :       JS::ForOfIterator iter(cx);
    3237           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    3238           0 :         return false;
    3239             :       }
    3240           0 :       if (!iter.valueIsIterable()) {
    3241           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'websockets' member of WebSocketDict");
    3242           0 :         return false;
    3243             :       }
    3244           0 :       Sequence<WebSocketElement> &arr = (mWebsockets.Value());
    3245           0 :       JS::Rooted<JS::Value> temp(cx);
    3246             :       while (true) {
    3247             :         bool done;
    3248           0 :         if (!iter.next(&temp, &done)) {
    3249           0 :           return false;
    3250             :         }
    3251           0 :         if (done) {
    3252           0 :           break;
    3253             :         }
    3254           0 :         WebSocketElement* slotPtr = arr.AppendElement(mozilla::fallible);
    3255           0 :         if (!slotPtr) {
    3256           0 :           JS_ReportOutOfMemory(cx);
    3257           0 :           return false;
    3258             :         }
    3259           0 :         WebSocketElement& slot = *slotPtr;
    3260           0 :         if (!slot.Init(cx, temp,  "Element of 'websockets' member of WebSocketDict", passedToJSImpl)) {
    3261           0 :           return false;
    3262             :         }
    3263           0 :       }
    3264             :     } else {
    3265           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'websockets' member of WebSocketDict");
    3266           0 :       return false;
    3267             :     }
    3268           0 :     mIsAnyMemberPresent = true;
    3269             :   }
    3270           0 :   return true;
    3271             : }
    3272             : 
    3273             : bool
    3274           0 : WebSocketDict::Init(const nsAString& aJSON)
    3275             : {
    3276           0 :   AutoJSAPI jsapi;
    3277           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    3278           0 :   if (!cleanGlobal) {
    3279           0 :     return false;
    3280             :   }
    3281           0 :   if (!jsapi.Init(cleanGlobal)) {
    3282           0 :     return false;
    3283             :   }
    3284           0 :   JSContext* cx = jsapi.cx();
    3285           0 :   JS::Rooted<JS::Value> json(cx);
    3286           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    3287           0 :   NS_ENSURE_TRUE(ok, false);
    3288           0 :   return Init(cx, json);
    3289             : }
    3290             : 
    3291             : bool
    3292           0 : WebSocketDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    3293             : {
    3294           0 :   WebSocketDictAtoms* atomsCache = GetAtomCache<WebSocketDictAtoms>(cx);
    3295           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    3296           0 :     return false;
    3297             :   }
    3298             : 
    3299           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    3300           0 :   if (!obj) {
    3301           0 :     return false;
    3302             :   }
    3303           0 :   rval.set(JS::ObjectValue(*obj));
    3304             : 
    3305           0 :   if (mWebsockets.WasPassed()) {
    3306             :     do {
    3307             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3308           0 :       JS::Rooted<JS::Value> temp(cx);
    3309           0 :       Sequence<WebSocketElement> const & currentValue = mWebsockets.InternalValue();
    3310             : 
    3311           0 :       uint32_t length = currentValue.Length();
    3312           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    3313           0 :       if (!returnArray) {
    3314           0 :         return false;
    3315             :       }
    3316             :       // Scope for 'tmp'
    3317             :       {
    3318           0 :         JS::Rooted<JS::Value> tmp(cx);
    3319           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    3320             :           // Control block to let us common up the JS_DefineElement calls when there
    3321             :           // are different ways to succeed at wrapping the object.
    3322             :           do {
    3323           0 :             if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
    3324           0 :               return false;
    3325             :             }
    3326           0 :             break;
    3327             :           } while (0);
    3328           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    3329             :                                 JSPROP_ENUMERATE)) {
    3330           0 :             return false;
    3331             :           }
    3332             :         }
    3333             :       }
    3334           0 :       temp.setObject(*returnArray);
    3335           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->websockets_id, temp, JSPROP_ENUMERATE)) {
    3336           0 :         return false;
    3337             :       }
    3338           0 :       break;
    3339             :     } while(0);
    3340             :   }
    3341             : 
    3342           0 :   return true;
    3343             : }
    3344             : 
    3345             : bool
    3346           0 : WebSocketDict::ToJSON(nsAString& aJSON) const
    3347             : {
    3348           0 :   AutoJSAPI jsapi;
    3349           0 :   jsapi.Init();
    3350           0 :   JSContext *cx = jsapi.cx();
    3351             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    3352             :   // because we'll only be creating objects, in ways that have no
    3353             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    3354             :   // which likewise guarantees no side-effects for the sorts of
    3355             :   // things we will pass it.
    3356           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    3357           0 :   JS::Rooted<JS::Value> val(cx);
    3358           0 :   if (!ToObjectInternal(cx, &val)) {
    3359           0 :     return false;
    3360             :   }
    3361           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    3362           0 :   return StringifyToJSON(cx, obj, aJSON);
    3363             : }
    3364             : 
    3365             : void
    3366           0 : WebSocketDict::TraceDictionary(JSTracer* trc)
    3367             : {
    3368           0 : }
    3369             : 
    3370             : WebSocketDict&
    3371           0 : WebSocketDict::operator=(const WebSocketDict& aOther)
    3372             : {
    3373           0 :   mWebsockets.Reset();
    3374           0 :   if (aOther.mWebsockets.WasPassed()) {
    3375           0 :     mWebsockets.Construct(aOther.mWebsockets.Value());
    3376             :   }
    3377           0 :   return *this;
    3378             : }
    3379             : 
    3380             : namespace binding_detail {
    3381             : } // namespace binding_detail
    3382             : 
    3383             : 
    3384             : 
    3385           0 : HttpConnDict::HttpConnDict()
    3386             : {
    3387             :   // Safe to pass a null context if we pass a null value
    3388           0 :   Init(nullptr, JS::NullHandleValue);
    3389           0 : }
    3390             : 
    3391             : 
    3392             : 
    3393             : bool
    3394           0 : HttpConnDict::InitIds(JSContext* cx, HttpConnDictAtoms* atomsCache)
    3395             : {
    3396           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    3397             : 
    3398             :   // Initialize these in reverse order so that any failure leaves the first one
    3399             :   // uninitialized.
    3400           0 :   if (!atomsCache->connections_id.init(cx, "connections")) {
    3401           0 :     return false;
    3402             :   }
    3403           0 :   return true;
    3404             : }
    3405             : 
    3406             : bool
    3407           0 : HttpConnDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    3408             : {
    3409             :   // Passing a null JSContext is OK only if we're initing from null,
    3410             :   // Since in that case we will not have to do any property gets
    3411             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    3412             :   // checkers by static analysis tools
    3413           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    3414           0 :   HttpConnDictAtoms* atomsCache = nullptr;
    3415           0 :   if (cx) {
    3416           0 :     atomsCache = GetAtomCache<HttpConnDictAtoms>(cx);
    3417           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    3418           0 :       return false;
    3419             :     }
    3420             :   }
    3421             : 
    3422           0 :   if (!IsConvertibleToDictionary(val)) {
    3423           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    3424             :   }
    3425             : 
    3426           0 :   bool isNull = val.isNullOrUndefined();
    3427             :   // We only need these if !isNull, in which case we have |cx|.
    3428           0 :   Maybe<JS::Rooted<JSObject *> > object;
    3429           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    3430           0 :   if (!isNull) {
    3431           0 :     MOZ_ASSERT(cx);
    3432           0 :     object.emplace(cx, &val.toObject());
    3433           0 :     temp.emplace(cx);
    3434             :   }
    3435           0 :   if (!isNull) {
    3436           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->connections_id, temp.ptr())) {
    3437           0 :       return false;
    3438             :     }
    3439             :   }
    3440           0 :   if (!isNull && !temp->isUndefined()) {
    3441           0 :     mConnections.Construct();
    3442           0 :     if (temp.ref().isObject()) {
    3443           0 :       JS::ForOfIterator iter(cx);
    3444           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    3445           0 :         return false;
    3446             :       }
    3447           0 :       if (!iter.valueIsIterable()) {
    3448           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'connections' member of HttpConnDict");
    3449           0 :         return false;
    3450             :       }
    3451           0 :       Sequence<HttpConnectionElement> &arr = (mConnections.Value());
    3452           0 :       JS::Rooted<JS::Value> temp(cx);
    3453             :       while (true) {
    3454             :         bool done;
    3455           0 :         if (!iter.next(&temp, &done)) {
    3456           0 :           return false;
    3457             :         }
    3458           0 :         if (done) {
    3459           0 :           break;
    3460             :         }
    3461           0 :         HttpConnectionElement* slotPtr = arr.AppendElement(mozilla::fallible);
    3462           0 :         if (!slotPtr) {
    3463           0 :           JS_ReportOutOfMemory(cx);
    3464           0 :           return false;
    3465             :         }
    3466           0 :         HttpConnectionElement& slot = *slotPtr;
    3467           0 :         if (!slot.Init(cx, temp,  "Element of 'connections' member of HttpConnDict", passedToJSImpl)) {
    3468           0 :           return false;
    3469             :         }
    3470           0 :       }
    3471             :     } else {
    3472           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'connections' member of HttpConnDict");
    3473           0 :       return false;
    3474             :     }
    3475           0 :     mIsAnyMemberPresent = true;
    3476             :   }
    3477           0 :   return true;
    3478             : }
    3479             : 
    3480             : bool
    3481           0 : HttpConnDict::Init(const nsAString& aJSON)
    3482             : {
    3483           0 :   AutoJSAPI jsapi;
    3484           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    3485           0 :   if (!cleanGlobal) {
    3486           0 :     return false;
    3487             :   }
    3488           0 :   if (!jsapi.Init(cleanGlobal)) {
    3489           0 :     return false;
    3490             :   }
    3491           0 :   JSContext* cx = jsapi.cx();
    3492           0 :   JS::Rooted<JS::Value> json(cx);
    3493           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    3494           0 :   NS_ENSURE_TRUE(ok, false);
    3495           0 :   return Init(cx, json);
    3496             : }
    3497             : 
    3498             : bool
    3499           0 : HttpConnDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    3500             : {
    3501           0 :   HttpConnDictAtoms* atomsCache = GetAtomCache<HttpConnDictAtoms>(cx);
    3502           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    3503           0 :     return false;
    3504             :   }
    3505             : 
    3506           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    3507           0 :   if (!obj) {
    3508           0 :     return false;
    3509             :   }
    3510           0 :   rval.set(JS::ObjectValue(*obj));
    3511             : 
    3512           0 :   if (mConnections.WasPassed()) {
    3513             :     do {
    3514             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3515           0 :       JS::Rooted<JS::Value> temp(cx);
    3516           0 :       Sequence<HttpConnectionElement> const & currentValue = mConnections.InternalValue();
    3517             : 
    3518           0 :       uint32_t length = currentValue.Length();
    3519           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    3520           0 :       if (!returnArray) {
    3521           0 :         return false;
    3522             :       }
    3523             :       // Scope for 'tmp'
    3524             :       {
    3525           0 :         JS::Rooted<JS::Value> tmp(cx);
    3526           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    3527             :           // Control block to let us common up the JS_DefineElement calls when there
    3528             :           // are different ways to succeed at wrapping the object.
    3529             :           do {
    3530           0 :             if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
    3531           0 :               return false;
    3532             :             }
    3533           0 :             break;
    3534             :           } while (0);
    3535           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    3536             :                                 JSPROP_ENUMERATE)) {
    3537           0 :             return false;
    3538             :           }
    3539             :         }
    3540             :       }
    3541           0 :       temp.setObject(*returnArray);
    3542           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->connections_id, temp, JSPROP_ENUMERATE)) {
    3543           0 :         return false;
    3544             :       }
    3545           0 :       break;
    3546             :     } while(0);
    3547             :   }
    3548             : 
    3549           0 :   return true;
    3550             : }
    3551             : 
    3552             : bool
    3553           0 : HttpConnDict::ToJSON(nsAString& aJSON) const
    3554             : {
    3555           0 :   AutoJSAPI jsapi;
    3556           0 :   jsapi.Init();
    3557           0 :   JSContext *cx = jsapi.cx();
    3558             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    3559             :   // because we'll only be creating objects, in ways that have no
    3560             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    3561             :   // which likewise guarantees no side-effects for the sorts of
    3562             :   // things we will pass it.
    3563           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    3564           0 :   JS::Rooted<JS::Value> val(cx);
    3565           0 :   if (!ToObjectInternal(cx, &val)) {
    3566           0 :     return false;
    3567             :   }
    3568           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    3569           0 :   return StringifyToJSON(cx, obj, aJSON);
    3570             : }
    3571             : 
    3572             : void
    3573           0 : HttpConnDict::TraceDictionary(JSTracer* trc)
    3574             : {
    3575           0 : }
    3576             : 
    3577             : HttpConnDict&
    3578           0 : HttpConnDict::operator=(const HttpConnDict& aOther)
    3579             : {
    3580           0 :   mConnections.Reset();
    3581           0 :   if (aOther.mConnections.WasPassed()) {
    3582           0 :     mConnections.Construct(aOther.mConnections.Value());
    3583             :   }
    3584           0 :   return *this;
    3585             : }
    3586             : 
    3587             : namespace binding_detail {
    3588             : } // namespace binding_detail
    3589             : 
    3590             : 
    3591             : } // namespace dom
    3592             : } // namespace mozilla

Generated by: LCOV version 1.13