Thanks Claude for your careful review, and for trying to articulate a more general principle behind the invariant checks. The lack of such crisp principles makes it (too) difficult to verify whether all necessary checks are in place.
To clarify, in the case of "update" MOP operations such as defineProperty and deleteProperty, your "state B" (the observable state of the target), presumably is the state of the target *after* the proxy trap has executed, i.e. state B should already reflect the update. Both the original issue and your new test case with deleteProperty are cases where the proxy pretends to have altered the target but has in fact not. In a later interaction, the proxy reverts to the original state. This violates a client's expectations about when state transitions occur. Interestingly, the opposite problem, where a proxy does alter the target as requested, but then reports that the update failed, is allowed, even though this technically also violates a client's expectations about what state transitions have occurred. But a failed update leads to a TypeError anyway. At this point, we should probably iron out the details of the fix in a GitHub issue or on bugs.ecmascript.org. Cheers, Tom 2016-08-09 14:44 GMT+02:00 Claude Pache <[email protected]>: > Given a Proxy that pretends to be in state A while its target is > observably in state B, and assuming that the target satisfies the > Invariants of the Essential Internal Methods [6.1.7.3], I claim that, in > order to force the Proxy to satisfy those Invariants, it is necessary and > sufficient to check that the two following conditions hold: > > * it is legal for an object to pass from state A to state B; and, > * it is legal for an object to pass from state B to state A. > > [6.1.7.3]: https://tc39.github.io/ecma262/#sec-invariants-of- > the-essential-internal-methods > > > Because I am too lazy to write the proof just now, I cowardly leave it as > an exercice to the reader. Meanwhile, that principle may be used to audit > the robustness of the Proxy specification. I have found the following bug > in Proxy.[[Delete]]() by applying the above principle to: > > * state A: nonexistent property on a nonextensible object; > * state B: existent own property on a nonextensible object. > > Resurrection of a successfully deleted property on a nonextensible object: > > ```js > var target = Object.preventExtensions({ x: 1 }) > var proxy = new Proxy(target, { > deleteProperty() { return true } > }) > > Object.isExtensible(proxy) // false > delete proxy.x // true > proxy.hasOwnProperty('x') // true > ``` > > After a first scan, I haven't found other bugs in the essential methods of > Proxy, than that one and the missing nonconfigurable-but-writable check in > [[GetOwnPropertyDescriptor]] and [[DefineOwnProperty]] already mentioned in > that thread. > > I plan to propose a minimal patch (i.e., just adding the missing checks) > in a few days. > > —Claude > > >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

