[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