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

          Line data    Source code
       1             : /* THIS FILE IS AUTOGENERATED FROM U2F.webidl BY Codegen.py - DO NOT EDIT */
       2             : 
       3             : #include "AtomList.h"
       4             : #include "U2FBinding.h"
       5             : #include "WrapperFactory.h"
       6             : #include "jsapi.h"
       7             : #include "mozilla/OwningNonNull.h"
       8             : #include "mozilla/Preferences.h"
       9             : #include "mozilla/dom/BindingUtils.h"
      10             : #include "mozilla/dom/DOMJSClass.h"
      11             : #include "mozilla/dom/NonRefcountedDOMObject.h"
      12             : #include "mozilla/dom/Nullable.h"
      13             : #include "mozilla/dom/PrimitiveConversions.h"
      14             : #include "mozilla/dom/ScriptSettings.h"
      15             : #include "mozilla/dom/SimpleGlobalObject.h"
      16             : #include "mozilla/dom/U2F.h"
      17             : #include "mozilla/dom/XrayExpandoClass.h"
      18             : 
      19             : namespace mozilla {
      20             : namespace dom {
      21             : 
      22             : namespace TransportValues {
      23             : extern const EnumEntry strings[5] = {
      24             :   {"bt", 2},
      25             :   {"ble", 3},
      26             :   {"nfc", 3},
      27             :   {"usb", 3},
      28             :   { nullptr, 0 }
      29             : };
      30             : } // namespace TransportValues
      31             : 
      32             : bool
      33           0 : ToJSValue(JSContext* aCx, Transport aArgument, JS::MutableHandle<JS::Value> aValue)
      34             : {
      35           0 :   MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(TransportValues::strings));
      36             :   JSString* resultStr =
      37           0 :     JS_NewStringCopyN(aCx, TransportValues::strings[uint32_t(aArgument)].value,
      38           0 :                       TransportValues::strings[uint32_t(aArgument)].length);
      39           0 :   if (!resultStr) {
      40           0 :     return false;
      41             :   }
      42           0 :   aValue.setString(resultStr);
      43           0 :   return true;
      44             : }
      45             : 
      46             : 
      47             : 
      48           0 : RegisterRequest::RegisterRequest()
      49             : {
      50             :   // Safe to pass a null context if we pass a null value
      51           0 :   Init(nullptr, JS::NullHandleValue);
      52           0 : }
      53             : 
      54             : 
      55             : 
      56             : bool
      57           0 : RegisterRequest::InitIds(JSContext* cx, RegisterRequestAtoms* atomsCache)
      58             : {
      59           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
      60             : 
      61             :   // Initialize these in reverse order so that any failure leaves the first one
      62             :   // uninitialized.
      63           0 :   if (!atomsCache->version_id.init(cx, "version") ||
      64           0 :       !atomsCache->challenge_id.init(cx, "challenge")) {
      65           0 :     return false;
      66             :   }
      67           0 :   return true;
      68             : }
      69             : 
      70             : bool
      71           0 : RegisterRequest::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
      72             : {
      73             :   // Passing a null JSContext is OK only if we're initing from null,
      74             :   // Since in that case we will not have to do any property gets
      75             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
      76             :   // checkers by static analysis tools
      77           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
      78           0 :   RegisterRequestAtoms* atomsCache = nullptr;
      79           0 :   if (cx) {
      80           0 :     atomsCache = GetAtomCache<RegisterRequestAtoms>(cx);
      81           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
      82           0 :       return false;
      83             :     }
      84             :   }
      85             : 
      86           0 :   if (!IsConvertibleToDictionary(val)) {
      87           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
      88             :   }
      89             : 
      90           0 :   bool isNull = val.isNullOrUndefined();
      91             :   // We only need these if !isNull, in which case we have |cx|.
      92           0 :   Maybe<JS::Rooted<JSObject *> > object;
      93           0 :   Maybe<JS::Rooted<JS::Value> > temp;
      94           0 :   if (!isNull) {
      95           0 :     MOZ_ASSERT(cx);
      96           0 :     object.emplace(cx, &val.toObject());
      97           0 :     temp.emplace(cx);
      98             :   }
      99           0 :   if (!isNull) {
     100           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->challenge_id, temp.ptr())) {
     101           0 :       return false;
     102             :     }
     103             :   }
     104           0 :   if (!isNull && !temp->isUndefined()) {
     105           0 :     mChallenge.Construct();
     106           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mChallenge.Value()))) {
     107           0 :       return false;
     108             :     }
     109           0 :     mIsAnyMemberPresent = true;
     110             :   }
     111             : 
     112           0 :   if (!isNull) {
     113           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->version_id, temp.ptr())) {
     114           0 :       return false;
     115             :     }
     116             :   }
     117           0 :   if (!isNull && !temp->isUndefined()) {
     118           0 :     mVersion.Construct();
     119           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mVersion.Value()))) {
     120           0 :       return false;
     121             :     }
     122           0 :     mIsAnyMemberPresent = true;
     123             :   }
     124           0 :   return true;
     125             : }
     126             : 
     127             : bool
     128           0 : RegisterRequest::Init(const nsAString& aJSON)
     129             : {
     130           0 :   AutoJSAPI jsapi;
     131           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     132           0 :   if (!cleanGlobal) {
     133           0 :     return false;
     134             :   }
     135           0 :   if (!jsapi.Init(cleanGlobal)) {
     136           0 :     return false;
     137             :   }
     138           0 :   JSContext* cx = jsapi.cx();
     139           0 :   JS::Rooted<JS::Value> json(cx);
     140           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     141           0 :   NS_ENSURE_TRUE(ok, false);
     142           0 :   return Init(cx, json);
     143             : }
     144             : 
     145             : bool
     146           0 : RegisterRequest::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     147             : {
     148           0 :   RegisterRequestAtoms* atomsCache = GetAtomCache<RegisterRequestAtoms>(cx);
     149           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     150           0 :     return false;
     151             :   }
     152             : 
     153           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     154           0 :   if (!obj) {
     155           0 :     return false;
     156             :   }
     157           0 :   rval.set(JS::ObjectValue(*obj));
     158             : 
     159           0 :   if (mChallenge.WasPassed()) {
     160             :     do {
     161             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     162           0 :       JS::Rooted<JS::Value> temp(cx);
     163           0 :       nsString const & currentValue = mChallenge.InternalValue();
     164           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     165           0 :         return false;
     166             :       }
     167           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->challenge_id, temp, JSPROP_ENUMERATE)) {
     168           0 :         return false;
     169             :       }
     170           0 :       break;
     171             :     } while(0);
     172             :   }
     173             : 
     174           0 :   if (mVersion.WasPassed()) {
     175             :     do {
     176             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     177           0 :       JS::Rooted<JS::Value> temp(cx);
     178           0 :       nsString const & currentValue = mVersion.InternalValue();
     179           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     180           0 :         return false;
     181             :       }
     182           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->version_id, temp, JSPROP_ENUMERATE)) {
     183           0 :         return false;
     184             :       }
     185           0 :       break;
     186             :     } while(0);
     187             :   }
     188             : 
     189           0 :   return true;
     190             : }
     191             : 
     192             : bool
     193           0 : RegisterRequest::ToJSON(nsAString& aJSON) const
     194             : {
     195           0 :   AutoJSAPI jsapi;
     196           0 :   jsapi.Init();
     197           0 :   JSContext *cx = jsapi.cx();
     198             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     199             :   // because we'll only be creating objects, in ways that have no
     200             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     201             :   // which likewise guarantees no side-effects for the sorts of
     202             :   // things we will pass it.
     203           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     204           0 :   JS::Rooted<JS::Value> val(cx);
     205           0 :   if (!ToObjectInternal(cx, &val)) {
     206           0 :     return false;
     207             :   }
     208           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     209           0 :   return StringifyToJSON(cx, obj, aJSON);
     210             : }
     211             : 
     212             : void
     213           0 : RegisterRequest::TraceDictionary(JSTracer* trc)
     214             : {
     215           0 : }
     216             : 
     217             : RegisterRequest&
     218           0 : RegisterRequest::operator=(const RegisterRequest& aOther)
     219             : {
     220           0 :   mChallenge.Reset();
     221           0 :   if (aOther.mChallenge.WasPassed()) {
     222           0 :     mChallenge.Construct(aOther.mChallenge.Value());
     223             :   }
     224           0 :   mVersion.Reset();
     225           0 :   if (aOther.mVersion.WasPassed()) {
     226           0 :     mVersion.Construct(aOther.mVersion.Value());
     227             :   }
     228           0 :   return *this;
     229             : }
     230             : 
     231             : namespace binding_detail {
     232             : } // namespace binding_detail
     233             : 
     234             : 
     235             : 
     236           0 : RegisterResponse::RegisterResponse()
     237             : {
     238             :   // Safe to pass a null context if we pass a null value
     239           0 :   Init(nullptr, JS::NullHandleValue);
     240           0 : }
     241             : 
     242             : 
     243             : 
     244             : bool
     245           0 : RegisterResponse::InitIds(JSContext* cx, RegisterResponseAtoms* atomsCache)
     246             : {
     247           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     248             : 
     249             :   // Initialize these in reverse order so that any failure leaves the first one
     250             :   // uninitialized.
     251           0 :   if (!atomsCache->version_id.init(cx, "version") ||
     252           0 :       !atomsCache->registrationData_id.init(cx, "registrationData") ||
     253           0 :       !atomsCache->errorMessage_id.init(cx, "errorMessage") ||
     254           0 :       !atomsCache->errorCode_id.init(cx, "errorCode") ||
     255           0 :       !atomsCache->clientData_id.init(cx, "clientData")) {
     256           0 :     return false;
     257             :   }
     258           0 :   return true;
     259             : }
     260             : 
     261             : bool
     262           0 : RegisterResponse::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     263             : {
     264             :   // Passing a null JSContext is OK only if we're initing from null,
     265             :   // Since in that case we will not have to do any property gets
     266             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     267             :   // checkers by static analysis tools
     268           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     269           0 :   RegisterResponseAtoms* atomsCache = nullptr;
     270           0 :   if (cx) {
     271           0 :     atomsCache = GetAtomCache<RegisterResponseAtoms>(cx);
     272           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     273           0 :       return false;
     274             :     }
     275             :   }
     276             : 
     277           0 :   if (!IsConvertibleToDictionary(val)) {
     278           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     279             :   }
     280             : 
     281           0 :   bool isNull = val.isNullOrUndefined();
     282             :   // We only need these if !isNull, in which case we have |cx|.
     283           0 :   Maybe<JS::Rooted<JSObject *> > object;
     284           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     285           0 :   if (!isNull) {
     286           0 :     MOZ_ASSERT(cx);
     287           0 :     object.emplace(cx, &val.toObject());
     288           0 :     temp.emplace(cx);
     289             :   }
     290           0 :   if (!isNull) {
     291           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->clientData_id, temp.ptr())) {
     292           0 :       return false;
     293             :     }
     294             :   }
     295           0 :   if (!isNull && !temp->isUndefined()) {
     296           0 :     mClientData.Construct();
     297           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mClientData.Value()))) {
     298           0 :       return false;
     299             :     }
     300           0 :     mIsAnyMemberPresent = true;
     301             :   }
     302             : 
     303           0 :   if (!isNull) {
     304           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->errorCode_id, temp.ptr())) {
     305           0 :       return false;
     306             :     }
     307             :   }
     308           0 :   if (!isNull && !temp->isUndefined()) {
     309           0 :     mErrorCode.Construct();
     310           0 :     if (temp.ref().isNullOrUndefined()) {
     311           0 :       (mErrorCode.Value()).SetNull();
     312           0 :     } else if (!ValueToPrimitive<uint16_t, eDefault>(cx, temp.ref(), &(mErrorCode.Value()).SetValue())) {
     313           0 :       return false;
     314             :     }
     315           0 :     mIsAnyMemberPresent = true;
     316             :   }
     317             : 
     318           0 :   if (!isNull) {
     319           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->errorMessage_id, temp.ptr())) {
     320           0 :       return false;
     321             :     }
     322             :   }
     323           0 :   if (!isNull && !temp->isUndefined()) {
     324           0 :     mErrorMessage.Construct();
     325           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, (mErrorMessage.Value()))) {
     326           0 :       return false;
     327             :     }
     328           0 :     mIsAnyMemberPresent = true;
     329             :   }
     330             : 
     331           0 :   if (!isNull) {
     332           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->registrationData_id, temp.ptr())) {
     333           0 :       return false;
     334             :     }
     335             :   }
     336           0 :   if (!isNull && !temp->isUndefined()) {
     337           0 :     mRegistrationData.Construct();
     338           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mRegistrationData.Value()))) {
     339           0 :       return false;
     340             :     }
     341           0 :     mIsAnyMemberPresent = true;
     342             :   }
     343             : 
     344           0 :   if (!isNull) {
     345           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->version_id, temp.ptr())) {
     346           0 :       return false;
     347             :     }
     348             :   }
     349           0 :   if (!isNull && !temp->isUndefined()) {
     350           0 :     mVersion.Construct();
     351           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mVersion.Value()))) {
     352           0 :       return false;
     353             :     }
     354           0 :     mIsAnyMemberPresent = true;
     355             :   }
     356           0 :   return true;
     357             : }
     358             : 
     359             : bool
     360           0 : RegisterResponse::Init(const nsAString& aJSON)
     361             : {
     362           0 :   AutoJSAPI jsapi;
     363           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     364           0 :   if (!cleanGlobal) {
     365           0 :     return false;
     366             :   }
     367           0 :   if (!jsapi.Init(cleanGlobal)) {
     368           0 :     return false;
     369             :   }
     370           0 :   JSContext* cx = jsapi.cx();
     371           0 :   JS::Rooted<JS::Value> json(cx);
     372           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     373           0 :   NS_ENSURE_TRUE(ok, false);
     374           0 :   return Init(cx, json);
     375             : }
     376             : 
     377             : bool
     378           0 : RegisterResponse::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     379             : {
     380           0 :   RegisterResponseAtoms* atomsCache = GetAtomCache<RegisterResponseAtoms>(cx);
     381           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     382           0 :     return false;
     383             :   }
     384             : 
     385           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     386           0 :   if (!obj) {
     387           0 :     return false;
     388             :   }
     389           0 :   rval.set(JS::ObjectValue(*obj));
     390             : 
     391           0 :   if (mClientData.WasPassed()) {
     392             :     do {
     393             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     394           0 :       JS::Rooted<JS::Value> temp(cx);
     395           0 :       nsString const & currentValue = mClientData.InternalValue();
     396           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     397           0 :         return false;
     398             :       }
     399           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->clientData_id, temp, JSPROP_ENUMERATE)) {
     400           0 :         return false;
     401             :       }
     402           0 :       break;
     403             :     } while(0);
     404             :   }
     405             : 
     406           0 :   if (mErrorCode.WasPassed()) {
     407             :     do {
     408             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     409           0 :       JS::Rooted<JS::Value> temp(cx);
     410           0 :       Nullable<uint16_t> const & currentValue = mErrorCode.InternalValue();
     411           0 :       if (currentValue.IsNull()) {
     412           0 :         temp.setNull();
     413           0 :         if (!JS_DefinePropertyById(cx, obj, atomsCache->errorCode_id, temp, JSPROP_ENUMERATE)) {
     414           0 :           return false;
     415             :         }
     416           0 :         break;
     417             :       }
     418           0 :       temp.setInt32(int32_t(currentValue.Value()));
     419           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->errorCode_id, temp, JSPROP_ENUMERATE)) {
     420           0 :         return false;
     421             :       }
     422           0 :       break;
     423             :     } while(0);
     424             :   }
     425             : 
     426           0 :   if (mErrorMessage.WasPassed()) {
     427             :     do {
     428             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     429           0 :       JS::Rooted<JS::Value> temp(cx);
     430           0 :       nsString const & currentValue = mErrorMessage.InternalValue();
     431           0 :       if (!xpc::StringToJsval(cx, currentValue, &temp)) {
     432           0 :         return false;
     433             :       }
     434           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->errorMessage_id, temp, JSPROP_ENUMERATE)) {
     435           0 :         return false;
     436             :       }
     437           0 :       break;
     438             :     } while(0);
     439             :   }
     440             : 
     441           0 :   if (mRegistrationData.WasPassed()) {
     442             :     do {
     443             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     444           0 :       JS::Rooted<JS::Value> temp(cx);
     445           0 :       nsString const & currentValue = mRegistrationData.InternalValue();
     446           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     447           0 :         return false;
     448             :       }
     449           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->registrationData_id, temp, JSPROP_ENUMERATE)) {
     450           0 :         return false;
     451             :       }
     452           0 :       break;
     453             :     } while(0);
     454             :   }
     455             : 
     456           0 :   if (mVersion.WasPassed()) {
     457             :     do {
     458             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     459           0 :       JS::Rooted<JS::Value> temp(cx);
     460           0 :       nsString const & currentValue = mVersion.InternalValue();
     461           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     462           0 :         return false;
     463             :       }
     464           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->version_id, temp, JSPROP_ENUMERATE)) {
     465           0 :         return false;
     466             :       }
     467           0 :       break;
     468             :     } while(0);
     469             :   }
     470             : 
     471           0 :   return true;
     472             : }
     473             : 
     474             : bool
     475           0 : RegisterResponse::ToJSON(nsAString& aJSON) const
     476             : {
     477           0 :   AutoJSAPI jsapi;
     478           0 :   jsapi.Init();
     479           0 :   JSContext *cx = jsapi.cx();
     480             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     481             :   // because we'll only be creating objects, in ways that have no
     482             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     483             :   // which likewise guarantees no side-effects for the sorts of
     484             :   // things we will pass it.
     485           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     486           0 :   JS::Rooted<JS::Value> val(cx);
     487           0 :   if (!ToObjectInternal(cx, &val)) {
     488           0 :     return false;
     489             :   }
     490           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     491           0 :   return StringifyToJSON(cx, obj, aJSON);
     492             : }
     493             : 
     494             : void
     495           0 : RegisterResponse::TraceDictionary(JSTracer* trc)
     496             : {
     497           0 : }
     498             : 
     499             : RegisterResponse&
     500           0 : RegisterResponse::operator=(const RegisterResponse& aOther)
     501             : {
     502           0 :   mClientData.Reset();
     503           0 :   if (aOther.mClientData.WasPassed()) {
     504           0 :     mClientData.Construct(aOther.mClientData.Value());
     505             :   }
     506           0 :   mErrorCode.Reset();
     507           0 :   if (aOther.mErrorCode.WasPassed()) {
     508           0 :     mErrorCode.Construct(aOther.mErrorCode.Value());
     509             :   }
     510           0 :   mErrorMessage.Reset();
     511           0 :   if (aOther.mErrorMessage.WasPassed()) {
     512           0 :     mErrorMessage.Construct(aOther.mErrorMessage.Value());
     513             :   }
     514           0 :   mRegistrationData.Reset();
     515           0 :   if (aOther.mRegistrationData.WasPassed()) {
     516           0 :     mRegistrationData.Construct(aOther.mRegistrationData.Value());
     517             :   }
     518           0 :   mVersion.Reset();
     519           0 :   if (aOther.mVersion.WasPassed()) {
     520           0 :     mVersion.Construct(aOther.mVersion.Value());
     521             :   }
     522           0 :   return *this;
     523             : }
     524             : 
     525             : namespace binding_detail {
     526             : } // namespace binding_detail
     527             : 
     528             : 
     529             : 
     530           0 : RegisteredKey::RegisteredKey()
     531             : {
     532             :   // Safe to pass a null context if we pass a null value
     533           0 :   Init(nullptr, JS::NullHandleValue);
     534           0 : }
     535             : 
     536             : 
     537             : 
     538             : bool
     539           0 : RegisteredKey::InitIds(JSContext* cx, RegisteredKeyAtoms* atomsCache)
     540             : {
     541           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     542             : 
     543             :   // Initialize these in reverse order so that any failure leaves the first one
     544             :   // uninitialized.
     545           0 :   if (!atomsCache->version_id.init(cx, "version") ||
     546           0 :       !atomsCache->transports_id.init(cx, "transports") ||
     547           0 :       !atomsCache->keyHandle_id.init(cx, "keyHandle") ||
     548           0 :       !atomsCache->appId_id.init(cx, "appId")) {
     549           0 :     return false;
     550             :   }
     551           0 :   return true;
     552             : }
     553             : 
     554             : bool
     555           0 : RegisteredKey::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     556             : {
     557             :   // Passing a null JSContext is OK only if we're initing from null,
     558             :   // Since in that case we will not have to do any property gets
     559             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     560             :   // checkers by static analysis tools
     561           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     562           0 :   RegisteredKeyAtoms* atomsCache = nullptr;
     563           0 :   if (cx) {
     564           0 :     atomsCache = GetAtomCache<RegisteredKeyAtoms>(cx);
     565           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     566           0 :       return false;
     567             :     }
     568             :   }
     569             : 
     570           0 :   if (!IsConvertibleToDictionary(val)) {
     571           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     572             :   }
     573             : 
     574           0 :   bool isNull = val.isNullOrUndefined();
     575             :   // We only need these if !isNull, in which case we have |cx|.
     576           0 :   Maybe<JS::Rooted<JSObject *> > object;
     577           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     578           0 :   if (!isNull) {
     579           0 :     MOZ_ASSERT(cx);
     580           0 :     object.emplace(cx, &val.toObject());
     581           0 :     temp.emplace(cx);
     582             :   }
     583           0 :   if (!isNull) {
     584           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->appId_id, temp.ptr())) {
     585           0 :       return false;
     586             :     }
     587             :   }
     588           0 :   if (!isNull && !temp->isUndefined()) {
     589           0 :     mAppId.Construct();
     590           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, (mAppId.Value()))) {
     591           0 :       return false;
     592             :     }
     593           0 :     mIsAnyMemberPresent = true;
     594             :   }
     595             : 
     596           0 :   if (!isNull) {
     597           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->keyHandle_id, temp.ptr())) {
     598           0 :       return false;
     599             :     }
     600             :   }
     601           0 :   if (!isNull && !temp->isUndefined()) {
     602           0 :     mKeyHandle.Construct();
     603           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mKeyHandle.Value()))) {
     604           0 :       return false;
     605             :     }
     606           0 :     mIsAnyMemberPresent = true;
     607             :   }
     608             : 
     609           0 :   if (!isNull) {
     610           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->transports_id, temp.ptr())) {
     611           0 :       return false;
     612             :     }
     613             :   }
     614           0 :   if (!isNull && !temp->isUndefined()) {
     615           0 :     mTransports.Construct();
     616           0 :     if (temp.ref().isObject()) {
     617           0 :       JS::ForOfIterator iter(cx);
     618           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
     619           0 :         return false;
     620             :       }
     621           0 :       if (!iter.valueIsIterable()) {
     622           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'transports' member of RegisteredKey");
     623           0 :         return false;
     624             :       }
     625           0 :       Sequence<Transport> &arr = (mTransports.Value()).SetValue();
     626           0 :       JS::Rooted<JS::Value> temp(cx);
     627             :       while (true) {
     628             :         bool done;
     629           0 :         if (!iter.next(&temp, &done)) {
     630           0 :           return false;
     631             :         }
     632           0 :         if (done) {
     633           0 :           break;
     634             :         }
     635           0 :         Transport* slotPtr = arr.AppendElement(mozilla::fallible);
     636           0 :         if (!slotPtr) {
     637           0 :           JS_ReportOutOfMemory(cx);
     638           0 :           return false;
     639             :         }
     640           0 :         Transport& slot = *slotPtr;
     641             :         {
     642             :           int index;
     643           0 :           if (!FindEnumStringIndex<true>(cx, temp, TransportValues::strings, "Transport", "Element of 'transports' member of RegisteredKey", &index)) {
     644           0 :             return false;
     645             :           }
     646           0 :           MOZ_ASSERT(index >= 0);
     647           0 :           slot = static_cast<Transport>(index);
     648             :         }
     649           0 :       }
     650           0 :     } else if (temp.ref().isNullOrUndefined()) {
     651           0 :       (mTransports.Value()).SetNull();
     652             :     } else {
     653           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'transports' member of RegisteredKey");
     654           0 :       return false;
     655             :     }
     656           0 :     mIsAnyMemberPresent = true;
     657             :   }
     658             : 
     659           0 :   if (!isNull) {
     660           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->version_id, temp.ptr())) {
     661           0 :       return false;
     662             :     }
     663             :   }
     664           0 :   if (!isNull && !temp->isUndefined()) {
     665           0 :     mVersion.Construct();
     666           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mVersion.Value()))) {
     667           0 :       return false;
     668             :     }
     669           0 :     mIsAnyMemberPresent = true;
     670             :   }
     671           0 :   return true;
     672             : }
     673             : 
     674             : bool
     675           0 : RegisteredKey::Init(const nsAString& aJSON)
     676             : {
     677           0 :   AutoJSAPI jsapi;
     678           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     679           0 :   if (!cleanGlobal) {
     680           0 :     return false;
     681             :   }
     682           0 :   if (!jsapi.Init(cleanGlobal)) {
     683           0 :     return false;
     684             :   }
     685           0 :   JSContext* cx = jsapi.cx();
     686           0 :   JS::Rooted<JS::Value> json(cx);
     687           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     688           0 :   NS_ENSURE_TRUE(ok, false);
     689           0 :   return Init(cx, json);
     690             : }
     691             : 
     692             : bool
     693           0 : RegisteredKey::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     694             : {
     695           0 :   RegisteredKeyAtoms* atomsCache = GetAtomCache<RegisteredKeyAtoms>(cx);
     696           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     697           0 :     return false;
     698             :   }
     699             : 
     700           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     701           0 :   if (!obj) {
     702           0 :     return false;
     703             :   }
     704           0 :   rval.set(JS::ObjectValue(*obj));
     705             : 
     706           0 :   if (mAppId.WasPassed()) {
     707             :     do {
     708             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     709           0 :       JS::Rooted<JS::Value> temp(cx);
     710           0 :       nsString const & currentValue = mAppId.InternalValue();
     711           0 :       if (!xpc::StringToJsval(cx, currentValue, &temp)) {
     712           0 :         return false;
     713             :       }
     714           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->appId_id, temp, JSPROP_ENUMERATE)) {
     715           0 :         return false;
     716             :       }
     717           0 :       break;
     718             :     } while(0);
     719             :   }
     720             : 
     721           0 :   if (mKeyHandle.WasPassed()) {
     722             :     do {
     723             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     724           0 :       JS::Rooted<JS::Value> temp(cx);
     725           0 :       nsString const & currentValue = mKeyHandle.InternalValue();
     726           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     727           0 :         return false;
     728             :       }
     729           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->keyHandle_id, temp, JSPROP_ENUMERATE)) {
     730           0 :         return false;
     731             :       }
     732           0 :       break;
     733             :     } while(0);
     734             :   }
     735             : 
     736           0 :   if (mTransports.WasPassed()) {
     737             :     do {
     738             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     739           0 :       JS::Rooted<JS::Value> temp(cx);
     740           0 :       Nullable<Sequence<Transport>> const & currentValue = mTransports.InternalValue();
     741             : 
     742           0 :       if (currentValue.IsNull()) {
     743           0 :         temp.setNull();
     744           0 :         if (!JS_DefinePropertyById(cx, obj, atomsCache->transports_id, temp, JSPROP_ENUMERATE)) {
     745           0 :           return false;
     746             :         }
     747           0 :         break;
     748             :       }
     749             : 
     750           0 :       uint32_t length = currentValue.Value().Length();
     751           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
     752           0 :       if (!returnArray) {
     753           0 :         return false;
     754             :       }
     755             :       // Scope for 'tmp'
     756             :       {
     757           0 :         JS::Rooted<JS::Value> tmp(cx);
     758           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
     759             :           // Control block to let us common up the JS_DefineElement calls when there
     760             :           // are different ways to succeed at wrapping the object.
     761             :           do {
     762           0 :             if (!ToJSValue(cx, currentValue.Value()[sequenceIdx0], &tmp)) {
     763           0 :               return false;
     764             :             }
     765           0 :             break;
     766             :           } while (0);
     767           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
     768             :                                 JSPROP_ENUMERATE)) {
     769           0 :             return false;
     770             :           }
     771             :         }
     772             :       }
     773           0 :       temp.setObject(*returnArray);
     774           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->transports_id, temp, JSPROP_ENUMERATE)) {
     775           0 :         return false;
     776             :       }
     777           0 :       break;
     778             :     } while(0);
     779             :   }
     780             : 
     781           0 :   if (mVersion.WasPassed()) {
     782             :     do {
     783             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     784           0 :       JS::Rooted<JS::Value> temp(cx);
     785           0 :       nsString const & currentValue = mVersion.InternalValue();
     786           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     787           0 :         return false;
     788             :       }
     789           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->version_id, temp, JSPROP_ENUMERATE)) {
     790           0 :         return false;
     791             :       }
     792           0 :       break;
     793             :     } while(0);
     794             :   }
     795             : 
     796           0 :   return true;
     797             : }
     798             : 
     799             : bool
     800           0 : RegisteredKey::ToJSON(nsAString& aJSON) const
     801             : {
     802           0 :   AutoJSAPI jsapi;
     803           0 :   jsapi.Init();
     804           0 :   JSContext *cx = jsapi.cx();
     805             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     806             :   // because we'll only be creating objects, in ways that have no
     807             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     808             :   // which likewise guarantees no side-effects for the sorts of
     809             :   // things we will pass it.
     810           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     811           0 :   JS::Rooted<JS::Value> val(cx);
     812           0 :   if (!ToObjectInternal(cx, &val)) {
     813           0 :     return false;
     814             :   }
     815           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     816           0 :   return StringifyToJSON(cx, obj, aJSON);
     817             : }
     818             : 
     819             : void
     820           0 : RegisteredKey::TraceDictionary(JSTracer* trc)
     821             : {
     822           0 : }
     823             : 
     824             : RegisteredKey&
     825           0 : RegisteredKey::operator=(const RegisteredKey& aOther)
     826             : {
     827           0 :   mAppId.Reset();
     828           0 :   if (aOther.mAppId.WasPassed()) {
     829           0 :     mAppId.Construct(aOther.mAppId.Value());
     830             :   }
     831           0 :   mKeyHandle.Reset();
     832           0 :   if (aOther.mKeyHandle.WasPassed()) {
     833           0 :     mKeyHandle.Construct(aOther.mKeyHandle.Value());
     834             :   }
     835           0 :   mTransports.Reset();
     836           0 :   if (aOther.mTransports.WasPassed()) {
     837           0 :     mTransports.Construct(aOther.mTransports.Value());
     838             :   }
     839           0 :   mVersion.Reset();
     840           0 :   if (aOther.mVersion.WasPassed()) {
     841           0 :     mVersion.Construct(aOther.mVersion.Value());
     842             :   }
     843           0 :   return *this;
     844             : }
     845             : 
     846             : namespace binding_detail {
     847             : } // namespace binding_detail
     848             : 
     849             : 
     850             : 
     851           0 : SignResponse::SignResponse()
     852             : {
     853             :   // Safe to pass a null context if we pass a null value
     854           0 :   Init(nullptr, JS::NullHandleValue);
     855           0 : }
     856             : 
     857             : 
     858             : 
     859             : bool
     860           0 : SignResponse::InitIds(JSContext* cx, SignResponseAtoms* atomsCache)
     861             : {
     862           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     863             : 
     864             :   // Initialize these in reverse order so that any failure leaves the first one
     865             :   // uninitialized.
     866           0 :   if (!atomsCache->signatureData_id.init(cx, "signatureData") ||
     867           0 :       !atomsCache->keyHandle_id.init(cx, "keyHandle") ||
     868           0 :       !atomsCache->errorMessage_id.init(cx, "errorMessage") ||
     869           0 :       !atomsCache->errorCode_id.init(cx, "errorCode") ||
     870           0 :       !atomsCache->clientData_id.init(cx, "clientData")) {
     871           0 :     return false;
     872             :   }
     873           0 :   return true;
     874             : }
     875             : 
     876             : bool
     877           0 : SignResponse::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     878             : {
     879             :   // Passing a null JSContext is OK only if we're initing from null,
     880             :   // Since in that case we will not have to do any property gets
     881             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     882             :   // checkers by static analysis tools
     883           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     884           0 :   SignResponseAtoms* atomsCache = nullptr;
     885           0 :   if (cx) {
     886           0 :     atomsCache = GetAtomCache<SignResponseAtoms>(cx);
     887           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     888           0 :       return false;
     889             :     }
     890             :   }
     891             : 
     892           0 :   if (!IsConvertibleToDictionary(val)) {
     893           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     894             :   }
     895             : 
     896           0 :   bool isNull = val.isNullOrUndefined();
     897             :   // We only need these if !isNull, in which case we have |cx|.
     898           0 :   Maybe<JS::Rooted<JSObject *> > object;
     899           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     900           0 :   if (!isNull) {
     901           0 :     MOZ_ASSERT(cx);
     902           0 :     object.emplace(cx, &val.toObject());
     903           0 :     temp.emplace(cx);
     904             :   }
     905           0 :   if (!isNull) {
     906           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->clientData_id, temp.ptr())) {
     907           0 :       return false;
     908             :     }
     909             :   }
     910           0 :   if (!isNull && !temp->isUndefined()) {
     911           0 :     mClientData.Construct();
     912           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mClientData.Value()))) {
     913           0 :       return false;
     914             :     }
     915           0 :     mIsAnyMemberPresent = true;
     916             :   }
     917             : 
     918           0 :   if (!isNull) {
     919           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->errorCode_id, temp.ptr())) {
     920           0 :       return false;
     921             :     }
     922             :   }
     923           0 :   if (!isNull && !temp->isUndefined()) {
     924           0 :     mErrorCode.Construct();
     925           0 :     if (temp.ref().isNullOrUndefined()) {
     926           0 :       (mErrorCode.Value()).SetNull();
     927           0 :     } else if (!ValueToPrimitive<uint16_t, eDefault>(cx, temp.ref(), &(mErrorCode.Value()).SetValue())) {
     928           0 :       return false;
     929             :     }
     930           0 :     mIsAnyMemberPresent = true;
     931             :   }
     932             : 
     933           0 :   if (!isNull) {
     934           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->errorMessage_id, temp.ptr())) {
     935           0 :       return false;
     936             :     }
     937             :   }
     938           0 :   if (!isNull && !temp->isUndefined()) {
     939           0 :     mErrorMessage.Construct();
     940           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, (mErrorMessage.Value()))) {
     941           0 :       return false;
     942             :     }
     943           0 :     mIsAnyMemberPresent = true;
     944             :   }
     945             : 
     946           0 :   if (!isNull) {
     947           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->keyHandle_id, temp.ptr())) {
     948           0 :       return false;
     949             :     }
     950             :   }
     951           0 :   if (!isNull && !temp->isUndefined()) {
     952           0 :     mKeyHandle.Construct();
     953           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mKeyHandle.Value()))) {
     954           0 :       return false;
     955             :     }
     956           0 :     mIsAnyMemberPresent = true;
     957             :   }
     958             : 
     959           0 :   if (!isNull) {
     960           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->signatureData_id, temp.ptr())) {
     961           0 :       return false;
     962             :     }
     963             :   }
     964           0 :   if (!isNull && !temp->isUndefined()) {
     965           0 :     mSignatureData.Construct();
     966           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mSignatureData.Value()))) {
     967           0 :       return false;
     968             :     }
     969           0 :     mIsAnyMemberPresent = true;
     970             :   }
     971           0 :   return true;
     972             : }
     973             : 
     974             : bool
     975           0 : SignResponse::Init(const nsAString& aJSON)
     976             : {
     977           0 :   AutoJSAPI jsapi;
     978           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     979           0 :   if (!cleanGlobal) {
     980           0 :     return false;
     981             :   }
     982           0 :   if (!jsapi.Init(cleanGlobal)) {
     983           0 :     return false;
     984             :   }
     985           0 :   JSContext* cx = jsapi.cx();
     986           0 :   JS::Rooted<JS::Value> json(cx);
     987           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     988           0 :   NS_ENSURE_TRUE(ok, false);
     989           0 :   return Init(cx, json);
     990             : }
     991             : 
     992             : bool
     993           0 : SignResponse::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     994             : {
     995           0 :   SignResponseAtoms* atomsCache = GetAtomCache<SignResponseAtoms>(cx);
     996           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     997           0 :     return false;
     998             :   }
     999             : 
    1000           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    1001           0 :   if (!obj) {
    1002           0 :     return false;
    1003             :   }
    1004           0 :   rval.set(JS::ObjectValue(*obj));
    1005             : 
    1006           0 :   if (mClientData.WasPassed()) {
    1007             :     do {
    1008             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1009           0 :       JS::Rooted<JS::Value> temp(cx);
    1010           0 :       nsString const & currentValue = mClientData.InternalValue();
    1011           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    1012           0 :         return false;
    1013             :       }
    1014           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->clientData_id, temp, JSPROP_ENUMERATE)) {
    1015           0 :         return false;
    1016             :       }
    1017           0 :       break;
    1018             :     } while(0);
    1019             :   }
    1020             : 
    1021           0 :   if (mErrorCode.WasPassed()) {
    1022             :     do {
    1023             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1024           0 :       JS::Rooted<JS::Value> temp(cx);
    1025           0 :       Nullable<uint16_t> const & currentValue = mErrorCode.InternalValue();
    1026           0 :       if (currentValue.IsNull()) {
    1027           0 :         temp.setNull();
    1028           0 :         if (!JS_DefinePropertyById(cx, obj, atomsCache->errorCode_id, temp, JSPROP_ENUMERATE)) {
    1029           0 :           return false;
    1030             :         }
    1031           0 :         break;
    1032             :       }
    1033           0 :       temp.setInt32(int32_t(currentValue.Value()));
    1034           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->errorCode_id, temp, JSPROP_ENUMERATE)) {
    1035           0 :         return false;
    1036             :       }
    1037           0 :       break;
    1038             :     } while(0);
    1039             :   }
    1040             : 
    1041           0 :   if (mErrorMessage.WasPassed()) {
    1042             :     do {
    1043             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1044           0 :       JS::Rooted<JS::Value> temp(cx);
    1045           0 :       nsString const & currentValue = mErrorMessage.InternalValue();
    1046           0 :       if (!xpc::StringToJsval(cx, currentValue, &temp)) {
    1047           0 :         return false;
    1048             :       }
    1049           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->errorMessage_id, temp, JSPROP_ENUMERATE)) {
    1050           0 :         return false;
    1051             :       }
    1052           0 :       break;
    1053             :     } while(0);
    1054             :   }
    1055             : 
    1056           0 :   if (mKeyHandle.WasPassed()) {
    1057             :     do {
    1058             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1059           0 :       JS::Rooted<JS::Value> temp(cx);
    1060           0 :       nsString const & currentValue = mKeyHandle.InternalValue();
    1061           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    1062           0 :         return false;
    1063             :       }
    1064           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->keyHandle_id, temp, JSPROP_ENUMERATE)) {
    1065           0 :         return false;
    1066             :       }
    1067           0 :       break;
    1068             :     } while(0);
    1069             :   }
    1070             : 
    1071           0 :   if (mSignatureData.WasPassed()) {
    1072             :     do {
    1073             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1074           0 :       JS::Rooted<JS::Value> temp(cx);
    1075           0 :       nsString const & currentValue = mSignatureData.InternalValue();
    1076           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    1077           0 :         return false;
    1078             :       }
    1079           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->signatureData_id, temp, JSPROP_ENUMERATE)) {
    1080           0 :         return false;
    1081             :       }
    1082           0 :       break;
    1083             :     } while(0);
    1084             :   }
    1085             : 
    1086           0 :   return true;
    1087             : }
    1088             : 
    1089             : bool
    1090           0 : SignResponse::ToJSON(nsAString& aJSON) const
    1091             : {
    1092           0 :   AutoJSAPI jsapi;
    1093           0 :   jsapi.Init();
    1094           0 :   JSContext *cx = jsapi.cx();
    1095             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    1096             :   // because we'll only be creating objects, in ways that have no
    1097             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    1098             :   // which likewise guarantees no side-effects for the sorts of
    1099             :   // things we will pass it.
    1100           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    1101           0 :   JS::Rooted<JS::Value> val(cx);
    1102           0 :   if (!ToObjectInternal(cx, &val)) {
    1103           0 :     return false;
    1104             :   }
    1105           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    1106           0 :   return StringifyToJSON(cx, obj, aJSON);
    1107             : }
    1108             : 
    1109             : void
    1110           0 : SignResponse::TraceDictionary(JSTracer* trc)
    1111             : {
    1112           0 : }
    1113             : 
    1114             : SignResponse&
    1115           0 : SignResponse::operator=(const SignResponse& aOther)
    1116             : {
    1117           0 :   mClientData.Reset();
    1118           0 :   if (aOther.mClientData.WasPassed()) {
    1119           0 :     mClientData.Construct(aOther.mClientData.Value());
    1120             :   }
    1121           0 :   mErrorCode.Reset();
    1122           0 :   if (aOther.mErrorCode.WasPassed()) {
    1123           0 :     mErrorCode.Construct(aOther.mErrorCode.Value());
    1124             :   }
    1125           0 :   mErrorMessage.Reset();
    1126           0 :   if (aOther.mErrorMessage.WasPassed()) {
    1127           0 :     mErrorMessage.Construct(aOther.mErrorMessage.Value());
    1128             :   }
    1129           0 :   mKeyHandle.Reset();
    1130           0 :   if (aOther.mKeyHandle.WasPassed()) {
    1131           0 :     mKeyHandle.Construct(aOther.mKeyHandle.Value());
    1132             :   }
    1133           0 :   mSignatureData.Reset();
    1134           0 :   if (aOther.mSignatureData.WasPassed()) {
    1135           0 :     mSignatureData.Construct(aOther.mSignatureData.Value());
    1136             :   }
    1137           0 :   return *this;
    1138             : }
    1139             : 
    1140             : namespace binding_detail {
    1141             : } // namespace binding_detail
    1142             : 
    1143             : 
    1144             : 
    1145           0 : U2FClientData::U2FClientData()
    1146             : {
    1147             :   // Safe to pass a null context if we pass a null value
    1148           0 :   Init(nullptr, JS::NullHandleValue);
    1149           0 : }
    1150             : 
    1151             : 
    1152             : 
    1153             : bool
    1154           0 : U2FClientData::InitIds(JSContext* cx, U2FClientDataAtoms* atomsCache)
    1155             : {
    1156           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1157             : 
    1158             :   // Initialize these in reverse order so that any failure leaves the first one
    1159             :   // uninitialized.
    1160           0 :   if (!atomsCache->typ_id.init(cx, "typ") ||
    1161           0 :       !atomsCache->origin_id.init(cx, "origin") ||
    1162           0 :       !atomsCache->challenge_id.init(cx, "challenge")) {
    1163           0 :     return false;
    1164             :   }
    1165           0 :   return true;
    1166             : }
    1167             : 
    1168             : bool
    1169           0 : U2FClientData::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1170             : {
    1171             :   // Passing a null JSContext is OK only if we're initing from null,
    1172             :   // Since in that case we will not have to do any property gets
    1173             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1174             :   // checkers by static analysis tools
    1175           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1176           0 :   U2FClientDataAtoms* atomsCache = nullptr;
    1177           0 :   if (cx) {
    1178           0 :     atomsCache = GetAtomCache<U2FClientDataAtoms>(cx);
    1179           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1180           0 :       return false;
    1181             :     }
    1182             :   }
    1183             : 
    1184           0 :   if (!IsConvertibleToDictionary(val)) {
    1185           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    1186             :   }
    1187             : 
    1188           0 :   bool isNull = val.isNullOrUndefined();
    1189             :   // We only need these if !isNull, in which case we have |cx|.
    1190           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1191           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1192           0 :   if (!isNull) {
    1193           0 :     MOZ_ASSERT(cx);
    1194           0 :     object.emplace(cx, &val.toObject());
    1195           0 :     temp.emplace(cx);
    1196             :   }
    1197           0 :   if (!isNull) {
    1198           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->challenge_id, temp.ptr())) {
    1199           0 :       return false;
    1200             :     }
    1201             :   }
    1202           0 :   if (!isNull && !temp->isUndefined()) {
    1203           0 :     mChallenge.Construct();
    1204           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mChallenge.Value()))) {
    1205           0 :       return false;
    1206             :     }
    1207           0 :     mIsAnyMemberPresent = true;
    1208             :   }
    1209             : 
    1210           0 :   if (!isNull) {
    1211           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->origin_id, temp.ptr())) {
    1212           0 :       return false;
    1213             :     }
    1214             :   }
    1215           0 :   if (!isNull && !temp->isUndefined()) {
    1216           0 :     mOrigin.Construct();
    1217           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mOrigin.Value()))) {
    1218           0 :       return false;
    1219             :     }
    1220           0 :     mIsAnyMemberPresent = true;
    1221             :   }
    1222             : 
    1223           0 :   if (!isNull) {
    1224           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->typ_id, temp.ptr())) {
    1225           0 :       return false;
    1226             :     }
    1227             :   }
    1228           0 :   if (!isNull && !temp->isUndefined()) {
    1229           0 :     mTyp.Construct();
    1230           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mTyp.Value()))) {
    1231           0 :       return false;
    1232             :     }
    1233           0 :     mIsAnyMemberPresent = true;
    1234             :   }
    1235           0 :   return true;
    1236             : }
    1237             : 
    1238             : bool
    1239           0 : U2FClientData::Init(const nsAString& aJSON)
    1240             : {
    1241           0 :   AutoJSAPI jsapi;
    1242           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    1243           0 :   if (!cleanGlobal) {
    1244           0 :     return false;
    1245             :   }
    1246           0 :   if (!jsapi.Init(cleanGlobal)) {
    1247           0 :     return false;
    1248             :   }
    1249           0 :   JSContext* cx = jsapi.cx();
    1250           0 :   JS::Rooted<JS::Value> json(cx);
    1251           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    1252           0 :   NS_ENSURE_TRUE(ok, false);
    1253           0 :   return Init(cx, json);
    1254             : }
    1255             : 
    1256             : bool
    1257           0 : U2FClientData::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1258             : {
    1259           0 :   U2FClientDataAtoms* atomsCache = GetAtomCache<U2FClientDataAtoms>(cx);
    1260           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1261           0 :     return false;
    1262             :   }
    1263             : 
    1264           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    1265           0 :   if (!obj) {
    1266           0 :     return false;
    1267             :   }
    1268           0 :   rval.set(JS::ObjectValue(*obj));
    1269             : 
    1270           0 :   if (mChallenge.WasPassed()) {
    1271             :     do {
    1272             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1273           0 :       JS::Rooted<JS::Value> temp(cx);
    1274           0 :       nsString const & currentValue = mChallenge.InternalValue();
    1275           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    1276           0 :         return false;
    1277             :       }
    1278           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->challenge_id, temp, JSPROP_ENUMERATE)) {
    1279           0 :         return false;
    1280             :       }
    1281           0 :       break;
    1282             :     } while(0);
    1283             :   }
    1284             : 
    1285           0 :   if (mOrigin.WasPassed()) {
    1286             :     do {
    1287             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1288           0 :       JS::Rooted<JS::Value> temp(cx);
    1289           0 :       nsString const & currentValue = mOrigin.InternalValue();
    1290           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    1291           0 :         return false;
    1292             :       }
    1293           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->origin_id, temp, JSPROP_ENUMERATE)) {
    1294           0 :         return false;
    1295             :       }
    1296           0 :       break;
    1297             :     } while(0);
    1298             :   }
    1299             : 
    1300           0 :   if (mTyp.WasPassed()) {
    1301             :     do {
    1302             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1303           0 :       JS::Rooted<JS::Value> temp(cx);
    1304           0 :       nsString const & currentValue = mTyp.InternalValue();
    1305           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    1306           0 :         return false;
    1307             :       }
    1308           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->typ_id, temp, JSPROP_ENUMERATE)) {
    1309           0 :         return false;
    1310             :       }
    1311           0 :       break;
    1312             :     } while(0);
    1313             :   }
    1314             : 
    1315           0 :   return true;
    1316             : }
    1317             : 
    1318             : bool
    1319           0 : U2FClientData::ToJSON(nsAString& aJSON) const
    1320             : {
    1321           0 :   AutoJSAPI jsapi;
    1322           0 :   jsapi.Init();
    1323           0 :   JSContext *cx = jsapi.cx();
    1324             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    1325             :   // because we'll only be creating objects, in ways that have no
    1326             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    1327             :   // which likewise guarantees no side-effects for the sorts of
    1328             :   // things we will pass it.
    1329           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    1330           0 :   JS::Rooted<JS::Value> val(cx);
    1331           0 :   if (!ToObjectInternal(cx, &val)) {
    1332           0 :     return false;
    1333             :   }
    1334           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    1335           0 :   return StringifyToJSON(cx, obj, aJSON);
    1336             : }
    1337             : 
    1338             : void
    1339           0 : U2FClientData::TraceDictionary(JSTracer* trc)
    1340             : {
    1341           0 : }
    1342             : 
    1343             : U2FClientData&
    1344           0 : U2FClientData::operator=(const U2FClientData& aOther)
    1345             : {
    1346           0 :   mChallenge.Reset();
    1347           0 :   if (aOther.mChallenge.WasPassed()) {
    1348           0 :     mChallenge.Construct(aOther.mChallenge.Value());
    1349             :   }
    1350           0 :   mOrigin.Reset();
    1351           0 :   if (aOther.mOrigin.WasPassed()) {
    1352           0 :     mOrigin.Construct(aOther.mOrigin.Value());
    1353             :   }
    1354           0 :   mTyp.Reset();
    1355           0 :   if (aOther.mTyp.WasPassed()) {
    1356           0 :     mTyp.Construct(aOther.mTyp.Value());
    1357             :   }
    1358           0 :   return *this;
    1359             : }
    1360             : 
    1361             : namespace binding_detail {
    1362             : } // namespace binding_detail
    1363             : 
    1364             : 
    1365             : void
    1366           0 : U2FRegisterCallback::Call(JSContext* cx, JS::Handle<JS::Value> aThisVal, const RegisterResponse& response, ErrorResult& aRv)
    1367             : {
    1368           0 :   JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    1369           0 :   JS::AutoValueVector argv(cx);
    1370           0 :   if (!argv.resize(1)) {
    1371           0 :     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    1372           0 :     return;
    1373             :   }
    1374           0 :   unsigned argc = 1;
    1375             : 
    1376             :   do {
    1377           0 :     if (!response.ToObjectInternal(cx, argv[0])) {
    1378           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1379           0 :       return;
    1380             :     }
    1381           0 :     break;
    1382             :   } while (0);
    1383             : 
    1384           0 :   JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
    1385           0 :   if (!JS::Call(cx, aThisVal, callable,
    1386           0 :                 JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    1387           0 :     aRv.NoteJSContextException(cx);
    1388           0 :     return;
    1389             :   }
    1390             : }
    1391             : 
    1392             : 
    1393             : 
    1394             : void
    1395           0 : U2FSignCallback::Call(JSContext* cx, JS::Handle<JS::Value> aThisVal, const SignResponse& response, ErrorResult& aRv)
    1396             : {
    1397           0 :   JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    1398           0 :   JS::AutoValueVector argv(cx);
    1399           0 :   if (!argv.resize(1)) {
    1400           0 :     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    1401           0 :     return;
    1402             :   }
    1403           0 :   unsigned argc = 1;
    1404             : 
    1405             :   do {
    1406           0 :     if (!response.ToObjectInternal(cx, argv[0])) {
    1407           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1408           0 :       return;
    1409             :     }
    1410           0 :     break;
    1411             :   } while (0);
    1412             : 
    1413           0 :   JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
    1414           0 :   if (!JS::Call(cx, aThisVal, callable,
    1415           0 :                 JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    1416           0 :     aRv.NoteJSContextException(cx);
    1417           0 :     return;
    1418             :   }
    1419             : }
    1420             : 
    1421             : 
    1422             : 
    1423             : namespace binding_detail {
    1424             : } // namespace binding_detail
    1425             : 
    1426             : 
    1427             : namespace binding_detail {
    1428             : } // namespace binding_detail
    1429             : 
    1430             : 
    1431             : namespace U2FBinding {
    1432             : 
    1433             : static bool
    1434           0 : _register_(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::U2F* self, const JSJitMethodCallArgs& args)
    1435             : {
    1436           0 :   if (MOZ_UNLIKELY(args.length() < 4)) {
    1437           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "U2F.register");
    1438             :   }
    1439           0 :   binding_detail::FakeString arg0;
    1440           0 :   if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
    1441           0 :     return false;
    1442             :   }
    1443           0 :   binding_detail::AutoSequence<RegisterRequest> arg1;
    1444           0 :   if (args[1].isObject()) {
    1445           0 :     JS::ForOfIterator iter(cx);
    1446           0 :     if (!iter.init(args[1], JS::ForOfIterator::AllowNonIterable)) {
    1447           0 :       return false;
    1448             :     }
    1449           0 :     if (!iter.valueIsIterable()) {
    1450           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 2 of U2F.register");
    1451           0 :       return false;
    1452             :     }
    1453           0 :     binding_detail::AutoSequence<RegisterRequest> &arr = arg1;
    1454           0 :     JS::Rooted<JS::Value> temp(cx);
    1455             :     while (true) {
    1456             :       bool done;
    1457           0 :       if (!iter.next(&temp, &done)) {
    1458           0 :         return false;
    1459             :       }
    1460           0 :       if (done) {
    1461           0 :         break;
    1462             :       }
    1463           0 :       RegisterRequest* slotPtr = arr.AppendElement(mozilla::fallible);
    1464           0 :       if (!slotPtr) {
    1465           0 :         JS_ReportOutOfMemory(cx);
    1466           0 :         return false;
    1467             :       }
    1468           0 :       RegisterRequest& slot = *slotPtr;
    1469           0 :       if (!slot.Init(cx, temp,  "Element of argument 2 of U2F.register", false)) {
    1470           0 :         return false;
    1471             :       }
    1472           0 :     }
    1473             :   } else {
    1474           0 :     ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 2 of U2F.register");
    1475           0 :     return false;
    1476             :   }
    1477           0 :   binding_detail::AutoSequence<RegisteredKey> arg2;
    1478           0 :   if (args[2].isObject()) {
    1479           0 :     JS::ForOfIterator iter(cx);
    1480           0 :     if (!iter.init(args[2], JS::ForOfIterator::AllowNonIterable)) {
    1481           0 :       return false;
    1482             :     }
    1483           0 :     if (!iter.valueIsIterable()) {
    1484           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 3 of U2F.register");
    1485           0 :       return false;
    1486             :     }
    1487           0 :     binding_detail::AutoSequence<RegisteredKey> &arr = arg2;
    1488           0 :     JS::Rooted<JS::Value> temp(cx);
    1489             :     while (true) {
    1490             :       bool done;
    1491           0 :       if (!iter.next(&temp, &done)) {
    1492           0 :         return false;
    1493             :       }
    1494           0 :       if (done) {
    1495           0 :         break;
    1496             :       }
    1497           0 :       RegisteredKey* slotPtr = arr.AppendElement(mozilla::fallible);
    1498           0 :       if (!slotPtr) {
    1499           0 :         JS_ReportOutOfMemory(cx);
    1500           0 :         return false;
    1501             :       }
    1502           0 :       RegisteredKey& slot = *slotPtr;
    1503           0 :       if (!slot.Init(cx, temp,  "Element of argument 3 of U2F.register", false)) {
    1504           0 :         return false;
    1505             :       }
    1506           0 :     }
    1507             :   } else {
    1508           0 :     ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 3 of U2F.register");
    1509           0 :     return false;
    1510             :   }
    1511           0 :   RootedCallback<OwningNonNull<binding_detail::FastU2FRegisterCallback>> arg3(cx);
    1512           0 :   if (args[3].isObject()) {
    1513           0 :     if (JS::IsCallable(&args[3].toObject())) {
    1514             :     { // scope for tempRoot
    1515           0 :       JS::Rooted<JSObject*> tempRoot(cx, &args[3].toObject());
    1516           0 :       arg3 = new binding_detail::FastU2FRegisterCallback(tempRoot);
    1517             :     }
    1518             :     } else {
    1519           0 :       ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "Argument 4 of U2F.register");
    1520           0 :       return false;
    1521             :     }
    1522             :   } else {
    1523           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 4 of U2F.register");
    1524           0 :     return false;
    1525             :   }
    1526           0 :   Optional<Nullable<int32_t>> arg4;
    1527           0 :   if (args.hasDefined(4)) {
    1528           0 :     arg4.Construct();
    1529           0 :     if (args[4].isNullOrUndefined()) {
    1530           0 :       arg4.Value().SetNull();
    1531           0 :     } else if (!ValueToPrimitive<int32_t, eDefault>(cx, args[4], &arg4.Value().SetValue())) {
    1532           0 :       return false;
    1533             :     }
    1534             :   }
    1535           0 :   binding_detail::FastErrorResult rv;
    1536           0 :   self->Register(NonNullHelper(Constify(arg0)), Constify(arg1), Constify(arg2), NonNullHelper(arg3), Constify(arg4), rv);
    1537           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    1538           0 :     return false;
    1539             :   }
    1540           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    1541           0 :   args.rval().setUndefined();
    1542           0 :   return true;
    1543             : }
    1544             : 
    1545             : static const JSJitInfo register_methodinfo = {
    1546             :   { (JSJitGetterOp)_register_ },
    1547             :   { prototypes::id::U2F },
    1548             :   { PrototypeTraits<prototypes::id::U2F>::Depth },
    1549             :   JSJitInfo::Method,
    1550             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    1551             :   JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
    1552             :   false,  /* isInfallible. False in setters. */
    1553             :   false,  /* isMovable.  Not relevant for setters. */
    1554             :   false, /* isEliminatable.  Not relevant for setters. */
    1555             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    1556             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    1557             :   false,  /* isTypedMethod.  Only relevant for methods. */
    1558             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    1559             : };
    1560             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    1561             : static_assert(0 < 1, "There is no slot for us");
    1562             : 
    1563             : static bool
    1564           0 : sign(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::U2F* self, const JSJitMethodCallArgs& args)
    1565             : {
    1566           0 :   if (MOZ_UNLIKELY(args.length() < 4)) {
    1567           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "U2F.sign");
    1568             :   }
    1569           0 :   binding_detail::FakeString arg0;
    1570           0 :   if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
    1571           0 :     return false;
    1572             :   }
    1573           0 :   binding_detail::FakeString arg1;
    1574           0 :   if (!ConvertJSValueToString(cx, args[1], eStringify, eStringify, arg1)) {
    1575           0 :     return false;
    1576             :   }
    1577           0 :   binding_detail::AutoSequence<RegisteredKey> arg2;
    1578           0 :   if (args[2].isObject()) {
    1579           0 :     JS::ForOfIterator iter(cx);
    1580           0 :     if (!iter.init(args[2], JS::ForOfIterator::AllowNonIterable)) {
    1581           0 :       return false;
    1582             :     }
    1583           0 :     if (!iter.valueIsIterable()) {
    1584           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 3 of U2F.sign");
    1585           0 :       return false;
    1586             :     }
    1587           0 :     binding_detail::AutoSequence<RegisteredKey> &arr = arg2;
    1588           0 :     JS::Rooted<JS::Value> temp(cx);
    1589             :     while (true) {
    1590             :       bool done;
    1591           0 :       if (!iter.next(&temp, &done)) {
    1592           0 :         return false;
    1593             :       }
    1594           0 :       if (done) {
    1595           0 :         break;
    1596             :       }
    1597           0 :       RegisteredKey* slotPtr = arr.AppendElement(mozilla::fallible);
    1598           0 :       if (!slotPtr) {
    1599           0 :         JS_ReportOutOfMemory(cx);
    1600           0 :         return false;
    1601             :       }
    1602           0 :       RegisteredKey& slot = *slotPtr;
    1603           0 :       if (!slot.Init(cx, temp,  "Element of argument 3 of U2F.sign", false)) {
    1604           0 :         return false;
    1605             :       }
    1606           0 :     }
    1607             :   } else {
    1608           0 :     ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 3 of U2F.sign");
    1609           0 :     return false;
    1610             :   }
    1611           0 :   RootedCallback<OwningNonNull<binding_detail::FastU2FSignCallback>> arg3(cx);
    1612           0 :   if (args[3].isObject()) {
    1613           0 :     if (JS::IsCallable(&args[3].toObject())) {
    1614             :     { // scope for tempRoot
    1615           0 :       JS::Rooted<JSObject*> tempRoot(cx, &args[3].toObject());
    1616           0 :       arg3 = new binding_detail::FastU2FSignCallback(tempRoot);
    1617             :     }
    1618             :     } else {
    1619           0 :       ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "Argument 4 of U2F.sign");
    1620           0 :       return false;
    1621             :     }
    1622             :   } else {
    1623           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 4 of U2F.sign");
    1624           0 :     return false;
    1625             :   }
    1626           0 :   Optional<Nullable<int32_t>> arg4;
    1627           0 :   if (args.hasDefined(4)) {
    1628           0 :     arg4.Construct();
    1629           0 :     if (args[4].isNullOrUndefined()) {
    1630           0 :       arg4.Value().SetNull();
    1631           0 :     } else if (!ValueToPrimitive<int32_t, eDefault>(cx, args[4], &arg4.Value().SetValue())) {
    1632           0 :       return false;
    1633             :     }
    1634             :   }
    1635           0 :   binding_detail::FastErrorResult rv;
    1636           0 :   self->Sign(NonNullHelper(Constify(arg0)), NonNullHelper(Constify(arg1)), Constify(arg2), NonNullHelper(arg3), Constify(arg4), rv);
    1637           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    1638           0 :     return false;
    1639             :   }
    1640           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    1641           0 :   args.rval().setUndefined();
    1642           0 :   return true;
    1643             : }
    1644             : 
    1645             : static const JSJitInfo sign_methodinfo = {
    1646             :   { (JSJitGetterOp)sign },
    1647             :   { prototypes::id::U2F },
    1648             :   { PrototypeTraits<prototypes::id::U2F>::Depth },
    1649             :   JSJitInfo::Method,
    1650             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    1651             :   JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
    1652             :   false,  /* isInfallible. False in setters. */
    1653             :   false,  /* isMovable.  Not relevant for setters. */
    1654             :   false, /* isEliminatable.  Not relevant for setters. */
    1655             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    1656             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    1657             :   false,  /* isTypedMethod.  Only relevant for methods. */
    1658             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    1659             : };
    1660             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    1661             : static_assert(0 < 1, "There is no slot for us");
    1662             : 
    1663             : static bool
    1664           0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
    1665             : {
    1666           0 :   mozilla::dom::U2F* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::U2F>(obj);
    1667             :   // We don't want to preserve if we don't have a wrapper, and we
    1668             :   // obviously can't preserve if we're not initialized.
    1669           0 :   if (self && self->GetWrapperPreserveColor()) {
    1670           0 :     PreserveWrapper(self);
    1671             :   }
    1672           0 :   return true;
    1673             : }
    1674             : 
    1675             : static void
    1676           0 : _finalize(js::FreeOp* fop, JSObject* obj)
    1677             : {
    1678           0 :   mozilla::dom::U2F* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::U2F>(obj);
    1679           0 :   if (self) {
    1680           0 :     ClearWrapper(self, self, obj);
    1681           0 :     AddForDeferredFinalization<mozilla::dom::U2F>(self);
    1682             :   }
    1683           0 : }
    1684             : 
    1685             : static void
    1686           0 : _objectMoved(JSObject* obj, const JSObject* old)
    1687             : {
    1688           0 :   mozilla::dom::U2F* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::U2F>(obj);
    1689           0 :   if (self) {
    1690           0 :     UpdateWrapper(self, self, obj, old);
    1691             :   }
    1692           0 : }
    1693             : 
    1694             : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
    1695             : #if defined(__clang__)
    1696             : #pragma clang diagnostic push
    1697             : #pragma clang diagnostic ignored "-Wmissing-braces"
    1698             : #endif
    1699             : static const JSFunctionSpec sMethods_specs[] = {
    1700             :   JS_FNSPEC("register", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&register_methodinfo), 4, JSPROP_ENUMERATE, nullptr),
    1701             :   JS_FNSPEC("sign", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&sign_methodinfo), 4, JSPROP_ENUMERATE, nullptr),
    1702             :   JS_FS_END
    1703             : };
    1704             : #if defined(__clang__)
    1705             : #pragma clang diagnostic pop
    1706             : #endif
    1707             : 
    1708             : 
    1709             : // Can't be const because the pref-enabled boolean needs to be writable
    1710             : static Prefable<const JSFunctionSpec> sMethods[] = {
    1711             :   { nullptr, &sMethods_specs[0] },
    1712             :   { nullptr, nullptr }
    1713             : };
    1714             : 
    1715             : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
    1716             :     "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
    1717             : static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
    1718             :     "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
    1719             : 
    1720             : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
    1721             : #if defined(__clang__)
    1722             : #pragma clang diagnostic push
    1723             : #pragma clang diagnostic ignored "-Wmissing-braces"
    1724             : #endif
    1725             : static const ConstantSpec sConstants_specs[] = {
    1726             :   { "OK", JS::Int32Value(0) },
    1727             :   { "OTHER_ERROR", JS::Int32Value(1) },
    1728             :   { "BAD_REQUEST", JS::Int32Value(2) },
    1729             :   { "CONFIGURATION_UNSUPPORTED", JS::Int32Value(3) },
    1730             :   { "DEVICE_INELIGIBLE", JS::Int32Value(4) },
    1731             :   { "TIMEOUT", JS::Int32Value(5) },
    1732             :   { 0, JS::UndefinedValue() }
    1733             : };
    1734             : #if defined(__clang__)
    1735             : #pragma clang diagnostic pop
    1736             : #endif
    1737             : 
    1738             : 
    1739             : // Can't be const because the pref-enabled boolean needs to be writable
    1740             : static Prefable<const ConstantSpec> sConstants[] = {
    1741             :   { nullptr, &sConstants_specs[0] },
    1742             :   { nullptr, nullptr }
    1743             : };
    1744             : 
    1745             : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
    1746             :     "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
    1747             : static_assert(6 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
    1748             :     "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
    1749             : 
    1750             : 
    1751             : static uint16_t sNativeProperties_sortedPropertyIndices[8];
    1752             : static PropertyInfo sNativeProperties_propertyInfos[8];
    1753             : 
    1754             : static const NativePropertiesN<2> sNativeProperties = {
    1755             :   false, 0,
    1756             :   false, 0,
    1757             :   true,  0 /* sMethods */,
    1758             :   false, 0,
    1759             :   false, 0,
    1760             :   false, 0,
    1761             :   true,  1 /* sConstants */,
    1762             :   -1,
    1763             :   8,
    1764             :   sNativeProperties_sortedPropertyIndices,
    1765             :   {
    1766             :     { sMethods, &sNativeProperties_propertyInfos[0] },
    1767             :     { sConstants, &sNativeProperties_propertyInfos[2] }
    1768             :   }
    1769             : };
    1770             : static_assert(8 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
    1771             :     "We have a property info count that is oversized");
    1772             : 
    1773             : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
    1774             :   {
    1775             :     "Function",
    1776             :     JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
    1777             :     &sBoringInterfaceObjectClassClassOps,
    1778             :     JS_NULL_CLASS_SPEC,
    1779             :     JS_NULL_CLASS_EXT,
    1780             :     &sInterfaceObjectClassObjectOps
    1781             :   },
    1782             :   eInterface,
    1783             :   true,
    1784             :   prototypes::id::U2F,
    1785             :   PrototypeTraits<prototypes::id::U2F>::Depth,
    1786             :   sNativePropertyHooks,
    1787             :   "function U2F() {\n    [native code]\n}",
    1788             :   JS::GetRealmFunctionPrototype
    1789             : };
    1790             : 
    1791             : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
    1792             :   {
    1793             :     "U2FPrototype",
    1794             :     JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
    1795             :     JS_NULL_CLASS_OPS,
    1796             :     JS_NULL_CLASS_SPEC,
    1797             :     JS_NULL_CLASS_EXT,
    1798             :     JS_NULL_OBJECT_OPS
    1799             :   },
    1800             :   eInterfacePrototype,
    1801             :   false,
    1802             :   prototypes::id::U2F,
    1803             :   PrototypeTraits<prototypes::id::U2F>::Depth,
    1804             :   sNativePropertyHooks,
    1805             :   "[object U2FPrototype]",
    1806             :   JS::GetRealmObjectPrototype
    1807             : };
    1808             : 
    1809             : bool
    1810           0 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
    1811             : {
    1812             :   static bool sPrefValue;
    1813             :   static bool sPrefCacheSetUp = false;
    1814           0 :   if (!sPrefCacheSetUp) {
    1815           0 :     sPrefCacheSetUp = true;
    1816           0 :     Preferences::AddBoolVarCache(&sPrefValue, "security.webauth.u2f");
    1817             :   }
    1818             : 
    1819           0 :   return sPrefValue;
    1820             : }
    1821             : 
    1822             : JSObject*
    1823           0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
    1824             : {
    1825           0 :   return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
    1826             : }
    1827             : 
    1828             : static const js::ClassOps sClassOps = {
    1829             :   _addProperty, /* addProperty */
    1830             :   nullptr,               /* delProperty */
    1831             :   nullptr,               /* getProperty */
    1832             :   nullptr,               /* setProperty */
    1833             :   nullptr,               /* enumerate */
    1834             :   nullptr, /* newEnumerate */
    1835             :   nullptr, /* resolve */
    1836             :   nullptr, /* mayResolve */
    1837             :   _finalize, /* finalize */
    1838             :   nullptr, /* call */
    1839             :   nullptr,               /* hasInstance */
    1840             :   nullptr,               /* construct */
    1841             :   nullptr, /* trace */
    1842             : };
    1843             : 
    1844             : static const js::ClassExtension sClassExtension = {
    1845             :   nullptr, /* weakmapKeyDelegateOp */
    1846             :   _objectMoved /* objectMovedOp */
    1847             : };
    1848             : 
    1849             : static const DOMJSClass sClass = {
    1850             :   { "U2F",
    1851             :     JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
    1852             :     &sClassOps,
    1853             :     JS_NULL_CLASS_SPEC,
    1854             :     &sClassExtension,
    1855             :     JS_NULL_OBJECT_OPS
    1856             :   },
    1857             :   { prototypes::id::U2F, 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 },
    1858             :   IsBaseOf<nsISupports, mozilla::dom::U2F >::value,
    1859             :   sNativePropertyHooks,
    1860             :   FindAssociatedGlobalForNative<mozilla::dom::U2F>::Get,
    1861             :   GetProtoObjectHandle,
    1862             :   GetCCParticipant<mozilla::dom::U2F>::Get()
    1863             : };
    1864             : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
    1865             :               "Must have the right minimal number of reserved slots.");
    1866             : static_assert(1 >= 1,
    1867             :               "Must have enough reserved slots.");
    1868             : 
    1869             : const JSClass*
    1870           0 : GetJSClass()
    1871             : {
    1872           0 :   return sClass.ToJSClass();
    1873             : }
    1874             : 
    1875             : bool
    1876           0 : Wrap(JSContext* aCx, mozilla::dom::U2F* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
    1877             : {
    1878             :   MOZ_ASSERT(static_cast<mozilla::dom::U2F*>(aObject) ==
    1879             :              reinterpret_cast<mozilla::dom::U2F*>(aObject),
    1880             :              "Multiple inheritance for mozilla::dom::U2F is broken.");
    1881           0 :   MOZ_ASSERT(ToSupportsIsCorrect(aObject));
    1882           0 :   MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
    1883           0 :   MOZ_ASSERT(!aCache->GetWrapper(),
    1884             :              "You should probably not be using Wrap() directly; use "
    1885             :              "GetOrCreateDOMReflector instead");
    1886             : 
    1887           0 :   MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
    1888             :              "nsISupports must be on our primary inheritance chain");
    1889             : 
    1890           0 :   JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
    1891           0 :   if (!global) {
    1892           0 :     return false;
    1893             :   }
    1894           0 :   MOZ_ASSERT(JS_IsGlobalObject(global));
    1895           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(global));
    1896             : 
    1897             :   // That might have ended up wrapping us already, due to the wonders
    1898             :   // of XBL.  Check for that, and bail out as needed.
    1899           0 :   aReflector.set(aCache->GetWrapper());
    1900           0 :   if (aReflector) {
    1901             : #ifdef DEBUG
    1902           0 :     binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
    1903             : #endif // DEBUG
    1904           0 :     return true;
    1905             :   }
    1906             : 
    1907           0 :   JSAutoCompartment ac(aCx, global);
    1908           0 :   JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
    1909           0 :   if (!canonicalProto) {
    1910           0 :     return false;
    1911             :   }
    1912           0 :   JS::Rooted<JSObject*> proto(aCx);
    1913           0 :   if (aGivenProto) {
    1914           0 :     proto = aGivenProto;
    1915             :     // Unfortunately, while aGivenProto was in the compartment of aCx
    1916             :     // coming in, we changed compartments to that of "parent" so may need
    1917             :     // to wrap the proto here.
    1918           0 :     if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
    1919           0 :       if (!JS_WrapObject(aCx, &proto)) {
    1920           0 :         return false;
    1921             :       }
    1922             :     }
    1923             :   } else {
    1924           0 :     proto = canonicalProto;
    1925             :   }
    1926             : 
    1927           0 :   BindingJSObjectCreator<mozilla::dom::U2F> creator(aCx);
    1928           0 :   creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
    1929           0 :   if (!aReflector) {
    1930           0 :     return false;
    1931             :   }
    1932             : 
    1933           0 :   aCache->SetWrapper(aReflector);
    1934           0 :   creator.InitializationSucceeded();
    1935             : 
    1936           0 :   MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
    1937             :              aCache->GetWrapperPreserveColor() == aReflector);
    1938             :   // If proto != canonicalProto, we have to preserve our wrapper;
    1939             :   // otherwise we won't be able to properly recreate it later, since
    1940             :   // we won't know what proto to use.  Note that we don't check
    1941             :   // aGivenProto here, since it's entirely possible (and even
    1942             :   // somewhat common) to have a non-null aGivenProto which is the
    1943             :   // same as canonicalProto.
    1944           0 :   if (proto != canonicalProto) {
    1945           0 :     PreserveWrapper(aObject);
    1946             :   }
    1947             : 
    1948           0 :   return true;
    1949             : }
    1950             : 
    1951             : const NativePropertyHooks sNativePropertyHooks[] = { {
    1952             :   nullptr,
    1953             :   nullptr,
    1954             :   nullptr,
    1955             :   { sNativeProperties.Upcast(), nullptr },
    1956             :   prototypes::id::U2F,
    1957             :   constructors::id::U2F,
    1958             :   nullptr,
    1959             :   &DefaultXrayExpandoObjectClass
    1960             : } };
    1961             : 
    1962             : void
    1963           0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
    1964             : {
    1965           0 :   JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
    1966           0 :   if (!parentProto) {
    1967           0 :     return;
    1968             :   }
    1969             : 
    1970           0 :   JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
    1971           0 :   if (!constructorProto) {
    1972           0 :     return;
    1973             :   }
    1974             : 
    1975             :   static bool sIdsInited = false;
    1976           0 :   if (!sIdsInited && NS_IsMainThread()) {
    1977           0 :     if (!InitIds(aCx, sNativeProperties.Upcast())) {
    1978           0 :       return;
    1979             :     }
    1980           0 :     sIdsInited = true;
    1981             :   }
    1982             : 
    1983           0 :   JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::U2F);
    1984           0 :   JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::U2F);
    1985           0 :   dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
    1986             :                               &sPrototypeClass.mBase, protoCache,
    1987             :                               constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
    1988             :                               interfaceCache,
    1989             :                               sNativeProperties.Upcast(),
    1990             :                               nullptr,
    1991             :                               "U2F", aDefineOnGlobal,
    1992             :                               nullptr,
    1993           0 :                               false);
    1994             : }
    1995             : 
    1996             : JS::Handle<JSObject*>
    1997           0 : GetProtoObjectHandle(JSContext* aCx)
    1998             : {
    1999             :   /* Get the interface prototype object for this class.  This will create the
    2000             :      object as needed. */
    2001           0 :   bool aDefineOnGlobal = true;
    2002             : 
    2003             :   /* Make sure our global is sane.  Hopefully we can remove this sometime */
    2004           0 :   JSObject* global = JS::CurrentGlobalOrNull(aCx);
    2005           0 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
    2006           0 :     return nullptr;
    2007             :   }
    2008             : 
    2009             :   /* Check to see whether the interface objects are already installed */
    2010           0 :   ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
    2011           0 :   if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::U2F)) {
    2012           0 :     JS::Rooted<JSObject*> rootedGlobal(aCx, global);
    2013           0 :     CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
    2014             :   }
    2015             : 
    2016             :   /*
    2017             :    * The object might _still_ be null, but that's OK.
    2018             :    *
    2019             :    * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
    2020             :    * traced by TraceProtoAndIfaceCache() and its contents are never
    2021             :    * changed after they have been set.
    2022             :    *
    2023             :    * Calling address() avoids the read read barrier that does gray
    2024             :    * unmarking, but it's not possible for the object to be gray here.
    2025             :    */
    2026             : 
    2027           0 :   const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::U2F);
    2028           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
    2029           0 :   return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
    2030             : }
    2031             : 
    2032             : JS::Handle<JSObject*>
    2033           0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
    2034             : {
    2035             :   /* Get the interface object for this class.  This will create the object as
    2036             :      needed. */
    2037             : 
    2038             :   /* Make sure our global is sane.  Hopefully we can remove this sometime */
    2039           0 :   JSObject* global = JS::CurrentGlobalOrNull(aCx);
    2040           0 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
    2041           0 :     return nullptr;
    2042             :   }
    2043             : 
    2044             :   /* Check to see whether the interface objects are already installed */
    2045           0 :   ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
    2046           0 :   if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::U2F)) {
    2047           0 :     JS::Rooted<JSObject*> rootedGlobal(aCx, global);
    2048           0 :     CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
    2049             :   }
    2050             : 
    2051             :   /*
    2052             :    * The object might _still_ be null, but that's OK.
    2053             :    *
    2054             :    * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
    2055             :    * traced by TraceProtoAndIfaceCache() and its contents are never
    2056             :    * changed after they have been set.
    2057             :    *
    2058             :    * Calling address() avoids the read read barrier that does gray
    2059             :    * unmarking, but it's not possible for the object to be gray here.
    2060             :    */
    2061             : 
    2062           0 :   const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::U2F);
    2063           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
    2064           0 :   return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
    2065             : }
    2066             : 
    2067             : JSObject*
    2068           0 : GetConstructorObject(JSContext* aCx)
    2069             : {
    2070           0 :   return GetConstructorObjectHandle(aCx);
    2071             : }
    2072             : 
    2073             : } // namespace U2FBinding
    2074             : 
    2075             : 
    2076             : 
    2077             : } // namespace dom
    2078             : } // namespace mozilla

Generated by: LCOV version 1.13