Bug 972385 - Make JS::AutoValueVector subscript operator return handles. r=jonco, smaug
authorMichael Shuen <mz_mhs-ctb@outlook.com>
Mon, 28 Apr 2014 16:53:00 +0200
changeset 181068 6ed9e9e160f2fbda7093441b5dfca5436b56ea72
parent 181067 7f902da7deba4eadccd38b632d1f3769dff91bca
child 181069 bae0d4946901aa614a90a7118d4d17b51120781d
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersjonco, smaug
bugs972385
milestone32.0a1
Bug 972385 - Make JS::AutoValueVector subscript operator return handles. r=jonco, smaug
content/base/src/nsObjectLoadingContent.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsJSEnvironment.cpp
dom/bindings/BindingUtils.h
dom/bindings/Codegen.py
dom/bindings/ToJSValue.h
dom/mobilemessage/src/MobileMessageManager.cpp
dom/mobilemessage/src/MobileMessageManager.h
js/ipc/JavaScriptChild.cpp
js/src/builtin/TypedObject.cpp
js/src/ctypes/CTypes.cpp
js/src/jit/AsmJSLink.cpp
js/src/jit/BaselineBailouts.cpp
js/src/jit/BaselineFrame.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsobj.cpp
js/src/jsproxy.cpp
js/src/jsscript.cpp
js/src/jswrapper.cpp
js/src/vm/Debugger.cpp
js/src/vm/OldDebugAPI.cpp
js/src/vm/ScopeObject.cpp
js/src/vm/Shape.cpp
js/src/vm/StructuredClone.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/wrappers/FilteringWrapper.cpp
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -3204,17 +3204,17 @@ nsObjectLoadingContent::LegacyCall(JSCon
   JSAutoCompartment ac(aCx, obj);
   JS::AutoValueVector args(aCx);
   if (!args.append(aArguments.Elements(), aArguments.Length())) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return JS::UndefinedValue();
   }
 
   for (size_t i = 0; i < args.length(); i++) {
-    if (!JS_WrapValue(aCx, args.handleAt(i))) {
+    if (!JS_WrapValue(aCx, args[i])) {
       aRv.Throw(NS_ERROR_UNEXPECTED);
       return JS::UndefinedValue();
     }
   }
 
   JS::Rooted<JS::Value> thisVal(aCx, aThisVal);
   if (!JS_WrapValue(aCx, &thisVal)) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1970,21 +1970,21 @@ BaseStubConstructor(nsIWeakReference* aW
         unsigned argc = args.length() + 1;
         JS::AutoValueVector argv(cx);
         if (!argv.resize(argc)) {
           return NS_ERROR_OUT_OF_MEMORY;
         }
 
         nsCOMPtr<nsIDOMWindow> currentWin(do_GetInterface(currentInner));
         rv = WrapNative(cx, currentWin, &NS_GET_IID(nsIDOMWindow),
-                        true, argv.handleAt(0));
+                        true, argv[0]);
 
         for (size_t i = 1; i < argc; ++i) {
-          argv[i] = args[i - 1];
-          if (!JS_WrapValue(cx, argv.handleAt(i)))
+          argv[i].set(args[i - 1]);
+          if (!JS_WrapValue(cx, argv[i]))
             return NS_ERROR_FAILURE;
         }
 
         JS::Rooted<JS::Value> frval(cx);
         bool ret = JS_CallFunctionValue(cx, thisObject, funval, argv, &frval);
 
         if (!ret) {
           return NS_ERROR_FAILURE;
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -997,17 +997,17 @@ nsJSContext::SetProperty(JS::Handle<JSOb
   JS::Rooted<JSObject*> global(mContext, GetWindowProxy());
   nsresult rv =
     ConvertSupportsTojsvals(aArgs, global, args);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // got the arguments, now attach them.
 
   for (uint32_t i = 0; i < args.length(); ++i) {
-    if (!JS_WrapValue(mContext, args.handleAt(i))) {
+    if (!JS_WrapValue(mContext, args[i])) {
       return NS_ERROR_FAILURE;
     }
   }
 
   JS::Rooted<JSObject*> array(mContext, ::JS_NewArrayObject(mContext, args));
   if (!array) {
     return NS_ERROR_FAILURE;
   }
@@ -1061,17 +1061,17 @@ nsJSContext::ConvertSupportsTojsvals(nsI
   // Use the caller's auto guards to release and unroot.
   if (!aArgsOut.resize(argCount)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   if (argsArray) {
     for (uint32_t argCtr = 0; argCtr < argCount && NS_SUCCEEDED(rv); argCtr++) {
       nsCOMPtr<nsISupports> arg;
-      JS::MutableHandle<JS::Value> thisVal = aArgsOut.handleAt(argCtr);
+      JS::MutableHandle<JS::Value> thisVal = aArgsOut[argCtr];
       argsArray->QueryElementAt(argCtr, NS_GET_IID(nsISupports),
                                 getter_AddRefs(arg));
       if (!arg) {
         thisVal.setNull();
         continue;
       }
       nsCOMPtr<nsIVariant> variant(do_QueryInterface(arg));
       if (variant != nullptr) {
@@ -1094,17 +1094,17 @@ nsJSContext::ConvertSupportsTojsvals(nsI
           JSAutoCompartment ac(cx, aScope);
           rv = nsContentUtils::WrapNative(cx, arg, thisVal);
         }
       }
     }
   } else {
     nsCOMPtr<nsIVariant> variant = do_QueryInterface(aArgs);
     if (variant) {
-      rv = xpc->VariantToJS(cx, aScope, variant, aArgsOut.handleAt(0));
+      rv = xpc->VariantToJS(cx, aScope, variant, aArgsOut[0]);
     } else {
       NS_ERROR("Not an array, not an interface?");
       rv = NS_ERROR_UNEXPECTED;
     }
   }
   return rv;
 }
 
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -2049,17 +2049,17 @@ IdEquals(jsid id, const char* string)
   return JSID_IS_STRING(id) &&
          JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(id), string);
 }
 
 inline bool
 AddStringToIDVector(JSContext* cx, JS::AutoIdVector& vector, const char* name)
 {
   return vector.growBy(1) &&
-         InternJSString(cx, vector[vector.length() - 1], name);
+         InternJSString(cx, *(vector[vector.length() - 1]).address(), name);
 }
 
 // Implementation of the bits that XrayWrapper needs
 
 /**
  * This resolves indexed or named properties of obj.
  *
  * wrapper is the Xray JS object.
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -12520,18 +12520,18 @@ class CallbackMember(CGNativeMember):
             prepend = ""
 
         try:
             conversion = prepend + wrapForType(
                 arg.type, self.descriptorProvider,
                 {
                     'result': result,
                     'successCode': "continue;\n" if arg.variadic else "break;\n",
-                    'jsvalRef': "argv.handleAt(%s)" % jsvalIndex,
-                    'jsvalHandle': "argv.handleAt(%s)" % jsvalIndex,
+                    'jsvalRef': "argv[%s]" % jsvalIndex,
+                    'jsvalHandle': "argv[%s]" % jsvalIndex,
                     # XXXbz we don't have anything better to use for 'obj',
                     # really...  It's OK to use CallbackPreserveColor because
                     # CallSetup already handled the unmark-gray bits for us.
                     'obj': 'CallbackPreserveColor()',
                     'returnsNewObject': False,
                     'exceptionCode': self.exceptionCode
                 })
         except MethodNotNewObjectError as err:
@@ -12553,17 +12553,17 @@ class CallbackMember(CGNativeMember):
             conversion = fill(
                 """
                 if (${argName}.WasPassed()) {
                   $*{conversion}
                 } else if (argc == ${iPlus1}) {
                   // This is our current trailing argument; reduce argc
                   --argc;
                 } else {
-                  argv[${i}] = JS::UndefinedValue();
+                  argv[${i}].setUndefined();
                 }
                 """,
                 argName=arg.identifier.name,
                 conversion=conversion,
                 iPlus1=i + 1,
                 i=i)
         return conversion
 
@@ -12811,17 +12811,17 @@ class CallbackSetter(CallbackAccessor):
     def getRvalDecl(self):
         # We don't need an rval
         return ""
 
     def getCall(self):
         return fill(
             """
             MOZ_ASSERT(argv.length() == 1);
-            if (!JS_SetProperty(cx, CallbackPreserveColor(), "${attrName}", argv.handleAt(0))) {
+            if (!JS_SetProperty(cx, CallbackPreserveColor(), "${attrName}", argv[0])) {
               aRv.Throw(NS_ERROR_UNEXPECTED);
               return${errorReturn};
             }
             """,
             attrName=self.descriptorProvider.binaryNames.get(self.attrName,
                                                              self.attrName),
             errorReturn=self.getDefaultRetval())
 
--- a/dom/bindings/ToJSValue.h
+++ b/dom/bindings/ToJSValue.h
@@ -239,17 +239,17 @@ ToJSValue(JSContext* aCx,
   // Make sure we're called in a compartment
   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
 
   JS::AutoValueVector v(aCx);
   if (!v.resize(aLength)) {
     return false;
   }
   for (size_t i = 0; i < aLength; ++i) {
-    if (!ToJSValue(aCx, aArguments[i], v.handleAt(i))) {
+    if (!ToJSValue(aCx, aArguments[i], v[i])) {
       return false;
     }
   }
   JSObject* arrayObj = JS_NewArrayObject(aCx, v);
   if (!arrayObj) {
     return false;
   }
   aValue.setObject(*arrayObj);
--- a/dom/mobilemessage/src/MobileMessageManager.cpp
+++ b/dom/mobilemessage/src/MobileMessageManager.cpp
@@ -126,17 +126,17 @@ MobileMessageManager::GetSegmentInfoForT
   return NS_OK;
 }
 
 nsresult
 MobileMessageManager::Send(JSContext* aCx, JS::Handle<JSObject*> aGlobal,
                            uint32_t aServiceId,
                            JS::Handle<JSString*> aNumber,
                            const nsAString& aMessage,
-                           JS::Value* aRequest)
+                           JS::MutableHandle<JS::Value> aRequest)
 {
   nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsService, NS_ERROR_FAILURE);
 
   nsDependentJSString number;
   number.init(aCx, aNumber);
 
   nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
@@ -144,26 +144,24 @@ MobileMessageManager::Send(JSContext* aC
     new MobileMessageCallback(request);
 
   // By default, we don't send silent messages via MobileMessageManager.
   nsresult rv = smsService->Send(aServiceId, number, aMessage,
                                  false, msgCallback);
   NS_ENSURE_SUCCESS(rv, rv);
 
   js::AssertSameCompartment(aCx, aGlobal);
-  JS::Rooted<JS::Value> rval(aCx);
   rv = nsContentUtils::WrapNative(aCx,
                                   static_cast<nsIDOMDOMRequest*>(request.get()),
-                                  &rval);
+                                  aRequest);
   if (NS_FAILED(rv)) {
     NS_ERROR("Failed to create the js value!");
     return rv;
   }
 
-  *aRequest = rval;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MobileMessageManager::Send(JS::Handle<JS::Value> aNumber,
                            const nsAString& aMessage,
                            JS::Handle<JS::Value> aSendParams,
                            JSContext* aCx,
@@ -203,17 +201,17 @@ MobileMessageManager::Send(JS::Handle<JS
     }
     if (sendParams.mServiceId.WasPassed()) {
       serviceId = sendParams.mServiceId.Value();
     }
   }
 
   if (aNumber.isString()) {
     JS::Rooted<JSString*> str(aCx, aNumber.toString());
-    return Send(aCx, global, serviceId, str, aMessage, aReturn.address());
+    return Send(aCx, global, serviceId, str, aMessage, aReturn);
   }
 
   // Must be an array then.
   JS::Rooted<JSObject*> numbers(aCx, &aNumber.toObject());
 
   uint32_t size;
   if (!JS_GetArrayLength(aCx, numbers, &size)) {
     return NS_ERROR_FAILURE;
@@ -231,17 +229,17 @@ MobileMessageManager::Send(JS::Handle<JS
       return NS_ERROR_INVALID_ARG;
     }
 
     str = JS::ToString(aCx, number);
     if (!str) {
       return NS_ERROR_FAILURE;
     }
 
-    nsresult rv = Send(aCx, global, serviceId, str, aMessage, &requests[i]);
+    nsresult rv = Send(aCx, global, serviceId, str, aMessage, requests[i]);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   JS::Rooted<JSObject*> obj(aCx);
   obj = JS_NewArrayObject(aCx, requests);
   if (!obj) {
     return NS_ERROR_FAILURE;
   }
--- a/dom/mobilemessage/src/MobileMessageManager.h
+++ b/dom/mobilemessage/src/MobileMessageManager.h
@@ -33,17 +33,17 @@ public:
 private:
   /**
    * Internal Send() method used to send one message.
    */
   nsresult Send(JSContext* aCx, JS::Handle<JSObject*> aGlobal,
                 uint32_t aServiceId,
                 JS::Handle<JSString*> aNumber,
                 const nsAString& aMessage,
-                JS::Value* aRequest);
+                JS::MutableHandle<JS::Value> aRequest);
 
   nsresult DispatchTrustedSmsEventToSelf(const char* aTopic,
                                          const nsAString& aEventName,
                                          nsISupports* aMsg);
 
   /**
    * Helper to get message ID from SMS/MMS Message object
    */
--- a/js/ipc/JavaScriptChild.cpp
+++ b/js/ipc/JavaScriptChild.cpp
@@ -496,17 +496,17 @@ JavaScriptChild::AnswerCall(const Object
     }
 
     RootedValue rval(cx);
     {
         AutoSaveContextOptions asco(cx);
         ContextOptionsRef(cx).setDontReportUncaught(true);
 
         HandleValueArray args = HandleValueArray::subarray(vals, 2, vals.length() - 2);
-        bool success = JS::Call(cx, vals.handleAt(1), vals.handleAt(0), args, &rval);
+        bool success = JS::Call(cx, vals[1], vals[0], args, &rval);
         if (!success)
             return fail(cx, rs);
     }
 
     if (!toVariant(cx, rval, result))
         return fail(cx, rs);
 
     // Prefill everything with a dummy jsval.
@@ -531,17 +531,17 @@ JavaScriptChild::AnswerCall(const Object
         if (!vals.append(v))
             return fail(cx, rs);
     }
 
     // Copy the outparams. If any outparam is already set to a void_t, we
     // treat this as the outparam never having been set.
     for (size_t i = 0; i < vals.length(); i++) {
         JSVariant variant;
-        if (!toVariant(cx, vals.handleAt(i), &variant))
+        if (!toVariant(cx, vals[i], &variant))
             return fail(cx, rs);
         outparams->ReplaceElementAt(i, JSParam(variant));
     }
 
     return ok(rs);
 }
 
 bool
@@ -591,17 +591,17 @@ JavaScriptChild::AnswerGetPropertyNames(
     JSAutoCompartment comp(cx, obj);
 
     AutoIdVector props(cx);
     if (!js::GetPropertyNames(cx, obj, flags, &props))
         return fail(cx, rs);
 
     for (size_t i = 0; i < props.length(); i++) {
         nsString name;
-        if (!convertIdToGeckoString(cx, props.handleAt(i), &name))
+        if (!convertIdToGeckoString(cx, props[i], &name))
             return fail(cx, rs);
 
         names->AppendElement(name);
     }
 
     return ok(rs);
 }
 
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -925,17 +925,17 @@ StructMetaTypeDescr::create(JSContext *c
         }
         if (!fieldTypeObjs.append(ObjectValue(*fieldType))) {
             js_ReportOutOfMemory(cx);
             return nullptr;
         }
 
         // userFieldTypes[id] = typeObj
         if (!JSObject::defineGeneric(cx, userFieldTypes, id,
-                                     fieldTypeObjs.handleAt(i), nullptr, nullptr,
+                                     fieldTypeObjs[i], nullptr, nullptr,
                                      JSPROP_READONLY | JSPROP_PERMANENT))
             return nullptr;
 
         // Append "f:Type" to the string repr
         if (i > 0 && !stringBuffer.append(", ")) {
             js_ReportOutOfMemory(cx);
             return nullptr;
         }
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -1158,58 +1158,58 @@ InitTypeClasses(JSContext* cx, HandleObj
   //     * [[Class]] "CDataProto"
   //     * __proto__ === 'p', the prototype object from above
   //     * 'constructor' property === 't'
   AutoObjectVector protos(cx);
   protos.resize(CTYPEPROTO_SLOTS);
   if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
          sPointerFunction, nullptr, sPointerProps,
          sPointerInstanceFunctions, sPointerInstanceProps,
-         protos.handleAt(SLOT_POINTERPROTO), protos.handleAt(SLOT_POINTERDATAPROTO)))
+         protos[SLOT_POINTERPROTO], protos[SLOT_POINTERDATAPROTO]))
     return false;
 
   if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
          sArrayFunction, nullptr, sArrayProps,
          sArrayInstanceFunctions, sArrayInstanceProps,
-         protos.handleAt(SLOT_ARRAYPROTO), protos.handleAt(SLOT_ARRAYDATAPROTO)))
+         protos[SLOT_ARRAYPROTO], protos[SLOT_ARRAYDATAPROTO]))
     return false;
 
   if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
          sStructFunction, sStructFunctions, sStructProps,
          sStructInstanceFunctions, nullptr,
-         protos.handleAt(SLOT_STRUCTPROTO), protos.handleAt(SLOT_STRUCTDATAPROTO)))
-    return false;
-
-  if (!InitTypeConstructor(cx, parent, CTypeProto, protos.handleAt(SLOT_POINTERDATAPROTO),
+         protos[SLOT_STRUCTPROTO], protos[SLOT_STRUCTDATAPROTO]))
+    return false;
+
+  if (!InitTypeConstructor(cx, parent, CTypeProto, protos[SLOT_POINTERDATAPROTO],
          sFunctionFunction, nullptr, sFunctionProps, sFunctionInstanceFunctions, nullptr,
-         protos.handleAt(SLOT_FUNCTIONPROTO), protos.handleAt(SLOT_FUNCTIONDATAPROTO)))
-    return false;
-
-  protos[SLOT_CDATAPROTO] = CDataProto;
+         protos[SLOT_FUNCTIONPROTO], protos[SLOT_FUNCTIONDATAPROTO]))
+    return false;
+
+  protos[SLOT_CDATAPROTO].set(CDataProto);
 
   // Create and attach the ctypes.{Int64,UInt64} constructors.
   // Each of these has, respectively:
   //   * [[Class]] "Function"
   //   * __proto__ === Function.prototype
   //   * A constructor that creates a ctypes.{Int64,UInt64} object, respectively.
   //   * 'prototype' property:
   //     * [[Class]] {"Int64Proto","UInt64Proto"}
   //     * 'constructor' property === ctypes.{Int64,UInt64}
-  protos[SLOT_INT64PROTO] = InitInt64Class(cx, parent, &sInt64ProtoClass,
-    Int64::Construct, sInt64Functions, sInt64StaticFunctions);
+  protos[SLOT_INT64PROTO].set(InitInt64Class(cx, parent, &sInt64ProtoClass,
+    Int64::Construct, sInt64Functions, sInt64StaticFunctions));
   if (!protos[SLOT_INT64PROTO])
     return false;
-  protos[SLOT_UINT64PROTO] = InitInt64Class(cx, parent, &sUInt64ProtoClass,
-    UInt64::Construct, sUInt64Functions, sUInt64StaticFunctions);
+  protos[SLOT_UINT64PROTO].set(InitInt64Class(cx, parent, &sUInt64ProtoClass,
+    UInt64::Construct, sUInt64Functions, sUInt64StaticFunctions));
   if (!protos[SLOT_UINT64PROTO])
     return false;
 
   // Finally, store a pointer to the global ctypes object.
   // Note that there is no other reliable manner of locating this object.
-  protos[SLOT_CTYPES] = parent;
+  protos[SLOT_CTYPES].set(parent);
 
   // Attach the prototypes just created to each of ctypes.CType.prototype,
   // and the special type constructors, so we can access them when constructing
   // instances of those types.
   AttachProtos(CTypeProto, protos);
   AttachProtos(protos[SLOT_POINTERPROTO], protos);
   AttachProtos(protos[SLOT_ARRAYPROTO], protos);
   AttachProtos(protos[SLOT_STRUCTPROTO], protos);
@@ -4822,17 +4822,17 @@ StructType::DefineInternal(JSContext* cx
       RootedValue item(cx);
       if (!JS_GetElement(cx, fieldsObj, i, &item))
         return false;
 
       RootedObject fieldType(cx, nullptr);
       Rooted<JSFlatString*> name(cx, ExtractStructField(cx, item, fieldType.address()));
       if (!name)
         return false;
-      fieldRoots[i] = JS::ObjectValue(*fieldType);
+      fieldRoots[i].setObject(*fieldType);
 
       // Make sure each field name is unique
       FieldInfoHash::AddPtr entryPtr = fields->lookupForAdd(name);
       if (entryPtr) {
         JS_ReportError(cx, "struct fields must have unique names");
         return false;
       }
 
@@ -5130,17 +5130,17 @@ StructType::BuildFieldsArray(JSContext* 
   // Prepare a new array for the 'fields' property of the StructType.
   JS::AutoValueVector fieldsVec(cx);
   if (!fieldsVec.resize(len))
     return nullptr;
 
   for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
     const FieldInfoHash::Entry& entry = r.front();
     // Add the field descriptor to the array.
-    if (!AddFieldToArray(cx, &fieldsVec[entry.value().mIndex],
+    if (!AddFieldToArray(cx, fieldsVec[entry.value().mIndex].address(),
                          entry.key(), entry.value().mType))
       return nullptr;
   }
 
   RootedObject fieldsProp(cx, JS_NewArrayObject(cx, fieldsVec));
   if (!fieldsProp)
     return nullptr;
 
@@ -5615,17 +5615,17 @@ FunctionType::Create(JSContext* cx, unsi
       JS_ReportOutOfMemory(cx);
       return false;
     }
   }
 
   // Pull out the argument types from the array, if any.
   JS_ASSERT_IF(argTypes.length(), arrayObj);
   for (uint32_t i = 0; i < argTypes.length(); ++i) {
-    if (!JS_GetElement(cx, arrayObj, i, argTypes.handleAt(i)))
+    if (!JS_GetElement(cx, arrayObj, i, argTypes[i]))
       return false;
   }
 
   JSObject* result = CreateInternal(cx, args[0], args[1],
       argTypes.begin(), argTypes.length());
   if (!result)
     return false;
 
@@ -5941,17 +5941,17 @@ FunctionType::ArgTypesGetter(JSContext* 
   // Prepare a new array.
   JS::Rooted<JSObject*> argTypes(cx);
   {
       JS::AutoValueVector vec(cx);
       if (!vec.resize(len))
         return false;
 
       for (size_t i = 0; i < len; ++i)
-        vec[i] = JS::ObjectValue(*fninfo->mArgTypes[i]);
+        vec[i].setObject(*fninfo->mArgTypes[i]);
 
       argTypes = JS_NewArrayObject(cx, vec);
       if (!argTypes)
         return false;
   }
 
   // Seal and cache it.
   if (!JS_FreezeObject(cx, argTypes))
@@ -6177,17 +6177,17 @@ CClosure::ClosureStub(ffi_cif* cif, void
     JS_ReportOutOfMemory(cx);
     return;
   }
 
   for (uint32_t i = 0; i < cif->nargs; ++i) {
     // Convert each argument, and have any CData objects created depend on
     // the existing buffers.
     RootedObject argType(cx, fninfo->mArgTypes[i]);
-    if (!ConvertToJS(cx, argType, NullPtr(), args[i], false, false, &argv[i]))
+    if (!ConvertToJS(cx, argType, NullPtr(), args[i], false, false, argv[i].address()))
       return;
   }
 
   // Call the JS function. 'thisObj' may be nullptr, in which case the JS
   // engine will find an appropriate object to use.
   RootedValue rval(cx);
   bool success = JS_CallFunctionValue(cx, thisObj, jsfnVal, argv, &rval);
 
--- a/js/src/jit/AsmJSLink.cpp
+++ b/js/src/jit/AsmJSLink.cpp
@@ -234,17 +234,17 @@ ValidateFFI(JSContext *cx, AsmJSModule::
     RootedPropertyName field(cx, global.ffiField());
     RootedValue v(cx);
     if (!GetDataProperty(cx, importVal, field, &v))
         return false;
 
     if (!v.isObject() || !v.toObject().is<JSFunction>())
         return LinkFail(cx, "FFI imports must be functions");
 
-    (*ffis)[global.ffiIndex()] = &v.toObject().as<JSFunction>();
+    (*ffis)[global.ffiIndex()].set(&v.toObject().as<JSFunction>());
     return true;
 }
 
 static bool
 ValidateArrayView(JSContext *cx, AsmJSModule::Global &global, HandleValue globalVal,
                   HandleValue bufferVal)
 {
     RootedPropertyName field(cx, global.viewName());
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -669,17 +669,17 @@ InitFromBailout(JSContext *cx, HandleScr
         for (uint32_t i = 0; i < fun->nargs(); i++) {
             Value arg = iter.read();
             IonSpew(IonSpew_BaselineBailouts, "      arg %d = %016llx",
                         (int) i, *((uint64_t *) &arg));
             if (callerPC) {
                 size_t argOffset = builder.framePushed() + IonJSFrameLayout::offsetOfActualArg(i);
                 *builder.valuePointerAtStackOffset(argOffset) = arg;
             } else {
-                startFrameFormals[i] = arg;
+                startFrameFormals[i].set(arg);
             }
         }
     }
 
     for (uint32_t i = 0; i < script->nfixed(); i++) {
         Value slot = iter.read();
         if (!builder.writeValue(slot, "FixedValue"))
             return false;
@@ -753,17 +753,17 @@ InitFromBailout(JSContext *cx, HandleScr
                 if (!builder.writeValue(UndefinedValue(), "StackValue"))
                     return false;
             }
             // Save the actual arguments. They are needed on the callee side
             // as the arguments. Else we can't recover them.
             if (!savedCallerArgs.resize(inlined_args))
                 return false;
             for (uint32_t i = 0; i < inlined_args; i++)
-                savedCallerArgs[i] = iter.read();
+                savedCallerArgs[i].set(iter.read());
 
             if (IsSetPropPC(pc)) {
                 // We would love to just save all the arguments and leave them
                 // in the stub frame pushed below, but we will lose the inital
                 // argument which the function was called with, which we must
                 // return to the caller, even if the setter internally modifies
                 // its arguments. Stash the initial argument on the stack, to be
                 // later retrieved by the SetProp_Fallback stub.
--- a/js/src/jit/BaselineFrame.cpp
+++ b/js/src/jit/BaselineFrame.cpp
@@ -106,17 +106,17 @@ BaselineFrame::copyRawFrameSlots(AutoVal
     unsigned nfixed = script()->nfixed();
     unsigned nformals = numFormalArgs();
 
     if (!vec->resize(nformals + nfixed))
         return false;
 
     mozilla::PodCopy(vec->begin(), argv(), nformals);
     for (unsigned i = 0; i < nfixed; i++)
-        (*vec)[nformals + i] = *valueSlot(i);
+        (*vec)[nformals + i].set(*valueSlot(i));
     return true;
 }
 
 bool
 BaselineFrame::strictEvalPrologue(JSContext *cx)
 {
     JS_ASSERT(isStrictEvalFrame());
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -230,23 +230,20 @@ class AutoVectorRooter : protected AutoG
     }
 
     void clear() { vector.clear(); }
 
     bool reserve(size_t newLength) {
         return vector.reserve(newLength);
     }
 
-    T &operator[](size_t i) { return vector[i]; }
-    const T &operator[](size_t i) const { return vector[i]; }
-
-    JS::MutableHandle<T> handleAt(size_t i) {
+    JS::MutableHandle<T> operator[](size_t i) {
         return JS::MutableHandle<T>::fromMarkedLocation(&vector[i]);
     }
-    JS::Handle<T> handleAt(size_t i) const {
+    JS::Handle<T> operator[](size_t i) const {
         return JS::Handle<T>::fromMarkedLocation(&vector[i]);
     }
 
     const T *begin() const { return vector.begin(); }
     T *begin() { return vector.begin(); }
 
     const T *end() const { return vector.end(); }
     T *end() { return vector.end(); }
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1739,24 +1739,24 @@ MergeSortByKey(K keys, size_t len, K scr
         if (i == j)
             continue; // fixed point
 
         MOZ_ASSERT(j > i, "Everything less than |i| should be in the right place!");
         Value tv = (*vec)[j];
         do {
             size_t k = keys[j].elementIndex;
             keys[j].elementIndex = j;
-            (*vec)[j] = (*vec)[k];
+            (*vec)[j].set((*vec)[k]);
             j = k;
         } while (j != i);
 
         // We could assert the loop invariant that |i == keys[i].elementIndex|
         // here if we synced |keys[i].elementIndex|.  But doing so would render
         // the assertion vacuous, so don't bother, even in debug builds.
-        (*vec)[i] = tv;
+        (*vec)[i].set(tv);
     }
 
     return true;
 }
 
 /*
  * Sort Values as strings.
  *
@@ -1815,17 +1815,17 @@ SortNumerically(JSContext *cx, AutoValue
         return false;
 
     /* Convert Values to numerics. */
     for (size_t i = 0; i < len; i++) {
         if (!CheckForInterrupt(cx))
             return false;
 
         double dv;
-        if (!ToNumber(cx, vec->handleAt(i), &dv))
+        if (!ToNumber(cx, (*vec)[i], &dv))
             return false;
 
         NumericElement el = { dv, i };
         numElements.infallibleAppend(el);
     }
 
     /* Resize strElements so we can perform MergeSort. */
     JS_ALWAYS_TRUE(numElements.resize(2 * len));
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -998,42 +998,42 @@ js::DefineProperties(JSContext *cx, Hand
     AutoPropDescArrayRooter descs(cx);
     if (!ReadPropertyDescriptors(cx, props, true, &ids, &descs))
         return false;
 
     if (obj->is<ArrayObject>()) {
         bool dummy;
         Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
         for (size_t i = 0, len = ids.length(); i < len; i++) {
-            if (!DefinePropertyOnArray(cx, arr, ids.handleAt(i), descs[i], true, &dummy))
+            if (!DefinePropertyOnArray(cx, arr, ids[i], descs[i], true, &dummy))
                 return false;
         }
         return true;
     }
 
     if (obj->getOps()->lookupGeneric) {
         /*
          * FIXME: Once ScriptedIndirectProxies are removed, this code should call
          * TrapDefineOwnProperty directly
          */
         if (obj->is<ProxyObject>()) {
             for (size_t i = 0, len = ids.length(); i < len; i++) {
                 RootedValue pd(cx, descs[i].pd());
-                if (!Proxy::defineProperty(cx, obj, ids.handleAt(i), pd))
+                if (!Proxy::defineProperty(cx, obj, ids[i], pd))
                     return false;
             }
             return true;
         }
         bool dummy;
         return Reject(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE, true, &dummy);
     }
 
     bool dummy;
     for (size_t i = 0, len = ids.length(); i < len; i++) {
-        if (!DefinePropertyOnObject(cx, obj, ids.handleAt(i), descs[i], true, &dummy))
+        if (!DefinePropertyOnObject(cx, obj, ids[i], descs[i], true, &dummy))
             return false;
     }
 
     return true;
 }
 
 extern bool
 js_PopulateObject(JSContext *cx, HandleObject newborn, HandleObject props)
@@ -1738,17 +1738,17 @@ JS_CopyPropertiesFrom(JSContext *cx, Han
 {
     JSAutoCompartment ac(cx, obj);
 
     AutoIdVector props(cx);
     if (!GetPropertyNames(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN, &props))
         return false;
 
     for (size_t i = 0; i < props.length(); ++i) {
-        if (!JS_CopyPropertyFrom(cx, props.handleAt(i), target, obj))
+        if (!JS_CopyPropertyFrom(cx, props[i], target, obj))
             return false;
     }
 
     return true;
 }
 
 static bool
 CopySlots(JSContext *cx, HandleObject from, HandleObject to)
@@ -2008,17 +2008,17 @@ js::XDRObjectLiteral(XDRState<mode> *xdr
                 // If we have reached the native property of the array class, we
                 // exit as the remaining would only be reserved slots.
                 if (!it.front().hasSlot()) {
                     JS_ASSERT(isArray);
                     break;
                 }
 
                 JS_ASSERT(it.front().hasDefaultGetter());
-                ids[it.front().slot()] = it.front().propid();
+                ids[it.front().slot()].set(it.front().propid());
             }
         }
 
         if (!xdr->codeUint32(&nslot))
             return false;
 
         RootedAtom atom(cx);
         RootedId id(cx);
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -238,17 +238,17 @@ BaseProxyHandler::keys(JSContext *cx, Ha
     size_t i = 0;
     for (size_t j = 0, len = props.length(); j < len; j++) {
         JS_ASSERT(i <= j);
         id = props[j];
         AutoWaivePolicy policy(cx, proxy, id, BaseProxyHandler::GET);
         if (!getOwnPropertyDescriptor(cx, proxy, id, &desc))
             return false;
         if (desc.object() && desc.isEnumerable())
-            props[i++] = id;
+            props[i++].set(id);
     }
 
     JS_ASSERT(i <= props.length());
     props.resize(i);
 
     return true;
 }
 
@@ -1577,17 +1577,17 @@ ArrayToIdVector(JSContext *cx, HandleObj
 
         // step ii
         RootedId id(cx);
         if (!ValueToId<CanGC>(cx, v, &id))
             return false;
 
         // step iii
         for (uint32_t j = 0; j < i; ++j) {
-            if (props[j] == id) {
+            if (props[j].get() == id) {
                 ReportInvalidTrapResult(cx, proxy, trapName);
                 return false;
             }
         }
 
         // step iv
         bool isFixed;
         if (!HasOwn(cx, target, id, &isFixed))
@@ -1613,17 +1613,17 @@ ArrayToIdVector(JSContext *cx, HandleObj
         return false;
 
     // step m
     for (size_t i = 0; i < ownProps.length(); ++i) {
         RootedId id(cx, ownProps[i]);
 
         bool found = false;
         for (size_t j = 0; j < props.length(); ++j) {
-            if (props[j] == id) {
+            if (props[j].get() == id) {
                 found = true;
                break;
             }
         }
         if (found)
             continue;
 
         // step i
@@ -2448,17 +2448,17 @@ JS_FRIEND_API(bool)
 js::AppendUnique(JSContext *cx, AutoIdVector &base, AutoIdVector &others)
 {
     AutoIdVector uniqueOthers(cx);
     if (!uniqueOthers.reserve(others.length()))
         return false;
     for (size_t i = 0; i < others.length(); ++i) {
         bool unique = true;
         for (size_t j = 0; j < base.length(); ++j) {
-            if (others[i] == base[j]) {
+            if (others[i].get() == base[j]) {
                 unique = false;
                 break;
             }
         }
         if (unique)
             uniqueOthers.append(others[i]);
     }
     return base.appendAll(uniqueOthers);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -230,17 +230,17 @@ XDRScriptBindings(XDRState<mode> *xdr, L
 
         AutoValueVector atoms(cx);
         if (!atoms.resize(nameCount))
             return false;
         for (uint32_t i = 0; i < nameCount; i++) {
             RootedAtom atom(cx);
             if (!XDRAtom(xdr, &atom))
                 return false;
-            atoms[i] = StringValue(atom);
+            atoms[i].setString(atom);
         }
 
         Binding *bindingArray = las.alloc().newArrayUninitialized<Binding>(nameCount);
         if (!bindingArray)
             return false;
         for (uint32_t i = 0; i < nameCount; i++) {
             uint8_t u8;
             if (!xdr->codeUint8(&u8))
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -405,17 +405,17 @@ Reify(JSContext *cx, JSCompartment *orig
         if (!keys.reserve(length))
             return false;
         for (size_t i = 0; i < length; ++i) {
             RootedId id(cx);
             RootedValue v(cx, StringValue(ni->begin()[i]));
             if (!ValueToId<CanGC>(cx, v, &id))
                 return false;
             keys.infallibleAppend(id);
-            if (!origin->wrapId(cx, &keys[i]))
+            if (!origin->wrapId(cx, keys[i].address()))
                 return false;
         }
     }
 
     close.clear();
     if (!CloseIterator(cx, iterObj))
         return false;
 
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2797,17 +2797,17 @@ Debugger::findScripts(JSContext *cx, uns
 
     RootedObject result(cx, NewDenseAllocatedArray(cx, scripts.length()));
     if (!result)
         return false;
 
     result->ensureDenseInitializedLength(cx, 0, scripts.length());
 
     for (size_t i = 0; i < scripts.length(); i++) {
-        JSObject *scriptObject = dbg->wrapScript(cx, scripts.handleAt(i));
+        JSObject *scriptObject = dbg->wrapScript(cx, scripts[i]);
         if (!scriptObject)
             return false;
         result->setDenseElement(i, ObjectValue(*scriptObject));
     }
 
     args.rval().setObject(*result);
     return true;
 }
@@ -4704,18 +4704,18 @@ DebuggerGenericEval(JSContext *cx, const
         RootedObject bindingsobj(cx, NonNullObject(cx, bindings));
         if (!bindingsobj ||
             !GetPropertyNames(cx, bindingsobj, JSITER_OWNONLY, &keys) ||
             !values.growBy(keys.length()))
         {
             return false;
         }
         for (size_t i = 0; i < keys.length(); i++) {
-            MutableHandleValue valp = values.handleAt(i);
-            if (!JSObject::getGeneric(cx, bindingsobj, bindingsobj, keys.handleAt(i), valp) ||
+            MutableHandleValue valp = values[i];
+            if (!JSObject::getGeneric(cx, bindingsobj, bindingsobj, keys[i], valp) ||
                 !dbg->unwrapDebuggeeValue(cx, valp))
             {
                 return false;
             }
         }
     }
 
     /* Set options from object if provided. */
@@ -4781,17 +4781,17 @@ DebuggerGenericEval(JSContext *cx, const
     if (evalWithBindings) {
         /* TODO - This should probably be a Call object, like ES5 strict eval. */
         env = NewObjectWithGivenProto(cx, &JSObject::class_, nullptr, env);
         if (!env)
             return false;
         RootedId id(cx);
         for (size_t i = 0; i < keys.length(); i++) {
             id = keys[i];
-            MutableHandleValue val = values.handleAt(i);
+            MutableHandleValue val = values[i];
             if (!cx->compartment()->wrap(cx, val) ||
                 !DefineNativeProperty(cx, env, id, val, nullptr, nullptr, 0))
             {
                 return false;
             }
         }
     }
 
@@ -5218,21 +5218,21 @@ DebuggerObject_getOwnPropertyNames(JSCon
          jsid id = keys[i];
          if (JSID_IS_INT(id)) {
              JSString *str = Int32ToString<CanGC>(cx, JSID_TO_INT(id));
              if (!str)
                  return false;
              vals[i].setString(str);
          } else if (JSID_IS_ATOM(id)) {
              vals[i].setString(JSID_TO_STRING(id));
-             if (!cx->compartment()->wrap(cx, vals.handleAt(i)))
+             if (!cx->compartment()->wrap(cx, vals[i]))
                  return false;
          } else {
              vals[i].setObject(*JSID_TO_OBJECT(id));
-             if (!dbg->wrapDebuggeeValue(cx, vals.handleAt(i)))
+             if (!dbg->wrapDebuggeeValue(cx, vals[i]))
                  return false;
          }
     }
 
     JSObject *aobj = NewDenseCopiedArray(cx, vals.length(), vals.begin());
     if (!aobj)
         return false;
     args.rval().setObject(*aobj);
@@ -5317,24 +5317,24 @@ DebuggerObject_defineProperties(JSContex
 
         Maybe<AutoCompartment> ac;
         ac.construct(cx, obj);
         RootedId id(cx);
         for (size_t i = 0; i < n; i++) {
             if (!rewrappedIds.append(JSID_VOID) || !rewrappedDescs.append())
                 return false;
             id = ids[i];
-            if (!unwrappedDescs[i].wrapInto(cx, obj, id, &rewrappedIds[i], &rewrappedDescs[i]))
+            if (!unwrappedDescs[i].wrapInto(cx, obj, id, rewrappedIds[i].address(), &rewrappedDescs[i]))
                 return false;
         }
 
         ErrorCopier ec(ac, dbg->toJSObject());
         for (size_t i = 0; i < n; i++) {
             bool dummy;
-            if (!DefineProperty(cx, obj, rewrappedIds.handleAt(i),
+            if (!DefineProperty(cx, obj, rewrappedIds[i],
                                 rewrappedDescs[i], true, &dummy))
             {
                 return false;
             }
         }
     }
 
     args.rval().setUndefined();
--- a/js/src/vm/OldDebugAPI.cpp
+++ b/js/src/vm/OldDebugAPI.cpp
@@ -672,17 +672,17 @@ JS_GetPropertyDescArray(JSContext *cx, J
         for (i = 0; i < props.length(); ++i) {
             pd[i].id = JSVAL_NULL;
             pd[i].value = JSVAL_NULL;
             if (!AddValueRoot(cx, &pd[i].id, nullptr))
                 goto bad;
             pd[i].id = IdToValue(props[i]);
             if (!AddValueRoot(cx, &pd[i].value, nullptr))
                 goto bad;
-            if (!Proxy::get(cx, obj, obj, props.handleAt(i), MutableHandleValue::fromMarkedLocation(&pd[i].value)))
+            if (!Proxy::get(cx, obj, obj, props[i], MutableHandleValue::fromMarkedLocation(&pd[i].value)))
                 goto bad;
         }
 
         pda->length = props.length();
         pda->array = pd;
         return true;
     }
 
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -797,17 +797,17 @@ js::XDRStaticBlockObject(XDRState<mode> 
             obj->setAliased(i, !!aliased);
         }
     } else {
         AutoShapeVector shapes(cx);
         if (!shapes.growBy(count))
             return false;
 
         for (Shape::Range<NoGC> r(obj->lastProperty()); !r.empty(); r.popFront())
-            shapes[obj->shapeToIndex(r.front())] = &r.front();
+            shapes[obj->shapeToIndex(r.front())].set(&r.front());
 
         RootedShape shape(cx);
         RootedId propid(cx);
         RootedAtom atom(cx);
         for (unsigned i = 0; i < count; i++) {
             shape = shapes[i];
             JS_ASSERT(shape->hasDefaultGetter());
             JS_ASSERT(obj->shapeToIndex(*shape) == i);
@@ -848,17 +848,17 @@ CloneStaticBlockObject(JSContext *cx, Ha
     clone->setLocalOffset(srcBlock->localOffset());
 
     /* Shape::Range is reverse order, so build a list in forward order. */
     AutoShapeVector shapes(cx);
     if (!shapes.growBy(srcBlock->numVariables()))
         return nullptr;
 
     for (Shape::Range<NoGC> r(srcBlock->lastProperty()); !r.empty(); r.popFront())
-        shapes[srcBlock->shapeToIndex(r.front())] = &r.front();
+        shapes[srcBlock->shapeToIndex(r.front())].set(&r.front());
 
     for (Shape **p = shapes.begin(); p != shapes.end(); ++p) {
         RootedId id(cx, (*p)->propid());
         unsigned i = srcBlock->shapeToIndex(**p);
 
         bool redeclared;
         if (!StaticBlockObject::addVar(cx, clone, id, i, &redeclared)) {
             JS_ASSERT(!redeclared);
@@ -1905,17 +1905,17 @@ DebugScopes::onPopCall(AbstractFramePtr 
         /*
          * Copy in formals that are not aliased via the scope chain
          * but are aliased via the arguments object.
          */
         RootedScript script(cx, frame.script());
         if (script->analyzedArgsUsage() && script->needsArgsObj() && frame.hasArgsObj()) {
             for (unsigned i = 0; i < frame.numFormalArgs(); ++i) {
                 if (script->formalLivesInArgumentsObject(i))
-                    vec[i] = frame.argsObj().arg(i);
+                    vec[i].set(frame.argsObj().arg(i));
             }
         }
 
         /*
          * Use a dense array as storage (since proxies do not have trace
          * hooks). This array must not escape into the wild.
          */
         RootedObject snapshot(cx, NewDenseCopiedArray(cx, vec.length(), vec.begin()));
--- a/js/src/vm/Shape.cpp
+++ b/js/src/vm/Shape.cpp
@@ -685,17 +685,17 @@ js::NewReshapedObject(JSContext *cx, Han
     js::AutoIdVector ids(cx);
     {
         for (unsigned i = 0; i <= shape->slot(); i++) {
             if (!ids.append(JSID_VOID))
                 return nullptr;
         }
         Shape *nshape = shape;
         while (!nshape->isEmptyShape()) {
-            ids[nshape->slot()] = nshape->propid();
+            ids[nshape->slot()].set(nshape->propid());
             nshape = nshape->previous();
         }
     }
 
     /* Construct the new shape, without updating type information. */
     RootedId id(cx);
     RootedShape newShape(cx, res->lastProperty());
     for (unsigned i = 0; i < ids.length(); i++) {
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -1245,17 +1245,17 @@ JSStructuredCloneReader::readTypedArray(
       default:
         MOZ_ASSUME_UNREACHABLE("unknown TypedArrayObject type");
     }
 
     if (!obj)
         return false;
     vp->setObject(*obj);
 
-    allObjs[placeholderIndex] = *vp;
+    allObjs[placeholderIndex].set(*vp);
 
     return true;
 }
 
 bool
 JSStructuredCloneReader::readArrayBuffer(uint32_t nbytes, Value *vp)
 {
     JSObject *obj = ArrayBufferObject::create(context(), nbytes);
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -386,17 +386,17 @@ CloneNonReflectorsRead(JSContext *cx, JS
 {
     MOZ_ASSERT(closure, "Null pointer!");
     AutoObjectVector *reflectors = static_cast<AutoObjectVector *>(closure);
     if (tag == SCTAG_REFLECTOR) {
         MOZ_ASSERT(!data);
 
         size_t idx;
         if (JS_ReadBytes(reader, &idx, sizeof(size_t))) {
-            RootedObject reflector(cx, reflectors->handleAt(idx));
+            RootedObject reflector(cx, (*reflectors)[idx]);
             MOZ_ASSERT(reflector, "No object pointer?");
             MOZ_ASSERT(IsReflector(reflector), "Object pointer must be a reflector!");
 
             if (!JS_WrapObject(cx, &reflector))
                 return nullptr;
             MOZ_ASSERT(WrapperFactory::IsXrayWrapper(reflector) ||
                        IsReflector(reflector));
 
--- a/js/xpconnect/wrappers/FilteringWrapper.cpp
+++ b/js/xpconnect/wrappers/FilteringWrapper.cpp
@@ -30,17 +30,17 @@ template <typename Policy>
 static bool
 Filter(JSContext *cx, HandleObject wrapper, AutoIdVector &props)
 {
     size_t w = 0;
     RootedId id(cx);
     for (size_t n = 0; n < props.length(); ++n) {
         id = props[n];
         if (Policy::check(cx, wrapper, id, Wrapper::GET))
-            props[w++] = id;
+            props[w++].set(id);
         else if (JS_IsExceptionPending(cx))
             return false;
     }
     props.resize(w);
     return true;
 }
 
 template <typename Policy>