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

          Line data    Source code
       1             : /* THIS FILE IS AUTOGENERATED FROM RTCRtpSender.webidl BY Codegen.py - DO NOT EDIT */
       2             : 
       3             : #include "AtomList.h"
       4             : #include "RTCDTMFSenderBinding.h"
       5             : #include "RTCRtpSenderBinding.h"
       6             : #include "WrapperFactory.h"
       7             : #include "jsapi.h"
       8             : #include "mozilla/FloatingPoint.h"
       9             : #include "mozilla/OwningNonNull.h"
      10             : #include "mozilla/Preferences.h"
      11             : #include "mozilla/dom/BindingUtils.h"
      12             : #include "mozilla/dom/DOMJSClass.h"
      13             : #include "mozilla/dom/MediaStreamTrack.h"
      14             : #include "mozilla/dom/NonRefcountedDOMObject.h"
      15             : #include "mozilla/dom/Nullable.h"
      16             : #include "mozilla/dom/PrimitiveConversions.h"
      17             : #include "mozilla/dom/Promise.h"
      18             : #include "mozilla/dom/ScriptSettings.h"
      19             : #include "mozilla/dom/SimpleGlobalObject.h"
      20             : #include "mozilla/dom/ToJSValue.h"
      21             : #include "mozilla/dom/XrayExpandoClass.h"
      22             : #include "nsContentUtils.h"
      23             : #include "nsIGlobalObject.h"
      24             : 
      25             : namespace mozilla {
      26             : namespace dom {
      27             : 
      28             : namespace RTCPriorityTypeValues {
      29             : extern const EnumEntry strings[5] = {
      30             :   {"very-low", 8},
      31             :   {"low", 3},
      32             :   {"medium", 6},
      33             :   {"high", 4},
      34             :   { nullptr, 0 }
      35             : };
      36             : } // namespace RTCPriorityTypeValues
      37             : 
      38             : bool
      39           0 : ToJSValue(JSContext* aCx, RTCPriorityType aArgument, JS::MutableHandle<JS::Value> aValue)
      40             : {
      41           0 :   MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(RTCPriorityTypeValues::strings));
      42             :   JSString* resultStr =
      43           0 :     JS_NewStringCopyN(aCx, RTCPriorityTypeValues::strings[uint32_t(aArgument)].value,
      44           0 :                       RTCPriorityTypeValues::strings[uint32_t(aArgument)].length);
      45           0 :   if (!resultStr) {
      46           0 :     return false;
      47             :   }
      48           0 :   aValue.setString(resultStr);
      49           0 :   return true;
      50             : }
      51             : 
      52             : 
      53             : namespace RTCDegradationPreferenceValues {
      54             : extern const EnumEntry strings[4] = {
      55             :   {"maintain-framerate", 18},
      56             :   {"maintain-resolution", 19},
      57             :   {"balanced", 8},
      58             :   { nullptr, 0 }
      59             : };
      60             : } // namespace RTCDegradationPreferenceValues
      61             : 
      62             : bool
      63           0 : ToJSValue(JSContext* aCx, RTCDegradationPreference aArgument, JS::MutableHandle<JS::Value> aValue)
      64             : {
      65           0 :   MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(RTCDegradationPreferenceValues::strings));
      66             :   JSString* resultStr =
      67           0 :     JS_NewStringCopyN(aCx, RTCDegradationPreferenceValues::strings[uint32_t(aArgument)].value,
      68           0 :                       RTCDegradationPreferenceValues::strings[uint32_t(aArgument)].length);
      69           0 :   if (!resultStr) {
      70           0 :     return false;
      71             :   }
      72           0 :   aValue.setString(resultStr);
      73           0 :   return true;
      74             : }
      75             : 
      76             : 
      77             : 
      78           0 : RTCFecParameters::RTCFecParameters()
      79             : {
      80             :   // Safe to pass a null context if we pass a null value
      81           0 :   Init(nullptr, JS::NullHandleValue);
      82           0 : }
      83             : 
      84             : 
      85             : 
      86             : bool
      87           0 : RTCFecParameters::InitIds(JSContext* cx, RTCFecParametersAtoms* atomsCache)
      88             : {
      89           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
      90             : 
      91             :   // Initialize these in reverse order so that any failure leaves the first one
      92             :   // uninitialized.
      93           0 :   if (!atomsCache->ssrc_id.init(cx, "ssrc")) {
      94           0 :     return false;
      95             :   }
      96           0 :   return true;
      97             : }
      98             : 
      99             : bool
     100           0 : RTCFecParameters::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     101             : {
     102             :   // Passing a null JSContext is OK only if we're initing from null,
     103             :   // Since in that case we will not have to do any property gets
     104             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     105             :   // checkers by static analysis tools
     106           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     107           0 :   RTCFecParametersAtoms* atomsCache = nullptr;
     108           0 :   if (cx) {
     109           0 :     atomsCache = GetAtomCache<RTCFecParametersAtoms>(cx);
     110           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     111           0 :       return false;
     112             :     }
     113             :   }
     114             : 
     115           0 :   if (!IsConvertibleToDictionary(val)) {
     116           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     117             :   }
     118             : 
     119           0 :   bool isNull = val.isNullOrUndefined();
     120             :   // We only need these if !isNull, in which case we have |cx|.
     121           0 :   Maybe<JS::Rooted<JSObject *> > object;
     122           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     123           0 :   if (!isNull) {
     124           0 :     MOZ_ASSERT(cx);
     125           0 :     object.emplace(cx, &val.toObject());
     126           0 :     temp.emplace(cx);
     127             :   }
     128           0 :   if (!isNull) {
     129           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->ssrc_id, temp.ptr())) {
     130           0 :       return false;
     131             :     }
     132             :   }
     133           0 :   if (!isNull && !temp->isUndefined()) {
     134           0 :     mSsrc.Construct();
     135           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mSsrc.Value()))) {
     136           0 :       return false;
     137             :     }
     138           0 :     mIsAnyMemberPresent = true;
     139             :   }
     140           0 :   return true;
     141             : }
     142             : 
     143             : bool
     144           0 : RTCFecParameters::Init(const nsAString& aJSON)
     145             : {
     146           0 :   AutoJSAPI jsapi;
     147           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     148           0 :   if (!cleanGlobal) {
     149           0 :     return false;
     150             :   }
     151           0 :   if (!jsapi.Init(cleanGlobal)) {
     152           0 :     return false;
     153             :   }
     154           0 :   JSContext* cx = jsapi.cx();
     155           0 :   JS::Rooted<JS::Value> json(cx);
     156           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     157           0 :   NS_ENSURE_TRUE(ok, false);
     158           0 :   return Init(cx, json);
     159             : }
     160             : 
     161             : bool
     162           0 : RTCFecParameters::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     163             : {
     164           0 :   RTCFecParametersAtoms* atomsCache = GetAtomCache<RTCFecParametersAtoms>(cx);
     165           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     166           0 :     return false;
     167             :   }
     168             : 
     169           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     170           0 :   if (!obj) {
     171           0 :     return false;
     172             :   }
     173           0 :   rval.set(JS::ObjectValue(*obj));
     174             : 
     175           0 :   if (mSsrc.WasPassed()) {
     176             :     do {
     177             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     178           0 :       JS::Rooted<JS::Value> temp(cx);
     179           0 :       uint32_t const & currentValue = mSsrc.InternalValue();
     180           0 :       temp.setNumber(currentValue);
     181           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->ssrc_id, temp, JSPROP_ENUMERATE)) {
     182           0 :         return false;
     183             :       }
     184           0 :       break;
     185             :     } while(0);
     186             :   }
     187             : 
     188           0 :   return true;
     189             : }
     190             : 
     191             : bool
     192           0 : RTCFecParameters::ToJSON(nsAString& aJSON) const
     193             : {
     194           0 :   AutoJSAPI jsapi;
     195           0 :   jsapi.Init();
     196           0 :   JSContext *cx = jsapi.cx();
     197             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     198             :   // because we'll only be creating objects, in ways that have no
     199             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     200             :   // which likewise guarantees no side-effects for the sorts of
     201             :   // things we will pass it.
     202           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     203           0 :   JS::Rooted<JS::Value> val(cx);
     204           0 :   if (!ToObjectInternal(cx, &val)) {
     205           0 :     return false;
     206             :   }
     207           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     208           0 :   return StringifyToJSON(cx, obj, aJSON);
     209             : }
     210             : 
     211             : void
     212           0 : RTCFecParameters::TraceDictionary(JSTracer* trc)
     213             : {
     214           0 : }
     215             : 
     216             : RTCFecParameters&
     217           0 : RTCFecParameters::operator=(const RTCFecParameters& aOther)
     218             : {
     219           0 :   mSsrc.Reset();
     220           0 :   if (aOther.mSsrc.WasPassed()) {
     221           0 :     mSsrc.Construct(aOther.mSsrc.Value());
     222             :   }
     223           0 :   return *this;
     224             : }
     225             : 
     226             : namespace binding_detail {
     227             : } // namespace binding_detail
     228             : 
     229             : 
     230             : 
     231           0 : RTCRtcpParameters::RTCRtcpParameters()
     232             : {
     233             :   // Safe to pass a null context if we pass a null value
     234           0 :   Init(nullptr, JS::NullHandleValue);
     235           0 : }
     236             : 
     237             : 
     238             : 
     239             : bool
     240           0 : RTCRtcpParameters::InitIds(JSContext* cx, RTCRtcpParametersAtoms* atomsCache)
     241             : {
     242           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     243             : 
     244             :   // Initialize these in reverse order so that any failure leaves the first one
     245             :   // uninitialized.
     246           0 :   if (!atomsCache->reducedSize_id.init(cx, "reducedSize") ||
     247           0 :       !atomsCache->cname_id.init(cx, "cname")) {
     248           0 :     return false;
     249             :   }
     250           0 :   return true;
     251             : }
     252             : 
     253             : bool
     254           0 : RTCRtcpParameters::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     255             : {
     256             :   // Passing a null JSContext is OK only if we're initing from null,
     257             :   // Since in that case we will not have to do any property gets
     258             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     259             :   // checkers by static analysis tools
     260           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     261           0 :   RTCRtcpParametersAtoms* atomsCache = nullptr;
     262           0 :   if (cx) {
     263           0 :     atomsCache = GetAtomCache<RTCRtcpParametersAtoms>(cx);
     264           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     265           0 :       return false;
     266             :     }
     267             :   }
     268             : 
     269           0 :   if (!IsConvertibleToDictionary(val)) {
     270           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     271             :   }
     272             : 
     273           0 :   bool isNull = val.isNullOrUndefined();
     274             :   // We only need these if !isNull, in which case we have |cx|.
     275           0 :   Maybe<JS::Rooted<JSObject *> > object;
     276           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     277           0 :   if (!isNull) {
     278           0 :     MOZ_ASSERT(cx);
     279           0 :     object.emplace(cx, &val.toObject());
     280           0 :     temp.emplace(cx);
     281             :   }
     282           0 :   if (!isNull) {
     283           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->cname_id, temp.ptr())) {
     284           0 :       return false;
     285             :     }
     286             :   }
     287           0 :   if (!isNull && !temp->isUndefined()) {
     288           0 :     mCname.Construct();
     289           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mCname.Value()))) {
     290           0 :       return false;
     291             :     }
     292           0 :     mIsAnyMemberPresent = true;
     293             :   }
     294             : 
     295           0 :   if (!isNull) {
     296           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->reducedSize_id, temp.ptr())) {
     297           0 :       return false;
     298             :     }
     299             :   }
     300           0 :   if (!isNull && !temp->isUndefined()) {
     301           0 :     mReducedSize.Construct();
     302           0 :     if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mReducedSize.Value()))) {
     303           0 :       return false;
     304             :     }
     305           0 :     mIsAnyMemberPresent = true;
     306             :   }
     307           0 :   return true;
     308             : }
     309             : 
     310             : bool
     311           0 : RTCRtcpParameters::Init(const nsAString& aJSON)
     312             : {
     313           0 :   AutoJSAPI jsapi;
     314           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     315           0 :   if (!cleanGlobal) {
     316           0 :     return false;
     317             :   }
     318           0 :   if (!jsapi.Init(cleanGlobal)) {
     319           0 :     return false;
     320             :   }
     321           0 :   JSContext* cx = jsapi.cx();
     322           0 :   JS::Rooted<JS::Value> json(cx);
     323           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     324           0 :   NS_ENSURE_TRUE(ok, false);
     325           0 :   return Init(cx, json);
     326             : }
     327             : 
     328             : bool
     329           0 : RTCRtcpParameters::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     330             : {
     331           0 :   RTCRtcpParametersAtoms* atomsCache = GetAtomCache<RTCRtcpParametersAtoms>(cx);
     332           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     333           0 :     return false;
     334             :   }
     335             : 
     336           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     337           0 :   if (!obj) {
     338           0 :     return false;
     339             :   }
     340           0 :   rval.set(JS::ObjectValue(*obj));
     341             : 
     342           0 :   if (mCname.WasPassed()) {
     343             :     do {
     344             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     345           0 :       JS::Rooted<JS::Value> temp(cx);
     346           0 :       nsString const & currentValue = mCname.InternalValue();
     347           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     348           0 :         return false;
     349             :       }
     350           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->cname_id, temp, JSPROP_ENUMERATE)) {
     351           0 :         return false;
     352             :       }
     353           0 :       break;
     354             :     } while(0);
     355             :   }
     356             : 
     357           0 :   if (mReducedSize.WasPassed()) {
     358             :     do {
     359             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     360           0 :       JS::Rooted<JS::Value> temp(cx);
     361           0 :       bool const & currentValue = mReducedSize.InternalValue();
     362           0 :       temp.setBoolean(currentValue);
     363           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->reducedSize_id, temp, JSPROP_ENUMERATE)) {
     364           0 :         return false;
     365             :       }
     366           0 :       break;
     367             :     } while(0);
     368             :   }
     369             : 
     370           0 :   return true;
     371             : }
     372             : 
     373             : bool
     374           0 : RTCRtcpParameters::ToJSON(nsAString& aJSON) const
     375             : {
     376           0 :   AutoJSAPI jsapi;
     377           0 :   jsapi.Init();
     378           0 :   JSContext *cx = jsapi.cx();
     379             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     380             :   // because we'll only be creating objects, in ways that have no
     381             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     382             :   // which likewise guarantees no side-effects for the sorts of
     383             :   // things we will pass it.
     384           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     385           0 :   JS::Rooted<JS::Value> val(cx);
     386           0 :   if (!ToObjectInternal(cx, &val)) {
     387           0 :     return false;
     388             :   }
     389           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     390           0 :   return StringifyToJSON(cx, obj, aJSON);
     391             : }
     392             : 
     393             : void
     394           0 : RTCRtcpParameters::TraceDictionary(JSTracer* trc)
     395             : {
     396           0 : }
     397             : 
     398             : RTCRtcpParameters&
     399           0 : RTCRtcpParameters::operator=(const RTCRtcpParameters& aOther)
     400             : {
     401           0 :   mCname.Reset();
     402           0 :   if (aOther.mCname.WasPassed()) {
     403           0 :     mCname.Construct(aOther.mCname.Value());
     404             :   }
     405           0 :   mReducedSize.Reset();
     406           0 :   if (aOther.mReducedSize.WasPassed()) {
     407           0 :     mReducedSize.Construct(aOther.mReducedSize.Value());
     408             :   }
     409           0 :   return *this;
     410             : }
     411             : 
     412             : namespace binding_detail {
     413             : } // namespace binding_detail
     414             : 
     415             : 
     416             : 
     417           0 : RTCRtpCodecParameters::RTCRtpCodecParameters()
     418             : {
     419             :   // Safe to pass a null context if we pass a null value
     420           0 :   Init(nullptr, JS::NullHandleValue);
     421           0 : }
     422             : 
     423             : 
     424             : 
     425             : bool
     426           0 : RTCRtpCodecParameters::InitIds(JSContext* cx, RTCRtpCodecParametersAtoms* atomsCache)
     427             : {
     428           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     429             : 
     430             :   // Initialize these in reverse order so that any failure leaves the first one
     431             :   // uninitialized.
     432           0 :   if (!atomsCache->sdpFmtpLine_id.init(cx, "sdpFmtpLine") ||
     433           0 :       !atomsCache->payloadType_id.init(cx, "payloadType") ||
     434           0 :       !atomsCache->mimeType_id.init(cx, "mimeType") ||
     435           0 :       !atomsCache->clockRate_id.init(cx, "clockRate") ||
     436           0 :       !atomsCache->channels_id.init(cx, "channels")) {
     437           0 :     return false;
     438             :   }
     439           0 :   return true;
     440             : }
     441             : 
     442             : bool
     443           0 : RTCRtpCodecParameters::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     444             : {
     445             :   // Passing a null JSContext is OK only if we're initing from null,
     446             :   // Since in that case we will not have to do any property gets
     447             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     448             :   // checkers by static analysis tools
     449           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     450           0 :   RTCRtpCodecParametersAtoms* atomsCache = nullptr;
     451           0 :   if (cx) {
     452           0 :     atomsCache = GetAtomCache<RTCRtpCodecParametersAtoms>(cx);
     453           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     454           0 :       return false;
     455             :     }
     456             :   }
     457             : 
     458           0 :   if (!IsConvertibleToDictionary(val)) {
     459           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     460             :   }
     461             : 
     462           0 :   bool isNull = val.isNullOrUndefined();
     463             :   // We only need these if !isNull, in which case we have |cx|.
     464           0 :   Maybe<JS::Rooted<JSObject *> > object;
     465           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     466           0 :   if (!isNull) {
     467           0 :     MOZ_ASSERT(cx);
     468           0 :     object.emplace(cx, &val.toObject());
     469           0 :     temp.emplace(cx);
     470             :   }
     471           0 :   if (!isNull) {
     472           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->channels_id, temp.ptr())) {
     473           0 :       return false;
     474             :     }
     475             :   }
     476           0 :   if (!isNull && !temp->isUndefined()) {
     477           0 :     if (!ValueToPrimitive<uint16_t, eDefault>(cx, temp.ref(), &mChannels)) {
     478           0 :       return false;
     479             :     }
     480             :   } else {
     481           0 :     mChannels = 1;
     482             :   }
     483           0 :   mIsAnyMemberPresent = true;
     484             : 
     485           0 :   if (!isNull) {
     486           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->clockRate_id, temp.ptr())) {
     487           0 :       return false;
     488             :     }
     489             :   }
     490           0 :   if (!isNull && !temp->isUndefined()) {
     491           0 :     mClockRate.Construct();
     492           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mClockRate.Value()))) {
     493           0 :       return false;
     494             :     }
     495           0 :     mIsAnyMemberPresent = true;
     496             :   }
     497             : 
     498           0 :   if (!isNull) {
     499           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->mimeType_id, temp.ptr())) {
     500           0 :       return false;
     501             :     }
     502             :   }
     503           0 :   if (!isNull && !temp->isUndefined()) {
     504           0 :     mMimeType.Construct();
     505           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mMimeType.Value()))) {
     506           0 :       return false;
     507             :     }
     508           0 :     mIsAnyMemberPresent = true;
     509             :   }
     510             : 
     511           0 :   if (!isNull) {
     512           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->payloadType_id, temp.ptr())) {
     513           0 :       return false;
     514             :     }
     515             :   }
     516           0 :   if (!isNull && !temp->isUndefined()) {
     517           0 :     mPayloadType.Construct();
     518           0 :     if (!ValueToPrimitive<uint16_t, eDefault>(cx, temp.ref(), &(mPayloadType.Value()))) {
     519           0 :       return false;
     520             :     }
     521           0 :     mIsAnyMemberPresent = true;
     522             :   }
     523             : 
     524           0 :   if (!isNull) {
     525           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->sdpFmtpLine_id, temp.ptr())) {
     526           0 :       return false;
     527             :     }
     528             :   }
     529           0 :   if (!isNull && !temp->isUndefined()) {
     530           0 :     mSdpFmtpLine.Construct();
     531           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mSdpFmtpLine.Value()))) {
     532           0 :       return false;
     533             :     }
     534           0 :     mIsAnyMemberPresent = true;
     535             :   }
     536           0 :   return true;
     537             : }
     538             : 
     539             : bool
     540           0 : RTCRtpCodecParameters::Init(const nsAString& aJSON)
     541             : {
     542           0 :   AutoJSAPI jsapi;
     543           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     544           0 :   if (!cleanGlobal) {
     545           0 :     return false;
     546             :   }
     547           0 :   if (!jsapi.Init(cleanGlobal)) {
     548           0 :     return false;
     549             :   }
     550           0 :   JSContext* cx = jsapi.cx();
     551           0 :   JS::Rooted<JS::Value> json(cx);
     552           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     553           0 :   NS_ENSURE_TRUE(ok, false);
     554           0 :   return Init(cx, json);
     555             : }
     556             : 
     557             : bool
     558           0 : RTCRtpCodecParameters::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     559             : {
     560           0 :   RTCRtpCodecParametersAtoms* atomsCache = GetAtomCache<RTCRtpCodecParametersAtoms>(cx);
     561           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     562           0 :     return false;
     563             :   }
     564             : 
     565           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     566           0 :   if (!obj) {
     567           0 :     return false;
     568             :   }
     569           0 :   rval.set(JS::ObjectValue(*obj));
     570             : 
     571             :   do {
     572             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     573           0 :     JS::Rooted<JS::Value> temp(cx);
     574           0 :     uint16_t const & currentValue = mChannels;
     575           0 :     temp.setInt32(int32_t(currentValue));
     576           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->channels_id, temp, JSPROP_ENUMERATE)) {
     577           0 :       return false;
     578             :     }
     579           0 :     break;
     580             :   } while(0);
     581             : 
     582           0 :   if (mClockRate.WasPassed()) {
     583             :     do {
     584             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     585           0 :       JS::Rooted<JS::Value> temp(cx);
     586           0 :       uint32_t const & currentValue = mClockRate.InternalValue();
     587           0 :       temp.setNumber(currentValue);
     588           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->clockRate_id, temp, JSPROP_ENUMERATE)) {
     589           0 :         return false;
     590             :       }
     591           0 :       break;
     592             :     } while(0);
     593             :   }
     594             : 
     595           0 :   if (mMimeType.WasPassed()) {
     596             :     do {
     597             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     598           0 :       JS::Rooted<JS::Value> temp(cx);
     599           0 :       nsString const & currentValue = mMimeType.InternalValue();
     600           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     601           0 :         return false;
     602             :       }
     603           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->mimeType_id, temp, JSPROP_ENUMERATE)) {
     604           0 :         return false;
     605             :       }
     606           0 :       break;
     607             :     } while(0);
     608             :   }
     609             : 
     610           0 :   if (mPayloadType.WasPassed()) {
     611             :     do {
     612             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     613           0 :       JS::Rooted<JS::Value> temp(cx);
     614           0 :       uint16_t const & currentValue = mPayloadType.InternalValue();
     615           0 :       temp.setInt32(int32_t(currentValue));
     616           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->payloadType_id, temp, JSPROP_ENUMERATE)) {
     617           0 :         return false;
     618             :       }
     619           0 :       break;
     620             :     } while(0);
     621             :   }
     622             : 
     623           0 :   if (mSdpFmtpLine.WasPassed()) {
     624             :     do {
     625             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     626           0 :       JS::Rooted<JS::Value> temp(cx);
     627           0 :       nsString const & currentValue = mSdpFmtpLine.InternalValue();
     628           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     629           0 :         return false;
     630             :       }
     631           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->sdpFmtpLine_id, temp, JSPROP_ENUMERATE)) {
     632           0 :         return false;
     633             :       }
     634           0 :       break;
     635             :     } while(0);
     636             :   }
     637             : 
     638           0 :   return true;
     639             : }
     640             : 
     641             : bool
     642           0 : RTCRtpCodecParameters::ToJSON(nsAString& aJSON) const
     643             : {
     644           0 :   AutoJSAPI jsapi;
     645           0 :   jsapi.Init();
     646           0 :   JSContext *cx = jsapi.cx();
     647             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     648             :   // because we'll only be creating objects, in ways that have no
     649             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     650             :   // which likewise guarantees no side-effects for the sorts of
     651             :   // things we will pass it.
     652           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     653           0 :   JS::Rooted<JS::Value> val(cx);
     654           0 :   if (!ToObjectInternal(cx, &val)) {
     655           0 :     return false;
     656             :   }
     657           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     658           0 :   return StringifyToJSON(cx, obj, aJSON);
     659             : }
     660             : 
     661             : void
     662           0 : RTCRtpCodecParameters::TraceDictionary(JSTracer* trc)
     663             : {
     664           0 : }
     665             : 
     666             : RTCRtpCodecParameters&
     667           0 : RTCRtpCodecParameters::operator=(const RTCRtpCodecParameters& aOther)
     668             : {
     669           0 :   mChannels = aOther.mChannels;
     670           0 :   mClockRate.Reset();
     671           0 :   if (aOther.mClockRate.WasPassed()) {
     672           0 :     mClockRate.Construct(aOther.mClockRate.Value());
     673             :   }
     674           0 :   mMimeType.Reset();
     675           0 :   if (aOther.mMimeType.WasPassed()) {
     676           0 :     mMimeType.Construct(aOther.mMimeType.Value());
     677             :   }
     678           0 :   mPayloadType.Reset();
     679           0 :   if (aOther.mPayloadType.WasPassed()) {
     680           0 :     mPayloadType.Construct(aOther.mPayloadType.Value());
     681             :   }
     682           0 :   mSdpFmtpLine.Reset();
     683           0 :   if (aOther.mSdpFmtpLine.WasPassed()) {
     684           0 :     mSdpFmtpLine.Construct(aOther.mSdpFmtpLine.Value());
     685             :   }
     686           0 :   return *this;
     687             : }
     688             : 
     689             : namespace binding_detail {
     690             : } // namespace binding_detail
     691             : 
     692             : 
     693             : 
     694           0 : RTCRtpHeaderExtensionParameters::RTCRtpHeaderExtensionParameters()
     695             : {
     696             :   // Safe to pass a null context if we pass a null value
     697           0 :   Init(nullptr, JS::NullHandleValue);
     698           0 : }
     699             : 
     700             : 
     701             : 
     702             : bool
     703           0 : RTCRtpHeaderExtensionParameters::InitIds(JSContext* cx, RTCRtpHeaderExtensionParametersAtoms* atomsCache)
     704             : {
     705           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     706             : 
     707             :   // Initialize these in reverse order so that any failure leaves the first one
     708             :   // uninitialized.
     709           0 :   if (!atomsCache->uri_id.init(cx, "uri") ||
     710           0 :       !atomsCache->id_id.init(cx, "id") ||
     711           0 :       !atomsCache->encrypted_id.init(cx, "encrypted")) {
     712           0 :     return false;
     713             :   }
     714           0 :   return true;
     715             : }
     716             : 
     717             : bool
     718           0 : RTCRtpHeaderExtensionParameters::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     719             : {
     720             :   // Passing a null JSContext is OK only if we're initing from null,
     721             :   // Since in that case we will not have to do any property gets
     722             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     723             :   // checkers by static analysis tools
     724           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     725           0 :   RTCRtpHeaderExtensionParametersAtoms* atomsCache = nullptr;
     726           0 :   if (cx) {
     727           0 :     atomsCache = GetAtomCache<RTCRtpHeaderExtensionParametersAtoms>(cx);
     728           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     729           0 :       return false;
     730             :     }
     731             :   }
     732             : 
     733           0 :   if (!IsConvertibleToDictionary(val)) {
     734           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     735             :   }
     736             : 
     737           0 :   bool isNull = val.isNullOrUndefined();
     738             :   // We only need these if !isNull, in which case we have |cx|.
     739           0 :   Maybe<JS::Rooted<JSObject *> > object;
     740           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     741           0 :   if (!isNull) {
     742           0 :     MOZ_ASSERT(cx);
     743           0 :     object.emplace(cx, &val.toObject());
     744           0 :     temp.emplace(cx);
     745             :   }
     746           0 :   if (!isNull) {
     747           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->encrypted_id, temp.ptr())) {
     748           0 :       return false;
     749             :     }
     750             :   }
     751           0 :   if (!isNull && !temp->isUndefined()) {
     752           0 :     mEncrypted.Construct();
     753           0 :     if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mEncrypted.Value()))) {
     754           0 :       return false;
     755             :     }
     756           0 :     mIsAnyMemberPresent = true;
     757             :   }
     758             : 
     759           0 :   if (!isNull) {
     760           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->id_id, temp.ptr())) {
     761           0 :       return false;
     762             :     }
     763             :   }
     764           0 :   if (!isNull && !temp->isUndefined()) {
     765           0 :     mId.Construct();
     766           0 :     if (!ValueToPrimitive<uint16_t, eDefault>(cx, temp.ref(), &(mId.Value()))) {
     767           0 :       return false;
     768             :     }
     769           0 :     mIsAnyMemberPresent = true;
     770             :   }
     771             : 
     772           0 :   if (!isNull) {
     773           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->uri_id, temp.ptr())) {
     774           0 :       return false;
     775             :     }
     776             :   }
     777           0 :   if (!isNull && !temp->isUndefined()) {
     778           0 :     mUri.Construct();
     779           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mUri.Value()))) {
     780           0 :       return false;
     781             :     }
     782           0 :     mIsAnyMemberPresent = true;
     783             :   }
     784           0 :   return true;
     785             : }
     786             : 
     787             : bool
     788           0 : RTCRtpHeaderExtensionParameters::Init(const nsAString& aJSON)
     789             : {
     790           0 :   AutoJSAPI jsapi;
     791           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     792           0 :   if (!cleanGlobal) {
     793           0 :     return false;
     794             :   }
     795           0 :   if (!jsapi.Init(cleanGlobal)) {
     796           0 :     return false;
     797             :   }
     798           0 :   JSContext* cx = jsapi.cx();
     799           0 :   JS::Rooted<JS::Value> json(cx);
     800           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     801           0 :   NS_ENSURE_TRUE(ok, false);
     802           0 :   return Init(cx, json);
     803             : }
     804             : 
     805             : bool
     806           0 : RTCRtpHeaderExtensionParameters::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     807             : {
     808           0 :   RTCRtpHeaderExtensionParametersAtoms* atomsCache = GetAtomCache<RTCRtpHeaderExtensionParametersAtoms>(cx);
     809           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     810           0 :     return false;
     811             :   }
     812             : 
     813           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     814           0 :   if (!obj) {
     815           0 :     return false;
     816             :   }
     817           0 :   rval.set(JS::ObjectValue(*obj));
     818             : 
     819           0 :   if (mEncrypted.WasPassed()) {
     820             :     do {
     821             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     822           0 :       JS::Rooted<JS::Value> temp(cx);
     823           0 :       bool const & currentValue = mEncrypted.InternalValue();
     824           0 :       temp.setBoolean(currentValue);
     825           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->encrypted_id, temp, JSPROP_ENUMERATE)) {
     826           0 :         return false;
     827             :       }
     828           0 :       break;
     829             :     } while(0);
     830             :   }
     831             : 
     832           0 :   if (mId.WasPassed()) {
     833             :     do {
     834             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     835           0 :       JS::Rooted<JS::Value> temp(cx);
     836           0 :       uint16_t const & currentValue = mId.InternalValue();
     837           0 :       temp.setInt32(int32_t(currentValue));
     838           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->id_id, temp, JSPROP_ENUMERATE)) {
     839           0 :         return false;
     840             :       }
     841           0 :       break;
     842             :     } while(0);
     843             :   }
     844             : 
     845           0 :   if (mUri.WasPassed()) {
     846             :     do {
     847             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     848           0 :       JS::Rooted<JS::Value> temp(cx);
     849           0 :       nsString const & currentValue = mUri.InternalValue();
     850           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
     851           0 :         return false;
     852             :       }
     853           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->uri_id, temp, JSPROP_ENUMERATE)) {
     854           0 :         return false;
     855             :       }
     856           0 :       break;
     857             :     } while(0);
     858             :   }
     859             : 
     860           0 :   return true;
     861             : }
     862             : 
     863             : bool
     864           0 : RTCRtpHeaderExtensionParameters::ToJSON(nsAString& aJSON) const
     865             : {
     866           0 :   AutoJSAPI jsapi;
     867           0 :   jsapi.Init();
     868           0 :   JSContext *cx = jsapi.cx();
     869             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
     870             :   // because we'll only be creating objects, in ways that have no
     871             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
     872             :   // which likewise guarantees no side-effects for the sorts of
     873             :   // things we will pass it.
     874           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
     875           0 :   JS::Rooted<JS::Value> val(cx);
     876           0 :   if (!ToObjectInternal(cx, &val)) {
     877           0 :     return false;
     878             :   }
     879           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
     880           0 :   return StringifyToJSON(cx, obj, aJSON);
     881             : }
     882             : 
     883             : void
     884           0 : RTCRtpHeaderExtensionParameters::TraceDictionary(JSTracer* trc)
     885             : {
     886           0 : }
     887             : 
     888             : RTCRtpHeaderExtensionParameters&
     889           0 : RTCRtpHeaderExtensionParameters::operator=(const RTCRtpHeaderExtensionParameters& aOther)
     890             : {
     891           0 :   mEncrypted.Reset();
     892           0 :   if (aOther.mEncrypted.WasPassed()) {
     893           0 :     mEncrypted.Construct(aOther.mEncrypted.Value());
     894             :   }
     895           0 :   mId.Reset();
     896           0 :   if (aOther.mId.WasPassed()) {
     897           0 :     mId.Construct(aOther.mId.Value());
     898             :   }
     899           0 :   mUri.Reset();
     900           0 :   if (aOther.mUri.WasPassed()) {
     901           0 :     mUri.Construct(aOther.mUri.Value());
     902             :   }
     903           0 :   return *this;
     904             : }
     905             : 
     906             : namespace binding_detail {
     907             : } // namespace binding_detail
     908             : 
     909             : 
     910             : 
     911           0 : RTCRtxParameters::RTCRtxParameters()
     912             : {
     913             :   // Safe to pass a null context if we pass a null value
     914           0 :   Init(nullptr, JS::NullHandleValue);
     915           0 : }
     916             : 
     917             : 
     918             : 
     919             : bool
     920           0 : RTCRtxParameters::InitIds(JSContext* cx, RTCRtxParametersAtoms* atomsCache)
     921             : {
     922           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     923             : 
     924             :   // Initialize these in reverse order so that any failure leaves the first one
     925             :   // uninitialized.
     926           0 :   if (!atomsCache->ssrc_id.init(cx, "ssrc")) {
     927           0 :     return false;
     928             :   }
     929           0 :   return true;
     930             : }
     931             : 
     932             : bool
     933           0 : RTCRtxParameters::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     934             : {
     935             :   // Passing a null JSContext is OK only if we're initing from null,
     936             :   // Since in that case we will not have to do any property gets
     937             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     938             :   // checkers by static analysis tools
     939           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     940           0 :   RTCRtxParametersAtoms* atomsCache = nullptr;
     941           0 :   if (cx) {
     942           0 :     atomsCache = GetAtomCache<RTCRtxParametersAtoms>(cx);
     943           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     944           0 :       return false;
     945             :     }
     946             :   }
     947             : 
     948           0 :   if (!IsConvertibleToDictionary(val)) {
     949           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     950             :   }
     951             : 
     952           0 :   bool isNull = val.isNullOrUndefined();
     953             :   // We only need these if !isNull, in which case we have |cx|.
     954           0 :   Maybe<JS::Rooted<JSObject *> > object;
     955           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     956           0 :   if (!isNull) {
     957           0 :     MOZ_ASSERT(cx);
     958           0 :     object.emplace(cx, &val.toObject());
     959           0 :     temp.emplace(cx);
     960             :   }
     961           0 :   if (!isNull) {
     962           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->ssrc_id, temp.ptr())) {
     963           0 :       return false;
     964             :     }
     965             :   }
     966           0 :   if (!isNull && !temp->isUndefined()) {
     967           0 :     mSsrc.Construct();
     968           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mSsrc.Value()))) {
     969           0 :       return false;
     970             :     }
     971           0 :     mIsAnyMemberPresent = true;
     972             :   }
     973           0 :   return true;
     974             : }
     975             : 
     976             : bool
     977           0 : RTCRtxParameters::Init(const nsAString& aJSON)
     978             : {
     979           0 :   AutoJSAPI jsapi;
     980           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     981           0 :   if (!cleanGlobal) {
     982           0 :     return false;
     983             :   }
     984           0 :   if (!jsapi.Init(cleanGlobal)) {
     985           0 :     return false;
     986             :   }
     987           0 :   JSContext* cx = jsapi.cx();
     988           0 :   JS::Rooted<JS::Value> json(cx);
     989           0 :   bool ok = ParseJSON(cx, aJSON, &json);
     990           0 :   NS_ENSURE_TRUE(ok, false);
     991           0 :   return Init(cx, json);
     992             : }
     993             : 
     994             : bool
     995           0 : RTCRtxParameters::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     996             : {
     997           0 :   RTCRtxParametersAtoms* atomsCache = GetAtomCache<RTCRtxParametersAtoms>(cx);
     998           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     999           0 :     return false;
    1000             :   }
    1001             : 
    1002           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    1003           0 :   if (!obj) {
    1004           0 :     return false;
    1005             :   }
    1006           0 :   rval.set(JS::ObjectValue(*obj));
    1007             : 
    1008           0 :   if (mSsrc.WasPassed()) {
    1009             :     do {
    1010             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1011           0 :       JS::Rooted<JS::Value> temp(cx);
    1012           0 :       uint32_t const & currentValue = mSsrc.InternalValue();
    1013           0 :       temp.setNumber(currentValue);
    1014           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->ssrc_id, temp, JSPROP_ENUMERATE)) {
    1015           0 :         return false;
    1016             :       }
    1017           0 :       break;
    1018             :     } while(0);
    1019             :   }
    1020             : 
    1021           0 :   return true;
    1022             : }
    1023             : 
    1024             : bool
    1025           0 : RTCRtxParameters::ToJSON(nsAString& aJSON) const
    1026             : {
    1027           0 :   AutoJSAPI jsapi;
    1028           0 :   jsapi.Init();
    1029           0 :   JSContext *cx = jsapi.cx();
    1030             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    1031             :   // because we'll only be creating objects, in ways that have no
    1032             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    1033             :   // which likewise guarantees no side-effects for the sorts of
    1034             :   // things we will pass it.
    1035           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    1036           0 :   JS::Rooted<JS::Value> val(cx);
    1037           0 :   if (!ToObjectInternal(cx, &val)) {
    1038           0 :     return false;
    1039             :   }
    1040           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    1041           0 :   return StringifyToJSON(cx, obj, aJSON);
    1042             : }
    1043             : 
    1044             : void
    1045           0 : RTCRtxParameters::TraceDictionary(JSTracer* trc)
    1046             : {
    1047           0 : }
    1048             : 
    1049             : RTCRtxParameters&
    1050           0 : RTCRtxParameters::operator=(const RTCRtxParameters& aOther)
    1051             : {
    1052           0 :   mSsrc.Reset();
    1053           0 :   if (aOther.mSsrc.WasPassed()) {
    1054           0 :     mSsrc.Construct(aOther.mSsrc.Value());
    1055             :   }
    1056           0 :   return *this;
    1057             : }
    1058             : 
    1059             : namespace binding_detail {
    1060             : } // namespace binding_detail
    1061             : 
    1062             : 
    1063             : 
    1064           0 : RTCRtpEncodingParameters::RTCRtpEncodingParameters()
    1065           0 :   : mFec(FastDictionaryInitializer()),
    1066           0 :     mRtx(FastDictionaryInitializer())
    1067             : {
    1068             :   // Safe to pass a null context if we pass a null value
    1069           0 :   Init(nullptr, JS::NullHandleValue);
    1070           0 : }
    1071             : 
    1072             : 
    1073             : 
    1074             : bool
    1075           0 : RTCRtpEncodingParameters::InitIds(JSContext* cx, RTCRtpEncodingParametersAtoms* atomsCache)
    1076             : {
    1077           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1078             : 
    1079             :   // Initialize these in reverse order so that any failure leaves the first one
    1080             :   // uninitialized.
    1081           0 :   if (!atomsCache->ssrc_id.init(cx, "ssrc") ||
    1082           0 :       !atomsCache->scaleResolutionDownBy_id.init(cx, "scaleResolutionDownBy") ||
    1083           0 :       !atomsCache->rtx_id.init(cx, "rtx") ||
    1084           0 :       !atomsCache->rid_id.init(cx, "rid") ||
    1085           0 :       !atomsCache->priority_id.init(cx, "priority") ||
    1086           0 :       !atomsCache->maxBitrate_id.init(cx, "maxBitrate") ||
    1087           0 :       !atomsCache->fec_id.init(cx, "fec") ||
    1088           0 :       !atomsCache->degradationPreference_id.init(cx, "degradationPreference") ||
    1089           0 :       !atomsCache->active_id.init(cx, "active")) {
    1090           0 :     return false;
    1091             :   }
    1092           0 :   return true;
    1093             : }
    1094             : 
    1095             : bool
    1096           0 : RTCRtpEncodingParameters::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1097             : {
    1098             :   // Passing a null JSContext is OK only if we're initing from null,
    1099             :   // Since in that case we will not have to do any property gets
    1100             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1101             :   // checkers by static analysis tools
    1102           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1103           0 :   RTCRtpEncodingParametersAtoms* atomsCache = nullptr;
    1104           0 :   if (cx) {
    1105           0 :     atomsCache = GetAtomCache<RTCRtpEncodingParametersAtoms>(cx);
    1106           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1107           0 :       return false;
    1108             :     }
    1109             :   }
    1110             : 
    1111           0 :   if (!IsConvertibleToDictionary(val)) {
    1112           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    1113             :   }
    1114             : 
    1115           0 :   bool isNull = val.isNullOrUndefined();
    1116             :   // We only need these if !isNull, in which case we have |cx|.
    1117           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1118           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1119           0 :   if (!isNull) {
    1120           0 :     MOZ_ASSERT(cx);
    1121           0 :     object.emplace(cx, &val.toObject());
    1122           0 :     temp.emplace(cx);
    1123             :   }
    1124           0 :   if (!isNull) {
    1125           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->active_id, temp.ptr())) {
    1126           0 :       return false;
    1127             :     }
    1128             :   }
    1129           0 :   if (!isNull && !temp->isUndefined()) {
    1130           0 :     mActive.Construct();
    1131           0 :     if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mActive.Value()))) {
    1132           0 :       return false;
    1133             :     }
    1134           0 :     mIsAnyMemberPresent = true;
    1135             :   }
    1136             : 
    1137           0 :   if (!isNull) {
    1138           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->degradationPreference_id, temp.ptr())) {
    1139           0 :       return false;
    1140             :     }
    1141             :   }
    1142           0 :   if (!isNull && !temp->isUndefined()) {
    1143             :     {
    1144             :       int index;
    1145           0 :       if (!FindEnumStringIndex<true>(cx, temp.ref(), RTCDegradationPreferenceValues::strings, "RTCDegradationPreference", "'degradationPreference' member of RTCRtpEncodingParameters", &index)) {
    1146           0 :         return false;
    1147             :       }
    1148           0 :       MOZ_ASSERT(index >= 0);
    1149           0 :       mDegradationPreference = static_cast<RTCDegradationPreference>(index);
    1150             :     }
    1151             :   } else {
    1152           0 :     mDegradationPreference = RTCDegradationPreference::Balanced;
    1153             :   }
    1154           0 :   mIsAnyMemberPresent = true;
    1155             : 
    1156           0 :   if (!isNull) {
    1157           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->fec_id, temp.ptr())) {
    1158           0 :       return false;
    1159             :     }
    1160             :   }
    1161           0 :   if (!mFec.Init(cx, (!isNull && !temp->isUndefined()) ? temp.ref() : JS::NullHandleValue,  "'fec' member of RTCRtpEncodingParameters", passedToJSImpl)) {
    1162           0 :     return false;
    1163             :   }
    1164           0 :   mIsAnyMemberPresent = true;
    1165             : 
    1166           0 :   if (!isNull) {
    1167           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->maxBitrate_id, temp.ptr())) {
    1168           0 :       return false;
    1169             :     }
    1170             :   }
    1171           0 :   if (!isNull && !temp->isUndefined()) {
    1172           0 :     mMaxBitrate.Construct();
    1173           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mMaxBitrate.Value()))) {
    1174           0 :       return false;
    1175             :     }
    1176           0 :     mIsAnyMemberPresent = true;
    1177             :   }
    1178             : 
    1179           0 :   if (!isNull) {
    1180           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->priority_id, temp.ptr())) {
    1181           0 :       return false;
    1182             :     }
    1183             :   }
    1184           0 :   if (!isNull && !temp->isUndefined()) {
    1185           0 :     mPriority.Construct();
    1186             :     {
    1187             :       int index;
    1188           0 :       if (!FindEnumStringIndex<true>(cx, temp.ref(), RTCPriorityTypeValues::strings, "RTCPriorityType", "'priority' member of RTCRtpEncodingParameters", &index)) {
    1189           0 :         return false;
    1190             :       }
    1191           0 :       MOZ_ASSERT(index >= 0);
    1192           0 :       (mPriority.Value()) = static_cast<RTCPriorityType>(index);
    1193             :     }
    1194           0 :     mIsAnyMemberPresent = true;
    1195             :   }
    1196             : 
    1197           0 :   if (!isNull) {
    1198           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->rid_id, temp.ptr())) {
    1199           0 :       return false;
    1200             :     }
    1201             :   }
    1202           0 :   if (!isNull && !temp->isUndefined()) {
    1203           0 :     mRid.Construct();
    1204           0 :     if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mRid.Value()))) {
    1205           0 :       return false;
    1206             :     }
    1207           0 :     mIsAnyMemberPresent = true;
    1208             :   }
    1209             : 
    1210           0 :   if (!isNull) {
    1211           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->rtx_id, temp.ptr())) {
    1212           0 :       return false;
    1213             :     }
    1214             :   }
    1215           0 :   if (!mRtx.Init(cx, (!isNull && !temp->isUndefined()) ? temp.ref() : JS::NullHandleValue,  "'rtx' member of RTCRtpEncodingParameters", passedToJSImpl)) {
    1216           0 :     return false;
    1217             :   }
    1218           0 :   mIsAnyMemberPresent = true;
    1219             : 
    1220           0 :   if (!isNull) {
    1221           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->scaleResolutionDownBy_id, temp.ptr())) {
    1222           0 :       return false;
    1223             :     }
    1224             :   }
    1225           0 :   if (!isNull && !temp->isUndefined()) {
    1226           0 :     if (!ValueToPrimitive<float, eDefault>(cx, temp.ref(), &mScaleResolutionDownBy)) {
    1227           0 :       return false;
    1228           0 :     } else if (!mozilla::IsFinite(mScaleResolutionDownBy)) {
    1229           0 :       ThrowErrorMessage(cx, MSG_NOT_FINITE, "'scaleResolutionDownBy' member of RTCRtpEncodingParameters");
    1230           0 :       return false;
    1231             :     }
    1232             :   } else {
    1233           0 :     mScaleResolutionDownBy = 1.0F;
    1234             :   }
    1235           0 :   mIsAnyMemberPresent = true;
    1236             : 
    1237           0 :   if (!isNull) {
    1238           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->ssrc_id, temp.ptr())) {
    1239           0 :       return false;
    1240             :     }
    1241             :   }
    1242           0 :   if (!isNull && !temp->isUndefined()) {
    1243           0 :     mSsrc.Construct();
    1244           0 :     if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mSsrc.Value()))) {
    1245           0 :       return false;
    1246             :     }
    1247           0 :     mIsAnyMemberPresent = true;
    1248             :   }
    1249           0 :   return true;
    1250             : }
    1251             : 
    1252             : bool
    1253           0 : RTCRtpEncodingParameters::Init(const nsAString& aJSON)
    1254             : {
    1255           0 :   AutoJSAPI jsapi;
    1256           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    1257           0 :   if (!cleanGlobal) {
    1258           0 :     return false;
    1259             :   }
    1260           0 :   if (!jsapi.Init(cleanGlobal)) {
    1261           0 :     return false;
    1262             :   }
    1263           0 :   JSContext* cx = jsapi.cx();
    1264           0 :   JS::Rooted<JS::Value> json(cx);
    1265           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    1266           0 :   NS_ENSURE_TRUE(ok, false);
    1267           0 :   return Init(cx, json);
    1268             : }
    1269             : 
    1270             : bool
    1271           0 : RTCRtpEncodingParameters::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1272             : {
    1273           0 :   RTCRtpEncodingParametersAtoms* atomsCache = GetAtomCache<RTCRtpEncodingParametersAtoms>(cx);
    1274           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1275           0 :     return false;
    1276             :   }
    1277             : 
    1278           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    1279           0 :   if (!obj) {
    1280           0 :     return false;
    1281             :   }
    1282           0 :   rval.set(JS::ObjectValue(*obj));
    1283             : 
    1284           0 :   if (mActive.WasPassed()) {
    1285             :     do {
    1286             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1287           0 :       JS::Rooted<JS::Value> temp(cx);
    1288           0 :       bool const & currentValue = mActive.InternalValue();
    1289           0 :       temp.setBoolean(currentValue);
    1290           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->active_id, temp, JSPROP_ENUMERATE)) {
    1291           0 :         return false;
    1292             :       }
    1293           0 :       break;
    1294             :     } while(0);
    1295             :   }
    1296             : 
    1297             :   do {
    1298             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1299           0 :     JS::Rooted<JS::Value> temp(cx);
    1300           0 :     RTCDegradationPreference const & currentValue = mDegradationPreference;
    1301           0 :     if (!ToJSValue(cx, currentValue, &temp)) {
    1302           0 :       return false;
    1303             :     }
    1304           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->degradationPreference_id, temp, JSPROP_ENUMERATE)) {
    1305           0 :       return false;
    1306             :     }
    1307           0 :     break;
    1308             :   } while(0);
    1309             : 
    1310             :   do {
    1311             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1312           0 :     JS::Rooted<JS::Value> temp(cx);
    1313           0 :     RTCFecParameters const & currentValue = mFec;
    1314           0 :     if (!currentValue.ToObjectInternal(cx, &temp)) {
    1315           0 :       return false;
    1316             :     }
    1317           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->fec_id, temp, JSPROP_ENUMERATE)) {
    1318           0 :       return false;
    1319             :     }
    1320           0 :     break;
    1321             :   } while(0);
    1322             : 
    1323           0 :   if (mMaxBitrate.WasPassed()) {
    1324             :     do {
    1325             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1326           0 :       JS::Rooted<JS::Value> temp(cx);
    1327           0 :       uint32_t const & currentValue = mMaxBitrate.InternalValue();
    1328           0 :       temp.setNumber(currentValue);
    1329           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->maxBitrate_id, temp, JSPROP_ENUMERATE)) {
    1330           0 :         return false;
    1331             :       }
    1332           0 :       break;
    1333             :     } while(0);
    1334             :   }
    1335             : 
    1336           0 :   if (mPriority.WasPassed()) {
    1337             :     do {
    1338             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1339           0 :       JS::Rooted<JS::Value> temp(cx);
    1340           0 :       RTCPriorityType const & currentValue = mPriority.InternalValue();
    1341           0 :       if (!ToJSValue(cx, currentValue, &temp)) {
    1342           0 :         return false;
    1343             :       }
    1344           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->priority_id, temp, JSPROP_ENUMERATE)) {
    1345           0 :         return false;
    1346             :       }
    1347           0 :       break;
    1348             :     } while(0);
    1349             :   }
    1350             : 
    1351           0 :   if (mRid.WasPassed()) {
    1352             :     do {
    1353             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1354           0 :       JS::Rooted<JS::Value> temp(cx);
    1355           0 :       nsString const & currentValue = mRid.InternalValue();
    1356           0 :       if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
    1357           0 :         return false;
    1358             :       }
    1359           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->rid_id, temp, JSPROP_ENUMERATE)) {
    1360           0 :         return false;
    1361             :       }
    1362           0 :       break;
    1363             :     } while(0);
    1364             :   }
    1365             : 
    1366             :   do {
    1367             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1368           0 :     JS::Rooted<JS::Value> temp(cx);
    1369           0 :     RTCRtxParameters const & currentValue = mRtx;
    1370           0 :     if (!currentValue.ToObjectInternal(cx, &temp)) {
    1371           0 :       return false;
    1372             :     }
    1373           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->rtx_id, temp, JSPROP_ENUMERATE)) {
    1374           0 :       return false;
    1375             :     }
    1376           0 :     break;
    1377             :   } while(0);
    1378             : 
    1379             :   do {
    1380             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1381           0 :     JS::Rooted<JS::Value> temp(cx);
    1382           0 :     float const & currentValue = mScaleResolutionDownBy;
    1383           0 :     temp.set(JS_NumberValue(double(currentValue)));
    1384           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->scaleResolutionDownBy_id, temp, JSPROP_ENUMERATE)) {
    1385           0 :       return false;
    1386             :     }
    1387           0 :     break;
    1388             :   } while(0);
    1389             : 
    1390           0 :   if (mSsrc.WasPassed()) {
    1391             :     do {
    1392             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1393           0 :       JS::Rooted<JS::Value> temp(cx);
    1394           0 :       uint32_t const & currentValue = mSsrc.InternalValue();
    1395           0 :       temp.setNumber(currentValue);
    1396           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->ssrc_id, temp, JSPROP_ENUMERATE)) {
    1397           0 :         return false;
    1398             :       }
    1399           0 :       break;
    1400             :     } while(0);
    1401             :   }
    1402             : 
    1403           0 :   return true;
    1404             : }
    1405             : 
    1406             : bool
    1407           0 : RTCRtpEncodingParameters::ToJSON(nsAString& aJSON) const
    1408             : {
    1409           0 :   AutoJSAPI jsapi;
    1410           0 :   jsapi.Init();
    1411           0 :   JSContext *cx = jsapi.cx();
    1412             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    1413             :   // because we'll only be creating objects, in ways that have no
    1414             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    1415             :   // which likewise guarantees no side-effects for the sorts of
    1416             :   // things we will pass it.
    1417           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    1418           0 :   JS::Rooted<JS::Value> val(cx);
    1419           0 :   if (!ToObjectInternal(cx, &val)) {
    1420           0 :     return false;
    1421             :   }
    1422           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    1423           0 :   return StringifyToJSON(cx, obj, aJSON);
    1424             : }
    1425             : 
    1426             : void
    1427           0 : RTCRtpEncodingParameters::TraceDictionary(JSTracer* trc)
    1428             : {
    1429           0 : }
    1430             : 
    1431             : RTCRtpEncodingParameters&
    1432           0 : RTCRtpEncodingParameters::operator=(const RTCRtpEncodingParameters& aOther)
    1433             : {
    1434           0 :   mActive.Reset();
    1435           0 :   if (aOther.mActive.WasPassed()) {
    1436           0 :     mActive.Construct(aOther.mActive.Value());
    1437             :   }
    1438           0 :   mDegradationPreference = aOther.mDegradationPreference;
    1439           0 :   mFec = aOther.mFec;
    1440           0 :   mMaxBitrate.Reset();
    1441           0 :   if (aOther.mMaxBitrate.WasPassed()) {
    1442           0 :     mMaxBitrate.Construct(aOther.mMaxBitrate.Value());
    1443             :   }
    1444           0 :   mPriority.Reset();
    1445           0 :   if (aOther.mPriority.WasPassed()) {
    1446           0 :     mPriority.Construct(aOther.mPriority.Value());
    1447             :   }
    1448           0 :   mRid.Reset();
    1449           0 :   if (aOther.mRid.WasPassed()) {
    1450           0 :     mRid.Construct(aOther.mRid.Value());
    1451             :   }
    1452           0 :   mRtx = aOther.mRtx;
    1453           0 :   mScaleResolutionDownBy = aOther.mScaleResolutionDownBy;
    1454           0 :   mSsrc.Reset();
    1455           0 :   if (aOther.mSsrc.WasPassed()) {
    1456           0 :     mSsrc.Construct(aOther.mSsrc.Value());
    1457             :   }
    1458           0 :   return *this;
    1459             : }
    1460             : 
    1461             : namespace binding_detail {
    1462             : } // namespace binding_detail
    1463             : 
    1464             : 
    1465             : 
    1466           0 : RTCRtpParameters::RTCRtpParameters()
    1467           0 :   : mRtcp(FastDictionaryInitializer())
    1468             : {
    1469             :   // Safe to pass a null context if we pass a null value
    1470           0 :   Init(nullptr, JS::NullHandleValue);
    1471           0 : }
    1472             : 
    1473             : 
    1474             : 
    1475             : bool
    1476           0 : RTCRtpParameters::InitIds(JSContext* cx, RTCRtpParametersAtoms* atomsCache)
    1477             : {
    1478           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    1479             : 
    1480             :   // Initialize these in reverse order so that any failure leaves the first one
    1481             :   // uninitialized.
    1482           0 :   if (!atomsCache->rtcp_id.init(cx, "rtcp") ||
    1483           0 :       !atomsCache->headerExtensions_id.init(cx, "headerExtensions") ||
    1484           0 :       !atomsCache->encodings_id.init(cx, "encodings") ||
    1485           0 :       !atomsCache->codecs_id.init(cx, "codecs")) {
    1486           0 :     return false;
    1487             :   }
    1488           0 :   return true;
    1489             : }
    1490             : 
    1491             : bool
    1492           0 : RTCRtpParameters::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
    1493             : {
    1494             :   // Passing a null JSContext is OK only if we're initing from null,
    1495             :   // Since in that case we will not have to do any property gets
    1496             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
    1497             :   // checkers by static analysis tools
    1498           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
    1499           0 :   RTCRtpParametersAtoms* atomsCache = nullptr;
    1500           0 :   if (cx) {
    1501           0 :     atomsCache = GetAtomCache<RTCRtpParametersAtoms>(cx);
    1502           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1503           0 :       return false;
    1504             :     }
    1505             :   }
    1506             : 
    1507           0 :   if (!IsConvertibleToDictionary(val)) {
    1508           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
    1509             :   }
    1510             : 
    1511           0 :   bool isNull = val.isNullOrUndefined();
    1512             :   // We only need these if !isNull, in which case we have |cx|.
    1513           0 :   Maybe<JS::Rooted<JSObject *> > object;
    1514           0 :   Maybe<JS::Rooted<JS::Value> > temp;
    1515           0 :   if (!isNull) {
    1516           0 :     MOZ_ASSERT(cx);
    1517           0 :     object.emplace(cx, &val.toObject());
    1518           0 :     temp.emplace(cx);
    1519             :   }
    1520           0 :   if (!isNull) {
    1521           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->codecs_id, temp.ptr())) {
    1522           0 :       return false;
    1523             :     }
    1524             :   }
    1525           0 :   if (!isNull && !temp->isUndefined()) {
    1526           0 :     mCodecs.Construct();
    1527           0 :     if (temp.ref().isObject()) {
    1528           0 :       JS::ForOfIterator iter(cx);
    1529           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    1530           0 :         return false;
    1531             :       }
    1532           0 :       if (!iter.valueIsIterable()) {
    1533           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'codecs' member of RTCRtpParameters");
    1534           0 :         return false;
    1535             :       }
    1536           0 :       Sequence<RTCRtpCodecParameters> &arr = (mCodecs.Value());
    1537           0 :       JS::Rooted<JS::Value> temp(cx);
    1538             :       while (true) {
    1539             :         bool done;
    1540           0 :         if (!iter.next(&temp, &done)) {
    1541           0 :           return false;
    1542             :         }
    1543           0 :         if (done) {
    1544           0 :           break;
    1545             :         }
    1546           0 :         RTCRtpCodecParameters* slotPtr = arr.AppendElement(mozilla::fallible);
    1547           0 :         if (!slotPtr) {
    1548           0 :           JS_ReportOutOfMemory(cx);
    1549           0 :           return false;
    1550             :         }
    1551           0 :         RTCRtpCodecParameters& slot = *slotPtr;
    1552           0 :         if (!slot.Init(cx, temp,  "Element of 'codecs' member of RTCRtpParameters", passedToJSImpl)) {
    1553           0 :           return false;
    1554             :         }
    1555           0 :       }
    1556             :     } else {
    1557           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'codecs' member of RTCRtpParameters");
    1558           0 :       return false;
    1559             :     }
    1560           0 :     mIsAnyMemberPresent = true;
    1561             :   }
    1562             : 
    1563           0 :   if (!isNull) {
    1564           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->encodings_id, temp.ptr())) {
    1565           0 :       return false;
    1566             :     }
    1567             :   }
    1568           0 :   if (!isNull && !temp->isUndefined()) {
    1569           0 :     mEncodings.Construct();
    1570           0 :     if (temp.ref().isObject()) {
    1571           0 :       JS::ForOfIterator iter(cx);
    1572           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    1573           0 :         return false;
    1574             :       }
    1575           0 :       if (!iter.valueIsIterable()) {
    1576           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'encodings' member of RTCRtpParameters");
    1577           0 :         return false;
    1578             :       }
    1579           0 :       Sequence<RTCRtpEncodingParameters> &arr = (mEncodings.Value());
    1580           0 :       JS::Rooted<JS::Value> temp(cx);
    1581             :       while (true) {
    1582             :         bool done;
    1583           0 :         if (!iter.next(&temp, &done)) {
    1584           0 :           return false;
    1585             :         }
    1586           0 :         if (done) {
    1587           0 :           break;
    1588             :         }
    1589           0 :         RTCRtpEncodingParameters* slotPtr = arr.AppendElement(mozilla::fallible);
    1590           0 :         if (!slotPtr) {
    1591           0 :           JS_ReportOutOfMemory(cx);
    1592           0 :           return false;
    1593             :         }
    1594           0 :         RTCRtpEncodingParameters& slot = *slotPtr;
    1595           0 :         if (!slot.Init(cx, temp,  "Element of 'encodings' member of RTCRtpParameters", passedToJSImpl)) {
    1596           0 :           return false;
    1597             :         }
    1598           0 :       }
    1599             :     } else {
    1600           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'encodings' member of RTCRtpParameters");
    1601           0 :       return false;
    1602             :     }
    1603           0 :     mIsAnyMemberPresent = true;
    1604             :   }
    1605             : 
    1606           0 :   if (!isNull) {
    1607           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->headerExtensions_id, temp.ptr())) {
    1608           0 :       return false;
    1609             :     }
    1610             :   }
    1611           0 :   if (!isNull && !temp->isUndefined()) {
    1612           0 :     mHeaderExtensions.Construct();
    1613           0 :     if (temp.ref().isObject()) {
    1614           0 :       JS::ForOfIterator iter(cx);
    1615           0 :       if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
    1616           0 :         return false;
    1617             :       }
    1618           0 :       if (!iter.valueIsIterable()) {
    1619           0 :         ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'headerExtensions' member of RTCRtpParameters");
    1620           0 :         return false;
    1621             :       }
    1622           0 :       Sequence<RTCRtpHeaderExtensionParameters> &arr = (mHeaderExtensions.Value());
    1623           0 :       JS::Rooted<JS::Value> temp(cx);
    1624             :       while (true) {
    1625             :         bool done;
    1626           0 :         if (!iter.next(&temp, &done)) {
    1627           0 :           return false;
    1628             :         }
    1629           0 :         if (done) {
    1630           0 :           break;
    1631             :         }
    1632           0 :         RTCRtpHeaderExtensionParameters* slotPtr = arr.AppendElement(mozilla::fallible);
    1633           0 :         if (!slotPtr) {
    1634           0 :           JS_ReportOutOfMemory(cx);
    1635           0 :           return false;
    1636             :         }
    1637           0 :         RTCRtpHeaderExtensionParameters& slot = *slotPtr;
    1638           0 :         if (!slot.Init(cx, temp,  "Element of 'headerExtensions' member of RTCRtpParameters", passedToJSImpl)) {
    1639           0 :           return false;
    1640             :         }
    1641           0 :       }
    1642             :     } else {
    1643           0 :       ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'headerExtensions' member of RTCRtpParameters");
    1644           0 :       return false;
    1645             :     }
    1646           0 :     mIsAnyMemberPresent = true;
    1647             :   }
    1648             : 
    1649           0 :   if (!isNull) {
    1650           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->rtcp_id, temp.ptr())) {
    1651           0 :       return false;
    1652             :     }
    1653             :   }
    1654           0 :   if (!mRtcp.Init(cx, (!isNull && !temp->isUndefined()) ? temp.ref() : JS::NullHandleValue,  "'rtcp' member of RTCRtpParameters", passedToJSImpl)) {
    1655           0 :     return false;
    1656             :   }
    1657           0 :   mIsAnyMemberPresent = true;
    1658           0 :   return true;
    1659             : }
    1660             : 
    1661             : bool
    1662           0 : RTCRtpParameters::Init(const nsAString& aJSON)
    1663             : {
    1664           0 :   AutoJSAPI jsapi;
    1665           0 :   JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
    1666           0 :   if (!cleanGlobal) {
    1667           0 :     return false;
    1668             :   }
    1669           0 :   if (!jsapi.Init(cleanGlobal)) {
    1670           0 :     return false;
    1671             :   }
    1672           0 :   JSContext* cx = jsapi.cx();
    1673           0 :   JS::Rooted<JS::Value> json(cx);
    1674           0 :   bool ok = ParseJSON(cx, aJSON, &json);
    1675           0 :   NS_ENSURE_TRUE(ok, false);
    1676           0 :   return Init(cx, json);
    1677             : }
    1678             : 
    1679             : bool
    1680           0 : RTCRtpParameters::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
    1681             : {
    1682           0 :   RTCRtpParametersAtoms* atomsCache = GetAtomCache<RTCRtpParametersAtoms>(cx);
    1683           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
    1684           0 :     return false;
    1685             :   }
    1686             : 
    1687           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
    1688           0 :   if (!obj) {
    1689           0 :     return false;
    1690             :   }
    1691           0 :   rval.set(JS::ObjectValue(*obj));
    1692             : 
    1693           0 :   if (mCodecs.WasPassed()) {
    1694             :     do {
    1695             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1696           0 :       JS::Rooted<JS::Value> temp(cx);
    1697           0 :       Sequence<RTCRtpCodecParameters> const & currentValue = mCodecs.InternalValue();
    1698             : 
    1699           0 :       uint32_t length = currentValue.Length();
    1700           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    1701           0 :       if (!returnArray) {
    1702           0 :         return false;
    1703             :       }
    1704             :       // Scope for 'tmp'
    1705             :       {
    1706           0 :         JS::Rooted<JS::Value> tmp(cx);
    1707           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    1708             :           // Control block to let us common up the JS_DefineElement calls when there
    1709             :           // are different ways to succeed at wrapping the object.
    1710             :           do {
    1711           0 :             if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
    1712           0 :               return false;
    1713             :             }
    1714           0 :             break;
    1715             :           } while (0);
    1716           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    1717             :                                 JSPROP_ENUMERATE)) {
    1718           0 :             return false;
    1719             :           }
    1720             :         }
    1721             :       }
    1722           0 :       temp.setObject(*returnArray);
    1723           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->codecs_id, temp, JSPROP_ENUMERATE)) {
    1724           0 :         return false;
    1725             :       }
    1726           0 :       break;
    1727             :     } while(0);
    1728             :   }
    1729             : 
    1730           0 :   if (mEncodings.WasPassed()) {
    1731             :     do {
    1732             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1733           0 :       JS::Rooted<JS::Value> temp(cx);
    1734           0 :       Sequence<RTCRtpEncodingParameters> const & currentValue = mEncodings.InternalValue();
    1735             : 
    1736           0 :       uint32_t length = currentValue.Length();
    1737           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    1738           0 :       if (!returnArray) {
    1739           0 :         return false;
    1740             :       }
    1741             :       // Scope for 'tmp'
    1742             :       {
    1743           0 :         JS::Rooted<JS::Value> tmp(cx);
    1744           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    1745             :           // Control block to let us common up the JS_DefineElement calls when there
    1746             :           // are different ways to succeed at wrapping the object.
    1747             :           do {
    1748           0 :             if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
    1749           0 :               return false;
    1750             :             }
    1751           0 :             break;
    1752             :           } while (0);
    1753           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    1754             :                                 JSPROP_ENUMERATE)) {
    1755           0 :             return false;
    1756             :           }
    1757             :         }
    1758             :       }
    1759           0 :       temp.setObject(*returnArray);
    1760           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->encodings_id, temp, JSPROP_ENUMERATE)) {
    1761           0 :         return false;
    1762             :       }
    1763           0 :       break;
    1764             :     } while(0);
    1765             :   }
    1766             : 
    1767           0 :   if (mHeaderExtensions.WasPassed()) {
    1768             :     do {
    1769             :       // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1770           0 :       JS::Rooted<JS::Value> temp(cx);
    1771           0 :       Sequence<RTCRtpHeaderExtensionParameters> const & currentValue = mHeaderExtensions.InternalValue();
    1772             : 
    1773           0 :       uint32_t length = currentValue.Length();
    1774           0 :       JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
    1775           0 :       if (!returnArray) {
    1776           0 :         return false;
    1777             :       }
    1778             :       // Scope for 'tmp'
    1779             :       {
    1780           0 :         JS::Rooted<JS::Value> tmp(cx);
    1781           0 :         for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
    1782             :           // Control block to let us common up the JS_DefineElement calls when there
    1783             :           // are different ways to succeed at wrapping the object.
    1784             :           do {
    1785           0 :             if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
    1786           0 :               return false;
    1787             :             }
    1788           0 :             break;
    1789             :           } while (0);
    1790           0 :           if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
    1791             :                                 JSPROP_ENUMERATE)) {
    1792           0 :             return false;
    1793             :           }
    1794             :         }
    1795             :       }
    1796           0 :       temp.setObject(*returnArray);
    1797           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->headerExtensions_id, temp, JSPROP_ENUMERATE)) {
    1798           0 :         return false;
    1799             :       }
    1800           0 :       break;
    1801             :     } while(0);
    1802             :   }
    1803             : 
    1804             :   do {
    1805             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
    1806           0 :     JS::Rooted<JS::Value> temp(cx);
    1807           0 :     RTCRtcpParameters const & currentValue = mRtcp;
    1808           0 :     if (!currentValue.ToObjectInternal(cx, &temp)) {
    1809           0 :       return false;
    1810             :     }
    1811           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->rtcp_id, temp, JSPROP_ENUMERATE)) {
    1812           0 :       return false;
    1813             :     }
    1814           0 :     break;
    1815             :   } while(0);
    1816             : 
    1817           0 :   return true;
    1818             : }
    1819             : 
    1820             : bool
    1821           0 : RTCRtpParameters::ToJSON(nsAString& aJSON) const
    1822             : {
    1823           0 :   AutoJSAPI jsapi;
    1824           0 :   jsapi.Init();
    1825           0 :   JSContext *cx = jsapi.cx();
    1826             :   // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
    1827             :   // because we'll only be creating objects, in ways that have no
    1828             :   // side-effects, followed by a call to JS::ToJSONMaybeSafely,
    1829             :   // which likewise guarantees no side-effects for the sorts of
    1830             :   // things we will pass it.
    1831           0 :   JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
    1832           0 :   JS::Rooted<JS::Value> val(cx);
    1833           0 :   if (!ToObjectInternal(cx, &val)) {
    1834           0 :     return false;
    1835             :   }
    1836           0 :   JS::Rooted<JSObject*> obj(cx, &val.toObject());
    1837           0 :   return StringifyToJSON(cx, obj, aJSON);
    1838             : }
    1839             : 
    1840             : void
    1841           0 : RTCRtpParameters::TraceDictionary(JSTracer* trc)
    1842             : {
    1843           0 : }
    1844             : 
    1845             : RTCRtpParameters&
    1846           0 : RTCRtpParameters::operator=(const RTCRtpParameters& aOther)
    1847             : {
    1848           0 :   mCodecs.Reset();
    1849           0 :   if (aOther.mCodecs.WasPassed()) {
    1850           0 :     mCodecs.Construct(aOther.mCodecs.Value());
    1851             :   }
    1852           0 :   mEncodings.Reset();
    1853           0 :   if (aOther.mEncodings.WasPassed()) {
    1854           0 :     mEncodings.Construct(aOther.mEncodings.Value());
    1855             :   }
    1856           0 :   mHeaderExtensions.Reset();
    1857           0 :   if (aOther.mHeaderExtensions.WasPassed()) {
    1858           0 :     mHeaderExtensions.Construct(aOther.mHeaderExtensions.Value());
    1859             :   }
    1860           0 :   mRtcp = aOther.mRtcp;
    1861           0 :   return *this;
    1862             : }
    1863             : 
    1864             : namespace binding_detail {
    1865             : } // namespace binding_detail
    1866             : 
    1867             : 
    1868             : namespace RTCRtpSenderBinding {
    1869             : 
    1870             : static bool
    1871           0 : get_track(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCRtpSender* self, JSJitGetterCallArgs args)
    1872             : {
    1873           0 :   Maybe<JS::Rooted<JSObject*> > unwrappedObj;
    1874           0 :   bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
    1875           0 :   if (objIsXray) {
    1876           0 :     unwrappedObj.emplace(cx, obj);
    1877             :   }
    1878           0 :   if (objIsXray) {
    1879           0 :     unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
    1880           0 :     if (!unwrappedObj.ref()) {
    1881           0 :       return false;
    1882             :     }
    1883             :   }
    1884           0 :   binding_detail::FastErrorResult rv;
    1885           0 :   auto result(StrongOrRawPtr<mozilla::dom::MediaStreamTrack>(self->GetTrack(rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj))));
    1886           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    1887           0 :     return false;
    1888             :   }
    1889           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    1890           0 :   if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
    1891           0 :     MOZ_ASSERT(true || JS_IsExceptionPending(cx));
    1892           0 :     return false;
    1893             :   }
    1894           0 :   return true;
    1895             : }
    1896             : 
    1897             : static const JSJitInfo track_getterinfo = {
    1898             :   { (JSJitGetterOp)get_track },
    1899             :   { prototypes::id::RTCRtpSender },
    1900             :   { PrototypeTraits<prototypes::id::RTCRtpSender>::Depth },
    1901             :   JSJitInfo::Getter,
    1902             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    1903             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    1904             :   false,  /* isInfallible. False in setters. */
    1905             :   false,  /* isMovable.  Not relevant for setters. */
    1906             :   false, /* isEliminatable.  Not relevant for setters. */
    1907             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    1908             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    1909             :   false,  /* isTypedMethod.  Only relevant for methods. */
    1910             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    1911             : };
    1912             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    1913             : static_assert(0 < 1, "There is no slot for us");
    1914             : 
    1915             : static bool
    1916           0 : setParameters(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCRtpSender* self, const JSJitMethodCallArgs& args)
    1917             : {
    1918           0 :   Maybe<JS::Rooted<JSObject*> > unwrappedObj;
    1919           0 :   bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
    1920           0 :   if (objIsXray) {
    1921           0 :     unwrappedObj.emplace(cx, obj);
    1922             :   }
    1923           0 :   binding_detail::FastRTCRtpParameters arg0;
    1924           0 :   if (!arg0.Init(cx, (args.hasDefined(0)) ? args[0] : JS::NullHandleValue,  "Argument 1 of RTCRtpSender.setParameters", true)) {
    1925           0 :     return false;
    1926             :   }
    1927           0 :   if (objIsXray) {
    1928           0 :     unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
    1929           0 :     if (!unwrappedObj.ref()) {
    1930           0 :       return false;
    1931             :     }
    1932             :   }
    1933           0 :   binding_detail::FastErrorResult rv;
    1934           0 :   auto result(StrongOrRawPtr<Promise>(self->SetParameters(Constify(arg0), rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj))));
    1935           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    1936           0 :     return false;
    1937             :   }
    1938           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    1939           0 :   if (!ToJSValue(cx, result, args.rval())) {
    1940           0 :     return false;
    1941             :   }
    1942           0 :   return true;
    1943             : }
    1944             : 
    1945             : static bool
    1946           0 : setParameters_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCRtpSender* self, const JSJitMethodCallArgs& args)
    1947             : {
    1948             :   // Make sure to save the callee before someone maybe messes
    1949             :   // with rval().
    1950           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    1951           0 :   bool ok = setParameters(cx, obj, self, args);
    1952           0 :   if (ok) {
    1953           0 :     return true;
    1954             :   }
    1955           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    1956           0 :                                    args.rval());
    1957             : }
    1958             : 
    1959             : static const JSJitInfo setParameters_methodinfo = {
    1960             :   { (JSJitGetterOp)setParameters_promiseWrapper },
    1961             :   { prototypes::id::RTCRtpSender },
    1962             :   { PrototypeTraits<prototypes::id::RTCRtpSender>::Depth },
    1963             :   JSJitInfo::Method,
    1964             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    1965             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    1966             :   false,  /* isInfallible. False in setters. */
    1967             :   false,  /* isMovable.  Not relevant for setters. */
    1968             :   false, /* isEliminatable.  Not relevant for setters. */
    1969             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    1970             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    1971             :   false,  /* isTypedMethod.  Only relevant for methods. */
    1972             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    1973             : };
    1974             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    1975             : static_assert(0 < 1, "There is no slot for us");
    1976             : 
    1977             : static bool
    1978           0 : getParameters(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCRtpSender* self, const JSJitMethodCallArgs& args)
    1979             : {
    1980           0 :   Maybe<JS::Rooted<JSObject*> > unwrappedObj;
    1981           0 :   bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
    1982           0 :   if (objIsXray) {
    1983           0 :     unwrappedObj.emplace(cx, obj);
    1984             :   }
    1985           0 :   if (objIsXray) {
    1986           0 :     unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
    1987           0 :     if (!unwrappedObj.ref()) {
    1988           0 :       return false;
    1989             :     }
    1990             :   }
    1991           0 :   binding_detail::FastErrorResult rv;
    1992           0 :   RTCRtpParameters result;
    1993           0 :   self->GetParameters(result, rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj));
    1994           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    1995           0 :     return false;
    1996             :   }
    1997           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    1998           0 :   if (!result.ToObjectInternal(cx, args.rval())) {
    1999           0 :     return false;
    2000             :   }
    2001           0 :   return true;
    2002             : }
    2003             : 
    2004             : static const JSJitInfo getParameters_methodinfo = {
    2005             :   { (JSJitGetterOp)getParameters },
    2006             :   { prototypes::id::RTCRtpSender },
    2007             :   { PrototypeTraits<prototypes::id::RTCRtpSender>::Depth },
    2008             :   JSJitInfo::Method,
    2009             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    2010             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    2011             :   false,  /* isInfallible. False in setters. */
    2012             :   false,  /* isMovable.  Not relevant for setters. */
    2013             :   false, /* isEliminatable.  Not relevant for setters. */
    2014             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    2015             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    2016             :   false,  /* isTypedMethod.  Only relevant for methods. */
    2017             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    2018             : };
    2019             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    2020             : static_assert(0 < 1, "There is no slot for us");
    2021             : 
    2022             : static bool
    2023           0 : replaceTrack(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCRtpSender* self, const JSJitMethodCallArgs& args)
    2024             : {
    2025           0 :   if (MOZ_UNLIKELY(args.length() < 1)) {
    2026           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "RTCRtpSender.replaceTrack");
    2027             :   }
    2028           0 :   Maybe<JS::Rooted<JSObject*> > unwrappedObj;
    2029           0 :   bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
    2030           0 :   if (objIsXray) {
    2031           0 :     unwrappedObj.emplace(cx, obj);
    2032             :   }
    2033           0 :   NonNull<mozilla::dom::MediaStreamTrack> arg0;
    2034           0 :   if (args[0].isObject()) {
    2035             :     {
    2036           0 :       nsresult rv = UnwrapObject<prototypes::id::MediaStreamTrack, mozilla::dom::MediaStreamTrack>(args[0], arg0);
    2037           0 :       if (NS_FAILED(rv)) {
    2038           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 1 of RTCRtpSender.replaceTrack", "MediaStreamTrack");
    2039           0 :         return false;
    2040             :       }
    2041             :     }
    2042             :   } else {
    2043           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of RTCRtpSender.replaceTrack");
    2044           0 :     return false;
    2045             :   }
    2046           0 :   if (objIsXray) {
    2047           0 :     unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
    2048           0 :     if (!unwrappedObj.ref()) {
    2049           0 :       return false;
    2050             :     }
    2051             :   }
    2052           0 :   binding_detail::FastErrorResult rv;
    2053           0 :   auto result(StrongOrRawPtr<Promise>(self->ReplaceTrack(NonNullHelper(arg0), rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj))));
    2054           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    2055           0 :     return false;
    2056             :   }
    2057           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    2058           0 :   if (!ToJSValue(cx, result, args.rval())) {
    2059           0 :     return false;
    2060             :   }
    2061           0 :   return true;
    2062             : }
    2063             : 
    2064             : static bool
    2065           0 : replaceTrack_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCRtpSender* self, const JSJitMethodCallArgs& args)
    2066             : {
    2067             :   // Make sure to save the callee before someone maybe messes
    2068             :   // with rval().
    2069           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    2070           0 :   bool ok = replaceTrack(cx, obj, self, args);
    2071           0 :   if (ok) {
    2072           0 :     return true;
    2073             :   }
    2074           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    2075           0 :                                    args.rval());
    2076             : }
    2077             : 
    2078             : static const JSJitInfo replaceTrack_methodinfo = {
    2079             :   { (JSJitGetterOp)replaceTrack_promiseWrapper },
    2080             :   { prototypes::id::RTCRtpSender },
    2081             :   { PrototypeTraits<prototypes::id::RTCRtpSender>::Depth },
    2082             :   JSJitInfo::Method,
    2083             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    2084             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    2085             :   false,  /* isInfallible. False in setters. */
    2086             :   false,  /* isMovable.  Not relevant for setters. */
    2087             :   false, /* isEliminatable.  Not relevant for setters. */
    2088             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    2089             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    2090             :   false,  /* isTypedMethod.  Only relevant for methods. */
    2091             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    2092             : };
    2093             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    2094             : static_assert(0 < 1, "There is no slot for us");
    2095             : 
    2096             : static bool
    2097           0 : getStats(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCRtpSender* self, const JSJitMethodCallArgs& args)
    2098             : {
    2099           0 :   Maybe<JS::Rooted<JSObject*> > unwrappedObj;
    2100           0 :   bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
    2101           0 :   if (objIsXray) {
    2102           0 :     unwrappedObj.emplace(cx, obj);
    2103             :   }
    2104           0 :   if (objIsXray) {
    2105           0 :     unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
    2106           0 :     if (!unwrappedObj.ref()) {
    2107           0 :       return false;
    2108             :     }
    2109             :   }
    2110           0 :   binding_detail::FastErrorResult rv;
    2111           0 :   auto result(StrongOrRawPtr<Promise>(self->GetStats(rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj))));
    2112           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    2113           0 :     return false;
    2114             :   }
    2115           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    2116           0 :   if (!ToJSValue(cx, result, args.rval())) {
    2117           0 :     return false;
    2118             :   }
    2119           0 :   return true;
    2120             : }
    2121             : 
    2122             : static bool
    2123           0 : getStats_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCRtpSender* self, const JSJitMethodCallArgs& args)
    2124             : {
    2125             :   // Make sure to save the callee before someone maybe messes
    2126             :   // with rval().
    2127           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    2128           0 :   bool ok = getStats(cx, obj, self, args);
    2129           0 :   if (ok) {
    2130           0 :     return true;
    2131             :   }
    2132           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    2133           0 :                                    args.rval());
    2134             : }
    2135             : 
    2136             : static const JSJitInfo getStats_methodinfo = {
    2137             :   { (JSJitGetterOp)getStats_promiseWrapper },
    2138             :   { prototypes::id::RTCRtpSender },
    2139             :   { PrototypeTraits<prototypes::id::RTCRtpSender>::Depth },
    2140             :   JSJitInfo::Method,
    2141             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    2142             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    2143             :   false,  /* isInfallible. False in setters. */
    2144             :   false,  /* isMovable.  Not relevant for setters. */
    2145             :   false, /* isEliminatable.  Not relevant for setters. */
    2146             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    2147             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    2148             :   false,  /* isTypedMethod.  Only relevant for methods. */
    2149             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    2150             : };
    2151             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    2152             : static_assert(0 < 1, "There is no slot for us");
    2153             : 
    2154             : static bool
    2155           0 : get_dtmf(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::RTCRtpSender* self, JSJitGetterCallArgs args)
    2156             : {
    2157           0 :   Maybe<JS::Rooted<JSObject*> > unwrappedObj;
    2158           0 :   bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
    2159           0 :   if (objIsXray) {
    2160           0 :     unwrappedObj.emplace(cx, obj);
    2161             :   }
    2162           0 :   if (objIsXray) {
    2163           0 :     unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
    2164           0 :     if (!unwrappedObj.ref()) {
    2165           0 :       return false;
    2166             :     }
    2167             :   }
    2168           0 :   binding_detail::FastErrorResult rv;
    2169           0 :   auto result(StrongOrRawPtr<mozilla::dom::RTCDTMFSender>(self->GetDtmf(rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj))));
    2170           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    2171           0 :     return false;
    2172             :   }
    2173           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    2174           0 :   if (!result) {
    2175           0 :     args.rval().setNull();
    2176           0 :     return true;
    2177             :   }
    2178           0 :   if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
    2179           0 :     MOZ_ASSERT(true || JS_IsExceptionPending(cx));
    2180           0 :     return false;
    2181             :   }
    2182           0 :   return true;
    2183             : }
    2184             : 
    2185             : static const JSJitInfo dtmf_getterinfo = {
    2186             :   { (JSJitGetterOp)get_dtmf },
    2187             :   { prototypes::id::RTCRtpSender },
    2188             :   { PrototypeTraits<prototypes::id::RTCRtpSender>::Depth },
    2189             :   JSJitInfo::Getter,
    2190             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    2191             :   JSVAL_TYPE_UNKNOWN,  /* returnType.  Not relevant for setters. */
    2192             :   false,  /* isInfallible. False in setters. */
    2193             :   false,  /* isMovable.  Not relevant for setters. */
    2194             :   false, /* isEliminatable.  Not relevant for setters. */
    2195             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    2196             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    2197             :   false,  /* isTypedMethod.  Only relevant for methods. */
    2198             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    2199             : };
    2200             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    2201             : static_assert(0 < 1, "There is no slot for us");
    2202             : 
    2203             : static bool
    2204           0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
    2205             : {
    2206           0 :   mozilla::dom::RTCRtpSender* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::RTCRtpSender>(obj);
    2207             :   // We don't want to preserve if we don't have a wrapper, and we
    2208             :   // obviously can't preserve if we're not initialized.
    2209           0 :   if (self && self->GetWrapperPreserveColor()) {
    2210           0 :     PreserveWrapper(self);
    2211             :   }
    2212           0 :   return true;
    2213             : }
    2214             : 
    2215             : static void
    2216           0 : _finalize(js::FreeOp* fop, JSObject* obj)
    2217             : {
    2218           0 :   mozilla::dom::RTCRtpSender* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::RTCRtpSender>(obj);
    2219           0 :   if (self) {
    2220           0 :     ClearWrapper(self, self, obj);
    2221           0 :     AddForDeferredFinalization<mozilla::dom::RTCRtpSender>(self);
    2222             :   }
    2223           0 : }
    2224             : 
    2225             : static void
    2226           0 : _objectMoved(JSObject* obj, const JSObject* old)
    2227             : {
    2228           0 :   mozilla::dom::RTCRtpSender* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::RTCRtpSender>(obj);
    2229           0 :   if (self) {
    2230           0 :     UpdateWrapper(self, self, obj, old);
    2231             :   }
    2232           0 : }
    2233             : 
    2234             : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
    2235             : #if defined(__clang__)
    2236             : #pragma clang diagnostic push
    2237             : #pragma clang diagnostic ignored "-Wmissing-braces"
    2238             : #endif
    2239             : static const JSFunctionSpec sChromeStaticMethods_specs[] = {
    2240             :   JS_FNSPEC("_create", RTCRtpSender::_Create, nullptr, 2, 0, nullptr),
    2241             :   JS_FS_END
    2242             : };
    2243             : #if defined(__clang__)
    2244             : #pragma clang diagnostic pop
    2245             : #endif
    2246             : 
    2247             : 
    2248             : // Can't be const because the pref-enabled boolean needs to be writable
    2249             : static Prefable<const JSFunctionSpec> sChromeStaticMethods[] = {
    2250             :   { nullptr, &sChromeStaticMethods_specs[0] },
    2251             :   { nullptr, nullptr }
    2252             : };
    2253             : 
    2254             : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
    2255             :     "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
    2256             : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
    2257             :     "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
    2258             : 
    2259             : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
    2260             : #if defined(__clang__)
    2261             : #pragma clang diagnostic push
    2262             : #pragma clang diagnostic ignored "-Wmissing-braces"
    2263             : #endif
    2264             : static const JSFunctionSpec sMethods_specs[] = {
    2265             :   JS_FNSPEC("setParameters", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&setParameters_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
    2266             :   JS_FNSPEC("getParameters", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&getParameters_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
    2267             :   JS_FNSPEC("replaceTrack", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&replaceTrack_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
    2268             :   JS_FNSPEC("getStats", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&getStats_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
    2269             :   JS_FS_END
    2270             : };
    2271             : #if defined(__clang__)
    2272             : #pragma clang diagnostic pop
    2273             : #endif
    2274             : 
    2275             : 
    2276             : // Can't be const because the pref-enabled boolean needs to be writable
    2277             : static Prefable<const JSFunctionSpec> sMethods[] = {
    2278             :   { nullptr, &sMethods_specs[0] },
    2279             :   { nullptr, nullptr }
    2280             : };
    2281             : 
    2282             : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
    2283             :     "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
    2284             : static_assert(4 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
    2285             :     "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
    2286             : 
    2287             : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
    2288             : #if defined(__clang__)
    2289             : #pragma clang diagnostic push
    2290             : #pragma clang diagnostic ignored "-Wmissing-braces"
    2291             : #endif
    2292             : static const JSPropertySpec sAttributes_specs[] = {
    2293             :   { "track", JSPROP_SHARED | JSPROP_ENUMERATE, GenericBindingGetter, &track_getterinfo, nullptr, nullptr },
    2294             :   { nullptr, 0, nullptr, nullptr, nullptr, nullptr },
    2295             :   { "dtmf", JSPROP_SHARED | JSPROP_ENUMERATE, GenericBindingGetter, &dtmf_getterinfo, nullptr, nullptr },
    2296             :   { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
    2297             : };
    2298             : #if defined(__clang__)
    2299             : #pragma clang diagnostic pop
    2300             : #endif
    2301             : 
    2302             : static PrefableDisablers sAttributes_disablers2 = {
    2303             :   true, false, 0, nullptr
    2304             : };
    2305             : 
    2306             : // Can't be const because the pref-enabled boolean needs to be writable
    2307             : static Prefable<const JSPropertySpec> sAttributes[] = {
    2308             :   { nullptr, &sAttributes_specs[0] },
    2309             :   { &sAttributes_disablers2, &sAttributes_specs[2] },
    2310             :   { nullptr, nullptr }
    2311             : };
    2312             : 
    2313             : static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
    2314             :     "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
    2315             : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
    2316             :     "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
    2317             : 
    2318             : 
    2319             : static uint16_t sNativeProperties_sortedPropertyIndices[6];
    2320             : static PropertyInfo sNativeProperties_propertyInfos[6];
    2321             : 
    2322             : static const NativePropertiesN<2> sNativeProperties = {
    2323             :   false, 0,
    2324             :   false, 0,
    2325             :   true,  0 /* sMethods */,
    2326             :   true,  1 /* sAttributes */,
    2327             :   false, 0,
    2328             :   false, 0,
    2329             :   false, 0,
    2330             :   -1,
    2331             :   6,
    2332             :   sNativeProperties_sortedPropertyIndices,
    2333             :   {
    2334             :     { sMethods, &sNativeProperties_propertyInfos[0] },
    2335             :     { sAttributes, &sNativeProperties_propertyInfos[4] }
    2336             :   }
    2337             : };
    2338             : static_assert(6 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
    2339             :     "We have a property info count that is oversized");
    2340             : 
    2341             : static uint16_t sChromeOnlyNativeProperties_sortedPropertyIndices[1];
    2342             : static PropertyInfo sChromeOnlyNativeProperties_propertyInfos[1];
    2343             : 
    2344             : static const NativePropertiesN<1> sChromeOnlyNativeProperties = {
    2345             :   true,  0 /* sChromeStaticMethods */,
    2346             :   false, 0,
    2347             :   false, 0,
    2348             :   false, 0,
    2349             :   false, 0,
    2350             :   false, 0,
    2351             :   false, 0,
    2352             :   -1,
    2353             :   1,
    2354             :   sChromeOnlyNativeProperties_sortedPropertyIndices,
    2355             :   {
    2356             :     { sChromeStaticMethods, &sChromeOnlyNativeProperties_propertyInfos[0] }
    2357             :   }
    2358             : };
    2359             : static_assert(1 < 1ull << CHAR_BIT * sizeof(sChromeOnlyNativeProperties.propertyInfoCount),
    2360             :     "We have a property info count that is oversized");
    2361             : 
    2362             : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
    2363             :   {
    2364             :     "Function",
    2365             :     JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
    2366             :     &sBoringInterfaceObjectClassClassOps,
    2367             :     JS_NULL_CLASS_SPEC,
    2368             :     JS_NULL_CLASS_EXT,
    2369             :     &sInterfaceObjectClassObjectOps
    2370             :   },
    2371             :   eInterface,
    2372             :   true,
    2373             :   prototypes::id::RTCRtpSender,
    2374             :   PrototypeTraits<prototypes::id::RTCRtpSender>::Depth,
    2375             :   sNativePropertyHooks,
    2376             :   "function RTCRtpSender() {\n    [native code]\n}",
    2377             :   JS::GetRealmFunctionPrototype
    2378             : };
    2379             : 
    2380             : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
    2381             :   {
    2382             :     "RTCRtpSenderPrototype",
    2383             :     JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
    2384             :     JS_NULL_CLASS_OPS,
    2385             :     JS_NULL_CLASS_SPEC,
    2386             :     JS_NULL_CLASS_EXT,
    2387             :     JS_NULL_OBJECT_OPS
    2388             :   },
    2389             :   eInterfacePrototype,
    2390             :   false,
    2391             :   prototypes::id::RTCRtpSender,
    2392             :   PrototypeTraits<prototypes::id::RTCRtpSender>::Depth,
    2393             :   sNativePropertyHooks,
    2394             :   "[object RTCRtpSenderPrototype]",
    2395             :   JS::GetRealmObjectPrototype
    2396             : };
    2397             : 
    2398             : bool
    2399           0 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
    2400             : {
    2401             :   static bool sPrefValue;
    2402             :   static bool sPrefCacheSetUp = false;
    2403           0 :   if (!sPrefCacheSetUp) {
    2404           0 :     sPrefCacheSetUp = true;
    2405           0 :     Preferences::AddBoolVarCache(&sPrefValue, "media.peerconnection.enabled");
    2406             :   }
    2407             : 
    2408           0 :   return sPrefValue;
    2409             : }
    2410             : 
    2411             : JSObject*
    2412           0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
    2413             : {
    2414           0 :   return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
    2415             : }
    2416             : 
    2417             : static const js::ClassOps sClassOps = {
    2418             :   _addProperty, /* addProperty */
    2419             :   nullptr,               /* delProperty */
    2420             :   nullptr,               /* getProperty */
    2421             :   nullptr,               /* setProperty */
    2422             :   nullptr,               /* enumerate */
    2423             :   nullptr, /* newEnumerate */
    2424             :   nullptr, /* resolve */
    2425             :   nullptr, /* mayResolve */
    2426             :   _finalize, /* finalize */
    2427             :   nullptr, /* call */
    2428             :   nullptr,               /* hasInstance */
    2429             :   nullptr,               /* construct */
    2430             :   nullptr, /* trace */
    2431             : };
    2432             : 
    2433             : static const js::ClassExtension sClassExtension = {
    2434             :   nullptr, /* weakmapKeyDelegateOp */
    2435             :   _objectMoved /* objectMovedOp */
    2436             : };
    2437             : 
    2438             : static const DOMJSClass sClass = {
    2439             :   { "RTCRtpSender",
    2440             :     JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
    2441             :     &sClassOps,
    2442             :     JS_NULL_CLASS_SPEC,
    2443             :     &sClassExtension,
    2444             :     JS_NULL_OBJECT_OPS
    2445             :   },
    2446             :   { prototypes::id::RTCRtpSender, 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 },
    2447             :   IsBaseOf<nsISupports, mozilla::dom::RTCRtpSender >::value,
    2448             :   sNativePropertyHooks,
    2449             :   FindAssociatedGlobalForNative<mozilla::dom::RTCRtpSender>::Get,
    2450             :   GetProtoObjectHandle,
    2451             :   GetCCParticipant<mozilla::dom::RTCRtpSender>::Get()
    2452             : };
    2453             : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
    2454             :               "Must have the right minimal number of reserved slots.");
    2455             : static_assert(1 >= 1,
    2456             :               "Must have enough reserved slots.");
    2457             : 
    2458             : const JSClass*
    2459           0 : GetJSClass()
    2460             : {
    2461           0 :   return sClass.ToJSClass();
    2462             : }
    2463             : 
    2464             : bool
    2465           0 : Wrap(JSContext* aCx, mozilla::dom::RTCRtpSender* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
    2466             : {
    2467             :   MOZ_ASSERT(static_cast<mozilla::dom::RTCRtpSender*>(aObject) ==
    2468             :              reinterpret_cast<mozilla::dom::RTCRtpSender*>(aObject),
    2469             :              "Multiple inheritance for mozilla::dom::RTCRtpSender is broken.");
    2470           0 :   MOZ_ASSERT(ToSupportsIsCorrect(aObject));
    2471           0 :   MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
    2472           0 :   MOZ_ASSERT(!aCache->GetWrapper(),
    2473             :              "You should probably not be using Wrap() directly; use "
    2474             :              "GetOrCreateDOMReflector instead");
    2475             : 
    2476           0 :   MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
    2477             :              "nsISupports must be on our primary inheritance chain");
    2478             : 
    2479           0 :   JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
    2480           0 :   if (!global) {
    2481           0 :     return false;
    2482             :   }
    2483           0 :   MOZ_ASSERT(JS_IsGlobalObject(global));
    2484           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(global));
    2485             : 
    2486             :   // That might have ended up wrapping us already, due to the wonders
    2487             :   // of XBL.  Check for that, and bail out as needed.
    2488           0 :   aReflector.set(aCache->GetWrapper());
    2489           0 :   if (aReflector) {
    2490             : #ifdef DEBUG
    2491           0 :     binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
    2492             : #endif // DEBUG
    2493           0 :     return true;
    2494             :   }
    2495             : 
    2496           0 :   JSAutoCompartment ac(aCx, global);
    2497           0 :   JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
    2498           0 :   if (!canonicalProto) {
    2499           0 :     return false;
    2500             :   }
    2501           0 :   JS::Rooted<JSObject*> proto(aCx);
    2502           0 :   if (aGivenProto) {
    2503           0 :     proto = aGivenProto;
    2504             :     // Unfortunately, while aGivenProto was in the compartment of aCx
    2505             :     // coming in, we changed compartments to that of "parent" so may need
    2506             :     // to wrap the proto here.
    2507           0 :     if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
    2508           0 :       if (!JS_WrapObject(aCx, &proto)) {
    2509           0 :         return false;
    2510             :       }
    2511             :     }
    2512             :   } else {
    2513           0 :     proto = canonicalProto;
    2514             :   }
    2515             : 
    2516           0 :   BindingJSObjectCreator<mozilla::dom::RTCRtpSender> creator(aCx);
    2517           0 :   creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
    2518           0 :   if (!aReflector) {
    2519           0 :     return false;
    2520             :   }
    2521             : 
    2522           0 :   aCache->SetWrapper(aReflector);
    2523           0 :   creator.InitializationSucceeded();
    2524             : 
    2525           0 :   MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
    2526             :              aCache->GetWrapperPreserveColor() == aReflector);
    2527             :   // If proto != canonicalProto, we have to preserve our wrapper;
    2528             :   // otherwise we won't be able to properly recreate it later, since
    2529             :   // we won't know what proto to use.  Note that we don't check
    2530             :   // aGivenProto here, since it's entirely possible (and even
    2531             :   // somewhat common) to have a non-null aGivenProto which is the
    2532             :   // same as canonicalProto.
    2533           0 :   if (proto != canonicalProto) {
    2534           0 :     PreserveWrapper(aObject);
    2535             :   }
    2536             : 
    2537           0 :   return true;
    2538             : }
    2539             : 
    2540             : const NativePropertyHooks sNativePropertyHooks[] = { {
    2541             :   nullptr,
    2542             :   nullptr,
    2543             :   nullptr,
    2544             :   { sNativeProperties.Upcast(), sChromeOnlyNativeProperties.Upcast() },
    2545             :   prototypes::id::RTCRtpSender,
    2546             :   constructors::id::RTCRtpSender,
    2547             :   nullptr,
    2548             :   &DefaultXrayExpandoObjectClass
    2549             : } };
    2550             : 
    2551             : void
    2552           0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
    2553             : {
    2554           0 :   JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
    2555           0 :   if (!parentProto) {
    2556           0 :     return;
    2557             :   }
    2558             : 
    2559           0 :   JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
    2560           0 :   if (!constructorProto) {
    2561           0 :     return;
    2562             :   }
    2563             : 
    2564             :   static bool sIdsInited = false;
    2565           0 :   if (!sIdsInited && NS_IsMainThread()) {
    2566           0 :     if (!InitIds(aCx, sNativeProperties.Upcast())) {
    2567           0 :       return;
    2568             :     }
    2569           0 :     if (!InitIds(aCx, sChromeOnlyNativeProperties.Upcast())) {
    2570           0 :       return;
    2571             :     }
    2572           0 :     sIdsInited = true;
    2573             :   }
    2574             : 
    2575             :   static bool sPrefCachesInited = false;
    2576           0 :   if (!sPrefCachesInited && NS_IsMainThread()) {
    2577           0 :     sPrefCachesInited = true;
    2578           0 :     Preferences::AddBoolVarCache(&sAttributes[1].disablers->enabled, "media.peerconnection.dtmf.enabled");
    2579             :   }
    2580             : 
    2581           0 :   JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::RTCRtpSender);
    2582           0 :   JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::RTCRtpSender);
    2583           0 :   dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
    2584             :                               &sPrototypeClass.mBase, protoCache,
    2585             :                               constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
    2586             :                               interfaceCache,
    2587             :                               sNativeProperties.Upcast(),
    2588           0 :                               nsContentUtils::ThreadsafeIsSystemCaller(aCx) ? sChromeOnlyNativeProperties.Upcast() : nullptr,
    2589             :                               "RTCRtpSender", aDefineOnGlobal,
    2590             :                               nullptr,
    2591           0 :                               false);
    2592             : }
    2593             : 
    2594             : JS::Handle<JSObject*>
    2595           0 : GetProtoObjectHandle(JSContext* aCx)
    2596             : {
    2597             :   /* Get the interface prototype object for this class.  This will create the
    2598             :      object as needed. */
    2599           0 :   bool aDefineOnGlobal = true;
    2600             : 
    2601             :   /* Make sure our global is sane.  Hopefully we can remove this sometime */
    2602           0 :   JSObject* global = JS::CurrentGlobalOrNull(aCx);
    2603           0 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
    2604           0 :     return nullptr;
    2605             :   }
    2606             : 
    2607             :   /* Check to see whether the interface objects are already installed */
    2608           0 :   ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
    2609           0 :   if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::RTCRtpSender)) {
    2610           0 :     JS::Rooted<JSObject*> rootedGlobal(aCx, global);
    2611           0 :     CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
    2612             :   }
    2613             : 
    2614             :   /*
    2615             :    * The object might _still_ be null, but that's OK.
    2616             :    *
    2617             :    * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
    2618             :    * traced by TraceProtoAndIfaceCache() and its contents are never
    2619             :    * changed after they have been set.
    2620             :    *
    2621             :    * Calling address() avoids the read read barrier that does gray
    2622             :    * unmarking, but it's not possible for the object to be gray here.
    2623             :    */
    2624             : 
    2625           0 :   const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::RTCRtpSender);
    2626           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
    2627           0 :   return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
    2628             : }
    2629             : 
    2630             : JS::Handle<JSObject*>
    2631           0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
    2632             : {
    2633             :   /* Get the interface object for this class.  This will create the object as
    2634             :      needed. */
    2635             : 
    2636             :   /* Make sure our global is sane.  Hopefully we can remove this sometime */
    2637           0 :   JSObject* global = JS::CurrentGlobalOrNull(aCx);
    2638           0 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
    2639           0 :     return nullptr;
    2640             :   }
    2641             : 
    2642             :   /* Check to see whether the interface objects are already installed */
    2643           0 :   ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
    2644           0 :   if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::RTCRtpSender)) {
    2645           0 :     JS::Rooted<JSObject*> rootedGlobal(aCx, global);
    2646           0 :     CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
    2647             :   }
    2648             : 
    2649             :   /*
    2650             :    * The object might _still_ be null, but that's OK.
    2651             :    *
    2652             :    * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
    2653             :    * traced by TraceProtoAndIfaceCache() and its contents are never
    2654             :    * changed after they have been set.
    2655             :    *
    2656             :    * Calling address() avoids the read read barrier that does gray
    2657             :    * unmarking, but it's not possible for the object to be gray here.
    2658             :    */
    2659             : 
    2660           0 :   const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::RTCRtpSender);
    2661           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
    2662           0 :   return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
    2663             : }
    2664             : 
    2665             : JSObject*
    2666           0 : GetConstructorObject(JSContext* aCx)
    2667             : {
    2668           0 :   return GetConstructorObjectHandle(aCx);
    2669             : }
    2670             : 
    2671             : } // namespace RTCRtpSenderBinding
    2672             : 
    2673             : 
    2674             : 
    2675             : already_AddRefed<Promise>
    2676           0 : RTCRtpSenderJSImpl::SetParameters(const RTCRtpParameters& parameters, ErrorResult& aRv, JSCompartment* aCompartment)
    2677             : {
    2678           0 :   CallSetup s(this, aRv, "RTCRtpSender.setParameters", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
    2679           0 :   JSContext* cx = s.GetContext();
    2680           0 :   if (!cx) {
    2681           0 :     MOZ_ASSERT(aRv.Failed());
    2682           0 :     return nullptr;
    2683             :   }
    2684           0 :   JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    2685           0 :   JS::AutoValueVector argv(cx);
    2686           0 :   if (!argv.resize(1)) {
    2687           0 :     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    2688           0 :     return nullptr;
    2689             :   }
    2690           0 :   unsigned argc = 1;
    2691             : 
    2692             :   do {
    2693           0 :     if (!parameters.ToObjectInternal(cx, argv[0])) {
    2694           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2695           0 :       return nullptr;
    2696             :     }
    2697           0 :     break;
    2698             :   } while (0);
    2699             : 
    2700           0 :   JS::Rooted<JS::Value> callable(cx);
    2701           0 :   RTCRtpSenderAtoms* atomsCache = GetAtomCache<RTCRtpSenderAtoms>(cx);
    2702           0 :   if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
    2703           0 :       !GetCallableProperty(cx, atomsCache->setParameters_id, &callable)) {
    2704           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    2705           0 :     return nullptr;
    2706             :   }
    2707           0 :   JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
    2708           0 :   if (!JS::Call(cx, thisValue, callable,
    2709           0 :                 JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    2710           0 :     aRv.NoteJSContextException(cx);
    2711           0 :     return nullptr;
    2712             :   }
    2713           0 :   RefPtr<Promise> rvalDecl;
    2714             :   { // Scope for our GlobalObject, FastErrorResult, JSAutoCompartment,
    2715             :     // etc.
    2716             : 
    2717           0 :     JS::Rooted<JSObject*> globalObj(cx, JS::CurrentGlobalOrNull(cx));
    2718           0 :     if (!rval.isObject()) {
    2719           0 :       aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("return value of RTCRtpSender.setParameters"));
    2720           0 :       return nullptr;
    2721             :     }
    2722           0 :     JSObject* unwrappedVal = js::CheckedUnwrap(&rval.toObject());
    2723           0 :     if (!unwrappedVal) {
    2724             :       // A slight lie, but not much of one, for a dead object wrapper.
    2725           0 :       aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("return value of RTCRtpSender.setParameters"));
    2726           0 :       return nullptr;
    2727             :     }
    2728           0 :     globalObj = js::GetGlobalForObjectCrossCompartment(unwrappedVal);
    2729           0 :     JSAutoCompartment ac(cx, globalObj);
    2730           0 :     GlobalObject promiseGlobal(cx, globalObj);
    2731           0 :     if (promiseGlobal.Failed()) {
    2732           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2733           0 :       return nullptr;
    2734             :     }
    2735             : 
    2736           0 :     JS::Rooted<JS::Value> valueToResolve(cx, rval);
    2737           0 :     if (!JS_WrapValue(cx, &valueToResolve)) {
    2738           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2739           0 :       return nullptr;
    2740             :     }
    2741           0 :     binding_detail::FastErrorResult promiseRv;
    2742             :     nsCOMPtr<nsIGlobalObject> global =
    2743           0 :       do_QueryInterface(promiseGlobal.GetAsSupports());
    2744           0 :     if (!global) {
    2745           0 :       promiseRv.ThrowWithCustomCleanup(NS_ERROR_UNEXPECTED);
    2746           0 :       MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
    2747           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2748           0 :       return nullptr;
    2749             :     }
    2750           0 :     rvalDecl = Promise::Resolve(global, cx, valueToResolve,
    2751           0 :                                     promiseRv);
    2752           0 :     if (promiseRv.MaybeSetPendingException(cx)) {
    2753           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2754           0 :       return nullptr;
    2755             :     }
    2756             :   }
    2757           0 :   return rvalDecl.forget();
    2758             : }
    2759             : 
    2760             : void
    2761           0 : RTCRtpSenderJSImpl::GetParameters(RTCRtpParameters& aRetVal, ErrorResult& aRv, JSCompartment* aCompartment)
    2762             : {
    2763           0 :   CallSetup s(this, aRv, "RTCRtpSender.getParameters", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
    2764           0 :   JSContext* cx = s.GetContext();
    2765           0 :   if (!cx) {
    2766           0 :     MOZ_ASSERT(aRv.Failed());
    2767           0 :     return;
    2768             :   }
    2769           0 :   JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    2770             : 
    2771           0 :   JS::Rooted<JS::Value> callable(cx);
    2772           0 :   RTCRtpSenderAtoms* atomsCache = GetAtomCache<RTCRtpSenderAtoms>(cx);
    2773           0 :   if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
    2774           0 :       !GetCallableProperty(cx, atomsCache->getParameters_id, &callable)) {
    2775           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    2776           0 :     return;
    2777             :   }
    2778           0 :   JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
    2779           0 :   if (!JS::Call(cx, thisValue, callable,
    2780           0 :                 JS::HandleValueArray::empty(), &rval)) {
    2781           0 :     aRv.NoteJSContextException(cx);
    2782           0 :     return;
    2783             :   }
    2784           0 :   RTCRtpParameters& rvalDecl(aRetVal);
    2785           0 :   if (!rvalDecl.Init(cx, rval,  "Return value of RTCRtpSender.getParameters", false)) {
    2786           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    2787           0 :     return;
    2788             :   }
    2789             : }
    2790             : 
    2791             : already_AddRefed<Promise>
    2792           0 : RTCRtpSenderJSImpl::ReplaceTrack(MediaStreamTrack& track, ErrorResult& aRv, JSCompartment* aCompartment)
    2793             : {
    2794           0 :   CallSetup s(this, aRv, "RTCRtpSender.replaceTrack", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
    2795           0 :   JSContext* cx = s.GetContext();
    2796           0 :   if (!cx) {
    2797           0 :     MOZ_ASSERT(aRv.Failed());
    2798           0 :     return nullptr;
    2799             :   }
    2800           0 :   JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    2801           0 :   JS::AutoValueVector argv(cx);
    2802           0 :   if (!argv.resize(1)) {
    2803           0 :     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    2804           0 :     return nullptr;
    2805             :   }
    2806           0 :   unsigned argc = 1;
    2807             : 
    2808             :   do {
    2809           0 :     if (!GetOrCreateDOMReflector(cx, track, argv[0])) {
    2810           0 :       MOZ_ASSERT(true || JS_IsExceptionPending(cx));
    2811           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2812           0 :       return nullptr;
    2813             :     }
    2814           0 :     break;
    2815             :   } while (0);
    2816             : 
    2817           0 :   JS::Rooted<JS::Value> callable(cx);
    2818           0 :   RTCRtpSenderAtoms* atomsCache = GetAtomCache<RTCRtpSenderAtoms>(cx);
    2819           0 :   if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
    2820           0 :       !GetCallableProperty(cx, atomsCache->replaceTrack_id, &callable)) {
    2821           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    2822           0 :     return nullptr;
    2823             :   }
    2824           0 :   JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
    2825           0 :   if (!JS::Call(cx, thisValue, callable,
    2826           0 :                 JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    2827           0 :     aRv.NoteJSContextException(cx);
    2828           0 :     return nullptr;
    2829             :   }
    2830           0 :   RefPtr<Promise> rvalDecl;
    2831             :   { // Scope for our GlobalObject, FastErrorResult, JSAutoCompartment,
    2832             :     // etc.
    2833             : 
    2834           0 :     JS::Rooted<JSObject*> globalObj(cx, JS::CurrentGlobalOrNull(cx));
    2835           0 :     if (!rval.isObject()) {
    2836           0 :       aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("return value of RTCRtpSender.replaceTrack"));
    2837           0 :       return nullptr;
    2838             :     }
    2839           0 :     JSObject* unwrappedVal = js::CheckedUnwrap(&rval.toObject());
    2840           0 :     if (!unwrappedVal) {
    2841             :       // A slight lie, but not much of one, for a dead object wrapper.
    2842           0 :       aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("return value of RTCRtpSender.replaceTrack"));
    2843           0 :       return nullptr;
    2844             :     }
    2845           0 :     globalObj = js::GetGlobalForObjectCrossCompartment(unwrappedVal);
    2846           0 :     JSAutoCompartment ac(cx, globalObj);
    2847           0 :     GlobalObject promiseGlobal(cx, globalObj);
    2848           0 :     if (promiseGlobal.Failed()) {
    2849           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2850           0 :       return nullptr;
    2851             :     }
    2852             : 
    2853           0 :     JS::Rooted<JS::Value> valueToResolve(cx, rval);
    2854           0 :     if (!JS_WrapValue(cx, &valueToResolve)) {
    2855           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2856           0 :       return nullptr;
    2857             :     }
    2858           0 :     binding_detail::FastErrorResult promiseRv;
    2859             :     nsCOMPtr<nsIGlobalObject> global =
    2860           0 :       do_QueryInterface(promiseGlobal.GetAsSupports());
    2861           0 :     if (!global) {
    2862           0 :       promiseRv.ThrowWithCustomCleanup(NS_ERROR_UNEXPECTED);
    2863           0 :       MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
    2864           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2865           0 :       return nullptr;
    2866             :     }
    2867           0 :     rvalDecl = Promise::Resolve(global, cx, valueToResolve,
    2868           0 :                                     promiseRv);
    2869           0 :     if (promiseRv.MaybeSetPendingException(cx)) {
    2870           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2871           0 :       return nullptr;
    2872             :     }
    2873             :   }
    2874           0 :   return rvalDecl.forget();
    2875             : }
    2876             : 
    2877             : already_AddRefed<Promise>
    2878           0 : RTCRtpSenderJSImpl::GetStats(ErrorResult& aRv, JSCompartment* aCompartment)
    2879             : {
    2880           0 :   CallSetup s(this, aRv, "RTCRtpSender.getStats", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
    2881           0 :   JSContext* cx = s.GetContext();
    2882           0 :   if (!cx) {
    2883           0 :     MOZ_ASSERT(aRv.Failed());
    2884           0 :     return nullptr;
    2885             :   }
    2886           0 :   JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    2887             : 
    2888           0 :   JS::Rooted<JS::Value> callable(cx);
    2889           0 :   RTCRtpSenderAtoms* atomsCache = GetAtomCache<RTCRtpSenderAtoms>(cx);
    2890           0 :   if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
    2891           0 :       !GetCallableProperty(cx, atomsCache->getStats_id, &callable)) {
    2892           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    2893           0 :     return nullptr;
    2894             :   }
    2895           0 :   JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
    2896           0 :   if (!JS::Call(cx, thisValue, callable,
    2897           0 :                 JS::HandleValueArray::empty(), &rval)) {
    2898           0 :     aRv.NoteJSContextException(cx);
    2899           0 :     return nullptr;
    2900             :   }
    2901           0 :   RefPtr<Promise> rvalDecl;
    2902             :   { // Scope for our GlobalObject, FastErrorResult, JSAutoCompartment,
    2903             :     // etc.
    2904             : 
    2905           0 :     JS::Rooted<JSObject*> globalObj(cx, JS::CurrentGlobalOrNull(cx));
    2906           0 :     if (!rval.isObject()) {
    2907           0 :       aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("return value of RTCRtpSender.getStats"));
    2908           0 :       return nullptr;
    2909             :     }
    2910           0 :     JSObject* unwrappedVal = js::CheckedUnwrap(&rval.toObject());
    2911           0 :     if (!unwrappedVal) {
    2912             :       // A slight lie, but not much of one, for a dead object wrapper.
    2913           0 :       aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("return value of RTCRtpSender.getStats"));
    2914           0 :       return nullptr;
    2915             :     }
    2916           0 :     globalObj = js::GetGlobalForObjectCrossCompartment(unwrappedVal);
    2917           0 :     JSAutoCompartment ac(cx, globalObj);
    2918           0 :     GlobalObject promiseGlobal(cx, globalObj);
    2919           0 :     if (promiseGlobal.Failed()) {
    2920           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2921           0 :       return nullptr;
    2922             :     }
    2923             : 
    2924           0 :     JS::Rooted<JS::Value> valueToResolve(cx, rval);
    2925           0 :     if (!JS_WrapValue(cx, &valueToResolve)) {
    2926           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2927           0 :       return nullptr;
    2928             :     }
    2929           0 :     binding_detail::FastErrorResult promiseRv;
    2930             :     nsCOMPtr<nsIGlobalObject> global =
    2931           0 :       do_QueryInterface(promiseGlobal.GetAsSupports());
    2932           0 :     if (!global) {
    2933           0 :       promiseRv.ThrowWithCustomCleanup(NS_ERROR_UNEXPECTED);
    2934           0 :       MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
    2935           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2936           0 :       return nullptr;
    2937             :     }
    2938           0 :     rvalDecl = Promise::Resolve(global, cx, valueToResolve,
    2939           0 :                                     promiseRv);
    2940           0 :     if (promiseRv.MaybeSetPendingException(cx)) {
    2941           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    2942           0 :       return nullptr;
    2943             :     }
    2944             :   }
    2945           0 :   return rvalDecl.forget();
    2946             : }
    2947             : 
    2948             : bool
    2949           0 : RTCRtpSenderJSImpl::InitIds(JSContext* cx, RTCRtpSenderAtoms* atomsCache)
    2950             : {
    2951           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    2952             : 
    2953             :   // Initialize these in reverse order so that any failure leaves the first one
    2954             :   // uninitialized.
    2955           0 :   if (!atomsCache->dtmf_id.init(cx, "dtmf") ||
    2956           0 :       !atomsCache->getStats_id.init(cx, "getStats") ||
    2957           0 :       !atomsCache->replaceTrack_id.init(cx, "replaceTrack") ||
    2958           0 :       !atomsCache->getParameters_id.init(cx, "getParameters") ||
    2959           0 :       !atomsCache->setParameters_id.init(cx, "setParameters") ||
    2960           0 :       !atomsCache->track_id.init(cx, "track")) {
    2961           0 :     return false;
    2962             :   }
    2963           0 :   return true;
    2964             : }
    2965             : 
    2966             : 
    2967             : already_AddRefed<MediaStreamTrack>
    2968           0 : RTCRtpSenderJSImpl::GetTrack(ErrorResult& aRv, JSCompartment* aCompartment)
    2969             : {
    2970           0 :   CallSetup s(this, aRv, "RTCRtpSender.track", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
    2971           0 :   JSContext* cx = s.GetContext();
    2972           0 :   if (!cx) {
    2973           0 :     MOZ_ASSERT(aRv.Failed());
    2974           0 :     return nullptr;
    2975             :   }
    2976           0 :   JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    2977             : 
    2978           0 :   JS::Rooted<JSObject *> callback(cx, mCallback);
    2979           0 :   RTCRtpSenderAtoms* atomsCache = GetAtomCache<RTCRtpSenderAtoms>(cx);
    2980           0 :   if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
    2981           0 :       !JS_GetPropertyById(cx, callback, atomsCache->track_id, &rval)) {
    2982           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    2983           0 :     return nullptr;
    2984             :   }
    2985           0 :   RefPtr<mozilla::dom::MediaStreamTrack> rvalDecl;
    2986           0 :   if (rval.isObject()) {
    2987             :     static_assert(IsRefcounted<mozilla::dom::MediaStreamTrack>::value, "We can only store refcounted classes.");{
    2988           0 :       nsresult rv = UnwrapObject<prototypes::id::MediaStreamTrack, mozilla::dom::MediaStreamTrack>(rval, rvalDecl);
    2989           0 :       if (NS_FAILED(rv)) {
    2990           0 :         ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Return value of RTCRtpSender.track", "MediaStreamTrack");
    2991           0 :         aRv.Throw(NS_ERROR_UNEXPECTED);
    2992           0 :         return nullptr;
    2993             :       }
    2994             :     }
    2995             :   } else {
    2996           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Return value of RTCRtpSender.track");
    2997           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    2998           0 :     return nullptr;
    2999             :   }
    3000           0 :   return rvalDecl.forget();
    3001             : }
    3002             : 
    3003             : already_AddRefed<RTCDTMFSender>
    3004           0 : RTCRtpSenderJSImpl::GetDtmf(ErrorResult& aRv, JSCompartment* aCompartment)
    3005             : {
    3006           0 :   CallSetup s(this, aRv, "RTCRtpSender.dtmf", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
    3007           0 :   JSContext* cx = s.GetContext();
    3008           0 :   if (!cx) {
    3009           0 :     MOZ_ASSERT(aRv.Failed());
    3010           0 :     return nullptr;
    3011             :   }
    3012           0 :   JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    3013             : 
    3014           0 :   JS::Rooted<JSObject *> callback(cx, mCallback);
    3015           0 :   RTCRtpSenderAtoms* atomsCache = GetAtomCache<RTCRtpSenderAtoms>(cx);
    3016           0 :   if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
    3017           0 :       !JS_GetPropertyById(cx, callback, atomsCache->dtmf_id, &rval)) {
    3018           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    3019           0 :     return nullptr;
    3020             :   }
    3021           0 :   RefPtr<mozilla::dom::RTCDTMFSender> rvalDecl;
    3022           0 :   if (rval.isObject()) {
    3023             :     static_assert(IsRefcounted<mozilla::dom::RTCDTMFSender>::value, "We can only store refcounted classes.");{
    3024           0 :       nsresult rv = UnwrapObject<prototypes::id::RTCDTMFSender, mozilla::dom::RTCDTMFSender>(rval, rvalDecl);
    3025           0 :       if (NS_FAILED(rv)) {
    3026             :         // Be careful to not wrap random DOM objects here, even if
    3027             :         // they're wrapped in opaque security wrappers for some reason.
    3028             :         // XXXbz Wish we could check for a JS-implemented object
    3029             :         // that already has a content reflection...
    3030           0 :         if (!IsDOMObject(js::UncheckedUnwrap(&rval.toObject()))) {
    3031           0 :           nsCOMPtr<nsIGlobalObject> contentGlobal;
    3032           0 :           JS::Handle<JSObject*> callback = CallbackOrNull();
    3033           0 :           if (!callback ||
    3034           0 :               !GetContentGlobalForJSImplementedObject(cx, callback, getter_AddRefs(contentGlobal))) {
    3035           0 :             aRv.Throw(NS_ERROR_UNEXPECTED);
    3036           0 :             return nullptr;
    3037             :           }
    3038           0 :           JS::Rooted<JSObject*> jsImplSourceObj(cx, &rval.toObject());
    3039           0 :           rvalDecl = new mozilla::dom::RTCDTMFSender(jsImplSourceObj, contentGlobal);
    3040             :         } else {
    3041           0 :           ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Return value of RTCRtpSender.dtmf", "RTCDTMFSender");
    3042           0 :           aRv.Throw(NS_ERROR_UNEXPECTED);
    3043           0 :           return nullptr;
    3044             :         }
    3045             :       }
    3046             :     }
    3047           0 :   } else if (rval.isNullOrUndefined()) {
    3048           0 :     rvalDecl = nullptr;
    3049             :   } else {
    3050           0 :     ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Return value of RTCRtpSender.dtmf");
    3051           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    3052           0 :     return nullptr;
    3053             :   }
    3054           0 :   return rvalDecl.forget();
    3055             : }
    3056             : 
    3057             : 
    3058             : NS_IMPL_CYCLE_COLLECTION_CLASS(RTCRtpSender)
    3059           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(RTCRtpSender)
    3060           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mImpl)
    3061           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
    3062           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
    3063           0 :   tmp->ClearWeakReferences();
    3064           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    3065           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(RTCRtpSender)
    3066           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImpl)
    3067           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
    3068           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    3069           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(RTCRtpSender)
    3070           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(RTCRtpSender)
    3071           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(RTCRtpSender)
    3072           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RTCRtpSender)
    3073           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    3074           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    3075           0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
    3076           0 : NS_INTERFACE_MAP_END
    3077             : 
    3078           0 : RTCRtpSender::RTCRtpSender(JS::Handle<JSObject*> aJSImplObject, nsIGlobalObject* aParent)
    3079           0 :   : mImpl(new RTCRtpSenderJSImpl(nullptr, aJSImplObject, /* aIncumbentGlobal = */ nullptr)),
    3080           0 :     mParent(aParent)
    3081             : {
    3082           0 : }
    3083             : 
    3084             : 
    3085           0 : RTCRtpSender::~RTCRtpSender()
    3086             : {
    3087           0 : }
    3088             : 
    3089             : nsISupports*
    3090           0 : RTCRtpSender::GetParentObject() const
    3091             : {
    3092           0 :   return mParent;
    3093             : }
    3094             : 
    3095             : JSObject*
    3096           0 : RTCRtpSender::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
    3097             : {
    3098           0 :   JS::Rooted<JSObject*> obj(aCx, RTCRtpSenderBinding::Wrap(aCx, this, aGivenProto));
    3099           0 :   if (!obj) {
    3100           0 :     return nullptr;
    3101             :   }
    3102             : 
    3103             :   // Now define it on our chrome object
    3104           0 :   JSAutoCompartment ac(aCx, mImpl->CallbackOrNull());
    3105           0 :   if (!JS_WrapObject(aCx, &obj)) {
    3106           0 :     return nullptr;
    3107             :   }
    3108           0 :   if (!JS_DefineProperty(aCx, mImpl->CallbackOrNull(), "__DOM_IMPL__", obj, 0)) {
    3109           0 :     return nullptr;
    3110             :   }
    3111           0 :   return obj;
    3112             : }
    3113             : 
    3114             : // Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
    3115             : already_AddRefed<MediaStreamTrack>
    3116           0 : RTCRtpSender::GetTrack(ErrorResult& aRv, JSCompartment* aCompartment) const
    3117             : {
    3118           0 :   return mImpl->GetTrack(aRv, aCompartment);
    3119             : }
    3120             : 
    3121             : // Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
    3122             : already_AddRefed<Promise>
    3123           0 : RTCRtpSender::SetParameters(const RTCRtpParameters& parameters, ErrorResult& aRv, JSCompartment* aCompartment)
    3124             : {
    3125           0 :   return mImpl->SetParameters(parameters, aRv, aCompartment);
    3126             : }
    3127             : 
    3128             : void
    3129           0 : RTCRtpSender::GetParameters(RTCRtpParameters& aRetVal, ErrorResult& aRv, JSCompartment* aCompartment)
    3130             : {
    3131           0 :   return mImpl->GetParameters(aRetVal, aRv, aCompartment);
    3132             : }
    3133             : 
    3134             : // Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
    3135             : already_AddRefed<Promise>
    3136           0 : RTCRtpSender::ReplaceTrack(MediaStreamTrack& track, ErrorResult& aRv, JSCompartment* aCompartment)
    3137             : {
    3138           0 :   return mImpl->ReplaceTrack(track, aRv, aCompartment);
    3139             : }
    3140             : 
    3141             : // Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
    3142             : already_AddRefed<Promise>
    3143           0 : RTCRtpSender::GetStats(ErrorResult& aRv, JSCompartment* aCompartment)
    3144             : {
    3145           0 :   return mImpl->GetStats(aRv, aCompartment);
    3146             : }
    3147             : 
    3148             : // Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
    3149             : already_AddRefed<RTCDTMFSender>
    3150           0 : RTCRtpSender::GetDtmf(ErrorResult& aRv, JSCompartment* aCompartment) const
    3151             : {
    3152           0 :   return mImpl->GetDtmf(aRv, aCompartment);
    3153             : }
    3154             : 
    3155             : bool
    3156           0 : RTCRtpSender::_Create(JSContext* cx, unsigned argc, JS::Value* vp)
    3157             : {
    3158           0 :   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
    3159           0 :   if (args.length() < 2) {
    3160           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "RTCRtpSender._create");
    3161             :   }
    3162           0 :   if (!args[0].isObject()) {
    3163           0 :     return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of RTCRtpSender._create");
    3164             :   }
    3165           0 :   if (!args[1].isObject()) {
    3166           0 :     return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of RTCRtpSender._create");
    3167             :   }
    3168             : 
    3169             :   // GlobalObject will go through wrappers as needed for us, and
    3170             :   // is simpler than the right UnwrapArg incantation.
    3171           0 :   GlobalObject global(cx, &args[0].toObject());
    3172           0 :   if (global.Failed()) {
    3173           0 :     return false;
    3174             :   }
    3175           0 :   nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(global.GetAsSupports());
    3176           0 :   MOZ_ASSERT(globalHolder);
    3177           0 :   JS::Rooted<JSObject*> arg(cx, &args[1].toObject());
    3178           0 :   RefPtr<RTCRtpSender> impl = new RTCRtpSender(arg, globalHolder);
    3179           0 :   MOZ_ASSERT(js::IsObjectInContextCompartment(arg, cx));
    3180           0 :   return GetOrCreateDOMReflector(cx, impl, args.rval());
    3181             : }
    3182             : 
    3183             : 
    3184             : } // namespace dom
    3185             : } // namespace mozilla

Generated by: LCOV version 1.13