Bug 959787 - Handlify several JSAPI interfaces that can GC, Part 4; r=sfink,r=bz
authorTerrence Cole <terrence@mozilla.com>
Fri, 17 Jan 2014 10:08:51 -0800
changeset 180113 21cef8b355cea6e7785ef61567e1ea4f752f305b
parent 180112 2a3b16b9246af3316e7792f0bb016d9f8b2ffca7
child 180114 e40cf0c641b5543556240c97a08213e3b4c7a615
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink, bz
bugs959787
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 959787 - Handlify several JSAPI interfaces that can GC, Part 4; r=sfink,r=bz
caps/src/nsScriptSecurityManager.cpp
dom/base/nsDOMClassInfo.cpp
dom/bindings/BindingUtils.cpp
dom/bindings/Codegen.py
dom/bindings/DOMJSProxyHandler.cpp
dom/media/MediaManager.cpp
dom/plugins/base/nsJSNPRuntime.cpp
dom/xbl/nsXBLProtoImplField.cpp
js/ipc/JavaScriptShared.cpp
js/jsd/jsd_val.cpp
js/src/jsapi-tests/testLookup.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCQuickStubs.h
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
storage/src/mozStorageStatementParams.cpp
toolkit/components/places/History.cpp
tools/profiler/JSObjectBuilder.cpp
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -95,17 +95,17 @@ nsScriptSecurityManager::SubjectIsPrivil
 static inline const char16_t *
 IDToString(JSContext *cx, jsid id_)
 {
     JS::RootedId id(cx, id_);
     if (JSID_IS_STRING(id))
         return JS_GetInternedStringChars(JSID_TO_STRING(id));
 
     JS::Rooted<JS::Value> idval(cx);
-    if (!JS_IdToValue(cx, id, idval.address()))
+    if (!JS_IdToValue(cx, id, &idval))
         return nullptr;
     JSString *str = JS::ToString(cx, idval);
     if(!str)
         return nullptr;
     return JS_GetStringCharsZ(cx, str);
 }
 
 class nsAutoInPrincipalDomainOriginSetter {
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -585,17 +585,17 @@ FindObjectClass(JSContext* cx, JSObject*
 }
 
 static inline JSString *
 IdToString(JSContext *cx, jsid id)
 {
   if (JSID_IS_STRING(id))
     return JSID_TO_STRING(id);
   JS::Rooted<JS::Value> idval(cx);
-  if (!::JS_IdToValue(cx, id, idval.address()))
+  if (!::JS_IdToValue(cx, id, &idval))
     return nullptr;
   return JS::ToString(cx, idval);
 }
 
 static inline nsresult
 WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
            nsWrapperCache *cache, const nsIID* aIID, JS::MutableHandle<JS::Value> vp,
            bool aAllowWrapping)
@@ -1306,17 +1306,17 @@ nsDOMClassInfo::GetArrayIndexFromId(JSCo
   }
 
   int i;
   if (JSID_IS_INT(id)) {
       i = JSID_TO_INT(id);
   } else {
       JS::Rooted<JS::Value> idval(cx);
       double array_index;
-      if (!::JS_IdToValue(cx, id, idval.address()) ||
+      if (!::JS_IdToValue(cx, id, &idval) ||
           !JS::ToNumber(cx, idval, &array_index) ||
           !::JS_DoubleIsInt32(array_index, &i)) {
         return -1;
       }
   }
 
   if (aIsNumber) {
     *aIsNumber = true;
@@ -4353,17 +4353,19 @@ nsStorage2SH::NewEnumerate(nsIXPConnectW
     (nsTArray<nsString> *)JSVAL_TO_PRIVATE(*statep);
 
   if (enum_op == JSENUMERATE_NEXT && keys->Length() != 0) {
     nsString& key = keys->ElementAt(0);
     JSString *str =
       JS_NewUCStringCopyN(cx, key.get(), key.Length());
     NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
 
-    JS_ValueToId(cx, STRING_TO_JSVAL(str), idp);
+    JS::Rooted<jsid> id(cx);
+    JS_ValueToId(cx, JS::StringValue(str), &id);
+    *idp = id;
 
     keys->RemoveElementAt(0);
 
     return NS_OK;
   }
 
   // destroy the keys array if we have no keys or if we're done
   NS_ABORT_IF_FALSE(enum_op == JSENUMERATE_DESTROY ||
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -1474,17 +1474,17 @@ AppendNamedPropertyIds(JSContext* cx, JS
 {
   for (uint32_t i = 0; i < names.Length(); ++i) {
     JS::Rooted<JS::Value> v(cx);
     if (!xpc::NonVoidStringToJsval(cx, names[i], &v)) {
       return false;
     }
 
     JS::Rooted<jsid> id(cx);
-    if (!JS_ValueToId(cx, v, id.address())) {
+    if (!JS_ValueToId(cx, v, &id)) {
       return false;
     }
 
     if (shadowPrototypeProperties || !HasPropertyOnPrototype(cx, proxy, id)) {
       if (!props.append(id)) {
         return false;
       }
     }
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -5220,17 +5220,18 @@ if (!${obj}) {
             if (self.idlNode.getExtendedAttribute("Cached") and
                 self.descriptor.wrapperCache):
                 preserveWrapper = "PreserveWrapper(self);\n"
             else:
                 preserveWrapper = ""
             if self.idlNode.getExtendedAttribute("Frozen"):
                 assert self.idlNode.type.isSequence()
                 freezeValue = CGGeneric(
-                    "if (!JS_FreezeObject(cx, &args.rval().toObject())) {\n"
+                    "JS::Rooted<JSObject*> rvalObj(cx, &args.rval().toObject());\n"
+                    "if (!JS_FreezeObject(cx, rvalObj)) {\n"
                     "  return false;\n"
                     "}")
                 if self.idlNode.type.nullable():
                     freezeValue = CGIfWrapper(freezeValue,
                                               "args.rval().isObject()")
                 freezeValue = freezeValue.define() + "\n"
             else:
                 freezeValue = ""
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -280,17 +280,17 @@ DOMProxyHandler::has(JSContext* cx, JS::
 }
 
 int32_t
 IdToInt32(JSContext* cx, JS::Handle<jsid> id)
 {
   JS::Rooted<JS::Value> idval(cx);
   double array_index;
   int32_t i;
-  if (!::JS_IdToValue(cx, id, idval.address()) ||
+  if (!::JS_IdToValue(cx, id, &idval) ||
       !JS::ToNumber(cx, idval, &array_index) ||
       !::JS_DoubleIsInt32(array_index, &i)) {
     return -1;
   }
 
   return i;
 }
 
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -100,17 +100,17 @@ static nsresult CompareDictionaries(JSCo
     JS::Rooted<JS::Value> bprop(aCx);
     if (!JS_GetPropertyById(aCx, b, props[i], &bprop)) {
       LOG(("Error parsing dictionary!\n"));
       return NS_ERROR_UNEXPECTED;
     }
     if (bprop.isUndefined()) {
       // Unknown property found in A. Bail with name
       JS::Rooted<JS::Value> nameval(aCx);
-      bool success = JS_IdToValue(aCx, props[i], nameval.address());
+      bool success = JS_IdToValue(aCx, props[i], &nameval);
       NS_ENSURE_TRUE(success, NS_ERROR_UNEXPECTED);
 
       JS::Rooted<JSString*> namestr(aCx, JS::ToString(aCx, nameval));
       NS_ENSURE_TRUE(namestr, NS_ERROR_UNEXPECTED);
       aDifference->Assign(JS_GetStringCharsZ(aCx, namestr));
       return NS_OK;
     }
   }
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -894,17 +894,17 @@ nsJSObjWrapper::NP_Enumerate(NPObject *n
   *idarray = (NPIdentifier *)PR_Malloc(*count * sizeof(NPIdentifier));
   if (!*idarray) {
     ThrowJSException(cx, "Memory allocation failed for NPIdentifier!");
     return false;
   }
 
   for (uint32_t i = 0; i < *count; i++) {
     JS::Rooted<JS::Value> v(cx);
-    if (!JS_IdToValue(cx, ida[i], v.address())) {
+    if (!JS_IdToValue(cx, ida[i], &v)) {
       PR_Free(*idarray);
       return false;
     }
 
     NPIdentifier id;
     if (v.isString()) {
       JS::Rooted<JSString*> str(cx, v.toString());
       str = JS_InternJSString(cx, str);
--- a/dom/xbl/nsXBLProtoImplField.cpp
+++ b/dom/xbl/nsXBLProtoImplField.cpp
@@ -185,17 +185,17 @@ InstallXBLField(JSContext* cx,
 
     JS::Rooted<JSObject*> xblProto(cx);
     xblProto = &js::GetFunctionNativeReserved(callee, XBLPROTO_SLOT).toObject();
 
     JS::Rooted<JS::Value> name(cx, js::GetFunctionNativeReserved(callee, FIELD_SLOT));
     JSFlatString* fieldStr = JS_ASSERT_STRING_IS_FLAT(name.toString());
     fieldName.init(fieldStr);
 
-    MOZ_ALWAYS_TRUE(JS_ValueToId(cx, name, idp.address()));
+    MOZ_ALWAYS_TRUE(JS_ValueToId(cx, name, idp));
 
     // If a separate XBL scope is being used, the callee is not same-compartment
     // with the xbl prototype, and the object is a cross-compartment wrapper.
     xblProto = js::UncheckedUnwrap(xblProto);
     JSAutoCompartment ac2(cx, xblProto);
     JS::Value slotVal = ::JS_GetReservedSlot(xblProto, 0);
     protoBinding = static_cast<nsXBLPrototypeBinding*>(slotVal.toPrivate());
     MOZ_ASSERT(protoBinding);
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -132,17 +132,17 @@ JavaScriptShared::init()
         return false;
     return true;
 }
 
 bool
 JavaScriptShared::convertIdToGeckoString(JSContext *cx, JS::HandleId id, nsString *to)
 {
     RootedValue idval(cx);
-    if (!JS_IdToValue(cx, id, idval.address()))
+    if (!JS_IdToValue(cx, id, &idval))
         return false;
 
     RootedString str(cx, ToString(cx, idval));
     if (!str)
         return false;
 
     const jschar *chars = JS_GetStringCharsZ(cx, str);
     if (!chars)
@@ -154,17 +154,17 @@ JavaScriptShared::convertIdToGeckoString
 
 bool
 JavaScriptShared::convertGeckoStringToId(JSContext *cx, const nsString &from, JS::MutableHandleId to)
 {
     RootedString str(cx, JS_NewUCStringCopyN(cx, from.BeginReading(), from.Length()));
     if (!str)
         return false;
 
-    return JS_ValueToId(cx, StringValue(str), to.address());
+    return JS_ValueToId(cx, StringValue(str), to);
 }
 
 bool
 JavaScriptShared::toVariant(JSContext *cx, JS::HandleValue from, JSVariant *to)
 {
     switch (JS_TypeOfValue(cx, from)) {
       case JSTYPE_VOID:
         *to = void_t();
--- a/js/jsd/jsd_val.cpp
+++ b/js/jsd/jsd_val.cpp
@@ -497,17 +497,17 @@ jsd_GetValueProperty(JSDContext* jsdc, J
             if (JS_CompareStrings(cx, propName, name, &result) && !result)
                 return jsdprop;
         }
         JSD_DropProperty(jsdc, jsdprop);
     }
     /* Not found in property list, look it up explicitly */
 
     nameval = STRING_TO_JSVAL(name);
-    if(!JS_ValueToId(cx, nameval, nameid.address()))
+    if(!JS_ValueToId(cx, nameval, &nameid))
         return nullptr;
 
     if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
         return nullptr;
 
     JS::Rooted<JSPropertyDescriptor> desc(cx);
     {
         JSAutoCompartment ac(cx, obj);
@@ -539,17 +539,17 @@ jsd_GetValueProperty(JSDContext* jsdc, J
             }
         }
         else
         {
             propValue = val;
         }
     }
 
-    if (!JS_IdToValue(cx, nameid, propId.address()))
+    if (!JS_IdToValue(cx, nameid, &propId))
         return nullptr;
 
     propAlias = JSVAL_NULL;
     propFlags |= desc.isEnumerable() ? JSPD_ENUMERATE : 0
         | desc.isReadonly() ? JSPD_READONLY  : 0
         | desc.isPermanent() ? JSPD_PERMANENT : 0;
 
     return _newProperty(jsdc, propId, propValue, propAlias, propFlags, JSDPD_HINTED);
--- a/js/src/jsapi-tests/testLookup.cpp
+++ b/js/src/jsapi-tests/testLookup.cpp
@@ -50,17 +50,17 @@ static const JSClass DocumentAllClass = 
 };
 
 bool
 document_resolve(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned flags,
                  JS::MutableHandleObject objp)
 {
     // If id is "all", resolve document.all=true.
     JS::RootedValue v(cx);
-    if (!JS_IdToValue(cx, id, v.address()))
+    if (!JS_IdToValue(cx, id, &v))
         return false;
     if (JSVAL_IS_STRING(v)) {
         JSString *str = JSVAL_TO_STRING(v);
         JSFlatString *flatStr = JS_FlattenString(cx, str);
         if (!flatStr)
             return false;
         if (JS_FlatStringEqualsAscii(flatStr, "all")) {
             JS::Rooted<JSObject*> docAll(cx,
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2220,38 +2220,32 @@ JS_IdArrayGet(JSContext *cx, JSIdArray *
 
 JS_PUBLIC_API(void)
 JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
 {
     cx->runtime()->defaultFreeOp()->free_(ida);
 }
 
 JS_PUBLIC_API(bool)
-JS_ValueToId(JSContext *cx, jsval valueArg, jsid *idp)
+JS_ValueToId(JSContext *cx, jsval valueArg, MutableHandleId idp)
 {
     RootedValue value(cx, valueArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
-
-    RootedId id(cx);
-    if (!ValueToId<CanGC>(cx, value, &id))
-        return false;
-
-    *idp = id;
-    return true;
+    return ValueToId<CanGC>(cx, value, idp);
 }
 
 JS_PUBLIC_API(bool)
-JS_IdToValue(JSContext *cx, jsid id, jsval *vp)
+JS_IdToValue(JSContext *cx, jsid id, MutableHandleValue vp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    *vp = IdToJsval(id);
-    assertSameCompartment(cx, *vp);
+    vp.set(IdToJsval(id));
+    assertSameCompartment(cx, vp);
     return true;
 }
 
 JS_PUBLIC_API(bool)
 JS_DefaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
@@ -2656,30 +2650,27 @@ JS_IsNative(JSObject *obj)
 
 JS_PUBLIC_API(JSRuntime *)
 JS_GetObjectRuntime(JSObject *obj)
 {
     return obj->compartment()->runtimeFromMainThread();
 }
 
 JS_PUBLIC_API(bool)
-JS_FreezeObject(JSContext *cx, JSObject *objArg)
-{
-    RootedObject obj(cx, objArg);
+JS_FreezeObject(JSContext *cx, HandleObject obj)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-
     return JSObject::freeze(cx, obj);
 }
 
 JS_PUBLIC_API(bool)
-JS_DeepFreezeObject(JSContext *cx, JSObject *objArg)
-{
-    RootedObject obj(cx, objArg);
+JS_DeepFreezeObject(JSContext *cx, HandleObject obj)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
     bool extensible;
     if (!JSObject::isExtensible(cx, obj, &extensible))
         return false;
@@ -3680,20 +3671,18 @@ static const Class prop_iter_class = {
     nullptr,        /* checkAccess */
     nullptr,        /* call        */
     nullptr,        /* hasInstance */
     nullptr,        /* construct   */
     prop_iter_trace
 };
 
 JS_PUBLIC_API(JSObject *)
-JS_NewPropertyIterator(JSContext *cx, JSObject *objArg)
-{
-    RootedObject obj(cx, objArg);
-
+JS_NewPropertyIterator(JSContext *cx, HandleObject obj)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     RootedObject iterobj(cx, NewObjectWithClassProto(cx, &prop_iter_class, nullptr, obj));
     if (!iterobj)
         return nullptr;
 
@@ -3712,20 +3701,18 @@ JS_NewPropertyIterator(JSContext *cx, JS
     }
 
     /* iterobj cannot escape to other threads here. */
     iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index));
     return iterobj;
 }
 
 JS_PUBLIC_API(bool)
-JS_NextProperty(JSContext *cx, JSObject *iterobjArg, jsid *idp)
-{
-    RootedObject iterobj(cx, iterobjArg);
-
+JS_NextProperty(JSContext *cx, HandleObject iterobj, jsid *idp)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, iterobj);
     int32_t i = iterobj->getSlot(JSSLOT_ITER_INDEX).toInt32();
     if (i < 0) {
         /* Native case: private data is a property tree node pointer. */
         JS_ASSERT(iterobj->getParent()->isNative());
         Shape *shape = static_cast<Shape *>(iterobj->getPrivate());
@@ -3784,49 +3771,41 @@ JS_PUBLIC_API(bool)
 JS_IsArrayObject(JSContext *cx, JSObject *objArg)
 {
     RootedObject obj(cx, objArg);
     assertSameCompartment(cx, obj);
     return ObjectClassIs(obj, ESClass_Array, cx);
 }
 
 JS_PUBLIC_API(bool)
-JS_GetArrayLength(JSContext *cx, JSObject *objArg, uint32_t *lengthp)
-{
-    RootedObject obj(cx, objArg);
+JS_GetArrayLength(JSContext *cx, HandleObject obj, uint32_t *lengthp)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return GetLengthProperty(cx, obj, lengthp);
 }
 
 JS_PUBLIC_API(bool)
-JS_SetArrayLength(JSContext *cx, JSObject *objArg, uint32_t length)
-{
-    RootedObject obj(cx, objArg);
+JS_SetArrayLength(JSContext *cx, HandleObject obj, uint32_t length)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return SetLengthProperty(cx, obj, length);
 }
 
 JS_PUBLIC_API(bool)
-JS_CheckAccess(JSContext *cx, JSObject *objArg, jsid idArg, JSAccessMode mode,
-               jsval *vp, unsigned *attrsp)
-{
-    RootedObject obj(cx, objArg);
-    RootedId id(cx, idArg);
-    RootedValue value(cx, *vp);
-
+JS_CheckAccess(JSContext *cx, HandleObject obj, HandleId id, JSAccessMode mode,
+               MutableHandleValue vp, unsigned *attrsp)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
-    bool status = CheckAccess(cx, obj, id, mode, &value, attrsp);
-    *vp = value;
-    return status;
+    return CheckAccess(cx, obj, id, mode, vp, attrsp);
 }
 
 JS_PUBLIC_API(void)
 JS_HoldPrincipals(JSPrincipals *principals)
 {
     ++principals->refcount;
 }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2304,20 +2304,20 @@ class AutoIdArray : private AutoGCRooter
     /* No copy or assignment semantics. */
     AutoIdArray(AutoIdArray &ida) MOZ_DELETE;
     void operator=(AutoIdArray &ida) MOZ_DELETE;
 };
 
 } /* namespace JS */
 
 extern JS_PUBLIC_API(bool)
-JS_ValueToId(JSContext *cx, jsval v, jsid *idp);
+JS_ValueToId(JSContext *cx, jsval v, JS::MutableHandle<jsid> idp);
 
 extern JS_PUBLIC_API(bool)
-JS_IdToValue(JSContext *cx, jsid id, jsval *vp);
+JS_IdToValue(JSContext *cx, jsid id, JS::MutableHandle<JS::Value> vp);
 
 /*
  * JSNewResolveOp flag bits.
  */
 #define JSRESOLVE_ASSIGNING     0x01    /* resolve on the left of assignment */
 
 /*
  * Invoke the [[DefaultValue]] hook (see ES5 8.6.2) with the provided hint on
@@ -2740,23 +2740,23 @@ JS_NewObjectWithGivenProto(JSContext *cx
                            JS::Handle<JSObject*> parent);
 
 /*
  * Freeze obj, and all objects it refers to, recursively. This will not recurse
  * through non-extensible objects, on the assumption that those are already
  * deep-frozen.
  */
 extern JS_PUBLIC_API(bool)
-JS_DeepFreezeObject(JSContext *cx, JSObject *obj);
+JS_DeepFreezeObject(JSContext *cx, JS::Handle<JSObject*> obj);
 
 /*
  * Freezes an object; see ES5's Object.freeze(obj) method.
  */
 extern JS_PUBLIC_API(bool)
-JS_FreezeObject(JSContext *cx, JSObject *obj);
+JS_FreezeObject(JSContext *cx, JS::Handle<JSObject*> obj);
 
 extern JS_PUBLIC_API(bool)
 JS_PreventExtensions(JSContext *cx, JS::HandleObject obj);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_New(JSContext *cx, JSObject *ctor, unsigned argc, jsval *argv);
 
 extern JS_PUBLIC_API(JSObject *)
@@ -3055,20 +3055,20 @@ JS_DeleteUCProperty2(JSContext *cx, JSOb
 
 extern JS_PUBLIC_API(JSObject *)
 JS_NewArrayObject(JSContext *cx, int length, jsval *vector);
 
 extern JS_PUBLIC_API(bool)
 JS_IsArrayObject(JSContext *cx, JSObject *obj);
 
 extern JS_PUBLIC_API(bool)
-JS_GetArrayLength(JSContext *cx, JSObject *obj, uint32_t *lengthp);
+JS_GetArrayLength(JSContext *cx, JS::Handle<JSObject*> obj, uint32_t *lengthp);
 
 extern JS_PUBLIC_API(bool)
-JS_SetArrayLength(JSContext *cx, JSObject *obj, uint32_t length);
+JS_SetArrayLength(JSContext *cx, JS::Handle<JSObject*> obj, uint32_t length);
 
 extern JS_PUBLIC_API(bool)
 JS_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, jsval value,
                  JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
 
 extern JS_PUBLIC_API(bool)
 JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, uint32_t index, bool *foundp);
 
@@ -3153,29 +3153,29 @@ extern JS_PUBLIC_API(JSIdArray *)
 JS_Enumerate(JSContext *cx, JSObject *obj);
 
 /*
  * Create an object to iterate over enumerable properties of obj, in arbitrary
  * property definition order.  NB: This differs from longstanding for..in loop
  * order, which uses order of property definition in obj.
  */
 extern JS_PUBLIC_API(JSObject *)
-JS_NewPropertyIterator(JSContext *cx, JSObject *obj);
+JS_NewPropertyIterator(JSContext *cx, JS::Handle<JSObject*> obj);
 
 /*
  * Return true on success with *idp containing the id of the next enumerable
  * property to visit using iterobj, or JSID_IS_VOID if there is no such property
  * left to visit.  Return false on error.
  */
 extern JS_PUBLIC_API(bool)
-JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp);
+JS_NextProperty(JSContext *cx, JS::Handle<JSObject*> iterobj, jsid *idp);
 
 extern JS_PUBLIC_API(bool)
-JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
-               jsval *vp, unsigned *attrsp);
+JS_CheckAccess(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSAccessMode mode,
+               JS::MutableHandle<JS::Value> vp, unsigned *attrsp);
 
 extern JS_PUBLIC_API(jsval)
 JS_GetReservedSlot(JSObject *obj, uint32_t index);
 
 extern JS_PUBLIC_API(void)
 JS_SetReservedSlot(JSObject *obj, uint32_t index, jsval v);
 
 /************************************************************************/
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -1290,17 +1290,17 @@ mozJSComponentLoader::ImportInto(const n
         nsAutoCString logBuffer;
 #endif
 
         RootedValue value(mContext);
         RootedId symbolId(mContext);
         for (uint32_t i = 0; i < symbolCount; ++i) {
             if (!JS_GetElement(mContext, symbolsObj, i, &value) ||
                 !value.isString() ||
-                !JS_ValueToId(mContext, value, symbolId.address())) {
+                !JS_ValueToId(mContext, value, &symbolId)) {
                 return ReportOnCaller(cxhelper, ERROR_ARRAY_ELEMENT,
                                       PromiseFlatCString(aLocation).get(), i);
             }
 
             if (!JS_GetPropertyById(mContext, mod->obj, symbolId, &value)) {
                 JSAutoByteString bytes(mContext, JSID_TO_STRING(symbolId));
                 if (!bytes)
                     return NS_ERROR_FAILURE;
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -165,17 +165,17 @@ SandboxImport(JSContext *cx, unsigned ar
         funname = JS_GetFunctionId(fun);
         if (!funname) {
             XPCThrower::Throw(NS_ERROR_INVALID_ARG, cx);
             return false;
         }
     }
 
     RootedId id(cx);
-    if (!JS_ValueToId(cx, StringValue(funname), id.address()))
+    if (!JS_ValueToId(cx, StringValue(funname), &id))
         return false;
 
     // We need to resolve the this object, because this function is used
     // unbound and should still work and act on the original sandbox.
     RootedObject thisObject(cx, JS_THIS_OBJECT(cx, vp));
     if (!thisObject) {
         XPCThrower::Throw(NS_ERROR_UNEXPECTED, cx);
         return false;
@@ -289,17 +289,17 @@ ExportFunction(JSContext *cx, HandleValu
             // copy the name from the function being imported.
             JSFunction *fun = JS_GetObjectFunction(funObj);
             RootedString funName(cx, JS_GetFunctionId(fun));
             if (!funName)
                 funName = JS_InternString(cx, "");
 
             RootedValue vname(cx);
             vname.setString(funName);
-            if (!JS_ValueToId(cx, vname, id.address()))
+            if (!JS_ValueToId(cx, vname, &id))
                 return false;
         }
         MOZ_ASSERT(JSID_IS_STRING(id));
 
         // The function forwarder will live in the target compartment. Since
         // this function will be referenced from its private slot, to avoid a
         // GC hazard, we must wrap it to the same compartment.
         if (!JS_WrapObject(cx, &funObj))
@@ -1442,17 +1442,17 @@ OptionsBase::ParseId(const char *name, M
     RootedValue value(mCx);
     bool found;
     bool ok = ParseValue(name, &value, &found);
     NS_ENSURE_TRUE(ok, false);
 
     if (!found)
         return true;
 
-    return JS_ValueToId(mCx, value, prop.address());
+    return JS_ValueToId(mCx, value, prop);
 }
 
 /*
  * Helper that tries to get a list of DOM constructors and other helpers from the options object.
  */
 bool
 SandboxOptions::ParseGlobalProperties()
 {
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -258,19 +258,21 @@ nsXPCComponents_Interfaces::NewEnumerate
             uint32_t idx = JSVAL_TO_INT(*statep);
             nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(idx);
             *statep = UINT_TO_JSVAL(idx + 1);
 
             if (interface) {
                 JSString* idstr;
                 const char* name;
 
+                JS::Rooted<jsid> id(cx);
                 if (NS_SUCCEEDED(interface->GetNameShared(&name)) && name &&
                         nullptr != (idstr = JS_NewStringCopyZ(cx, name)) &&
-                        JS_ValueToId(cx, STRING_TO_JSVAL(idstr), idp)) {
+                        JS_ValueToId(cx, StringValue(idstr), &id)) {
+                    *idp = id;
                     return NS_OK;
                 }
             }
             // fall through
         }
 
         case JSENUMERATE_DESTROY:
         default:
@@ -507,17 +509,19 @@ nsXPCComponents_InterfacesByID::NewEnume
             if (interface) {
                 nsIID const *iid;
                 char idstr[NSID_LENGTH];
                 JSString* jsstr;
 
                 if (NS_SUCCEEDED(interface->GetIIDShared(&iid))) {
                     iid->ToProvidedString(idstr);
                     jsstr = JS_NewStringCopyZ(cx, idstr);
-                    if (jsstr && JS_ValueToId(cx, STRING_TO_JSVAL(jsstr), idp)) {
+                    JS::Rooted<jsid> id(cx);
+                    if (jsstr && JS_ValueToId(cx, StringValue(jsstr), &id)) {
+                        *idp = id;
                         return NS_OK;
                     }
                 }
             }
             // FALL THROUGH
         }
 
         case JSENUMERATE_DESTROY:
@@ -761,18 +765,20 @@ nsXPCComponents_Classes::NewEnumerate(ns
 
             if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
                 NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
                 nsCOMPtr<nsISupportsCString> holder(do_QueryInterface(isup));
                 if (holder) {
                     nsAutoCString name;
                     if (NS_SUCCEEDED(holder->GetData(name))) {
                         JSString* idstr = JS_NewStringCopyN(cx, name.get(), name.Length());
+                        JS::Rooted<jsid> id(cx);
                         if (idstr &&
-                            JS_ValueToId(cx, STRING_TO_JSVAL(idstr), idp)) {
+                            JS_ValueToId(cx, StringValue(idstr), &id)) {
+                            *idp = id;
                             return NS_OK;
                         }
                     }
                 }
             }
             // else... FALL THROUGH
         }
 
@@ -1001,18 +1007,20 @@ nsXPCComponents_ClassesByID::NewEnumerat
             if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
                 NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
                 nsCOMPtr<nsISupportsID> holder(do_QueryInterface(isup));
                 if (holder) {
                     char* name;
                     if (NS_SUCCEEDED(holder->ToString(&name)) && name) {
                         JSString* idstr = JS_NewStringCopyZ(cx, name);
                         nsMemory::Free(name);
+                        JS::Rooted<jsid> id(cx);
                         if (idstr &&
-                            JS_ValueToId(cx, STRING_TO_JSVAL(idstr), idp)) {
+                            JS_ValueToId(cx, StringValue(idstr), &id)) {
+                            *idp = id;
                             return NS_OK;
                         }
                     }
                 }
             }
             // else... FALL THROUGH
         }
 
@@ -1253,18 +1261,21 @@ nsXPCComponents_Results::NewEnumerate(ns
             return NS_OK;
         }
         case JSENUMERATE_NEXT:
         {
             const char* name;
             iter = (const void**) JSVAL_TO_PRIVATE(*statep);
             if (nsXPCException::IterateNSResults(nullptr, &name, nullptr, iter)) {
                 JSString* idstr = JS_NewStringCopyZ(cx, name);
-                if (idstr && JS_ValueToId(cx, STRING_TO_JSVAL(idstr), idp))
+                JS::Rooted<jsid> id(cx);
+                if (idstr && JS_ValueToId(cx, StringValue(idstr), &id)) {
+                    *idp = id;
                     return NS_OK;
+                }
             }
             // else... FALL THROUGH
         }
 
         case JSENUMERATE_DESTROY:
         default:
             iter = (const void**) JSVAL_TO_PRIVATE(*statep);
             delete [] (char*) iter;
@@ -2394,17 +2405,17 @@ nsXPCComponents_Constructor::CallOrConst
                                       getter_AddRefs(holder))) || !holder ||
             // Assign, not compare
             !(ifacesObj = holder->GetJSObject())) {
             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
         }
 
         RootedString str(cx, ToString(cx, args[1]));
         RootedId id(cx);
-        if (!str || !JS_ValueToId(cx, StringValue(str), id.address()))
+        if (!str || !JS_ValueToId(cx, StringValue(str), &id))
             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
 
         RootedValue val(cx);
         if (!JS_GetPropertyById(cx, ifacesObj, id, &val) || val.isPrimitive())
             return ThrowAndFail(NS_ERROR_XPC_BAD_IID, cx, _retval);
 
         nsCOMPtr<nsIXPConnectWrappedNative> wn;
         if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, &val.toObject(),
@@ -2442,17 +2453,17 @@ nsXPCComponents_Constructor::CallOrConst
                                       getter_AddRefs(holder))) || !holder ||
             // Assign, not compare
             !(classesObj = holder->GetJSObject())) {
             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
         }
 
         RootedString str(cx, ToString(cx, args[0]));
         RootedId id(cx);
-        if (!str || !JS_ValueToId(cx, StringValue(str), id.address()))
+        if (!str || !JS_ValueToId(cx, StringValue(str), &id))
             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
 
         RootedValue val(cx);
         if (!JS_GetPropertyById(cx, classesObj, id, &val) || val.isPrimitive())
             return ThrowAndFail(NS_ERROR_XPC_BAD_CID, cx, _retval);
 
         nsCOMPtr<nsIXPConnectWrappedNative> wn;
         if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(val),
--- a/js/xpconnect/src/XPCQuickStubs.h
+++ b/js/xpconnect/src/XPCQuickStubs.h
@@ -605,17 +605,17 @@ PropertyOpForwarder(JSContext *cx, unsig
 
     JSObject *ptrobj = JSVAL_TO_OBJECT(v);
     Op *popp = static_cast<Op *>(JS_GetPrivate(ptrobj));
 
     v = js::GetFunctionNativeReserved(callee, 1);
 
     JS::RootedValue argval(cx, (argc > 0) ? args.get(0) : JSVAL_VOID);
     JS::RootedId id(cx);
-    if (!JS_ValueToId(cx, v, id.address()))
+    if (!JS_ValueToId(cx, v, &id))
         return false;
     args.rval().set(argval);
     return ApplyPropertyOp<Op>(cx, *popp, obj, id, args.rval());
 }
 
 extern const JSClass PointerHolderClass;
 
 template<typename Op>
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -726,17 +726,17 @@ env_setProperty(JSContext *cx, HandleObj
 {
 /* XXX porting may be easy, but these don't seem to supply setenv by default */
 #if !defined XP_OS2 && !defined SOLARIS
     JSString *valstr;
     JS::Rooted<JSString*> idstr(cx);
     int rv;
 
     RootedValue idval(cx);
-    if (!JS_IdToValue(cx, id, idval.address()))
+    if (!JS_IdToValue(cx, id, &idval))
         return false;
 
     idstr = ToString(cx, idval);
     valstr = ToString(cx, vp);
     if (!idstr || !valstr)
         return false;
     JSAutoByteString name(cx, idstr);
     if (!name)
@@ -809,17 +809,17 @@ env_enumerate(JSContext *cx, HandleObjec
 
 static bool
 env_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
             JS::MutableHandleObject objp)
 {
     JSString *idstr, *valstr;
 
     RootedValue idval(cx);
-    if (!JS_IdToValue(cx, id, idval.address()))
+    if (!JS_IdToValue(cx, id, &idval))
         return false;
 
     idstr = ToString(cx, idval);
     if (!idstr)
         return false;
     JSAutoByteString name(cx, idstr);
     if (!name)
         return false;
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -330,17 +330,17 @@ nsXPCWrappedJSClass::GetNamedPropertyAsV
     RootedValue value(cx);
     if (!XPCStringConvert::ReadableToJSVal(ccx, aName, &buf, &value))
         return NS_ERROR_OUT_OF_MEMORY;
     if (buf)
         buf->AddRef();
 
     RootedId id(cx);
     nsresult rv = NS_OK;
-    if (!JS_ValueToId(cx, value, id.address()) ||
+    if (!JS_ValueToId(cx, value, &id) ||
         !GetNamedPropertyAsVariantRaw(ccx, aJSObj, id, aResult, &rv)) {
         if (NS_FAILED(rv))
             return rv;
         return NS_ERROR_FAILURE;
     }
     return NS_OK;
 }
 
@@ -373,17 +373,17 @@ nsXPCWrappedJSClass::BuildPropertyEnumer
         if (!GetNamedPropertyAsVariantRaw(ccx, aJSObj, idName,
                                           getter_AddRefs(value), &rv)) {
             if (NS_FAILED(rv))
                 return rv;
             return NS_ERROR_FAILURE;
         }
 
         RootedValue jsvalName(cx);
-        if (!JS_IdToValue(cx, idName, jsvalName.address()))
+        if (!JS_IdToValue(cx, idName, &jsvalName))
             return NS_ERROR_FAILURE;
 
         JSString* name = ToString(cx, jsvalName);
         if (!name)
             return NS_ERROR_FAILURE;
 
         size_t length;
         const jschar *chars = JS_GetStringCharsAndLength(cx, name, &length);
--- a/storage/src/mozStorageStatementParams.cpp
+++ b/storage/src/mozStorageStatementParams.cpp
@@ -123,20 +123,22 @@ StatementParams::NewEnumerate(nsIXPConne
       NS_ENSURE_SUCCESS(rv, rv);
 
       // But drop the first character, which is going to be a ':'.
       JSString *jsname = ::JS_NewStringCopyN(aCtx, &(name.get()[1]),
                                              name.Length() - 1);
       NS_ENSURE_TRUE(jsname, NS_ERROR_OUT_OF_MEMORY);
 
       // Set our name.
-      if (!::JS_ValueToId(aCtx, STRING_TO_JSVAL(jsname), _idp)) {
+      JS::Rooted<jsid> id(aCtx);
+      if (!::JS_ValueToId(aCtx, JS::StringValue(jsname), &id)) {
         *_retval = false;
         return NS_OK;
       }
+      *_idp = id;
 
       // And increment our index.
       *_statep = INT_TO_JSVAL(++index);
 
       break;
     }
     case JSENUMERATE_DESTROY:
     {
--- a/toolkit/components/places/History.cpp
+++ b/toolkit/components/places/History.cpp
@@ -226,37 +226,37 @@ namespace {
  * @param [in] aCtx
  *        The JSContext for aValue.
  * @param [out] _array
  *        the JS array.
  * @param [out] _arrayLength
  *        _array's length.
  */
 nsresult
-GetJSArrayFromJSValue(const JS::Value& aValue,
+GetJSArrayFromJSValue(JS::Handle<JS::Value> aValue,
                       JSContext* aCtx,
-                      JSObject** _array,
+                      JS::MutableHandle<JSObject*> _array,
                       uint32_t* _arrayLength) {
   if (aValue.isObjectOrNull()) {
     JS::Rooted<JSObject*> val(aCtx, aValue.toObjectOrNull());
     if (JS_IsArrayObject(aCtx, val)) {
-      *_array = val;
-      (void)JS_GetArrayLength(aCtx, *_array, _arrayLength);
+      _array.set(val);
+      (void)JS_GetArrayLength(aCtx, _array, _arrayLength);
       NS_ENSURE_ARG(*_arrayLength > 0);
       return NS_OK;
     }
   }
-  
+
   // Build a temporary array to store this one item so the code below can
   // just loop.
   *_arrayLength = 1;
-  *_array = JS_NewArrayObject(aCtx, 0, nullptr);
-  NS_ENSURE_TRUE(*_array, NS_ERROR_OUT_OF_MEMORY);
-
-  bool rc = JS_DefineElement(aCtx, *_array, 0, aValue, nullptr, nullptr, 0);
+  _array.set(JS_NewArrayObject(aCtx, 0, nullptr));
+  NS_ENSURE_TRUE(_array, NS_ERROR_OUT_OF_MEMORY);
+
+  bool rc = JS_DefineElement(aCtx, _array, 0, aValue, nullptr, nullptr, 0);
   NS_ENSURE_TRUE(rc, NS_ERROR_UNEXPECTED);
   return NS_OK;
 }
 
 /**
  * Attemps to convert a given js value to a nsIURI object.
  * @param aCtx
  *        The JSContext for aValue.
@@ -2681,17 +2681,17 @@ History::GetPlacesInfo(JS::Handle<JS::Va
                        mozIVisitInfoCallback* aCallback,
                        JSContext* aCtx) {
   nsNavHistory* navHistory = nsNavHistory::GetHistoryService();
   NS_ABORT_IF_FALSE(navHistory, "Could not get nsNavHistory?!");
 
   uint32_t placesIndentifiersLength;
   JS::Rooted<JSObject*> placesIndentifiers(aCtx);
   nsresult rv = GetJSArrayFromJSValue(aPlaceIdentifiers, aCtx,
-                                      placesIndentifiers.address(),
+                                      &placesIndentifiers,
                                       &placesIndentifiersLength);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsTArray<VisitData> placesInfo;
   placesInfo.SetCapacity(placesIndentifiersLength);
   for (uint32_t i = 0; i < placesIndentifiersLength; i++) {
     JS::Rooted<JS::Value> placeIdentifier(aCtx);
     bool rc = JS_GetElement(aCtx, placesIndentifiers, i, &placeIdentifier);
@@ -2749,17 +2749,17 @@ History::UpdatePlaces(JS::Handle<JS::Val
                       mozIVisitInfoCallback* aCallback,
                       JSContext* aCtx)
 {
   NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_UNEXPECTED);
   NS_ENSURE_TRUE(!JSVAL_IS_PRIMITIVE(aPlaceInfos), NS_ERROR_INVALID_ARG);
 
   uint32_t infosLength;
   JS::Rooted<JSObject*> infos(aCtx);
-  nsresult rv = GetJSArrayFromJSValue(aPlaceInfos, aCtx, infos.address(), &infosLength);
+  nsresult rv = GetJSArrayFromJSValue(aPlaceInfos, aCtx, &infos, &infosLength);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsTArray<VisitData> visitData;
   for (uint32_t i = 0; i < infosLength; i++) {
     JS::Rooted<JSObject*> info(aCtx);
     nsresult rv = GetJSObjectFromArray(aCtx, infos, i, info.address());
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/tools/profiler/JSObjectBuilder.cpp
+++ b/tools/profiler/JSObjectBuilder.cpp
@@ -76,17 +76,17 @@ JSObjectBuilder::DefineProperty(JS::Hand
 
 void
 JSObjectBuilder::ArrayPush(JS::HandleObject aArray, int value)
 {
   if (!mOk)
     return;
 
   uint32_t length;
-  mOk = JS_GetArrayLength(mCx, (JSObject*)aArray, &length);
+  mOk = JS_GetArrayLength(mCx, aArray, &length);
 
   if (!mOk)
     return;
 
   JS::RootedValue objval(mCx, INT_TO_JSVAL(value));
   mOk = JS_SetElement(mCx, aArray, length, &objval);
 }
 
@@ -98,17 +98,17 @@ JSObjectBuilder::ArrayPush(JS::HandleObj
 
   JS::RootedString string(mCx, JS_NewStringCopyN(mCx, value, strlen(value)));
   if (!string) {
     mOk = false;
     return;
   }
 
   uint32_t length;
-  mOk = JS_GetArrayLength(mCx, (JSObject*)aArray, &length);
+  mOk = JS_GetArrayLength(mCx, aArray, &length);
 
   if (!mOk)
     return;
 
   JS::RootedValue objval(mCx, STRING_TO_JSVAL(string));
   mOk = JS_SetElement(mCx, aArray, length, &objval);
 }