Igor Baklan (2016-05-14T11:07:52.000Z)
io.baklan at gmail.com (2016-05-14T11:11:51.315Z)
Fist of all little bit more details. Here `@@apply` and `@@update` proposed like some "fallback scenario" for "()" for non function objects (and not Proxy objects) - generally for objects that do not support `"()"` "natively". **(1)** Currently js has `"()"` operation (lets call it `"_=_()"`) but has not `"()="` operation (lets call it `"_()=_"`). Also operation "()" currently applied only to a functions, but not applied to the arbitrary objects (even when I create Proxy from arbitrary object and trying to implement "()" in Proxy, it still not work since target object was not a function, as for me it is more bug then feature:) ). So it supposed that if `obj` is not a function, then operation `"()"` goes to fallback scenario and try to use `obj[@@apply]` as an implementation of `"()"` operation for this `obj` object. But if `obj` object is Proxy object, than it obtains this operation as "direct" call of `apply` handler method (bypassing fallback to `obj[@@apply]`) . So `obj[@@apply]` should be used for "()" operation in some similar way as `vlaueOf` and `toString` are used by `"+"` operation - when object itself natively support this operation (like Number, String, etc does) the no fallback scenarios are used - `"+"` operation just do its native implementation, but when object do not natively support `"+"` (case of arbitrary object, not Number, not String, ...) then some additional fallback actions happens (with calling `valueOf` / `toString`). So here is the same idea - if `obj` is a function (or Proxy object) no fallback actions should occur - operation "()" should be done "natively". if object not a function neither a Proxy object, then fallback to `obj[@@apply]` should occur (and signature of this `obj[@@apply]`-method assumed to be the same as in proxy handler `apply` method (`function(target, thisArg, argumentsList) {}`) - so it should obtain more information then just a list of an arguments it also should obtain `target` and `thisArg` where `target` should be bound to `obj` and `thisArg` should be also properly passed, if it was `owner.obj(arg)` then `thisArg` should be bound to `owner` (*NOT* to `obj`)). **(2)** For `"()="` operation (`obj(..args) = val`) currently no implementation present (this construction unconditionally cause compile time error). But if we assume that it really present/implemented, and name it as `update` (like it was done in Scala), then `update` and `apply` in Proxy handler should be in the same relationship as `get` and `set` , and once again, it should be assumed that Prxoy object may "natively" implement update operation, and "fallback scenario" related to `obj[@@update]` should NOT happen for Proxy objects. So more strict definition off behavior will look like this: Considering `owner.obj(..args) = val` case: 1) If `owner.obj` is NOT a Proxy object (do not support `_()=_` operation "natively") then this should be evaluated to ```js owner.obj[@@update](/*target:*/ owner.obj, /*thisArg:*/ owner, args) ``` 2) If `owner.obj` is Proxy object (and that's why do support `_()=_` operation "natively") then underling assignment should refer to Proxy object handler `update` operation with same arguments as above, if proxy handler do not support `update` implementation, than it can fallback to `target` implantation of `_()=_` operation (and apply this rule recursively but this time for `target`) Considering this thoughts particular answer to your post will be: > ... and we already have Proxy traps for method calls: `get` and `apply` if `obj` is Proxy object, it assumed that it implements "`_=_()`" and `"_()=_"` operations "natively" so it should not use `obj[@@apply]` and `obj[@@update]` methods (and that is why `get` should not trigger), instead "`_=_()`" and `"_()=_"` operations should be directly forwarded to proxy handler (`apply` and `update` method accordingly) ; `obj[@@apply]` and `obj[@@update]` methods should be used only for objects which are both not js Function neither js Proxy object. Also proposed `update` handler method is more like counterpart of `apply`, like `set` proxy handler method is counterpart to `get` proxy handler method. > But there's also an inherent compatibility issue. Whenever you add a new trap, the deal is, all existing Proxy handlers were written without consideration for the new operation. So old code, used in combination with the new language feature, would tend to break. In case if old code was used, then it should mean that no `update` method present in proxy handler and so that `obj(...args) = val` will fallback to `target(...args) = val` (by actual result of execution); if `target` object was also defined/constructed by old code, then construct `obj(...args) = val` will lead to the same error as `target(...args) = val` does (since old code will not implement it for `target` too), so nothing will change for old code in this case; if old code of proxy will be applied for `target` object from "new code" (that occasionally happen to implement `"_()=_"` operation some how), then `obj(...args) = val` will succeed transparently and has same result as `target(...args) = val`. And yes, "old code" proxy handler will not intercept this situation, and that means that all handlers that currently intercept all operations over object will became less "universal". But this doesn't mean that "purely old" code will be broken in any way by introduction of this feature.