diff --git a/js/src/proxy/ScriptedDirectProxyHandler.cpp b/js/src/proxy/ScriptedDirectProxyHandler.cpp index 1a3ba0c520d0..8f3ddf50e075 100644 --- a/js/src/proxy/ScriptedDirectProxyHandler.cpp +++ b/js/src/proxy/ScriptedDirectProxyHandler.cpp @@ -328,6 +328,35 @@ ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy) return false; } +// ES6 implements both getPrototypeOf and setPrototypeOf 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 +{ + RootedObject target(cx, proxy->as().target()); + // Though handler is used elsewhere, spec mandates that both get set to null. + if (!target) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED); + return false; + } + + return DirectProxyHandler::getPrototypeOf(cx, proxy, protop); +} + +bool +ScriptedDirectProxyHandler::setPrototypeOf(JSContext *cx, HandleObject proxy, + HandleObject proto, bool *bp) const +{ + RootedObject target(cx, proxy->as().target()); + if (!target) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED); + return false; + } + + return DirectProxyHandler::setPrototypeOf(cx, proxy, proto, bp); +} + // Corresponds to the "standard" property descriptor getOwn getPrototypeOf dance. It's so explicit // here because ScriptedDirectProxyHandler allows script visibility for this operation. bool @@ -1090,35 +1119,6 @@ ScriptedDirectProxyHandler::isCallable(JSObject *obj) const return obj->as().extra(IS_CALLABLE_EXTRA).toBoolean(); } -// ES6 implements both getPrototypeOf and setPrototypeOf 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 -{ - RootedObject target(cx, proxy->as().target()); - // Though handler is used elsewhere, spec mandates that both get set to null. - if (!target) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED); - return false; - } - - return DirectProxyHandler::getPrototypeOf(cx, proxy, protop); -} - -bool -ScriptedDirectProxyHandler::setPrototypeOf(JSContext *cx, HandleObject proxy, - HandleObject proto, bool *bp) const -{ - RootedObject target(cx, proxy->as().target()); - if (!target) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED); - return false; - } - - return DirectProxyHandler::setPrototypeOf(cx, proxy, proto, bp); -} - const char ScriptedDirectProxyHandler::family = 0; const ScriptedDirectProxyHandler ScriptedDirectProxyHandler::singleton; diff --git a/js/src/proxy/ScriptedDirectProxyHandler.h b/js/src/proxy/ScriptedDirectProxyHandler.h index 6558a1bef208..fd886391080e 100644 --- a/js/src/proxy/ScriptedDirectProxyHandler.h +++ b/js/src/proxy/ScriptedDirectProxyHandler.h @@ -29,6 +29,13 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler { virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE; virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE; virtual bool preventExtensions(JSContext *cx, HandleObject proxy) 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 has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE; virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id, MutableHandleValue vp) const MOZ_OVERRIDE; @@ -36,11 +43,6 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler { bool strict, MutableHandleValue vp) 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; - // These are standard internal methods, but are not 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; /* SpiderMonkey extensions. */ virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, diff --git a/js/src/tests/ecma_6/Proxy/revocable-proxy-prototype.js b/js/src/tests/ecma_6/Proxy/revocable-proxy-prototype.js new file mode 100644 index 000000000000..7afbc15d2a4c --- /dev/null +++ b/js/src/tests/ecma_6/Proxy/revocable-proxy-prototype.js @@ -0,0 +1,40 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'revocable-proxy-prototype.js'; +var BUGNUMBER = 1052139; +var summary = "Accessing a revocable proxy's [[Prototype]] shouldn't crash"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ +function checkFunctionAppliedToRevokedProxy(fun) +{ + var p = Proxy.revocable({}, {}); + p.revoke(); + + try + { + fun(p.proxy); + throw "didn't throw"; + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "expected TypeError, got " + e); + } +} + +checkFunctionAppliedToRevokedProxy(proxy => Object.getPrototypeOf(proxy)); +checkFunctionAppliedToRevokedProxy(proxy => Object.setPrototypeOf(proxy, null)); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete");