Object.freezing proxies should freeze or throw?
Claude Pache
claude.pache at gmail.com
Tue Aug 9 12:44:03 UTC 2016
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
More information about the es-discuss
mailing list