> Le 11 août 2016 à 13:14, Tom Van Cutsem <[email protected]> a écrit :
> 
> I don't think it's too worrisome because of the following reasoning:
> 
> Any code prior to the first invocation of obj.x (let's call this the "outer 
> code") will have observed the property as configurable & writable, so having 
> obj.x evaluate to 1 is a valid outcome.
> 
> Any code that runs synchronously between the call to Object.defineProperty 
> and the `return 1` statement (let's call this the "inner code"), will 
> consistently observe obj.x as non-configurable,non-writable and will always 
> read 2.
> 
> A worrisome scenario would be when the inner code computes results based on 
> the new value of x that are also accessible to the outer code, and the outer 
> code somehow expects that value to be consistent with the old value of x. 
> However, it's unclear that this bug is really due to the violation of an ES 
> invariant.
> 
> I'm not sure if proxies would amplify the problem. Actually, the invariant 
> assertions in the Proxy internal methods were designed precisely to avoid 
> such bugs, which is why all the assertions trigger when the trap has finished 
> executing and the proxy can no longer influence the outcome of the 
> intercepted operation. The bug described above would be avoided if the 
> internal methods of Ordinary ES objects would apply the same kind of 
> invariant checks as proxies do, checking the result of the [[Get]] operation 
> with the property's current attribute state. However, I suspect that would 
> probably be a bridge too far in terms of cost vs payoff.

If we want to avoid the "bug" I mentioned, the invariant checks for proxies 
have to be done very carefully in order to avoid some really weird (and most 
surely implausible) edge cases as demonstrated by the scenario below.
The key fact is that, while the traps of the proxy may behave regularly, the 
target might be itself an exotic object that manifests weird behaviours.

Let P be a Proxy, T its target object, and let's invoke 
P.[[GetOwnProperty]]("x").
https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getownproperty-p
 
<https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getownproperty-p>
The following scenario is possible:

* step 8: P's getOwnPropertyDescriptor trap is invoked on property "x". That 
trap exists but simply returns T.[[GetOwnProperty]]("x")
* step 10: T.[[GetOwnProperty]]("x") returns naturally the same descriptor.
* step 12 (or 11c): T.[[IsExtensible]]() is invoked. But it happens that T is a 
strange exotic object (e.g. a proxy) with a weird [[IsExtensible]] method that 
does the following:
        * if it is extensible,
                1. it deletes its property "x";
                2. it makes itself nonextensible;
                3. it publishes somewhere that P is nonextensible and has no 
property "x" (e.g., by using the observe function of my original message);
* Following steps: Checks are made based on results of steps 10 and 12. 
Naturally, given the result of step 10, all checks pass.

As a consequence, the property "x" is observed as present on P, while it was 
previously observed as absent on nonextensible P.

(A solution would be to invoke T.[[IsExtensible]]() only when we know in 
advance that we will throw in case T is nonextensible. But it is probably not 
worth to worry for that.)

—Claude

> 
> Regards,
> Tom
> 
> 
> 2016-08-10 17:51 GMT+02:00 Claude Pache <[email protected] 
> <mailto:[email protected]>>:
> Test case:
> 
> ```js
> var results = []
> 
> var observe = function (method, object, ...args) {
>     results.push({
>         method: method
>       , object: object
>       , args: args
>       , output: Reflect[method](object, ...args)
>     })
> }
> 
> var obj = { get x() {
>     Object.defineProperty(this, 'x', { value: 2, configurable: false, 
> writable: false })
>     observe('getOwnPropertyDescriptor', this, 'x')
>     return 1
> } }
> 
> observe('get', obj, 'x')
> 
> results[0]
> // { method: "getOwnPropertyDescriptor", object: obj, args: [ "x" ], output: 
> { value: 2, writable: false, enumerable: true, configurable: false } }
> // `obj` is observed to have a nonconfigurable, nonwritable property "x" with 
> value `2`.
> 
> results[1] // { method: "get", object: obj, args: [ "x" ], output: 1 }
> // Then, `obj.[[Get]]("x") is observed to return `1`.
> ```
> 
> Not sure if it is worrisome. What is sure, the situation could become worse 
> with fanciful proxies.
> 
> ―Claude
> _______________________________________________
> es-discuss mailing list
> [email protected] <mailto:[email protected]>
> https://mail.mozilla.org/listinfo/es-discuss 
> <https://mail.mozilla.org/listinfo/es-discuss>
> 

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to