Figuring out the behavior of WindowProxy in the face of non-configurable properties

classic Classic list List threaded Threaded
51 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Figuring out the behavior of WindowProxy in the face of non-configurable properties

Boris Zbarsky
[ccing public-script-coord because I'm not sure what list is best for
this; mostly I'm looking for feedback from other UA implementors.]

We really need to create an actual specification for WindowProxy.  One
of the serious problems is what to do with non-configurable properties.

Consider this testcase (live version at
http://web.mit.edu/bzbarsky/www/testcases/windowproxy/non-configurable-props-1.html 
with slightly different logging):

   <iframe></iframe>
   <script>
   onload = function() {
     var subframe = frames[0];
     Object.defineProperty(subframe, "foo", { value: 1 });
     console.log(Object.getOwnPropertyDescriptor(subframe, "foo"));

     frames[0].frameElement.onload = function() {
       console.log(Object.getOwnPropertyDescriptor(subframe, "foo"));
     };

     frames[0].location = "about:blank";
   };
   </script>

The console in Firefox nightly and Chrome dev shows:

   Object { configurable: false, enumerable: false, value: 1,
            writable: false }
   undefined

The console in Safari 7 and WebKit nightly shows:

   undefined
   undefined

The console in IE 11 shows:

   [object Object]
   undefined

and if I examine the actual descriptor returned, .configurable is false.
  No exceptions are thrown by any of the browsers.

As I understand the ES spec, none of these browsers are enforcing the
fundamental invariants: three of them because they have a
non-configurable property go away and one because it silently doesn't
define a non-configurable property when you try to do it.

Though the Safari behavior is actually quite interesting.
http://web.mit.edu/bzbarsky/www/testcases/windowproxy/non-configurable-props-2.html 
shows that if the property is defined from inside the subframe then
getOwnPropertyDescriptor does not see it from the outside, even though
from the inside it's visible.  And
http://web.mit.edu/bzbarsky/www/testcases/windowproxy/non-configurable-props-3.html 
shows that when defining from "outside" the property _is_ in fact being
defined as far as scripts "inside" are concerned.

Oh, and getting .foo from "outside" returns 1, but doing
getOwnPropertyDescriptor up the proto chain of "subframe" consistently
returns undefined in Safari.

This last bit has nothing to do with configurability, by the way
Object.getOwnPropertyDescriptor returns undefined from the "outside" in
general in Safari.

Per spec ES6, it seems to me like attempting to define a
non-configurable property on a WindowProxy should throw and getting a
property descriptor for a non-configurable property that got defined on
the Window (e.g. via "var") should report it as configurable.  But that
matches precisely 0 UAs.... and throwing seems like a compat worry.  :(

Anyway, what are reasonable behaviors here?  What are UAs willing to
align on?

-Boris
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Mark S. Miller-2
On Sun, Nov 30, 2014 at 12:21 PM, Boris Zbarsky <[hidden email]> wrote:

> [ccing public-script-coord because I'm not sure what list is best for this;
> mostly I'm looking for feedback from other UA implementors.]
>
> We really need to create an actual specification for WindowProxy.  One of
> the serious problems is what to do with non-configurable properties.
>
> Consider this testcase (live version at
> http://web.mit.edu/bzbarsky/www/testcases/windowproxy/non-configurable-props-1.html
> with slightly different logging):
>
>   <iframe></iframe>
>   <script>
>   onload = function() {
>     var subframe = frames[0];
>     Object.defineProperty(subframe, "foo", { value: 1 });
>     console.log(Object.getOwnPropertyDescriptor(subframe, "foo"));
>
>     frames[0].frameElement.onload = function() {
>       console.log(Object.getOwnPropertyDescriptor(subframe, "foo"));
>     };
>
>     frames[0].location = "about:blank";
>   };
>   </script>
>
> The console in Firefox nightly and Chrome dev shows:
>
>   Object { configurable: false, enumerable: false, value: 1,
>            writable: false }
>   undefined
>
> The console in Safari 7 and WebKit nightly shows:
>
>   undefined
>   undefined
>
> The console in IE 11 shows:
>
>   [object Object]
>   undefined
>
> and if I examine the actual descriptor returned, .configurable is false.  No
> exceptions are thrown by any of the browsers.
>
> As I understand the ES spec, none of these browsers are enforcing the
> fundamental invariants: three of them because they have a non-configurable
> property go away and one because it silently doesn't define a
> non-configurable property when you try to do it.
>
> Though the Safari behavior is actually quite interesting.
> http://web.mit.edu/bzbarsky/www/testcases/windowproxy/non-configurable-props-2.html
> shows that if the property is defined from inside the subframe then
> getOwnPropertyDescriptor does not see it from the outside, even though from
> the inside it's visible.  And
> http://web.mit.edu/bzbarsky/www/testcases/windowproxy/non-configurable-props-3.html
> shows that when defining from "outside" the property _is_ in fact being
> defined as far as scripts "inside" are concerned.
>
> Oh, and getting .foo from "outside" returns 1, but doing
> getOwnPropertyDescriptor up the proto chain of "subframe" consistently
> returns undefined in Safari.
>
> This last bit has nothing to do with configurability, by the way
> Object.getOwnPropertyDescriptor returns undefined from the "outside" in
> general in Safari.
>
> Per spec ES6, it seems to me like attempting to define a non-configurable
> property on a WindowProxy should throw and getting a property descriptor for
> a non-configurable property that got defined on the Window (e.g. via "var")
> should report it as configurable.

Yes, both of these conclusions are correct.


>  But that matches precisely 0 UAs.... and
> throwing seems like a compat worry.  :(
>
> Anyway, what are reasonable behaviors here?  What are UAs willing to align
> on?

The only reasonable behavior that I see is the one you specified.
Introducing an invariant violation of this sort would kill these
invariants in general, as the Proxy target mechanism relies on these
invariants to enforce that Proxies cannot introduce more violations.

Put another way, if this invariant is preserved by WindowProxy, then
anyone else seeking to create another object that violates this
invariant can create a Proxy whose target is a WindowProxy. Its
violation enables further violations. The invariants are inductive. A
violation breaks the induction.

From prior similar experiences, the way to get this fixed quickly is
to add test262 tests which fail on these violations. All browsers have
been much quicker to fix breakage that shows up in test262 results
than to mere bug reports.


>
> -Boris
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss



--
    Cheers,
    --MarkM
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Mark S. Miller
On Sun, Nov 30, 2014 at 6:12 PM, Mark S. Miller <[hidden email]> wrote:
[...]
> Put another way, if this invariant is preserved by WindowProxy, then

Should be: "is not preserved by" or "is violated by"

> anyone else seeking to create another object that violates this
> invariant can create a Proxy whose target is a WindowProxy. Its
> violation enables further violations. The invariants are inductive. A
> violation breaks the induction.


--

  Cheers,
  --MarkM
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Andreas Rossberg-4
In reply to this post by Mark S. Miller-2
On 1 December 2014 at 03:12, Mark S. Miller <[hidden email]> wrote:
> On Sun, Nov 30, 2014 at 12:21 PM, Boris Zbarsky <[hidden email]> wrote:
>> Per spec ES6, it seems to me like attempting to define a non-configurable
>> property on a WindowProxy should throw and getting a property descriptor for
>> a non-configurable property that got defined on the Window (e.g. via "var")
>> should report it as configurable.

Can you clarify? Do you mean that it should report properties as
configurable, but still reject attempts to actually reconfigure them?
Also, how would you allow 'var' to even define non-configurable
properties? If you want DefineProperty to throw on any such attempt,
then 'var' semantics would somehow have to bypass the MOP.

> From prior similar experiences, the way to get this fixed quickly is
> to add test262 tests which fail on these violations. All browsers have
> been much quicker to fix breakage that shows up in test262 results
> than to mere bug reports.

Well, let's find a workable semantics first. :)

/Andreas
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

David Bruant-5
Hi,

I feel like I've been in an equivalent discussion some time ago, so
taking the liberty to answer.

Le 02/12/2014 13:59, Andreas Rossberg a écrit :
> On 1 December 2014 at 03:12, Mark S. Miller <[hidden email]> wrote:
>> On Sun, Nov 30, 2014 at 12:21 PM, Boris Zbarsky <[hidden email]> wrote:
>>> Per spec ES6, it seems to me like attempting to define a non-configurable
>>> property on a WindowProxy should throw and getting a property descriptor for
>>> a non-configurable property that got defined on the Window (e.g. via "var")
>>> should report it as configurable.
> Can you clarify? Do you mean that it should report properties as
> configurable, but still reject attempts to actually reconfigure them?
Yes. This is doable with proxies (which the WindowProxy object needs to
be anyway).
* the defineProperty trap throws when it sees configurable:false
* the getOwnPropertyDescriptor trap always reports configurable:true
* and the target has all properties actually configurable (but it's
almost irrelevant to the discussion)

> Also, how would you allow 'var' to even define non-configurable
> properties? If you want DefineProperty to throw on any such attempt,
> then 'var' semantics would somehow have to bypass the MOP.
Thinking in terms of proxies, the runtime can have access to the target
and the handler while userland scripts only have access to the proxy
(which the HTML Living standard mandates anyway with the difference
between Window and WindowProxy objects. No userland script ever have
access to the Window object).
The handler can have access to the list all declared variable to know
which property should behave as if non-configurable.

David
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

David Bruant-5
Le 02/12/2014 14:24, David Bruant a écrit :
> Hi,
>
> I feel like I've been in an equivalent discussion some time ago
The topic felt familiar :-p
http://lists.w3.org/Archives/Public/public-script-coord/2012OctDec/0322.html

David
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Mark S. Miller
Yes. I was glad to find in that message a pointer back to
https://mail.mozilla.org/pipermail/es-discuss/2012-December/027114.html

On Tue, Dec 2, 2014 at 5:36 AM, David Bruant <[hidden email]> wrote:

> Le 02/12/2014 14:24, David Bruant a écrit :
>>
>> Hi,
>>
>> I feel like I've been in an equivalent discussion some time ago
>
> The topic felt familiar :-p
> http://lists.w3.org/Archives/Public/public-script-coord/2012OctDec/0322.html
>
>
> David
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss



--
Text by me above is hereby placed in the public domain

  Cheers,
  --MarkM
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Boris Zbarsky
In reply to this post by Andreas Rossberg-4
On 12/2/14, 4:59 AM, Andreas Rossberg wrote:
> On 1 December 2014 at 03:12, Mark S. Miller <[hidden email]> wrote:
>> On Sun, Nov 30, 2014 at 12:21 PM, Boris Zbarsky <[hidden email]> wrote:
>>> Per spec ES6, it seems to me like attempting to define a non-configurable
>>> property on a WindowProxy should throw and getting a property descriptor for
>>> a non-configurable property that got defined on the Window (e.g. via "var")
>>> should report it as configurable.
>
> Can you clarify? Do you mean that it should report properties as
> configurable, but still reject attempts to actually reconfigure them?

Yes, correct.

> Also, how would you allow 'var' to even define non-configurable
> properties?

Because "var" operates on the global directly.  The global is a Window,
not a WindowProxy and has no magic behavior.

> If you want DefineProperty to throw on any such attempt,
> then 'var' semantics would somehow have to bypass the MOP.

The idea is that WindowProxy's [[DefineOwnProperty]] would throw as
needed.  Window's [[DefineOwnProperty]] is just
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-ordinarydefineownproperty

-Boris
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Boris Zbarsky
In reply to this post by David Bruant-5
On 12/2/14, 5:24 AM, David Bruant wrote:
> The handler can have access to the list all declared variable to know
> which property should behave as if non-configurable.

That's not even needed.  If the handler just passes configurable defines
on through to the target for a property declared via "var", they will
end up in
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-validateandapplypropertydescriptor 
and throw in step 5.

-Boris
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Boris Zbarsky
In reply to this post by Mark S. Miller-2
On 11/30/14, 6:12 PM, Mark S. Miller wrote:
> On Sun, Nov 30, 2014 at 12:21 PM, Boris Zbarsky <[hidden email]> wrote:
>> Per spec ES6, it seems to me like attempting to define a non-configurable
>> property on a WindowProxy should throw and getting a property descriptor for
>> a non-configurable property that got defined on the Window (e.g. via "var")
>> should report it as configurable.
>
> Yes, both of these conclusions are correct.

OK.  What do we do if we discover that throwing from the defineProperty
call with a non-configurable property descriptor is not web-compatible?
  I'm going to try doing it in Firefox, and would welcome other UAs
doing it ASAP to figure out whether we're in that situation.

-Boris
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Mark S. Miller-2
On Thu, Dec 4, 2014 at 2:58 AM, Boris Zbarsky <[hidden email]> wrote:

> On 11/30/14, 6:12 PM, Mark S. Miller wrote:
>>
>> On Sun, Nov 30, 2014 at 12:21 PM, Boris Zbarsky <[hidden email]> wrote:
>>>
>>> Per spec ES6, it seems to me like attempting to define a non-configurable
>>> property on a WindowProxy should throw and getting a property descriptor
>>> for
>>> a non-configurable property that got defined on the Window (e.g. via
>>> "var")
>>> should report it as configurable.
>>
>>
>> Yes, both of these conclusions are correct.
>
>
> OK.  What do we do if we discover that throwing from the defineProperty call
> with a non-configurable property descriptor is not web-compatible?

What we always do, for example, when we found that having

     Object.prototype.toString.call(null)

throw was not web compatible. We look into the specifics of the
incompatibility encountered and design a non-web-breaking workaround
that is least painful for the semantics we desire. For example, in
this case, we changed it to return
"[object Null]" even though that string itself had never previously
been returned. The specific web compatibility we encountered for this
case merely required a non-throw. It did not care what the contents of
the string were. This outcome could not have been predicted from first
principles.

Other times, as when we found that introducing a new global variable
named "JSON" was not web compatible, we found we could evangelize the
origin of that incompatibility to fix it at the source, rather than
change the spec.


>  I'm
> going to try doing it in Firefox, and would welcome other UAs doing it ASAP
> to figure out whether we're in that situation.

Excellent! Bravo!


>
> -Boris



--
    Cheers,
    --MarkM
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Boris Zbarsky
In reply to this post by Boris Zbarsky
On 12/4/14, 10:44 AM, Travis Leithead wrote:
> So... this will prevent defining non-configurable properties on the global?

It will prevent using

   Object.defineProperty(window, "name",  non-configurable-descriptor);

to define a property.

Note that "window" is not the global.  It's a proxy whose target is the
global.

> Combined with [PrimaryGlobal], this seems at odds with what browsers do internally to prevent re-definition of some properties like "document"?

Browsers can define properties on the actual global, so there is no
problem here.

> Are we sure we want this restriction?

Well, good question.  If we don't do this restriction (by which I assume
defineProperty throwing; I assume getOwnPropertyDescriptor claiming
configurable always is less controversial), what do we want to do?

Note that I did a bit of digging into the history here and as far as I
can tell every single UA screwed up when implementing
Object.getOwnPropertyDescriptor and company in ES5.  ES5 clearly spells
out the rules for these methods, and browsers just didn't follow those
rules.  Plus lack of testing and here we are.

-Boris
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Boris Zbarsky
On 12/4/14, 1:36 PM, Travis Leithead wrote:
>> Note that "window" is not the global.  It's a proxy whose target is the global.
>
> Yes, but within a browser UA, there is no way to get a reference to the naked global because all entry-points return window proxies ;-)

Well, no way from web script.  The browser internals can do it,
presumably, right?

>> Well, good question.  If we don't do this restriction (by which I assume
>> defineProperty throwing; I assume getOwnPropertyDescriptor claiming
>> configurable always is less controversial), what do we want to do?
>
> As I look back on your original message, I fail to see what the problem is. You seem to think that the window proxy is referring to the same window object before and after the navigation.

The window proxy object identity does not change before and after the
navigation.

The window object the proxy is pointing to changes.

> In fact, in most implementations that I'm aware of, there is the concept of the "inner" and "outer" window.

Yes, I'm well aware.

> The "outer" window is the window proxy, which is the object that implements the cross-origin access control.

In Gecko, the cross-origin access control is actually implemented using
a separate security membrane proxy whose target is the "outer" window.
But sure.

> In IE's implementation, the window proxy has no storage as a typical JS var--it's only a semi-intelligent forwarder to its companion "inner" window.

That's an IE implementation detail.  In Gecko, the "window proxy" is a
JS proxy object with a proxy handler written in C++.  That, too, is an
implementation detail.

What matters here is what JS consumers see.  Consumers typically (there
are some exceptions involving scope chains) just see the window proxy, yes?

So when a script does:

   Object.defineProperty(frames[0], "foo", { value: true; });

It is defining a property on frames[0].  The fact that this is actually
a proxy for some other object (the global inside that iframe) is
somewhat of an implementation detail, again.  From the consumer's and
the spec's point of view, frames[0] is something with some internal
methods ([[GetOwnProperty]], [[DefineOwnProperty]], etc) which are
implemented in some way.  Still from the spec's point of view, the
implementation of these internal methods must satisfy
<http://people.mozilla.org/~jorendorff/es6-draft.html#sec-invariants-of-the-essential-internal-methods>.

> So, in your code sample, your "defineProperty" call forwarded to the "inner" window where the property was defined.

Sure.  I understand that.  As in, the proxy's [[DefineOwnProperty]]
invoke's the target's [[DefineOwnProperty]].

> After the navigation, the "inner" window was swapped out for a new one (and whole new type system at that) which the existing window proxy ("outer" window) now refers.

Sure.

> This gave the appearance of the non-configurable property disappearing

This isn't about "appearance".  The relevant spec invariant for
[[GetOwnProperty]], for example, is:

   If P’s attributes other than [[Writable]] may change over time or
   if the property might disappear, then P’s [[Configurable]] attribute
   must be true.

And Object.getOwnPropertyDescriptor is clearly defined to invoke
[[GetOwnProperty]].

So when a page does Object.getOwnPropertyDescriptor(window, "foo") this
is invoking the window proxy's [[GetOwnProperty]].  That's allowed to do
all sorts of stuff as long as it preserves the invariants involved,
including the one I quote above.  The fact that the "disappearing" is
due to the target changing is an implementation detail of the window proxy.

> but in reality it would still be there if you could get a reference to the "inner" window

Which doesn't matter, because the consumer is not interacting with the
"inner" window.

> *I wonder if you can capture the inner window in a scope chain or closure somehow

Sure, for a scope chain.  Testcase at
https://web.mit.edu/bzbarsky/www/testcases/windowproxy/use-old-window-1.html 
shows "OLD WINDOW" on the first line in Firefox, Chrome, and Safari.  In
IE11 it throws a "Can't execute code from a freed script" exception; I
can't find anything in the specs that allows that, fwiw.

> so that you could observe that "foo" is still there even though you can't directly see it anymore?

Absolutely.

> I think that might work if the executing code was defined in the old iframe's environment and executed after navigation...

Right.

But we're not talking about indirect probes like this here, just about
the basic invariants object internal methods are supposed to preserve.

-Boris
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Mark S. Miller
On Thu, Dec 4, 2014 at 4:32 PM, Boris Zbarsky <[hidden email]> wrote:

> On 12/4/14, 1:36 PM, Travis Leithead wrote:
>>>
>>> Note that "window" is not the global.  It's a proxy whose target is the
>>> global.
>>
>>
>> Yes, but within a browser UA, there is no way to get a reference to the
>> naked global because all entry-points return window proxies ;-)
>
>
> Well, no way from web script.  The browser internals can do it, presumably,
> right?
>
>>> Well, good question.  If we don't do this restriction (by which I assume
>>> defineProperty throwing; I assume getOwnPropertyDescriptor claiming
>>> configurable always is less controversial), what do we want to do?
>>
>>
>> As I look back on your original message, I fail to see what the problem
>> is. You seem to think that the window proxy is referring to the same window
>> object before and after the navigation.
>
>
> The window proxy object identity does not change before and after the
> navigation.
>
> The window object the proxy is pointing to changes.
>
>> In fact, in most implementations that I'm aware of, there is the concept
>> of the "inner" and "outer" window.
>
>
> Yes, I'm well aware.
>
>> The "outer" window is the window proxy, which is the object that
>> implements the cross-origin access control.
>
>
> In Gecko, the cross-origin access control is actually implemented using a
> separate security membrane proxy whose target is the "outer" window. But
> sure.
>
>> In IE's implementation, the window proxy has no storage as a typical JS
>> var--it's only a semi-intelligent forwarder to its companion "inner" window.
>
>
> That's an IE implementation detail.  In Gecko, the "window proxy" is a JS
> proxy object with a proxy handler written in C++.  That, too, is an
> implementation detail.
>
> What matters here is what JS consumers see.  Consumers typically (there are
> some exceptions involving scope chains) just see the window proxy, yes?
>
> So when a script does:
>
>   Object.defineProperty(frames[0], "foo", { value: true; });
>
> It is defining a property on frames[0].  The fact that this is actually a
> proxy for some other object (the global inside that iframe) is somewhat of
> an implementation detail, again.  From the consumer's and the spec's point
> of view, frames[0] is something with some internal methods
> ([[GetOwnProperty]], [[DefineOwnProperty]], etc) which are implemented in
> some way.  Still from the spec's point of view, the implementation of these
> internal methods must satisfy
> <http://people.mozilla.org/~jorendorff/es6-draft.html#sec-invariants-of-the-essential-internal-methods>.
>
>> So, in your code sample, your "defineProperty" call forwarded to the
>> "inner" window where the property was defined.
>
>
> Sure.  I understand that.  As in, the proxy's [[DefineOwnProperty]] invoke's
> the target's [[DefineOwnProperty]].
>
>> After the navigation, the "inner" window was swapped out for a new one
>> (and whole new type system at that) which the existing window proxy ("outer"
>> window) now refers.
>
>
> Sure.
>
>> This gave the appearance of the non-configurable property disappearing
>
>
> This isn't about "appearance".  The relevant spec invariant for
> [[GetOwnProperty]], for example, is:
>
>   If P’s attributes other than [[Writable]] may change over time or
>   if the property might disappear, then P’s [[Configurable]] attribute
>   must be true.
>
> And Object.getOwnPropertyDescriptor is clearly defined to invoke
> [[GetOwnProperty]].
>
> So when a page does Object.getOwnPropertyDescriptor(window, "foo") this is
> invoking the window proxy's [[GetOwnProperty]].  That's allowed to do all
> sorts of stuff as long as it preserves the invariants involved, including
> the one I quote above.  The fact that the "disappearing" is due to the
> target changing is an implementation detail of the window proxy.
>
>> but in reality it would still be there if you could get a reference to the
>> "inner" window
>
>
> Which doesn't matter, because the consumer is not interacting with the
> "inner" window.
>
>> *I wonder if you can capture the inner window in a scope chain or closure
>> somehow
>
>
> Sure, for a scope chain.  Testcase at
> https://web.mit.edu/bzbarsky/www/testcases/windowproxy/use-old-window-1.html

That page demands a client certificate. Is that intentional?


> shows "OLD WINDOW" on the first line in Firefox, Chrome, and Safari.  In
> IE11 it throws a "Can't execute code from a freed script" exception; I can't
> find anything in the specs that allows that, fwiw.
>
>> so that you could observe that "foo" is still there even though you can't
>> directly see it anymore?
>
>
> Absolutely.
>
>> I think that might work if the executing code was defined in the old
>> iframe's environment and executed after navigation...
>
>
> Right.
>
> But we're not talking about indirect probes like this here, just about the
> basic invariants object internal methods are supposed to preserve.
>
>
> -Boris
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss



--
  Cheers,
  --MarkM
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Boris Zbarsky
On 12/4/14, 4:45 PM, Mark Miller wrote:
> On Thu, Dec 4, 2014 at 4:32 PM, Boris Zbarsky <[hidden email]> wrote:
>> Sure, for a scope chain.  Testcase at
>> https://web.mit.edu/bzbarsky/www/testcases/windowproxy/use-old-window-1.html
>
> That page demands a client certificate. Is that intentional?

Er, sorry.
http://web.mit.edu/bzbarsky/www/testcases/windowproxy/use-old-window-1.html 
should work for everyone.

-Boris
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Mark S. Miller
On Thu, Dec 4, 2014 at 4:49 PM, Boris Zbarsky <[hidden email]> wrote:

> On 12/4/14, 4:45 PM, Mark Miller wrote:
>>
>> On Thu, Dec 4, 2014 at 4:32 PM, Boris Zbarsky <[hidden email]> wrote:
>>>
>>> Sure, for a scope chain.  Testcase at
>>>
>>> https://web.mit.edu/bzbarsky/www/testcases/windowproxy/use-old-window-1.html
>>
>>
>> That page demands a client certificate. Is that intentional?
>
>
> Er, sorry.
> http://web.mit.edu/bzbarsky/www/testcases/windowproxy/use-old-window-1.html
> should work for everyone.
>
> -Boris


Here's an unexpected weirdness, probably not deeply related. Change
your first helper page to


<script>
var someName = "OLD WINDOW";
var evil = eval;
function f() {
  return someName;
}
function g() {
  return (1,evil)("3");
}
</script>



On FF and Safari, I get 3 as expected. On Chrome, I get on my console:

    Uncaught EvalError: The "this" value passed to eval must be the
global object from which eval originated

Especially weird, because this code doesn't pass any this to the
renamed eval. I don't know what this means.



--
  Cheers,
  --MarkM
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Andreas Rossberg-4
On 5 December 2014 at 02:19, Mark Miller <[hidden email]> wrote:

> On Thu, Dec 4, 2014 at 4:49 PM, Boris Zbarsky <[hidden email]> wrote:
>> On 12/4/14, 4:45 PM, Mark Miller wrote:
>>>
>>> On Thu, Dec 4, 2014 at 4:32 PM, Boris Zbarsky <[hidden email]> wrote:
>>>>
>>>> Sure, for a scope chain.  Testcase at
>>>>
>>>> https://web.mit.edu/bzbarsky/www/testcases/windowproxy/use-old-window-1.html
>>>
>>>
>>> That page demands a client certificate. Is that intentional?
>>
>>
>> Er, sorry.
>> http://web.mit.edu/bzbarsky/www/testcases/windowproxy/use-old-window-1.html
>> should work for everyone.
>>
>> -Boris
>
> Here's an unexpected weirdness, probably not deeply related. Change
> your first helper page to
>
> <script>
> var someName = "OLD WINDOW";
> var evil = eval;
> function f() {
>   return someName;
> }
> function g() {
>   return (1,evil)("3");
> }
> </script>
>
> On FF and Safari, I get 3 as expected. On Chrome, I get on my console:
>
>     Uncaught EvalError: The "this" value passed to eval must be the
> global object from which eval originated
>
> Especially weird, because this code doesn't pass any this to the
> renamed eval. I don't know what this means.

This seems to be an attempt to kill off dead window contexts as early
as possible, in order to avoid memory leaks. Toon might be able to say
more.

/Andreas
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Ian Hickson
In reply to this post by Boris Zbarsky
On Thu, 4 Dec 2014, Boris Zbarsky wrote:
> On 12/4/14, 1:36 PM, Travis Leithead wrote:
> >
> > In IE's implementation, the window proxy has no storage as a typical
> > JS var--it's only a semi-intelligent forwarder to its companion
> > "inner" window.
>
> That's an IE implementation detail.

It's more than that. It's how the HTML spec defines WindowProxy.


> So when a script does:
>
>    Object.defineProperty(frames[0], "foo", { value: true; });
>
> It is defining a property on frames[0].  The fact that this is actually
> a proxy for some other object (the global inside that iframe) is
> somewhat of an implementation detail, again.

According to the HTML spec, all operations that would be performed on the
WindowProxy object must be performed on the Window object of the browsing
context's active document instead. So the above would set a property on
the underlying Window object, not the WindowProxy.


> This isn't about "appearance".  The relevant spec invariant for
> [[GetOwnProperty]], for example, is:
>
>    If P’s attributes other than [[Writable]] may change over time or
>    if the property might disappear, then P’s [[Configurable]] attribute
>    must be true.
>
> And Object.getOwnPropertyDescriptor is clearly defined to invoke
> [[GetOwnProperty]].
>
> So when a page does Object.getOwnPropertyDescriptor(window, "foo") this
> is invoking the window proxy's [[GetOwnProperty]].
...but the window proxy's [[GetOwnProperty]] just forwards that straight
to the Window's [[GetOwnProperty]].

The property is on the Window, not the WindowProxy. It can't disappear
from the Window. The invariant is thus maintained.

There is no way to directly query the WindowProxy. To all intents and
purposes, it's not a real object. It's a reference to another object,
which happens to change during navigation.

--
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Boris Zbarsky
On 1/14/15 3:17 PM, Ian Hickson wrote:
> It's more than that. It's how the HTML spec defines WindowProxy.

The point is, the HTML spec's definition is not expressible in ES terms.
  So how do go about bridging this gap?

> According to the HTML spec, all operations that would be performed on the
> WindowProxy object must be performed on the Window object of the browsing
> context's active document instead. So the above would set a property on
> the underlying Window object, not the WindowProxy.

It would call the [[DefineOwnProperty]] trap of the WindowProxy.  That
then forwards to the Window, yes?

> ...but the window proxy's [[GetOwnProperty]] just forwards that straight
> to the Window's [[GetOwnProperty]].

Yes, but since which window it forwards to changes you get an invariant
violation for the WindowProxy object itself.

> The property is on the Window, not the WindowProxy. It can't disappear
> from the Window. The invariant is thus maintained.

I think you misunderstand what the invariant is.

> There is no way to directly query the WindowProxy.

It doesn't matter.  The user sees the WindowProxy, not the Window. After
you navigate, you still have the same WindowProxy (e.g. .contentWindow
returns something that is === to the thing you had before you
navigated).  But properties it claimed to have that were
non-configurable are now gone.  That is precisely a violation of the
invariants.

> To all intents and purposes, it's not a real object.

It looks like an object and quacks like an object.  Sorry, but it's an
object as far as all consumers are concerned; they have no way to tell
it apart from an object except _maybe_ via these invariant violations.
But then you've entered circular argument territory.

> It's a reference to another object

JS doesn't have such a type in the language, sadly, so we can't model it
that way for consumers.

-Boris
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Figuring out the behavior of WindowProxy in the face of non-configurable properties

Mark S. Miller-2
Boris has this exactly right. Further, a malicious proxy handler can leverage the presence of a single object that violates these invariants into the creation of arbitrary other proxies objects that also violate these invariants. The key is that the enforcement of the invariants relies on the proxy's target being constrained by these invariants.




On Wed, Jan 14, 2015 at 2:32 PM, Boris Zbarsky <[hidden email]> wrote:
On 1/14/15 3:17 PM, Ian Hickson wrote:
It's more than that. It's how the HTML spec defines WindowProxy.

The point is, the HTML spec's definition is not expressible in ES terms.  So how do go about bridging this gap?

According to the HTML spec, all operations that would be performed on the
WindowProxy object must be performed on the Window object of the browsing
context's active document instead. So the above would set a property on
the underlying Window object, not the WindowProxy.

It would call the [[DefineOwnProperty]] trap of the WindowProxy.  That then forwards to the Window, yes?

...but the window proxy's [[GetOwnProperty]] just forwards that straight
to the Window's [[GetOwnProperty]].

Yes, but since which window it forwards to changes you get an invariant violation for the WindowProxy object itself.

The property is on the Window, not the WindowProxy. It can't disappear
from the Window. The invariant is thus maintained.

I think you misunderstand what the invariant is.

There is no way to directly query the WindowProxy.

It doesn't matter.  The user sees the WindowProxy, not the Window. After you navigate, you still have the same WindowProxy (e.g. .contentWindow returns something that is === to the thing you had before you navigated).  But properties it claimed to have that were non-configurable are now gone.  That is precisely a violation of the invariants.

To all intents and purposes, it's not a real object.

It looks like an object and quacks like an object.  Sorry, but it's an object as far as all consumers are concerned; they have no way to tell it apart from an object except _maybe_ via these invariant violations. But then you've entered circular argument territory.

It's a reference to another object

JS doesn't have such a type in the language, sadly, so we can't model it that way for consumers.

-Boris



--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
123