Bug 1142784, part 2 - Change ProxyHandler::defineProperty() to make the desc argument a non-mutable handle. r=Waldo.
☠☠ backed out by c3638d994edd ☠ ☠
authorJason Orendorff <jorendorff@mozilla.com>
Tue, 17 Feb 2015 11:58:43 -0600
changeset 235004 dcd0af73ac848137d04fa35cc1d111ece51677fe
parent 235003 034f9c8e79ee7a3d54a265324e980c545195c65d
child 235005 e5f0cb31263d820a926a55b288d7ac2951777611
push id14649
push usercbook@mozilla.com
push dateMon, 23 Mar 2015 12:44:57 +0000
treeherderb2g-inbound@509d65f46712 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1142784
milestone39.0a1
Bug 1142784, part 2 - Change ProxyHandler::defineProperty() to make the desc argument a non-mutable handle. r=Waldo.
dom/base/WindowNamedPropertiesHandler.cpp
dom/base/WindowNamedPropertiesHandler.h
dom/base/nsGlobalWindow.cpp
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/bindings/Codegen.py
dom/bindings/DOMJSProxyHandler.cpp
dom/bindings/DOMJSProxyHandler.h
js/ipc/WrapperOwner.cpp
js/ipc/WrapperOwner.h
js/public/Proxy.h
js/src/jsapi-tests/testSetPropertyIgnoringNamedGetter.cpp
js/src/jsfriendapi.h
js/src/jsobj.cpp
js/src/jswrapper.h
js/src/proxy/BaseProxyHandler.cpp
js/src/proxy/CrossCompartmentWrapper.cpp
js/src/proxy/DeadObjectProxy.cpp
js/src/proxy/DeadObjectProxy.h
js/src/proxy/DirectProxyHandler.cpp
js/src/proxy/Proxy.cpp
js/src/proxy/Proxy.h
js/src/proxy/ScriptedDirectProxyHandler.cpp
js/src/proxy/ScriptedDirectProxyHandler.h
js/src/proxy/ScriptedIndirectProxyHandler.cpp
js/src/proxy/ScriptedIndirectProxyHandler.h
js/src/proxy/SecurityWrapper.cpp
js/src/vm/ScopeObject.cpp
js/xpconnect/wrappers/AddonWrapper.cpp
js/xpconnect/wrappers/AddonWrapper.h
js/xpconnect/wrappers/ChromeObjectWrapper.cpp
js/xpconnect/wrappers/ChromeObjectWrapper.h
js/xpconnect/wrappers/FilteringWrapper.cpp
js/xpconnect/wrappers/FilteringWrapper.h
js/xpconnect/wrappers/XrayWrapper.cpp
js/xpconnect/wrappers/XrayWrapper.h
--- a/dom/base/WindowNamedPropertiesHandler.cpp
+++ b/dom/base/WindowNamedPropertiesHandler.cpp
@@ -154,17 +154,17 @@ WindowNamedPropertiesHandler::getOwnProp
   aDesc.setAttributes(JSPROP_ENUMERATE);
   return true;
 }
 
 bool
 WindowNamedPropertiesHandler::defineProperty(JSContext* aCx,
                                              JS::Handle<JSObject*> aProxy,
                                              JS::Handle<jsid> aId,
-                                             JS::MutableHandle<JSPropertyDescriptor> aDesc,
+                                             JS::Handle<JSPropertyDescriptor> aDesc,
                                              JS::ObjectOpResult &result) const
 {
   ErrorResult rv;
   rv.ThrowTypeError(MSG_DEFINEPROPERTY_ON_GSP);
   rv.ReportErrorWithMessage(aCx);
   return false;
 }
 
--- a/dom/base/WindowNamedPropertiesHandler.h
+++ b/dom/base/WindowNamedPropertiesHandler.h
@@ -23,17 +23,17 @@ public:
   getOwnPropDescriptor(JSContext* aCx, JS::Handle<JSObject*> aProxy,
                        JS::Handle<jsid> aId,
                        bool /* unused */,
                        JS::MutableHandle<JSPropertyDescriptor> aDesc)
                        const override;
   virtual bool
   defineProperty(JSContext* aCx, JS::Handle<JSObject*> aProxy,
                  JS::Handle<jsid> aId,
-                 JS::MutableHandle<JSPropertyDescriptor> aDesc,
+                 JS::Handle<JSPropertyDescriptor> aDesc,
                  JS::ObjectOpResult &result) const override;
   virtual bool
   ownPropNames(JSContext* aCx, JS::Handle<JSObject*> aProxy, unsigned flags,
                JS::AutoIdVector& aProps) const override;
   virtual bool
   delete_(JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
           JS::ObjectOpResult &aResult) const override;
   virtual bool
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -616,17 +616,17 @@ public:
   virtual bool getOwnPropertyDescriptor(JSContext* cx,
                                         JS::Handle<JSObject*> proxy,
                                         JS::Handle<jsid> id,
                                         JS::MutableHandle<JSPropertyDescriptor> desc)
                                         const override;
   virtual bool defineProperty(JSContext* cx,
                               JS::Handle<JSObject*> proxy,
                               JS::Handle<jsid> id,
-                              JS::MutableHandle<JSPropertyDescriptor> desc,
+                              JS::Handle<JSPropertyDescriptor> desc,
                               JS::ObjectOpResult &result) const override;
   virtual bool ownPropertyKeys(JSContext *cx,
                                JS::Handle<JSObject*> proxy,
                                JS::AutoIdVector &props) const override;
   virtual bool delete_(JSContext *cx, JS::Handle<JSObject*> proxy,
                        JS::Handle<jsid> id,
                        JS::ObjectOpResult &result) const override;
   virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
@@ -777,17 +777,17 @@ nsOuterWindowProxy::getOwnPropertyDescri
 
   return js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc);
 }
 
 bool
 nsOuterWindowProxy::defineProperty(JSContext* cx,
                                    JS::Handle<JSObject*> proxy,
                                    JS::Handle<jsid> id,
-                                   JS::MutableHandle<JSPropertyDescriptor> desc,
+                                   JS::Handle<JSPropertyDescriptor> desc,
                                    JS::ObjectOpResult &result) const
 {
   int32_t index = GetArrayIndexFromId(cx, id);
   if (IsArrayIndex(index)) {
     // Spec says to Reject whether this is a supported index or not,
     // since we have no indexed setter or indexed creator.  It is up
     // to the caller to decide whether to throw a TypeError.
     return result.failCantDefineWindowElement();
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -1434,17 +1434,17 @@ XrayResolveOwnProperty(JSContext* cx, JS
   }
 
   return true;
 }
 
 bool
 XrayDefineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
                    JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
-                   JS::MutableHandle<JSPropertyDescriptor> desc,
+                   JS::Handle<JSPropertyDescriptor> desc,
                    JS::ObjectOpResult &result, bool *defined)
 {
   if (!js::IsProxy(obj))
     return true;
 
   const DOMProxyHandler* handler = GetDOMProxyHandler(obj);
   return handler->defineProperty(cx, wrapper, id, desc, result, defined);
 }
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -2459,17 +2459,17 @@ XrayResolveOwnProperty(JSContext* cx, JS
  * id and desc are the parameters for the property to be defined.
  * result is the out-parameter indicating success (read it only if
  *     this returns true and also sets *defined to true).
  * defined will be set to true if a property was set as a result of this call.
  */
 bool
 XrayDefineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
                    JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
-                   JS::MutableHandle<JSPropertyDescriptor> desc,
+                   JS::Handle<JSPropertyDescriptor> desc,
                    JS::ObjectOpResult &result,
                    bool *defined);
 
 /**
  * Add to props the property keys of all indexed or named properties of obj and
  * operations, attributes and constants of the interfaces for obj.
  *
  * wrapper is the Xray JS object.
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -10239,17 +10239,17 @@ class CGDOMJSProxyHandler_getOwnPropDesc
 
 class CGDOMJSProxyHandler_defineProperty(ClassMethod):
     def __init__(self, descriptor):
         # The usual convention is to name the ObjectOpResult out-parameter
         # `result`, but that name is a bit overloaded around here.
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'proxy'),
                 Argument('JS::Handle<jsid>', 'id'),
-                Argument('JS::MutableHandle<JSPropertyDescriptor>', 'desc'),
+                Argument('JS::Handle<JSPropertyDescriptor>', 'desc'),
                 Argument('JS::ObjectOpResult&', 'opresult'),
                 Argument('bool*', 'defined')]
         ClassMethod.__init__(self, "defineProperty", "bool", args, virtual=True, override=True, const=True)
         self.descriptor = descriptor
 
     def getBody(self):
         set = ""
 
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -190,17 +190,17 @@ BaseDOMProxyHandler::getOwnPropertyDescr
                                               MutableHandle<JSPropertyDescriptor> desc) const
 {
   return getOwnPropDescriptor(cx, proxy, id, /* ignoreNamedProps = */ false,
                               desc);
 }
 
 bool
 DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
-                                MutableHandle<JSPropertyDescriptor> desc,
+                                Handle<JSPropertyDescriptor> desc,
                                 JS::ObjectOpResult &result, bool *defined) const
 {
   if (desc.hasGetterObject() && desc.setter() == JS_StrictPropertyStub) {
     return result.failGetterOnly();
   }
 
   if (xpc::WrapperFactory::IsXrayWrapper(proxy)) {
     return result.succeed();
@@ -247,17 +247,17 @@ DOMProxyHandler::set(JSContext *cx, Hand
     if (!js::GetObjectProto(cx, proxy, &proto)) {
       return false;
     }
     if (proto && !JS_GetPropertyDescriptorById(cx, proto, id, &desc)) {
       return false;
     }
   }
 
-  return js::SetPropertyIgnoringNamedGetter(cx, proxy, id, vp, receiver, &desc, result);
+  return js::SetPropertyIgnoringNamedGetter(cx, proxy, id, vp, receiver, desc, result);
 }
 
 bool
 DOMProxyHandler::delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
                          JS::Handle<jsid> id, JS::ObjectOpResult &result) const
 {
   JS::Rooted<JSObject*> expando(cx);
   if (!xpc::WrapperFactory::IsXrayWrapper(proxy) && (expando = GetExpandoObject(proxy))) {
--- a/dom/bindings/DOMJSProxyHandler.h
+++ b/dom/bindings/DOMJSProxyHandler.h
@@ -100,24 +100,24 @@ protected:
 class DOMProxyHandler : public BaseDOMProxyHandler
 {
 public:
   MOZ_CONSTEXPR DOMProxyHandler()
     : BaseDOMProxyHandler(&family)
   {}
 
   bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
-                      JS::MutableHandle<JSPropertyDescriptor> desc,
+                      JS::Handle<JSPropertyDescriptor> desc,
                       JS::ObjectOpResult &result) const override
   {
     bool unused;
     return defineProperty(cx, proxy, id, desc, result, &unused);
   }
   virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
-                              JS::MutableHandle<JSPropertyDescriptor> desc,
+                              JS::Handle<JSPropertyDescriptor> desc,
                               JS::ObjectOpResult &result, bool *defined) const;
   bool delete_(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
                JS::ObjectOpResult &result) const override;
   bool preventExtensions(JSContext* cx, JS::Handle<JSObject*> proxy,
                          JS::ObjectOpResult& result) const override;
   bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
                     const override;
   bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
--- a/js/ipc/WrapperOwner.cpp
+++ b/js/ipc/WrapperOwner.cpp
@@ -92,17 +92,17 @@ class CPOWProxyHandler : public BaseProx
 
     virtual bool finalizeInBackground(Value priv) const override {
         return false;
     }
 
     virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
                                           MutableHandle<JSPropertyDescriptor> desc) const override;
     virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                                MutableHandle<JSPropertyDescriptor> desc,
+                                Handle<JSPropertyDescriptor> desc,
                                 ObjectOpResult &result) const override;
     virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
                                  AutoIdVector &props) const override;
     virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id,
                          ObjectOpResult &result) const override;
     virtual bool enumerate(JSContext *cx, HandleObject proxy, MutableHandleObject objp) const override;
     virtual bool preventExtensions(JSContext *cx, HandleObject proxy,
                                    ObjectOpResult &result) const override;
@@ -208,25 +208,25 @@ WrapperOwner::getOwnPropertyDescriptor(J
     if (!ok(cx, status))
         return false;
 
     return toDescriptor(cx, result, desc);
 }
 
 bool
 CPOWProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                                 MutableHandle<JSPropertyDescriptor> desc,
+                                 Handle<JSPropertyDescriptor> desc,
                                  ObjectOpResult &result) const
 {
     FORWARD(defineProperty, (cx, proxy, id, desc, result));
 }
 
 bool
 WrapperOwner::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                             MutableHandle<JSPropertyDescriptor> desc,
+                             Handle<JSPropertyDescriptor> desc,
                              ObjectOpResult &result)
 {
     ObjectId objId = idOf(proxy);
 
     JSIDVariant idVar;
     if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
--- a/js/ipc/WrapperOwner.h
+++ b/js/ipc/WrapperOwner.h
@@ -27,17 +27,17 @@ class WrapperOwner : public virtual Java
     explicit WrapperOwner(JSRuntime *rt);
     bool init();
 
     // Standard internal methods.
     // (The traps should be in the same order like js/Proxy.h)
     bool getOwnPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
                                   JS::MutableHandle<JSPropertyDescriptor> desc);
     bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
-                        JS::MutableHandle<JSPropertyDescriptor> desc,
+                        JS::Handle<JSPropertyDescriptor> desc,
                         JS::ObjectOpResult &result);
     bool ownPropertyKeys(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
     bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
                  JS::ObjectOpResult &result);
     bool preventExtensions(JSContext *cx, JS::HandleObject proxy, JS::ObjectOpResult &result);
     bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
     bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
     bool get(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
--- a/js/public/Proxy.h
+++ b/js/public/Proxy.h
@@ -13,16 +13,17 @@
 
 #include "js/CallNonGenericMethod.h"
 #include "js/Class.h"
 
 namespace js {
 
 using JS::AutoIdVector;
 using JS::CallArgs;
+using JS::Handle;
 using JS::HandleId;
 using JS::HandleObject;
 using JS::HandleValue;
 using JS::IsAcceptableThis;
 using JS::MutableHandle;
 using JS::MutableHandleObject;
 using JS::MutableHandleValue;
 using JS::NativeImpl;
@@ -247,17 +248,17 @@ class JS_FRIEND_API(BaseProxyHandler)
 
     virtual bool enter(JSContext *cx, HandleObject wrapper, HandleId id, Action act,
                        bool *bp) const;
 
     /* Standard internal methods. */
     virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
                                           MutableHandle<JSPropertyDescriptor> desc) const = 0;
     virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                                MutableHandle<JSPropertyDescriptor> desc,
+                                Handle<JSPropertyDescriptor> desc,
                                 ObjectOpResult &result) const = 0;
     virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
                                  AutoIdVector &props) const = 0;
     virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id,
                          ObjectOpResult &result) const = 0;
 
     /*
      * Because [[Enumerate]] is one of the standard traps it should be overridden.
@@ -368,17 +369,17 @@ class JS_FRIEND_API(DirectProxyHandler) 
                                               bool aHasSecurityPolicy = false)
       : BaseProxyHandler(aFamily, aHasPrototype, aHasSecurityPolicy)
     { }
 
     /* Standard internal methods. */
     virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
                                           MutableHandle<JSPropertyDescriptor> desc) const override;
     virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                                MutableHandle<JSPropertyDescriptor> desc,
+                                Handle<JSPropertyDescriptor> desc,
                                 ObjectOpResult &result) const override;
     virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
                                  AutoIdVector &props) const override;
     virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id,
                          ObjectOpResult &result) const override;
     virtual bool enumerate(JSContext *cx, HandleObject proxy,
                            MutableHandleObject objp) const override;
     virtual bool getPrototype(JSContext *cx, HandleObject proxy,
--- a/js/src/jsapi-tests/testSetPropertyIgnoringNamedGetter.cpp
+++ b/js/src/jsapi-tests/testSetPropertyIgnoringNamedGetter.cpp
@@ -28,17 +28,17 @@ class CustomProxyHandler : public Direct
     }
 
     bool set(JSContext *cx, HandleObject proxy, HandleObject receiver,
              HandleId id, MutableHandleValue vp, ObjectOpResult &result) const override
     {
         Rooted<JSPropertyDescriptor> desc(cx);
         if (!DirectProxyHandler::getPropertyDescriptor(cx, proxy, id, &desc))
             return false;
-        return SetPropertyIgnoringNamedGetter(cx, proxy, id, vp, receiver, &desc, result);
+        return SetPropertyIgnoringNamedGetter(cx, proxy, id, vp, receiver, desc, result);
     }
 
   private:
     bool impl(JSContext *cx, HandleObject proxy, HandleId id,
               MutableHandle<JSPropertyDescriptor> desc, bool ownOnly) const
     {
         if (JSID_IS_STRING(id)) {
             bool match;
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -2628,17 +2628,17 @@ ForwardToNative(JSContext *cx, JSNative 
  * except the initial getOwnPropertyDescriptor() call.  The caller must supply
  * that descriptor as the 'ownDesc' parameter.
  *
  * Implemented in proxy/BaseProxyHandler.cpp.
  */
 JS_FRIEND_API(bool)
 SetPropertyIgnoringNamedGetter(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                                JS::MutableHandleValue vp, JS::HandleObject receiver,
-                               JS::MutableHandle<JSPropertyDescriptor> ownDesc,
+                               JS::Handle<JSPropertyDescriptor> ownDesc,
                                JS::ObjectOpResult &result);
 
 JS_FRIEND_API(void)
 ReportErrorWithId(JSContext *cx, const char *msg, JS::HandleId id);
 
 // This function is for one specific use case, please don't use this for anything else!
 extern JS_FRIEND_API(bool)
 ExecuteInGlobalAndReturnScope(JSContext *cx, JS::HandleObject obj, JS::HandleScript script,
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -684,17 +684,17 @@ js::StandardDefineProperty(JSContext *cx
 
     if (obj->is<UnboxedPlainObject>() && !UnboxedPlainObject::convertToNative(cx, obj))
         return false;
 
     if (obj->getOps()->lookupProperty) {
         if (obj->is<ProxyObject>()) {
             Rooted<PropertyDescriptor> pd(cx, desc);
             pd.object().set(obj);
-            return Proxy::defineProperty(cx, obj, id, &pd, result);
+            return Proxy::defineProperty(cx, obj, id, pd, result);
         }
         return result.fail(JSMSG_OBJECT_NOT_EXTENSIBLE);
     }
 
     return DefinePropertyOnObject(cx, obj.as<NativeObject>(), id, desc, result);
 }
 
 bool
--- a/js/src/jswrapper.h
+++ b/js/src/jswrapper.h
@@ -112,17 +112,17 @@ class JS_FRIEND_API(CrossCompartmentWrap
                                                    bool aHasSecurityPolicy = false)
       : Wrapper(CROSS_COMPARTMENT | aFlags, aHasPrototype, aHasSecurityPolicy)
     { }
 
     /* Standard internal methods. */
     virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject wrapper, HandleId id,
                                           MutableHandle<JSPropertyDescriptor> desc) const override;
     virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                                MutableHandle<JSPropertyDescriptor> desc,
+                                Handle<JSPropertyDescriptor> desc,
                                 ObjectOpResult &result) const override;
     virtual bool ownPropertyKeys(JSContext *cx, HandleObject wrapper,
                                  AutoIdVector &props) const override;
     virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id,
                          ObjectOpResult &result) const override;
     virtual bool enumerate(JSContext *cx, HandleObject wrapper, MutableHandleObject objp) const override;
     virtual bool getPrototype(JSContext *cx, HandleObject proxy,
                               MutableHandleObject protop) const override;
@@ -180,17 +180,17 @@ class JS_FRIEND_API(SecurityWrapper) : p
     explicit MOZ_CONSTEXPR SecurityWrapper(unsigned flags, bool hasPrototype = false)
       : Base(flags, hasPrototype, /* hasSecurityPolicy = */ true)
     { }
 
     virtual bool enter(JSContext *cx, HandleObject wrapper, HandleId id, Wrapper::Action act,
                        bool *bp) const override;
 
     virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                                MutableHandle<JSPropertyDescriptor> desc,
+                                Handle<JSPropertyDescriptor> desc,
                                 ObjectOpResult &result) const override;
     virtual bool isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible) const override;
     virtual bool preventExtensions(JSContext *cx, HandleObject wrapper,
                                    ObjectOpResult &result) const override;
     virtual bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
                               ObjectOpResult &result) const override;
     virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded) const override;
 
--- a/js/src/proxy/BaseProxyHandler.cpp
+++ b/js/src/proxy/BaseProxyHandler.cpp
@@ -83,25 +83,27 @@ BaseProxyHandler::set(JSContext *cx, Han
 
     // Steps 2-3.  (Step 1 is a superfluous assertion.)
     Rooted<PropertyDescriptor> ownDesc(cx);
     if (!getOwnPropertyDescriptor(cx, proxy, id, &ownDesc))
         return false;
 
     // The rest is factored out into a separate function with a weird name.
     // This algorithm continues just below.
-    return SetPropertyIgnoringNamedGetter(cx, proxy, id, vp, receiver, &ownDesc, result);
+    return SetPropertyIgnoringNamedGetter(cx, proxy, id, vp, receiver, ownDesc, result);
 }
 
 bool
 js::SetPropertyIgnoringNamedGetter(JSContext *cx, HandleObject obj, HandleId id,
                                    MutableHandleValue vp, HandleObject receiver,
-                                   MutableHandle<PropertyDescriptor> ownDesc,
+                                   Handle<PropertyDescriptor> ownDesc_,
                                    ObjectOpResult &result)
 {
+    Rooted<PropertyDescriptor> ownDesc(cx, ownDesc_);
+
     // Step 4.
     if (!ownDesc.object()) {
         // The spec calls this variable "parent", but that word has weird
         // connotations in SpiderMonkey, so let's go with "proto".
         RootedObject proto(cx);
         if (!GetPrototype(cx, obj, &proto))
             return false;
         if (proto)
--- a/js/src/proxy/CrossCompartmentWrapper.cpp
+++ b/js/src/proxy/CrossCompartmentWrapper.cpp
@@ -44,23 +44,23 @@ CrossCompartmentWrapper::getOwnPropertyD
     PIERCE(cx, wrapper,
            NOTHING,
            Wrapper::getOwnPropertyDescriptor(cx, wrapper, id, desc),
            cx->compartment()->wrap(cx, desc));
 }
 
 bool
 CrossCompartmentWrapper::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                                        MutableHandle<PropertyDescriptor> desc,
+                                        Handle<PropertyDescriptor> desc,
                                         ObjectOpResult &result) const
 {
     Rooted<PropertyDescriptor> desc2(cx, desc);
     PIERCE(cx, wrapper,
            cx->compartment()->wrap(cx, &desc2),
-           Wrapper::defineProperty(cx, wrapper, id, &desc2, result),
+           Wrapper::defineProperty(cx, wrapper, id, desc2, result),
            NOTHING);
 }
 
 bool
 CrossCompartmentWrapper::ownPropertyKeys(JSContext *cx, HandleObject wrapper,
                                          AutoIdVector &props) const
 {
     PIERCE(cx, wrapper,
--- a/js/src/proxy/DeadObjectProxy.cpp
+++ b/js/src/proxy/DeadObjectProxy.cpp
@@ -27,17 +27,17 @@ DeadObjectProxy::getOwnPropertyDescripto
                                           MutableHandle<PropertyDescriptor> desc) const
 {
     JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
     return false;
 }
 
 bool
 DeadObjectProxy::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                                MutableHandle<PropertyDescriptor> desc,
+                                Handle<PropertyDescriptor> desc,
                                 ObjectOpResult &result) const
 {
     JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
     return false;
 }
 
 bool
 DeadObjectProxy::ownPropertyKeys(JSContext *cx, HandleObject wrapper,
--- a/js/src/proxy/DeadObjectProxy.h
+++ b/js/src/proxy/DeadObjectProxy.h
@@ -17,17 +17,17 @@ class DeadObjectProxy : public BaseProxy
     explicit MOZ_CONSTEXPR DeadObjectProxy()
       : BaseProxyHandler(&family)
     { }
 
     /* Standard internal methods. */
     virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject wrapper, HandleId id,
                                           MutableHandle<JSPropertyDescriptor> desc) const override;
     virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                                MutableHandle<JSPropertyDescriptor> desc,
+                                Handle<JSPropertyDescriptor> desc,
                                 ObjectOpResult &result) const override;
     virtual bool ownPropertyKeys(JSContext *cx, HandleObject wrapper,
                                  AutoIdVector &props) const override;
     virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id,
                          ObjectOpResult &result) const override;
     virtual bool enumerate(JSContext *cx, HandleObject wrapper, MutableHandleObject objp) const override;
     virtual bool getPrototype(JSContext *cx, HandleObject proxy,
                               MutableHandleObject protop) const override;
--- a/js/src/proxy/DirectProxyHandler.cpp
+++ b/js/src/proxy/DirectProxyHandler.cpp
@@ -29,17 +29,17 @@ DirectProxyHandler::getOwnPropertyDescri
 {
     assertEnteredPolicy(cx, proxy, id, GET | SET | GET_PROPERTY_DESCRIPTOR);
     RootedObject target(cx, proxy->as<ProxyObject>().target());
     return GetOwnPropertyDescriptor(cx, target, id, desc);
 }
 
 bool
 DirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                                   MutableHandle<PropertyDescriptor> desc,
+                                   Handle<PropertyDescriptor> desc,
                                    ObjectOpResult &result) const
 {
     assertEnteredPolicy(cx, proxy, id, SET);
     RootedObject target(cx, proxy->as<ProxyObject>().target());
     return StandardDefineProperty(cx, target, id, desc, result);
 }
 
 bool
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -129,17 +129,17 @@ Proxy::getOwnPropertyDescriptor(JSContex
     AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET_PROPERTY_DESCRIPTOR, true);
     if (!policy.allowed())
         return policy.returnValue();
     return handler->getOwnPropertyDescriptor(cx, proxy, id, desc);
 }
 
 bool
 Proxy::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                      MutableHandle<PropertyDescriptor> desc, ObjectOpResult &result)
+                      Handle<PropertyDescriptor> desc, ObjectOpResult &result)
 {
     JS_CHECK_RECURSION(cx, return false);
     const BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
     AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true);
     if (!policy.allowed()) {
         if (!policy.returnValue())
             return false;
         return result.succeed();
@@ -564,17 +564,17 @@ js::proxy_DefineProperty(JSContext *cx, 
                          ObjectOpResult &result)
 {
     Rooted<PropertyDescriptor> desc(cx);
     desc.object().set(obj);
     desc.value().set(value);
     desc.setAttributes(attrs);
     desc.setGetter(getter);
     desc.setSetter(setter);
-    return Proxy::defineProperty(cx, obj, id, &desc, result);
+    return Proxy::defineProperty(cx, obj, id, desc, result);
 }
 
 bool
 js::proxy_HasProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *foundp)
 {
     return Proxy::has(cx, obj, id, foundp);
 }
 
--- a/js/src/proxy/Proxy.h
+++ b/js/src/proxy/Proxy.h
@@ -24,17 +24,17 @@ class RegExpGuard;
  */
 class Proxy
 {
   public:
     /* Standard internal methods. */
     static bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
                                          MutableHandle<JSPropertyDescriptor> desc);
     static bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                               MutableHandle<JSPropertyDescriptor> desc, ObjectOpResult &result);
+                               Handle<JSPropertyDescriptor> desc, ObjectOpResult &result);
     static bool ownPropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props);
     static bool delete_(JSContext *cx, HandleObject proxy, HandleId id, ObjectOpResult &result);
     static bool enumerate(JSContext *cx, HandleObject proxy, MutableHandleObject objp);
     static bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible);
     static bool preventExtensions(JSContext *cx, HandleObject proxy, ObjectOpResult &result);
     static bool getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop);
     static bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
                              ObjectOpResult &result);
--- a/js/src/proxy/ScriptedDirectProxyHandler.cpp
+++ b/js/src/proxy/ScriptedDirectProxyHandler.cpp
@@ -545,17 +545,17 @@ ScriptedDirectProxyHandler::getOwnProper
     desc.set(resultDesc);
     desc.object().set(proxy);
     return true;
 }
 
 // ES6 draft rev 31 (15 Jan 2015) 9.5.6 Proxy.[[DefineOwnProperty]](P, Desc)
 bool
 ScriptedDirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                                           MutableHandle<PropertyDescriptor> desc,
+                                           Handle<PropertyDescriptor> desc,
                                            ObjectOpResult &result) const
 {
     // steps 2-4
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
     if (!handler) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
         return false;
     }
--- a/js/src/proxy/ScriptedDirectProxyHandler.h
+++ b/js/src/proxy/ScriptedDirectProxyHandler.h
@@ -17,17 +17,17 @@ class ScriptedDirectProxyHandler : publi
     MOZ_CONSTEXPR ScriptedDirectProxyHandler()
       : BaseProxyHandler(&family)
     { }
 
     /* Standard internal methods. */
     virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
                                           MutableHandle<JSPropertyDescriptor> desc) const override;
     virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                                MutableHandle<JSPropertyDescriptor> desc,
+                                Handle<JSPropertyDescriptor> desc,
                                 ObjectOpResult &result) const override;
     virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
                                  AutoIdVector &props) const override;
     virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id,
                          ObjectOpResult &result) const override;
     virtual bool enumerate(JSContext *cx, HandleObject proxy, MutableHandleObject objp) const override;
 
     /* These two are standard internal methods but aren't implemented to spec yet. */
--- a/js/src/proxy/ScriptedIndirectProxyHandler.cpp
+++ b/js/src/proxy/ScriptedIndirectProxyHandler.cpp
@@ -192,17 +192,17 @@ ScriptedIndirectProxyHandler::getOwnProp
            Trap1(cx, handler, fval, id, &value) &&
            ((value.isUndefined() && IndicatePropertyNotFound(desc)) ||
             (ReturnedValueMustNotBePrimitive(cx, proxy, cx->names().getPropertyDescriptor, value) &&
              ObjectToCompletePropertyDescriptor(cx, proxy, value, desc)));
 }
 
 bool
 ScriptedIndirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                                             MutableHandle<PropertyDescriptor> desc,
+                                             Handle<PropertyDescriptor> desc,
                                              ObjectOpResult &result) const
 {
     RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
     RootedValue fval(cx), value(cx);
     return GetFundamentalTrap(cx, handler, cx->names().defineProperty, &fval) &&
            FromPropertyDescriptor(cx, desc, &value) &&
            Trap2(cx, handler, fval, id, value, &value) &&
            result.succeed();
@@ -388,17 +388,17 @@ ScriptedIndirectProxyHandler::derivedSet
             {
                 return result.succeed();
             }
         }
         desc.value().set(vp.get());
 
         if (descIsOwn) {
             MOZ_ASSERT(desc.object() == proxy);
-            return this->defineProperty(cx, proxy, id, &desc, result);
+            return this->defineProperty(cx, proxy, id, desc, result);
         }
         return DefineProperty(cx, receiver, id, desc.value(), desc.getter(), desc.setter(),
                               desc.attributes(), result);
     }
     desc.object().set(receiver);
     desc.value().set(vp.get());
     desc.setAttributes(JSPROP_ENUMERATE);
     desc.setGetter(nullptr);
--- a/js/src/proxy/ScriptedIndirectProxyHandler.h
+++ b/js/src/proxy/ScriptedIndirectProxyHandler.h
@@ -18,17 +18,17 @@ class ScriptedIndirectProxyHandler : pub
     MOZ_CONSTEXPR ScriptedIndirectProxyHandler()
       : BaseProxyHandler(&family)
     { }
 
     /* Standard internal methods. */
     virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
                                           MutableHandle<JSPropertyDescriptor> desc) const override;
     virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                                MutableHandle<JSPropertyDescriptor> desc,
+                                Handle<JSPropertyDescriptor> desc,
                                 ObjectOpResult &result) const override;
     virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
                                  AutoIdVector &props) const override;
     virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id,
                          ObjectOpResult &result) const override;
     virtual bool enumerate(JSContext *cx, HandleObject proxy,
                            MutableHandleObject objp) const override;
     virtual bool preventExtensions(JSContext *cx, HandleObject proxy,
--- a/js/src/proxy/SecurityWrapper.cpp
+++ b/js/src/proxy/SecurityWrapper.cpp
@@ -98,18 +98,18 @@ bool
 SecurityWrapper<Base>::boxedValue_unbox(JSContext *cx, HandleObject obj, MutableHandleValue vp) const
 {
     vp.setUndefined();
     return true;
 }
 
 template <class Base>
 bool
-SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper,
-                                      HandleId id, MutableHandle<PropertyDescriptor> desc,
+SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
+                                      Handle<PropertyDescriptor> desc,
                                       ObjectOpResult &result) const
 {
     if (desc.getter() || desc.setter()) {
         RootedValue idVal(cx, IdToValue(id));
         JSString *str = ValueToSource(cx, idVal);
         if (!str)
             return false;
         AutoStableStringChars chars(cx);
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -1613,17 +1613,17 @@ class DebugScopeProxy : public BaseProxy
           case ACCESS_GENERIC:
             return SetProperty(cx, scope, scope, id, vp, result);
           default:
             MOZ_CRASH("bad AccessResult");
         }
     }
 
     bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
-                        MutableHandle<PropertyDescriptor> desc,
+                        Handle<PropertyDescriptor> desc,
                         ObjectOpResult &result) const override
     {
         Rooted<ScopeObject*> scope(cx, &proxy->as<DebugScopeObject>().scope());
 
         bool found;
         if (!has(cx, proxy, id, &found))
             return false;
         if (found)
--- a/js/xpconnect/wrappers/AddonWrapper.cpp
+++ b/js/xpconnect/wrappers/AddonWrapper.cpp
@@ -142,18 +142,18 @@ AddonWrapper<Base>::set(JSContext *cx, J
     }
 
     return result.failCantSetInterposed();
 }
 
 template<typename Base>
 bool
 AddonWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                                   MutableHandle<JSPropertyDescriptor> desc,
-                                   JS::ObjectOpResult &result) const
+                                   Handle<JSPropertyDescriptor> desc,
+                                   ObjectOpResult &result) const
 {
     Rooted<JSPropertyDescriptor> interpDesc(cx);
     if (!Interpose(cx, wrapper, nullptr, id, &interpDesc))
         return false;
 
     if (!interpDesc.object())
         return Base::defineProperty(cx, wrapper, id, desc, result);
 
--- a/js/xpconnect/wrappers/AddonWrapper.h
+++ b/js/xpconnect/wrappers/AddonWrapper.h
@@ -23,17 +23,17 @@ template<typename Base>
 class AddonWrapper : public Base {
   public:
     explicit MOZ_CONSTEXPR AddonWrapper(unsigned flags) : Base(flags) { }
 
     virtual bool getOwnPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper,
                                           JS::Handle<jsid> id,
                                           JS::MutableHandle<JSPropertyDescriptor> desc) const override;
     virtual bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
-                                JS::MutableHandle<JSPropertyDescriptor> desc,
+                                JS::Handle<JSPropertyDescriptor> desc,
                                 JS::ObjectOpResult &result) const override;
     virtual bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
                          JS::ObjectOpResult &result) const override;
     virtual bool get(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> receiver,
                      JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
     virtual bool set(JSContext *cx, JS::HandleObject wrapper, JS::HandleObject receiver,
                      JS::HandleId id, JS::MutableHandleValue vp,
                      JS::ObjectOpResult &result) const override;
--- a/js/xpconnect/wrappers/ChromeObjectWrapper.cpp
+++ b/js/xpconnect/wrappers/ChromeObjectWrapper.cpp
@@ -16,17 +16,17 @@ using namespace JS;
 
 namespace xpc {
 
 const ChromeObjectWrapper ChromeObjectWrapper::singleton;
 
 bool
 ChromeObjectWrapper::defineProperty(JSContext *cx, HandleObject wrapper,
                                     HandleId id,
-                                    MutableHandle<JSPropertyDescriptor> desc,
+                                    Handle<JSPropertyDescriptor> desc,
                                     JS::ObjectOpResult &result) const
 {
     if (!AccessCheck::checkPassToPrivilegedCode(cx, wrapper, desc.value()))
         return false;
     return ChromeObjectWrapperBase::defineProperty(cx, wrapper, id, desc, result);
 }
 
 bool
--- a/js/xpconnect/wrappers/ChromeObjectWrapper.h
+++ b/js/xpconnect/wrappers/ChromeObjectWrapper.h
@@ -24,17 +24,17 @@ struct ExposedPropertiesOnly;
 
 class ChromeObjectWrapper : public ChromeObjectWrapperBase
 {
   public:
     MOZ_CONSTEXPR ChromeObjectWrapper() : ChromeObjectWrapperBase(0) {}
 
     virtual bool defineProperty(JSContext *cx, JS::Handle<JSObject*> wrapper,
                                 JS::Handle<jsid> id,
-                                JS::MutableHandle<JSPropertyDescriptor> desc,
+                                JS::Handle<JSPropertyDescriptor> desc,
                                 JS::ObjectOpResult &result) const override;
     virtual bool set(JSContext *cx, JS::Handle<JSObject*> wrapper,
                      JS::Handle<JSObject*> receiver, JS::Handle<jsid> id,
                      JS::MutableHandle<JS::Value> vp,
                      JS::ObjectOpResult &result) const override;
 
     static const ChromeObjectWrapper singleton;
 };
--- a/js/xpconnect/wrappers/FilteringWrapper.cpp
+++ b/js/xpconnect/wrappers/FilteringWrapper.cpp
@@ -229,17 +229,17 @@ CrossOriginXrayWrapper::ownPropertyKeys(
     // the underlying native object may report. Override the inherited trap to
     // avoid passing JSITER_OWNONLY as a flag.
     return SecurityXrayDOM::getPropertyKeys(cx, wrapper, JSITER_HIDDEN, props);
 }
 
 bool
 CrossOriginXrayWrapper::defineProperty(JSContext *cx, JS::Handle<JSObject*> wrapper,
                                        JS::Handle<jsid> id,
-                                       JS::MutableHandle<JSPropertyDescriptor> desc,
+                                       JS::Handle<JSPropertyDescriptor> desc,
                                        JS::ObjectOpResult &result) const
 {
     JS_ReportError(cx, "Permission denied to define property on cross-origin object");
     return false;
 }
 
 bool
 CrossOriginXrayWrapper::delete_(JSContext *cx, JS::Handle<JSObject*> wrapper,
--- a/js/xpconnect/wrappers/FilteringWrapper.h
+++ b/js/xpconnect/wrappers/FilteringWrapper.h
@@ -68,17 +68,17 @@ class CrossOriginXrayWrapper : public Se
   public:
     explicit CrossOriginXrayWrapper(unsigned flags);
 
     virtual bool getOwnPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper,
                                           JS::Handle<jsid> id,
                                           JS::MutableHandle<JSPropertyDescriptor> desc) const override;
     virtual bool defineProperty(JSContext *cx, JS::Handle<JSObject*> wrapper,
                                 JS::Handle<jsid> id,
-                                JS::MutableHandle<JSPropertyDescriptor> desc,
+                                JS::Handle<JSPropertyDescriptor> desc,
                                 JS::ObjectOpResult &result) const override;
     virtual bool ownPropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
                                  JS::AutoIdVector &props) const override;
     virtual bool delete_(JSContext *cx, JS::Handle<JSObject*> wrapper,
                          JS::Handle<jsid> id, JS::ObjectOpResult &result) const override;
 
     virtual bool getPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper,
                                        JS::Handle<jsid> id,
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -588,17 +588,17 @@ JSXrayTraits::delete_(JSContext *cx, Han
         if (desc.object())
             return JS_DeletePropertyById(cx, target, id, result);
     }
     return result.succeed();
 }
 
 bool
 JSXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                             MutableHandle<JSPropertyDescriptor> desc,
+                             Handle<JSPropertyDescriptor> desc,
                              Handle<JSPropertyDescriptor> existingDesc,
                              ObjectOpResult &result,
                              bool *defined)
 {
     *defined = false;
     RootedObject holder(cx, ensureHolder(cx, wrapper));
     if (!holder)
         return false;
@@ -632,19 +632,20 @@ JSXrayTraits::defineProperty(JSContext *
             JS_ReportError(cx, "Not allowed to overwrite accessor property on [Object] or [Array] XrayWrapper");
             return false;
         }
         if (existingDesc.object() && existingDesc.object() != wrapper) {
             JS_ReportError(cx, "Not allowed to shadow non-own Xray-resolved property on [Object] or [Array] XrayWrapper");
             return false;
         }
 
+        Rooted<JSPropertyDescriptor> wrappedDesc(cx, desc);
         JSAutoCompartment ac(cx, target);
-        if (!JS_WrapPropertyDescriptor(cx, desc) ||
-            !JS_DefinePropertyById(cx, target, id, desc, result))
+        if (!JS_WrapPropertyDescriptor(cx, &wrappedDesc) ||
+            !JS_DefinePropertyById(cx, target, id, wrappedDesc, result))
         {
             return false;
         }
         *defined = true;
         return true;
     }
 
     return true;
@@ -1410,17 +1411,17 @@ XPCWrappedNativeXrayTraits::resolveOwnPr
     // in the wrapper's compartment here, not the wrappee.
     MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
 
     return JS_GetPropertyDescriptorById(cx, holder, id, desc);
 }
 
 bool
 XPCWrappedNativeXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                                           MutableHandle<JSPropertyDescriptor> desc,
+                                           Handle<JSPropertyDescriptor> desc,
                                            Handle<JSPropertyDescriptor> existingDesc,
                                            JS::ObjectOpResult &result, bool *defined)
 {
     *defined = false;
     RootedObject holder(cx, singleton.ensureHolder(cx, wrapper));
 
     // Check for an indexed property on a Window.  If that's happening, do
     // nothing but claim we defined it so it won't get added as an expando.
@@ -1571,17 +1572,17 @@ DOMXrayTraits::resolveOwnProperty(JSCont
         return true;
 
     return JS_DefinePropertyById(cx, holder, id, desc) &&
            JS_GetPropertyDescriptorById(cx, holder, id, desc);
 }
 
 bool
 DOMXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                              MutableHandle<JSPropertyDescriptor> desc,
+                              Handle<JSPropertyDescriptor> desc,
                               Handle<JSPropertyDescriptor> existingDesc,
                               JS::ObjectOpResult &result, bool *defined)
 {
     // Check for an indexed property on a Window.  If that's happening, do
     // nothing but claim we defined it so it won't get added as an expando.
     if (IsWindow(cx, wrapper)) {
         int32_t index = GetArrayIndexFromId(cx, id);
         if (IsArrayIndex(index)) {
@@ -1925,17 +1926,17 @@ XrayWrapper<Base, Traits>::getOwnPropert
 // object. Manually re-apply Xrays if necessary.
 //
 // NB: In order to satisfy the invariants of WaiveXray, we need to pass
 // in an object sans security wrapper, which means we need to strip off any
 // potential same-compartment security wrapper that may have been applied
 // to the content object. This is ok, because the the expando object is only
 // ever accessed by code across the compartment boundary.
 static bool
-RecreateLostWaivers(JSContext *cx, JSPropertyDescriptor *orig,
+RecreateLostWaivers(JSContext *cx, const JSPropertyDescriptor *orig,
                     MutableHandle<JSPropertyDescriptor> wrapped)
 {
     // Compute whether the original objects were waived, and implicitly, whether
     // they were objects at all.
     bool valueWasWaived =
         orig->value.isObject() &&
         WrapperFactory::HasWaiveXrayFlag(&orig->value.toObject());
     bool getterWasWaived =
@@ -1970,17 +1971,17 @@ RecreateLostWaivers(JSContext *cx, JSPro
     }
 
     return true;
 }
 
 template <typename Base, typename Traits>
 bool
 XrayWrapper<Base, Traits>::defineProperty(JSContext *cx, HandleObject wrapper,
-                                          HandleId id, MutableHandle<JSPropertyDescriptor> desc,
+                                          HandleId id, Handle<JSPropertyDescriptor> desc,
                                           ObjectOpResult &result) const
 {
     assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::SET);
 
     Rooted<JSPropertyDescriptor> existing_desc(cx);
     if (!JS_GetPropertyDescriptorById(cx, wrapper, id, &existing_desc))
         return false;
 
--- a/js/xpconnect/wrappers/XrayWrapper.h
+++ b/js/xpconnect/wrappers/XrayWrapper.h
@@ -128,17 +128,17 @@ public:
 
     virtual bool resolveNativeProperty(JSContext *cx, JS::HandleObject wrapper,
                                        JS::HandleObject holder, JS::HandleId id,
                                        JS::MutableHandle<JSPropertyDescriptor> desc) override;
     virtual bool resolveOwnProperty(JSContext *cx, const js::Wrapper &jsWrapper, JS::HandleObject wrapper,
                                     JS::HandleObject holder, JS::HandleId id,
                                     JS::MutableHandle<JSPropertyDescriptor> desc) override;
     bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
-                        JS::MutableHandle<JSPropertyDescriptor> desc,
+                        JS::Handle<JSPropertyDescriptor> desc,
                         JS::Handle<JSPropertyDescriptor> existingDesc,
                         JS::ObjectOpResult &result, bool *defined);
     virtual bool enumerateNames(JSContext *cx, JS::HandleObject wrapper, unsigned flags,
                                 JS::AutoIdVector &props);
     static bool call(JSContext *cx, JS::HandleObject wrapper,
                      const JS::CallArgs &args, const js::Wrapper& baseInstance);
     static bool construct(JSContext *cx, JS::HandleObject wrapper,
                           const JS::CallArgs &args, const js::Wrapper& baseInstance);
@@ -180,17 +180,17 @@ public:
         // MOZ_CRASH("resolveNativeProperty hook should never be called with HasPrototype = 1");
         //       but we can't do that yet because XrayUtils::HasNativeProperty calls this.
         return true;
     }
     virtual bool resolveOwnProperty(JSContext *cx, const js::Wrapper &jsWrapper, JS::HandleObject wrapper,
                                     JS::HandleObject holder, JS::HandleId id,
                                     JS::MutableHandle<JSPropertyDescriptor> desc) override;
     bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
-                        JS::MutableHandle<JSPropertyDescriptor> desc,
+                        JS::Handle<JSPropertyDescriptor> desc,
                         JS::Handle<JSPropertyDescriptor> existingDesc,
                         JS::ObjectOpResult &result, bool *defined);
     virtual bool enumerateNames(JSContext *cx, JS::HandleObject wrapper, unsigned flags,
                                 JS::AutoIdVector &props);
     static bool call(JSContext *cx, JS::HandleObject wrapper,
                      const JS::CallArgs &args, const js::Wrapper& baseInstance);
     static bool construct(JSContext *cx, JS::HandleObject wrapper,
                           const JS::CallArgs &args, const js::Wrapper& baseInstance);
@@ -223,17 +223,17 @@ public:
 
     virtual bool resolveOwnProperty(JSContext *cx, const js::Wrapper &jsWrapper, JS::HandleObject wrapper,
                                     JS::HandleObject holder, JS::HandleId id,
                                     JS::MutableHandle<JSPropertyDescriptor> desc) override;
 
     bool delete_(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id, JS::ObjectOpResult &result);
 
     bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
-                        JS::MutableHandle<JSPropertyDescriptor> desc,
+                        JS::Handle<JSPropertyDescriptor> desc,
                         JS::Handle<JSPropertyDescriptor> existingDesc,
                         JS::ObjectOpResult &result, bool *defined);
 
     virtual bool enumerateNames(JSContext *cx, JS::HandleObject wrapper, unsigned flags,
                                 JS::AutoIdVector &props);
 
     static bool call(JSContext *cx, JS::HandleObject wrapper,
                      const JS::CallArgs &args, const js::Wrapper& baseInstance)
@@ -341,17 +341,17 @@ public:
         MOZ_CRASH("resolveNativeProperty hook should never be called with HasPrototype = 1");
     }
 
     virtual bool resolveOwnProperty(JSContext *cx, const js::Wrapper &jsWrapper, JS::HandleObject wrapper,
                                     JS::HandleObject holder, JS::HandleId id,
                                     JS::MutableHandle<JSPropertyDescriptor> desc) override;
 
     bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
-                        JS::MutableHandle<JSPropertyDescriptor> desc,
+                        JS::Handle<JSPropertyDescriptor> desc,
                         JS::Handle<JSPropertyDescriptor> existingDesc,
                         JS::ObjectOpResult &result, bool *defined)
     {
         *defined = false;
         return true;
     }
 
     virtual bool enumerateNames(JSContext *cx, JS::HandleObject wrapper, unsigned flags,
@@ -415,17 +415,17 @@ class XrayWrapper : public Base {
     MOZ_CONSTEXPR explicit XrayWrapper(unsigned flags)
       : Base(flags | WrapperFactory::IS_XRAY_WRAPPER_FLAG, Traits::HasPrototype)
     { };
 
     /* Standard internal methods. */
     virtual bool getOwnPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
                                           JS::MutableHandle<JSPropertyDescriptor> desc) const override;
     virtual bool defineProperty(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
-                                JS::MutableHandle<JSPropertyDescriptor> desc,
+                                JS::Handle<JSPropertyDescriptor> desc,
                                 JS::ObjectOpResult &result) const override;
     virtual bool ownPropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
                                  JS::AutoIdVector &props) const override;
     virtual bool delete_(JSContext *cx, JS::Handle<JSObject*> wrapper,
                          JS::Handle<jsid> id, JS::ObjectOpResult &result) const override;
     virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper,
                            JS::MutableHandle<JSObject*> objp) const override;
     virtual bool getPrototype(JSContext *cx, JS::HandleObject wrapper,