LCOV - code coverage report
Current view: top level - obj-x86_64-pc-linux-gnu/dom/bindings - SubtleCryptoBinding.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 22 3391 0.6 %
Date: 2017-07-14 16:53:18 Functions: 3 202 1.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* THIS FILE IS AUTOGENERATED FROM SubtleCrypto.webidl BY Codegen.py - DO NOT EDIT */
       2             : 
       3             : #include "AtomList.h"
       4             : #include "SubtleCryptoBinding.h"
       5             : #include "WrapperFactory.h"
       6             : #include "XrayWrapper.h"
       7             : #include "jsfriendapi.h"
       8             : #include "mozilla/OwningNonNull.h"
       9             : #include "mozilla/dom/BindingUtils.h"
      10             : #include "mozilla/dom/CryptoKey.h"
      11             : #include "mozilla/dom/DOMJSClass.h"
      12             : #include "mozilla/dom/NonRefcountedDOMObject.h"
      13             : #include "mozilla/dom/PrimitiveConversions.h"
      14             : #include "mozilla/dom/Promise.h"
      15             : #include "mozilla/dom/ScriptSettings.h"
      16             : #include "mozilla/dom/SimpleGlobalObject.h"
      17             : #include "mozilla/dom/SubtleCrypto.h"
      18             : #include "mozilla/dom/ToJSValue.h"
      19             : #include "mozilla/dom/UnionConversions.h"
      20             : #include "mozilla/dom/UnionTypes.h"
      21             : #include "mozilla/dom/XrayExpandoClass.h"
      22             : 
      23             : namespace mozilla {
      24             : namespace dom {
      25             : 
      26             : 
      27           0 : Algorithm::Algorithm()
      28             : {
      29             :   // Safe to pass a null context if we pass a null value
      30           0 :   Init(nullptr, JS::NullHandleValue);
      31           0 : }
      32             : 
      33             : 
      34             : 
      35             : bool
      36           0 : Algorithm::InitIds(JSContext* cx, AlgorithmAtoms* atomsCache)
      37             : {
      38           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
      39             : 
      40             :   // Initialize these in reverse order so that any failure leaves the first one
      41             :   // uninitialized.
      42           0 :   if (!atomsCache->name_id.init(cx, "name")) {
      43           0 :     return false;
      44             :   }
      45           0 :   return true;
      46             : }
      47             : 
      48             : bool
      49           0 : Algorithm::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
      50             : {
      51             :   // Passing a null JSContext is OK only if we're initing from null,
      52             :   // Since in that case we will not have to do any property gets
      53             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
      54             :   // checkers by static analysis tools
      55           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
      56           0 :   AlgorithmAtoms* atomsCache = nullptr;
      57           0 :   if (cx) {
      58           0 :     atomsCache = GetAtomCache<AlgorithmAtoms>(cx);
      59           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
      60           0 :       return false;
      61             :     }
      62             :   }
      63             : 
      64           0 :   if (!IsConvertibleToDictionary(val)) {
      65           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
      66             :   }
      67             : 
      68           0 :   bool isNull = val.isNullOrUndefined();
      69             :   // We only need these if !isNull, in which case we have |cx|.
      70           0 :   Maybe<JS::Rooted<JSObject *> > object;
      71           0 :   Maybe<JS::Rooted<JS::Value> > temp;
      72           0 :   if (!isNull) {
      73           0 :     MOZ_ASSERT(cx);
      74           0 :     object.emplace(cx, &val.toObject());
      75           0 :     temp.emplace(cx);
      76             :   }
      77           0 :   if (!isNull) {
      78           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->name_id, temp.ptr())) {
      79           0 :       return false;
      80             :     }
      81             :   }
      82           0 :   if (!isNull && !temp->isUndefined()) {
      83           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mName)) {
      84           0 :       return false;
      85             :     }
      86           0 :     mIsAnyMemberPresent = true;
      87           0 :   } else if (cx) {
      88             :     // Don't error out if we have no cx.  In that
      89             :     // situation the caller is default-constructing us and we'll
      90             :     // just assume they know what they're doing.
      91           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
      92           0 :                              "'name' member of Algorithm");
      93             :   }
      94           0 :   return true;
      95             : }
      96             : 
      97             : bool
      98           0 : Algorithm::Init(const nsAString& aJSON)
      99             : {
     100           0 :   AutoJSAPI jsapi;
     101           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     102           0 :   if (!cleanGlobal) {
     103           0 :     return false;
     104             :   }
     105           0 :   if (!jsapi.Init(cleanGlobal)) {
     106           0 :     return false;
     107             :   }
     108           0 :   JSContext* cx = jsapi.cx();
     109           0 :   JS::Rooted<JS::Value> json(cx);
     110           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     111           0 :   NS_ENSURE_TRUE(ok, false);
     112           0 :   return Init(cx, json);
     113             : }
     114             : 
     115             : bool
     116           0 : Algorithm::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     117             : {
     118           0 :   AlgorithmAtoms* atomsCache = GetAtomCache<AlgorithmAtoms>(cx);
     119           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     120           0 :     return false;
     121             :   }
     122             : 
     123           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     124           0 :   if (!obj) {
     125           0 :     return false;
     126             :   }
     127           0 :   rval.set(JS::ObjectValue(*obj));
     128             : 
     129             :   do {
     130             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     131           0 :     JS::Rooted<JS::Value> temp(cx);
     132           0 :     nsString const & currentValue = mName;
     133           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     134           0 :       return false;
     135             :     }
     136           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->name_id, temp, JSPROP_ENUMERATE)) {
     137           0 :       return false;
     138             :     }
     139           0 :     break;
     140             :   } while(0);
     141             : 
     142           0 :   return true;
     143             : }
     144             : 
     145             : bool
     146           0 : Algorithm::ToJSON(nsAString& aJSON) const
     147             : {
     148           0 :   AutoJSAPI jsapi;
     149           0 :   jsapi.Init();
     150           0 :   JSContext *cx = jsapi.cx();
     151             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     152             :   // because we'll only be creating objects, in ways that have no
     153             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     154             :   // which likewise guarantees no side-effects for the sorts of
     155             :   // things we will pass it.
     156           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     157           0 :   JS::Rooted<JS::Value> val(cx);
     158           0 :   if (!ToObjectInternal(cx, &val)) {
     159           0 :     return false;
     160             :   }
     161           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     162           0 :   return StringifyToJSON(cx, obj, aJSON);
     163             : }
     164             : 
     165             : void
     166           0 : Algorithm::TraceDictionary(JSTracer* trc)
     167             : {
     168           0 : }
     169             : 
     170             : Algorithm&
     171           0 : Algorithm::operator=(const Algorithm& aOther)
     172             : {
     173           0 :   mName = aOther.mName;
     174           0 :   return *this;
     175             : }
     176             : 
     177             : namespace binding_detail {
     178             : } // namespace binding_detail
     179             : 
     180             : 
     181             : 
     182           0 : CryptoKeyPair::CryptoKeyPair()
     183             : {
     184             :   // Safe to pass a null context if we pass a null value
     185           0 :   Init(nullptr, JS::NullHandleValue);
     186           0 : }
     187             : 
     188             : 
     189             : 
     190             : bool
     191           0 : CryptoKeyPair::InitIds(JSContext* cx, CryptoKeyPairAtoms* atomsCache)
     192             : {
     193           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     194             : 
     195             :   // Initialize these in reverse order so that any failure leaves the first one
     196             :   // uninitialized.
     197           0 :   if (!atomsCache->publicKey_id.init(cx, "publicKey") ||
     198           0 :       !atomsCache->privateKey_id.init(cx, "privateKey")) {
     199           0 :     return false;
     200             :   }
     201           0 :   return true;
     202             : }
     203             : 
     204             : bool
     205           0 : CryptoKeyPair::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     206             : {
     207             :   // Passing a null JSContext is OK only if we're initing from null,
     208             :   // Since in that case we will not have to do any property gets
     209             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     210             :   // checkers by static analysis tools
     211           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     212           0 :   CryptoKeyPairAtoms* atomsCache = nullptr;
     213           0 :   if (cx) {
     214           0 :     atomsCache = GetAtomCache<CryptoKeyPairAtoms>(cx);
     215           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     216           0 :       return false;
     217             :     }
     218             :   }
     219             : 
     220           0 :   if (!IsConvertibleToDictionary(val)) {
     221           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     222             :   }
     223             : 
     224           0 :   bool isNull = val.isNullOrUndefined();
     225             :   // We only need these if !isNull, in which case we have |cx|.
     226           0 :   Maybe<JS::Rooted<JSObject *> > object;
     227           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     228           0 :   if (!isNull) {
     229           0 :     MOZ_ASSERT(cx);
     230           0 :     object.emplace(cx, &val.toObject());
     231           0 :     temp.emplace(cx);
     232             :   }
     233           0 :   if (!isNull) {
     234           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->privateKey_id, temp.ptr())) {
     235           0 :       return false;
     236             :     }
     237             :   }
     238           0 :   if (!isNull && !temp->isUndefined()) {
     239           0 :     if (temp.ref().isObject()) {
     240             :       static_assert(IsRefcounted<mozilla::dom::CryptoKey>::value, "We can only store refcounted classes.");{
     241           0 :         nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(temp.ptr(), mPrivateKey);
     242           0 :         if (NS_FAILED(rv)) {
     243           0 :           ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "'privateKey' member of CryptoKeyPair", "CryptoKey");
     244           0 :           return false;
     245             :         }
     246             :       }
     247             :     } else {
     248           0 :       ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'privateKey' member of CryptoKeyPair");
     249           0 :       return false;
     250             :     }
     251           0 :     mIsAnyMemberPresent = true;
     252           0 :   } else if (cx) {
     253             :     // Don't error out if we have no cx.  In that
     254             :     // situation the caller is default-constructing us and we'll
     255             :     // just assume they know what they're doing.
     256           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
     257           0 :                              "'privateKey' member of CryptoKeyPair");
     258             :   }
     259             : 
     260           0 :   if (!isNull) {
     261           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->publicKey_id, temp.ptr())) {
     262           0 :       return false;
     263             :     }
     264             :   }
     265           0 :   if (!isNull && !temp->isUndefined()) {
     266           0 :     if (temp.ref().isObject()) {
     267             :       static_assert(IsRefcounted<mozilla::dom::CryptoKey>::value, "We can only store refcounted classes.");{
     268           0 :         nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(temp.ptr(), mPublicKey);
     269           0 :         if (NS_FAILED(rv)) {
     270           0 :           ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "'publicKey' member of CryptoKeyPair", "CryptoKey");
     271           0 :           return false;
     272             :         }
     273             :       }
     274             :     } else {
     275           0 :       ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'publicKey' member of CryptoKeyPair");
     276           0 :       return false;
     277             :     }
     278           0 :     mIsAnyMemberPresent = true;
     279           0 :   } else if (cx) {
     280             :     // Don't error out if we have no cx.  In that
     281             :     // situation the caller is default-constructing us and we'll
     282             :     // just assume they know what they're doing.
     283           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
     284           0 :                              "'publicKey' member of CryptoKeyPair");
     285             :   }
     286           0 :   return true;
     287             : }
     288             : 
     289             : bool
     290           0 : CryptoKeyPair::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     291             : {
     292           0 :   CryptoKeyPairAtoms* atomsCache = GetAtomCache<CryptoKeyPairAtoms>(cx);
     293           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     294           0 :     return false;
     295             :   }
     296             : 
     297           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     298           0 :   if (!obj) {
     299           0 :     return false;
     300             :   }
     301           0 :   rval.set(JS::ObjectValue(*obj));
     302             : 
     303             :   do {
     304             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     305           0 :     JS::Rooted<JS::Value> temp(cx);
     306           0 :     OwningNonNull<mozilla::dom::CryptoKey> const & currentValue = mPrivateKey;
     307           0 :     if (!GetOrCreateDOMReflector(cx, currentValue, &temp)) {
     308           0 :       MOZ_ASSERT(true || JS_IsExceptionPending(cx));
     309           0 :       return false;
     310             :     }
     311           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->privateKey_id, temp, JSPROP_ENUMERATE)) {
     312           0 :       return false;
     313             :     }
     314           0 :     break;
     315             :   } while(0);
     316             : 
     317             :   do {
     318             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     319           0 :     JS::Rooted<JS::Value> temp(cx);
     320           0 :     OwningNonNull<mozilla::dom::CryptoKey> const & currentValue = mPublicKey;
     321           0 :     if (!GetOrCreateDOMReflector(cx, currentValue, &temp)) {
     322           0 :       MOZ_ASSERT(true || JS_IsExceptionPending(cx));
     323           0 :       return false;
     324             :     }
     325           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->publicKey_id, temp, JSPROP_ENUMERATE)) {
     326           0 :       return false;
     327             :     }
     328           0 :     break;
     329             :   } while(0);
     330             : 
     331           0 :   return true;
     332             : }
     333             : 
     334             : void
     335           0 : CryptoKeyPair::TraceDictionary(JSTracer* trc)
     336             : {
     337           0 : }
     338             : 
     339             : CryptoKeyPair&
     340           0 : CryptoKeyPair::operator=(const CryptoKeyPair& aOther)
     341             : {
     342           0 :   mPrivateKey = aOther.mPrivateKey;
     343           0 :   mPublicKey = aOther.mPublicKey;
     344           0 :   return *this;
     345             : }
     346             : 
     347             : namespace binding_detail {
     348             : } // namespace binding_detail
     349             : 
     350             : 
     351             : 
     352           0 : RsaHashedImportParams::RsaHashedImportParams()
     353             : {
     354             :   // Safe to pass a null context if we pass a null value
     355           0 :   Init(nullptr, JS::NullHandleValue);
     356           0 : }
     357             : 
     358             : 
     359             : bool
     360           0 : RsaHashedImportParams::InitIds(JSContext* cx, RsaHashedImportParamsAtoms* atomsCache)
     361             : {
     362           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     363             : 
     364             :   // Initialize these in reverse order so that any failure leaves the first one
     365             :   // uninitialized.
     366           0 :   if (!atomsCache->hash_id.init(cx, "hash")) {
     367           0 :     return false;
     368             :   }
     369           0 :   return true;
     370             : }
     371             : 
     372             : bool
     373           0 : RsaHashedImportParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     374             : {
     375             :   // Passing a null JSContext is OK only if we're initing from null,
     376             :   // Since in that case we will not have to do any property gets
     377             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     378             :   // checkers by static analysis tools
     379           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     380           0 :   RsaHashedImportParamsAtoms* atomsCache = nullptr;
     381           0 :   if (cx) {
     382           0 :     atomsCache = GetAtomCache<RsaHashedImportParamsAtoms>(cx);
     383           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     384           0 :       return false;
     385             :     }
     386             :   }
     387             : 
     388           0 :   if (!IsConvertibleToDictionary(val)) {
     389           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     390             :   }
     391             : 
     392           0 :   bool isNull = val.isNullOrUndefined();
     393             :   // We only need these if !isNull, in which case we have |cx|.
     394           0 :   Maybe<JS::Rooted<JSObject *> > object;
     395           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     396           0 :   if (!isNull) {
     397           0 :     MOZ_ASSERT(cx);
     398           0 :     object.emplace(cx, &val.toObject());
     399           0 :     temp.emplace(cx);
     400             :   }
     401           0 :   if (!isNull) {
     402           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->hash_id, temp.ptr())) {
     403           0 :       return false;
     404             :     }
     405             :   }
     406           0 :   if (!isNull && !temp->isUndefined()) {
     407             :     {
     408           0 :       bool done = false, failed = false, tryNext;
     409           0 :       if (temp.ref().isObject()) {
     410           0 :         if (!mHash.SetToObject(cx, &temp.ref().toObject(), passedToJSImpl)) {
     411           0 :           return false;
     412             :         }
     413           0 :         done = true;
     414             :       } else {
     415             :         do {
     416           0 :           done = (failed = !mHash.TrySetToString(cx, temp.ref(), tryNext)) || !tryNext;
     417           0 :           break;
     418             :         } while (0);
     419             :       }
     420           0 :       if (failed) {
     421           0 :         return false;
     422             :       }
     423           0 :       if (!done) {
     424           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'hash' member of RsaHashedImportParams", "Object");
     425           0 :         return false;
     426             :       }
     427             :     }
     428           0 :     mIsAnyMemberPresent = true;
     429           0 :   } else if (cx) {
     430             :     // Don't error out if we have no cx.  In that
     431             :     // situation the caller is default-constructing us and we'll
     432             :     // just assume they know what they're doing.
     433           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
     434           0 :                              "'hash' member of RsaHashedImportParams");
     435             :   }
     436           0 :   return true;
     437             : }
     438             : 
     439             : bool
     440           0 : RsaHashedImportParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     441             : {
     442           0 :   RsaHashedImportParamsAtoms* atomsCache = GetAtomCache<RsaHashedImportParamsAtoms>(cx);
     443           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     444           0 :     return false;
     445             :   }
     446             : 
     447           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     448           0 :   if (!obj) {
     449           0 :     return false;
     450             :   }
     451           0 :   rval.set(JS::ObjectValue(*obj));
     452             : 
     453             :   do {
     454             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     455           0 :     JS::Rooted<JS::Value> temp(cx);
     456           0 :     OwningObjectOrString const & currentValue = mHash;
     457           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
     458           0 :       return false;
     459             :     }
     460           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->hash_id, temp, JSPROP_ENUMERATE)) {
     461           0 :       return false;
     462             :     }
     463           0 :     break;
     464             :   } while(0);
     465             : 
     466           0 :   return true;
     467             : }
     468             : 
     469             : void
     470           0 : RsaHashedImportParams::TraceDictionary(JSTracer* trc)
     471             : {
     472           0 :   mHash.TraceUnion(trc);
     473           0 : }
     474             : 
     475             : namespace binding_detail {
     476             : } // namespace binding_detail
     477             : 
     478             : 
     479             : 
     480           0 : RsaOtherPrimesInfo::RsaOtherPrimesInfo()
     481             : {
     482             :   // Safe to pass a null context if we pass a null value
     483           0 :   Init(nullptr, JS::NullHandleValue);
     484           0 : }
     485             : 
     486             : 
     487             : 
     488             : bool
     489           0 : RsaOtherPrimesInfo::InitIds(JSContext* cx, RsaOtherPrimesInfoAtoms* atomsCache)
     490             : {
     491           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     492             : 
     493             :   // Initialize these in reverse order so that any failure leaves the first one
     494             :   // uninitialized.
     495           0 :   if (!atomsCache->t_id.init(cx, "t") ||
     496           0 :       !atomsCache->r_id.init(cx, "r") ||
     497           0 :       !atomsCache->d_id.init(cx, "d")) {
     498           0 :     return false;
     499             :   }
     500           0 :   return true;
     501             : }
     502             : 
     503             : bool
     504           0 : RsaOtherPrimesInfo::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     505             : {
     506             :   // Passing a null JSContext is OK only if we're initing from null,
     507             :   // Since in that case we will not have to do any property gets
     508             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     509             :   // checkers by static analysis tools
     510           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     511           0 :   RsaOtherPrimesInfoAtoms* atomsCache = nullptr;
     512           0 :   if (cx) {
     513           0 :     atomsCache = GetAtomCache<RsaOtherPrimesInfoAtoms>(cx);
     514           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     515           0 :       return false;
     516             :     }
     517             :   }
     518             : 
     519           0 :   if (!IsConvertibleToDictionary(val)) {
     520           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     521             :   }
     522             : 
     523           0 :   bool isNull = val.isNullOrUndefined();
     524             :   // We only need these if !isNull, in which case we have |cx|.
     525           0 :   Maybe<JS::Rooted<JSObject *> > object;
     526           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     527           0 :   if (!isNull) {
     528           0 :     MOZ_ASSERT(cx);
     529           0 :     object.emplace(cx, &val.toObject());
     530           0 :     temp.emplace(cx);
     531             :   }
     532           0 :   if (!isNull) {
     533           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->d_id, temp.ptr())) {
     534           0 :       return false;
     535             :     }
     536             :   }
     537           0 :   if (!isNull && !temp->isUndefined()) {
     538           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mD)) {
     539           0 :       return false;
     540             :     }
     541           0 :     mIsAnyMemberPresent = true;
     542           0 :   } else if (cx) {
     543             :     // Don't error out if we have no cx.  In that
     544             :     // situation the caller is default-constructing us and we'll
     545             :     // just assume they know what they're doing.
     546           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
     547           0 :                              "'d' member of RsaOtherPrimesInfo");
     548             :   }
     549             : 
     550           0 :   if (!isNull) {
     551           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->r_id, temp.ptr())) {
     552           0 :       return false;
     553             :     }
     554             :   }
     555           0 :   if (!isNull && !temp->isUndefined()) {
     556           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mR)) {
     557           0 :       return false;
     558             :     }
     559           0 :     mIsAnyMemberPresent = true;
     560           0 :   } else if (cx) {
     561             :     // Don't error out if we have no cx.  In that
     562             :     // situation the caller is default-constructing us and we'll
     563             :     // just assume they know what they're doing.
     564           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
     565           0 :                              "'r' member of RsaOtherPrimesInfo");
     566             :   }
     567             : 
     568           0 :   if (!isNull) {
     569           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->t_id, temp.ptr())) {
     570           0 :       return false;
     571             :     }
     572             :   }
     573           0 :   if (!isNull && !temp->isUndefined()) {
     574           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mT)) {
     575           0 :       return false;
     576             :     }
     577           0 :     mIsAnyMemberPresent = true;
     578           0 :   } else if (cx) {
     579             :     // Don't error out if we have no cx.  In that
     580             :     // situation the caller is default-constructing us and we'll
     581             :     // just assume they know what they're doing.
     582           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
     583           0 :                              "'t' member of RsaOtherPrimesInfo");
     584             :   }
     585           0 :   return true;
     586             : }
     587             : 
     588             : bool
     589           0 : RsaOtherPrimesInfo::Init(const nsAString& aJSON)
     590             : {
     591           0 :   AutoJSAPI jsapi;
     592           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     593           0 :   if (!cleanGlobal) {
     594           0 :     return false;
     595             :   }
     596           0 :   if (!jsapi.Init(cleanGlobal)) {
     597           0 :     return false;
     598             :   }
     599           0 :   JSContext* cx = jsapi.cx();
     600           0 :   JS::Rooted<JS::Value> json(cx);
     601           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     602           0 :   NS_ENSURE_TRUE(ok, false);
     603           0 :   return Init(cx, json);
     604             : }
     605             : 
     606             : bool
     607           0 : RsaOtherPrimesInfo::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     608             : {
     609           0 :   RsaOtherPrimesInfoAtoms* atomsCache = GetAtomCache<RsaOtherPrimesInfoAtoms>(cx);
     610           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     611           0 :     return false;
     612             :   }
     613             : 
     614           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     615           0 :   if (!obj) {
     616           0 :     return false;
     617             :   }
     618           0 :   rval.set(JS::ObjectValue(*obj));
     619             : 
     620             :   do {
     621             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     622           0 :     JS::Rooted<JS::Value> temp(cx);
     623           0 :     nsString const & currentValue = mD;
     624           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     625           0 :       return false;
     626             :     }
     627           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->d_id, temp, JSPROP_ENUMERATE)) {
     628           0 :       return false;
     629             :     }
     630           0 :     break;
     631             :   } while(0);
     632             : 
     633             :   do {
     634             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     635           0 :     JS::Rooted<JS::Value> temp(cx);
     636           0 :     nsString const & currentValue = mR;
     637           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     638           0 :       return false;
     639             :     }
     640           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->r_id, temp, JSPROP_ENUMERATE)) {
     641           0 :       return false;
     642             :     }
     643           0 :     break;
     644             :   } while(0);
     645             : 
     646             :   do {
     647             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     648           0 :     JS::Rooted<JS::Value> temp(cx);
     649           0 :     nsString const & currentValue = mT;
     650           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     651           0 :       return false;
     652             :     }
     653           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->t_id, temp, JSPROP_ENUMERATE)) {
     654           0 :       return false;
     655             :     }
     656           0 :     break;
     657             :   } while(0);
     658             : 
     659           0 :   return true;
     660             : }
     661             : 
     662             : bool
     663           0 : RsaOtherPrimesInfo::ToJSON(nsAString& aJSON) const
     664             : {
     665           0 :   AutoJSAPI jsapi;
     666           0 :   jsapi.Init();
     667           0 :   JSContext *cx = jsapi.cx();
     668             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     669             :   // because we'll only be creating objects, in ways that have no
     670             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     671             :   // which likewise guarantees no side-effects for the sorts of
     672             :   // things we will pass it.
     673           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     674           0 :   JS::Rooted<JS::Value> val(cx);
     675           0 :   if (!ToObjectInternal(cx, &val)) {
     676           0 :     return false;
     677             :   }
     678           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     679           0 :   return StringifyToJSON(cx, obj, aJSON);
     680             : }
     681             : 
     682             : void
     683           0 : RsaOtherPrimesInfo::TraceDictionary(JSTracer* trc)
     684             : {
     685           0 : }
     686             : 
     687             : RsaOtherPrimesInfo&
     688           0 : RsaOtherPrimesInfo::operator=(const RsaOtherPrimesInfo& aOther)
     689             : {
     690           0 :   mD = aOther.mD;
     691           0 :   mR = aOther.mR;
     692           0 :   mT = aOther.mT;
     693           0 :   return *this;
     694             : }
     695             : 
     696             : namespace binding_detail {
     697             : } // namespace binding_detail
     698             : 
     699             : 
     700             : 
     701           0 : AesCbcParams::AesCbcParams()
     702           0 :   : Algorithm(FastDictionaryInitializer())
     703             : {
     704             :   // Safe to pass a null context if we pass a null value
     705           0 :   Init(nullptr, JS::NullHandleValue);
     706           0 : }
     707             : 
     708             : 
     709             : bool
     710           0 : AesCbcParams::InitIds(JSContext* cx, AesCbcParamsAtoms* atomsCache)
     711             : {
     712           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     713             : 
     714             :   // Initialize these in reverse order so that any failure leaves the first one
     715             :   // uninitialized.
     716           0 :   if (!atomsCache->iv_id.init(cx, "iv")) {
     717           0 :     return false;
     718             :   }
     719           0 :   return true;
     720             : }
     721             : 
     722             : bool
     723           0 : AesCbcParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     724             : {
     725             :   // Passing a null JSContext is OK only if we're initing from null,
     726             :   // Since in that case we will not have to do any property gets
     727             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     728             :   // checkers by static analysis tools
     729           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     730           0 :   AesCbcParamsAtoms* atomsCache = nullptr;
     731           0 :   if (cx) {
     732           0 :     atomsCache = GetAtomCache<AesCbcParamsAtoms>(cx);
     733           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     734           0 :       return false;
     735             :     }
     736             :   }
     737             : 
     738             :   // Per spec, we init the parent's members first
     739           0 :   if (!Algorithm::Init(cx, val)) {
     740           0 :     return false;
     741             :   }
     742             : 
     743           0 :   bool isNull = val.isNullOrUndefined();
     744             :   // We only need these if !isNull, in which case we have |cx|.
     745           0 :   Maybe<JS::Rooted<JSObject *> > object;
     746           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     747           0 :   if (!isNull) {
     748           0 :     MOZ_ASSERT(cx);
     749           0 :     object.emplace(cx, &val.toObject());
     750           0 :     temp.emplace(cx);
     751             :   }
     752           0 :   if (!isNull) {
     753           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->iv_id, temp.ptr())) {
     754           0 :       return false;
     755             :     }
     756             :   }
     757           0 :   if (!isNull && !temp->isUndefined()) {
     758             :     {
     759           0 :       bool done = false, failed = false, tryNext;
     760           0 :       if (temp.ref().isObject()) {
     761           0 :         done = (failed = !mIv.TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
     762           0 :                (failed = !mIv.TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
     763             : 
     764             :       }
     765           0 :       if (failed) {
     766           0 :         return false;
     767             :       }
     768           0 :       if (!done) {
     769           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'iv' member of AesCbcParams", "ArrayBufferView, ArrayBuffer");
     770           0 :         return false;
     771             :       }
     772             :     }
     773           0 :     mIsAnyMemberPresent = true;
     774           0 :   } else if (cx) {
     775             :     // Don't error out if we have no cx.  In that
     776             :     // situation the caller is default-constructing us and we'll
     777             :     // just assume they know what they're doing.
     778           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
     779           0 :                              "'iv' member of AesCbcParams");
     780             :   }
     781           0 :   return true;
     782             : }
     783             : 
     784             : bool
     785           0 : AesCbcParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     786             : {
     787           0 :   AesCbcParamsAtoms* atomsCache = GetAtomCache<AesCbcParamsAtoms>(cx);
     788           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     789           0 :     return false;
     790             :   }
     791             : 
     792             :   // Per spec, we define the parent's members first
     793           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
     794           0 :     return false;
     795             :   }
     796           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
     797             : 
     798             :   do {
     799             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     800           0 :     JS::Rooted<JS::Value> temp(cx);
     801           0 :     OwningArrayBufferViewOrArrayBuffer const & currentValue = mIv;
     802           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
     803           0 :       return false;
     804             :     }
     805           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->iv_id, temp, JSPROP_ENUMERATE)) {
     806           0 :       return false;
     807             :     }
     808           0 :     break;
     809             :   } while(0);
     810             : 
     811           0 :   return true;
     812             : }
     813             : 
     814             : void
     815           0 : AesCbcParams::TraceDictionary(JSTracer* trc)
     816             : {
     817           0 :   Algorithm::TraceDictionary(trc);
     818           0 :   mIv.TraceUnion(trc);
     819           0 : }
     820             : 
     821             : namespace binding_detail {
     822             : } // namespace binding_detail
     823             : 
     824             : 
     825             : 
     826           0 : AesCtrParams::AesCtrParams()
     827           0 :   : Algorithm(FastDictionaryInitializer())
     828             : {
     829             :   // Safe to pass a null context if we pass a null value
     830           0 :   Init(nullptr, JS::NullHandleValue);
     831           0 : }
     832             : 
     833             : 
     834             : bool
     835           0 : AesCtrParams::InitIds(JSContext* cx, AesCtrParamsAtoms* atomsCache)
     836             : {
     837           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     838             : 
     839             :   // Initialize these in reverse order so that any failure leaves the first one
     840             :   // uninitialized.
     841           0 :   if (!atomsCache->length_id.init(cx, "length") ||
     842           0 :       !atomsCache->counter_id.init(cx, "counter")) {
     843           0 :     return false;
     844             :   }
     845           0 :   return true;
     846             : }
     847             : 
     848             : bool
     849           0 : AesCtrParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     850             : {
     851             :   // Passing a null JSContext is OK only if we're initing from null,
     852             :   // Since in that case we will not have to do any property gets
     853             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     854             :   // checkers by static analysis tools
     855           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     856           0 :   AesCtrParamsAtoms* atomsCache = nullptr;
     857           0 :   if (cx) {
     858           0 :     atomsCache = GetAtomCache<AesCtrParamsAtoms>(cx);
     859           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     860           0 :       return false;
     861             :     }
     862             :   }
     863             : 
     864             :   // Per spec, we init the parent's members first
     865           0 :   if (!Algorithm::Init(cx, val)) {
     866           0 :     return false;
     867             :   }
     868             : 
     869           0 :   bool isNull = val.isNullOrUndefined();
     870             :   // We only need these if !isNull, in which case we have |cx|.
     871           0 :   Maybe<JS::Rooted<JSObject *> > object;
     872           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     873           0 :   if (!isNull) {
     874           0 :     MOZ_ASSERT(cx);
     875           0 :     object.emplace(cx, &val.toObject());
     876           0 :     temp.emplace(cx);
     877             :   }
     878           0 :   if (!isNull) {
     879           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->counter_id, temp.ptr())) {
     880           0 :       return false;
     881             :     }
     882             :   }
     883           0 :   if (!isNull && !temp->isUndefined()) {
     884             :     {
     885           0 :       bool done = false, failed = false, tryNext;
     886           0 :       if (temp.ref().isObject()) {
     887           0 :         done = (failed = !mCounter.TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
     888           0 :                (failed = !mCounter.TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
     889             : 
     890             :       }
     891           0 :       if (failed) {
     892           0 :         return false;
     893             :       }
     894           0 :       if (!done) {
     895           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'counter' member of AesCtrParams", "ArrayBufferView, ArrayBuffer");
     896           0 :         return false;
     897             :       }
     898             :     }
     899           0 :     mIsAnyMemberPresent = true;
     900           0 :   } else if (cx) {
     901             :     // Don't error out if we have no cx.  In that
     902             :     // situation the caller is default-constructing us and we'll
     903             :     // just assume they know what they're doing.
     904           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
     905           0 :                              "'counter' member of AesCtrParams");
     906             :   }
     907             : 
     908           0 :   if (!isNull) {
     909           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->length_id, temp.ptr())) {
     910           0 :       return false;
     911             :     }
     912             :   }
     913           0 :   if (!isNull && !temp->isUndefined()) {
     914           0 :     if (!ValueToPrimitive<uint8_t, eEnforceRange>(cx, temp.ref(), &mLength)) {
     915           0 :       return false;
     916             :     }
     917           0 :     mIsAnyMemberPresent = true;
     918           0 :   } else if (cx) {
     919             :     // Don't error out if we have no cx.  In that
     920             :     // situation the caller is default-constructing us and we'll
     921             :     // just assume they know what they're doing.
     922           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
     923           0 :                              "'length' member of AesCtrParams");
     924             :   }
     925           0 :   return true;
     926             : }
     927             : 
     928             : bool
     929           0 : AesCtrParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     930             : {
     931           0 :   AesCtrParamsAtoms* atomsCache = GetAtomCache<AesCtrParamsAtoms>(cx);
     932           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     933           0 :     return false;
     934             :   }
     935             : 
     936             :   // Per spec, we define the parent's members first
     937           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
     938           0 :     return false;
     939             :   }
     940           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
     941             : 
     942             :   do {
     943             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     944           0 :     JS::Rooted<JS::Value> temp(cx);
     945           0 :     OwningArrayBufferViewOrArrayBuffer const & currentValue = mCounter;
     946           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
     947           0 :       return false;
     948             :     }
     949           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->counter_id, temp, JSPROP_ENUMERATE)) {
     950           0 :       return false;
     951             :     }
     952           0 :     break;
     953             :   } while(0);
     954             : 
     955             :   do {
     956             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     957           0 :     JS::Rooted<JS::Value> temp(cx);
     958           0 :     uint8_t const & currentValue = mLength;
     959           0 :     temp.setInt32(int32_t(currentValue));
     960           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->length_id, temp, JSPROP_ENUMERATE)) {
     961           0 :       return false;
     962             :     }
     963           0 :     break;
     964             :   } while(0);
     965             : 
     966           0 :   return true;
     967             : }
     968             : 
     969             : void
     970           0 : AesCtrParams::TraceDictionary(JSTracer* trc)
     971             : {
     972           0 :   Algorithm::TraceDictionary(trc);
     973           0 :   mCounter.TraceUnion(trc);
     974           0 : }
     975             : 
     976             : namespace binding_detail {
     977             : } // namespace binding_detail
     978             : 
     979             : 
     980             : 
     981           0 : AesDerivedKeyParams::AesDerivedKeyParams()
     982           0 :   : Algorithm(FastDictionaryInitializer())
     983             : {
     984             :   // Safe to pass a null context if we pass a null value
     985           0 :   Init(nullptr, JS::NullHandleValue);
     986           0 : }
     987             : 
     988             : 
     989             : 
     990             : bool
     991           0 : AesDerivedKeyParams::InitIds(JSContext* cx, AesDerivedKeyParamsAtoms* atomsCache)
     992             : {
     993           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     994             : 
     995             :   // Initialize these in reverse order so that any failure leaves the first one
     996             :   // uninitialized.
     997           0 :   if (!atomsCache->length_id.init(cx, "length")) {
     998           0 :     return false;
     999             :   }
    1000           0 :   return true;
    1001             : }
    1002             : 
    1003             : bool
    1004           0 : AesDerivedKeyParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1005             : {
    1006             :   // Passing a null JSContext is OK only if we're initing from null,
    1007             :   // Since in that case we will not have to do any property gets
    1008             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1009             :   // checkers by static analysis tools
    1010           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1011           0 :   AesDerivedKeyParamsAtoms* atomsCache = nullptr;
    1012           0 :   if (cx) {
    1013           0 :     atomsCache = GetAtomCache<AesDerivedKeyParamsAtoms>(cx);
    1014           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1015           0 :       return false;
    1016             :     }
    1017             :   }
    1018             : 
    1019             :   // Per spec, we init the parent's members first
    1020           0 :   if (!Algorithm::Init(cx, val)) {
    1021           0 :     return false;
    1022             :   }
    1023             : 
    1024           0 :   bool isNull = val.isNullOrUndefined();
    1025             :   // We only need these if !isNull, in which case we have |cx|.
    1026           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1027           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1028           0 :   if (!isNull) {
    1029           0 :     MOZ_ASSERT(cx);
    1030           0 :     object.emplace(cx, &val.toObject());
    1031           0 :     temp.emplace(cx);
    1032             :   }
    1033           0 :   if (!isNull) {
    1034           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->length_id, temp.ptr())) {
    1035           0 :       return false;
    1036             :     }
    1037             :   }
    1038           0 :   if (!isNull && !temp->isUndefined()) {
    1039           0 :     if (!ValueToPrimitive<uint32_t, eEnforceRange>(cx, temp.ref(), &mLength)) {
    1040           0 :       return false;
    1041             :     }
    1042           0 :     mIsAnyMemberPresent = true;
    1043           0 :   } else if (cx) {
    1044             :     // Don't error out if we have no cx.  In that
    1045             :     // situation the caller is default-constructing us and we'll
    1046             :     // just assume they know what they're doing.
    1047           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    1048           0 :                              "'length' member of AesDerivedKeyParams");
    1049             :   }
    1050           0 :   return true;
    1051             : }
    1052             : 
    1053             : bool
    1054           0 : AesDerivedKeyParams::Init(const nsAString& aJSON)
    1055             : {
    1056           0 :   AutoJSAPI jsapi;
    1057           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    1058           0 :   if (!cleanGlobal) {
    1059           0 :     return false;
    1060             :   }
    1061           0 :   if (!jsapi.Init(cleanGlobal)) {
    1062           0 :     return false;
    1063             :   }
    1064           0 :   JSContext* cx = jsapi.cx();
    1065           0 :   JS::Rooted<JS::Value> json(cx);
    1066           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    1067           0 :   NS_ENSURE_TRUE(ok, false);
    1068           0 :   return Init(cx, json);
    1069             : }
    1070             : 
    1071             : bool
    1072           0 : AesDerivedKeyParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1073             : {
    1074           0 :   AesDerivedKeyParamsAtoms* atomsCache = GetAtomCache<AesDerivedKeyParamsAtoms>(cx);
    1075           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1076           0 :     return false;
    1077             :   }
    1078             : 
    1079             :   // Per spec, we define the parent's members first
    1080           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    1081           0 :     return false;
    1082             :   }
    1083           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    1084             : 
    1085             :   do {
    1086             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1087           0 :     JS::Rooted<JS::Value> temp(cx);
    1088           0 :     uint32_t const & currentValue = mLength;
    1089           0 :     temp.setNumber(currentValue);
    1090           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->length_id, temp, JSPROP_ENUMERATE)) {
    1091           0 :       return false;
    1092             :     }
    1093           0 :     break;
    1094             :   } while(0);
    1095             : 
    1096           0 :   return true;
    1097             : }
    1098             : 
    1099             : bool
    1100           0 : AesDerivedKeyParams::ToJSON(nsAString& aJSON) const
    1101             : {
    1102           0 :   AutoJSAPI jsapi;
    1103           0 :   jsapi.Init();
    1104           0 :   JSContext *cx = jsapi.cx();
    1105             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    1106             :   // because we'll only be creating objects, in ways that have no
    1107             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    1108             :   // which likewise guarantees no side-effects for the sorts of
    1109             :   // things we will pass it.
    1110           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    1111           0 :   JS::Rooted<JS::Value> val(cx);
    1112           0 :   if (!ToObjectInternal(cx, &val)) {
    1113           0 :     return false;
    1114             :   }
    1115           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    1116           0 :   return StringifyToJSON(cx, obj, aJSON);
    1117             : }
    1118             : 
    1119             : void
    1120           0 : AesDerivedKeyParams::TraceDictionary(JSTracer* trc)
    1121             : {
    1122           0 :   Algorithm::TraceDictionary(trc);
    1123           0 : }
    1124             : 
    1125             : AesDerivedKeyParams&
    1126           0 : AesDerivedKeyParams::operator=(const AesDerivedKeyParams& aOther)
    1127             : {
    1128           0 :   Algorithm::operator=(aOther);
    1129           0 :   mLength = aOther.mLength;
    1130           0 :   return *this;
    1131             : }
    1132             : 
    1133             : namespace binding_detail {
    1134             : } // namespace binding_detail
    1135             : 
    1136             : 
    1137             : 
    1138           0 : AesGcmParams::AesGcmParams()
    1139           0 :   : Algorithm(FastDictionaryInitializer())
    1140             : {
    1141             :   // Safe to pass a null context if we pass a null value
    1142           0 :   Init(nullptr, JS::NullHandleValue);
    1143           0 : }
    1144             : 
    1145             : 
    1146             : bool
    1147           0 : AesGcmParams::InitIds(JSContext* cx, AesGcmParamsAtoms* atomsCache)
    1148             : {
    1149           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1150             : 
    1151             :   // Initialize these in reverse order so that any failure leaves the first one
    1152             :   // uninitialized.
    1153           0 :   if (!atomsCache->tagLength_id.init(cx, "tagLength") ||
    1154           0 :       !atomsCache->iv_id.init(cx, "iv") ||
    1155           0 :       !atomsCache->additionalData_id.init(cx, "additionalData")) {
    1156           0 :     return false;
    1157             :   }
    1158           0 :   return true;
    1159             : }
    1160             : 
    1161             : bool
    1162           0 : AesGcmParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1163             : {
    1164             :   // Passing a null JSContext is OK only if we're initing from null,
    1165             :   // Since in that case we will not have to do any property gets
    1166             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1167             :   // checkers by static analysis tools
    1168           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1169           0 :   AesGcmParamsAtoms* atomsCache = nullptr;
    1170           0 :   if (cx) {
    1171           0 :     atomsCache = GetAtomCache<AesGcmParamsAtoms>(cx);
    1172           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1173           0 :       return false;
    1174             :     }
    1175             :   }
    1176             : 
    1177             :   // Per spec, we init the parent's members first
    1178           0 :   if (!Algorithm::Init(cx, val)) {
    1179           0 :     return false;
    1180             :   }
    1181             : 
    1182           0 :   bool isNull = val.isNullOrUndefined();
    1183             :   // We only need these if !isNull, in which case we have |cx|.
    1184           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1185           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1186           0 :   if (!isNull) {
    1187           0 :     MOZ_ASSERT(cx);
    1188           0 :     object.emplace(cx, &val.toObject());
    1189           0 :     temp.emplace(cx);
    1190             :   }
    1191           0 :   if (!isNull) {
    1192           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->additionalData_id, temp.ptr())) {
    1193           0 :       return false;
    1194             :     }
    1195             :   }
    1196           0 :   if (!isNull && !temp->isUndefined()) {
    1197           0 :     mAdditionalData.Construct();
    1198             :     {
    1199           0 :       bool done = false, failed = false, tryNext;
    1200           0 :       if (temp.ref().isObject()) {
    1201           0 :         done = (failed = !(mAdditionalData.Value()).TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
    1202           0 :                (failed = !(mAdditionalData.Value()).TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
    1203             : 
    1204             :       }
    1205           0 :       if (failed) {
    1206           0 :         return false;
    1207             :       }
    1208           0 :       if (!done) {
    1209           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'additionalData' member of AesGcmParams", "ArrayBufferView, ArrayBuffer");
    1210           0 :         return false;
    1211             :       }
    1212             :     }
    1213           0 :     mIsAnyMemberPresent = true;
    1214             :   }
    1215             : 
    1216           0 :   if (!isNull) {
    1217           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->iv_id, temp.ptr())) {
    1218           0 :       return false;
    1219             :     }
    1220             :   }
    1221           0 :   if (!isNull && !temp->isUndefined()) {
    1222             :     {
    1223           0 :       bool done = false, failed = false, tryNext;
    1224           0 :       if (temp.ref().isObject()) {
    1225           0 :         done = (failed = !mIv.TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
    1226           0 :                (failed = !mIv.TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
    1227             : 
    1228             :       }
    1229           0 :       if (failed) {
    1230           0 :         return false;
    1231             :       }
    1232           0 :       if (!done) {
    1233           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'iv' member of AesGcmParams", "ArrayBufferView, ArrayBuffer");
    1234           0 :         return false;
    1235             :       }
    1236             :     }
    1237           0 :     mIsAnyMemberPresent = true;
    1238           0 :   } else if (cx) {
    1239             :     // Don't error out if we have no cx.  In that
    1240             :     // situation the caller is default-constructing us and we'll
    1241             :     // just assume they know what they're doing.
    1242           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    1243           0 :                              "'iv' member of AesGcmParams");
    1244             :   }
    1245             : 
    1246           0 :   if (!isNull) {
    1247           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->tagLength_id, temp.ptr())) {
    1248           0 :       return false;
    1249             :     }
    1250             :   }
    1251           0 :   if (!isNull && !temp->isUndefined()) {
    1252           0 :     mTagLength.Construct();
    1253           0 :     if (!ValueToPrimitive<uint8_t, eEnforceRange>(cx, temp.ref(), &(mTagLength.Value()))) {
    1254           0 :       return false;
    1255             :     }
    1256           0 :     mIsAnyMemberPresent = true;
    1257             :   }
    1258           0 :   return true;
    1259             : }
    1260             : 
    1261             : bool
    1262           0 : AesGcmParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1263             : {
    1264           0 :   AesGcmParamsAtoms* atomsCache = GetAtomCache<AesGcmParamsAtoms>(cx);
    1265           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1266           0 :     return false;
    1267             :   }
    1268             : 
    1269             :   // Per spec, we define the parent's members first
    1270           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    1271           0 :     return false;
    1272             :   }
    1273           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    1274             : 
    1275           0 :   if (mAdditionalData.WasPassed()) {
    1276             :     do {
    1277             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1278           0 :       JS::Rooted<JS::Value> temp(cx);
    1279           0 :       OwningArrayBufferViewOrArrayBuffer const & currentValue = mAdditionalData.InternalValue();
    1280           0 :       if (!currentValue.ToJSVal(cx, obj, &temp)) {
    1281           0 :         return false;
    1282             :       }
    1283           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->additionalData_id, temp, JSPROP_ENUMERATE)) {
    1284           0 :         return false;
    1285             :       }
    1286           0 :       break;
    1287             :     } while(0);
    1288             :   }
    1289             : 
    1290             :   do {
    1291             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1292           0 :     JS::Rooted<JS::Value> temp(cx);
    1293           0 :     OwningArrayBufferViewOrArrayBuffer const & currentValue = mIv;
    1294           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
    1295           0 :       return false;
    1296             :     }
    1297           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->iv_id, temp, JSPROP_ENUMERATE)) {
    1298           0 :       return false;
    1299             :     }
    1300           0 :     break;
    1301             :   } while(0);
    1302             : 
    1303           0 :   if (mTagLength.WasPassed()) {
    1304             :     do {
    1305             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1306           0 :       JS::Rooted<JS::Value> temp(cx);
    1307           0 :       uint8_t const & currentValue = mTagLength.InternalValue();
    1308           0 :       temp.setInt32(int32_t(currentValue));
    1309           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->tagLength_id, temp, JSPROP_ENUMERATE)) {
    1310           0 :         return false;
    1311             :       }
    1312           0 :       break;
    1313             :     } while(0);
    1314             :   }
    1315             : 
    1316           0 :   return true;
    1317             : }
    1318             : 
    1319             : void
    1320           0 : AesGcmParams::TraceDictionary(JSTracer* trc)
    1321             : {
    1322           0 :   Algorithm::TraceDictionary(trc);
    1323           0 :   if (mAdditionalData.WasPassed()) {
    1324           0 :     mAdditionalData.Value().TraceUnion(trc);
    1325             :   }
    1326             : 
    1327           0 :   mIv.TraceUnion(trc);
    1328           0 : }
    1329             : 
    1330             : namespace binding_detail {
    1331             : } // namespace binding_detail
    1332             : 
    1333             : 
    1334             : 
    1335           0 : AesKeyGenParams::AesKeyGenParams()
    1336           0 :   : Algorithm(FastDictionaryInitializer())
    1337             : {
    1338             :   // Safe to pass a null context if we pass a null value
    1339           0 :   Init(nullptr, JS::NullHandleValue);
    1340           0 : }
    1341             : 
    1342             : 
    1343             : 
    1344             : bool
    1345           0 : AesKeyGenParams::InitIds(JSContext* cx, AesKeyGenParamsAtoms* atomsCache)
    1346             : {
    1347           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1348             : 
    1349             :   // Initialize these in reverse order so that any failure leaves the first one
    1350             :   // uninitialized.
    1351           0 :   if (!atomsCache->length_id.init(cx, "length")) {
    1352           0 :     return false;
    1353             :   }
    1354           0 :   return true;
    1355             : }
    1356             : 
    1357             : bool
    1358           0 : AesKeyGenParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1359             : {
    1360             :   // Passing a null JSContext is OK only if we're initing from null,
    1361             :   // Since in that case we will not have to do any property gets
    1362             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1363             :   // checkers by static analysis tools
    1364           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1365           0 :   AesKeyGenParamsAtoms* atomsCache = nullptr;
    1366           0 :   if (cx) {
    1367           0 :     atomsCache = GetAtomCache<AesKeyGenParamsAtoms>(cx);
    1368           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1369           0 :       return false;
    1370             :     }
    1371             :   }
    1372             : 
    1373             :   // Per spec, we init the parent's members first
    1374           0 :   if (!Algorithm::Init(cx, val)) {
    1375           0 :     return false;
    1376             :   }
    1377             : 
    1378           0 :   bool isNull = val.isNullOrUndefined();
    1379             :   // We only need these if !isNull, in which case we have |cx|.
    1380           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1381           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1382           0 :   if (!isNull) {
    1383           0 :     MOZ_ASSERT(cx);
    1384           0 :     object.emplace(cx, &val.toObject());
    1385           0 :     temp.emplace(cx);
    1386             :   }
    1387           0 :   if (!isNull) {
    1388           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->length_id, temp.ptr())) {
    1389           0 :       return false;
    1390             :     }
    1391             :   }
    1392           0 :   if (!isNull && !temp->isUndefined()) {
    1393           0 :     if (!ValueToPrimitive<uint16_t, eEnforceRange>(cx, temp.ref(), &mLength)) {
    1394           0 :       return false;
    1395             :     }
    1396           0 :     mIsAnyMemberPresent = true;
    1397           0 :   } else if (cx) {
    1398             :     // Don't error out if we have no cx.  In that
    1399             :     // situation the caller is default-constructing us and we'll
    1400             :     // just assume they know what they're doing.
    1401           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    1402           0 :                              "'length' member of AesKeyGenParams");
    1403             :   }
    1404           0 :   return true;
    1405             : }
    1406             : 
    1407             : bool
    1408           0 : AesKeyGenParams::Init(const nsAString& aJSON)
    1409             : {
    1410           0 :   AutoJSAPI jsapi;
    1411           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    1412           0 :   if (!cleanGlobal) {
    1413           0 :     return false;
    1414             :   }
    1415           0 :   if (!jsapi.Init(cleanGlobal)) {
    1416           0 :     return false;
    1417             :   }
    1418           0 :   JSContext* cx = jsapi.cx();
    1419           0 :   JS::Rooted<JS::Value> json(cx);
    1420           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    1421           0 :   NS_ENSURE_TRUE(ok, false);
    1422           0 :   return Init(cx, json);
    1423             : }
    1424             : 
    1425             : bool
    1426           0 : AesKeyGenParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1427             : {
    1428           0 :   AesKeyGenParamsAtoms* atomsCache = GetAtomCache<AesKeyGenParamsAtoms>(cx);
    1429           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1430           0 :     return false;
    1431             :   }
    1432             : 
    1433             :   // Per spec, we define the parent's members first
    1434           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    1435           0 :     return false;
    1436             :   }
    1437           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    1438             : 
    1439             :   do {
    1440             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1441           0 :     JS::Rooted<JS::Value> temp(cx);
    1442           0 :     uint16_t const & currentValue = mLength;
    1443           0 :     temp.setInt32(int32_t(currentValue));
    1444           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->length_id, temp, JSPROP_ENUMERATE)) {
    1445           0 :       return false;
    1446             :     }
    1447           0 :     break;
    1448             :   } while(0);
    1449             : 
    1450           0 :   return true;
    1451             : }
    1452             : 
    1453             : bool
    1454           0 : AesKeyGenParams::ToJSON(nsAString& aJSON) const
    1455             : {
    1456           0 :   AutoJSAPI jsapi;
    1457           0 :   jsapi.Init();
    1458           0 :   JSContext *cx = jsapi.cx();
    1459             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    1460             :   // because we'll only be creating objects, in ways that have no
    1461             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    1462             :   // which likewise guarantees no side-effects for the sorts of
    1463             :   // things we will pass it.
    1464           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    1465           0 :   JS::Rooted<JS::Value> val(cx);
    1466           0 :   if (!ToObjectInternal(cx, &val)) {
    1467           0 :     return false;
    1468             :   }
    1469           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    1470           0 :   return StringifyToJSON(cx, obj, aJSON);
    1471             : }
    1472             : 
    1473             : void
    1474           0 : AesKeyGenParams::TraceDictionary(JSTracer* trc)
    1475             : {
    1476           0 :   Algorithm::TraceDictionary(trc);
    1477           0 : }
    1478             : 
    1479             : AesKeyGenParams&
    1480           0 : AesKeyGenParams::operator=(const AesKeyGenParams& aOther)
    1481             : {
    1482           0 :   Algorithm::operator=(aOther);
    1483           0 :   mLength = aOther.mLength;
    1484           0 :   return *this;
    1485             : }
    1486             : 
    1487             : namespace binding_detail {
    1488             : } // namespace binding_detail
    1489             : 
    1490             : 
    1491             : 
    1492           0 : DhImportKeyParams::DhImportKeyParams()
    1493           0 :   : Algorithm(FastDictionaryInitializer())
    1494             : {
    1495             :   // Safe to pass a null context if we pass a null value
    1496           0 :   Init(nullptr, JS::NullHandleValue);
    1497           0 : }
    1498             : 
    1499             : 
    1500             : bool
    1501           0 : DhImportKeyParams::InitIds(JSContext* cx, DhImportKeyParamsAtoms* atomsCache)
    1502             : {
    1503           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1504             : 
    1505             :   // Initialize these in reverse order so that any failure leaves the first one
    1506             :   // uninitialized.
    1507           0 :   if (!atomsCache->prime_id.init(cx, "prime") ||
    1508           0 :       !atomsCache->generator_id.init(cx, "generator")) {
    1509           0 :     return false;
    1510             :   }
    1511           0 :   return true;
    1512             : }
    1513             : 
    1514             : bool
    1515           0 : DhImportKeyParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1516             : {
    1517             :   // Passing a null JSContext is OK only if we're initing from null,
    1518             :   // Since in that case we will not have to do any property gets
    1519             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1520             :   // checkers by static analysis tools
    1521           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1522           0 :   DhImportKeyParamsAtoms* atomsCache = nullptr;
    1523           0 :   if (cx) {
    1524           0 :     atomsCache = GetAtomCache<DhImportKeyParamsAtoms>(cx);
    1525           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1526           0 :       return false;
    1527             :     }
    1528             :   }
    1529             : 
    1530             :   // Per spec, we init the parent's members first
    1531           0 :   if (!Algorithm::Init(cx, val)) {
    1532           0 :     return false;
    1533             :   }
    1534             : 
    1535           0 :   bool isNull = val.isNullOrUndefined();
    1536             :   // We only need these if !isNull, in which case we have |cx|.
    1537           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1538           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1539           0 :   if (!isNull) {
    1540           0 :     MOZ_ASSERT(cx);
    1541           0 :     object.emplace(cx, &val.toObject());
    1542           0 :     temp.emplace(cx);
    1543             :   }
    1544           0 :   if (!isNull) {
    1545           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->generator_id, temp.ptr())) {
    1546           0 :       return false;
    1547             :     }
    1548             :   }
    1549           0 :   if (!isNull && !temp->isUndefined()) {
    1550           0 :     if (temp.ref().isObject()) {
    1551           0 :       if (!mGenerator.Init(&temp.ref().toObject())) {
    1552           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "'generator' member of DhImportKeyParams", "Uint8Array");
    1553           0 :         return false;
    1554             :       }
    1555             :     } else {
    1556           0 :       ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'generator' member of DhImportKeyParams");
    1557           0 :       return false;
    1558             :     }
    1559           0 :     mIsAnyMemberPresent = true;
    1560           0 :   } else if (cx) {
    1561             :     // Don't error out if we have no cx.  In that
    1562             :     // situation the caller is default-constructing us and we'll
    1563             :     // just assume they know what they're doing.
    1564           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    1565           0 :                              "'generator' member of DhImportKeyParams");
    1566             :   }
    1567             : 
    1568           0 :   if (!isNull) {
    1569           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->prime_id, temp.ptr())) {
    1570           0 :       return false;
    1571             :     }
    1572             :   }
    1573           0 :   if (!isNull && !temp->isUndefined()) {
    1574           0 :     if (temp.ref().isObject()) {
    1575           0 :       if (!mPrime.Init(&temp.ref().toObject())) {
    1576           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "'prime' member of DhImportKeyParams", "Uint8Array");
    1577           0 :         return false;
    1578             :       }
    1579             :     } else {
    1580           0 :       ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'prime' member of DhImportKeyParams");
    1581           0 :       return false;
    1582             :     }
    1583           0 :     mIsAnyMemberPresent = true;
    1584           0 :   } else if (cx) {
    1585             :     // Don't error out if we have no cx.  In that
    1586             :     // situation the caller is default-constructing us and we'll
    1587             :     // just assume they know what they're doing.
    1588           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    1589           0 :                              "'prime' member of DhImportKeyParams");
    1590             :   }
    1591           0 :   return true;
    1592             : }
    1593             : 
    1594             : bool
    1595           0 : DhImportKeyParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1596             : {
    1597           0 :   DhImportKeyParamsAtoms* atomsCache = GetAtomCache<DhImportKeyParamsAtoms>(cx);
    1598           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1599           0 :     return false;
    1600             :   }
    1601             : 
    1602             :   // Per spec, we define the parent's members first
    1603           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    1604           0 :     return false;
    1605             :   }
    1606           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    1607             : 
    1608             :   do {
    1609             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1610           0 :     JS::Rooted<JS::Value> temp(cx);
    1611           0 :     Uint8Array const & currentValue = mGenerator;
    1612           0 :     temp.setObject(*currentValue.Obj());
    1613           0 :     if (!MaybeWrapNonDOMObjectValue(cx, &temp)) {
    1614           0 :       return false;
    1615             :     }
    1616           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->generator_id, temp, JSPROP_ENUMERATE)) {
    1617           0 :       return false;
    1618             :     }
    1619           0 :     break;
    1620             :   } while(0);
    1621             : 
    1622             :   do {
    1623             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1624           0 :     JS::Rooted<JS::Value> temp(cx);
    1625           0 :     Uint8Array const & currentValue = mPrime;
    1626           0 :     temp.setObject(*currentValue.Obj());
    1627           0 :     if (!MaybeWrapNonDOMObjectValue(cx, &temp)) {
    1628           0 :       return false;
    1629             :     }
    1630           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->prime_id, temp, JSPROP_ENUMERATE)) {
    1631           0 :       return false;
    1632             :     }
    1633           0 :     break;
    1634             :   } while(0);
    1635             : 
    1636           0 :   return true;
    1637             : }
    1638             : 
    1639             : void
    1640           0 : DhImportKeyParams::TraceDictionary(JSTracer* trc)
    1641             : {
    1642           0 :   Algorithm::TraceDictionary(trc);
    1643           0 :   mGenerator.TraceSelf(trc);
    1644             : 
    1645           0 :   mPrime.TraceSelf(trc);
    1646           0 : }
    1647             : 
    1648             : namespace binding_detail {
    1649             : } // namespace binding_detail
    1650             : 
    1651             : 
    1652             : 
    1653           0 : DhKeyDeriveParams::DhKeyDeriveParams()
    1654           0 :   : Algorithm(FastDictionaryInitializer())
    1655             : {
    1656             :   // Safe to pass a null context if we pass a null value
    1657           0 :   Init(nullptr, JS::NullHandleValue);
    1658           0 : }
    1659             : 
    1660             : 
    1661             : 
    1662             : bool
    1663           0 : DhKeyDeriveParams::InitIds(JSContext* cx, DhKeyDeriveParamsAtoms* atomsCache)
    1664             : {
    1665           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1666             : 
    1667             :   // Initialize these in reverse order so that any failure leaves the first one
    1668             :   // uninitialized.
    1669           0 :   if (!atomsCache->public_id.init(cx, "public")) {
    1670           0 :     return false;
    1671             :   }
    1672           0 :   return true;
    1673             : }
    1674             : 
    1675             : bool
    1676           0 : DhKeyDeriveParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1677             : {
    1678             :   // Passing a null JSContext is OK only if we're initing from null,
    1679             :   // Since in that case we will not have to do any property gets
    1680             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1681             :   // checkers by static analysis tools
    1682           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1683           0 :   DhKeyDeriveParamsAtoms* atomsCache = nullptr;
    1684           0 :   if (cx) {
    1685           0 :     atomsCache = GetAtomCache<DhKeyDeriveParamsAtoms>(cx);
    1686           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1687           0 :       return false;
    1688             :     }
    1689             :   }
    1690             : 
    1691             :   // Per spec, we init the parent's members first
    1692           0 :   if (!Algorithm::Init(cx, val)) {
    1693           0 :     return false;
    1694             :   }
    1695             : 
    1696           0 :   bool isNull = val.isNullOrUndefined();
    1697             :   // We only need these if !isNull, in which case we have |cx|.
    1698           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1699           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1700           0 :   if (!isNull) {
    1701           0 :     MOZ_ASSERT(cx);
    1702           0 :     object.emplace(cx, &val.toObject());
    1703           0 :     temp.emplace(cx);
    1704             :   }
    1705           0 :   if (!isNull) {
    1706           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->public_id, temp.ptr())) {
    1707           0 :       return false;
    1708             :     }
    1709             :   }
    1710           0 :   if (!isNull && !temp->isUndefined()) {
    1711           0 :     if (temp.ref().isObject()) {
    1712             :       static_assert(IsRefcounted<mozilla::dom::CryptoKey>::value, "We can only store refcounted classes.");{
    1713           0 :         nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(temp.ptr(), mPublic);
    1714           0 :         if (NS_FAILED(rv)) {
    1715           0 :           ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "'public' member of DhKeyDeriveParams", "CryptoKey");
    1716           0 :           return false;
    1717             :         }
    1718             :       }
    1719             :     } else {
    1720           0 :       ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'public' member of DhKeyDeriveParams");
    1721           0 :       return false;
    1722             :     }
    1723           0 :     mIsAnyMemberPresent = true;
    1724           0 :   } else if (cx) {
    1725             :     // Don't error out if we have no cx.  In that
    1726             :     // situation the caller is default-constructing us and we'll
    1727             :     // just assume they know what they're doing.
    1728           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    1729           0 :                              "'public' member of DhKeyDeriveParams");
    1730             :   }
    1731           0 :   return true;
    1732             : }
    1733             : 
    1734             : bool
    1735           0 : DhKeyDeriveParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1736             : {
    1737           0 :   DhKeyDeriveParamsAtoms* atomsCache = GetAtomCache<DhKeyDeriveParamsAtoms>(cx);
    1738           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1739           0 :     return false;
    1740             :   }
    1741             : 
    1742             :   // Per spec, we define the parent's members first
    1743           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    1744           0 :     return false;
    1745             :   }
    1746           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    1747             : 
    1748             :   do {
    1749             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1750           0 :     JS::Rooted<JS::Value> temp(cx);
    1751           0 :     OwningNonNull<mozilla::dom::CryptoKey> const & currentValue = mPublic;
    1752           0 :     if (!GetOrCreateDOMReflector(cx, currentValue, &temp)) {
    1753           0 :       MOZ_ASSERT(true || JS_IsExceptionPending(cx));
    1754           0 :       return false;
    1755             :     }
    1756           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->public_id, temp, JSPROP_ENUMERATE)) {
    1757           0 :       return false;
    1758             :     }
    1759           0 :     break;
    1760             :   } while(0);
    1761             : 
    1762           0 :   return true;
    1763             : }
    1764             : 
    1765             : void
    1766           0 : DhKeyDeriveParams::TraceDictionary(JSTracer* trc)
    1767             : {
    1768           0 :   Algorithm::TraceDictionary(trc);
    1769           0 : }
    1770             : 
    1771             : DhKeyDeriveParams&
    1772           0 : DhKeyDeriveParams::operator=(const DhKeyDeriveParams& aOther)
    1773             : {
    1774           0 :   Algorithm::operator=(aOther);
    1775           0 :   mPublic = aOther.mPublic;
    1776           0 :   return *this;
    1777             : }
    1778             : 
    1779             : namespace binding_detail {
    1780             : } // namespace binding_detail
    1781             : 
    1782             : 
    1783             : 
    1784           0 : DhKeyGenParams::DhKeyGenParams()
    1785           0 :   : Algorithm(FastDictionaryInitializer())
    1786             : {
    1787             :   // Safe to pass a null context if we pass a null value
    1788           0 :   Init(nullptr, JS::NullHandleValue);
    1789           0 : }
    1790             : 
    1791             : 
    1792             : bool
    1793           0 : DhKeyGenParams::InitIds(JSContext* cx, DhKeyGenParamsAtoms* atomsCache)
    1794             : {
    1795           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1796             : 
    1797             :   // Initialize these in reverse order so that any failure leaves the first one
    1798             :   // uninitialized.
    1799           0 :   if (!atomsCache->prime_id.init(cx, "prime") ||
    1800           0 :       !atomsCache->generator_id.init(cx, "generator")) {
    1801           0 :     return false;
    1802             :   }
    1803           0 :   return true;
    1804             : }
    1805             : 
    1806             : bool
    1807           0 : DhKeyGenParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1808             : {
    1809             :   // Passing a null JSContext is OK only if we're initing from null,
    1810             :   // Since in that case we will not have to do any property gets
    1811             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1812             :   // checkers by static analysis tools
    1813           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1814           0 :   DhKeyGenParamsAtoms* atomsCache = nullptr;
    1815           0 :   if (cx) {
    1816           0 :     atomsCache = GetAtomCache<DhKeyGenParamsAtoms>(cx);
    1817           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1818           0 :       return false;
    1819             :     }
    1820             :   }
    1821             : 
    1822             :   // Per spec, we init the parent's members first
    1823           0 :   if (!Algorithm::Init(cx, val)) {
    1824           0 :     return false;
    1825             :   }
    1826             : 
    1827           0 :   bool isNull = val.isNullOrUndefined();
    1828             :   // We only need these if !isNull, in which case we have |cx|.
    1829           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1830           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1831           0 :   if (!isNull) {
    1832           0 :     MOZ_ASSERT(cx);
    1833           0 :     object.emplace(cx, &val.toObject());
    1834           0 :     temp.emplace(cx);
    1835             :   }
    1836           0 :   if (!isNull) {
    1837           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->generator_id, temp.ptr())) {
    1838           0 :       return false;
    1839             :     }
    1840             :   }
    1841           0 :   if (!isNull && !temp->isUndefined()) {
    1842           0 :     if (temp.ref().isObject()) {
    1843           0 :       if (!mGenerator.Init(&temp.ref().toObject())) {
    1844           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "'generator' member of DhKeyGenParams", "Uint8Array");
    1845           0 :         return false;
    1846             :       }
    1847             :     } else {
    1848           0 :       ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'generator' member of DhKeyGenParams");
    1849           0 :       return false;
    1850             :     }
    1851           0 :     mIsAnyMemberPresent = true;
    1852           0 :   } else if (cx) {
    1853             :     // Don't error out if we have no cx.  In that
    1854             :     // situation the caller is default-constructing us and we'll
    1855             :     // just assume they know what they're doing.
    1856           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    1857           0 :                              "'generator' member of DhKeyGenParams");
    1858             :   }
    1859             : 
    1860           0 :   if (!isNull) {
    1861           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->prime_id, temp.ptr())) {
    1862           0 :       return false;
    1863             :     }
    1864             :   }
    1865           0 :   if (!isNull && !temp->isUndefined()) {
    1866           0 :     if (temp.ref().isObject()) {
    1867           0 :       if (!mPrime.Init(&temp.ref().toObject())) {
    1868           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "'prime' member of DhKeyGenParams", "Uint8Array");
    1869           0 :         return false;
    1870             :       }
    1871             :     } else {
    1872           0 :       ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'prime' member of DhKeyGenParams");
    1873           0 :       return false;
    1874             :     }
    1875           0 :     mIsAnyMemberPresent = true;
    1876           0 :   } else if (cx) {
    1877             :     // Don't error out if we have no cx.  In that
    1878             :     // situation the caller is default-constructing us and we'll
    1879             :     // just assume they know what they're doing.
    1880           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    1881           0 :                              "'prime' member of DhKeyGenParams");
    1882             :   }
    1883           0 :   return true;
    1884             : }
    1885             : 
    1886             : bool
    1887           0 : DhKeyGenParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1888             : {
    1889           0 :   DhKeyGenParamsAtoms* atomsCache = GetAtomCache<DhKeyGenParamsAtoms>(cx);
    1890           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1891           0 :     return false;
    1892             :   }
    1893             : 
    1894             :   // Per spec, we define the parent's members first
    1895           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    1896           0 :     return false;
    1897             :   }
    1898           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    1899             : 
    1900             :   do {
    1901             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1902           0 :     JS::Rooted<JS::Value> temp(cx);
    1903           0 :     Uint8Array const & currentValue = mGenerator;
    1904           0 :     temp.setObject(*currentValue.Obj());
    1905           0 :     if (!MaybeWrapNonDOMObjectValue(cx, &temp)) {
    1906           0 :       return false;
    1907             :     }
    1908           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->generator_id, temp, JSPROP_ENUMERATE)) {
    1909           0 :       return false;
    1910             :     }
    1911           0 :     break;
    1912             :   } while(0);
    1913             : 
    1914             :   do {
    1915             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1916           0 :     JS::Rooted<JS::Value> temp(cx);
    1917           0 :     Uint8Array const & currentValue = mPrime;
    1918           0 :     temp.setObject(*currentValue.Obj());
    1919           0 :     if (!MaybeWrapNonDOMObjectValue(cx, &temp)) {
    1920           0 :       return false;
    1921             :     }
    1922           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->prime_id, temp, JSPROP_ENUMERATE)) {
    1923           0 :       return false;
    1924             :     }
    1925           0 :     break;
    1926             :   } while(0);
    1927             : 
    1928           0 :   return true;
    1929             : }
    1930             : 
    1931             : void
    1932           0 : DhKeyGenParams::TraceDictionary(JSTracer* trc)
    1933             : {
    1934           0 :   Algorithm::TraceDictionary(trc);
    1935           0 :   mGenerator.TraceSelf(trc);
    1936             : 
    1937           0 :   mPrime.TraceSelf(trc);
    1938           0 : }
    1939             : 
    1940             : namespace binding_detail {
    1941             : } // namespace binding_detail
    1942             : 
    1943             : 
    1944             : 
    1945           0 : EcKeyGenParams::EcKeyGenParams()
    1946           0 :   : Algorithm(FastDictionaryInitializer())
    1947             : {
    1948             :   // Safe to pass a null context if we pass a null value
    1949           0 :   Init(nullptr, JS::NullHandleValue);
    1950           0 : }
    1951             : 
    1952             : 
    1953             : 
    1954             : bool
    1955           0 : EcKeyGenParams::InitIds(JSContext* cx, EcKeyGenParamsAtoms* atomsCache)
    1956             : {
    1957           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1958             : 
    1959             :   // Initialize these in reverse order so that any failure leaves the first one
    1960             :   // uninitialized.
    1961           0 :   if (!atomsCache->namedCurve_id.init(cx, "namedCurve")) {
    1962           0 :     return false;
    1963             :   }
    1964           0 :   return true;
    1965             : }
    1966             : 
    1967             : bool
    1968           0 : EcKeyGenParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1969             : {
    1970             :   // Passing a null JSContext is OK only if we're initing from null,
    1971             :   // Since in that case we will not have to do any property gets
    1972             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1973             :   // checkers by static analysis tools
    1974           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1975           0 :   EcKeyGenParamsAtoms* atomsCache = nullptr;
    1976           0 :   if (cx) {
    1977           0 :     atomsCache = GetAtomCache<EcKeyGenParamsAtoms>(cx);
    1978           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1979           0 :       return false;
    1980             :     }
    1981             :   }
    1982             : 
    1983             :   // Per spec, we init the parent's members first
    1984           0 :   if (!Algorithm::Init(cx, val)) {
    1985           0 :     return false;
    1986             :   }
    1987             : 
    1988           0 :   bool isNull = val.isNullOrUndefined();
    1989             :   // We only need these if !isNull, in which case we have |cx|.
    1990           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1991           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1992           0 :   if (!isNull) {
    1993           0 :     MOZ_ASSERT(cx);
    1994           0 :     object.emplace(cx, &val.toObject());
    1995           0 :     temp.emplace(cx);
    1996             :   }
    1997           0 :   if (!isNull) {
    1998           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->namedCurve_id, temp.ptr())) {
    1999           0 :       return false;
    2000             :     }
    2001             :   }
    2002           0 :   if (!isNull && !temp->isUndefined()) {
    2003           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mNamedCurve)) {
    2004           0 :       return false;
    2005             :     }
    2006           0 :     mIsAnyMemberPresent = true;
    2007           0 :   } else if (cx) {
    2008             :     // Don't error out if we have no cx.  In that
    2009             :     // situation the caller is default-constructing us and we'll
    2010             :     // just assume they know what they're doing.
    2011           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    2012           0 :                              "'namedCurve' member of EcKeyGenParams");
    2013             :   }
    2014           0 :   return true;
    2015             : }
    2016             : 
    2017             : bool
    2018           0 : EcKeyGenParams::Init(const nsAString& aJSON)
    2019             : {
    2020           0 :   AutoJSAPI jsapi;
    2021           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    2022           0 :   if (!cleanGlobal) {
    2023           0 :     return false;
    2024             :   }
    2025           0 :   if (!jsapi.Init(cleanGlobal)) {
    2026           0 :     return false;
    2027             :   }
    2028           0 :   JSContext* cx = jsapi.cx();
    2029           0 :   JS::Rooted<JS::Value> json(cx);
    2030           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    2031           0 :   NS_ENSURE_TRUE(ok, false);
    2032           0 :   return Init(cx, json);
    2033             : }
    2034             : 
    2035             : bool
    2036           0 : EcKeyGenParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    2037             : {
    2038           0 :   EcKeyGenParamsAtoms* atomsCache = GetAtomCache<EcKeyGenParamsAtoms>(cx);
    2039           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2040           0 :     return false;
    2041             :   }
    2042             : 
    2043             :   // Per spec, we define the parent's members first
    2044           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    2045           0 :     return false;
    2046             :   }
    2047           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    2048             : 
    2049             :   do {
    2050             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2051           0 :     JS::Rooted<JS::Value> temp(cx);
    2052           0 :     nsString const & currentValue = mNamedCurve;
    2053           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    2054           0 :       return false;
    2055             :     }
    2056           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->namedCurve_id, temp, JSPROP_ENUMERATE)) {
    2057           0 :       return false;
    2058             :     }
    2059           0 :     break;
    2060             :   } while(0);
    2061             : 
    2062           0 :   return true;
    2063             : }
    2064             : 
    2065             : bool
    2066           0 : EcKeyGenParams::ToJSON(nsAString& aJSON) const
    2067             : {
    2068           0 :   AutoJSAPI jsapi;
    2069           0 :   jsapi.Init();
    2070           0 :   JSContext *cx = jsapi.cx();
    2071             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    2072             :   // because we'll only be creating objects, in ways that have no
    2073             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    2074             :   // which likewise guarantees no side-effects for the sorts of
    2075             :   // things we will pass it.
    2076           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    2077           0 :   JS::Rooted<JS::Value> val(cx);
    2078           0 :   if (!ToObjectInternal(cx, &val)) {
    2079           0 :     return false;
    2080             :   }
    2081           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    2082           0 :   return StringifyToJSON(cx, obj, aJSON);
    2083             : }
    2084             : 
    2085             : void
    2086           0 : EcKeyGenParams::TraceDictionary(JSTracer* trc)
    2087             : {
    2088           0 :   Algorithm::TraceDictionary(trc);
    2089           0 : }
    2090             : 
    2091             : EcKeyGenParams&
    2092           0 : EcKeyGenParams::operator=(const EcKeyGenParams& aOther)
    2093             : {
    2094           0 :   Algorithm::operator=(aOther);
    2095           0 :   mNamedCurve = aOther.mNamedCurve;
    2096           0 :   return *this;
    2097             : }
    2098             : 
    2099             : namespace binding_detail {
    2100             : } // namespace binding_detail
    2101             : 
    2102             : 
    2103             : 
    2104           0 : EcKeyImportParams::EcKeyImportParams()
    2105           0 :   : Algorithm(FastDictionaryInitializer())
    2106             : {
    2107             :   // Safe to pass a null context if we pass a null value
    2108           0 :   Init(nullptr, JS::NullHandleValue);
    2109           0 : }
    2110             : 
    2111             : 
    2112             : 
    2113             : bool
    2114           0 : EcKeyImportParams::InitIds(JSContext* cx, EcKeyImportParamsAtoms* atomsCache)
    2115             : {
    2116           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    2117             : 
    2118             :   // Initialize these in reverse order so that any failure leaves the first one
    2119             :   // uninitialized.
    2120           0 :   if (!atomsCache->namedCurve_id.init(cx, "namedCurve")) {
    2121           0 :     return false;
    2122             :   }
    2123           0 :   return true;
    2124             : }
    2125             : 
    2126             : bool
    2127           0 : EcKeyImportParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    2128             : {
    2129             :   // Passing a null JSContext is OK only if we're initing from null,
    2130             :   // Since in that case we will not have to do any property gets
    2131             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    2132             :   // checkers by static analysis tools
    2133           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    2134           0 :   EcKeyImportParamsAtoms* atomsCache = nullptr;
    2135           0 :   if (cx) {
    2136           0 :     atomsCache = GetAtomCache<EcKeyImportParamsAtoms>(cx);
    2137           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2138           0 :       return false;
    2139             :     }
    2140             :   }
    2141             : 
    2142             :   // Per spec, we init the parent's members first
    2143           0 :   if (!Algorithm::Init(cx, val)) {
    2144           0 :     return false;
    2145             :   }
    2146             : 
    2147           0 :   bool isNull = val.isNullOrUndefined();
    2148             :   // We only need these if !isNull, in which case we have |cx|.
    2149           0 :   Maybe<JS::Rooted<JSObject *> > object;
    2150           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    2151           0 :   if (!isNull) {
    2152           0 :     MOZ_ASSERT(cx);
    2153           0 :     object.emplace(cx, &val.toObject());
    2154           0 :     temp.emplace(cx);
    2155             :   }
    2156           0 :   if (!isNull) {
    2157           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->namedCurve_id, temp.ptr())) {
    2158           0 :       return false;
    2159             :     }
    2160             :   }
    2161           0 :   if (!isNull && !temp->isUndefined()) {
    2162           0 :     mNamedCurve.Construct();
    2163           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mNamedCurve.Value()))) {
    2164           0 :       return false;
    2165             :     }
    2166           0 :     mIsAnyMemberPresent = true;
    2167             :   }
    2168           0 :   return true;
    2169             : }
    2170             : 
    2171             : bool
    2172           0 : EcKeyImportParams::Init(const nsAString& aJSON)
    2173             : {
    2174           0 :   AutoJSAPI jsapi;
    2175           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    2176           0 :   if (!cleanGlobal) {
    2177           0 :     return false;
    2178             :   }
    2179           0 :   if (!jsapi.Init(cleanGlobal)) {
    2180           0 :     return false;
    2181             :   }
    2182           0 :   JSContext* cx = jsapi.cx();
    2183           0 :   JS::Rooted<JS::Value> json(cx);
    2184           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    2185           0 :   NS_ENSURE_TRUE(ok, false);
    2186           0 :   return Init(cx, json);
    2187             : }
    2188             : 
    2189             : bool
    2190           0 : EcKeyImportParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    2191             : {
    2192           0 :   EcKeyImportParamsAtoms* atomsCache = GetAtomCache<EcKeyImportParamsAtoms>(cx);
    2193           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2194           0 :     return false;
    2195             :   }
    2196             : 
    2197             :   // Per spec, we define the parent's members first
    2198           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    2199           0 :     return false;
    2200             :   }
    2201           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    2202             : 
    2203           0 :   if (mNamedCurve.WasPassed()) {
    2204             :     do {
    2205             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2206           0 :       JS::Rooted<JS::Value> temp(cx);
    2207           0 :       nsString const & currentValue = mNamedCurve.InternalValue();
    2208           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    2209           0 :         return false;
    2210             :       }
    2211           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->namedCurve_id, temp, JSPROP_ENUMERATE)) {
    2212           0 :         return false;
    2213             :       }
    2214           0 :       break;
    2215             :     } while(0);
    2216             :   }
    2217             : 
    2218           0 :   return true;
    2219             : }
    2220             : 
    2221             : bool
    2222           0 : EcKeyImportParams::ToJSON(nsAString& aJSON) const
    2223             : {
    2224           0 :   AutoJSAPI jsapi;
    2225           0 :   jsapi.Init();
    2226           0 :   JSContext *cx = jsapi.cx();
    2227             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    2228             :   // because we'll only be creating objects, in ways that have no
    2229             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    2230             :   // which likewise guarantees no side-effects for the sorts of
    2231             :   // things we will pass it.
    2232           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    2233           0 :   JS::Rooted<JS::Value> val(cx);
    2234           0 :   if (!ToObjectInternal(cx, &val)) {
    2235           0 :     return false;
    2236             :   }
    2237           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    2238           0 :   return StringifyToJSON(cx, obj, aJSON);
    2239             : }
    2240             : 
    2241             : void
    2242           0 : EcKeyImportParams::TraceDictionary(JSTracer* trc)
    2243             : {
    2244           0 :   Algorithm::TraceDictionary(trc);
    2245           0 : }
    2246             : 
    2247             : EcKeyImportParams&
    2248           0 : EcKeyImportParams::operator=(const EcKeyImportParams& aOther)
    2249             : {
    2250           0 :   Algorithm::operator=(aOther);
    2251           0 :   mNamedCurve.Reset();
    2252           0 :   if (aOther.mNamedCurve.WasPassed()) {
    2253           0 :     mNamedCurve.Construct(aOther.mNamedCurve.Value());
    2254             :   }
    2255           0 :   return *this;
    2256             : }
    2257             : 
    2258             : namespace binding_detail {
    2259             : } // namespace binding_detail
    2260             : 
    2261             : 
    2262             : 
    2263           0 : EcdhKeyDeriveParams::EcdhKeyDeriveParams()
    2264           0 :   : Algorithm(FastDictionaryInitializer())
    2265             : {
    2266             :   // Safe to pass a null context if we pass a null value
    2267           0 :   Init(nullptr, JS::NullHandleValue);
    2268           0 : }
    2269             : 
    2270             : 
    2271             : 
    2272             : bool
    2273           0 : EcdhKeyDeriveParams::InitIds(JSContext* cx, EcdhKeyDeriveParamsAtoms* atomsCache)
    2274             : {
    2275           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    2276             : 
    2277             :   // Initialize these in reverse order so that any failure leaves the first one
    2278             :   // uninitialized.
    2279           0 :   if (!atomsCache->public_id.init(cx, "public")) {
    2280           0 :     return false;
    2281             :   }
    2282           0 :   return true;
    2283             : }
    2284             : 
    2285             : bool
    2286           0 : EcdhKeyDeriveParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    2287             : {
    2288             :   // Passing a null JSContext is OK only if we're initing from null,
    2289             :   // Since in that case we will not have to do any property gets
    2290             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    2291             :   // checkers by static analysis tools
    2292           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    2293           0 :   EcdhKeyDeriveParamsAtoms* atomsCache = nullptr;
    2294           0 :   if (cx) {
    2295           0 :     atomsCache = GetAtomCache<EcdhKeyDeriveParamsAtoms>(cx);
    2296           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2297           0 :       return false;
    2298             :     }
    2299             :   }
    2300             : 
    2301             :   // Per spec, we init the parent's members first
    2302           0 :   if (!Algorithm::Init(cx, val)) {
    2303           0 :     return false;
    2304             :   }
    2305             : 
    2306           0 :   bool isNull = val.isNullOrUndefined();
    2307             :   // We only need these if !isNull, in which case we have |cx|.
    2308           0 :   Maybe<JS::Rooted<JSObject *> > object;
    2309           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    2310           0 :   if (!isNull) {
    2311           0 :     MOZ_ASSERT(cx);
    2312           0 :     object.emplace(cx, &val.toObject());
    2313           0 :     temp.emplace(cx);
    2314             :   }
    2315           0 :   if (!isNull) {
    2316           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->public_id, temp.ptr())) {
    2317           0 :       return false;
    2318             :     }
    2319             :   }
    2320           0 :   if (!isNull && !temp->isUndefined()) {
    2321           0 :     if (temp.ref().isObject()) {
    2322             :       static_assert(IsRefcounted<mozilla::dom::CryptoKey>::value, "We can only store refcounted classes.");{
    2323           0 :         nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(temp.ptr(), mPublic);
    2324           0 :         if (NS_FAILED(rv)) {
    2325           0 :           ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "'public' member of EcdhKeyDeriveParams", "CryptoKey");
    2326           0 :           return false;
    2327             :         }
    2328             :       }
    2329             :     } else {
    2330           0 :       ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'public' member of EcdhKeyDeriveParams");
    2331           0 :       return false;
    2332             :     }
    2333           0 :     mIsAnyMemberPresent = true;
    2334           0 :   } else if (cx) {
    2335             :     // Don't error out if we have no cx.  In that
    2336             :     // situation the caller is default-constructing us and we'll
    2337             :     // just assume they know what they're doing.
    2338           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    2339           0 :                              "'public' member of EcdhKeyDeriveParams");
    2340             :   }
    2341           0 :   return true;
    2342             : }
    2343             : 
    2344             : bool
    2345           0 : EcdhKeyDeriveParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    2346             : {
    2347           0 :   EcdhKeyDeriveParamsAtoms* atomsCache = GetAtomCache<EcdhKeyDeriveParamsAtoms>(cx);
    2348           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2349           0 :     return false;
    2350             :   }
    2351             : 
    2352             :   // Per spec, we define the parent's members first
    2353           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    2354           0 :     return false;
    2355             :   }
    2356           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    2357             : 
    2358             :   do {
    2359             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2360           0 :     JS::Rooted<JS::Value> temp(cx);
    2361           0 :     OwningNonNull<mozilla::dom::CryptoKey> const & currentValue = mPublic;
    2362           0 :     if (!GetOrCreateDOMReflector(cx, currentValue, &temp)) {
    2363           0 :       MOZ_ASSERT(true || JS_IsExceptionPending(cx));
    2364           0 :       return false;
    2365             :     }
    2366           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->public_id, temp, JSPROP_ENUMERATE)) {
    2367           0 :       return false;
    2368             :     }
    2369           0 :     break;
    2370             :   } while(0);
    2371             : 
    2372           0 :   return true;
    2373             : }
    2374             : 
    2375             : void
    2376           0 : EcdhKeyDeriveParams::TraceDictionary(JSTracer* trc)
    2377             : {
    2378           0 :   Algorithm::TraceDictionary(trc);
    2379           0 : }
    2380             : 
    2381             : EcdhKeyDeriveParams&
    2382           0 : EcdhKeyDeriveParams::operator=(const EcdhKeyDeriveParams& aOther)
    2383             : {
    2384           0 :   Algorithm::operator=(aOther);
    2385           0 :   mPublic = aOther.mPublic;
    2386           0 :   return *this;
    2387             : }
    2388             : 
    2389             : namespace binding_detail {
    2390             : } // namespace binding_detail
    2391             : 
    2392             : 
    2393             : 
    2394           0 : EcdsaParams::EcdsaParams()
    2395           0 :   : Algorithm(FastDictionaryInitializer())
    2396             : {
    2397             :   // Safe to pass a null context if we pass a null value
    2398           0 :   Init(nullptr, JS::NullHandleValue);
    2399           0 : }
    2400             : 
    2401             : 
    2402             : bool
    2403           0 : EcdsaParams::InitIds(JSContext* cx, EcdsaParamsAtoms* atomsCache)
    2404             : {
    2405           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    2406             : 
    2407             :   // Initialize these in reverse order so that any failure leaves the first one
    2408             :   // uninitialized.
    2409           0 :   if (!atomsCache->hash_id.init(cx, "hash")) {
    2410           0 :     return false;
    2411             :   }
    2412           0 :   return true;
    2413             : }
    2414             : 
    2415             : bool
    2416           0 : EcdsaParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    2417             : {
    2418             :   // Passing a null JSContext is OK only if we're initing from null,
    2419             :   // Since in that case we will not have to do any property gets
    2420             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    2421             :   // checkers by static analysis tools
    2422           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    2423           0 :   EcdsaParamsAtoms* atomsCache = nullptr;
    2424           0 :   if (cx) {
    2425           0 :     atomsCache = GetAtomCache<EcdsaParamsAtoms>(cx);
    2426           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2427           0 :       return false;
    2428             :     }
    2429             :   }
    2430             : 
    2431             :   // Per spec, we init the parent's members first
    2432           0 :   if (!Algorithm::Init(cx, val)) {
    2433           0 :     return false;
    2434             :   }
    2435             : 
    2436           0 :   bool isNull = val.isNullOrUndefined();
    2437             :   // We only need these if !isNull, in which case we have |cx|.
    2438           0 :   Maybe<JS::Rooted<JSObject *> > object;
    2439           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    2440           0 :   if (!isNull) {
    2441           0 :     MOZ_ASSERT(cx);
    2442           0 :     object.emplace(cx, &val.toObject());
    2443           0 :     temp.emplace(cx);
    2444             :   }
    2445           0 :   if (!isNull) {
    2446           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->hash_id, temp.ptr())) {
    2447           0 :       return false;
    2448             :     }
    2449             :   }
    2450           0 :   if (!isNull && !temp->isUndefined()) {
    2451             :     {
    2452           0 :       bool done = false, failed = false, tryNext;
    2453           0 :       if (temp.ref().isObject()) {
    2454           0 :         if (!mHash.SetToObject(cx, &temp.ref().toObject(), passedToJSImpl)) {
    2455           0 :           return false;
    2456             :         }
    2457           0 :         done = true;
    2458             :       } else {
    2459             :         do {
    2460           0 :           done = (failed = !mHash.TrySetToString(cx, temp.ref(), tryNext)) || !tryNext;
    2461           0 :           break;
    2462             :         } while (0);
    2463             :       }
    2464           0 :       if (failed) {
    2465           0 :         return false;
    2466             :       }
    2467           0 :       if (!done) {
    2468           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'hash' member of EcdsaParams", "Object");
    2469           0 :         return false;
    2470             :       }
    2471             :     }
    2472           0 :     mIsAnyMemberPresent = true;
    2473           0 :   } else if (cx) {
    2474             :     // Don't error out if we have no cx.  In that
    2475             :     // situation the caller is default-constructing us and we'll
    2476             :     // just assume they know what they're doing.
    2477           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    2478           0 :                              "'hash' member of EcdsaParams");
    2479             :   }
    2480           0 :   return true;
    2481             : }
    2482             : 
    2483             : bool
    2484           0 : EcdsaParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    2485             : {
    2486           0 :   EcdsaParamsAtoms* atomsCache = GetAtomCache<EcdsaParamsAtoms>(cx);
    2487           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2488           0 :     return false;
    2489             :   }
    2490             : 
    2491             :   // Per spec, we define the parent's members first
    2492           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    2493           0 :     return false;
    2494             :   }
    2495           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    2496             : 
    2497             :   do {
    2498             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2499           0 :     JS::Rooted<JS::Value> temp(cx);
    2500           0 :     OwningObjectOrString const & currentValue = mHash;
    2501           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
    2502           0 :       return false;
    2503             :     }
    2504           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->hash_id, temp, JSPROP_ENUMERATE)) {
    2505           0 :       return false;
    2506             :     }
    2507           0 :     break;
    2508             :   } while(0);
    2509             : 
    2510           0 :   return true;
    2511             : }
    2512             : 
    2513             : void
    2514           0 : EcdsaParams::TraceDictionary(JSTracer* trc)
    2515             : {
    2516           0 :   Algorithm::TraceDictionary(trc);
    2517           0 :   mHash.TraceUnion(trc);
    2518           0 : }
    2519             : 
    2520             : namespace binding_detail {
    2521             : } // namespace binding_detail
    2522             : 
    2523             : 
    2524             : 
    2525           0 : HkdfParams::HkdfParams()
    2526           0 :   : Algorithm(FastDictionaryInitializer())
    2527             : {
    2528             :   // Safe to pass a null context if we pass a null value
    2529           0 :   Init(nullptr, JS::NullHandleValue);
    2530           0 : }
    2531             : 
    2532             : 
    2533             : bool
    2534           0 : HkdfParams::InitIds(JSContext* cx, HkdfParamsAtoms* atomsCache)
    2535             : {
    2536           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    2537             : 
    2538             :   // Initialize these in reverse order so that any failure leaves the first one
    2539             :   // uninitialized.
    2540           0 :   if (!atomsCache->salt_id.init(cx, "salt") ||
    2541           0 :       !atomsCache->info_id.init(cx, "info") ||
    2542           0 :       !atomsCache->hash_id.init(cx, "hash")) {
    2543           0 :     return false;
    2544             :   }
    2545           0 :   return true;
    2546             : }
    2547             : 
    2548             : bool
    2549           0 : HkdfParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    2550             : {
    2551             :   // Passing a null JSContext is OK only if we're initing from null,
    2552             :   // Since in that case we will not have to do any property gets
    2553             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    2554             :   // checkers by static analysis tools
    2555           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    2556           0 :   HkdfParamsAtoms* atomsCache = nullptr;
    2557           0 :   if (cx) {
    2558           0 :     atomsCache = GetAtomCache<HkdfParamsAtoms>(cx);
    2559           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2560           0 :       return false;
    2561             :     }
    2562             :   }
    2563             : 
    2564             :   // Per spec, we init the parent's members first
    2565           0 :   if (!Algorithm::Init(cx, val)) {
    2566           0 :     return false;
    2567             :   }
    2568             : 
    2569           0 :   bool isNull = val.isNullOrUndefined();
    2570             :   // We only need these if !isNull, in which case we have |cx|.
    2571           0 :   Maybe<JS::Rooted<JSObject *> > object;
    2572           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    2573           0 :   if (!isNull) {
    2574           0 :     MOZ_ASSERT(cx);
    2575           0 :     object.emplace(cx, &val.toObject());
    2576           0 :     temp.emplace(cx);
    2577             :   }
    2578           0 :   if (!isNull) {
    2579           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->hash_id, temp.ptr())) {
    2580           0 :       return false;
    2581             :     }
    2582             :   }
    2583           0 :   if (!isNull && !temp->isUndefined()) {
    2584             :     {
    2585           0 :       bool done = false, failed = false, tryNext;
    2586           0 :       if (temp.ref().isObject()) {
    2587           0 :         if (!mHash.SetToObject(cx, &temp.ref().toObject(), passedToJSImpl)) {
    2588           0 :           return false;
    2589             :         }
    2590           0 :         done = true;
    2591             :       } else {
    2592             :         do {
    2593           0 :           done = (failed = !mHash.TrySetToString(cx, temp.ref(), tryNext)) || !tryNext;
    2594           0 :           break;
    2595             :         } while (0);
    2596             :       }
    2597           0 :       if (failed) {
    2598           0 :         return false;
    2599             :       }
    2600           0 :       if (!done) {
    2601           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'hash' member of HkdfParams", "Object");
    2602           0 :         return false;
    2603             :       }
    2604             :     }
    2605           0 :     mIsAnyMemberPresent = true;
    2606           0 :   } else if (cx) {
    2607             :     // Don't error out if we have no cx.  In that
    2608             :     // situation the caller is default-constructing us and we'll
    2609             :     // just assume they know what they're doing.
    2610           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    2611           0 :                              "'hash' member of HkdfParams");
    2612             :   }
    2613             : 
    2614           0 :   if (!isNull) {
    2615           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->info_id, temp.ptr())) {
    2616           0 :       return false;
    2617             :     }
    2618             :   }
    2619           0 :   if (!isNull && !temp->isUndefined()) {
    2620             :     {
    2621           0 :       bool done = false, failed = false, tryNext;
    2622           0 :       if (temp.ref().isObject()) {
    2623           0 :         done = (failed = !mInfo.TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
    2624           0 :                (failed = !mInfo.TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
    2625             : 
    2626             :       }
    2627           0 :       if (failed) {
    2628           0 :         return false;
    2629             :       }
    2630           0 :       if (!done) {
    2631           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'info' member of HkdfParams", "ArrayBufferView, ArrayBuffer");
    2632           0 :         return false;
    2633             :       }
    2634             :     }
    2635           0 :     mIsAnyMemberPresent = true;
    2636           0 :   } else if (cx) {
    2637             :     // Don't error out if we have no cx.  In that
    2638             :     // situation the caller is default-constructing us and we'll
    2639             :     // just assume they know what they're doing.
    2640           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    2641           0 :                              "'info' member of HkdfParams");
    2642             :   }
    2643             : 
    2644           0 :   if (!isNull) {
    2645           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->salt_id, temp.ptr())) {
    2646           0 :       return false;
    2647             :     }
    2648             :   }
    2649           0 :   if (!isNull && !temp->isUndefined()) {
    2650             :     {
    2651           0 :       bool done = false, failed = false, tryNext;
    2652           0 :       if (temp.ref().isObject()) {
    2653           0 :         done = (failed = !mSalt.TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
    2654           0 :                (failed = !mSalt.TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
    2655             : 
    2656             :       }
    2657           0 :       if (failed) {
    2658           0 :         return false;
    2659             :       }
    2660           0 :       if (!done) {
    2661           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'salt' member of HkdfParams", "ArrayBufferView, ArrayBuffer");
    2662           0 :         return false;
    2663             :       }
    2664             :     }
    2665           0 :     mIsAnyMemberPresent = true;
    2666           0 :   } else if (cx) {
    2667             :     // Don't error out if we have no cx.  In that
    2668             :     // situation the caller is default-constructing us and we'll
    2669             :     // just assume they know what they're doing.
    2670           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    2671           0 :                              "'salt' member of HkdfParams");
    2672             :   }
    2673           0 :   return true;
    2674             : }
    2675             : 
    2676             : bool
    2677           0 : HkdfParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    2678             : {
    2679           0 :   HkdfParamsAtoms* atomsCache = GetAtomCache<HkdfParamsAtoms>(cx);
    2680           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2681           0 :     return false;
    2682             :   }
    2683             : 
    2684             :   // Per spec, we define the parent's members first
    2685           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    2686           0 :     return false;
    2687             :   }
    2688           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    2689             : 
    2690             :   do {
    2691             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2692           0 :     JS::Rooted<JS::Value> temp(cx);
    2693           0 :     OwningObjectOrString const & currentValue = mHash;
    2694           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
    2695           0 :       return false;
    2696             :     }
    2697           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->hash_id, temp, JSPROP_ENUMERATE)) {
    2698           0 :       return false;
    2699             :     }
    2700           0 :     break;
    2701             :   } while(0);
    2702             : 
    2703             :   do {
    2704             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2705           0 :     JS::Rooted<JS::Value> temp(cx);
    2706           0 :     OwningArrayBufferViewOrArrayBuffer const & currentValue = mInfo;
    2707           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
    2708           0 :       return false;
    2709             :     }
    2710           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->info_id, temp, JSPROP_ENUMERATE)) {
    2711           0 :       return false;
    2712             :     }
    2713           0 :     break;
    2714             :   } while(0);
    2715             : 
    2716             :   do {
    2717             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2718           0 :     JS::Rooted<JS::Value> temp(cx);
    2719           0 :     OwningArrayBufferViewOrArrayBuffer const & currentValue = mSalt;
    2720           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
    2721           0 :       return false;
    2722             :     }
    2723           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->salt_id, temp, JSPROP_ENUMERATE)) {
    2724           0 :       return false;
    2725             :     }
    2726           0 :     break;
    2727             :   } while(0);
    2728             : 
    2729           0 :   return true;
    2730             : }
    2731             : 
    2732             : void
    2733           0 : HkdfParams::TraceDictionary(JSTracer* trc)
    2734             : {
    2735           0 :   Algorithm::TraceDictionary(trc);
    2736           0 :   mHash.TraceUnion(trc);
    2737             : 
    2738           0 :   mInfo.TraceUnion(trc);
    2739             : 
    2740           0 :   mSalt.TraceUnion(trc);
    2741           0 : }
    2742             : 
    2743             : namespace binding_detail {
    2744             : } // namespace binding_detail
    2745             : 
    2746             : 
    2747             : 
    2748           0 : HmacImportParams::HmacImportParams()
    2749           0 :   : Algorithm(FastDictionaryInitializer())
    2750             : {
    2751             :   // Safe to pass a null context if we pass a null value
    2752           0 :   Init(nullptr, JS::NullHandleValue);
    2753           0 : }
    2754             : 
    2755             : 
    2756             : bool
    2757           0 : HmacImportParams::InitIds(JSContext* cx, HmacImportParamsAtoms* atomsCache)
    2758             : {
    2759           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    2760             : 
    2761             :   // Initialize these in reverse order so that any failure leaves the first one
    2762             :   // uninitialized.
    2763           0 :   if (!atomsCache->hash_id.init(cx, "hash")) {
    2764           0 :     return false;
    2765             :   }
    2766           0 :   return true;
    2767             : }
    2768             : 
    2769             : bool
    2770           0 : HmacImportParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    2771             : {
    2772             :   // Passing a null JSContext is OK only if we're initing from null,
    2773             :   // Since in that case we will not have to do any property gets
    2774             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    2775             :   // checkers by static analysis tools
    2776           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    2777           0 :   HmacImportParamsAtoms* atomsCache = nullptr;
    2778           0 :   if (cx) {
    2779           0 :     atomsCache = GetAtomCache<HmacImportParamsAtoms>(cx);
    2780           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2781           0 :       return false;
    2782             :     }
    2783             :   }
    2784             : 
    2785             :   // Per spec, we init the parent's members first
    2786           0 :   if (!Algorithm::Init(cx, val)) {
    2787           0 :     return false;
    2788             :   }
    2789             : 
    2790           0 :   bool isNull = val.isNullOrUndefined();
    2791             :   // We only need these if !isNull, in which case we have |cx|.
    2792           0 :   Maybe<JS::Rooted<JSObject *> > object;
    2793           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    2794           0 :   if (!isNull) {
    2795           0 :     MOZ_ASSERT(cx);
    2796           0 :     object.emplace(cx, &val.toObject());
    2797           0 :     temp.emplace(cx);
    2798             :   }
    2799           0 :   if (!isNull) {
    2800           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->hash_id, temp.ptr())) {
    2801           0 :       return false;
    2802             :     }
    2803             :   }
    2804           0 :   if (!isNull && !temp->isUndefined()) {
    2805             :     {
    2806           0 :       bool done = false, failed = false, tryNext;
    2807           0 :       if (temp.ref().isObject()) {
    2808           0 :         if (!mHash.SetToObject(cx, &temp.ref().toObject(), passedToJSImpl)) {
    2809           0 :           return false;
    2810             :         }
    2811           0 :         done = true;
    2812             :       } else {
    2813             :         do {
    2814           0 :           done = (failed = !mHash.TrySetToString(cx, temp.ref(), tryNext)) || !tryNext;
    2815           0 :           break;
    2816             :         } while (0);
    2817             :       }
    2818           0 :       if (failed) {
    2819           0 :         return false;
    2820             :       }
    2821           0 :       if (!done) {
    2822           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'hash' member of HmacImportParams", "Object");
    2823           0 :         return false;
    2824             :       }
    2825             :     }
    2826           0 :     mIsAnyMemberPresent = true;
    2827           0 :   } else if (cx) {
    2828             :     // Don't error out if we have no cx.  In that
    2829             :     // situation the caller is default-constructing us and we'll
    2830             :     // just assume they know what they're doing.
    2831           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    2832           0 :                              "'hash' member of HmacImportParams");
    2833             :   }
    2834           0 :   return true;
    2835             : }
    2836             : 
    2837             : bool
    2838           0 : HmacImportParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    2839             : {
    2840           0 :   HmacImportParamsAtoms* atomsCache = GetAtomCache<HmacImportParamsAtoms>(cx);
    2841           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2842           0 :     return false;
    2843             :   }
    2844             : 
    2845             :   // Per spec, we define the parent's members first
    2846           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    2847           0 :     return false;
    2848             :   }
    2849           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    2850             : 
    2851             :   do {
    2852             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2853           0 :     JS::Rooted<JS::Value> temp(cx);
    2854           0 :     OwningObjectOrString const & currentValue = mHash;
    2855           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
    2856           0 :       return false;
    2857             :     }
    2858           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->hash_id, temp, JSPROP_ENUMERATE)) {
    2859           0 :       return false;
    2860             :     }
    2861           0 :     break;
    2862             :   } while(0);
    2863             : 
    2864           0 :   return true;
    2865             : }
    2866             : 
    2867             : void
    2868           0 : HmacImportParams::TraceDictionary(JSTracer* trc)
    2869             : {
    2870           0 :   Algorithm::TraceDictionary(trc);
    2871           0 :   mHash.TraceUnion(trc);
    2872           0 : }
    2873             : 
    2874             : namespace binding_detail {
    2875             : } // namespace binding_detail
    2876             : 
    2877             : 
    2878             : 
    2879           0 : HmacKeyGenParams::HmacKeyGenParams()
    2880           0 :   : Algorithm(FastDictionaryInitializer())
    2881             : {
    2882             :   // Safe to pass a null context if we pass a null value
    2883           0 :   Init(nullptr, JS::NullHandleValue);
    2884           0 : }
    2885             : 
    2886             : 
    2887             : bool
    2888           0 : HmacKeyGenParams::InitIds(JSContext* cx, HmacKeyGenParamsAtoms* atomsCache)
    2889             : {
    2890           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    2891             : 
    2892             :   // Initialize these in reverse order so that any failure leaves the first one
    2893             :   // uninitialized.
    2894           0 :   if (!atomsCache->length_id.init(cx, "length") ||
    2895           0 :       !atomsCache->hash_id.init(cx, "hash")) {
    2896           0 :     return false;
    2897             :   }
    2898           0 :   return true;
    2899             : }
    2900             : 
    2901             : bool
    2902           0 : HmacKeyGenParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    2903             : {
    2904             :   // Passing a null JSContext is OK only if we're initing from null,
    2905             :   // Since in that case we will not have to do any property gets
    2906             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    2907             :   // checkers by static analysis tools
    2908           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    2909           0 :   HmacKeyGenParamsAtoms* atomsCache = nullptr;
    2910           0 :   if (cx) {
    2911           0 :     atomsCache = GetAtomCache<HmacKeyGenParamsAtoms>(cx);
    2912           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2913           0 :       return false;
    2914             :     }
    2915             :   }
    2916             : 
    2917             :   // Per spec, we init the parent's members first
    2918           0 :   if (!Algorithm::Init(cx, val)) {
    2919           0 :     return false;
    2920             :   }
    2921             : 
    2922           0 :   bool isNull = val.isNullOrUndefined();
    2923             :   // We only need these if !isNull, in which case we have |cx|.
    2924           0 :   Maybe<JS::Rooted<JSObject *> > object;
    2925           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    2926           0 :   if (!isNull) {
    2927           0 :     MOZ_ASSERT(cx);
    2928           0 :     object.emplace(cx, &val.toObject());
    2929           0 :     temp.emplace(cx);
    2930             :   }
    2931           0 :   if (!isNull) {
    2932           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->hash_id, temp.ptr())) {
    2933           0 :       return false;
    2934             :     }
    2935             :   }
    2936           0 :   if (!isNull && !temp->isUndefined()) {
    2937             :     {
    2938           0 :       bool done = false, failed = false, tryNext;
    2939           0 :       if (temp.ref().isObject()) {
    2940           0 :         if (!mHash.SetToObject(cx, &temp.ref().toObject(), passedToJSImpl)) {
    2941           0 :           return false;
    2942             :         }
    2943           0 :         done = true;
    2944             :       } else {
    2945             :         do {
    2946           0 :           done = (failed = !mHash.TrySetToString(cx, temp.ref(), tryNext)) || !tryNext;
    2947           0 :           break;
    2948             :         } while (0);
    2949             :       }
    2950           0 :       if (failed) {
    2951           0 :         return false;
    2952             :       }
    2953           0 :       if (!done) {
    2954           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'hash' member of HmacKeyGenParams", "Object");
    2955           0 :         return false;
    2956             :       }
    2957             :     }
    2958           0 :     mIsAnyMemberPresent = true;
    2959           0 :   } else if (cx) {
    2960             :     // Don't error out if we have no cx.  In that
    2961             :     // situation the caller is default-constructing us and we'll
    2962             :     // just assume they know what they're doing.
    2963           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    2964           0 :                              "'hash' member of HmacKeyGenParams");
    2965             :   }
    2966             : 
    2967           0 :   if (!isNull) {
    2968           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->length_id, temp.ptr())) {
    2969           0 :       return false;
    2970             :     }
    2971             :   }
    2972           0 :   if (!isNull && !temp->isUndefined()) {
    2973           0 :     mLength.Construct();
    2974           0 :     if (!ValueToPrimitive<uint32_t, eEnforceRange>(cx, temp.ref(), &(mLength.Value()))) {
    2975           0 :       return false;
    2976             :     }
    2977           0 :     mIsAnyMemberPresent = true;
    2978             :   }
    2979           0 :   return true;
    2980             : }
    2981             : 
    2982             : bool
    2983           0 : HmacKeyGenParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    2984             : {
    2985           0 :   HmacKeyGenParamsAtoms* atomsCache = GetAtomCache<HmacKeyGenParamsAtoms>(cx);
    2986           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    2987           0 :     return false;
    2988             :   }
    2989             : 
    2990             :   // Per spec, we define the parent's members first
    2991           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    2992           0 :     return false;
    2993             :   }
    2994           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    2995             : 
    2996             :   do {
    2997             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    2998           0 :     JS::Rooted<JS::Value> temp(cx);
    2999           0 :     OwningObjectOrString const & currentValue = mHash;
    3000           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
    3001           0 :       return false;
    3002             :     }
    3003           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->hash_id, temp, JSPROP_ENUMERATE)) {
    3004           0 :       return false;
    3005             :     }
    3006           0 :     break;
    3007             :   } while(0);
    3008             : 
    3009           0 :   if (mLength.WasPassed()) {
    3010             :     do {
    3011             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3012           0 :       JS::Rooted<JS::Value> temp(cx);
    3013           0 :       uint32_t const & currentValue = mLength.InternalValue();
    3014           0 :       temp.setNumber(currentValue);
    3015           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->length_id, temp, JSPROP_ENUMERATE)) {
    3016           0 :         return false;
    3017             :       }
    3018           0 :       break;
    3019             :     } while(0);
    3020             :   }
    3021             : 
    3022           0 :   return true;
    3023             : }
    3024             : 
    3025             : void
    3026           0 : HmacKeyGenParams::TraceDictionary(JSTracer* trc)
    3027             : {
    3028           0 :   Algorithm::TraceDictionary(trc);
    3029           0 :   mHash.TraceUnion(trc);
    3030           0 : }
    3031             : 
    3032             : namespace binding_detail {
    3033             : } // namespace binding_detail
    3034             : 
    3035             : 
    3036             : 
    3037           0 : JsonWebKey::JsonWebKey()
    3038             : {
    3039             :   // Safe to pass a null context if we pass a null value
    3040           0 :   Init(nullptr, JS::NullHandleValue);
    3041           0 : }
    3042             : 
    3043             : 
    3044             : 
    3045             : bool
    3046           0 : JsonWebKey::InitIds(JSContext* cx, JsonWebKeyAtoms* atomsCache)
    3047             : {
    3048           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    3049             : 
    3050             :   // Initialize these in reverse order so that any failure leaves the first one
    3051             :   // uninitialized.
    3052           0 :   if (!atomsCache->y_id.init(cx, "y") ||
    3053           0 :       !atomsCache->x_id.init(cx, "x") ||
    3054           0 :       !atomsCache->use_id.init(cx, "use") ||
    3055           0 :       !atomsCache->qi_id.init(cx, "qi") ||
    3056           0 :       !atomsCache->q_id.init(cx, "q") ||
    3057           0 :       !atomsCache->p_id.init(cx, "p") ||
    3058           0 :       !atomsCache->oth_id.init(cx, "oth") ||
    3059           0 :       !atomsCache->n_id.init(cx, "n") ||
    3060           0 :       !atomsCache->kty_id.init(cx, "kty") ||
    3061           0 :       !atomsCache->key_ops_id.init(cx, "key_ops") ||
    3062           0 :       !atomsCache->k_id.init(cx, "k") ||
    3063           0 :       !atomsCache->ext_id.init(cx, "ext") ||
    3064           0 :       !atomsCache->e_id.init(cx, "e") ||
    3065           0 :       !atomsCache->dq_id.init(cx, "dq") ||
    3066           0 :       !atomsCache->dp_id.init(cx, "dp") ||
    3067           0 :       !atomsCache->d_id.init(cx, "d") ||
    3068           0 :       !atomsCache->crv_id.init(cx, "crv") ||
    3069           0 :       !atomsCache->alg_id.init(cx, "alg")) {
    3070           0 :     return false;
    3071             :   }
    3072           0 :   return true;
    3073             : }
    3074             : 
    3075             : bool
    3076           0 : JsonWebKey::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    3077             : {
    3078             :   // Passing a null JSContext is OK only if we're initing from null,
    3079             :   // Since in that case we will not have to do any property gets
    3080             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    3081             :   // checkers by static analysis tools
    3082           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    3083           0 :   JsonWebKeyAtoms* atomsCache = nullptr;
    3084           0 :   if (cx) {
    3085           0 :     atomsCache = GetAtomCache<JsonWebKeyAtoms>(cx);
    3086           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    3087           0 :       return false;
    3088             :     }
    3089             :   }
    3090             : 
    3091           0 :   if (!IsConvertibleToDictionary(val)) {
    3092           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    3093             :   }
    3094             : 
    3095           0 :   bool isNull = val.isNullOrUndefined();
    3096             :   // We only need these if !isNull, in which case we have |cx|.
    3097           0 :   Maybe<JS::Rooted<JSObject *> > object;
    3098           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    3099           0 :   if (!isNull) {
    3100           0 :     MOZ_ASSERT(cx);
    3101           0 :     object.emplace(cx, &val.toObject());
    3102           0 :     temp.emplace(cx);
    3103             :   }
    3104           0 :   if (!isNull) {
    3105           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->alg_id, temp.ptr())) {
    3106           0 :       return false;
    3107             :     }
    3108             :   }
    3109           0 :   if (!isNull && !temp->isUndefined()) {
    3110           0 :     mAlg.Construct();
    3111           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mAlg.Value()))) {
    3112           0 :       return false;
    3113             :     }
    3114           0 :     mIsAnyMemberPresent = true;
    3115             :   }
    3116             : 
    3117           0 :   if (!isNull) {
    3118           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->crv_id, temp.ptr())) {
    3119           0 :       return false;
    3120             :     }
    3121             :   }
    3122           0 :   if (!isNull && !temp->isUndefined()) {
    3123           0 :     mCrv.Construct();
    3124           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mCrv.Value()))) {
    3125           0 :       return false;
    3126             :     }
    3127           0 :     mIsAnyMemberPresent = true;
    3128             :   }
    3129             : 
    3130           0 :   if (!isNull) {
    3131           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->d_id, temp.ptr())) {
    3132           0 :       return false;
    3133             :     }
    3134             :   }
    3135           0 :   if (!isNull && !temp->isUndefined()) {
    3136           0 :     mD.Construct();
    3137           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mD.Value()))) {
    3138           0 :       return false;
    3139             :     }
    3140           0 :     mIsAnyMemberPresent = true;
    3141             :   }
    3142             : 
    3143           0 :   if (!isNull) {
    3144           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->dp_id, temp.ptr())) {
    3145           0 :       return false;
    3146             :     }
    3147             :   }
    3148           0 :   if (!isNull && !temp->isUndefined()) {
    3149           0 :     mDp.Construct();
    3150           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mDp.Value()))) {
    3151           0 :       return false;
    3152             :     }
    3153           0 :     mIsAnyMemberPresent = true;
    3154             :   }
    3155             : 
    3156           0 :   if (!isNull) {
    3157           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->dq_id, temp.ptr())) {
    3158           0 :       return false;
    3159             :     }
    3160             :   }
    3161           0 :   if (!isNull && !temp->isUndefined()) {
    3162           0 :     mDq.Construct();
    3163           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mDq.Value()))) {
    3164           0 :       return false;
    3165             :     }
    3166           0 :     mIsAnyMemberPresent = true;
    3167             :   }
    3168             : 
    3169           0 :   if (!isNull) {
    3170           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->e_id, temp.ptr())) {
    3171           0 :       return false;
    3172             :     }
    3173             :   }
    3174           0 :   if (!isNull && !temp->isUndefined()) {
    3175           0 :     mE.Construct();
    3176           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mE.Value()))) {
    3177           0 :       return false;
    3178             :     }
    3179           0 :     mIsAnyMemberPresent = true;
    3180             :   }
    3181             : 
    3182           0 :   if (!isNull) {
    3183           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->ext_id, temp.ptr())) {
    3184           0 :       return false;
    3185             :     }
    3186             :   }
    3187           0 :   if (!isNull && !temp->isUndefined()) {
    3188           0 :     mExt.Construct();
    3189           0 :     if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mExt.Value()))) {
    3190           0 :       return false;
    3191             :     }
    3192           0 :     mIsAnyMemberPresent = true;
    3193             :   }
    3194             : 
    3195           0 :   if (!isNull) {
    3196           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->k_id, temp.ptr())) {
    3197           0 :       return false;
    3198             :     }
    3199             :   }
    3200           0 :   if (!isNull && !temp->isUndefined()) {
    3201           0 :     mK.Construct();
    3202           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mK.Value()))) {
    3203           0 :       return false;
    3204             :     }
    3205           0 :     mIsAnyMemberPresent = true;
    3206             :   }
    3207             : 
    3208           0 :   if (!isNull) {
    3209           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->key_ops_id, temp.ptr())) {
    3210           0 :       return false;
    3211             :     }
    3212             :   }
    3213           0 :   if (!isNull && !temp->isUndefined()) {
    3214           0 :     mKey_ops.Construct();
    3215           0 :     if (temp.ref().isObject()) {
    3216           0 :       JS::ForOfIterator iter(cx);
    3217           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    3218           0 :         return false;
    3219             :       }
    3220           0 :       if (!iter.valueIsIterable()) {
    3221           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'key_ops' member of JsonWebKey");
    3222           0 :         return false;
    3223             :       }
    3224           0 :       Sequence<nsString> &arr = (mKey_ops.Value());
    3225           0 :       JS::Rooted<JS::Value> temp(cx);
    3226             :       while (true) {
    3227             :         bool done;
    3228           0 :         if (!iter.next(&temp, &done)) {
    3229           0 :           return false;
    3230             :         }
    3231           0 :         if (done) {
    3232           0 :           break;
    3233             :         }
    3234           0 :         nsString* slotPtr = arr.AppendElement(mozilla::fallible);
    3235           0 :         if (!slotPtr) {
    3236           0 :           JS_ReportOutOfMemory(cx);
    3237           0 :           return false;
    3238             :         }
    3239           0 :         nsString& slot = *slotPtr;
    3240           0 :         if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
    3241           0 :           return false;
    3242             :         }
    3243           0 :       }
    3244             :     } else {
    3245           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'key_ops' member of JsonWebKey");
    3246           0 :       return false;
    3247             :     }
    3248           0 :     mIsAnyMemberPresent = true;
    3249             :   }
    3250             : 
    3251           0 :   if (!isNull) {
    3252           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->kty_id, temp.ptr())) {
    3253           0 :       return false;
    3254             :     }
    3255             :   }
    3256           0 :   if (!isNull && !temp->isUndefined()) {
    3257           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mKty)) {
    3258           0 :       return false;
    3259             :     }
    3260           0 :     mIsAnyMemberPresent = true;
    3261           0 :   } else if (cx) {
    3262             :     // Don't error out if we have no cx.  In that
    3263             :     // situation the caller is default-constructing us and we'll
    3264             :     // just assume they know what they're doing.
    3265           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    3266           0 :                              "'kty' member of JsonWebKey");
    3267             :   }
    3268             : 
    3269           0 :   if (!isNull) {
    3270           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->n_id, temp.ptr())) {
    3271           0 :       return false;
    3272             :     }
    3273             :   }
    3274           0 :   if (!isNull && !temp->isUndefined()) {
    3275           0 :     mN.Construct();
    3276           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mN.Value()))) {
    3277           0 :       return false;
    3278             :     }
    3279           0 :     mIsAnyMemberPresent = true;
    3280             :   }
    3281             : 
    3282           0 :   if (!isNull) {
    3283           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->oth_id, temp.ptr())) {
    3284           0 :       return false;
    3285             :     }
    3286             :   }
    3287           0 :   if (!isNull && !temp->isUndefined()) {
    3288           0 :     mOth.Construct();
    3289           0 :     if (temp.ref().isObject()) {
    3290           0 :       JS::ForOfIterator iter(cx);
    3291           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    3292           0 :         return false;
    3293             :       }
    3294           0 :       if (!iter.valueIsIterable()) {
    3295           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'oth' member of JsonWebKey");
    3296           0 :         return false;
    3297             :       }
    3298           0 :       Sequence<RsaOtherPrimesInfo> &arr = (mOth.Value());
    3299           0 :       JS::Rooted<JS::Value> temp(cx);
    3300             :       while (true) {
    3301             :         bool done;
    3302           0 :         if (!iter.next(&temp, &done)) {
    3303           0 :           return false;
    3304             :         }
    3305           0 :         if (done) {
    3306           0 :           break;
    3307             :         }
    3308           0 :         RsaOtherPrimesInfo* slotPtr = arr.AppendElement(mozilla::fallible);
    3309           0 :         if (!slotPtr) {
    3310           0 :           JS_ReportOutOfMemory(cx);
    3311           0 :           return false;
    3312             :         }
    3313           0 :         RsaOtherPrimesInfo& slot = *slotPtr;
    3314           0 :         if (!slot.Init(cx, temp,  "Element of 'oth' member of JsonWebKey", passedToJSImpl)) {
    3315           0 :           return false;
    3316             :         }
    3317           0 :       }
    3318             :     } else {
    3319           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'oth' member of JsonWebKey");
    3320           0 :       return false;
    3321             :     }
    3322           0 :     mIsAnyMemberPresent = true;
    3323             :   }
    3324             : 
    3325           0 :   if (!isNull) {
    3326           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->p_id, temp.ptr())) {
    3327           0 :       return false;
    3328             :     }
    3329             :   }
    3330           0 :   if (!isNull && !temp->isUndefined()) {
    3331           0 :     mP.Construct();
    3332           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mP.Value()))) {
    3333           0 :       return false;
    3334             :     }
    3335           0 :     mIsAnyMemberPresent = true;
    3336             :   }
    3337             : 
    3338           0 :   if (!isNull) {
    3339           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->q_id, temp.ptr())) {
    3340           0 :       return false;
    3341             :     }
    3342             :   }
    3343           0 :   if (!isNull && !temp->isUndefined()) {
    3344           0 :     mQ.Construct();
    3345           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mQ.Value()))) {
    3346           0 :       return false;
    3347             :     }
    3348           0 :     mIsAnyMemberPresent = true;
    3349             :   }
    3350             : 
    3351           0 :   if (!isNull) {
    3352           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->qi_id, temp.ptr())) {
    3353           0 :       return false;
    3354             :     }
    3355             :   }
    3356           0 :   if (!isNull && !temp->isUndefined()) {
    3357           0 :     mQi.Construct();
    3358           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mQi.Value()))) {
    3359           0 :       return false;
    3360             :     }
    3361           0 :     mIsAnyMemberPresent = true;
    3362             :   }
    3363             : 
    3364           0 :   if (!isNull) {
    3365           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->use_id, temp.ptr())) {
    3366           0 :       return false;
    3367             :     }
    3368             :   }
    3369           0 :   if (!isNull && !temp->isUndefined()) {
    3370           0 :     mUse.Construct();
    3371           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mUse.Value()))) {
    3372           0 :       return false;
    3373             :     }
    3374           0 :     mIsAnyMemberPresent = true;
    3375             :   }
    3376             : 
    3377           0 :   if (!isNull) {
    3378           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->x_id, temp.ptr())) {
    3379           0 :       return false;
    3380             :     }
    3381             :   }
    3382           0 :   if (!isNull && !temp->isUndefined()) {
    3383           0 :     mX.Construct();
    3384           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mX.Value()))) {
    3385           0 :       return false;
    3386             :     }
    3387           0 :     mIsAnyMemberPresent = true;
    3388             :   }
    3389             : 
    3390           0 :   if (!isNull) {
    3391           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->y_id, temp.ptr())) {
    3392           0 :       return false;
    3393             :     }
    3394             :   }
    3395           0 :   if (!isNull && !temp->isUndefined()) {
    3396           0 :     mY.Construct();
    3397           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mY.Value()))) {
    3398           0 :       return false;
    3399             :     }
    3400           0 :     mIsAnyMemberPresent = true;
    3401             :   }
    3402           0 :   return true;
    3403             : }
    3404             : 
    3405             : bool
    3406           0 : JsonWebKey::Init(const nsAString& aJSON)
    3407             : {
    3408           0 :   AutoJSAPI jsapi;
    3409           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    3410           0 :   if (!cleanGlobal) {
    3411           0 :     return false;
    3412             :   }
    3413           0 :   if (!jsapi.Init(cleanGlobal)) {
    3414           0 :     return false;
    3415             :   }
    3416           0 :   JSContext* cx = jsapi.cx();
    3417           0 :   JS::Rooted<JS::Value> json(cx);
    3418           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    3419           0 :   NS_ENSURE_TRUE(ok, false);
    3420           0 :   return Init(cx, json);
    3421             : }
    3422             : 
    3423             : bool
    3424           0 : JsonWebKey::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    3425             : {
    3426           0 :   JsonWebKeyAtoms* atomsCache = GetAtomCache<JsonWebKeyAtoms>(cx);
    3427           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    3428           0 :     return false;
    3429             :   }
    3430             : 
    3431           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    3432           0 :   if (!obj) {
    3433           0 :     return false;
    3434             :   }
    3435           0 :   rval.set(JS::ObjectValue(*obj));
    3436             : 
    3437           0 :   if (mAlg.WasPassed()) {
    3438             :     do {
    3439             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3440           0 :       JS::Rooted<JS::Value> temp(cx);
    3441           0 :       nsString const & currentValue = mAlg.InternalValue();
    3442           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3443           0 :         return false;
    3444             :       }
    3445           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->alg_id, temp, JSPROP_ENUMERATE)) {
    3446           0 :         return false;
    3447             :       }
    3448           0 :       break;
    3449             :     } while(0);
    3450             :   }
    3451             : 
    3452           0 :   if (mCrv.WasPassed()) {
    3453             :     do {
    3454             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3455           0 :       JS::Rooted<JS::Value> temp(cx);
    3456           0 :       nsString const & currentValue = mCrv.InternalValue();
    3457           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3458           0 :         return false;
    3459             :       }
    3460           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->crv_id, temp, JSPROP_ENUMERATE)) {
    3461           0 :         return false;
    3462             :       }
    3463           0 :       break;
    3464             :     } while(0);
    3465             :   }
    3466             : 
    3467           0 :   if (mD.WasPassed()) {
    3468             :     do {
    3469             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3470           0 :       JS::Rooted<JS::Value> temp(cx);
    3471           0 :       nsString const & currentValue = mD.InternalValue();
    3472           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3473           0 :         return false;
    3474             :       }
    3475           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->d_id, temp, JSPROP_ENUMERATE)) {
    3476           0 :         return false;
    3477             :       }
    3478           0 :       break;
    3479             :     } while(0);
    3480             :   }
    3481             : 
    3482           0 :   if (mDp.WasPassed()) {
    3483             :     do {
    3484             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3485           0 :       JS::Rooted<JS::Value> temp(cx);
    3486           0 :       nsString const & currentValue = mDp.InternalValue();
    3487           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3488           0 :         return false;
    3489             :       }
    3490           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->dp_id, temp, JSPROP_ENUMERATE)) {
    3491           0 :         return false;
    3492             :       }
    3493           0 :       break;
    3494             :     } while(0);
    3495             :   }
    3496             : 
    3497           0 :   if (mDq.WasPassed()) {
    3498             :     do {
    3499             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3500           0 :       JS::Rooted<JS::Value> temp(cx);
    3501           0 :       nsString const & currentValue = mDq.InternalValue();
    3502           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3503           0 :         return false;
    3504             :       }
    3505           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->dq_id, temp, JSPROP_ENUMERATE)) {
    3506           0 :         return false;
    3507             :       }
    3508           0 :       break;
    3509             :     } while(0);
    3510             :   }
    3511             : 
    3512           0 :   if (mE.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 :       nsString const & currentValue = mE.InternalValue();
    3517           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3518           0 :         return false;
    3519             :       }
    3520           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->e_id, temp, JSPROP_ENUMERATE)) {
    3521           0 :         return false;
    3522             :       }
    3523           0 :       break;
    3524             :     } while(0);
    3525             :   }
    3526             : 
    3527           0 :   if (mExt.WasPassed()) {
    3528             :     do {
    3529             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3530           0 :       JS::Rooted<JS::Value> temp(cx);
    3531           0 :       bool const & currentValue = mExt.InternalValue();
    3532           0 :       temp.setBoolean(currentValue);
    3533           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->ext_id, temp, JSPROP_ENUMERATE)) {
    3534           0 :         return false;
    3535             :       }
    3536           0 :       break;
    3537             :     } while(0);
    3538             :   }
    3539             : 
    3540           0 :   if (mK.WasPassed()) {
    3541             :     do {
    3542             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3543           0 :       JS::Rooted<JS::Value> temp(cx);
    3544           0 :       nsString const & currentValue = mK.InternalValue();
    3545           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3546           0 :         return false;
    3547             :       }
    3548           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->k_id, temp, JSPROP_ENUMERATE)) {
    3549           0 :         return false;
    3550             :       }
    3551           0 :       break;
    3552             :     } while(0);
    3553             :   }
    3554             : 
    3555           0 :   if (mKey_ops.WasPassed()) {
    3556             :     do {
    3557             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3558           0 :       JS::Rooted<JS::Value> temp(cx);
    3559           0 :       Sequence<nsString> const & currentValue = mKey_ops.InternalValue();
    3560             : 
    3561           0 :       uint32_t length = currentValue.Length();
    3562           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    3563           0 :       if (!returnArray) {
    3564           0 :         return false;
    3565             :       }
    3566             :       // Scope for 'tmp'
    3567             :       {
    3568           0 :         JS::Rooted<JS::Value> tmp(cx);
    3569           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    3570             :           // Control block to let us common up the JS_DefineElement calls when there
    3571             :           // are different ways to succeed at wrapping the object.
    3572             :           do {
    3573           0 :             if (!xpc::NonVoidStringToJsval(cx, currentValue[sequenceIdx0], &tmp)) {
    3574           0 :               return false;
    3575             :             }
    3576           0 :             break;
    3577             :           } while (0);
    3578           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    3579             :                                 JSPROP_ENUMERATE)) {
    3580           0 :             return false;
    3581             :           }
    3582             :         }
    3583             :       }
    3584           0 :       temp.setObject(*returnArray);
    3585           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->key_ops_id, temp, JSPROP_ENUMERATE)) {
    3586           0 :         return false;
    3587             :       }
    3588           0 :       break;
    3589             :     } while(0);
    3590             :   }
    3591             : 
    3592             :   do {
    3593             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3594           0 :     JS::Rooted<JS::Value> temp(cx);
    3595           0 :     nsString const & currentValue = mKty;
    3596           0 :     if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3597           0 :       return false;
    3598             :     }
    3599           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->kty_id, temp, JSPROP_ENUMERATE)) {
    3600           0 :       return false;
    3601             :     }
    3602           0 :     break;
    3603             :   } while(0);
    3604             : 
    3605           0 :   if (mN.WasPassed()) {
    3606             :     do {
    3607             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3608           0 :       JS::Rooted<JS::Value> temp(cx);
    3609           0 :       nsString const & currentValue = mN.InternalValue();
    3610           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3611           0 :         return false;
    3612             :       }
    3613           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->n_id, temp, JSPROP_ENUMERATE)) {
    3614           0 :         return false;
    3615             :       }
    3616           0 :       break;
    3617             :     } while(0);
    3618             :   }
    3619             : 
    3620           0 :   if (mOth.WasPassed()) {
    3621             :     do {
    3622             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3623           0 :       JS::Rooted<JS::Value> temp(cx);
    3624           0 :       Sequence<RsaOtherPrimesInfo> const & currentValue = mOth.InternalValue();
    3625             : 
    3626           0 :       uint32_t length = currentValue.Length();
    3627           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    3628           0 :       if (!returnArray) {
    3629           0 :         return false;
    3630             :       }
    3631             :       // Scope for 'tmp'
    3632             :       {
    3633           0 :         JS::Rooted<JS::Value> tmp(cx);
    3634           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    3635             :           // Control block to let us common up the JS_DefineElement calls when there
    3636             :           // are different ways to succeed at wrapping the object.
    3637             :           do {
    3638           0 :             if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
    3639           0 :               return false;
    3640             :             }
    3641           0 :             break;
    3642             :           } while (0);
    3643           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    3644             :                                 JSPROP_ENUMERATE)) {
    3645           0 :             return false;
    3646             :           }
    3647             :         }
    3648             :       }
    3649           0 :       temp.setObject(*returnArray);
    3650           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->oth_id, temp, JSPROP_ENUMERATE)) {
    3651           0 :         return false;
    3652             :       }
    3653           0 :       break;
    3654             :     } while(0);
    3655             :   }
    3656             : 
    3657           0 :   if (mP.WasPassed()) {
    3658             :     do {
    3659             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3660           0 :       JS::Rooted<JS::Value> temp(cx);
    3661           0 :       nsString const & currentValue = mP.InternalValue();
    3662           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3663           0 :         return false;
    3664             :       }
    3665           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->p_id, temp, JSPROP_ENUMERATE)) {
    3666           0 :         return false;
    3667             :       }
    3668           0 :       break;
    3669             :     } while(0);
    3670             :   }
    3671             : 
    3672           0 :   if (mQ.WasPassed()) {
    3673             :     do {
    3674             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3675           0 :       JS::Rooted<JS::Value> temp(cx);
    3676           0 :       nsString const & currentValue = mQ.InternalValue();
    3677           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3678           0 :         return false;
    3679             :       }
    3680           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->q_id, temp, JSPROP_ENUMERATE)) {
    3681           0 :         return false;
    3682             :       }
    3683           0 :       break;
    3684             :     } while(0);
    3685             :   }
    3686             : 
    3687           0 :   if (mQi.WasPassed()) {
    3688             :     do {
    3689             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3690           0 :       JS::Rooted<JS::Value> temp(cx);
    3691           0 :       nsString const & currentValue = mQi.InternalValue();
    3692           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3693           0 :         return false;
    3694             :       }
    3695           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->qi_id, temp, JSPROP_ENUMERATE)) {
    3696           0 :         return false;
    3697             :       }
    3698           0 :       break;
    3699             :     } while(0);
    3700             :   }
    3701             : 
    3702           0 :   if (mUse.WasPassed()) {
    3703             :     do {
    3704             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3705           0 :       JS::Rooted<JS::Value> temp(cx);
    3706           0 :       nsString const & currentValue = mUse.InternalValue();
    3707           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3708           0 :         return false;
    3709             :       }
    3710           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->use_id, temp, JSPROP_ENUMERATE)) {
    3711           0 :         return false;
    3712             :       }
    3713           0 :       break;
    3714             :     } while(0);
    3715             :   }
    3716             : 
    3717           0 :   if (mX.WasPassed()) {
    3718             :     do {
    3719             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3720           0 :       JS::Rooted<JS::Value> temp(cx);
    3721           0 :       nsString const & currentValue = mX.InternalValue();
    3722           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3723           0 :         return false;
    3724             :       }
    3725           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->x_id, temp, JSPROP_ENUMERATE)) {
    3726           0 :         return false;
    3727             :       }
    3728           0 :       break;
    3729             :     } while(0);
    3730             :   }
    3731             : 
    3732           0 :   if (mY.WasPassed()) {
    3733             :     do {
    3734             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    3735           0 :       JS::Rooted<JS::Value> temp(cx);
    3736           0 :       nsString const & currentValue = mY.InternalValue();
    3737           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    3738           0 :         return false;
    3739             :       }
    3740           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->y_id, temp, JSPROP_ENUMERATE)) {
    3741           0 :         return false;
    3742             :       }
    3743           0 :       break;
    3744             :     } while(0);
    3745             :   }
    3746             : 
    3747           0 :   return true;
    3748             : }
    3749             : 
    3750             : bool
    3751           0 : JsonWebKey::ToJSON(nsAString& aJSON) const
    3752             : {
    3753           0 :   AutoJSAPI jsapi;
    3754           0 :   jsapi.Init();
    3755           0 :   JSContext *cx = jsapi.cx();
    3756             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    3757             :   // because we'll only be creating objects, in ways that have no
    3758             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    3759             :   // which likewise guarantees no side-effects for the sorts of
    3760             :   // things we will pass it.
    3761           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    3762           0 :   JS::Rooted<JS::Value> val(cx);
    3763           0 :   if (!ToObjectInternal(cx, &val)) {
    3764           0 :     return false;
    3765             :   }
    3766           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    3767           0 :   return StringifyToJSON(cx, obj, aJSON);
    3768             : }
    3769             : 
    3770             : void
    3771           0 : JsonWebKey::TraceDictionary(JSTracer* trc)
    3772             : {
    3773           0 : }
    3774             : 
    3775             : JsonWebKey&
    3776           0 : JsonWebKey::operator=(const JsonWebKey& aOther)
    3777             : {
    3778           0 :   mAlg.Reset();
    3779           0 :   if (aOther.mAlg.WasPassed()) {
    3780           0 :     mAlg.Construct(aOther.mAlg.Value());
    3781             :   }
    3782           0 :   mCrv.Reset();
    3783           0 :   if (aOther.mCrv.WasPassed()) {
    3784           0 :     mCrv.Construct(aOther.mCrv.Value());
    3785             :   }
    3786           0 :   mD.Reset();
    3787           0 :   if (aOther.mD.WasPassed()) {
    3788           0 :     mD.Construct(aOther.mD.Value());
    3789             :   }
    3790           0 :   mDp.Reset();
    3791           0 :   if (aOther.mDp.WasPassed()) {
    3792           0 :     mDp.Construct(aOther.mDp.Value());
    3793             :   }
    3794           0 :   mDq.Reset();
    3795           0 :   if (aOther.mDq.WasPassed()) {
    3796           0 :     mDq.Construct(aOther.mDq.Value());
    3797             :   }
    3798           0 :   mE.Reset();
    3799           0 :   if (aOther.mE.WasPassed()) {
    3800           0 :     mE.Construct(aOther.mE.Value());
    3801             :   }
    3802           0 :   mExt.Reset();
    3803           0 :   if (aOther.mExt.WasPassed()) {
    3804           0 :     mExt.Construct(aOther.mExt.Value());
    3805             :   }
    3806           0 :   mK.Reset();
    3807           0 :   if (aOther.mK.WasPassed()) {
    3808           0 :     mK.Construct(aOther.mK.Value());
    3809             :   }
    3810           0 :   mKey_ops.Reset();
    3811           0 :   if (aOther.mKey_ops.WasPassed()) {
    3812           0 :     mKey_ops.Construct(aOther.mKey_ops.Value());
    3813             :   }
    3814           0 :   mKty = aOther.mKty;
    3815           0 :   mN.Reset();
    3816           0 :   if (aOther.mN.WasPassed()) {
    3817           0 :     mN.Construct(aOther.mN.Value());
    3818             :   }
    3819           0 :   mOth.Reset();
    3820           0 :   if (aOther.mOth.WasPassed()) {
    3821           0 :     mOth.Construct(aOther.mOth.Value());
    3822             :   }
    3823           0 :   mP.Reset();
    3824           0 :   if (aOther.mP.WasPassed()) {
    3825           0 :     mP.Construct(aOther.mP.Value());
    3826             :   }
    3827           0 :   mQ.Reset();
    3828           0 :   if (aOther.mQ.WasPassed()) {
    3829           0 :     mQ.Construct(aOther.mQ.Value());
    3830             :   }
    3831           0 :   mQi.Reset();
    3832           0 :   if (aOther.mQi.WasPassed()) {
    3833           0 :     mQi.Construct(aOther.mQi.Value());
    3834             :   }
    3835           0 :   mUse.Reset();
    3836           0 :   if (aOther.mUse.WasPassed()) {
    3837           0 :     mUse.Construct(aOther.mUse.Value());
    3838             :   }
    3839           0 :   mX.Reset();
    3840           0 :   if (aOther.mX.WasPassed()) {
    3841           0 :     mX.Construct(aOther.mX.Value());
    3842             :   }
    3843           0 :   mY.Reset();
    3844           0 :   if (aOther.mY.WasPassed()) {
    3845           0 :     mY.Construct(aOther.mY.Value());
    3846             :   }
    3847           0 :   return *this;
    3848             : }
    3849             : 
    3850             : namespace binding_detail {
    3851             : } // namespace binding_detail
    3852             : 
    3853             : 
    3854             : 
    3855           0 : Pbkdf2Params::Pbkdf2Params()
    3856           0 :   : Algorithm(FastDictionaryInitializer())
    3857             : {
    3858             :   // Safe to pass a null context if we pass a null value
    3859           0 :   Init(nullptr, JS::NullHandleValue);
    3860           0 : }
    3861             : 
    3862             : 
    3863             : bool
    3864           0 : Pbkdf2Params::InitIds(JSContext* cx, Pbkdf2ParamsAtoms* atomsCache)
    3865             : {
    3866           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    3867             : 
    3868             :   // Initialize these in reverse order so that any failure leaves the first one
    3869             :   // uninitialized.
    3870           0 :   if (!atomsCache->salt_id.init(cx, "salt") ||
    3871           0 :       !atomsCache->iterations_id.init(cx, "iterations") ||
    3872           0 :       !atomsCache->hash_id.init(cx, "hash")) {
    3873           0 :     return false;
    3874             :   }
    3875           0 :   return true;
    3876             : }
    3877             : 
    3878             : bool
    3879           0 : Pbkdf2Params::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    3880             : {
    3881             :   // Passing a null JSContext is OK only if we're initing from null,
    3882             :   // Since in that case we will not have to do any property gets
    3883             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    3884             :   // checkers by static analysis tools
    3885           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    3886           0 :   Pbkdf2ParamsAtoms* atomsCache = nullptr;
    3887           0 :   if (cx) {
    3888           0 :     atomsCache = GetAtomCache<Pbkdf2ParamsAtoms>(cx);
    3889           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    3890           0 :       return false;
    3891             :     }
    3892             :   }
    3893             : 
    3894             :   // Per spec, we init the parent's members first
    3895           0 :   if (!Algorithm::Init(cx, val)) {
    3896           0 :     return false;
    3897             :   }
    3898             : 
    3899           0 :   bool isNull = val.isNullOrUndefined();
    3900             :   // We only need these if !isNull, in which case we have |cx|.
    3901           0 :   Maybe<JS::Rooted<JSObject *> > object;
    3902           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    3903           0 :   if (!isNull) {
    3904           0 :     MOZ_ASSERT(cx);
    3905           0 :     object.emplace(cx, &val.toObject());
    3906           0 :     temp.emplace(cx);
    3907             :   }
    3908           0 :   if (!isNull) {
    3909           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->hash_id, temp.ptr())) {
    3910           0 :       return false;
    3911             :     }
    3912             :   }
    3913           0 :   if (!isNull && !temp->isUndefined()) {
    3914             :     {
    3915           0 :       bool done = false, failed = false, tryNext;
    3916           0 :       if (temp.ref().isObject()) {
    3917           0 :         if (!mHash.SetToObject(cx, &temp.ref().toObject(), passedToJSImpl)) {
    3918           0 :           return false;
    3919             :         }
    3920           0 :         done = true;
    3921             :       } else {
    3922             :         do {
    3923           0 :           done = (failed = !mHash.TrySetToString(cx, temp.ref(), tryNext)) || !tryNext;
    3924           0 :           break;
    3925             :         } while (0);
    3926             :       }
    3927           0 :       if (failed) {
    3928           0 :         return false;
    3929             :       }
    3930           0 :       if (!done) {
    3931           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'hash' member of Pbkdf2Params", "Object");
    3932           0 :         return false;
    3933             :       }
    3934             :     }
    3935           0 :     mIsAnyMemberPresent = true;
    3936           0 :   } else if (cx) {
    3937             :     // Don't error out if we have no cx.  In that
    3938             :     // situation the caller is default-constructing us and we'll
    3939             :     // just assume they know what they're doing.
    3940           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    3941           0 :                              "'hash' member of Pbkdf2Params");
    3942             :   }
    3943             : 
    3944           0 :   if (!isNull) {
    3945           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->iterations_id, temp.ptr())) {
    3946           0 :       return false;
    3947             :     }
    3948             :   }
    3949           0 :   if (!isNull && !temp->isUndefined()) {
    3950           0 :     if (!ValueToPrimitive<uint32_t, eEnforceRange>(cx, temp.ref(), &mIterations)) {
    3951           0 :       return false;
    3952             :     }
    3953           0 :     mIsAnyMemberPresent = true;
    3954           0 :   } else if (cx) {
    3955             :     // Don't error out if we have no cx.  In that
    3956             :     // situation the caller is default-constructing us and we'll
    3957             :     // just assume they know what they're doing.
    3958           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    3959           0 :                              "'iterations' member of Pbkdf2Params");
    3960             :   }
    3961             : 
    3962           0 :   if (!isNull) {
    3963           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->salt_id, temp.ptr())) {
    3964           0 :       return false;
    3965             :     }
    3966             :   }
    3967           0 :   if (!isNull && !temp->isUndefined()) {
    3968             :     {
    3969           0 :       bool done = false, failed = false, tryNext;
    3970           0 :       if (temp.ref().isObject()) {
    3971           0 :         done = (failed = !mSalt.TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
    3972           0 :                (failed = !mSalt.TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
    3973             : 
    3974             :       }
    3975           0 :       if (failed) {
    3976           0 :         return false;
    3977             :       }
    3978           0 :       if (!done) {
    3979           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'salt' member of Pbkdf2Params", "ArrayBufferView, ArrayBuffer");
    3980           0 :         return false;
    3981             :       }
    3982             :     }
    3983           0 :     mIsAnyMemberPresent = true;
    3984           0 :   } else if (cx) {
    3985             :     // Don't error out if we have no cx.  In that
    3986             :     // situation the caller is default-constructing us and we'll
    3987             :     // just assume they know what they're doing.
    3988           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    3989           0 :                              "'salt' member of Pbkdf2Params");
    3990             :   }
    3991           0 :   return true;
    3992             : }
    3993             : 
    3994             : bool
    3995           0 : Pbkdf2Params::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    3996             : {
    3997           0 :   Pbkdf2ParamsAtoms* atomsCache = GetAtomCache<Pbkdf2ParamsAtoms>(cx);
    3998           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    3999           0 :     return false;
    4000             :   }
    4001             : 
    4002             :   // Per spec, we define the parent's members first
    4003           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    4004           0 :     return false;
    4005             :   }
    4006           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    4007             : 
    4008             :   do {
    4009             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    4010           0 :     JS::Rooted<JS::Value> temp(cx);
    4011           0 :     OwningObjectOrString const & currentValue = mHash;
    4012           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
    4013           0 :       return false;
    4014             :     }
    4015           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->hash_id, temp, JSPROP_ENUMERATE)) {
    4016           0 :       return false;
    4017             :     }
    4018           0 :     break;
    4019             :   } while(0);
    4020             : 
    4021             :   do {
    4022             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    4023           0 :     JS::Rooted<JS::Value> temp(cx);
    4024           0 :     uint32_t const & currentValue = mIterations;
    4025           0 :     temp.setNumber(currentValue);
    4026           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->iterations_id, temp, JSPROP_ENUMERATE)) {
    4027           0 :       return false;
    4028             :     }
    4029           0 :     break;
    4030             :   } while(0);
    4031             : 
    4032             :   do {
    4033             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    4034           0 :     JS::Rooted<JS::Value> temp(cx);
    4035           0 :     OwningArrayBufferViewOrArrayBuffer const & currentValue = mSalt;
    4036           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
    4037           0 :       return false;
    4038             :     }
    4039           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->salt_id, temp, JSPROP_ENUMERATE)) {
    4040           0 :       return false;
    4041             :     }
    4042           0 :     break;
    4043             :   } while(0);
    4044             : 
    4045           0 :   return true;
    4046             : }
    4047             : 
    4048             : void
    4049           0 : Pbkdf2Params::TraceDictionary(JSTracer* trc)
    4050             : {
    4051           0 :   Algorithm::TraceDictionary(trc);
    4052           0 :   mHash.TraceUnion(trc);
    4053             : 
    4054           0 :   mSalt.TraceUnion(trc);
    4055           0 : }
    4056             : 
    4057             : namespace binding_detail {
    4058             : } // namespace binding_detail
    4059             : 
    4060             : 
    4061             : 
    4062           0 : RsaHashedKeyGenParams::RsaHashedKeyGenParams()
    4063           0 :   : Algorithm(FastDictionaryInitializer())
    4064             : {
    4065             :   // Safe to pass a null context if we pass a null value
    4066           0 :   Init(nullptr, JS::NullHandleValue);
    4067           0 : }
    4068             : 
    4069             : 
    4070             : bool
    4071           0 : RsaHashedKeyGenParams::InitIds(JSContext* cx, RsaHashedKeyGenParamsAtoms* atomsCache)
    4072             : {
    4073           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    4074             : 
    4075             :   // Initialize these in reverse order so that any failure leaves the first one
    4076             :   // uninitialized.
    4077           0 :   if (!atomsCache->publicExponent_id.init(cx, "publicExponent") ||
    4078           0 :       !atomsCache->modulusLength_id.init(cx, "modulusLength") ||
    4079           0 :       !atomsCache->hash_id.init(cx, "hash")) {
    4080           0 :     return false;
    4081             :   }
    4082           0 :   return true;
    4083             : }
    4084             : 
    4085             : bool
    4086           0 : RsaHashedKeyGenParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    4087             : {
    4088             :   // Passing a null JSContext is OK only if we're initing from null,
    4089             :   // Since in that case we will not have to do any property gets
    4090             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    4091             :   // checkers by static analysis tools
    4092           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    4093           0 :   RsaHashedKeyGenParamsAtoms* atomsCache = nullptr;
    4094           0 :   if (cx) {
    4095           0 :     atomsCache = GetAtomCache<RsaHashedKeyGenParamsAtoms>(cx);
    4096           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    4097           0 :       return false;
    4098             :     }
    4099             :   }
    4100             : 
    4101             :   // Per spec, we init the parent's members first
    4102           0 :   if (!Algorithm::Init(cx, val)) {
    4103           0 :     return false;
    4104             :   }
    4105             : 
    4106           0 :   bool isNull = val.isNullOrUndefined();
    4107             :   // We only need these if !isNull, in which case we have |cx|.
    4108           0 :   Maybe<JS::Rooted<JSObject *> > object;
    4109           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    4110           0 :   if (!isNull) {
    4111           0 :     MOZ_ASSERT(cx);
    4112           0 :     object.emplace(cx, &val.toObject());
    4113           0 :     temp.emplace(cx);
    4114             :   }
    4115           0 :   if (!isNull) {
    4116           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->hash_id, temp.ptr())) {
    4117           0 :       return false;
    4118             :     }
    4119             :   }
    4120           0 :   if (!isNull && !temp->isUndefined()) {
    4121             :     {
    4122           0 :       bool done = false, failed = false, tryNext;
    4123           0 :       if (temp.ref().isObject()) {
    4124           0 :         if (!mHash.SetToObject(cx, &temp.ref().toObject(), passedToJSImpl)) {
    4125           0 :           return false;
    4126             :         }
    4127           0 :         done = true;
    4128             :       } else {
    4129             :         do {
    4130           0 :           done = (failed = !mHash.TrySetToString(cx, temp.ref(), tryNext)) || !tryNext;
    4131           0 :           break;
    4132             :         } while (0);
    4133             :       }
    4134           0 :       if (failed) {
    4135           0 :         return false;
    4136             :       }
    4137           0 :       if (!done) {
    4138           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'hash' member of RsaHashedKeyGenParams", "Object");
    4139           0 :         return false;
    4140             :       }
    4141             :     }
    4142           0 :     mIsAnyMemberPresent = true;
    4143           0 :   } else if (cx) {
    4144             :     // Don't error out if we have no cx.  In that
    4145             :     // situation the caller is default-constructing us and we'll
    4146             :     // just assume they know what they're doing.
    4147           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    4148           0 :                              "'hash' member of RsaHashedKeyGenParams");
    4149             :   }
    4150             : 
    4151           0 :   if (!isNull) {
    4152           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->modulusLength_id, temp.ptr())) {
    4153           0 :       return false;
    4154             :     }
    4155             :   }
    4156           0 :   if (!isNull && !temp->isUndefined()) {
    4157           0 :     if (!ValueToPrimitive<uint32_t, eEnforceRange>(cx, temp.ref(), &mModulusLength)) {
    4158           0 :       return false;
    4159             :     }
    4160           0 :     mIsAnyMemberPresent = true;
    4161           0 :   } else if (cx) {
    4162             :     // Don't error out if we have no cx.  In that
    4163             :     // situation the caller is default-constructing us and we'll
    4164             :     // just assume they know what they're doing.
    4165           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    4166           0 :                              "'modulusLength' member of RsaHashedKeyGenParams");
    4167             :   }
    4168             : 
    4169           0 :   if (!isNull) {
    4170           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->publicExponent_id, temp.ptr())) {
    4171           0 :       return false;
    4172             :     }
    4173             :   }
    4174           0 :   if (!isNull && !temp->isUndefined()) {
    4175           0 :     if (temp.ref().isObject()) {
    4176           0 :       if (!mPublicExponent.Init(&temp.ref().toObject())) {
    4177           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "'publicExponent' member of RsaHashedKeyGenParams", "Uint8Array");
    4178           0 :         return false;
    4179             :       }
    4180             :     } else {
    4181           0 :       ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'publicExponent' member of RsaHashedKeyGenParams");
    4182           0 :       return false;
    4183             :     }
    4184           0 :     mIsAnyMemberPresent = true;
    4185           0 :   } else if (cx) {
    4186             :     // Don't error out if we have no cx.  In that
    4187             :     // situation the caller is default-constructing us and we'll
    4188             :     // just assume they know what they're doing.
    4189           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    4190           0 :                              "'publicExponent' member of RsaHashedKeyGenParams");
    4191             :   }
    4192           0 :   return true;
    4193             : }
    4194             : 
    4195             : bool
    4196           0 : RsaHashedKeyGenParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    4197             : {
    4198           0 :   RsaHashedKeyGenParamsAtoms* atomsCache = GetAtomCache<RsaHashedKeyGenParamsAtoms>(cx);
    4199           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    4200           0 :     return false;
    4201             :   }
    4202             : 
    4203             :   // Per spec, we define the parent's members first
    4204           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    4205           0 :     return false;
    4206             :   }
    4207           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    4208             : 
    4209             :   do {
    4210             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    4211           0 :     JS::Rooted<JS::Value> temp(cx);
    4212           0 :     OwningObjectOrString const & currentValue = mHash;
    4213           0 :     if (!currentValue.ToJSVal(cx, obj, &temp)) {
    4214           0 :       return false;
    4215             :     }
    4216           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->hash_id, temp, JSPROP_ENUMERATE)) {
    4217           0 :       return false;
    4218             :     }
    4219           0 :     break;
    4220             :   } while(0);
    4221             : 
    4222             :   do {
    4223             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    4224           0 :     JS::Rooted<JS::Value> temp(cx);
    4225           0 :     uint32_t const & currentValue = mModulusLength;
    4226           0 :     temp.setNumber(currentValue);
    4227           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->modulusLength_id, temp, JSPROP_ENUMERATE)) {
    4228           0 :       return false;
    4229             :     }
    4230           0 :     break;
    4231             :   } while(0);
    4232             : 
    4233             :   do {
    4234             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    4235           0 :     JS::Rooted<JS::Value> temp(cx);
    4236           0 :     Uint8Array const & currentValue = mPublicExponent;
    4237           0 :     temp.setObject(*currentValue.Obj());
    4238           0 :     if (!MaybeWrapNonDOMObjectValue(cx, &temp)) {
    4239           0 :       return false;
    4240             :     }
    4241           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->publicExponent_id, temp, JSPROP_ENUMERATE)) {
    4242           0 :       return false;
    4243             :     }
    4244           0 :     break;
    4245             :   } while(0);
    4246             : 
    4247           0 :   return true;
    4248             : }
    4249             : 
    4250             : void
    4251           0 : RsaHashedKeyGenParams::TraceDictionary(JSTracer* trc)
    4252             : {
    4253           0 :   Algorithm::TraceDictionary(trc);
    4254           0 :   mHash.TraceUnion(trc);
    4255             : 
    4256           0 :   mPublicExponent.TraceSelf(trc);
    4257           0 : }
    4258             : 
    4259             : namespace binding_detail {
    4260             : } // namespace binding_detail
    4261             : 
    4262             : 
    4263             : 
    4264           0 : RsaOaepParams::RsaOaepParams()
    4265           0 :   : Algorithm(FastDictionaryInitializer())
    4266             : {
    4267             :   // Safe to pass a null context if we pass a null value
    4268           0 :   Init(nullptr, JS::NullHandleValue);
    4269           0 : }
    4270             : 
    4271             : 
    4272             : bool
    4273           0 : RsaOaepParams::InitIds(JSContext* cx, RsaOaepParamsAtoms* atomsCache)
    4274             : {
    4275           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    4276             : 
    4277             :   // Initialize these in reverse order so that any failure leaves the first one
    4278             :   // uninitialized.
    4279           0 :   if (!atomsCache->label_id.init(cx, "label")) {
    4280           0 :     return false;
    4281             :   }
    4282           0 :   return true;
    4283             : }
    4284             : 
    4285             : bool
    4286           0 : RsaOaepParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    4287             : {
    4288             :   // Passing a null JSContext is OK only if we're initing from null,
    4289             :   // Since in that case we will not have to do any property gets
    4290             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    4291             :   // checkers by static analysis tools
    4292           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    4293           0 :   RsaOaepParamsAtoms* atomsCache = nullptr;
    4294           0 :   if (cx) {
    4295           0 :     atomsCache = GetAtomCache<RsaOaepParamsAtoms>(cx);
    4296           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    4297           0 :       return false;
    4298             :     }
    4299             :   }
    4300             : 
    4301             :   // Per spec, we init the parent's members first
    4302           0 :   if (!Algorithm::Init(cx, val)) {
    4303           0 :     return false;
    4304             :   }
    4305             : 
    4306           0 :   bool isNull = val.isNullOrUndefined();
    4307             :   // We only need these if !isNull, in which case we have |cx|.
    4308           0 :   Maybe<JS::Rooted<JSObject *> > object;
    4309           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    4310           0 :   if (!isNull) {
    4311           0 :     MOZ_ASSERT(cx);
    4312           0 :     object.emplace(cx, &val.toObject());
    4313           0 :     temp.emplace(cx);
    4314             :   }
    4315           0 :   if (!isNull) {
    4316           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->label_id, temp.ptr())) {
    4317           0 :       return false;
    4318             :     }
    4319             :   }
    4320           0 :   if (!isNull && !temp->isUndefined()) {
    4321           0 :     mLabel.Construct();
    4322             :     {
    4323           0 :       bool done = false, failed = false, tryNext;
    4324           0 :       if (temp.ref().isObject()) {
    4325           0 :         done = (failed = !(mLabel.Value()).TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
    4326           0 :                (failed = !(mLabel.Value()).TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
    4327             : 
    4328             :       }
    4329           0 :       if (failed) {
    4330           0 :         return false;
    4331             :       }
    4332           0 :       if (!done) {
    4333           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'label' member of RsaOaepParams", "ArrayBufferView, ArrayBuffer");
    4334           0 :         return false;
    4335             :       }
    4336             :     }
    4337           0 :     mIsAnyMemberPresent = true;
    4338             :   }
    4339           0 :   return true;
    4340             : }
    4341             : 
    4342             : bool
    4343           0 : RsaOaepParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    4344             : {
    4345           0 :   RsaOaepParamsAtoms* atomsCache = GetAtomCache<RsaOaepParamsAtoms>(cx);
    4346           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    4347           0 :     return false;
    4348             :   }
    4349             : 
    4350             :   // Per spec, we define the parent's members first
    4351           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    4352           0 :     return false;
    4353             :   }
    4354           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    4355             : 
    4356           0 :   if (mLabel.WasPassed()) {
    4357             :     do {
    4358             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    4359           0 :       JS::Rooted<JS::Value> temp(cx);
    4360           0 :       OwningArrayBufferViewOrArrayBuffer const & currentValue = mLabel.InternalValue();
    4361           0 :       if (!currentValue.ToJSVal(cx, obj, &temp)) {
    4362           0 :         return false;
    4363             :       }
    4364           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->label_id, temp, JSPROP_ENUMERATE)) {
    4365           0 :         return false;
    4366             :       }
    4367           0 :       break;
    4368             :     } while(0);
    4369             :   }
    4370             : 
    4371           0 :   return true;
    4372             : }
    4373             : 
    4374             : void
    4375           0 : RsaOaepParams::TraceDictionary(JSTracer* trc)
    4376             : {
    4377           0 :   Algorithm::TraceDictionary(trc);
    4378           0 :   if (mLabel.WasPassed()) {
    4379           0 :     mLabel.Value().TraceUnion(trc);
    4380             :   }
    4381           0 : }
    4382             : 
    4383             : namespace binding_detail {
    4384             : } // namespace binding_detail
    4385             : 
    4386             : 
    4387             : 
    4388           0 : RsaPssParams::RsaPssParams()
    4389           0 :   : Algorithm(FastDictionaryInitializer())
    4390             : {
    4391             :   // Safe to pass a null context if we pass a null value
    4392           0 :   Init(nullptr, JS::NullHandleValue);
    4393           0 : }
    4394             : 
    4395             : 
    4396             : 
    4397             : bool
    4398           0 : RsaPssParams::InitIds(JSContext* cx, RsaPssParamsAtoms* atomsCache)
    4399             : {
    4400           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    4401             : 
    4402             :   // Initialize these in reverse order so that any failure leaves the first one
    4403             :   // uninitialized.
    4404           0 :   if (!atomsCache->saltLength_id.init(cx, "saltLength")) {
    4405           0 :     return false;
    4406             :   }
    4407           0 :   return true;
    4408             : }
    4409             : 
    4410             : bool
    4411           0 : RsaPssParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    4412             : {
    4413             :   // Passing a null JSContext is OK only if we're initing from null,
    4414             :   // Since in that case we will not have to do any property gets
    4415             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    4416             :   // checkers by static analysis tools
    4417           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    4418           0 :   RsaPssParamsAtoms* atomsCache = nullptr;
    4419           0 :   if (cx) {
    4420           0 :     atomsCache = GetAtomCache<RsaPssParamsAtoms>(cx);
    4421           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    4422           0 :       return false;
    4423             :     }
    4424             :   }
    4425             : 
    4426             :   // Per spec, we init the parent's members first
    4427           0 :   if (!Algorithm::Init(cx, val)) {
    4428           0 :     return false;
    4429             :   }
    4430             : 
    4431           0 :   bool isNull = val.isNullOrUndefined();
    4432             :   // We only need these if !isNull, in which case we have |cx|.
    4433           0 :   Maybe<JS::Rooted<JSObject *> > object;
    4434           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    4435           0 :   if (!isNull) {
    4436           0 :     MOZ_ASSERT(cx);
    4437           0 :     object.emplace(cx, &val.toObject());
    4438           0 :     temp.emplace(cx);
    4439             :   }
    4440           0 :   if (!isNull) {
    4441           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->saltLength_id, temp.ptr())) {
    4442           0 :       return false;
    4443             :     }
    4444             :   }
    4445           0 :   if (!isNull && !temp->isUndefined()) {
    4446           0 :     if (!ValueToPrimitive<uint32_t, eEnforceRange>(cx, temp.ref(), &mSaltLength)) {
    4447           0 :       return false;
    4448             :     }
    4449           0 :     mIsAnyMemberPresent = true;
    4450           0 :   } else if (cx) {
    4451             :     // Don't error out if we have no cx.  In that
    4452             :     // situation the caller is default-constructing us and we'll
    4453             :     // just assume they know what they're doing.
    4454           0 :     return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
    4455           0 :                              "'saltLength' member of RsaPssParams");
    4456             :   }
    4457           0 :   return true;
    4458             : }
    4459             : 
    4460             : bool
    4461           0 : RsaPssParams::Init(const nsAString& aJSON)
    4462             : {
    4463           0 :   AutoJSAPI jsapi;
    4464           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    4465           0 :   if (!cleanGlobal) {
    4466           0 :     return false;
    4467             :   }
    4468           0 :   if (!jsapi.Init(cleanGlobal)) {
    4469           0 :     return false;
    4470             :   }
    4471           0 :   JSContext* cx = jsapi.cx();
    4472           0 :   JS::Rooted<JS::Value> json(cx);
    4473           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    4474           0 :   NS_ENSURE_TRUE(ok, false);
    4475           0 :   return Init(cx, json);
    4476             : }
    4477             : 
    4478             : bool
    4479           0 : RsaPssParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    4480             : {
    4481           0 :   RsaPssParamsAtoms* atomsCache = GetAtomCache<RsaPssParamsAtoms>(cx);
    4482           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    4483           0 :     return false;
    4484             :   }
    4485             : 
    4486             :   // Per spec, we define the parent's members first
    4487           0 :   if (!Algorithm::ToObjectInternal(cx, rval)) {
    4488           0 :     return false;
    4489             :   }
    4490           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    4491             : 
    4492             :   do {
    4493             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    4494           0 :     JS::Rooted<JS::Value> temp(cx);
    4495           0 :     uint32_t const & currentValue = mSaltLength;
    4496           0 :     temp.setNumber(currentValue);
    4497           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->saltLength_id, temp, JSPROP_ENUMERATE)) {
    4498           0 :       return false;
    4499             :     }
    4500           0 :     break;
    4501             :   } while(0);
    4502             : 
    4503           0 :   return true;
    4504             : }
    4505             : 
    4506             : bool
    4507           0 : RsaPssParams::ToJSON(nsAString& aJSON) const
    4508             : {
    4509           0 :   AutoJSAPI jsapi;
    4510           0 :   jsapi.Init();
    4511           0 :   JSContext *cx = jsapi.cx();
    4512             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    4513             :   // because we'll only be creating objects, in ways that have no
    4514             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    4515             :   // which likewise guarantees no side-effects for the sorts of
    4516             :   // things we will pass it.
    4517           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    4518           0 :   JS::Rooted<JS::Value> val(cx);
    4519           0 :   if (!ToObjectInternal(cx, &val)) {
    4520           0 :     return false;
    4521             :   }
    4522           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    4523           0 :   return StringifyToJSON(cx, obj, aJSON);
    4524             : }
    4525             : 
    4526             : void
    4527           0 : RsaPssParams::TraceDictionary(JSTracer* trc)
    4528             : {
    4529           0 :   Algorithm::TraceDictionary(trc);
    4530           0 : }
    4531             : 
    4532             : RsaPssParams&
    4533           0 : RsaPssParams::operator=(const RsaPssParams& aOther)
    4534             : {
    4535           0 :   Algorithm::operator=(aOther);
    4536           0 :   mSaltLength = aOther.mSaltLength;
    4537           0 :   return *this;
    4538             : }
    4539             : 
    4540             : namespace binding_detail {
    4541             : } // namespace binding_detail
    4542             : 
    4543             : 
    4544             : 
    4545           0 : HmacDerivedKeyParams::HmacDerivedKeyParams()
    4546           0 :   : HmacImportParams(FastDictionaryInitializer())
    4547             : {
    4548             :   // Safe to pass a null context if we pass a null value
    4549           0 :   Init(nullptr, JS::NullHandleValue);
    4550           0 : }
    4551             : 
    4552             : 
    4553             : bool
    4554           0 : HmacDerivedKeyParams::InitIds(JSContext* cx, HmacDerivedKeyParamsAtoms* atomsCache)
    4555             : {
    4556           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    4557             : 
    4558             :   // Initialize these in reverse order so that any failure leaves the first one
    4559             :   // uninitialized.
    4560           0 :   if (!atomsCache->length_id.init(cx, "length")) {
    4561           0 :     return false;
    4562             :   }
    4563           0 :   return true;
    4564             : }
    4565             : 
    4566             : bool
    4567           0 : HmacDerivedKeyParams::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    4568             : {
    4569             :   // Passing a null JSContext is OK only if we're initing from null,
    4570             :   // Since in that case we will not have to do any property gets
    4571             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    4572             :   // checkers by static analysis tools
    4573           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    4574           0 :   HmacDerivedKeyParamsAtoms* atomsCache = nullptr;
    4575           0 :   if (cx) {
    4576           0 :     atomsCache = GetAtomCache<HmacDerivedKeyParamsAtoms>(cx);
    4577           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    4578           0 :       return false;
    4579             :     }
    4580             :   }
    4581             : 
    4582             :   // Per spec, we init the parent's members first
    4583           0 :   if (!HmacImportParams::Init(cx, val)) {
    4584           0 :     return false;
    4585             :   }
    4586             : 
    4587           0 :   bool isNull = val.isNullOrUndefined();
    4588             :   // We only need these if !isNull, in which case we have |cx|.
    4589           0 :   Maybe<JS::Rooted<JSObject *> > object;
    4590           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    4591           0 :   if (!isNull) {
    4592           0 :     MOZ_ASSERT(cx);
    4593           0 :     object.emplace(cx, &val.toObject());
    4594           0 :     temp.emplace(cx);
    4595             :   }
    4596           0 :   if (!isNull) {
    4597           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->length_id, temp.ptr())) {
    4598           0 :       return false;
    4599             :     }
    4600             :   }
    4601           0 :   if (!isNull && !temp->isUndefined()) {
    4602           0 :     mLength.Construct();
    4603           0 :     if (!ValueToPrimitive<uint32_t, eEnforceRange>(cx, temp.ref(), &(mLength.Value()))) {
    4604           0 :       return false;
    4605             :     }
    4606           0 :     mIsAnyMemberPresent = true;
    4607             :   }
    4608           0 :   return true;
    4609             : }
    4610             : 
    4611             : bool
    4612           0 : HmacDerivedKeyParams::Init(const nsAString& aJSON)
    4613             : {
    4614           0 :   AutoJSAPI jsapi;
    4615           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    4616           0 :   if (!cleanGlobal) {
    4617           0 :     return false;
    4618             :   }
    4619           0 :   if (!jsapi.Init(cleanGlobal)) {
    4620           0 :     return false;
    4621             :   }
    4622           0 :   JSContext* cx = jsapi.cx();
    4623           0 :   JS::Rooted<JS::Value> json(cx);
    4624           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    4625           0 :   NS_ENSURE_TRUE(ok, false);
    4626           0 :   return Init(cx, json);
    4627             : }
    4628             : 
    4629             : bool
    4630           0 : HmacDerivedKeyParams::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    4631             : {
    4632           0 :   HmacDerivedKeyParamsAtoms* atomsCache = GetAtomCache<HmacDerivedKeyParamsAtoms>(cx);
    4633           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    4634           0 :     return false;
    4635             :   }
    4636             : 
    4637             :   // Per spec, we define the parent's members first
    4638           0 :   if (!HmacImportParams::ToObjectInternal(cx, rval)) {
    4639           0 :     return false;
    4640             :   }
    4641           0 :   JS::Rooted<JSObject*> obj(cx, &rval.toObject());
    4642             : 
    4643           0 :   if (mLength.WasPassed()) {
    4644             :     do {
    4645             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    4646           0 :       JS::Rooted<JS::Value> temp(cx);
    4647           0 :       uint32_t const & currentValue = mLength.InternalValue();
    4648           0 :       temp.setNumber(currentValue);
    4649           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->length_id, temp, JSPROP_ENUMERATE)) {
    4650           0 :         return false;
    4651             :       }
    4652           0 :       break;
    4653             :     } while(0);
    4654             :   }
    4655             : 
    4656           0 :   return true;
    4657             : }
    4658             : 
    4659             : bool
    4660           0 : HmacDerivedKeyParams::ToJSON(nsAString& aJSON) const
    4661             : {
    4662           0 :   AutoJSAPI jsapi;
    4663           0 :   jsapi.Init();
    4664           0 :   JSContext *cx = jsapi.cx();
    4665             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    4666             :   // because we'll only be creating objects, in ways that have no
    4667             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    4668             :   // which likewise guarantees no side-effects for the sorts of
    4669             :   // things we will pass it.
    4670           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    4671           0 :   JS::Rooted<JS::Value> val(cx);
    4672           0 :   if (!ToObjectInternal(cx, &val)) {
    4673           0 :     return false;
    4674             :   }
    4675           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    4676           0 :   return StringifyToJSON(cx, obj, aJSON);
    4677             : }
    4678             : 
    4679             : void
    4680           0 : HmacDerivedKeyParams::TraceDictionary(JSTracer* trc)
    4681             : {
    4682           0 :   HmacImportParams::TraceDictionary(trc);
    4683           0 : }
    4684             : 
    4685             : namespace binding_detail {
    4686             : } // namespace binding_detail
    4687             : 
    4688             : 
    4689             : namespace CryptoKeyBinding {
    4690             : 
    4691             : static bool
    4692           0 : get_type(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::CryptoKey* self, JSJitGetterCallArgs args)
    4693             : {
    4694           0 :   DOMString result;
    4695           0 :   self->GetType(result);
    4696           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    4697           0 :   if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
    4698           0 :     return false;
    4699             :   }
    4700           0 :   return true;
    4701             : }
    4702             : 
    4703             : static const JSJitInfo type_getterinfo = {
    4704             :   { (JSJitGetterOp)get_type },
    4705             :   { prototypes::id::CryptoKey },
    4706             :   { PrototypeTraits<prototypes::id::CryptoKey>::Depth },
    4707             :   JSJitInfo::Getter,
    4708             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    4709             :   JSVAL_TYPE_STRING,  /* returnType.  Not relevant for setters. */
    4710             :   false,  /* isInfallible. False in setters. */
    4711             :   false,  /* isMovable.  Not relevant for setters. */
    4712             :   false, /* isEliminatable.  Not relevant for setters. */
    4713             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    4714             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    4715             :   false,  /* isTypedMethod.  Only relevant for methods. */
    4716             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    4717             : };
    4718             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    4719             : static_assert(0 < 3, "There is no slot for us");
    4720             : 
    4721             : static bool
    4722           0 : get_extractable(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::CryptoKey* self, JSJitGetterCallArgs args)
    4723             : {
    4724           0 :   bool result(self->Extractable());
    4725           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    4726           0 :   args.rval().setBoolean(result);
    4727           0 :   return true;
    4728             : }
    4729             : 
    4730             : static const JSJitInfo extractable_getterinfo = {
    4731             :   { (JSJitGetterOp)get_extractable },
    4732             :   { prototypes::id::CryptoKey },
    4733             :   { PrototypeTraits<prototypes::id::CryptoKey>::Depth },
    4734             :   JSJitInfo::Getter,
    4735             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    4736             :   JSVAL_TYPE_BOOLEAN,  /* returnType.  Not relevant for setters. */
    4737             :   true,  /* isInfallible. False in setters. */
    4738             :   false,  /* isMovable.  Not relevant for setters. */
    4739             :   false, /* isEliminatable.  Not relevant for setters. */
    4740             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    4741             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    4742             :   false,  /* isTypedMethod.  Only relevant for methods. */
    4743             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    4744             : };
    4745             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    4746             : static_assert(0 < 3, "There is no slot for us");
    4747             : 
    4748             : static bool
    4749           0 : get_algorithm(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::CryptoKey* self, JSJitGetterCallArgs args)
    4750             : {
    4751             :   // Have to either root across the getter call or reget after.
    4752             :   bool isXray;
    4753           0 :   JS::Rooted<JSObject*> slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray));
    4754           0 :   if (!slotStorage) {
    4755           0 :     return false;
    4756             :   }
    4757           0 :   const size_t slotIndex = isXray ? (xpc::JSSLOT_EXPANDO_COUNT + 0) : (DOM_INSTANCE_RESERVED_SLOTS + 0);
    4758           0 :   MOZ_ASSERT(JSCLASS_RESERVED_SLOTS(js::GetObjectClass(slotStorage)) > slotIndex);
    4759             :   {
    4760             :     // Scope for cachedVal
    4761           0 :     JS::Value cachedVal = js::GetReservedSlot(slotStorage, slotIndex);
    4762           0 :     if (!cachedVal.isUndefined()) {
    4763           0 :       args.rval().set(cachedVal);
    4764             :       // The cached value is in the compartment of slotStorage,
    4765             :       // so wrap into the caller compartment as needed.
    4766           0 :       return MaybeWrapObjectValue(cx, args.rval());
    4767             :     }
    4768             :   }
    4769             : 
    4770           0 :   binding_detail::FastErrorResult rv;
    4771           0 :   JS::Rooted<JSObject*> result(cx);
    4772           0 :   self->GetAlgorithm(cx, &result, rv);
    4773           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    4774           0 :     return false;
    4775             :   }
    4776           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    4777             :   {
    4778           0 :     JS::Rooted<JSObject*> conversionScope(cx, isXray ? obj : slotStorage);
    4779           0 :     JSAutoCompartment ac(cx, conversionScope);
    4780             :     do { // block we break out of when done wrapping
    4781           0 :       JS::ExposeObjectToActiveJS(result);
    4782           0 :       args.rval().setObject(*result);
    4783           0 :       if (!MaybeWrapObjectValue(cx, args.rval())) {
    4784           0 :         return false;
    4785             :       }
    4786           0 :       break;
    4787             :     } while (0);
    4788             :   }
    4789             :   { // And now store things in the compartment of our slotStorage.
    4790           0 :     JSAutoCompartment ac(cx, slotStorage);
    4791             :     // Make a copy so that we don't do unnecessary wrapping on args.rval().
    4792           0 :     JS::Rooted<JS::Value> storedVal(cx, args.rval());
    4793           0 :     if (!MaybeWrapObjectValue(cx, &storedVal)) {
    4794           0 :       return false;
    4795             :     }
    4796           0 :     js::SetReservedSlot(slotStorage, slotIndex, storedVal);
    4797           0 :     if (!isXray) {
    4798             :       // In the Xray case we don't need to do this, because getting the
    4799             :       // expando object already preserved our wrapper.
    4800           0 :       PreserveWrapper(self);
    4801             :     }
    4802             :   }
    4803             :   // And now make sure args.rval() is in the caller compartment
    4804           0 :   return MaybeWrapObjectValue(cx, args.rval());
    4805             : }
    4806             : 
    4807             : static const JSJitInfo algorithm_getterinfo = {
    4808             :   { (JSJitGetterOp)get_algorithm },
    4809             :   { prototypes::id::CryptoKey },
    4810             :   { PrototypeTraits<prototypes::id::CryptoKey>::Depth },
    4811             :   JSJitInfo::Getter,
    4812             :   JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
    4813             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    4814             :   false,  /* isInfallible. False in setters. */
    4815             :   false,  /* isMovable.  Not relevant for setters. */
    4816             :   false, /* isEliminatable.  Not relevant for setters. */
    4817             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    4818             :   true, /* isLazilyCachedInSlot.  Only relevant for getters. */
    4819             :   false,  /* isTypedMethod.  Only relevant for methods. */
    4820             :   (DOM_INSTANCE_RESERVED_SLOTS + 0)   /* Reserved slot index, if we're stored in a slot, else 0. */
    4821             : };
    4822             : static_assert((DOM_INSTANCE_RESERVED_SLOTS + 0) <= JSJitInfo::maxSlotIndex, "We won't fit");
    4823             : static_assert((DOM_INSTANCE_RESERVED_SLOTS + 0) < 3, "There is no slot for us");
    4824             : 
    4825             : static bool
    4826           0 : get_usages(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::CryptoKey* self, JSJitGetterCallArgs args)
    4827             : {
    4828             :   // Have to either root across the getter call or reget after.
    4829             :   bool isXray;
    4830           0 :   JS::Rooted<JSObject*> slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray));
    4831           0 :   if (!slotStorage) {
    4832           0 :     return false;
    4833             :   }
    4834           0 :   const size_t slotIndex = isXray ? (xpc::JSSLOT_EXPANDO_COUNT + 1) : (DOM_INSTANCE_RESERVED_SLOTS + 1);
    4835           0 :   MOZ_ASSERT(JSCLASS_RESERVED_SLOTS(js::GetObjectClass(slotStorage)) > slotIndex);
    4836             :   {
    4837             :     // Scope for cachedVal
    4838           0 :     JS::Value cachedVal = js::GetReservedSlot(slotStorage, slotIndex);
    4839           0 :     if (!cachedVal.isUndefined()) {
    4840           0 :       args.rval().set(cachedVal);
    4841             :       // The cached value is in the compartment of slotStorage,
    4842             :       // so wrap into the caller compartment as needed.
    4843           0 :       return MaybeWrapNonDOMObjectValue(cx, args.rval());
    4844             :     }
    4845             :   }
    4846             : 
    4847           0 :   nsTArray<nsString> result;
    4848           0 :   self->GetUsages(result);
    4849           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    4850             :   {
    4851           0 :     JS::Rooted<JSObject*> conversionScope(cx, isXray ? obj : slotStorage);
    4852           0 :     JSAutoCompartment ac(cx, conversionScope);
    4853             :     do { // block we break out of when done wrapping
    4854             : 
    4855           0 :       uint32_t length = result.Length();
    4856           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    4857           0 :       if (!returnArray) {
    4858           0 :         return false;
    4859             :       }
    4860             :       // Scope for 'tmp'
    4861             :       {
    4862           0 :         JS::Rooted<JS::Value> tmp(cx);
    4863           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    4864             :           // Control block to let us common up the JS_DefineElement calls when there
    4865             :           // are different ways to succeed at wrapping the object.
    4866             :           do {
    4867           0 :             if (!xpc::NonVoidStringToJsval(cx, result[sequenceIdx0], &tmp)) {
    4868           0 :               return false;
    4869             :             }
    4870           0 :             break;
    4871             :           } while (0);
    4872           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    4873             :                                 JSPROP_ENUMERATE)) {
    4874           0 :             return false;
    4875             :           }
    4876             :         }
    4877             :       }
    4878           0 :       args.rval().setObject(*returnArray);
    4879           0 :       break;
    4880             :     } while (0);
    4881           0 :     JS::Rooted<JSObject*> rvalObj(cx, &args.rval().toObject());
    4882           0 :     if (!JS_FreezeObject(cx, rvalObj)) {
    4883           0 :       return false;
    4884             :     }
    4885             :   }
    4886             :   { // And now store things in the compartment of our slotStorage.
    4887           0 :     JSAutoCompartment ac(cx, slotStorage);
    4888             :     // Make a copy so that we don't do unnecessary wrapping on args.rval().
    4889           0 :     JS::Rooted<JS::Value> storedVal(cx, args.rval());
    4890           0 :     if (!MaybeWrapNonDOMObjectValue(cx, &storedVal)) {
    4891           0 :       return false;
    4892             :     }
    4893           0 :     js::SetReservedSlot(slotStorage, slotIndex, storedVal);
    4894           0 :     if (!isXray) {
    4895             :       // In the Xray case we don't need to do this, because getting the
    4896             :       // expando object already preserved our wrapper.
    4897           0 :       PreserveWrapper(self);
    4898             :     }
    4899             :   }
    4900             :   // And now make sure args.rval() is in the caller compartment
    4901           0 :   return MaybeWrapNonDOMObjectValue(cx, args.rval());
    4902             : }
    4903             : 
    4904             : static const JSJitInfo usages_getterinfo = {
    4905             :   { (JSJitGetterOp)get_usages },
    4906             :   { prototypes::id::CryptoKey },
    4907             :   { PrototypeTraits<prototypes::id::CryptoKey>::Depth },
    4908             :   JSJitInfo::Getter,
    4909             :   JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
    4910             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    4911             :   false,  /* isInfallible. False in setters. */
    4912             :   true,  /* isMovable.  Not relevant for setters. */
    4913             :   true, /* isEliminatable.  Not relevant for setters. */
    4914             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    4915             :   true, /* isLazilyCachedInSlot.  Only relevant for getters. */
    4916             :   false,  /* isTypedMethod.  Only relevant for methods. */
    4917             :   (DOM_INSTANCE_RESERVED_SLOTS + 1)   /* Reserved slot index, if we're stored in a slot, else 0. */
    4918             : };
    4919             : static_assert((DOM_INSTANCE_RESERVED_SLOTS + 1) <= JSJitInfo::maxSlotIndex, "We won't fit");
    4920             : static_assert((DOM_INSTANCE_RESERVED_SLOTS + 1) < 3, "There is no slot for us");
    4921             : 
    4922             : static bool
    4923           0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
    4924             : {
    4925           0 :   mozilla::dom::CryptoKey* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::CryptoKey>(obj);
    4926             :   // We don't want to preserve if we don't have a wrapper, and we
    4927             :   // obviously can't preserve if we're not initialized.
    4928           0 :   if (self && self->GetWrapperPreserveColor()) {
    4929           0 :     PreserveWrapper(self);
    4930             :   }
    4931           0 :   return true;
    4932             : }
    4933             : 
    4934             : static void
    4935           0 : _finalize(js::FreeOp* fop, JSObject* obj)
    4936             : {
    4937           0 :   mozilla::dom::CryptoKey* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::CryptoKey>(obj);
    4938           0 :   if (self) {
    4939           0 :     ClearWrapper(self, self, obj);
    4940           0 :     AddForDeferredFinalization<mozilla::dom::CryptoKey>(self);
    4941             :   }
    4942           0 : }
    4943             : 
    4944             : static void
    4945           0 : _objectMoved(JSObject* obj, const JSObject* old)
    4946             : {
    4947           0 :   mozilla::dom::CryptoKey* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::CryptoKey>(obj);
    4948           0 :   if (self) {
    4949           0 :     UpdateWrapper(self, self, obj, old);
    4950             :   }
    4951           0 : }
    4952             : 
    4953             : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
    4954             : #if defined(__clang__)
    4955             : #pragma clang diagnostic push
    4956             : #pragma clang diagnostic ignored "-Wmissing-braces"
    4957             : #endif
    4958             : static const JSPropertySpec sAttributes_specs[] = {
    4959             :   { "type", JSPROP_SHARED | JSPROP_ENUMERATE, GenericBindingGetter, &type_getterinfo, nullptr, nullptr },
    4960             :   { "extractable", JSPROP_SHARED | JSPROP_ENUMERATE, GenericBindingGetter, &extractable_getterinfo, nullptr, nullptr },
    4961             :   { "algorithm", JSPROP_SHARED | JSPROP_ENUMERATE, GenericBindingGetter, &algorithm_getterinfo, nullptr, nullptr },
    4962             :   { "usages", JSPROP_SHARED | JSPROP_ENUMERATE, GenericBindingGetter, &usages_getterinfo, nullptr, nullptr },
    4963             :   { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
    4964             : };
    4965             : #if defined(__clang__)
    4966             : #pragma clang diagnostic pop
    4967             : #endif
    4968             : 
    4969             : 
    4970             : // Can't be const because the pref-enabled boolean needs to be writable
    4971             : static Prefable<const JSPropertySpec> sAttributes[] = {
    4972             :   { nullptr, &sAttributes_specs[0] },
    4973             :   { nullptr, nullptr }
    4974             : };
    4975             : 
    4976             : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
    4977             :     "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
    4978             : static_assert(4 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
    4979             :     "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
    4980             : 
    4981             : 
    4982             : static uint16_t sNativeProperties_sortedPropertyIndices[4];
    4983             : static PropertyInfo sNativeProperties_propertyInfos[4];
    4984             : 
    4985             : static const NativePropertiesN<1> sNativeProperties = {
    4986             :   false, 0,
    4987             :   false, 0,
    4988             :   false, 0,
    4989             :   true,  0 /* sAttributes */,
    4990             :   false, 0,
    4991             :   false, 0,
    4992             :   false, 0,
    4993             :   -1,
    4994             :   4,
    4995             :   sNativeProperties_sortedPropertyIndices,
    4996             :   {
    4997             :     { sAttributes, &sNativeProperties_propertyInfos[0] }
    4998             :   }
    4999             : };
    5000             : static_assert(4 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
    5001             :     "We have a property info count that is oversized");
    5002             : 
    5003             : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
    5004             :   {
    5005             :     "Function",
    5006             :     JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
    5007             :     &sBoringInterfaceObjectClassClassOps,
    5008             :     JS_NULL_CLASS_SPEC,
    5009             :     JS_NULL_CLASS_EXT,
    5010             :     &sInterfaceObjectClassObjectOps
    5011             :   },
    5012             :   eInterface,
    5013             :   true,
    5014             :   prototypes::id::CryptoKey,
    5015             :   PrototypeTraits<prototypes::id::CryptoKey>::Depth,
    5016             :   sNativePropertyHooks,
    5017             :   "function CryptoKey() {\n    [native code]\n}",
    5018             :   JS::GetRealmFunctionPrototype
    5019             : };
    5020             : 
    5021             : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
    5022             :   {
    5023             :     "CryptoKeyPrototype",
    5024             :     JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
    5025             :     JS_NULL_CLASS_OPS,
    5026             :     JS_NULL_CLASS_SPEC,
    5027             :     JS_NULL_CLASS_EXT,
    5028             :     JS_NULL_OBJECT_OPS
    5029             :   },
    5030             :   eInterfacePrototype,
    5031             :   false,
    5032             :   prototypes::id::CryptoKey,
    5033             :   PrototypeTraits<prototypes::id::CryptoKey>::Depth,
    5034             :   sNativePropertyHooks,
    5035             :   "[object CryptoKeyPrototype]",
    5036             :   JS::GetRealmObjectPrototype
    5037             : };
    5038             : 
    5039             : JSObject*
    5040           0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
    5041             : {
    5042           0 :   return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
    5043             : }
    5044             : 
    5045             : static const js::ClassOps sClassOps = {
    5046             :   _addProperty, /* addProperty */
    5047             :   nullptr,               /* delProperty */
    5048             :   nullptr,               /* getProperty */
    5049             :   nullptr,               /* setProperty */
    5050             :   nullptr,               /* enumerate */
    5051             :   nullptr, /* newEnumerate */
    5052             :   nullptr, /* resolve */
    5053             :   nullptr, /* mayResolve */
    5054             :   _finalize, /* finalize */
    5055             :   nullptr, /* call */
    5056             :   nullptr,               /* hasInstance */
    5057             :   nullptr,               /* construct */
    5058             :   nullptr, /* trace */
    5059             : };
    5060             : 
    5061             : static const js::ClassExtension sClassExtension = {
    5062             :   nullptr, /* weakmapKeyDelegateOp */
    5063             :   _objectMoved /* objectMovedOp */
    5064             : };
    5065             : 
    5066             : static const DOMJSClass sClass = {
    5067             :   { "CryptoKey",
    5068             :     JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(3),
    5069             :     &sClassOps,
    5070             :     JS_NULL_CLASS_SPEC,
    5071             :     &sClassExtension,
    5072             :     JS_NULL_OBJECT_OPS
    5073             :   },
    5074             :   { prototypes::id::CryptoKey, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
    5075             :   IsBaseOf<nsISupports, mozilla::dom::CryptoKey >::value,
    5076             :   sNativePropertyHooks,
    5077             :   FindAssociatedGlobalForNative<mozilla::dom::CryptoKey>::Get,
    5078             :   GetProtoObjectHandle,
    5079             :   GetCCParticipant<mozilla::dom::CryptoKey>::Get()
    5080             : };
    5081             : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
    5082             :               "Must have the right minimal number of reserved slots.");
    5083             : static_assert(3 >= 3,
    5084             :               "Must have enough reserved slots.");
    5085             : 
    5086             : const JSClass*
    5087           0 : GetJSClass()
    5088             : {
    5089           0 :   return sClass.ToJSClass();
    5090             : }
    5091             : 
    5092             : bool
    5093           0 : Wrap(JSContext* aCx, mozilla::dom::CryptoKey* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
    5094             : {
    5095             :   MOZ_ASSERT(static_cast<mozilla::dom::CryptoKey*>(aObject) ==
    5096             :              reinterpret_cast<mozilla::dom::CryptoKey*>(aObject),
    5097             :              "Multiple inheritance for mozilla::dom::CryptoKey is broken.");
    5098           0 :   MOZ_ASSERT(ToSupportsIsCorrect(aObject));
    5099           0 :   MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
    5100           0 :   MOZ_ASSERT(!aCache->GetWrapper(),
    5101             :              "You should probably not be using Wrap() directly; use "
    5102             :              "GetOrCreateDOMReflector instead");
    5103             : 
    5104           0 :   MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
    5105             :              "nsISupports must be on our primary inheritance chain");
    5106             : 
    5107           0 :   JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
    5108           0 :   if (!global) {
    5109           0 :     return false;
    5110             :   }
    5111           0 :   MOZ_ASSERT(JS_IsGlobalObject(global));
    5112           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(global));
    5113             : 
    5114             :   // That might have ended up wrapping us already, due to the wonders
    5115             :   // of XBL.  Check for that, and bail out as needed.
    5116           0 :   aReflector.set(aCache->GetWrapper());
    5117           0 :   if (aReflector) {
    5118             : #ifdef DEBUG
    5119           0 :     binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
    5120             : #endif // DEBUG
    5121           0 :     return true;
    5122             :   }
    5123             : 
    5124           0 :   JSAutoCompartment ac(aCx, global);
    5125           0 :   JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
    5126           0 :   if (!canonicalProto) {
    5127           0 :     return false;
    5128             :   }
    5129           0 :   JS::Rooted<JSObject*> proto(aCx);
    5130           0 :   if (aGivenProto) {
    5131           0 :     proto = aGivenProto;
    5132             :     // Unfortunately, while aGivenProto was in the compartment of aCx
    5133             :     // coming in, we changed compartments to that of "parent" so may need
    5134             :     // to wrap the proto here.
    5135           0 :     if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
    5136           0 :       if (!JS_WrapObject(aCx, &proto)) {
    5137           0 :         return false;
    5138             :       }
    5139             :     }
    5140             :   } else {
    5141           0 :     proto = canonicalProto;
    5142             :   }
    5143             : 
    5144           0 :   BindingJSObjectCreator<mozilla::dom::CryptoKey> creator(aCx);
    5145           0 :   creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
    5146           0 :   if (!aReflector) {
    5147           0 :     return false;
    5148             :   }
    5149             : 
    5150           0 :   aCache->SetWrapper(aReflector);
    5151           0 :   creator.InitializationSucceeded();
    5152             : 
    5153           0 :   MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
    5154             :              aCache->GetWrapperPreserveColor() == aReflector);
    5155             :   // If proto != canonicalProto, we have to preserve our wrapper;
    5156             :   // otherwise we won't be able to properly recreate it later, since
    5157             :   // we won't know what proto to use.  Note that we don't check
    5158             :   // aGivenProto here, since it's entirely possible (and even
    5159             :   // somewhat common) to have a non-null aGivenProto which is the
    5160             :   // same as canonicalProto.
    5161           0 :   if (proto != canonicalProto) {
    5162           0 :     PreserveWrapper(aObject);
    5163             :   }
    5164             : 
    5165           0 :   return true;
    5166             : }
    5167             : 
    5168             : // This may allocate too many slots, because we only really need
    5169             : // slots for our non-interface-typed members that we cache.  But
    5170             : // allocating slots only for those would make the slot index
    5171             : // computations much more complicated, so let's do this the simple
    5172             : // way for now.
    5173             : DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 2);
    5174             : 
    5175             : const NativePropertyHooks sNativePropertyHooks[] = { {
    5176             :   nullptr,
    5177             :   nullptr,
    5178             :   nullptr,
    5179             :   { sNativeProperties.Upcast(), nullptr },
    5180             :   prototypes::id::CryptoKey,
    5181             :   constructors::id::CryptoKey,
    5182             :   nullptr,
    5183             :   &sXrayExpandoObjectClass
    5184             : } };
    5185             : 
    5186             : void
    5187           0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
    5188             : {
    5189           0 :   JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
    5190           0 :   if (!parentProto) {
    5191           0 :     return;
    5192             :   }
    5193             : 
    5194           0 :   JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
    5195           0 :   if (!constructorProto) {
    5196           0 :     return;
    5197             :   }
    5198             : 
    5199             :   static bool sIdsInited = false;
    5200           0 :   if (!sIdsInited && NS_IsMainThread()) {
    5201           0 :     if (!InitIds(aCx, sNativeProperties.Upcast())) {
    5202           0 :       return;
    5203             :     }
    5204           0 :     sIdsInited = true;
    5205             :   }
    5206             : 
    5207           0 :   JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::CryptoKey);
    5208           0 :   JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::CryptoKey);
    5209           0 :   dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
    5210             :                               &sPrototypeClass.mBase, protoCache,
    5211             :                               constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
    5212             :                               interfaceCache,
    5213             :                               sNativeProperties.Upcast(),
    5214             :                               nullptr,
    5215             :                               "CryptoKey", aDefineOnGlobal,
    5216             :                               nullptr,
    5217           0 :                               false);
    5218             : }
    5219             : 
    5220             : JS::Handle<JSObject*>
    5221           0 : GetProtoObjectHandle(JSContext* aCx)
    5222             : {
    5223             :   /* Get the interface prototype object for this class.  This will create the
    5224             :      object as needed. */
    5225           0 :   bool aDefineOnGlobal = true;
    5226             : 
    5227             :   /* Make sure our global is sane.  Hopefully we can remove this sometime */
    5228           0 :   JSObject* global = JS::CurrentGlobalOrNull(aCx);
    5229           0 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
    5230           0 :     return nullptr;
    5231             :   }
    5232             : 
    5233             :   /* Check to see whether the interface objects are already installed */
    5234           0 :   ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
    5235           0 :   if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::CryptoKey)) {
    5236           0 :     JS::Rooted<JSObject*> rootedGlobal(aCx, global);
    5237           0 :     CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
    5238             :   }
    5239             : 
    5240             :   /*
    5241             :    * The object might _still_ be null, but that's OK.
    5242             :    *
    5243             :    * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
    5244             :    * traced by TraceProtoAndIfaceCache() and its contents are never
    5245             :    * changed after they have been set.
    5246             :    *
    5247             :    * Calling address() avoids the read read barrier that does gray
    5248             :    * unmarking, but it's not possible for the object to be gray here.
    5249             :    */
    5250             : 
    5251           0 :   const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::CryptoKey);
    5252           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
    5253           0 :   return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
    5254             : }
    5255             : 
    5256             : JS::Handle<JSObject*>
    5257           0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
    5258             : {
    5259             :   /* Get the interface object for this class.  This will create the object as
    5260             :      needed. */
    5261             : 
    5262             :   /* Make sure our global is sane.  Hopefully we can remove this sometime */
    5263           0 :   JSObject* global = JS::CurrentGlobalOrNull(aCx);
    5264           0 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
    5265           0 :     return nullptr;
    5266             :   }
    5267             : 
    5268             :   /* Check to see whether the interface objects are already installed */
    5269           0 :   ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
    5270           0 :   if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::CryptoKey)) {
    5271           0 :     JS::Rooted<JSObject*> rootedGlobal(aCx, global);
    5272           0 :     CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
    5273             :   }
    5274             : 
    5275             :   /*
    5276             :    * The object might _still_ be null, but that's OK.
    5277             :    *
    5278             :    * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
    5279             :    * traced by TraceProtoAndIfaceCache() and its contents are never
    5280             :    * changed after they have been set.
    5281             :    *
    5282             :    * Calling address() avoids the read read barrier that does gray
    5283             :    * unmarking, but it's not possible for the object to be gray here.
    5284             :    */
    5285             : 
    5286           0 :   const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::CryptoKey);
    5287           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
    5288           0 :   return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
    5289             : }
    5290             : 
    5291             : JSObject*
    5292           0 : GetConstructorObject(JSContext* aCx)
    5293             : {
    5294           0 :   return GetConstructorObjectHandle(aCx);
    5295             : }
    5296             : 
    5297             : } // namespace CryptoKeyBinding
    5298             : 
    5299             : 
    5300             : 
    5301             : namespace SubtleCryptoBinding {
    5302             : 
    5303             : static bool
    5304           0 : encrypt(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5305             : {
    5306           0 :   if (MOZ_UNLIKELY(args.length() < 3)) {
    5307           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "SubtleCrypto.encrypt");
    5308             :   }
    5309           0 :   ObjectOrString arg0;
    5310           0 :   ObjectOrStringArgument arg0_holder(arg0);
    5311             :   {
    5312           0 :     bool done = false, failed = false, tryNext;
    5313           0 :     if (args[0].isObject()) {
    5314           0 :       if (!arg0_holder.SetToObject(cx, &args[0].toObject(), false)) {
    5315           0 :         return false;
    5316             :       }
    5317           0 :       done = true;
    5318             :     } else {
    5319             :       do {
    5320           0 :         done = (failed = !arg0_holder.TrySetToString(cx, args[0], tryNext)) || !tryNext;
    5321           0 :         break;
    5322             :       } while (0);
    5323             :     }
    5324           0 :     if (failed) {
    5325           0 :       return false;
    5326             :     }
    5327           0 :     if (!done) {
    5328           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 1 of SubtleCrypto.encrypt", "Object");
    5329           0 :       return false;
    5330             :     }
    5331             :   }
    5332           0 :   NonNull<mozilla::dom::CryptoKey> arg1;
    5333           0 :   if (args[1].isObject()) {
    5334             :     {
    5335           0 :       nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(args[1], arg1);
    5336           0 :       if (NS_FAILED(rv)) {
    5337           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 2 of SubtleCrypto.encrypt", "CryptoKey");
    5338           0 :         return false;
    5339             :       }
    5340             :     }
    5341             :   } else {
    5342           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of SubtleCrypto.encrypt");
    5343           0 :     return false;
    5344             :   }
    5345           0 :   ArrayBufferViewOrArrayBuffer arg2;
    5346           0 :   ArrayBufferViewOrArrayBufferArgument arg2_holder(arg2);
    5347             :   {
    5348           0 :     bool done = false, failed = false, tryNext;
    5349           0 :     if (args[2].isObject()) {
    5350           0 :       done = (failed = !arg2_holder.TrySetToArrayBufferView(cx, args[2], tryNext, false)) || !tryNext ||
    5351           0 :              (failed = !arg2_holder.TrySetToArrayBuffer(cx, args[2], tryNext, false)) || !tryNext;
    5352             : 
    5353             :     }
    5354           0 :     if (failed) {
    5355           0 :       return false;
    5356             :     }
    5357           0 :     if (!done) {
    5358           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 3 of SubtleCrypto.encrypt", "ArrayBufferView, ArrayBuffer");
    5359           0 :       return false;
    5360             :     }
    5361             :   }
    5362           0 :   binding_detail::FastErrorResult rv;
    5363           0 :   auto result(StrongOrRawPtr<Promise>(self->Encrypt(cx, Constify(arg0), NonNullHelper(arg1), Constify(arg2), rv)));
    5364           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    5365           0 :     return false;
    5366             :   }
    5367           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    5368           0 :   if (!ToJSValue(cx, result, args.rval())) {
    5369           0 :     return false;
    5370             :   }
    5371           0 :   return true;
    5372             : }
    5373             : 
    5374             : static bool
    5375           0 : encrypt_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5376             : {
    5377             :   // Make sure to save the callee before someone maybe messes
    5378             :   // with rval().
    5379           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    5380           0 :   bool ok = encrypt(cx, obj, self, args);
    5381           0 :   if (ok) {
    5382           0 :     return true;
    5383             :   }
    5384           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    5385           0 :                                    args.rval());
    5386             : }
    5387             : 
    5388             : static const JSJitInfo encrypt_methodinfo = {
    5389             :   { (JSJitGetterOp)encrypt_promiseWrapper },
    5390             :   { prototypes::id::SubtleCrypto },
    5391             :   { PrototypeTraits<prototypes::id::SubtleCrypto>::Depth },
    5392             :   JSJitInfo::Method,
    5393             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    5394             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    5395             :   false,  /* isInfallible. False in setters. */
    5396             :   false,  /* isMovable.  Not relevant for setters. */
    5397             :   false, /* isEliminatable.  Not relevant for setters. */
    5398             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    5399             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    5400             :   false,  /* isTypedMethod.  Only relevant for methods. */
    5401             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    5402             : };
    5403             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    5404             : static_assert(0 < 1, "There is no slot for us");
    5405             : 
    5406             : static bool
    5407           0 : decrypt(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5408             : {
    5409           0 :   if (MOZ_UNLIKELY(args.length() < 3)) {
    5410           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "SubtleCrypto.decrypt");
    5411             :   }
    5412           0 :   ObjectOrString arg0;
    5413           0 :   ObjectOrStringArgument arg0_holder(arg0);
    5414             :   {
    5415           0 :     bool done = false, failed = false, tryNext;
    5416           0 :     if (args[0].isObject()) {
    5417           0 :       if (!arg0_holder.SetToObject(cx, &args[0].toObject(), false)) {
    5418           0 :         return false;
    5419             :       }
    5420           0 :       done = true;
    5421             :     } else {
    5422             :       do {
    5423           0 :         done = (failed = !arg0_holder.TrySetToString(cx, args[0], tryNext)) || !tryNext;
    5424           0 :         break;
    5425             :       } while (0);
    5426             :     }
    5427           0 :     if (failed) {
    5428           0 :       return false;
    5429             :     }
    5430           0 :     if (!done) {
    5431           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 1 of SubtleCrypto.decrypt", "Object");
    5432           0 :       return false;
    5433             :     }
    5434             :   }
    5435           0 :   NonNull<mozilla::dom::CryptoKey> arg1;
    5436           0 :   if (args[1].isObject()) {
    5437             :     {
    5438           0 :       nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(args[1], arg1);
    5439           0 :       if (NS_FAILED(rv)) {
    5440           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 2 of SubtleCrypto.decrypt", "CryptoKey");
    5441           0 :         return false;
    5442             :       }
    5443             :     }
    5444             :   } else {
    5445           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of SubtleCrypto.decrypt");
    5446           0 :     return false;
    5447             :   }
    5448           0 :   ArrayBufferViewOrArrayBuffer arg2;
    5449           0 :   ArrayBufferViewOrArrayBufferArgument arg2_holder(arg2);
    5450             :   {
    5451           0 :     bool done = false, failed = false, tryNext;
    5452           0 :     if (args[2].isObject()) {
    5453           0 :       done = (failed = !arg2_holder.TrySetToArrayBufferView(cx, args[2], tryNext, false)) || !tryNext ||
    5454           0 :              (failed = !arg2_holder.TrySetToArrayBuffer(cx, args[2], tryNext, false)) || !tryNext;
    5455             : 
    5456             :     }
    5457           0 :     if (failed) {
    5458           0 :       return false;
    5459             :     }
    5460           0 :     if (!done) {
    5461           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 3 of SubtleCrypto.decrypt", "ArrayBufferView, ArrayBuffer");
    5462           0 :       return false;
    5463             :     }
    5464             :   }
    5465           0 :   binding_detail::FastErrorResult rv;
    5466           0 :   auto result(StrongOrRawPtr<Promise>(self->Decrypt(cx, Constify(arg0), NonNullHelper(arg1), Constify(arg2), rv)));
    5467           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    5468           0 :     return false;
    5469             :   }
    5470           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    5471           0 :   if (!ToJSValue(cx, result, args.rval())) {
    5472           0 :     return false;
    5473             :   }
    5474           0 :   return true;
    5475             : }
    5476             : 
    5477             : static bool
    5478           0 : decrypt_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5479             : {
    5480             :   // Make sure to save the callee before someone maybe messes
    5481             :   // with rval().
    5482           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    5483           0 :   bool ok = decrypt(cx, obj, self, args);
    5484           0 :   if (ok) {
    5485           0 :     return true;
    5486             :   }
    5487           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    5488           0 :                                    args.rval());
    5489             : }
    5490             : 
    5491             : static const JSJitInfo decrypt_methodinfo = {
    5492             :   { (JSJitGetterOp)decrypt_promiseWrapper },
    5493             :   { prototypes::id::SubtleCrypto },
    5494             :   { PrototypeTraits<prototypes::id::SubtleCrypto>::Depth },
    5495             :   JSJitInfo::Method,
    5496             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    5497             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    5498             :   false,  /* isInfallible. False in setters. */
    5499             :   false,  /* isMovable.  Not relevant for setters. */
    5500             :   false, /* isEliminatable.  Not relevant for setters. */
    5501             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    5502             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    5503             :   false,  /* isTypedMethod.  Only relevant for methods. */
    5504             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    5505             : };
    5506             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    5507             : static_assert(0 < 1, "There is no slot for us");
    5508             : 
    5509             : static bool
    5510           0 : sign(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5511             : {
    5512           0 :   if (MOZ_UNLIKELY(args.length() < 3)) {
    5513           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "SubtleCrypto.sign");
    5514             :   }
    5515           0 :   ObjectOrString arg0;
    5516           0 :   ObjectOrStringArgument arg0_holder(arg0);
    5517             :   {
    5518           0 :     bool done = false, failed = false, tryNext;
    5519           0 :     if (args[0].isObject()) {
    5520           0 :       if (!arg0_holder.SetToObject(cx, &args[0].toObject(), false)) {
    5521           0 :         return false;
    5522             :       }
    5523           0 :       done = true;
    5524             :     } else {
    5525             :       do {
    5526           0 :         done = (failed = !arg0_holder.TrySetToString(cx, args[0], tryNext)) || !tryNext;
    5527           0 :         break;
    5528             :       } while (0);
    5529             :     }
    5530           0 :     if (failed) {
    5531           0 :       return false;
    5532             :     }
    5533           0 :     if (!done) {
    5534           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 1 of SubtleCrypto.sign", "Object");
    5535           0 :       return false;
    5536             :     }
    5537             :   }
    5538           0 :   NonNull<mozilla::dom::CryptoKey> arg1;
    5539           0 :   if (args[1].isObject()) {
    5540             :     {
    5541           0 :       nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(args[1], arg1);
    5542           0 :       if (NS_FAILED(rv)) {
    5543           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 2 of SubtleCrypto.sign", "CryptoKey");
    5544           0 :         return false;
    5545             :       }
    5546             :     }
    5547             :   } else {
    5548           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of SubtleCrypto.sign");
    5549           0 :     return false;
    5550             :   }
    5551           0 :   ArrayBufferViewOrArrayBuffer arg2;
    5552           0 :   ArrayBufferViewOrArrayBufferArgument arg2_holder(arg2);
    5553             :   {
    5554           0 :     bool done = false, failed = false, tryNext;
    5555           0 :     if (args[2].isObject()) {
    5556           0 :       done = (failed = !arg2_holder.TrySetToArrayBufferView(cx, args[2], tryNext, false)) || !tryNext ||
    5557           0 :              (failed = !arg2_holder.TrySetToArrayBuffer(cx, args[2], tryNext, false)) || !tryNext;
    5558             : 
    5559             :     }
    5560           0 :     if (failed) {
    5561           0 :       return false;
    5562             :     }
    5563           0 :     if (!done) {
    5564           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 3 of SubtleCrypto.sign", "ArrayBufferView, ArrayBuffer");
    5565           0 :       return false;
    5566             :     }
    5567             :   }
    5568           0 :   binding_detail::FastErrorResult rv;
    5569           0 :   auto result(StrongOrRawPtr<Promise>(self->Sign(cx, Constify(arg0), NonNullHelper(arg1), Constify(arg2), rv)));
    5570           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    5571           0 :     return false;
    5572             :   }
    5573           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    5574           0 :   if (!ToJSValue(cx, result, args.rval())) {
    5575           0 :     return false;
    5576             :   }
    5577           0 :   return true;
    5578             : }
    5579             : 
    5580             : static bool
    5581           0 : sign_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5582             : {
    5583             :   // Make sure to save the callee before someone maybe messes
    5584             :   // with rval().
    5585           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    5586           0 :   bool ok = sign(cx, obj, self, args);
    5587           0 :   if (ok) {
    5588           0 :     return true;
    5589             :   }
    5590           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    5591           0 :                                    args.rval());
    5592             : }
    5593             : 
    5594             : static const JSJitInfo sign_methodinfo = {
    5595             :   { (JSJitGetterOp)sign_promiseWrapper },
    5596             :   { prototypes::id::SubtleCrypto },
    5597             :   { PrototypeTraits<prototypes::id::SubtleCrypto>::Depth },
    5598             :   JSJitInfo::Method,
    5599             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    5600             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    5601             :   false,  /* isInfallible. False in setters. */
    5602             :   false,  /* isMovable.  Not relevant for setters. */
    5603             :   false, /* isEliminatable.  Not relevant for setters. */
    5604             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    5605             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    5606             :   false,  /* isTypedMethod.  Only relevant for methods. */
    5607             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    5608             : };
    5609             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    5610             : static_assert(0 < 1, "There is no slot for us");
    5611             : 
    5612             : static bool
    5613           0 : verify(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5614             : {
    5615           0 :   if (MOZ_UNLIKELY(args.length() < 4)) {
    5616           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "SubtleCrypto.verify");
    5617             :   }
    5618           0 :   ObjectOrString arg0;
    5619           0 :   ObjectOrStringArgument arg0_holder(arg0);
    5620             :   {
    5621           0 :     bool done = false, failed = false, tryNext;
    5622           0 :     if (args[0].isObject()) {
    5623           0 :       if (!arg0_holder.SetToObject(cx, &args[0].toObject(), false)) {
    5624           0 :         return false;
    5625             :       }
    5626           0 :       done = true;
    5627             :     } else {
    5628             :       do {
    5629           0 :         done = (failed = !arg0_holder.TrySetToString(cx, args[0], tryNext)) || !tryNext;
    5630           0 :         break;
    5631             :       } while (0);
    5632             :     }
    5633           0 :     if (failed) {
    5634           0 :       return false;
    5635             :     }
    5636           0 :     if (!done) {
    5637           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 1 of SubtleCrypto.verify", "Object");
    5638           0 :       return false;
    5639             :     }
    5640             :   }
    5641           0 :   NonNull<mozilla::dom::CryptoKey> arg1;
    5642           0 :   if (args[1].isObject()) {
    5643             :     {
    5644           0 :       nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(args[1], arg1);
    5645           0 :       if (NS_FAILED(rv)) {
    5646           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 2 of SubtleCrypto.verify", "CryptoKey");
    5647           0 :         return false;
    5648             :       }
    5649             :     }
    5650             :   } else {
    5651           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of SubtleCrypto.verify");
    5652           0 :     return false;
    5653             :   }
    5654           0 :   ArrayBufferViewOrArrayBuffer arg2;
    5655           0 :   ArrayBufferViewOrArrayBufferArgument arg2_holder(arg2);
    5656             :   {
    5657           0 :     bool done = false, failed = false, tryNext;
    5658           0 :     if (args[2].isObject()) {
    5659           0 :       done = (failed = !arg2_holder.TrySetToArrayBufferView(cx, args[2], tryNext, false)) || !tryNext ||
    5660           0 :              (failed = !arg2_holder.TrySetToArrayBuffer(cx, args[2], tryNext, false)) || !tryNext;
    5661             : 
    5662             :     }
    5663           0 :     if (failed) {
    5664           0 :       return false;
    5665             :     }
    5666           0 :     if (!done) {
    5667           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 3 of SubtleCrypto.verify", "ArrayBufferView, ArrayBuffer");
    5668           0 :       return false;
    5669             :     }
    5670             :   }
    5671           0 :   ArrayBufferViewOrArrayBuffer arg3;
    5672           0 :   ArrayBufferViewOrArrayBufferArgument arg3_holder(arg3);
    5673             :   {
    5674           0 :     bool done = false, failed = false, tryNext;
    5675           0 :     if (args[3].isObject()) {
    5676           0 :       done = (failed = !arg3_holder.TrySetToArrayBufferView(cx, args[3], tryNext, false)) || !tryNext ||
    5677           0 :              (failed = !arg3_holder.TrySetToArrayBuffer(cx, args[3], tryNext, false)) || !tryNext;
    5678             : 
    5679             :     }
    5680           0 :     if (failed) {
    5681           0 :       return false;
    5682             :     }
    5683           0 :     if (!done) {
    5684           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 4 of SubtleCrypto.verify", "ArrayBufferView, ArrayBuffer");
    5685           0 :       return false;
    5686             :     }
    5687             :   }
    5688           0 :   binding_detail::FastErrorResult rv;
    5689           0 :   auto result(StrongOrRawPtr<Promise>(self->Verify(cx, Constify(arg0), NonNullHelper(arg1), Constify(arg2), Constify(arg3), rv)));
    5690           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    5691           0 :     return false;
    5692             :   }
    5693           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    5694           0 :   if (!ToJSValue(cx, result, args.rval())) {
    5695           0 :     return false;
    5696             :   }
    5697           0 :   return true;
    5698             : }
    5699             : 
    5700             : static bool
    5701           0 : verify_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5702             : {
    5703             :   // Make sure to save the callee before someone maybe messes
    5704             :   // with rval().
    5705           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    5706           0 :   bool ok = verify(cx, obj, self, args);
    5707           0 :   if (ok) {
    5708           0 :     return true;
    5709             :   }
    5710           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    5711           0 :                                    args.rval());
    5712             : }
    5713             : 
    5714             : static const JSJitInfo verify_methodinfo = {
    5715             :   { (JSJitGetterOp)verify_promiseWrapper },
    5716             :   { prototypes::id::SubtleCrypto },
    5717             :   { PrototypeTraits<prototypes::id::SubtleCrypto>::Depth },
    5718             :   JSJitInfo::Method,
    5719             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    5720             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    5721             :   false,  /* isInfallible. False in setters. */
    5722             :   false,  /* isMovable.  Not relevant for setters. */
    5723             :   false, /* isEliminatable.  Not relevant for setters. */
    5724             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    5725             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    5726             :   false,  /* isTypedMethod.  Only relevant for methods. */
    5727             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    5728             : };
    5729             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    5730             : static_assert(0 < 1, "There is no slot for us");
    5731             : 
    5732             : static bool
    5733           0 : digest(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5734             : {
    5735           0 :   if (MOZ_UNLIKELY(args.length() < 2)) {
    5736           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "SubtleCrypto.digest");
    5737             :   }
    5738           0 :   ObjectOrString arg0;
    5739           0 :   ObjectOrStringArgument arg0_holder(arg0);
    5740             :   {
    5741           0 :     bool done = false, failed = false, tryNext;
    5742           0 :     if (args[0].isObject()) {
    5743           0 :       if (!arg0_holder.SetToObject(cx, &args[0].toObject(), false)) {
    5744           0 :         return false;
    5745             :       }
    5746           0 :       done = true;
    5747             :     } else {
    5748             :       do {
    5749           0 :         done = (failed = !arg0_holder.TrySetToString(cx, args[0], tryNext)) || !tryNext;
    5750           0 :         break;
    5751             :       } while (0);
    5752             :     }
    5753           0 :     if (failed) {
    5754           0 :       return false;
    5755             :     }
    5756           0 :     if (!done) {
    5757           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 1 of SubtleCrypto.digest", "Object");
    5758           0 :       return false;
    5759             :     }
    5760             :   }
    5761           0 :   ArrayBufferViewOrArrayBuffer arg1;
    5762           0 :   ArrayBufferViewOrArrayBufferArgument arg1_holder(arg1);
    5763             :   {
    5764           0 :     bool done = false, failed = false, tryNext;
    5765           0 :     if (args[1].isObject()) {
    5766           0 :       done = (failed = !arg1_holder.TrySetToArrayBufferView(cx, args[1], tryNext, false)) || !tryNext ||
    5767           0 :              (failed = !arg1_holder.TrySetToArrayBuffer(cx, args[1], tryNext, false)) || !tryNext;
    5768             : 
    5769             :     }
    5770           0 :     if (failed) {
    5771           0 :       return false;
    5772             :     }
    5773           0 :     if (!done) {
    5774           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 2 of SubtleCrypto.digest", "ArrayBufferView, ArrayBuffer");
    5775           0 :       return false;
    5776             :     }
    5777             :   }
    5778           0 :   binding_detail::FastErrorResult rv;
    5779           0 :   auto result(StrongOrRawPtr<Promise>(self->Digest(cx, Constify(arg0), Constify(arg1), rv)));
    5780           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    5781           0 :     return false;
    5782             :   }
    5783           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    5784           0 :   if (!ToJSValue(cx, result, args.rval())) {
    5785           0 :     return false;
    5786             :   }
    5787           0 :   return true;
    5788             : }
    5789             : 
    5790             : static bool
    5791           0 : digest_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5792             : {
    5793             :   // Make sure to save the callee before someone maybe messes
    5794             :   // with rval().
    5795           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    5796           0 :   bool ok = digest(cx, obj, self, args);
    5797           0 :   if (ok) {
    5798           0 :     return true;
    5799             :   }
    5800           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    5801           0 :                                    args.rval());
    5802             : }
    5803             : 
    5804             : static const JSJitInfo digest_methodinfo = {
    5805             :   { (JSJitGetterOp)digest_promiseWrapper },
    5806             :   { prototypes::id::SubtleCrypto },
    5807             :   { PrototypeTraits<prototypes::id::SubtleCrypto>::Depth },
    5808             :   JSJitInfo::Method,
    5809             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    5810             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    5811             :   false,  /* isInfallible. False in setters. */
    5812             :   false,  /* isMovable.  Not relevant for setters. */
    5813             :   false, /* isEliminatable.  Not relevant for setters. */
    5814             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    5815             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    5816             :   false,  /* isTypedMethod.  Only relevant for methods. */
    5817             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    5818             : };
    5819             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    5820             : static_assert(0 < 1, "There is no slot for us");
    5821             : 
    5822             : static bool
    5823           0 : generateKey(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5824             : {
    5825           0 :   if (MOZ_UNLIKELY(args.length() < 3)) {
    5826           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "SubtleCrypto.generateKey");
    5827             :   }
    5828           0 :   ObjectOrString arg0;
    5829           0 :   ObjectOrStringArgument arg0_holder(arg0);
    5830             :   {
    5831           0 :     bool done = false, failed = false, tryNext;
    5832           0 :     if (args[0].isObject()) {
    5833           0 :       if (!arg0_holder.SetToObject(cx, &args[0].toObject(), false)) {
    5834           0 :         return false;
    5835             :       }
    5836           0 :       done = true;
    5837             :     } else {
    5838             :       do {
    5839           0 :         done = (failed = !arg0_holder.TrySetToString(cx, args[0], tryNext)) || !tryNext;
    5840           0 :         break;
    5841             :       } while (0);
    5842             :     }
    5843           0 :     if (failed) {
    5844           0 :       return false;
    5845             :     }
    5846           0 :     if (!done) {
    5847           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 1 of SubtleCrypto.generateKey", "Object");
    5848           0 :       return false;
    5849             :     }
    5850             :   }
    5851             :   bool arg1;
    5852           0 :   if (!ValueToPrimitive<bool, eDefault>(cx, args[1], &arg1)) {
    5853           0 :     return false;
    5854             :   }
    5855           0 :   binding_detail::AutoSequence<nsString> arg2;
    5856           0 :   if (args[2].isObject()) {
    5857           0 :     JS::ForOfIterator iter(cx);
    5858           0 :     if (!iter.init(args[2], JS::ForOfIterator::AllowNonIterable)) {
    5859           0 :       return false;
    5860             :     }
    5861           0 :     if (!iter.valueIsIterable()) {
    5862           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 3 of SubtleCrypto.generateKey");
    5863           0 :       return false;
    5864             :     }
    5865           0 :     binding_detail::AutoSequence<nsString> &arr = arg2;
    5866           0 :     JS::Rooted<JS::Value> temp(cx);
    5867             :     while (true) {
    5868             :       bool done;
    5869           0 :       if (!iter.next(&temp, &done)) {
    5870           0 :         return false;
    5871             :       }
    5872           0 :       if (done) {
    5873           0 :         break;
    5874             :       }
    5875           0 :       nsString* slotPtr = arr.AppendElement(mozilla::fallible);
    5876           0 :       if (!slotPtr) {
    5877           0 :         JS_ReportOutOfMemory(cx);
    5878           0 :         return false;
    5879             :       }
    5880           0 :       nsString& slot = *slotPtr;
    5881           0 :       if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
    5882           0 :         return false;
    5883             :       }
    5884           0 :     }
    5885             :   } else {
    5886           0 :     ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 3 of SubtleCrypto.generateKey");
    5887           0 :     return false;
    5888             :   }
    5889           0 :   binding_detail::FastErrorResult rv;
    5890           0 :   auto result(StrongOrRawPtr<Promise>(self->GenerateKey(cx, Constify(arg0), arg1, Constify(arg2), rv)));
    5891           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    5892           0 :     return false;
    5893             :   }
    5894           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    5895           0 :   if (!ToJSValue(cx, result, args.rval())) {
    5896           0 :     return false;
    5897             :   }
    5898           0 :   return true;
    5899             : }
    5900             : 
    5901             : static bool
    5902           0 : generateKey_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5903             : {
    5904             :   // Make sure to save the callee before someone maybe messes
    5905             :   // with rval().
    5906           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    5907           0 :   bool ok = generateKey(cx, obj, self, args);
    5908           0 :   if (ok) {
    5909           0 :     return true;
    5910             :   }
    5911           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    5912           0 :                                    args.rval());
    5913             : }
    5914             : 
    5915             : static const JSJitInfo generateKey_methodinfo = {
    5916             :   { (JSJitGetterOp)generateKey_promiseWrapper },
    5917             :   { prototypes::id::SubtleCrypto },
    5918             :   { PrototypeTraits<prototypes::id::SubtleCrypto>::Depth },
    5919             :   JSJitInfo::Method,
    5920             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    5921             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    5922             :   false,  /* isInfallible. False in setters. */
    5923             :   false,  /* isMovable.  Not relevant for setters. */
    5924             :   false, /* isEliminatable.  Not relevant for setters. */
    5925             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    5926             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    5927             :   false,  /* isTypedMethod.  Only relevant for methods. */
    5928             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    5929             : };
    5930             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    5931             : static_assert(0 < 1, "There is no slot for us");
    5932             : 
    5933             : static bool
    5934           0 : deriveKey(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    5935             : {
    5936           0 :   if (MOZ_UNLIKELY(args.length() < 5)) {
    5937           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "SubtleCrypto.deriveKey");
    5938             :   }
    5939           0 :   ObjectOrString arg0;
    5940           0 :   ObjectOrStringArgument arg0_holder(arg0);
    5941             :   {
    5942           0 :     bool done = false, failed = false, tryNext;
    5943           0 :     if (args[0].isObject()) {
    5944           0 :       if (!arg0_holder.SetToObject(cx, &args[0].toObject(), false)) {
    5945           0 :         return false;
    5946             :       }
    5947           0 :       done = true;
    5948             :     } else {
    5949             :       do {
    5950           0 :         done = (failed = !arg0_holder.TrySetToString(cx, args[0], tryNext)) || !tryNext;
    5951           0 :         break;
    5952             :       } while (0);
    5953             :     }
    5954           0 :     if (failed) {
    5955           0 :       return false;
    5956             :     }
    5957           0 :     if (!done) {
    5958           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 1 of SubtleCrypto.deriveKey", "Object");
    5959           0 :       return false;
    5960             :     }
    5961             :   }
    5962           0 :   NonNull<mozilla::dom::CryptoKey> arg1;
    5963           0 :   if (args[1].isObject()) {
    5964             :     {
    5965           0 :       nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(args[1], arg1);
    5966           0 :       if (NS_FAILED(rv)) {
    5967           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 2 of SubtleCrypto.deriveKey", "CryptoKey");
    5968           0 :         return false;
    5969             :       }
    5970             :     }
    5971             :   } else {
    5972           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of SubtleCrypto.deriveKey");
    5973           0 :     return false;
    5974             :   }
    5975           0 :   ObjectOrString arg2;
    5976           0 :   ObjectOrStringArgument arg2_holder(arg2);
    5977             :   {
    5978           0 :     bool done = false, failed = false, tryNext;
    5979           0 :     if (args[2].isObject()) {
    5980           0 :       if (!arg2_holder.SetToObject(cx, &args[2].toObject(), false)) {
    5981           0 :         return false;
    5982             :       }
    5983           0 :       done = true;
    5984             :     } else {
    5985             :       do {
    5986           0 :         done = (failed = !arg2_holder.TrySetToString(cx, args[2], tryNext)) || !tryNext;
    5987           0 :         break;
    5988             :       } while (0);
    5989             :     }
    5990           0 :     if (failed) {
    5991           0 :       return false;
    5992             :     }
    5993           0 :     if (!done) {
    5994           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 3 of SubtleCrypto.deriveKey", "Object");
    5995           0 :       return false;
    5996             :     }
    5997             :   }
    5998             :   bool arg3;
    5999           0 :   if (!ValueToPrimitive<bool, eDefault>(cx, args[3], &arg3)) {
    6000           0 :     return false;
    6001             :   }
    6002           0 :   binding_detail::AutoSequence<nsString> arg4;
    6003           0 :   if (args[4].isObject()) {
    6004           0 :     JS::ForOfIterator iter(cx);
    6005           0 :     if (!iter.init(args[4], JS::ForOfIterator::AllowNonIterable)) {
    6006           0 :       return false;
    6007             :     }
    6008           0 :     if (!iter.valueIsIterable()) {
    6009           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 5 of SubtleCrypto.deriveKey");
    6010           0 :       return false;
    6011             :     }
    6012           0 :     binding_detail::AutoSequence<nsString> &arr = arg4;
    6013           0 :     JS::Rooted<JS::Value> temp(cx);
    6014             :     while (true) {
    6015             :       bool done;
    6016           0 :       if (!iter.next(&temp, &done)) {
    6017           0 :         return false;
    6018             :       }
    6019           0 :       if (done) {
    6020           0 :         break;
    6021             :       }
    6022           0 :       nsString* slotPtr = arr.AppendElement(mozilla::fallible);
    6023           0 :       if (!slotPtr) {
    6024           0 :         JS_ReportOutOfMemory(cx);
    6025           0 :         return false;
    6026             :       }
    6027           0 :       nsString& slot = *slotPtr;
    6028           0 :       if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
    6029           0 :         return false;
    6030             :       }
    6031           0 :     }
    6032             :   } else {
    6033           0 :     ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 5 of SubtleCrypto.deriveKey");
    6034           0 :     return false;
    6035             :   }
    6036           0 :   binding_detail::FastErrorResult rv;
    6037           0 :   auto result(StrongOrRawPtr<Promise>(self->DeriveKey(cx, Constify(arg0), NonNullHelper(arg1), Constify(arg2), arg3, Constify(arg4), rv)));
    6038           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    6039           0 :     return false;
    6040             :   }
    6041           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    6042           0 :   if (!ToJSValue(cx, result, args.rval())) {
    6043           0 :     return false;
    6044             :   }
    6045           0 :   return true;
    6046             : }
    6047             : 
    6048             : static bool
    6049           0 : deriveKey_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    6050             : {
    6051             :   // Make sure to save the callee before someone maybe messes
    6052             :   // with rval().
    6053           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    6054           0 :   bool ok = deriveKey(cx, obj, self, args);
    6055           0 :   if (ok) {
    6056           0 :     return true;
    6057             :   }
    6058           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    6059           0 :                                    args.rval());
    6060             : }
    6061             : 
    6062             : static const JSJitInfo deriveKey_methodinfo = {
    6063             :   { (JSJitGetterOp)deriveKey_promiseWrapper },
    6064             :   { prototypes::id::SubtleCrypto },
    6065             :   { PrototypeTraits<prototypes::id::SubtleCrypto>::Depth },
    6066             :   JSJitInfo::Method,
    6067             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    6068             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    6069             :   false,  /* isInfallible. False in setters. */
    6070             :   false,  /* isMovable.  Not relevant for setters. */
    6071             :   false, /* isEliminatable.  Not relevant for setters. */
    6072             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    6073             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    6074             :   false,  /* isTypedMethod.  Only relevant for methods. */
    6075             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    6076             : };
    6077             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    6078             : static_assert(0 < 1, "There is no slot for us");
    6079             : 
    6080             : static bool
    6081           0 : deriveBits(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    6082             : {
    6083           0 :   if (MOZ_UNLIKELY(args.length() < 3)) {
    6084           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "SubtleCrypto.deriveBits");
    6085             :   }
    6086           0 :   ObjectOrString arg0;
    6087           0 :   ObjectOrStringArgument arg0_holder(arg0);
    6088             :   {
    6089           0 :     bool done = false, failed = false, tryNext;
    6090           0 :     if (args[0].isObject()) {
    6091           0 :       if (!arg0_holder.SetToObject(cx, &args[0].toObject(), false)) {
    6092           0 :         return false;
    6093             :       }
    6094           0 :       done = true;
    6095             :     } else {
    6096             :       do {
    6097           0 :         done = (failed = !arg0_holder.TrySetToString(cx, args[0], tryNext)) || !tryNext;
    6098           0 :         break;
    6099             :       } while (0);
    6100             :     }
    6101           0 :     if (failed) {
    6102           0 :       return false;
    6103             :     }
    6104           0 :     if (!done) {
    6105           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 1 of SubtleCrypto.deriveBits", "Object");
    6106           0 :       return false;
    6107             :     }
    6108             :   }
    6109           0 :   NonNull<mozilla::dom::CryptoKey> arg1;
    6110           0 :   if (args[1].isObject()) {
    6111             :     {
    6112           0 :       nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(args[1], arg1);
    6113           0 :       if (NS_FAILED(rv)) {
    6114           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 2 of SubtleCrypto.deriveBits", "CryptoKey");
    6115           0 :         return false;
    6116             :       }
    6117             :     }
    6118             :   } else {
    6119           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of SubtleCrypto.deriveBits");
    6120           0 :     return false;
    6121             :   }
    6122             :   uint32_t arg2;
    6123           0 :   if (!ValueToPrimitive<uint32_t, eDefault>(cx, args[2], &arg2)) {
    6124           0 :     return false;
    6125             :   }
    6126           0 :   binding_detail::FastErrorResult rv;
    6127           0 :   auto result(StrongOrRawPtr<Promise>(self->DeriveBits(cx, Constify(arg0), NonNullHelper(arg1), arg2, rv)));
    6128           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    6129           0 :     return false;
    6130             :   }
    6131           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    6132           0 :   if (!ToJSValue(cx, result, args.rval())) {
    6133           0 :     return false;
    6134             :   }
    6135           0 :   return true;
    6136             : }
    6137             : 
    6138             : static bool
    6139           0 : deriveBits_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    6140             : {
    6141             :   // Make sure to save the callee before someone maybe messes
    6142             :   // with rval().
    6143           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    6144           0 :   bool ok = deriveBits(cx, obj, self, args);
    6145           0 :   if (ok) {
    6146           0 :     return true;
    6147             :   }
    6148           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    6149           0 :                                    args.rval());
    6150             : }
    6151             : 
    6152             : static const JSJitInfo deriveBits_methodinfo = {
    6153             :   { (JSJitGetterOp)deriveBits_promiseWrapper },
    6154             :   { prototypes::id::SubtleCrypto },
    6155             :   { PrototypeTraits<prototypes::id::SubtleCrypto>::Depth },
    6156             :   JSJitInfo::Method,
    6157             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    6158             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    6159             :   false,  /* isInfallible. False in setters. */
    6160             :   false,  /* isMovable.  Not relevant for setters. */
    6161             :   false, /* isEliminatable.  Not relevant for setters. */
    6162             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    6163             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    6164             :   false,  /* isTypedMethod.  Only relevant for methods. */
    6165             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    6166             : };
    6167             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    6168             : static_assert(0 < 1, "There is no slot for us");
    6169             : 
    6170             : static bool
    6171           0 : importKey(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    6172             : {
    6173           0 :   if (MOZ_UNLIKELY(args.length() < 5)) {
    6174           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "SubtleCrypto.importKey");
    6175             :   }
    6176           0 :   binding_detail::FakeString arg0;
    6177           0 :   if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
    6178           0 :     return false;
    6179             :   }
    6180           0 :   JS::Rooted<JSObject*> arg1(cx);
    6181           0 :   if (args[1].isObject()) {
    6182           0 :     arg1 = &args[1].toObject();
    6183             :   } else {
    6184           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of SubtleCrypto.importKey");
    6185           0 :     return false;
    6186             :   }
    6187           0 :   ObjectOrString arg2;
    6188           0 :   ObjectOrStringArgument arg2_holder(arg2);
    6189             :   {
    6190           0 :     bool done = false, failed = false, tryNext;
    6191           0 :     if (args[2].isObject()) {
    6192           0 :       if (!arg2_holder.SetToObject(cx, &args[2].toObject(), false)) {
    6193           0 :         return false;
    6194             :       }
    6195           0 :       done = true;
    6196             :     } else {
    6197             :       do {
    6198           0 :         done = (failed = !arg2_holder.TrySetToString(cx, args[2], tryNext)) || !tryNext;
    6199           0 :         break;
    6200             :       } while (0);
    6201             :     }
    6202           0 :     if (failed) {
    6203           0 :       return false;
    6204             :     }
    6205           0 :     if (!done) {
    6206           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 3 of SubtleCrypto.importKey", "Object");
    6207           0 :       return false;
    6208             :     }
    6209             :   }
    6210             :   bool arg3;
    6211           0 :   if (!ValueToPrimitive<bool, eDefault>(cx, args[3], &arg3)) {
    6212           0 :     return false;
    6213             :   }
    6214           0 :   binding_detail::AutoSequence<nsString> arg4;
    6215           0 :   if (args[4].isObject()) {
    6216           0 :     JS::ForOfIterator iter(cx);
    6217           0 :     if (!iter.init(args[4], JS::ForOfIterator::AllowNonIterable)) {
    6218           0 :       return false;
    6219             :     }
    6220           0 :     if (!iter.valueIsIterable()) {
    6221           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 5 of SubtleCrypto.importKey");
    6222           0 :       return false;
    6223             :     }
    6224           0 :     binding_detail::AutoSequence<nsString> &arr = arg4;
    6225           0 :     JS::Rooted<JS::Value> temp(cx);
    6226             :     while (true) {
    6227             :       bool done;
    6228           0 :       if (!iter.next(&temp, &done)) {
    6229           0 :         return false;
    6230             :       }
    6231           0 :       if (done) {
    6232           0 :         break;
    6233             :       }
    6234           0 :       nsString* slotPtr = arr.AppendElement(mozilla::fallible);
    6235           0 :       if (!slotPtr) {
    6236           0 :         JS_ReportOutOfMemory(cx);
    6237           0 :         return false;
    6238             :       }
    6239           0 :       nsString& slot = *slotPtr;
    6240           0 :       if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
    6241           0 :         return false;
    6242             :       }
    6243           0 :     }
    6244             :   } else {
    6245           0 :     ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 5 of SubtleCrypto.importKey");
    6246           0 :     return false;
    6247             :   }
    6248           0 :   binding_detail::FastErrorResult rv;
    6249           0 :   auto result(StrongOrRawPtr<Promise>(self->ImportKey(cx, NonNullHelper(Constify(arg0)), arg1, Constify(arg2), arg3, Constify(arg4), rv)));
    6250           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    6251           0 :     return false;
    6252             :   }
    6253           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    6254           0 :   if (!ToJSValue(cx, result, args.rval())) {
    6255           0 :     return false;
    6256             :   }
    6257           0 :   return true;
    6258             : }
    6259             : 
    6260             : static bool
    6261           0 : importKey_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    6262             : {
    6263             :   // Make sure to save the callee before someone maybe messes
    6264             :   // with rval().
    6265           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    6266           0 :   bool ok = importKey(cx, obj, self, args);
    6267           0 :   if (ok) {
    6268           0 :     return true;
    6269             :   }
    6270           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    6271           0 :                                    args.rval());
    6272             : }
    6273             : 
    6274             : static const JSJitInfo importKey_methodinfo = {
    6275             :   { (JSJitGetterOp)importKey_promiseWrapper },
    6276             :   { prototypes::id::SubtleCrypto },
    6277             :   { PrototypeTraits<prototypes::id::SubtleCrypto>::Depth },
    6278             :   JSJitInfo::Method,
    6279             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    6280             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    6281             :   false,  /* isInfallible. False in setters. */
    6282             :   false,  /* isMovable.  Not relevant for setters. */
    6283             :   false, /* isEliminatable.  Not relevant for setters. */
    6284             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    6285             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    6286             :   false,  /* isTypedMethod.  Only relevant for methods. */
    6287             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    6288             : };
    6289             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    6290             : static_assert(0 < 1, "There is no slot for us");
    6291             : 
    6292             : static bool
    6293           0 : exportKey(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    6294             : {
    6295           0 :   if (MOZ_UNLIKELY(args.length() < 2)) {
    6296           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "SubtleCrypto.exportKey");
    6297             :   }
    6298           0 :   binding_detail::FakeString arg0;
    6299           0 :   if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
    6300           0 :     return false;
    6301             :   }
    6302           0 :   NonNull<mozilla::dom::CryptoKey> arg1;
    6303           0 :   if (args[1].isObject()) {
    6304             :     {
    6305           0 :       nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(args[1], arg1);
    6306           0 :       if (NS_FAILED(rv)) {
    6307           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 2 of SubtleCrypto.exportKey", "CryptoKey");
    6308           0 :         return false;
    6309             :       }
    6310             :     }
    6311             :   } else {
    6312           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of SubtleCrypto.exportKey");
    6313           0 :     return false;
    6314             :   }
    6315           0 :   binding_detail::FastErrorResult rv;
    6316           0 :   auto result(StrongOrRawPtr<Promise>(self->ExportKey(NonNullHelper(Constify(arg0)), NonNullHelper(arg1), rv)));
    6317           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    6318           0 :     return false;
    6319             :   }
    6320           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    6321           0 :   if (!ToJSValue(cx, result, args.rval())) {
    6322           0 :     return false;
    6323             :   }
    6324           0 :   return true;
    6325             : }
    6326             : 
    6327             : static bool
    6328           0 : exportKey_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    6329             : {
    6330             :   // Make sure to save the callee before someone maybe messes
    6331             :   // with rval().
    6332           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    6333           0 :   bool ok = exportKey(cx, obj, self, args);
    6334           0 :   if (ok) {
    6335           0 :     return true;
    6336             :   }
    6337           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    6338           0 :                                    args.rval());
    6339             : }
    6340             : 
    6341             : static const JSJitInfo exportKey_methodinfo = {
    6342             :   { (JSJitGetterOp)exportKey_promiseWrapper },
    6343             :   { prototypes::id::SubtleCrypto },
    6344             :   { PrototypeTraits<prototypes::id::SubtleCrypto>::Depth },
    6345             :   JSJitInfo::Method,
    6346             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    6347             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    6348             :   false,  /* isInfallible. False in setters. */
    6349             :   false,  /* isMovable.  Not relevant for setters. */
    6350             :   false, /* isEliminatable.  Not relevant for setters. */
    6351             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    6352             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    6353             :   false,  /* isTypedMethod.  Only relevant for methods. */
    6354             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    6355             : };
    6356             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    6357             : static_assert(0 < 1, "There is no slot for us");
    6358             : 
    6359             : static bool
    6360           0 : wrapKey(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    6361             : {
    6362           0 :   if (MOZ_UNLIKELY(args.length() < 4)) {
    6363           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "SubtleCrypto.wrapKey");
    6364             :   }
    6365           0 :   binding_detail::FakeString arg0;
    6366           0 :   if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
    6367           0 :     return false;
    6368             :   }
    6369           0 :   NonNull<mozilla::dom::CryptoKey> arg1;
    6370           0 :   if (args[1].isObject()) {
    6371             :     {
    6372           0 :       nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(args[1], arg1);
    6373           0 :       if (NS_FAILED(rv)) {
    6374           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 2 of SubtleCrypto.wrapKey", "CryptoKey");
    6375           0 :         return false;
    6376             :       }
    6377             :     }
    6378             :   } else {
    6379           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of SubtleCrypto.wrapKey");
    6380           0 :     return false;
    6381             :   }
    6382           0 :   NonNull<mozilla::dom::CryptoKey> arg2;
    6383           0 :   if (args[2].isObject()) {
    6384             :     {
    6385           0 :       nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(args[2], arg2);
    6386           0 :       if (NS_FAILED(rv)) {
    6387           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 3 of SubtleCrypto.wrapKey", "CryptoKey");
    6388           0 :         return false;
    6389             :       }
    6390             :     }
    6391             :   } else {
    6392           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 3 of SubtleCrypto.wrapKey");
    6393           0 :     return false;
    6394             :   }
    6395           0 :   ObjectOrString arg3;
    6396           0 :   ObjectOrStringArgument arg3_holder(arg3);
    6397             :   {
    6398           0 :     bool done = false, failed = false, tryNext;
    6399           0 :     if (args[3].isObject()) {
    6400           0 :       if (!arg3_holder.SetToObject(cx, &args[3].toObject(), false)) {
    6401           0 :         return false;
    6402             :       }
    6403           0 :       done = true;
    6404             :     } else {
    6405             :       do {
    6406           0 :         done = (failed = !arg3_holder.TrySetToString(cx, args[3], tryNext)) || !tryNext;
    6407           0 :         break;
    6408             :       } while (0);
    6409             :     }
    6410           0 :     if (failed) {
    6411           0 :       return false;
    6412             :     }
    6413           0 :     if (!done) {
    6414           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 4 of SubtleCrypto.wrapKey", "Object");
    6415           0 :       return false;
    6416             :     }
    6417             :   }
    6418           0 :   binding_detail::FastErrorResult rv;
    6419           0 :   auto result(StrongOrRawPtr<Promise>(self->WrapKey(cx, NonNullHelper(Constify(arg0)), NonNullHelper(arg1), NonNullHelper(arg2), Constify(arg3), rv)));
    6420           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    6421           0 :     return false;
    6422             :   }
    6423           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    6424           0 :   if (!ToJSValue(cx, result, args.rval())) {
    6425           0 :     return false;
    6426             :   }
    6427           0 :   return true;
    6428             : }
    6429             : 
    6430             : static bool
    6431           0 : wrapKey_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    6432             : {
    6433             :   // Make sure to save the callee before someone maybe messes
    6434             :   // with rval().
    6435           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    6436           0 :   bool ok = wrapKey(cx, obj, self, args);
    6437           0 :   if (ok) {
    6438           0 :     return true;
    6439             :   }
    6440           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    6441           0 :                                    args.rval());
    6442             : }
    6443             : 
    6444             : static const JSJitInfo wrapKey_methodinfo = {
    6445             :   { (JSJitGetterOp)wrapKey_promiseWrapper },
    6446             :   { prototypes::id::SubtleCrypto },
    6447             :   { PrototypeTraits<prototypes::id::SubtleCrypto>::Depth },
    6448             :   JSJitInfo::Method,
    6449             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    6450             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    6451             :   false,  /* isInfallible. False in setters. */
    6452             :   false,  /* isMovable.  Not relevant for setters. */
    6453             :   false, /* isEliminatable.  Not relevant for setters. */
    6454             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    6455             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    6456             :   false,  /* isTypedMethod.  Only relevant for methods. */
    6457             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    6458             : };
    6459             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    6460             : static_assert(0 < 1, "There is no slot for us");
    6461             : 
    6462             : static bool
    6463           0 : unwrapKey(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    6464             : {
    6465           0 :   if (MOZ_UNLIKELY(args.length() < 7)) {
    6466           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "SubtleCrypto.unwrapKey");
    6467             :   }
    6468           0 :   binding_detail::FakeString arg0;
    6469           0 :   if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
    6470           0 :     return false;
    6471             :   }
    6472           0 :   ArrayBufferViewOrArrayBuffer arg1;
    6473           0 :   ArrayBufferViewOrArrayBufferArgument arg1_holder(arg1);
    6474             :   {
    6475           0 :     bool done = false, failed = false, tryNext;
    6476           0 :     if (args[1].isObject()) {
    6477           0 :       done = (failed = !arg1_holder.TrySetToArrayBufferView(cx, args[1], tryNext, false)) || !tryNext ||
    6478           0 :              (failed = !arg1_holder.TrySetToArrayBuffer(cx, args[1], tryNext, false)) || !tryNext;
    6479             : 
    6480             :     }
    6481           0 :     if (failed) {
    6482           0 :       return false;
    6483             :     }
    6484           0 :     if (!done) {
    6485           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 2 of SubtleCrypto.unwrapKey", "ArrayBufferView, ArrayBuffer");
    6486           0 :       return false;
    6487             :     }
    6488             :   }
    6489           0 :   NonNull<mozilla::dom::CryptoKey> arg2;
    6490           0 :   if (args[2].isObject()) {
    6491             :     {
    6492           0 :       nsresult rv = UnwrapObject<prototypes::id::CryptoKey, mozilla::dom::CryptoKey>(args[2], arg2);
    6493           0 :       if (NS_FAILED(rv)) {
    6494           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 3 of SubtleCrypto.unwrapKey", "CryptoKey");
    6495           0 :         return false;
    6496             :       }
    6497             :     }
    6498             :   } else {
    6499           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 3 of SubtleCrypto.unwrapKey");
    6500           0 :     return false;
    6501             :   }
    6502           0 :   ObjectOrString arg3;
    6503           0 :   ObjectOrStringArgument arg3_holder(arg3);
    6504             :   {
    6505           0 :     bool done = false, failed = false, tryNext;
    6506           0 :     if (args[3].isObject()) {
    6507           0 :       if (!arg3_holder.SetToObject(cx, &args[3].toObject(), false)) {
    6508           0 :         return false;
    6509             :       }
    6510           0 :       done = true;
    6511             :     } else {
    6512             :       do {
    6513           0 :         done = (failed = !arg3_holder.TrySetToString(cx, args[3], tryNext)) || !tryNext;
    6514           0 :         break;
    6515             :       } while (0);
    6516             :     }
    6517           0 :     if (failed) {
    6518           0 :       return false;
    6519             :     }
    6520           0 :     if (!done) {
    6521           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 4 of SubtleCrypto.unwrapKey", "Object");
    6522           0 :       return false;
    6523             :     }
    6524             :   }
    6525           0 :   ObjectOrString arg4;
    6526           0 :   ObjectOrStringArgument arg4_holder(arg4);
    6527             :   {
    6528           0 :     bool done = false, failed = false, tryNext;
    6529           0 :     if (args[4].isObject()) {
    6530           0 :       if (!arg4_holder.SetToObject(cx, &args[4].toObject(), false)) {
    6531           0 :         return false;
    6532             :       }
    6533           0 :       done = true;
    6534             :     } else {
    6535             :       do {
    6536           0 :         done = (failed = !arg4_holder.TrySetToString(cx, args[4], tryNext)) || !tryNext;
    6537           0 :         break;
    6538             :       } while (0);
    6539             :     }
    6540           0 :     if (failed) {
    6541           0 :       return false;
    6542             :     }
    6543           0 :     if (!done) {
    6544           0 :       ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 5 of SubtleCrypto.unwrapKey", "Object");
    6545           0 :       return false;
    6546             :     }
    6547             :   }
    6548             :   bool arg5;
    6549           0 :   if (!ValueToPrimitive<bool, eDefault>(cx, args[5], &arg5)) {
    6550           0 :     return false;
    6551             :   }
    6552           0 :   binding_detail::AutoSequence<nsString> arg6;
    6553           0 :   if (args[6].isObject()) {
    6554           0 :     JS::ForOfIterator iter(cx);
    6555           0 :     if (!iter.init(args[6], JS::ForOfIterator::AllowNonIterable)) {
    6556           0 :       return false;
    6557             :     }
    6558           0 :     if (!iter.valueIsIterable()) {
    6559           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 7 of SubtleCrypto.unwrapKey");
    6560           0 :       return false;
    6561             :     }
    6562           0 :     binding_detail::AutoSequence<nsString> &arr = arg6;
    6563           0 :     JS::Rooted<JS::Value> temp(cx);
    6564             :     while (true) {
    6565             :       bool done;
    6566           0 :       if (!iter.next(&temp, &done)) {
    6567           0 :         return false;
    6568             :       }
    6569           0 :       if (done) {
    6570           0 :         break;
    6571             :       }
    6572           0 :       nsString* slotPtr = arr.AppendElement(mozilla::fallible);
    6573           0 :       if (!slotPtr) {
    6574           0 :         JS_ReportOutOfMemory(cx);
    6575           0 :         return false;
    6576             :       }
    6577           0 :       nsString& slot = *slotPtr;
    6578           0 :       if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
    6579           0 :         return false;
    6580             :       }
    6581           0 :     }
    6582             :   } else {
    6583           0 :     ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 7 of SubtleCrypto.unwrapKey");
    6584           0 :     return false;
    6585             :   }
    6586           0 :   binding_detail::FastErrorResult rv;
    6587           0 :   auto result(StrongOrRawPtr<Promise>(self->UnwrapKey(cx, NonNullHelper(Constify(arg0)), Constify(arg1), NonNullHelper(arg2), Constify(arg3), Constify(arg4), arg5, Constify(arg6), rv)));
    6588           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    6589           0 :     return false;
    6590             :   }
    6591           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    6592           0 :   if (!ToJSValue(cx, result, args.rval())) {
    6593           0 :     return false;
    6594             :   }
    6595           0 :   return true;
    6596             : }
    6597             : 
    6598             : static bool
    6599           0 : unwrapKey_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::SubtleCrypto* self, const JSJitMethodCallArgs& args)
    6600             : {
    6601             :   // Make sure to save the callee before someone maybe messes
    6602             :   // with rval().
    6603           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    6604           0 :   bool ok = unwrapKey(cx, obj, self, args);
    6605           0 :   if (ok) {
    6606           0 :     return true;
    6607             :   }
    6608           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    6609           0 :                                    args.rval());
    6610             : }
    6611             : 
    6612             : static const JSJitInfo unwrapKey_methodinfo = {
    6613             :   { (JSJitGetterOp)unwrapKey_promiseWrapper },
    6614             :   { prototypes::id::SubtleCrypto },
    6615             :   { PrototypeTraits<prototypes::id::SubtleCrypto>::Depth },
    6616             :   JSJitInfo::Method,
    6617             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    6618             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    6619             :   false,  /* isInfallible. False in setters. */
    6620             :   false,  /* isMovable.  Not relevant for setters. */
    6621             :   false, /* isEliminatable.  Not relevant for setters. */
    6622             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    6623             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    6624             :   false,  /* isTypedMethod.  Only relevant for methods. */
    6625             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    6626             : };
    6627             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    6628             : static_assert(0 < 1, "There is no slot for us");
    6629             : 
    6630             : static bool
    6631           0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
    6632             : {
    6633           0 :   mozilla::dom::SubtleCrypto* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::SubtleCrypto>(obj);
    6634             :   // We don't want to preserve if we don't have a wrapper, and we
    6635             :   // obviously can't preserve if we're not initialized.
    6636           0 :   if (self && self->GetWrapperPreserveColor()) {
    6637           0 :     PreserveWrapper(self);
    6638             :   }
    6639           0 :   return true;
    6640             : }
    6641             : 
    6642             : static void
    6643           0 : _finalize(js::FreeOp* fop, JSObject* obj)
    6644             : {
    6645           0 :   mozilla::dom::SubtleCrypto* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::SubtleCrypto>(obj);
    6646           0 :   if (self) {
    6647           0 :     ClearWrapper(self, self, obj);
    6648           0 :     AddForDeferredFinalization<mozilla::dom::SubtleCrypto>(self);
    6649             :   }
    6650           0 : }
    6651             : 
    6652             : static void
    6653           0 : _objectMoved(JSObject* obj, const JSObject* old)
    6654             : {
    6655           0 :   mozilla::dom::SubtleCrypto* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::SubtleCrypto>(obj);
    6656           0 :   if (self) {
    6657           0 :     UpdateWrapper(self, self, obj, old);
    6658             :   }
    6659           0 : }
    6660             : 
    6661             : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
    6662             : #if defined(__clang__)
    6663             : #pragma clang diagnostic push
    6664             : #pragma clang diagnostic ignored "-Wmissing-braces"
    6665             : #endif
    6666             : static const JSFunctionSpec sMethods_specs[] = {
    6667             :   JS_FNSPEC("encrypt", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&encrypt_methodinfo), 3, JSPROP_ENUMERATE, nullptr),
    6668             :   JS_FNSPEC("decrypt", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&decrypt_methodinfo), 3, JSPROP_ENUMERATE, nullptr),
    6669             :   JS_FNSPEC("sign", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&sign_methodinfo), 3, JSPROP_ENUMERATE, nullptr),
    6670             :   JS_FNSPEC("verify", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&verify_methodinfo), 4, JSPROP_ENUMERATE, nullptr),
    6671             :   JS_FNSPEC("digest", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&digest_methodinfo), 2, JSPROP_ENUMERATE, nullptr),
    6672             :   JS_FNSPEC("generateKey", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&generateKey_methodinfo), 3, JSPROP_ENUMERATE, nullptr),
    6673             :   JS_FNSPEC("deriveKey", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&deriveKey_methodinfo), 5, JSPROP_ENUMERATE, nullptr),
    6674             :   JS_FNSPEC("deriveBits", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&deriveBits_methodinfo), 3, JSPROP_ENUMERATE, nullptr),
    6675             :   JS_FNSPEC("importKey", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&importKey_methodinfo), 5, JSPROP_ENUMERATE, nullptr),
    6676             :   JS_FNSPEC("exportKey", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&exportKey_methodinfo), 2, JSPROP_ENUMERATE, nullptr),
    6677             :   JS_FNSPEC("wrapKey", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&wrapKey_methodinfo), 4, JSPROP_ENUMERATE, nullptr),
    6678             :   JS_FNSPEC("unwrapKey", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&unwrapKey_methodinfo), 7, JSPROP_ENUMERATE, nullptr),
    6679             :   JS_FS_END
    6680             : };
    6681             : #if defined(__clang__)
    6682             : #pragma clang diagnostic pop
    6683             : #endif
    6684             : 
    6685             : 
    6686             : // Can't be const because the pref-enabled boolean needs to be writable
    6687             : static Prefable<const JSFunctionSpec> sMethods[] = {
    6688             :   { nullptr, &sMethods_specs[0] },
    6689             :   { nullptr, nullptr }
    6690             : };
    6691             : 
    6692             : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
    6693             :     "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
    6694             : static_assert(12 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
    6695             :     "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
    6696             : 
    6697             : 
    6698             : static uint16_t sNativeProperties_sortedPropertyIndices[12];
    6699             : static PropertyInfo sNativeProperties_propertyInfos[12];
    6700             : 
    6701             : static const NativePropertiesN<1> sNativeProperties = {
    6702             :   false, 0,
    6703             :   false, 0,
    6704             :   true,  0 /* sMethods */,
    6705             :   false, 0,
    6706             :   false, 0,
    6707             :   false, 0,
    6708             :   false, 0,
    6709             :   -1,
    6710             :   12,
    6711             :   sNativeProperties_sortedPropertyIndices,
    6712             :   {
    6713             :     { sMethods, &sNativeProperties_propertyInfos[0] }
    6714             :   }
    6715             : };
    6716             : static_assert(12 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
    6717             :     "We have a property info count that is oversized");
    6718             : 
    6719             : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
    6720             :   {
    6721             :     "Function",
    6722             :     JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
    6723             :     &sBoringInterfaceObjectClassClassOps,
    6724             :     JS_NULL_CLASS_SPEC,
    6725             :     JS_NULL_CLASS_EXT,
    6726             :     &sInterfaceObjectClassObjectOps
    6727             :   },
    6728             :   eInterface,
    6729             :   true,
    6730             :   prototypes::id::SubtleCrypto,
    6731             :   PrototypeTraits<prototypes::id::SubtleCrypto>::Depth,
    6732             :   sNativePropertyHooks,
    6733             :   "function SubtleCrypto() {\n    [native code]\n}",
    6734             :   JS::GetRealmFunctionPrototype
    6735             : };
    6736             : 
    6737             : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
    6738             :   {
    6739             :     "SubtleCryptoPrototype",
    6740             :     JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
    6741             :     JS_NULL_CLASS_OPS,
    6742             :     JS_NULL_CLASS_SPEC,
    6743             :     JS_NULL_CLASS_EXT,
    6744             :     JS_NULL_OBJECT_OPS
    6745             :   },
    6746             :   eInterfacePrototype,
    6747             :   false,
    6748             :   prototypes::id::SubtleCrypto,
    6749             :   PrototypeTraits<prototypes::id::SubtleCrypto>::Depth,
    6750             :   sNativePropertyHooks,
    6751             :   "[object SubtleCryptoPrototype]",
    6752             :   JS::GetRealmObjectPrototype
    6753             : };
    6754             : 
    6755             : JSObject*
    6756           0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
    6757             : {
    6758           0 :   return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
    6759             : }
    6760             : 
    6761             : static const js::ClassOps sClassOps = {
    6762             :   _addProperty, /* addProperty */
    6763             :   nullptr,               /* delProperty */
    6764             :   nullptr,               /* getProperty */
    6765             :   nullptr,               /* setProperty */
    6766             :   nullptr,               /* enumerate */
    6767             :   nullptr, /* newEnumerate */
    6768             :   nullptr, /* resolve */
    6769             :   nullptr, /* mayResolve */
    6770             :   _finalize, /* finalize */
    6771             :   nullptr, /* call */
    6772             :   nullptr,               /* hasInstance */
    6773             :   nullptr,               /* construct */
    6774             :   nullptr, /* trace */
    6775             : };
    6776             : 
    6777             : static const js::ClassExtension sClassExtension = {
    6778             :   nullptr, /* weakmapKeyDelegateOp */
    6779             :   _objectMoved /* objectMovedOp */
    6780             : };
    6781             : 
    6782             : static const DOMJSClass sClass = {
    6783             :   { "SubtleCrypto",
    6784             :     JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
    6785             :     &sClassOps,
    6786             :     JS_NULL_CLASS_SPEC,
    6787             :     &sClassExtension,
    6788             :     JS_NULL_OBJECT_OPS
    6789             :   },
    6790             :   { prototypes::id::SubtleCrypto, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
    6791             :   IsBaseOf<nsISupports, mozilla::dom::SubtleCrypto >::value,
    6792             :   sNativePropertyHooks,
    6793             :   FindAssociatedGlobalForNative<mozilla::dom::SubtleCrypto>::Get,
    6794             :   GetProtoObjectHandle,
    6795             :   GetCCParticipant<mozilla::dom::SubtleCrypto>::Get()
    6796             : };
    6797             : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
    6798             :               "Must have the right minimal number of reserved slots.");
    6799             : static_assert(1 >= 1,
    6800             :               "Must have enough reserved slots.");
    6801             : 
    6802             : const JSClass*
    6803           0 : GetJSClass()
    6804             : {
    6805           0 :   return sClass.ToJSClass();
    6806             : }
    6807             : 
    6808             : bool
    6809           0 : Wrap(JSContext* aCx, mozilla::dom::SubtleCrypto* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
    6810             : {
    6811             :   MOZ_ASSERT(static_cast<mozilla::dom::SubtleCrypto*>(aObject) ==
    6812             :              reinterpret_cast<mozilla::dom::SubtleCrypto*>(aObject),
    6813             :              "Multiple inheritance for mozilla::dom::SubtleCrypto is broken.");
    6814           0 :   MOZ_ASSERT(ToSupportsIsCorrect(aObject));
    6815           0 :   MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
    6816           0 :   MOZ_ASSERT(!aCache->GetWrapper(),
    6817             :              "You should probably not be using Wrap() directly; use "
    6818             :              "GetOrCreateDOMReflector instead");
    6819             : 
    6820           0 :   MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
    6821             :              "nsISupports must be on our primary inheritance chain");
    6822             : 
    6823           0 :   JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
    6824           0 :   if (!global) {
    6825           0 :     return false;
    6826             :   }
    6827           0 :   MOZ_ASSERT(JS_IsGlobalObject(global));
    6828           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(global));
    6829             : 
    6830             :   // That might have ended up wrapping us already, due to the wonders
    6831             :   // of XBL.  Check for that, and bail out as needed.
    6832           0 :   aReflector.set(aCache->GetWrapper());
    6833           0 :   if (aReflector) {
    6834             : #ifdef DEBUG
    6835           0 :     binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
    6836             : #endif // DEBUG
    6837           0 :     return true;
    6838             :   }
    6839             : 
    6840           0 :   JSAutoCompartment ac(aCx, global);
    6841           0 :   JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
    6842           0 :   if (!canonicalProto) {
    6843           0 :     return false;
    6844             :   }
    6845           0 :   JS::Rooted<JSObject*> proto(aCx);
    6846           0 :   if (aGivenProto) {
    6847           0 :     proto = aGivenProto;
    6848             :     // Unfortunately, while aGivenProto was in the compartment of aCx
    6849             :     // coming in, we changed compartments to that of "parent" so may need
    6850             :     // to wrap the proto here.
    6851           0 :     if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
    6852           0 :       if (!JS_WrapObject(aCx, &proto)) {
    6853           0 :         return false;
    6854             :       }
    6855             :     }
    6856             :   } else {
    6857           0 :     proto = canonicalProto;
    6858             :   }
    6859             : 
    6860           0 :   BindingJSObjectCreator<mozilla::dom::SubtleCrypto> creator(aCx);
    6861           0 :   creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
    6862           0 :   if (!aReflector) {
    6863           0 :     return false;
    6864             :   }
    6865             : 
    6866           0 :   aCache->SetWrapper(aReflector);
    6867           0 :   creator.InitializationSucceeded();
    6868             : 
    6869           0 :   MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
    6870             :              aCache->GetWrapperPreserveColor() == aReflector);
    6871             :   // If proto != canonicalProto, we have to preserve our wrapper;
    6872             :   // otherwise we won't be able to properly recreate it later, since
    6873             :   // we won't know what proto to use.  Note that we don't check
    6874             :   // aGivenProto here, since it's entirely possible (and even
    6875             :   // somewhat common) to have a non-null aGivenProto which is the
    6876             :   // same as canonicalProto.
    6877           0 :   if (proto != canonicalProto) {
    6878           0 :     PreserveWrapper(aObject);
    6879             :   }
    6880             : 
    6881           0 :   return true;
    6882             : }
    6883             : 
    6884             : const NativePropertyHooks sNativePropertyHooks[] = { {
    6885             :   nullptr,
    6886             :   nullptr,
    6887             :   nullptr,
    6888             :   { sNativeProperties.Upcast(), nullptr },
    6889             :   prototypes::id::SubtleCrypto,
    6890             :   constructors::id::SubtleCrypto,
    6891             :   nullptr,
    6892             :   &DefaultXrayExpandoObjectClass
    6893             : } };
    6894             : 
    6895             : void
    6896           1 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
    6897             : {
    6898           2 :   JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
    6899           1 :   if (!parentProto) {
    6900           0 :     return;
    6901             :   }
    6902             : 
    6903           2 :   JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
    6904           1 :   if (!constructorProto) {
    6905           0 :     return;
    6906             :   }
    6907             : 
    6908             :   static bool sIdsInited = false;
    6909           1 :   if (!sIdsInited && NS_IsMainThread()) {
    6910           0 :     if (!InitIds(aCx, sNativeProperties.Upcast())) {
    6911           0 :       return;
    6912             :     }
    6913           0 :     sIdsInited = true;
    6914             :   }
    6915             : 
    6916           1 :   JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::SubtleCrypto);
    6917           1 :   JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::SubtleCrypto);
    6918           2 :   dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
    6919             :                               &sPrototypeClass.mBase, protoCache,
    6920             :                               constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
    6921             :                               interfaceCache,
    6922             :                               sNativeProperties.Upcast(),
    6923             :                               nullptr,
    6924             :                               "SubtleCrypto", aDefineOnGlobal,
    6925             :                               nullptr,
    6926           1 :                               false);
    6927             : }
    6928             : 
    6929             : JS::Handle<JSObject*>
    6930           0 : GetProtoObjectHandle(JSContext* aCx)
    6931             : {
    6932             :   /* Get the interface prototype object for this class.  This will create the
    6933             :      object as needed. */
    6934           0 :   bool aDefineOnGlobal = true;
    6935             : 
    6936             :   /* Make sure our global is sane.  Hopefully we can remove this sometime */
    6937           0 :   JSObject* global = JS::CurrentGlobalOrNull(aCx);
    6938           0 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
    6939           0 :     return nullptr;
    6940             :   }
    6941             : 
    6942             :   /* Check to see whether the interface objects are already installed */
    6943           0 :   ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
    6944           0 :   if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::SubtleCrypto)) {
    6945           0 :     JS::Rooted<JSObject*> rootedGlobal(aCx, global);
    6946           0 :     CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
    6947             :   }
    6948             : 
    6949             :   /*
    6950             :    * The object might _still_ be null, but that's OK.
    6951             :    *
    6952             :    * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
    6953             :    * traced by TraceProtoAndIfaceCache() and its contents are never
    6954             :    * changed after they have been set.
    6955             :    *
    6956             :    * Calling address() avoids the read read barrier that does gray
    6957             :    * unmarking, but it's not possible for the object to be gray here.
    6958             :    */
    6959             : 
    6960           0 :   const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::SubtleCrypto);
    6961           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
    6962           0 :   return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
    6963             : }
    6964             : 
    6965             : JS::Handle<JSObject*>
    6966           1 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
    6967             : {
    6968             :   /* Get the interface object for this class.  This will create the object as
    6969             :      needed. */
    6970             : 
    6971             :   /* Make sure our global is sane.  Hopefully we can remove this sometime */
    6972           1 :   JSObject* global = JS::CurrentGlobalOrNull(aCx);
    6973           1 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
    6974           0 :     return nullptr;
    6975             :   }
    6976             : 
    6977             :   /* Check to see whether the interface objects are already installed */
    6978           1 :   ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
    6979           1 :   if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::SubtleCrypto)) {
    6980           2 :     JS::Rooted<JSObject*> rootedGlobal(aCx, global);
    6981           1 :     CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
    6982             :   }
    6983             : 
    6984             :   /*
    6985             :    * The object might _still_ be null, but that's OK.
    6986             :    *
    6987             :    * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
    6988             :    * traced by TraceProtoAndIfaceCache() and its contents are never
    6989             :    * changed after they have been set.
    6990             :    *
    6991             :    * Calling address() avoids the read read barrier that does gray
    6992             :    * unmarking, but it's not possible for the object to be gray here.
    6993             :    */
    6994             : 
    6995           1 :   const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::SubtleCrypto);
    6996           1 :   MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
    6997           1 :   return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
    6998             : }
    6999             : 
    7000             : JSObject*
    7001           1 : GetConstructorObject(JSContext* aCx)
    7002             : {
    7003           1 :   return GetConstructorObjectHandle(aCx);
    7004             : }
    7005             : 
    7006             : } // namespace SubtleCryptoBinding
    7007             : 
    7008             : 
    7009             : 
    7010             : } // namespace dom
    7011             : } // namespace mozilla

Generated by: LCOV version 1.13