WindowProxy objects violate ES5 invariants

Hi,

It is not absolutely necessary, but for context, you can read the recent 
related es-discuss thread [1].
WindowProxy instances, when changing of underlying targets violate ES5 
invariants (more because of under-specification than anything else I 
believe). These invariants apply to host objects too. For reference, 
section 8.6.2 [2]:
" The [[GetOwnProperty]] internal method of a host object must conform 
to the following invariants for each property of the host object:

     If a property is described as a data property and it may return 
different values over time, then either or both of the [[Writable]] and 
[[Configurable] attributes must be true even if no mechanism to change 
the value is exposed via the other internal methods.

     If a property is described as a data property and its [[Writable]] 
and [[Configurable]] are both false, then the SameValue (according to 
9.12) must be returned for the [[Value]] attribute of the property on 
all calls to [[GetOwnProperty]].

     If the value of the host object's [[Extensible]] internal property 
is has been observed by ECMAScript code to be *false*, then if a call to 
[[GetOwnProperty]] describes a property as non-existent all subsequent 
calls must also describe that property as non-existent."

I expose some of these violations in a script [3] (see the console). In 
this example, a WindowProxy instance is assigned a non-configurable, 
non-writable property, but when the underlying Window is changed, this 
property disappears violating the above invariant.


Some agreement has started to emerged on es-discuss [4] and the main 
idea would be the following: whenever the underlying window of a 
WindowProxy can change, the internal operations ([[DefineOwnProperty]], 
[[GetOwnProperty]]) must throw whenever they're about to commit to an 
invariant.
More concretely, it means that a WindowProxy which can has its window 
changed can't be made non-extensible and can't have non-configurable 
properties defined on it. Any attempt to make the object non-extensible 
must throw as well as any attempt to set a property as non-configurable 
or report a property as non-configurable (with 
Object.getOwnPropertyDescriptor).

This change is not compatible with what's currently implemented in both 
Chrome and Firefox, but I'm confident ES5 Object methods are not used a 
lot in content and even less likely on WindowProxy instances, so I think 
it's worth trying.

It's been pointed that a script can add a non-configurable property to 
its global object [5] and there is no reason to prevent that. So from 
the spec perspective, there would bit 2 types of WindowProxy:
* Those which are guaranteed to never change the underlying window (and 
can add non-configurable properties)
* Those which can change the underlying window (and should never do 
anything committing to invariants)
 From an ES6 perspective, different WindowProxies would be ES6 proxies 
with different handlers (if you're unfamiliar with ES6 direct proxies, 
feel free to ask questions)

What do you think of the problem?
What do you think of the suggested solution?

I'd like to write tests to be added to the webapps test mercurial. But 
before doing so, I'd like to know the exhaustive list of cases and 
conditions where:
* one has access to a WindowProxy which is guaranteed to never have its 
underlying window changed
* one has access to a WindowProxy which may have its underlying window 
changed

David

[1] https://mail.mozilla.org/pipermail/es-discuss/2012-December/027080.html
[2] http://es5.github.com/#x8.6.2
[3] http://davidbruant.github.com/iframeProxyIssueDemo/
[4] https://mail.mozilla.org/pipermail/es-discuss/2012-December/027114.html
[5] last point of 
https://mail.mozilla.org/pipermail/es-discuss/2012-December/027092.html

Received on Thursday, 13 December 2012 11:01:41 UTC