mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 06:05:44 +00:00
Bug 929467 - Only make Proxy a constructor when the target is a constructor. (r=jorendorff)
This commit is contained in:
parent
8bb1b9d23b
commit
d8e7cee936
14
js/src/jit-test/tests/proxy/testDirectProxyConstruct5.js
Normal file
14
js/src/jit-test/tests/proxy/testDirectProxyConstruct5.js
Normal file
@ -0,0 +1,14 @@
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
// Make sure that a proxy only has a [[Construct]] if the target does
|
||||
|
||||
var handler = {};
|
||||
var p = new Proxy(Math.sin, handler);
|
||||
var r = Proxy.revocable(Math.sin, handler).proxy;
|
||||
|
||||
assertThrowsInstanceOf(() => new p, TypeError, "Can't use 'new' on proxy with non-constructor target");
|
||||
assertThrowsInstanceOf(() => new r, TypeError, "Can't use 'new' on proxy with non-constructor target");
|
||||
// Better throw regardless of whether we have a handler trap.
|
||||
handler.construct = (() => ({}));
|
||||
assertThrowsInstanceOf(() => new p, TypeError, "Can't use 'new' on proxy with non-constructor target");
|
||||
assertThrowsInstanceOf(() => new r, TypeError, "Can't use 'new' on proxy with non-constructor target");
|
@ -1111,7 +1111,16 @@ bool
|
||||
ScriptedDirectProxyHandler::isCallable(JSObject *obj) const
|
||||
{
|
||||
MOZ_ASSERT(obj->as<ProxyObject>().handler() == &ScriptedDirectProxyHandler::singleton);
|
||||
return obj->as<ProxyObject>().extra(IS_CALLABLE_EXTRA).toBoolean();
|
||||
uint32_t callConstruct = obj->as<ProxyObject>().extra(IS_CALLCONSTRUCT_EXTRA).toPrivateUint32();
|
||||
return !!(callConstruct & IS_CALLABLE);
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptedDirectProxyHandler::isConstructor(JSObject *obj) const
|
||||
{
|
||||
MOZ_ASSERT(obj->as<ProxyObject>().handler() == &ScriptedDirectProxyHandler::singleton);
|
||||
uint32_t callConstruct = obj->as<ProxyObject>().extra(IS_CALLCONSTRUCT_EXTRA).toPrivateUint32();
|
||||
return !!(callConstruct & IS_CONSTRUCTOR);
|
||||
}
|
||||
|
||||
const char ScriptedDirectProxyHandler::family = 0;
|
||||
@ -1139,9 +1148,13 @@ js::proxy(JSContext *cx, unsigned argc, jsval *vp)
|
||||
if (!proxy_)
|
||||
return false;
|
||||
Rooted<ProxyObject*> proxy(cx, &proxy_->as<ProxyObject>());
|
||||
bool targetIsCallable = target->isCallable(); // Can GC - don't compute it inline.
|
||||
proxy->setExtra(ScriptedDirectProxyHandler::HANDLER_EXTRA, ObjectValue(*handler));
|
||||
proxy->setExtra(ScriptedDirectProxyHandler::IS_CALLABLE_EXTRA, BooleanValue(targetIsCallable));
|
||||
|
||||
// Assign [[Call]] and [[Construct]]
|
||||
uint32_t callable = target->isCallable() ? ScriptedDirectProxyHandler::IS_CALLABLE : 0;
|
||||
uint32_t constructor = target->isConstructor() ? ScriptedDirectProxyHandler::IS_CONSTRUCTOR : 0;
|
||||
proxy->as<ProxyObject>().setExtra(ScriptedDirectProxyHandler::IS_CALLCONSTRUCT_EXTRA,
|
||||
PrivateUint32Value(callable | constructor));
|
||||
args.rval().setObject(*proxy);
|
||||
return true;
|
||||
}
|
||||
|
@ -65,11 +65,8 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler {
|
||||
}
|
||||
|
||||
virtual bool isCallable(JSObject *obj) const MOZ_OVERRIDE;
|
||||
virtual bool isConstructor(JSObject *obj) const MOZ_OVERRIDE {
|
||||
// For now we maintain the broken behavior that a scripted proxy is constructable if it's
|
||||
// callable. See bug 929467.
|
||||
return isCallable(obj);
|
||||
}
|
||||
virtual bool isConstructor(JSObject *obj) const MOZ_OVERRIDE;
|
||||
|
||||
virtual bool isScripted() const MOZ_OVERRIDE { return true; }
|
||||
|
||||
static const char family;
|
||||
@ -78,7 +75,10 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler {
|
||||
// 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;
|
||||
static const int IS_CALLABLE_EXTRA = 1;
|
||||
static const int IS_CALLCONSTRUCT_EXTRA = 1;
|
||||
// Bitmasks for the "call/construct" slot
|
||||
static const int IS_CALLABLE = 1 << 0;
|
||||
static const int IS_CONSTRUCTOR = 1 << 1;
|
||||
// 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;
|
||||
|
Loading…
Reference in New Issue
Block a user