Bug 978279 - Implement revocation semantics. (r=jorendorff)

This commit is contained in:
Eric Faust
2014-07-22 14:10:31 -07:00
parent 680517faf1
commit eb88cd1af1
5 changed files with 134 additions and 16 deletions

View File

@@ -1086,6 +1086,13 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler {
virtual bool isScripted() const MOZ_OVERRIDE { return true; }
static const ScriptedDirectProxyHandler singleton;
// The "proxy extra" slot index in which the handler is stored. Revocable proxies need to set
// this at revocation time.
static const int HANDLER_EXTRA = 0;
// The "function extended" slot index in which the revocation object is stored. Per spec, this
// is to be cleared during the first revocation.
static const int REVOKE_SLOT = 0;
};
// This variable exists solely to provide a unique address for use as an identifier.
@@ -1230,13 +1237,11 @@ HasOwn(JSContext *cx, HandleObject obj, HandleId id, bool *bp)
}
// Get the [[ProxyHandler]] of a scripted direct proxy.
//
// NB: This *must* stay synched with proxy().
static JSObject *
GetDirectProxyHandlerObject(JSObject *proxy)
{
JS_ASSERT(proxy->as<ProxyObject>().handler() == &ScriptedDirectProxyHandler::singleton);
return proxy->as<ProxyObject>().extra(0).toObjectOrNull();
return proxy->as<ProxyObject>().extra(ScriptedDirectProxyHandler::HANDLER_EXTRA).toObjectOrNull();
}
static inline void
@@ -1366,7 +1371,11 @@ ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
// step 1
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// TODO: step 2: Implement revocation semantics. See bug 978279.
// step 2
if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 3
RootedObject target(cx, proxy->as<ProxyObject>().target());
@@ -1440,7 +1449,11 @@ ScriptedDirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject
// step 2
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// TODO: step 3: Implement revocation semantics. See bug 978279.
// step 3
if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 4
RootedObject target(cx, proxy->as<ProxyObject>().target());
@@ -1556,7 +1569,11 @@ ScriptedDirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, Ha
// step 2
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// TODO: step 3: Implement revocation semantics. See bug 978279.
// step 3
if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 4
RootedObject target(cx, proxy->as<ProxyObject>().target());
@@ -1642,7 +1659,11 @@ ScriptedDirectProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject prox
// step 1
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// TODO: step 2: Implement revocation semantics
// step 2
if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 3
RootedObject target(cx, proxy->as<ProxyObject>().target());
@@ -1684,7 +1705,11 @@ ScriptedDirectProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId
// step 2
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// TODO: step 3: Implement revocation semantics
// step 3
if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 4
RootedObject target(cx, proxy->as<ProxyObject>().target());
@@ -1741,7 +1766,11 @@ ScriptedDirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdV
// step 1
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// TODO: step 2: Implement revocation semantics.
// step 2
if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 3
RootedObject target(cx, proxy->as<ProxyObject>().target());
@@ -1787,7 +1816,11 @@ ScriptedDirectProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id,
// step 2
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// TODO: step 3: Implement revocation semantics.
// step 3
if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 4
RootedObject target(cx, proxy->as<ProxyObject>().target());
@@ -1851,7 +1884,11 @@ ScriptedDirectProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject
// step 2
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// TODO: step 3: Implement revocation semantics.
// step 3
if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 4
RootedObject target(cx, proxy->as<ProxyObject>().target());
@@ -1916,7 +1953,11 @@ ScriptedDirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject
// step 2
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// TODO: step 3: Implement revocation semantics
// step 3
if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 4
RootedObject target(cx, proxy->as<ProxyObject>().target());
@@ -1984,7 +2025,11 @@ ScriptedDirectProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool
// step 1
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// TODO: step 2: Implement revocation semantics.
// step 2
if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 3
RootedObject target(cx, proxy->as<ProxyObject>().target());
@@ -2040,7 +2085,11 @@ ScriptedDirectProxyHandler::call(JSContext *cx, HandleObject proxy, const CallAr
// step 1
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// TODO: step 2: Implement revocation semantics.
// step 2
if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 3
RootedObject target(cx, proxy->as<ProxyObject>().target());
@@ -2081,7 +2130,11 @@ ScriptedDirectProxyHandler::construct(JSContext *cx, HandleObject proxy, const C
// step 1
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// TODO: step 2: Implement revocation semantics.
// step 2
if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 3
RootedObject target(cx, proxy->as<ProxyObject>().target());
@@ -2924,11 +2977,65 @@ proxy(JSContext *cx, unsigned argc, jsval *vp)
options);
if (!proxy)
return false;
proxy->setExtra(0, ObjectOrNullValue(handler));
proxy->setExtra(ScriptedDirectProxyHandler::HANDLER_EXTRA, ObjectValue(*handler));
args.rval().setObject(*proxy);
return true;
}
static bool
RevokeProxy(JSContext *cx, unsigned argc, Value *vp)
{
CallReceiver rec = CallReceiverFromVp(vp);
RootedFunction func(cx, &rec.callee().as<JSFunction>());
RootedObject p(cx, func->getExtendedSlot(ScriptedDirectProxyHandler::REVOKE_SLOT).toObjectOrNull());
if (p) {
func->setExtendedSlot(ScriptedDirectProxyHandler::REVOKE_SLOT, NullValue());
MOZ_ASSERT(p->is<ProxyObject>());
p->as<ProxyObject>().setSameCompartmentPrivate(NullValue());
p->as<ProxyObject>().setExtra(ScriptedDirectProxyHandler::HANDLER_EXTRA, NullValue());
}
rec.rval().setUndefined();
return true;
}
static bool
proxy_revocable(JSContext *cx, unsigned argc, Value *vp)
{
CallReceiver args = CallReceiverFromVp(vp);
if (!proxy(cx, argc, vp))
return false;
RootedValue proxyVal(cx, args.rval());
MOZ_ASSERT(proxyVal.toObject().is<ProxyObject>());
RootedObject revoker(cx, NewFunctionByIdWithReserved(cx, RevokeProxy, 0, 0, cx->global(),
AtomToId(cx->names().revoke)));
if (!revoker)
return false;
revoker->as<JSFunction>().initExtendedSlot(ScriptedDirectProxyHandler::REVOKE_SLOT, proxyVal);
RootedObject result(cx, NewBuiltinClassInstance(cx, &JSObject::class_));
if (!result)
return false;
RootedValue revokeVal(cx, ObjectValue(*revoker));
if (!JSObject::defineProperty(cx, result, cx->names().proxy, proxyVal) ||
!JSObject::defineProperty(cx, result, cx->names().revoke, revokeVal))
{
return false;
}
args.rval().setObject(*result);
return true;
}
static bool
proxy_create(JSContext *cx, unsigned argc, Value *vp)
{
@@ -3021,6 +3128,7 @@ js_InitProxyClass(JSContext *cx, HandleObject obj)
static const JSFunctionSpec static_methods[] = {
JS_FN("create", proxy_create, 2, 0),
JS_FN("createFunction", proxy_createFunction, 3, 0),
JS_FN("revocable", proxy_revocable, 2, 0),
JS_FS_END
};