[whatwg] Window and WindowProxy
Boris Zbarsky
bzbarsky at MIT.EDU
Thu Aug 8 15:40:34 PDT 2013
On 8/8/13 5:05 PM, Ian Hickson wrote:
> I think the problem is that I have no idea what these ES6 terms are or
> what they mean.
OK. Which terms, exactly?
> Was all this a problem in previous revisions of JavaScript? Or is it some
> new problem caused by some new JavaScript feature?
It's a "problem", as far as it goes, caused by the ability to get
property descriptors at all. In the old world there was no way to
explicitly invoke [[DefineProperty]] or check whether something is
configurable. So some things were not observable that are now
observable, and the ES spec had to define what happens when you observe
them.
This is not an ES6 issue; ES5 has similar problems, but a bit less
clarity (e.g. no Proxy objects in ES5,
>>>> "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?
>
> I have basically no idea what any of it means. I understand all the
> individual words of that paragraph, but I've no idea what they mean when
> put next to each other in that order. :-) A property is just an entry in
> the bag that is a JS object, what does it mean for it to be or not be
> configurable?
Ah, ok. So in ES5 there is a concept of a "property descriptor". There
is both an internal representation of property descriptors and a way to
get JS objects that represent a property descriptor:
Object.getOwnPropertyDescriptor.
See ECMA-262 edition 5 section 8.10 for details on how property
descriptors work, but fundamentally a property descriptor for an
existing property describes how it's set up. A property descriptor can
also be used to create new properties via Object.defineProperty.
Every property descriptor has two booleans it stores: [[Enumerable]] and
[[Configurable]]. [[Enumerable]] controls whether the property shows up
in for..in enumeration. [[Configurable]] controls how the property
descriptor for this property can change. In particular, if
[[Configurable]] is false, then the values of [[Configurable]],
[[Enumerable]], [[Get]], [[Set]], and [[Writable]] for this property
cannot change in the future ([[Value]] can still change if this is a
value property that is [[Writable]]).
All property manipulation in ES5 and later is defined in terms of
property descriptors. For example, the definition of [[Put]] (which is
the thing that happens on "foo.bar = something") in ES5 section 8.12.5
does gets the property descriptor and then looking at that descriptor
and deciding what to do based on that ([[GetOwnProperty]] and
[[GetProperty]] return property descriptors, somewhat non-obviously).
> A proxy is something that passes incoming requests from one
> object to another object
A Proxy in ES6 is a particular kind of JS object that has pointers to
two other objects: a target and a handler. The target is what requests
get passed to, if desired. The handler is basically a mapping from MOP
names to JS functions implementing the relevant MOP operation.
So for example, an object with an indexed getter is defined in WebIDL by
defining that it has special implementations for three MOP operations:
[[GetOwnProperty]], [[DefineProperty]], and [[Delete]]. If you wanted
to implement such an object in JS, there is no way to do this in ES5.
In ES6, you would create a Proxy whose target is just a vanilla object
for storing expandos and the proto link and whose handler does the steps
defined by WebIDL for those three operations.
Note that your description of a proxy above is certainly implementable
as a Proxy, but a Proxy can also implement other things (again, like
things with indexed or named getters as currently specced).
See http://people.mozilla.org/~jorendorff/es6-draft.html#sec-8.5 for the
full-on spec bits.
> what does it mean for a proxy to have a property?
If it returns something other than undefined from [[GetOwnProperty]].
>> Er... That's a cross-site information leak.
>
> How so? The names of the IDL attributes and methods on Window objects are
> the same on all Window objects (WindowModal notwithstanding), and the
> non-IDL properties aren't enumerable cross-origin.
getOwnPropertyNames returns all own properties, not just enumerable ones.
> "For members that return objects (including function objects), each
> distinct effective script origin that is not the same as the Window
> object's Document's effective script origin must be provided with a
> separate set of objects. These objects must have the prototype chain
> appropriate for the script for which the objects are created (not those
> that would be appropriate for scripts whose script's global object is the
> Window object in question)."
Mmm... I don't think this works very well for Window.
> (same effective origin)
Sure.
>> 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.
>
> Well, what the spec says now is that when the script changes effective
> origin, it also changes its prototypes and so forth, essentially.
Does any UA do this? I would be somewhat surprised if this were web
compatible, and even more surprised if it were implementable in practice
and if any UA wanted to implement it....
> We (the Web community) can change what's allowed and what isn't allowed.
> We do so all the time.
Sure, but changing this makes it very hard to reason about ES, in very
undesirable ways. This has been pretty extensively hashed out on
es-discuss and public-script-coord...
And more to the point it seems unnecessary to throw out useful
invariants in this case just so we can preserve a particular
specification device.
>> 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.
>
> That's fine. The Window will keep having that property. The WindowProxy
> object's own properties can't be examined
The WindowProxy is the object the script has. It's the object
[[GetOwnProperty]] (via Object.getOwnPropertyDescriptor) is called on.
So the above requirement about the property not disappearing if it's
non-configurable applies to the WindowProxy.
Which is why WindowProxy can't ever claim to have non-configurable
properties... It would violate basic language invariants.
-Boris
More information about the whatwg
mailing list