Bug 1113369, part 7 - [[SetPrototypeOf]] ObjectOpResult support. r=Waldo, r=bz in dom, r=dvander in js/ipc, r=bholley in js/xpconnect.
authorJason Orendorff <jorendorff@mozilla.com>
Thu, 05 Feb 2015 16:36:50 -0600
changeset 261195 41df9affe00f2c266cf6bcc7e7c5b04846090872
parent 261194 e85721e916920f374a065a858e30fd69c1d4f997
child 261196 e9c646b6392f4c5f660f49d2472c190608c1690d
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, bz, dvander, bholley
bugs1113369
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 1113369, part 7 - [[SetPrototypeOf]] ObjectOpResult support. r=Waldo, r=bz in dom, r=dvander in js/ipc, r=bholley in js/xpconnect.
js/ipc/JavaScriptBase.h
js/ipc/PJavaScript.ipdl
js/ipc/WrapperAnswer.cpp
js/ipc/WrapperAnswer.h
js/ipc/WrapperOwner.cpp
js/ipc/WrapperOwner.h
js/public/Proxy.h
js/src/builtin/Object.cpp
js/src/jit/VMFunctions.cpp
js/src/js.msg
js/src/jsapi.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
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/SecurityWrapper.cpp
js/src/vm/Interpreter.cpp
js/src/vm/Xdr.h
js/xpconnect/wrappers/FilteringWrapper.cpp
js/xpconnect/wrappers/FilteringWrapper.h
js/xpconnect/wrappers/WaiveXrayWrapper.cpp
js/xpconnect/wrappers/WaiveXrayWrapper.h
js/xpconnect/wrappers/XrayWrapper.cpp
js/xpconnect/wrappers/XrayWrapper.h
--- a/js/ipc/JavaScriptBase.h
+++ b/js/ipc/JavaScriptBase.h
@@ -91,18 +91,18 @@ class JavaScriptBase : public WrapperOwn
     }
     bool RecvObjectClassIs(const uint64_t &objId, const uint32_t &classValue,
                              bool *result) {
         return Answer::RecvObjectClassIs(ObjectId::deserialize(objId), classValue, result);
     }
     bool RecvClassName(const uint64_t &objId, nsString *result) {
         return Answer::RecvClassName(ObjectId::deserialize(objId), result);
     }
-    bool RecvGetPrototypeOf(const uint64_t &objId, ReturnStatus *rs, ObjectOrNullVariant *result) {
-        return Answer::RecvGetPrototypeOf(ObjectId::deserialize(objId), rs, result);
+    bool RecvGetPrototype(const uint64_t &objId, ReturnStatus *rs, ObjectOrNullVariant *result) {
+        return Answer::RecvGetPrototype(ObjectId::deserialize(objId), rs, result);
     }
     bool RecvRegExpToShared(const uint64_t &objId, ReturnStatus *rs, nsString *source, uint32_t *flags) {
         return Answer::RecvRegExpToShared(ObjectId::deserialize(objId), rs, source, flags);
     }
 
     bool RecvGetPropertyKeys(const uint64_t &objId, const uint32_t &flags,
                              ReturnStatus *rs, nsTArray<JSIDVariant> *ids) {
         return Answer::RecvGetPropertyKeys(ObjectId::deserialize(objId), flags, rs, ids);
@@ -181,19 +181,19 @@ class JavaScriptBase : public WrapperOwn
     }
     bool SendObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
                            bool *result) {
         return Base::SendObjectClassIs(objId.serialize(), classValue, result);
     }
     bool SendClassName(const ObjectId &objId, nsString *result) {
         return Base::SendClassName(objId.serialize(), result);
     }
-    bool SendGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result) {
-        return Base::SendGetPrototypeOf(objId.serialize(), rs, result);
-     }
+    bool SendGetPrototype(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result) {
+        return Base::SendGetPrototype(objId.serialize(), rs, result);
+    }
 
     bool SendRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
                             nsString *source, uint32_t *flags) {
         return Base::SendRegExpToShared(objId.serialize(), rs, source, flags);
     }
 
     bool SendGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
                              ReturnStatus *rs, nsTArray<JSIDVariant> *ids) {
--- a/js/ipc/PJavaScript.ipdl
+++ b/js/ipc/PJavaScript.ipdl
@@ -35,17 +35,17 @@ both:
     prio(high) sync Get(uint64_t objId, ObjectVariant receiver, JSIDVariant id) returns (ReturnStatus rs, JSVariant result);
     prio(high) sync Set(uint64_t objId, ObjectVariant receiver, JSIDVariant id, JSVariant value) returns (ReturnStatus rs, JSVariant result);
 
     prio(high) sync IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
     prio(high) sync CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
     prio(high) sync HasInstance(uint64_t objId, JSVariant v) returns (ReturnStatus rs, bool has);
     prio(high) sync ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result);
     prio(high) sync ClassName(uint64_t objId) returns (nsString name);
-    prio(high) sync GetPrototypeOf(uint64_t objId) returns (ReturnStatus rs, ObjectOrNullVariant result);
+    prio(high) sync GetPrototype(uint64_t objId) returns (ReturnStatus rs, ObjectOrNullVariant result);
     prio(high) sync RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags);
 
     prio(high) sync GetPropertyKeys(uint64_t objId, uint32_t flags) returns (ReturnStatus rs, JSIDVariant[] ids);
     prio(high) sync InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof);
     prio(high) sync DOMInstanceOf(uint64_t objId, int prototypeID, int depth) returns (ReturnStatus rs, bool instanceof);
 
 parent:
     async __delete__();
--- a/js/ipc/WrapperAnswer.cpp
+++ b/js/ipc/WrapperAnswer.cpp
@@ -537,17 +537,17 @@ WrapperAnswer::RecvClassName(const Objec
 
     LOG("%s.className()", ReceiverObj(objId));
 
     *name = NS_ConvertASCIItoUTF16(js::ObjectClassName(cx, obj));
     return true;
 }
 
 bool
-WrapperAnswer::RecvGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result)
+WrapperAnswer::RecvGetPrototype(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result)
 {
     *result = NullVariant();
 
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext *cx = jsapi.cx();
 
@@ -557,17 +557,17 @@ WrapperAnswer::RecvGetPrototypeOf(const 
 
     JS::RootedObject proto(cx);
     if (!JS_GetPrototype(cx, obj, &proto))
         return fail(cx, rs);
 
     if (!toObjectOrNullVariant(cx, proto, result))
         return fail(cx, rs);
 
-    LOG("getPrototypeOf(%s)", ReceiverObj(objId));
+    LOG("getPrototype(%s)", ReceiverObj(objId));
 
     return ok(rs);
 }
 
 bool
 WrapperAnswer::RecvRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
                                   nsString *source, uint32_t *flags)
 {
--- a/js/ipc/WrapperAnswer.h
+++ b/js/ipc/WrapperAnswer.h
@@ -45,17 +45,17 @@ class WrapperAnswer : public virtual Jav
                           bool *result);
     bool RecvCallOrConstruct(const ObjectId &objId, InfallibleTArray<JSParam> &&argv,
                              const bool &construct, ReturnStatus *rs, JSVariant *result,
                              nsTArray<JSParam> *outparams);
     bool RecvHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp);
     bool RecvObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
                            bool *result);
     bool RecvClassName(const ObjectId &objId, nsString *result);
-    bool RecvGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result);
+    bool RecvGetPrototype(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result);
     bool RecvRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source, uint32_t *flags);
 
     bool RecvGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
                              ReturnStatus *rs, nsTArray<JSIDVariant> *ids);
     bool RecvInstanceOf(const ObjectId &objId, const JSIID &iid,
                         ReturnStatus *rs, bool *instanceof);
     bool RecvDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
                            ReturnStatus *rs, bool *instanceof);
--- a/js/ipc/WrapperOwner.cpp
+++ b/js/ipc/WrapperOwner.cpp
@@ -119,17 +119,17 @@ class CPOWProxyHandler : public BaseProx
     virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue,
                                JSContext *cx) const MOZ_OVERRIDE;
     virtual const char* className(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE;
     virtual bool regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g) const MOZ_OVERRIDE;
     virtual void finalize(JSFreeOp *fop, JSObject *proxy) const MOZ_OVERRIDE;
     virtual void objectMoved(JSObject *proxy, const JSObject *old) const MOZ_OVERRIDE;
     virtual bool isCallable(JSObject *obj) const MOZ_OVERRIDE;
     virtual bool isConstructor(JSObject *obj) const MOZ_OVERRIDE;
-    virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const MOZ_OVERRIDE;
+    virtual bool getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const MOZ_OVERRIDE;
 
     static const char family;
     static const CPOWProxyHandler singleton;
 };
 
 const char CPOWProxyHandler::family = 0;
 const CPOWProxyHandler CPOWProxyHandler::singleton;
 
@@ -682,29 +682,29 @@ WrapperOwner::className(JSContext *cx, H
         return "<error>";
 
     LOG_STACK();
 
     return ToNewCString(name);
 }
 
 bool
-CPOWProxyHandler::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject objp) const
+CPOWProxyHandler::getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject objp) const
 {
-    FORWARD(getPrototypeOf, (cx, proxy, objp));
+    FORWARD(getPrototype, (cx, proxy, objp));
 }
 
 bool
-WrapperOwner::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject objp)
+WrapperOwner::getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject objp)
 {
     ObjectId objId = idOf(proxy);
 
     ObjectOrNullVariant val;
     ReturnStatus status;
-    if (!SendGetPrototypeOf(objId, &status, &val))
+    if (!SendGetPrototype(objId, &status, &val))
         return ipcfail(cx);
 
     LOG_STACK();
 
     if (!ok(cx, status))
         return false;
 
     objp.set(fromObjectOrNullVariant(cx, val));
@@ -1025,17 +1025,17 @@ WrapperOwner::fromRemoteObjectVariant(JS
     ObjectId objId = ObjectId::deserialize(objVar.serializedId());
     RootedObject obj(cx, findCPOWById(objId));
     if (!obj) {
 
         // All CPOWs live in the privileged junk scope.
         RootedObject junkScope(cx, xpc::PrivilegedJunkScope());
         JSAutoCompartment ac(cx, junkScope);
         RootedValue v(cx, UndefinedValue());
-        // We need to setLazyProto for the getPrototypeOf hook.
+        // We need to setLazyProto for the getPrototype hook.
         ProxyOptions options;
         options.setLazyProto(true);
         obj = NewProxyObject(cx,
                              &CPOWProxyHandler::singleton,
                              v,
                              nullptr,
                              options);
         if (!obj)
--- a/js/ipc/WrapperOwner.h
+++ b/js/ipc/WrapperOwner.h
@@ -51,17 +51,17 @@ class WrapperOwner : public virtual Java
     bool getPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
                                JS::MutableHandle<JSPropertyDescriptor> desc);
     bool hasOwn(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
     bool getOwnEnumerablePropertyKeys(JSContext *cx, JS::HandleObject proxy,
                                       JS::AutoIdVector &props);
     bool hasInstance(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool *bp);
     bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
     const char* className(JSContext *cx, JS::HandleObject proxy);
-    bool getPrototypeOf(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleObject protop);
+    bool getPrototype(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleObject protop);
 
     bool regexp_toShared(JSContext *cx, JS::HandleObject proxy, js::RegExpGuard *g);
 
     nsresult instanceOf(JSObject *obj, const nsID *id, bool *bp);
 
     bool toString(JSContext *cx, JS::HandleObject callee, JS::CallArgs &args);
 
     /*
@@ -136,17 +136,17 @@ class WrapperOwner : public virtual Java
     virtual bool SendCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
                                      const bool &construct, ReturnStatus *rs, JSVariant *result,
                                      nsTArray<JSParam> *outparams) = 0;
     virtual bool SendHasInstance(const ObjectId &objId, const JSVariant &v,
                                  ReturnStatus *rs, bool *bp) = 0;
     virtual bool SendObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
                                    bool *result) = 0;
     virtual bool SendClassName(const ObjectId &objId, nsString *result) = 0;
-    virtual bool SendGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result) = 0;
+    virtual bool SendGetPrototype(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result) = 0;
     virtual bool SendRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source,
                                     uint32_t *flags) = 0;
 
     virtual bool SendGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
                                      ReturnStatus *rs, nsTArray<JSIDVariant> *ids) = 0;
     virtual bool SendInstanceOf(const ObjectId &objId, const JSIID &iid,
                                 ReturnStatus *rs, bool *instanceof) = 0;
     virtual bool SendDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
--- a/js/public/Proxy.h
+++ b/js/public/Proxy.h
@@ -123,23 +123,23 @@ class JS_FRIEND_API(Wrapper);
  * 1.  Proxies can use the standard prototype mechanism used throughout the
  *     engine. To do so, simply pass a prototype to NewProxyObject() at
  *     creation time. All prototype accesses will then "just work" to treat the
  *     proxy as a "normal" object.
  *
  * 2.  A proxy can implement more complicated prototype semantics (if, for
  *     example, it wants to delegate the prototype lookup to a wrapped object)
  *     by passing Proxy::LazyProto as the prototype at create time. This
- *     guarantees that the getPrototypeOf() handler method will be called every
+ *     guarantees that the getPrototype() handler method will be called every
  *     time the object's prototype chain is accessed.
  *
- *     This system is implemented with two methods: {get,set}PrototypeOf. The
- *     default implementation of setPrototypeOf throws a TypeError. Since it is
+ *     This system is implemented with two methods: {get,set}Prototype. The
+ *     default implementation of setPrototype throws a TypeError. Since it is
  *     not possible to create an object without a sense of prototype chain,
- *     handlers must implement getPrototypeOf if opting in to the dynamic
+ *     handlers must implement getPrototype if opting in to the dynamic
  *     prototype system.
  */
 
 /*
  * BaseProxyHandler is the most generic kind of proxy handler. It does not make
  * any assumptions about the target. Consequently, it does not provide any
  * default implementation for most methods. As a convenience, a few high-level
  * methods, like get() and set(), are given default implementations that work by
@@ -266,22 +266,23 @@ class JS_FRIEND_API(BaseProxyHandler)
      * into an Iterator object.
      */
     virtual bool enumerate(JSContext *cx, HandleObject proxy, MutableHandleObject objp) const = 0;
 
     /*
      * These methods are standard, but the engine does not normally call them.
      * They're opt-in. See "Proxy prototype chains" above.
      *
-     * getPrototypeOf() crashes if called. setPrototypeOf() throws a TypeError.
+     * getPrototype() crashes if called. setPrototype() throws a TypeError.
      */
-    virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const;
-    virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp) const;
+    virtual bool getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const;
+    virtual bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
+                              ObjectOpResult &result) const;
 
-    /* Non-standard but conceptual kin to {g,s}etPrototypeOf, so lives here. */
+    /* Non-standard but conceptual kin to {g,s}etPrototype, so lives here. */
     virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded) const;
 
     virtual bool preventExtensions(JSContext *cx, HandleObject proxy,
                                    ObjectOpResult &result) const = 0;
     virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const = 0;
 
     /*
      * These standard internal methods are implemented, as a convenience, so
@@ -375,20 +376,20 @@ class JS_FRIEND_API(DirectProxyHandler) 
                                 MutableHandle<JSPropertyDescriptor> desc,
                                 ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
                                  AutoIdVector &props) const MOZ_OVERRIDE;
     virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id,
                          ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool enumerate(JSContext *cx, HandleObject proxy,
                            MutableHandleObject objp) const MOZ_OVERRIDE;
-    virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
-                                MutableHandleObject protop) const MOZ_OVERRIDE;
-    virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,
-                                bool *bp) const MOZ_OVERRIDE;
+    virtual bool getPrototype(JSContext *cx, HandleObject proxy,
+                              MutableHandleObject protop) const MOZ_OVERRIDE;
+    virtual bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
+                              ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy,
                                        bool *succeeded) const MOZ_OVERRIDE;
     virtual bool preventExtensions(JSContext *cx, HandleObject proxy,
                                    ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
     virtual bool has(JSContext *cx, HandleObject proxy, HandleId id,
                      bool *bp) const MOZ_OVERRIDE;
     virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -439,35 +439,22 @@ obj_setPrototypeOf(JSContext *cx, unsign
     }
 
     /* Step 4. */
     if (!args[0].isObject()) {
         args.rval().set(args[0]);
         return true;
     }
 
-    /* Step 5-6. */
+    /* Step 5-7. */
     RootedObject obj(cx, &args[0].toObject());
     RootedObject newProto(cx, args[1].toObjectOrNull());
-
-    bool success;
-    if (!SetPrototype(cx, obj, newProto, &success))
+    if (!SetPrototype(cx, obj, newProto))
         return false;
 
-    /* Step 7. */
-    if (!success) {
-        UniquePtr<char[], JS::FreePolicy> bytes(DecompileValueGenerator(cx, JSDVG_SEARCH_STACK,
-                                                                        args[0], NullPtr()));
-        if (!bytes)
-            return false;
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
-                             bytes.get());
-        return false;
-    }
-
     /* Step 8. */
     args.rval().set(args[0]);
     return true;
 }
 
 #if JS_HAS_OBJ_WATCHPOINT
 
 bool
@@ -1026,26 +1013,19 @@ ProtoSetter(JSContext *cx, unsigned argc
 
     /* Do nothing if __proto__ isn't being set to an object or null. */
     if (args.length() == 0 || !args[0].isObjectOrNull()) {
         args.rval().setUndefined();
         return true;
     }
 
     Rooted<JSObject*> newProto(cx, args[0].toObjectOrNull());
-
-    bool success;
-    if (!SetPrototype(cx, obj, newProto, &success))
+    if (!SetPrototype(cx, obj, newProto))
         return false;
 
-    if (!success) {
-        ReportValueError(cx, JSMSG_SETPROTOTYPEOF_FAIL, JSDVG_IGNORE_STACK, thisv, js::NullPtr());
-        return false;
-    }
-
     args.rval().setUndefined();
     return true;
 }
 
 static const JSFunctionSpec object_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,             obj_toSource,                0,0),
 #endif
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -178,22 +178,17 @@ SetConst(JSContext *cx, HandlePropertyNa
 
 bool
 MutatePrototype(JSContext *cx, HandlePlainObject obj, HandleValue value)
 {
     if (!value.isObjectOrNull())
         return true;
 
     RootedObject newProto(cx, value.toObjectOrNull());
-
-    bool succeeded;
-    if (!SetPrototype(cx, obj, newProto, &succeeded))
-        return false;
-    MOZ_ASSERT(succeeded);
-    return true;
+    return SetPrototype(cx, obj, newProto);
 }
 
 bool
 InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
          jsbytecode *pc)
 {
     RootedId id(cx, NameToId(name));
     return InitPropertyOperation(cx, JSOp(*pc), obj, id, value);
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -90,17 +90,19 @@ MSG_DEF(JSMSG_CANT_REDEFINE_ARRAY_LENGTH
 MSG_DEF(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't define array index property past the end of an array with non-writable length")
 MSG_DEF(JSMSG_BAD_GET_SET_FIELD,       1, JSEXN_TYPEERR, "property descriptor's {0} field is neither undefined nor a function")
 MSG_DEF(JSMSG_THROW_TYPE_ERROR,        0, JSEXN_TYPEERR, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them")
 MSG_DEF(JSMSG_NOT_EXPECTED_TYPE,       3, JSEXN_TYPEERR, "{0}: expected {1}, got {2}")
 MSG_DEF(JSMSG_NOT_ITERABLE,            1, JSEXN_TYPEERR, "{0} is not iterable")
 MSG_DEF(JSMSG_ALREADY_HAS_PRAGMA,      2, JSEXN_NONE, "{0} is being assigned a {1}, but already has one")
 MSG_DEF(JSMSG_NEXT_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "iterator.next() returned a non-object value")
 MSG_DEF(JSMSG_WRONG_VALUE,             2, JSEXN_ERR, "expected {0} but found {1}")
-MSG_DEF(JSMSG_SETPROTOTYPEOF_FAIL,     1, JSEXN_TYPEERR, "[[SetPrototypeOf]] failed on {0}")
+MSG_DEF(JSMSG_CANT_SET_PROTO,          0, JSEXN_TYPEERR, "can't set prototype of this object")
+MSG_DEF(JSMSG_CANT_SET_PROTO_OF,       1, JSEXN_TYPEERR, "can't set prototype of {0}")
+MSG_DEF(JSMSG_CANT_SET_PROTO_CYCLE,    0, JSEXN_TYPEERR, "can't set prototype: it would cause a prototype chain cycle")
 MSG_DEF(JSMSG_INVALID_ARG_TYPE,        3, JSEXN_TYPEERR, "Invalid type: {0} can't be a{1} {2}")
 MSG_DEF(JSMSG_TERMINATED,              1, JSEXN_ERR, "Script terminated by timeout at:\n{0}")
 
 // JSON
 MSG_DEF(JSMSG_JSON_BAD_PARSE,          3, JSEXN_SYNTAXERR, "JSON.parse: {0} at line {1} column {2} of the JSON data")
 MSG_DEF(JSMSG_JSON_CYCLIC_VALUE,       1, JSEXN_TYPEERR, "cyclic {0} value")
 
 // Runtime errors
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1787,27 +1787,17 @@ JS_GetPrototype(JSContext *cx, JS::Handl
 
 JS_PUBLIC_API(bool)
 JS_SetPrototype(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<JSObject*> proto)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, proto);
 
-    bool succeeded;
-    if (!SetPrototype(cx, obj, proto, &succeeded))
-        return false;
-
-    if (!succeeded) {
-        RootedValue val(cx, ObjectValue(*obj));
-        ReportValueError(cx, JSMSG_SETPROTOTYPEOF_FAIL, JSDVG_IGNORE_STACK, val, js::NullPtr());
-        return false;
-    }
-
-    return true;
+    return SetPrototype(cx, obj, proto);
 }
 
 JS_PUBLIC_API(bool)
 JS_IsExtensible(JSContext *cx, HandleObject obj, bool *extensible)
 {
     return IsExtensible(cx, obj, extensible);
 }
 
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3082,94 +3082,98 @@ JSObject::reportNotExtensible(JSContext 
                                  JSDVG_IGNORE_STACK, val, js::NullPtr(),
                                  nullptr, nullptr);
 }
 
 
 /*** ES6 standard internal methods ***************************************************************/
 
 bool
-js::SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, bool *succeeded)
+js::SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, JS::ObjectOpResult &result)
 {
     /*
      * If |obj| has a "lazy" [[Prototype]], it is 1) a proxy 2) whose handler's
-     * {get,set}PrototypeOf and setImmutablePrototype methods mediate access to
+     * {get,set}Prototype and setImmutablePrototype methods mediate access to
      * |obj.[[Prototype]]|.  The Proxy subsystem is responsible for responding
      * to such attempts.
      */
     if (obj->hasLazyPrototype()) {
         MOZ_ASSERT(obj->is<ProxyObject>());
-        return Proxy::setPrototypeOf(cx, obj, proto, succeeded);
+        return Proxy::setPrototype(cx, obj, proto, result);
     }
 
     /* Disallow mutation of immutable [[Prototype]]s. */
     if (obj->nonLazyPrototypeIsImmutable()) {
-        *succeeded = false;
-        return true;
+        return result.fail(JSMSG_CANT_SET_PROTO);
     }
 
     /*
      * Disallow mutating the [[Prototype]] on ArrayBuffer objects, which
      * due to their complicated delegate-object shenanigans can't easily
      * have a mutable [[Prototype]].
      */
     if (obj->is<ArrayBufferObject>()) {
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
+        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_PROTO_OF,
                              "incompatible ArrayBuffer");
         return false;
     }
 
     /*
      * Disallow mutating the [[Prototype]] on Typed Objects, per the spec.
      */
     if (obj->is<TypedObject>()) {
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
+        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_PROTO_OF,
                              "incompatible TypedObject");
         return false;
     }
 
     /*
      * Explicitly disallow mutating the [[Prototype]] of Location objects
      * for flash-related security reasons.
      */
     if (!strcmp(obj->getClass()->name, "Location")) {
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
+        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_PROTO_OF,
                              "incompatible Location object");
         return false;
     }
 
     /* ES6 9.1.2 step 5 forbids changing [[Prototype]] if not [[Extensible]]. */
     bool extensible;
     if (!IsExtensible(cx, obj, &extensible))
         return false;
-    if (!extensible) {
-        *succeeded = false;
-        return true;
-    }
+    if (!extensible)
+        return result.fail(JSMSG_CANT_SET_PROTO);
 
     /* ES6 9.1.2 step 6 forbids generating cyclical prototype chains. */
     RootedObject obj2(cx);
     for (obj2 = proto; obj2; ) {
-        if (obj2 == obj) {
-            *succeeded = false;
-            return true;
-        }
+        if (obj2 == obj)
+            return result.fail(JSMSG_CANT_SET_PROTO_CYCLE);
 
         if (!GetPrototype(cx, obj2, &obj2))
             return false;
     }
 
     // Convert unboxed objects to their native representations before changing
     // their prototype/group, as they depend on the group for their layout.
     if (obj->is<UnboxedPlainObject>() && !UnboxedPlainObject::convertToNative(cx, obj))
         return false;
 
     Rooted<TaggedProto> taggedProto(cx, TaggedProto(proto));
-    *succeeded = SetClassAndProto(cx, obj, obj->getClass(), taggedProto);
-    return *succeeded;
+    if (!SetClassAndProto(cx, obj, obj->getClass(), taggedProto))
+        return false;
+
+    return result.succeed();
+}
+
+bool
+js::SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto)
+{
+    ObjectOpResult result;
+    return SetPrototype(cx, obj, proto, result) && result.checkStrict(cx, obj);
 }
 
 bool
 js::PreventExtensions(JSContext *cx, HandleObject obj, ObjectOpResult &result)
 {
     if (obj->is<ProxyObject>())
         return js::Proxy::preventExtensions(cx, obj, result);
 
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -339,17 +339,17 @@ class JSObject : public js::gc::Cell
 
     // Normal objects and a subset of proxies have uninteresting [[Prototype]].
     // For such objects the [[Prototype]] is just a value returned when needed
     // for accesses, or modified in response to requests.  These objects store
     // the [[Prototype]] directly within |obj->type_|.
     //
     // Proxies that don't have such a simple [[Prototype]] instead have a
     // "lazy" [[Prototype]].  Accessing the [[Prototype]] of such an object
-    // requires going through the proxy handler {get,set}PrototypeOf and
+    // requires going through the proxy handler {get,set}Prototype and
     // setImmutablePrototype methods.  This is most commonly useful for proxies
     // that are wrappers around other objects.  If the [[Prototype]] of the
     // underlying object changes, the [[Prototype]] of the wrapper must also
     // simultaneously change.  We implement this by having the handler methods
     // simply delegate to the wrapped object, forwarding its response to the
     // caller.
     //
     // This method returns true if this object has a non-simple [[Prototype]]
@@ -703,22 +703,27 @@ namespace js {
  * instead. See the comment on JSObject::getTaggedProto().
  */
 inline bool
 GetPrototype(JSContext *cx, HandleObject obj, MutableHandleObject protop);
 
 /*
  * ES6 [[SetPrototypeOf]]. Change obj's prototype to proto.
  *
- * Returns false on error, success of operation in outparam. For example, if
+ * Returns false on error, success of operation in *result. For example, if
  * obj is not extensible, its prototype is fixed. js::SetPrototype will return
- * true, because no exception is thrown for this; but *succeeded will be false.
+ * true, because no exception is thrown for this; but *result will be false.
  */
 extern bool
-SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, bool *succeeded);
+SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto,
+             ObjectOpResult &result);
+
+/* Convenience function: like the above, but throw on failure. */
+extern bool
+SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto);
 
 /*
  * ES6 [[IsExtensible]]. Extensible objects can have new properties defined on
  * them. Inextensible objects can't, and their [[Prototype]] slot is fixed as
  * well.
  */
 inline bool
 IsExtensible(ExclusiveContext *cx, HandleObject obj, bool *extensible);
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -128,17 +128,17 @@ JSObject::setGroup(js::ObjectGroup *grou
 
 /*** Standard internal methods *******************************************************************/
 
 inline bool
 js::GetPrototype(JSContext *cx, js::HandleObject obj, js::MutableHandleObject protop)
 {
     if (obj->getTaggedProto().isLazy()) {
         MOZ_ASSERT(obj->is<js::ProxyObject>());
-        return js::Proxy::getPrototypeOf(cx, obj, protop);
+        return js::Proxy::getPrototype(cx, obj, protop);
     } else {
         protop.set(obj->getTaggedProto().toObjectOrNull());
         return true;
     }
 }
 
 inline bool
 js::IsExtensible(ExclusiveContext *cx, HandleObject obj, bool *extensible)
--- a/js/src/jswrapper.h
+++ b/js/src/jswrapper.h
@@ -119,20 +119,20 @@ class JS_FRIEND_API(CrossCompartmentWrap
     virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
                                 MutableHandle<JSPropertyDescriptor> desc,
                                 ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool ownPropertyKeys(JSContext *cx, HandleObject wrapper,
                                  AutoIdVector &props) const MOZ_OVERRIDE;
     virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id,
                          ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool enumerate(JSContext *cx, HandleObject wrapper, MutableHandleObject objp) const MOZ_OVERRIDE;
-    virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
-                                MutableHandleObject protop) const MOZ_OVERRIDE;
-    virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,
-                                bool *bp) const MOZ_OVERRIDE;
+    virtual bool getPrototype(JSContext *cx, HandleObject proxy,
+                              MutableHandleObject protop) const MOZ_OVERRIDE;
+    virtual bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
+                              ObjectOpResult &result) const MOZ_OVERRIDE;
 
     virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy,
                                        bool *succeeded) const MOZ_OVERRIDE;
     virtual bool preventExtensions(JSContext *cx, HandleObject wrapper,
                                    ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible) const MOZ_OVERRIDE;
     virtual bool has(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp) const MOZ_OVERRIDE;
     virtual bool get(JSContext *cx, HandleObject wrapper, HandleObject receiver,
@@ -185,18 +185,18 @@ class JS_FRIEND_API(SecurityWrapper) : p
                        bool *bp) const MOZ_OVERRIDE;
 
     virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
                                 MutableHandle<JSPropertyDescriptor> desc,
                                 ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible) const MOZ_OVERRIDE;
     virtual bool preventExtensions(JSContext *cx, HandleObject wrapper,
                                    ObjectOpResult &result) const MOZ_OVERRIDE;
-    virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,
-                                bool *bp) const MOZ_OVERRIDE;
+    virtual bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
+                              ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE;
 
     virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
                             CallArgs args) const MOZ_OVERRIDE;
     virtual bool objectClassIs(HandleObject obj, ESClassValue classValue,
                                JSContext *cx) const MOZ_OVERRIDE;
     virtual bool regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g) const MOZ_OVERRIDE;
     virtual bool boxedValue_unbox(JSContext *cx, HandleObject proxy, MutableHandleValue vp) const MOZ_OVERRIDE;
--- a/js/src/proxy/BaseProxyHandler.cpp
+++ b/js/src/proxy/BaseProxyHandler.cpp
@@ -333,28 +333,29 @@ BaseProxyHandler::objectMoved(JSObject *
 
 JSObject *
 BaseProxyHandler::weakmapKeyDelegate(JSObject *proxy) const
 {
     return nullptr;
 }
 
 bool
-BaseProxyHandler::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
+BaseProxyHandler::getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
 {
-    MOZ_CRASH("Must override getPrototypeOf with lazy prototype.");
+    MOZ_CRASH("Must override getPrototype with lazy prototype.");
 }
 
 bool
-BaseProxyHandler::setPrototypeOf(JSContext *cx, HandleObject, HandleObject, bool *) const
+BaseProxyHandler::setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
+                               ObjectOpResult &result) const
 {
     // Disallow sets of protos on proxies with lazy protos, but no hook.
     // This keeps us away from the footgun of having the first proto set opt
     // you out of having dynamic protos altogether.
-    JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
+    JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_PROTO_OF,
                          "incompatible Proxy");
     return false;
 }
 
 bool
 BaseProxyHandler::setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded) const
 {
     *succeeded = false;
--- a/js/src/proxy/CrossCompartmentWrapper.cpp
+++ b/js/src/proxy/CrossCompartmentWrapper.cpp
@@ -75,39 +75,39 @@ CrossCompartmentWrapper::delete_(JSConte
 {
     PIERCE(cx, wrapper,
            NOTHING,
            Wrapper::delete_(cx, wrapper, id, result),
            NOTHING);
 }
 
 bool
-CrossCompartmentWrapper::getPrototypeOf(JSContext *cx, HandleObject wrapper,
-                                        MutableHandleObject protop) const
+CrossCompartmentWrapper::getPrototype(JSContext *cx, HandleObject wrapper,
+                                      MutableHandleObject protop) const
 {
     {
         RootedObject wrapped(cx, wrappedObject(wrapper));
         AutoCompartment call(cx, wrapped);
         if (!GetPrototype(cx, wrapped, protop))
             return false;
         if (protop)
             protop->setDelegate(cx);
     }
 
     return cx->compartment()->wrap(cx, protop);
 }
 
 bool
-CrossCompartmentWrapper::setPrototypeOf(JSContext *cx, HandleObject wrapper,
-                                        HandleObject proto, bool *bp) const
+CrossCompartmentWrapper::setPrototype(JSContext *cx, HandleObject wrapper,
+                                      HandleObject proto, ObjectOpResult &result) const
 {
     RootedObject protoCopy(cx, proto);
     PIERCE(cx, wrapper,
            cx->compartment()->wrap(cx, &protoCopy),
-           Wrapper::setPrototypeOf(cx, wrapper, protoCopy, bp),
+           Wrapper::setPrototype(cx, wrapper, protoCopy, result),
            NOTHING);
 }
 
 bool
 CrossCompartmentWrapper::setImmutablePrototype(JSContext *cx, HandleObject wrapper, bool *succeeded) const
 {
     PIERCE(cx, wrapper,
            NOTHING,
--- a/js/src/proxy/DeadObjectProxy.cpp
+++ b/js/src/proxy/DeadObjectProxy.cpp
@@ -58,17 +58,17 @@ DeadObjectProxy::delete_(JSContext *cx, 
 bool
 DeadObjectProxy::enumerate(JSContext *cx, HandleObject wrapper, MutableHandleObject objp) const
 {
     JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
     return false;
 }
 
 bool
-DeadObjectProxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
+DeadObjectProxy::getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
 {
     protop.set(nullptr);
     return true;
 }
 
 bool
 DeadObjectProxy::preventExtensions(JSContext *cx, HandleObject proxy, ObjectOpResult &result) const
 {
--- a/js/src/proxy/DeadObjectProxy.h
+++ b/js/src/proxy/DeadObjectProxy.h
@@ -24,18 +24,18 @@ class DeadObjectProxy : public BaseProxy
     virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
                                 MutableHandle<JSPropertyDescriptor> desc,
                                 ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool ownPropertyKeys(JSContext *cx, HandleObject wrapper,
                                  AutoIdVector &props) const MOZ_OVERRIDE;
     virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id,
                          ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool enumerate(JSContext *cx, HandleObject wrapper, MutableHandleObject objp) const MOZ_OVERRIDE;
-    virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
-                                MutableHandleObject protop) const MOZ_OVERRIDE;
+    virtual bool getPrototype(JSContext *cx, HandleObject proxy,
+                              MutableHandleObject protop) const MOZ_OVERRIDE;
     virtual bool preventExtensions(JSContext *cx, HandleObject proxy,
                                    ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
     virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
     virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
 
     /* SpiderMonkey extensions. */
     virtual bool getPropertyDescriptor(JSContext *cx, HandleObject wrapper, HandleId id,
--- a/js/src/proxy/DirectProxyHandler.cpp
+++ b/js/src/proxy/DirectProxyHandler.cpp
@@ -107,27 +107,28 @@ DirectProxyHandler::hasInstance(JSContex
     RootedObject target(cx, proxy->as<ProxyObject>().target());
     if (!HasInstance(cx, target, v, &b))
         return false;
     *bp = !!b;
     return true;
 }
 
 bool
-DirectProxyHandler::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
+DirectProxyHandler::getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
 {
     RootedObject target(cx, proxy->as<ProxyObject>().target());
     return GetPrototype(cx, target, protop);
 }
 
 bool
-DirectProxyHandler::setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp) const
+DirectProxyHandler::setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
+                                 ObjectOpResult &result) const
 {
     RootedObject target(cx, proxy->as<ProxyObject>().target());
-    return SetPrototype(cx, target, proto, bp);
+    return SetPrototype(cx, target, proto, result);
 }
 
 bool
 DirectProxyHandler::setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded) const
 {
     RootedObject target(cx, proxy->as<ProxyObject>().target());
     return SetImmutablePrototype(cx, target, succeeded);
 }
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -189,29 +189,29 @@ js::AppendUnique(JSContext *cx, AutoIdVe
         }
         if (unique)
             uniqueOthers.append(others[i]);
     }
     return base.appendAll(uniqueOthers);
 }
 
 /* static */ bool
-Proxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject proto)
+Proxy::getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject proto)
 {
     MOZ_ASSERT(proxy->hasLazyPrototype());
     JS_CHECK_RECURSION(cx, return false);
-    return proxy->as<ProxyObject>().handler()->getPrototypeOf(cx, proxy, proto);
+    return proxy->as<ProxyObject>().handler()->getPrototype(cx, proxy, proto);
 }
 
 /* static */ bool
-Proxy::setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp)
+Proxy::setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto, ObjectOpResult &result)
 {
     MOZ_ASSERT(proxy->hasLazyPrototype());
     JS_CHECK_RECURSION(cx, return false);
-    return proxy->as<ProxyObject>().handler()->setPrototypeOf(cx, proxy, proto, bp);
+    return proxy->as<ProxyObject>().handler()->setPrototype(cx, proxy, proto, result);
 }
 
 /* static */ bool
 Proxy::setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded)
 {
     JS_CHECK_RECURSION(cx, return false);
     const BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
     return handler->setImmutablePrototype(cx, proxy, succeeded);
--- a/js/src/proxy/Proxy.h
+++ b/js/src/proxy/Proxy.h
@@ -30,18 +30,19 @@ class Proxy
                                          MutableHandle<JSPropertyDescriptor> desc);
     static bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
                                MutableHandle<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 getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop);
-    static bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp);
+    static bool getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop);
+    static bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
+                             ObjectOpResult &result);
     static bool setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded);
     static bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp);
     static bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
                     MutableHandleValue vp);
     static bool set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
                     MutableHandleValue vp, ObjectOpResult &result);
     static bool call(JSContext *cx, HandleObject proxy, const CallArgs &args);
     static bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args);
--- a/js/src/proxy/ScriptedDirectProxyHandler.cpp
+++ b/js/src/proxy/ScriptedDirectProxyHandler.cpp
@@ -258,43 +258,43 @@ ArrayToIdVector(JSContext *cx, HandleObj
             return false;
         }
     }
 
     // step n
     return true;
 }
 
-// ES6 implements both getPrototypeOf and setPrototypeOf traps. We don't have them yet (see bug
+// ES6 implements both getPrototype and setPrototype traps. We don't have them yet (see bug
 // 888969). For now, use these, to account for proxy revocation.
 bool
-ScriptedDirectProxyHandler::getPrototypeOf(JSContext *cx, HandleObject proxy,
-                                           MutableHandleObject protop) const
+ScriptedDirectProxyHandler::getPrototype(JSContext *cx, HandleObject proxy,
+                                         MutableHandleObject protop) const
 {
     RootedObject target(cx, proxy->as<ProxyObject>().target());
     // Though handler is used elsewhere, spec mandates that both get set to null.
     if (!target) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
         return false;
     }
 
-    return DirectProxyHandler::getPrototypeOf(cx, proxy, protop);
+    return DirectProxyHandler::getPrototype(cx, proxy, protop);
 }
 
 bool
-ScriptedDirectProxyHandler::setPrototypeOf(JSContext *cx, HandleObject proxy,
-                                           HandleObject proto, bool *bp) const
+ScriptedDirectProxyHandler::setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
+                                         ObjectOpResult &result) const
 {
     RootedObject target(cx, proxy->as<ProxyObject>().target());
     if (!target) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
         return false;
     }
 
-    return DirectProxyHandler::setPrototypeOf(cx, proxy, proto, bp);
+    return DirectProxyHandler::setPrototype(cx, proxy, proto, result);
 }
 
 // Not yet part of ES6, but hopefully to be standards-tracked -- and needed to
 // handle revoked proxies in any event.
 bool
 ScriptedDirectProxyHandler::setImmutablePrototype(JSContext *cx, HandleObject proxy,
                                                   bool *succeeded) const
 {
@@ -401,17 +401,17 @@ ScriptedDirectProxyHandler::isExtensible
        return false;
     }
 
     // step 13
     *extensible = booleanTrapResult;
     return true;
 }
 
-// Corresponds to the "standard" property descriptor getOwn getPrototypeOf dance. It's so explicit
+// Corresponds to the "standard" property descriptor getOwn/getPrototype dance. It's so explicit
 // here because ScriptedDirectProxyHandler allows script visibility for this operation.
 bool
 ScriptedDirectProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
                                                   MutableHandle<PropertyDescriptor> desc) const
 {
     JS_CHECK_RECURSION(cx, return false);
 
     if (!GetOwnPropertyDescriptor(cx, proxy, id, desc))
--- a/js/src/proxy/ScriptedDirectProxyHandler.h
+++ b/js/src/proxy/ScriptedDirectProxyHandler.h
@@ -26,20 +26,20 @@ class ScriptedDirectProxyHandler : publi
                                 ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
                                  AutoIdVector &props) const MOZ_OVERRIDE;
     virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id,
                          ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool enumerate(JSContext *cx, HandleObject proxy, MutableHandleObject objp) const MOZ_OVERRIDE;
 
     /* These two are standard internal methods but aren't implemented to spec yet. */
-    virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
-                                MutableHandleObject protop) const MOZ_OVERRIDE;
-    virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,
-                                bool *bp) const MOZ_OVERRIDE;
+    virtual bool getPrototype(JSContext *cx, HandleObject proxy,
+                              MutableHandleObject protop) const MOZ_OVERRIDE;
+    virtual bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
+                              ObjectOpResult &result) const MOZ_OVERRIDE;
     /* Non-standard, but needed to handle revoked proxies. */
     virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy,
                                        bool *succeeded) const MOZ_OVERRIDE;
 
     virtual bool preventExtensions(JSContext *cx, HandleObject proxy,
                                    ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
 
--- a/js/src/proxy/SecurityWrapper.cpp
+++ b/js/src/proxy/SecurityWrapper.cpp
@@ -27,18 +27,18 @@ SecurityWrapper<Base>::nativeCall(JSCont
                                   CallArgs args) const
 {
     JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_UNWRAP_DENIED);
     return false;
 }
 
 template <class Base>
 bool
-SecurityWrapper<Base>::setPrototypeOf(JSContext *cx, HandleObject wrapper,
-                                      HandleObject proto, bool *bp) const
+SecurityWrapper<Base>::setPrototype(JSContext *cx, HandleObject wrapper, HandleObject proto,
+                                    ObjectOpResult &result) const
 {
     JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_UNWRAP_DENIED);
     return false;
 }
 
 template <class Base>
 bool
 SecurityWrapper<Base>::setImmutablePrototype(JSContext *cx, HandleObject wrapper,
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -3202,20 +3202,18 @@ CASE(JSOP_MUTATEPROTO)
     if (REGS.sp[-1].isObjectOrNull()) {
         RootedObject &newProto = rootObject1;
         rootObject1 = REGS.sp[-1].toObjectOrNull();
 
         RootedObject &obj = rootObject0;
         obj = &REGS.sp[-2].toObject();
         MOZ_ASSERT(obj->is<PlainObject>());
 
-        bool succeeded;
-        if (!SetPrototype(cx, obj, newProto, &succeeded))
+        if (!SetPrototype(cx, obj, newProto))
             goto error;
-        MOZ_ASSERT(succeeded);
     }
 
     REGS.sp--;
 }
 END_CASE(JSOP_MUTATEPROTO)
 
 CASE(JSOP_INITPROP)
 CASE(JSOP_INITLOCKEDPROP)
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -24,21 +24,21 @@ namespace js {
  * versions.  If deserialization fails, the data should be invalidated if
  * possible.
  *
  * When you change this, run make_opcode_doc.py and copy the new output into
  * this wiki page:
  *
  *  https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
  */
-static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 244;
+static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 245;
 static const uint32_t XDR_BYTECODE_VERSION =
     uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
 
-static_assert(JSErr_Limit == 381,
+static_assert(JSErr_Limit == 383,
               "GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
               "removed MSG_DEFs from js.msg, you should increment "
               "XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "
               "expected JSErr_Limit value.");
 
 class XDRBuffer {
   public:
     explicit XDRBuffer(JSContext *cx)
--- a/js/xpconnect/wrappers/FilteringWrapper.cpp
+++ b/js/xpconnect/wrappers/FilteringWrapper.cpp
@@ -159,18 +159,18 @@ bool
 FilteringWrapper<Base, Policy>::defaultValue(JSContext *cx, HandleObject obj,
                                              JSType hint, MutableHandleValue vp) const
 {
     return Base::defaultValue(cx, obj, hint, vp);
 }
 
 template <typename Base, typename Policy>
 bool
-FilteringWrapper<Base, Policy>::getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
-                                               JS::MutableHandleObject protop) const
+FilteringWrapper<Base, Policy>::getPrototype(JSContext *cx, JS::HandleObject wrapper,
+                                             JS::MutableHandleObject protop) const
 {
     // Filtering wrappers do not allow access to the prototype.
     protop.set(nullptr);
     return true;
 }
 
 template <typename Base, typename Policy>
 bool
--- a/js/xpconnect/wrappers/FilteringWrapper.h
+++ b/js/xpconnect/wrappers/FilteringWrapper.h
@@ -48,18 +48,18 @@ class FilteringWrapper : public Base {
                            const JS::CallArgs &args) const MOZ_OVERRIDE;
 
     virtual bool nativeCall(JSContext *cx, JS::IsAcceptableThis test, JS::NativeImpl impl,
                             JS::CallArgs args) const MOZ_OVERRIDE;
 
     virtual bool defaultValue(JSContext *cx, JS::Handle<JSObject*> obj, JSType hint,
                               JS::MutableHandleValue vp) const MOZ_OVERRIDE;
 
-    virtual bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
-                                JS::MutableHandleObject protop) const MOZ_OVERRIDE;
+    virtual bool getPrototype(JSContext *cx, JS::HandleObject wrapper,
+                              JS::MutableHandleObject protop) const MOZ_OVERRIDE;
 
     static const FilteringWrapper singleton;
 };
 
 /*
  * The HTML5 spec mandates very particular object behavior for cross-origin DOM
  * objects (Window and Location), some of which runs contrary to the way that
  * other XrayWrappers behave. We use this class to implement those semantics.
--- a/js/xpconnect/wrappers/WaiveXrayWrapper.cpp
+++ b/js/xpconnect/wrappers/WaiveXrayWrapper.cpp
@@ -86,15 +86,15 @@ bool
 WaiveXrayWrapper::nativeCall(JSContext *cx, JS::IsAcceptableThis test,
                              JS::NativeImpl impl, JS::CallArgs args) const
 {
     return CrossCompartmentWrapper::nativeCall(cx, test, impl, args) &&
            WrapperFactory::WaiveXrayAndWrap(cx, args.rval());
 }
 
 bool
-WaiveXrayWrapper::getPrototypeOf(JSContext *cx, HandleObject wrapper, MutableHandleObject protop) const
+WaiveXrayWrapper::getPrototype(JSContext *cx, HandleObject wrapper, MutableHandleObject protop) const
 {
-    return CrossCompartmentWrapper::getPrototypeOf(cx, wrapper, protop) &&
+    return CrossCompartmentWrapper::getPrototype(cx, wrapper, protop) &&
            (!protop || WrapperFactory::WaiveXrayAndWrap(cx, protop));
 }
 
 }
--- a/js/xpconnect/wrappers/WaiveXrayWrapper.h
+++ b/js/xpconnect/wrappers/WaiveXrayWrapper.h
@@ -15,18 +15,18 @@ namespace xpc {
 
 class WaiveXrayWrapper : public js::CrossCompartmentWrapper {
   public:
     explicit MOZ_CONSTEXPR WaiveXrayWrapper(unsigned flags) : js::CrossCompartmentWrapper(flags) { }
 
     virtual bool getOwnPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper,
                                           JS::Handle<jsid> id,
                                           JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
-    virtual bool getPrototypeOf(JSContext *cx, JS::Handle<JSObject*> wrapper,
-                                JS::MutableHandle<JSObject*> protop) const MOZ_OVERRIDE;
+    virtual bool getPrototype(JSContext *cx, JS::Handle<JSObject*> wrapper,
+                              JS::MutableHandle<JSObject*> protop) const MOZ_OVERRIDE;
     virtual bool get(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> receiver,
                      JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const MOZ_OVERRIDE;
     virtual bool call(JSContext *cx, JS::Handle<JSObject*> wrapper,
                       const JS::CallArgs &args) const MOZ_OVERRIDE;
     virtual bool construct(JSContext *cx, JS::Handle<JSObject*> wrapper,
                            const JS::CallArgs &args) const MOZ_OVERRIDE;
 
     virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -1628,19 +1628,19 @@ DOMXrayTraits::construct(JSContext *cx, 
             return false;
     }
     if (!args.rval().isObject() || !JS_WrapValue(cx, args.rval()))
         return false;
     return true;
 }
 
 bool
-DOMXrayTraits::getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
-                              JS::HandleObject target,
-                              JS::MutableHandleObject protop)
+DOMXrayTraits::getPrototype(JSContext *cx, JS::HandleObject wrapper,
+                            JS::HandleObject target,
+                            JS::MutableHandleObject protop)
 {
     return mozilla::dom::XrayGetNativeProto(cx, target, protop);
 }
 
 void
 DOMXrayTraits::preserveWrapper(JSObject *target)
 {
     nsISupports *identity = mozilla::dom::UnwrapDOMObjectToISupports(target);
@@ -2138,71 +2138,70 @@ XrayWrapper<Base, Traits>::defaultValue(
     //
     // NB: We don't have to worry about things with special [[DefaultValue]]
     // behavior like Date because we'll never have an XrayWrapper to them.
     return OrdinaryToPrimitive(cx, wrapper, hint, vp);
 }
 
 template <typename Base, typename Traits>
 bool
-XrayWrapper<Base, Traits>::getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
-                                          JS::MutableHandleObject protop) const
+XrayWrapper<Base, Traits>::getPrototype(JSContext *cx, JS::HandleObject wrapper,
+                                        JS::MutableHandleObject protop) const
 {
     // We really only want this override for non-SecurityWrapper-inheriting
     // |Base|. But doing that statically with templates requires partial method
     // specializations (and therefore a helper class), which is all more trouble
     // than it's worth. Do a dynamic check.
     if (Base::hasSecurityPolicy())
-        return Base::getPrototypeOf(cx, wrapper, protop);
+        return Base::getPrototype(cx, wrapper, protop);
 
     RootedObject target(cx, Traits::getTargetObject(wrapper));
     RootedObject expando(cx);
     if (!Traits::singleton.getExpandoObject(cx, target, wrapper, &expando))
         return false;
 
     // We want to keep the Xray's prototype distinct from that of content, but
     // only if there's been a set. If there's not an expando, or the expando
     // slot is |undefined|, hand back the default proto, appropriately wrapped.
 
     RootedValue v(cx);
     if (expando) {
         JSAutoCompartment ac(cx, expando);
         v = JS_GetReservedSlot(expando, JSSLOT_EXPANDO_PROTOTYPE);
     }
     if (v.isUndefined())
-        return getPrototypeOfHelper(cx, wrapper, target, protop);
+        return getPrototypeHelper(cx, wrapper, target, protop);
 
     protop.set(v.toObjectOrNull());
     return JS_WrapObject(cx, protop);
 }
 
 template <typename Base, typename Traits>
 bool
-XrayWrapper<Base, Traits>::setPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
-                                          JS::HandleObject proto, bool *bp) const
+XrayWrapper<Base, Traits>::setPrototype(JSContext *cx, JS::HandleObject wrapper,
+                                        JS::HandleObject proto, JS::ObjectOpResult &result) const
 {
     // Do this only for non-SecurityWrapper-inheriting |Base|. See the comment
-    // in getPrototypeOf().
+    // in getPrototype().
     if (Base::hasSecurityPolicy())
-        return Base::setPrototypeOf(cx, wrapper, proto, bp);
+        return Base::setPrototype(cx, wrapper, proto, result);
 
     RootedObject target(cx, Traits::getTargetObject(wrapper));
     RootedObject expando(cx, Traits::singleton.ensureExpandoObject(cx, wrapper, target));
     if (!expando)
         return false;
 
     // The expando lives in the target's compartment, so do our installation there.
     JSAutoCompartment ac(cx, target);
 
     RootedValue v(cx, ObjectOrNullValue(proto));
     if (!JS_WrapValue(cx, &v))
         return false;
     JS_SetReservedSlot(expando, JSSLOT_EXPANDO_PROTOTYPE, v);
-    *bp = true;
-    return true;
+    return result.succeed();
 }
 
 template <typename Base, typename Traits>
 bool
 XrayWrapper<Base, Traits>::setImmutablePrototype(JSContext *cx, JS::HandleObject wrapper,
                                                  bool *succeeded) const
 {
     // For now, lacking an obvious place to store a bit, prohibit making an
--- a/js/xpconnect/wrappers/XrayWrapper.h
+++ b/js/xpconnect/wrappers/XrayWrapper.h
@@ -182,19 +182,19 @@ public:
                         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);
 
-    static bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
-                               JS::HandleObject target,
-                               JS::MutableHandleObject protop);
+    static bool getPrototype(JSContext *cx, JS::HandleObject wrapper,
+                             JS::HandleObject target,
+                             JS::MutableHandleObject protop);
 
     virtual void preserveWrapper(JSObject *target) MOZ_OVERRIDE;
 
     virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
 
     static DOMXrayTraits singleton;
 };
 
@@ -248,19 +248,19 @@ public:
         if (self.getProtoKey(holder) == JSProto_Function)
             return baseInstance.construct(cx, wrapper, args);
 
         JS::RootedValue v(cx, JS::ObjectValue(*wrapper));
         js::ReportIsNotFunction(cx, v);
         return false;
     }
 
-    bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
-                        JS::HandleObject target,
-                        JS::MutableHandleObject protop)
+    bool getPrototype(JSContext *cx, JS::HandleObject wrapper,
+                      JS::HandleObject target,
+                      JS::MutableHandleObject protop)
     {
         JS::RootedObject holder(cx, ensureHolder(cx, wrapper));
         JSProtoKey key = getProtoKey(holder);
         if (isPrototype(holder)) {
             JSProtoKey parentKey = js::ParentKeyForStandardClass(key);
             if (parentKey == JSProto_Null) {
                 protop.set(nullptr);
                 return true;
@@ -363,19 +363,19 @@ public:
     static bool construct(JSContext *cx, JS::HandleObject wrapper,
                           const JS::CallArgs &args, const js::Wrapper& baseInstance)
     {
         JS::RootedValue v(cx, JS::ObjectValue(*wrapper));
         js::ReportIsNotFunction(cx, v);
         return false;
     }
 
-    bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
-                        JS::HandleObject target,
-                        JS::MutableHandleObject protop)
+    bool getPrototype(JSContext *cx, JS::HandleObject wrapper,
+                      JS::HandleObject target,
+                      JS::MutableHandleObject protop)
     {
         // Opaque wrappers just get targetGlobal.Object.prototype as their
         // prototype. This is preferable to using a null prototype because it
         // lets things like |toString| and |__proto__| work.
         {
             JSAutoCompartment ac(cx, target);
             if (!JS_GetClassPrototype(cx, JSProto_Object, protop))
                 return false;
@@ -415,20 +415,20 @@ class XrayWrapper : public Base {
                                 JS::MutableHandle<JSPropertyDescriptor> desc,
                                 JS::ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool ownPropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
                                  JS::AutoIdVector &props) const MOZ_OVERRIDE;
     virtual bool delete_(JSContext *cx, JS::Handle<JSObject*> wrapper,
                          JS::Handle<jsid> id, JS::ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper,
                            JS::MutableHandle<JSObject*> objp) const MOZ_OVERRIDE;
-    virtual bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
-                                JS::MutableHandleObject protop) const MOZ_OVERRIDE;
-    virtual bool setPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
-                                JS::HandleObject proto, bool *bp) const MOZ_OVERRIDE;
+    virtual bool getPrototype(JSContext *cx, JS::HandleObject wrapper,
+                              JS::MutableHandleObject protop) const MOZ_OVERRIDE;
+    virtual bool setPrototype(JSContext *cx, JS::HandleObject wrapper,
+                              JS::HandleObject proto, JS::ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool setImmutablePrototype(JSContext *cx, JS::HandleObject wrapper,
                                        bool *succeeded) const MOZ_OVERRIDE;
     virtual bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> wrapper,
                                    JS::ObjectOpResult &result) const MOZ_OVERRIDE;
     virtual bool isExtensible(JSContext *cx, JS::Handle<JSObject*> wrapper, bool *extensible) const MOZ_OVERRIDE;
     virtual bool has(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
                      bool *bp) const MOZ_OVERRIDE;
     virtual bool get(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> receiver,
@@ -454,33 +454,33 @@ class XrayWrapper : public Base {
                               JSType hint, JS::MutableHandleValue vp)
                               const MOZ_OVERRIDE;
 
     static const XrayWrapper singleton;
 
   private:
     template <bool HasPrototype>
     typename mozilla::EnableIf<HasPrototype, bool>::Type
-        getPrototypeOfHelper(JSContext *cx, JS::HandleObject wrapper,
-                             JS::HandleObject target, JS::MutableHandleObject protop) const
+        getPrototypeHelper(JSContext *cx, JS::HandleObject wrapper,
+                           JS::HandleObject target, JS::MutableHandleObject protop) const
     {
-        return Traits::singleton.getPrototypeOf(cx, wrapper, target, protop);
+        return Traits::singleton.getPrototype(cx, wrapper, target, protop);
     }
     template <bool HasPrototype>
     typename mozilla::EnableIf<!HasPrototype, bool>::Type
-        getPrototypeOfHelper(JSContext *cx, JS::HandleObject wrapper,
-                             JS::HandleObject target, JS::MutableHandleObject protop) const
+        getPrototypeHelper(JSContext *cx, JS::HandleObject wrapper,
+                           JS::HandleObject target, JS::MutableHandleObject protop) const
     {
-        return Base::getPrototypeOf(cx, wrapper, protop);
+        return Base::getPrototype(cx, wrapper, protop);
     }
-    bool getPrototypeOfHelper(JSContext *cx, JS::HandleObject wrapper,
-                              JS::HandleObject target, JS::MutableHandleObject protop) const
+    bool getPrototypeHelper(JSContext *cx, JS::HandleObject wrapper,
+                            JS::HandleObject target, JS::MutableHandleObject protop) const
     {
-        return getPrototypeOfHelper<Traits::HasPrototype>(cx, wrapper, target,
-                                                          protop);
+        return getPrototypeHelper<Traits::HasPrototype>(cx, wrapper, target,
+                                                        protop);
     }
 
   protected:
     bool getPropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper, unsigned flags,
                          JS::AutoIdVector &props) const;
 };
 
 #define PermissiveXrayXPCWN xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::XPCWrappedNativeXrayTraits>