Why Proxy "apply" trap limited to function only?
What exactly do you mean by “restricted to functions only”?
As I uderstood, here, in the spec it states that if target is "function", then trap "apply" is available, to catch function invocations harmony:virtual_object_api
And that's how it behaves in Forefox -- it just ignores "apply" trap if target object is not a function.
2016-03-02 14:55 GMT+02:00 Caitlin Potter <caitpotter88 at gmail.com>:
Le 2 mars 2016 à 13:21, Олег Галабурда <burdiuz at gmail.com> a écrit :
Hi!
I'm currently working on project that allows to manipulate objects passed from Worker. burdiuz/js-worker-interface, burdiuz/js-worker-interface
It creates wrapper objects that record actions applied to this object and send commands to Worker. The problem is, when request is made I cannot know what kind of object is this, so in case of function I should give ability to make calls on the wrapper object. As example, this code:
var api = new WorkerInterface('../webworker.js'); api.requestTime();
When "requestTime" was requested, it calls "get" and immediately returns new Proxy to serve function call. But at time when Proxy is created I do not know if that is function or not. Now I passed "apply" limitation by adding wrapper function and make Proxy think it works with function. burdiuz/js-worker-interface/blob/master/source/interface/proxy.js, burdiuz/js-worker-interface/blob/master/source/interface/proxy.js
If I guess correctly your issue, you would like to have something similar to:
foo.bar // not-a-function
and:
foo.bar() // a method call
? Indeed, that is not possible in JavaScript (and that limitation is not restricted to proxies).
I found in discussions why "call" trap was rejected, but didn't find anything about restricting "apply" trap to functions only.
Probably because "X is a function" is, by design, strictly equivalent to "X is callable"?
As far as I can tell, this is a bug in Firefox / SpiderMonkey. The [[CALL]] internal method of Proxy objects does not impose any restriction on the type of the Proxy target.
The following code behaves correctly in Chromium:
var proxy = new Proxy({}, { apply(target, thisArgument, arguments) { return Reflect.apply(Array, thisArgument, arguments); } });
proxy(1, 2, 3); // [1, 2, 3]
But as you say, this throws in Firefox, and based on the specification, this appears to be a bug. Implementations, amirite? ¯_(ツ)_/¯
Le 2 mars 2016 à 15:36, Caitlin Potter <caitpotter88 at gmail.com> a écrit :
As far as I can tell, this is a bug in Firefox / SpiderMonkey. The [[CALL]] internal method of Proxy objects does not impose any restriction on the type of the Proxy target.
The following code behaves correctly in Chromium:
var proxy = new Proxy({}, { apply(target, thisArgument, arguments) { return Reflect.apply(Array, thisArgument, arguments); } }); proxy(1, 2, 3); // [1, 2, 3]
But as you say, this throws in Firefox, and based on the specification, this appears to be a bug. Implementations, amirite? ¯_(ツ)_/¯
Rather, I'd say it is a bug in Chromium.
A Proxy should have a [[Call]] internal method if and only if its target has a [[Call]] internal method. See:
www.ecma-international.org/ecma-262/6.0/#sec-proxycreate, www.ecma-international.org/ecma-262/6.0/#sec-proxycreate step 7.
That maintains the equivalence: typeof x == "function"
iff x
is callable.
You’re right. I would argue this warrants a non-normative pointer to ProxyCreate() in the proxy [[CALL]] and [[CONSTRUCT]] internal methods.
Yes, correct. I want to be able to make a callable Proxy for non-callable objects and don't understand why Proxies are having these restrictions. As you can see I, and any other developer, can easily bypass this restriction and make a wrapper function that actually will be never called and just redirect calls made on Proxy to a method of an object. If "apply" trap will be allowed for any type of targets this will make life easier :)
2016-03-02 16:19 GMT+02:00 Claude Pache <claude.pache at gmail.com>:
Rather, I'd say it is a bug in Chromium.
A Proxy should have a [[Call]] internal method if and only if its target has a [[Call]] internal method. See:
www.ecma-international.org/ecma-262/6.0/#sec-proxycreate step 7.
That maintains the equivalence:
typeof x == "function"
iffx
is callable.
So, that's the restriction I'm talking about.
Le 2 mars 2016 à 15:47, Caitlin Potter <caitpotter88 at gmail.com> a écrit :
You’re right. I would argue this warrants a non-normative pointer to ProxyCreate() in the proxy [[CALL]] and [[CONSTRUCT]] internal methods.
Thanks!
Bug reported here:
bugs.chromium.org/p/v8/issues/detail?id=4796, bugs.chromium.org/p/v8/issues/detail?id=4796
We maintain the invariant that the typeof of an object is stable -- it never varies over time. An object is callable iff its typeof is 'function'. By making the callability and the typeof of the proxy dependent on its target, the two stay consistent.
On Wed, Mar 2, 2016 at 6:51 AM, Олег Галабурда <burdiuz at gmail.com> wrote:
Yes, correct. I want to be able to make a callable Proxy for non-callable objects and don't understand why Proxies are having these restrictions. As you can see I, and any other developer, can easily bypass this restriction and make a wrapper function that actually will be never called and just redirect calls made on Proxy to a method of an object.
Exactly. You are doing the right thing. This demonstrates that there is no loss of intended generality from imposing this restriction. It imposes a minor inconvenience for an uncommon case, as the price of being more straightforward for common cases.
I thought typeof (class {}) === "function"
as well. And classes, to my
knowledge aren't callable.
I thought
typeof (class {}) === "function"
as well. And classes, to my knowledge aren't callable.
Oh they are, they just throw when you call them : )
tc39.github.io/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist Step 2
Oh. I didn't realize that.
I'm currently working on project that allows to manipulate objects passed from Worker. burdiuz/js-worker-interface
It creates wrapper objects that record actions applied to this object and send commands to Worker. The problem is, when request is made I cannot know what kind of object is this, so in case of function I should give ability to make calls on the wrapper object. As example, this code:
var api = new WorkerInterface('../webworker.js'); api.requestTime();
When "requestTime" was requested, it calls "get" and immediately returns new Proxy to serve function call. But at time when Proxy is created I do not know if that is function or not. Now I passed "apply" limitation by adding wrapper function and make Proxy think it works with function. burdiuz/js-worker-interface/blob/master/source/interface/proxy.js
I found in discussions why "call" trap was rejected, but didn't find anything about restricting "apply" trap to functions only.