Bug 1142784, part 2 - Change ProxyHandler::defineProperty() to make the desc argument a non-mutable handle. r=Waldo.
authorJason Orendorff <jorendorff@mozilla.com>
Tue, 17 Feb 2015 11:58:43 -0600
changeset 264652 7eca624923335b1ef0952ff3979f4a083d73bf78
parent 264651 3feda0f90a1f84bf94d17b16548199d31d53f93d
child 264653 c8cf2a03ddcf31ea2d4355e52a89037468cd15f9
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1142784
milestone39.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 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
@@ -2461,17 +2461,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
@@ -10241,17 +10241,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
@@ -2623,17 +2623,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
@@ -1612,17 +1612,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,