[whatwg] Window and WindowProxy

Boris Zbarsky bzbarsky at MIT.EDU
Thu Aug 8 12:38:24 PDT 2013


On 8/8/13 2:48 PM, Ian Hickson wrote:
>> The current spec calls for the Window to be a proxy-like object, because
>> that's the only way to implement the spec's indexed getter behavior.
>
> I don't understand what you mean. What's different about Window's indexed
> getter behaviour than the indexed getter behaviours of all the other
> interfaces in HTML that have indexed getters?

Absolutely nothing.  All the other indexed getter behaviors in HTML 
require proxy-like behavior.

But none of the rest of them are the global object, so they can just be 
proxies and do their weird proxy things (again, in ES6 terms), and it's 
all ok.

>> "var" needs to be able to define non-configurable properties.  Proxies
>> don't necessarily offer useful guarantees about being able to define
>> such properties on them, and in particular the behavior for index/named
>> getters in WebIDL precludes definition of non-configurable properties of
>> the corresponding kind on the relevant object.
>
> I don't understand what this means, sorry.

Hmm.  Which part is unclear?

> If WebIDL makes it hard for an object that has indexed and named getters
> to also be a [Global] object, then we should fix WebIDL, since 33% of the
> [Global] objects, and nearly 100% of the actual [Global] objects in the
> wild, have indexed and named getters.

This is not a problem with WebIDL.  This is a problem with the fact that 
indexed and named getters as implemented in modern browsers effectively 
violate ES language invariants that the global is not allowed to violate.

Now the good thing is that we defined things in WebIDL so that this is 
ok: the named getters on the global are NOT on the global itself, but on 
the NamedPropertiesObject on its prototype chain (and the difference is 
readily observable; try "var foo = 5; alert(foo);" in a page that has 
<iframe name="foo"> and note that you get 5, which you would not if the 
named getter were on the Window directly).  And the indexed getter on 
Window, as I said, is black-box indistinguishable from living on the 
WindowProxy, because you can't use indices as barewords.  So the upshot 
is that a UA can just put them there and not have conflicts with the ES 
spec.

But, once again, if that's what UAs end up having to do anyway, we may 
as well spec it that way.

>> I'm not sure what you mean.  The "mapping" that needs to happen is "how
>> do I have a global that's not a magic proxy while being black-box
>> compatible with the spec?"
>
> The Window object is just a regular object as far as I can tell. It has no
> magical proxiness.

The indexed getter behavior is "magical proxiness" as implemented in UAs 
and specced in WebIDL.  Again, in ES6 terms.

And we've tried to find other ways to define it; they all suck even more.

> That's only WindowProxy, which isn't the global.

I think we might be using two different definitions of "proxy".

I am using "proxy" to indicate objects for which a normal, non-Proxy, 
user-created object in JS would not be able to emulate their behavior. 
Objects like that are why ES introduced Proxy objects, which are able to 
have a much wider range of behaviors than normal objects, because they 
can hook into various operations on a much lower level (specifically, 
they can more or less directly implement the MOP).

>> Because getOwnPropertyNames should return the own properties of the
>> object, but doing that on a WindowProxy for a cross-origin window should
>> not in fact return the Window's own properties.
>
> Yes, it should. At least, IMHO.

Er... That's a cross-site information leak.  While some browsers 
apparently do in fact have this leak, the web does not require it, I 
don't think we should spec it, and Gecko certainly has no plans to add it.

> WindowProxy should be _completely indistinguishable_ from the Window it
> currently points to, except for the way it can be distinguished when what
> it points to changes.

OK, so in this view there are multiple (one per origin, roughly) Window 
objects in JS all representing the same underlying browser object?

I don't understand how this can work with document.domain, where things 
that used to not be same-origin suddenly become same-origin: in that 
situation two different origins become the same origin and the fact that 
they have different Window objects for the same current window ends up 
observable.

I feel like I must be missing something about the model you're working 
with here.

>> Or another similar issue: getting a property descriptor from a
>> WindowProxy (for a same-origin window) should probably never claim to
>> have a non-configurable property, because on navigation the property
>> will in fact disappear and non-configurable properties are not allowed
>> to do that in ES.
>
> IMHO, yes, it should.

That's not allowed in ES.  Do see the thread I linked to.

>> See
>> http://lists.w3.org/Archives/Public/public-script-coord/2012OctDec/0386.html
>> and the threads it references.  But of course Window is required to be
>> able to have non-configurable properties (see "var").  So WindowProxy
>> can't just forward [[GetOwnProperty]] on to the Window.
>
> I think you're making this more complicated than it need be.
>
> Conceptually, it's just that the pointers to Window objects get redirected
> to point to a different Window object when the browsing context navigates.

Let me try to make this clearer.

If an object (in this case a WindowProxy, since that's what the script 
is working with) ever claims that it has a non-configurable property for 
some property name, ES requires that it _always_ do that from that point 
on.  This is a fundamental invariant that other parts of ES are built 
on, and security libraries (caja and the like) plan to make use of this 
invariant.

> It's as if script had gone through every variable that points to the first
> Window object and set the variable to point to the new Window object.

I understand your mental model for this part; I'm just telling you that 
it contradicts the ES spec and we need to reconcile the contradiction 
somehow.

> Every single MOP primitive for WindowProxy should just transparently proxy
> to the current underlying Window MOP primitive.

See above.

-Boris




More information about the whatwg mailing list