Bug 950407 - Fix broken scripted proxy prototype set forwarding. (r=bholley)
☠☠ backed out by 4a613dc5e5c7 ☠ ☠
authorEric Faust <efaustbmo@gmail.com>
Mon, 06 Jan 2014 11:34:26 -0800
changeset 162274 884a27ad7c5e71ebaa5a34d3c559b9bc7121f555
parent 162273 ac3f3d1d8201b1a47fb0bc8e518098918abb9380
child 162275 39a514870dd32c63aa80ffc3d82fc521983a5b76
push idunknown
push userunknown
push dateunknown
reviewersbholley
bugs950407
milestone29.0a1
Bug 950407 - Fix broken scripted proxy prototype set forwarding. (r=bholley)
js/src/jsobjinlines.h
js/src/jsproxy.cpp
js/src/vm/GlobalObject.cpp
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -417,16 +417,32 @@ JSObject::getProto(JSContext *cx, js::Ha
 JSObject::setProto(JSContext *cx, JS::HandleObject obj, JS::HandleObject proto, bool *succeeded)
 {
     /* Proxies live in their own little world. */
     if (obj->getTaggedProto().isLazy()) {
         JS_ASSERT(obj->is<js::ProxyObject>());
         return js::Proxy::setPrototypeOf(cx, obj, proto, succeeded);
     }
 
+    /*
+     * 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<js::ArrayBufferObject>()) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL);
+        return false;
+    }
+
+    unsigned dummy;
+    js::RootedId nid(cx, NameToId(cx->names().proto));
+    js::RootedValue v(cx);
+    if (!CheckAccess(cx, obj, nid, JSAccessMode(JSACC_PROTO | JSACC_WRITE), &v, &dummy))
+        return false;
+
     /* ES6 9.1.2 step 5 forbids changing [[Prototype]] if not [[Extensible]]. */
     bool extensible;
     if (!JSObject::isExtensible(cx, obj, &extensible))
         return false;
     if (!extensible) {
         *succeeded = false;
         return true;
     }
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -3244,25 +3244,22 @@ proxy(JSContext *cx, unsigned argc, jsva
         return false;
     }
     RootedObject target(cx, NonNullObject(cx, args[0]));
     if (!target)
         return false;
     RootedObject handler(cx, NonNullObject(cx, args[1]));
     if (!handler)
         return false;
-    RootedObject proto(cx);
-    if (!JSObject::getProto(cx, target, &proto))
-        return false;
     RootedValue priv(cx, ObjectValue(*target));
     ProxyOptions options;
     options.setCallable(target->isCallable());
     ProxyObject *proxy =
         ProxyObject::New(cx, &ScriptedDirectProxyHandler::singleton,
-                         priv, TaggedProto(proto), cx->global(),
+                         priv, TaggedProto(TaggedProto::LazyProto), cx->global(),
                          options);
     if (!proxy)
         return false;
     proxy->setExtra(0, ObjectOrNullValue(handler));
     vp->setObject(*proxy);
     return true;
 }
 
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -118,41 +118,24 @@ ProtoSetterImpl(JSContext *cx, CallArgs 
         return true;
     }
 
     if (!cx->runningWithTrustedPrincipals())
         ++sSetProtoCalled;
 
     Rooted<JSObject*> obj(cx, &args.thisv().toObject());
 
-    /*
-     * 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, js_GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
-                             "Object", "__proto__ setter", "ArrayBuffer");
-        return false;
-    }
-
     /* 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());
 
-    unsigned dummy;
-    RootedId nid(cx, NameToId(cx->names().proto));
-    RootedValue v(cx);
-    if (!CheckAccess(cx, obj, nid, JSAccessMode(JSACC_PROTO | JSACC_WRITE), &v, &dummy))
-        return false;
-
     bool success;
     if (!JSObject::setProto(cx, obj, newProto, &success))
         return false;
 
     if (!success) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL);
         return false;
     }