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

2015-01-28 Thread Domenic Denicola
From: Mark S. Miller [mailto:erig...@google.com] 

 On Tue, Jan 27, 2015 at 5:53 PM, Boris Zbarsky bzbar...@mit.edu wrote:
 I'd like to understand better the suggestion here, because I'm not sure I'm 
 entirely following it.  Specifically, I'd like to understand it in terms of 
 the internal methods defined by 
 https://github.com/domenic/window-proxy-spec.

 Presumably you're proposing that we keep all of that as-is except for 
 [[DefineOwnProperty]], right?

 For [[DefineOwnProperty]], are we basically talking about changing step 1 to:

 1)  If the [[Configurable]] field of Desc is present and 
 Desc.[[Configurable]] is false, then throw a TypeError exception.

 while keeping everything else as-is,

 Exactly correct. I didn't realize until reading your reply is that this is 
 all that's necessary -- that it successfully covers all the cases I was 
 thinking about without any further case division.

I'm having a bit of trouble understanding how this maps to the solution 
described in your previous message, Mark. Your I didn't realize until reading 
your reply is that this is all that's necessary indicates I'm probably just 
missing something, so help appreciated.

My question is, what happens if Desc.[[Configurable]] is not present, and P 
does not already exist on W? By my reading, we then fall through to calling the 
[[DefineOwnProperty]] internal method of W with arguments P and Desc.

Assuming W's [[DefineOwnProperty]] is that of an ordinary object, I believe 
that takes us through OrdinaryDefineOwnProperty(W, P, Desc). Since P does not 
exist on W, and W is extensible, that takes us to 
ValidateAndApplyPropertyDescriptor(O, P, true, Desc, undefined). Then according 
to step 2.c,  If the value of an attribute field of Desc is absent, the 
attribute of the newly created property is set to its default value. The 
default value is false, right? So won't this try to define a non-configurable 
property on W?

I would have thought the modification needed to be more like:

[[DefineOwnProperty]] (P, Desc)

1. If desc.[[Configurable]] is not present, set desc.[[Configurable]] to true.
2. If desc.[[Configurable]] is false, then throw a TypeError exception.
3. Return the result of calling the [[DefineOwnProperty]] internal method of W 
with arguments P and Desc.

(here I have inserted step 1, but step 2 and 3 are unchanged from the previous 
incarnation).
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-28 Thread Mark S. Miller
On Wed, Jan 28, 2015 at 8:51 AM, Domenic Denicola d...@domenic.me wrote:

 From: Mark S. Miller [mailto:erig...@google.com]

  On Tue, Jan 27, 2015 at 5:53 PM, Boris Zbarsky bzbar...@mit.edu wrote:
  I'd like to understand better the suggestion here, because I'm not sure
 I'm entirely following it.  Specifically, I'd like to understand it in
 terms of the internal methods defined by 
 https://github.com/domenic/window-proxy-spec.
 
  Presumably you're proposing that we keep all of that as-is except for
 [[DefineOwnProperty]], right?
 
  For [[DefineOwnProperty]], are we basically talking about changing step
 1 to:
 
  1)  If the [[Configurable]] field of Desc is present and
 Desc.[[Configurable]] is false, then throw a TypeError exception.
 
  while keeping everything else as-is,
 
  Exactly correct. I didn't realize until reading your reply is that this
 is all that's necessary -- that it successfully covers all the cases I was
 thinking about without any further case division.

 I'm having a bit of trouble understanding how this maps to the solution
 described in your previous message, Mark. Your I didn't realize until
 reading your reply is that this is all that's necessary indicates I'm
 probably just missing something, so help appreciated.

 My question is, what happens if Desc.[[Configurable]] is not present, and
 P does not already exist on W? By my reading, we then fall through to
 calling the [[DefineOwnProperty]] internal method of W with arguments P and
 Desc.

 Assuming W's [[DefineOwnProperty]] is that of an ordinary object, I
 believe that takes us through OrdinaryDefineOwnProperty(W, P, Desc). Since
 P does not exist on W, and W is extensible, that takes us to
 ValidateAndApplyPropertyDescriptor(O, P, true, Desc, undefined). Then
 according to step 2.c,  If the value of an attribute field of Desc is
 absent, the attribute of the newly created property is set to its default
 value. The default value is false, right? So won't this try to define a
 non-configurable property on W?


In this situation, it will try and succeed. This more closely obeys the
intent in the original code (e.g., the comment in the jQuery code), since
it creates a non-configurable property on the *Window* W. It does not
violate any invariant, since all that's observable on the *WindowProxy*
(given the rest of your draft spec, which remain unchanged) is a
configurable property of the same name.





 I would have thought the modification needed to be more like:

 [[DefineOwnProperty]] (P, Desc)

 1. If desc.[[Configurable]] is not present, set desc.[[Configurable]] to
 true.
 2. If desc.[[Configurable]] is false, then throw a TypeError exception.
 3. Return the result of calling the [[DefineOwnProperty]] internal method
 of W with arguments P and Desc.

 (here I have inserted step 1, but step 2 and 3 are unchanged from the
 previous incarnation).




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-28 Thread Mark S. Miller
On Wed, Jan 28, 2015 at 11:08 AM, Domenic Denicola d...@domenic.me wrote:

 From: Mark S. Miller [mailto:erig...@google.com]

  In this situation, it will try and succeed. This more closely obeys the
 intent in the original code (e.g., the comment in the jQuery code), since
 it creates a non-configurable property on the *Window* W. It does not
 violate any invariant, since all that's observable on the *WindowProxy*
 (given the rest of your draft spec, which remain unchanged) is a
 configurable property of the same name.

 Ah, I see! So then another non-intuitive (but invariant-preserving)
 consequence would be:

 ```js
 Object.defineProperty(window, prop, { value: foo });

 var propDesc = Object.getOwnPropertyDescriptor(window, prop);

 if (propDesc.configurable) {
   Object.defineProperty(window, prop, { value: bar });

   // this will fail, even though the property is supposedly configurable,
   // since when it forwards from the WindowProxy `window` to the underlying
   // Window object, it the Window's [[DefineOwnProperty]] fails.
 }
 ```

 Am I getting this right?


Exactly, yes. And again, if window is an ES6 proxy rather that a
WindowProxy, it could also cause this behavior, so it doesn't create any
situation which is not otherwise possible.

The key points are:

1) The throw does (arguably) better obey the code's intent, since the
property mostly acts like a non-configurable property until the window is
navigated.

2) If a window navigation happens between your first step and your second,
the second step may well succeed, which is what we (arguably) want, but
which would have been prohibited if propDesc.configurable evaluated to true.


-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-28 Thread Domenic Denicola
From: Mark S. Miller [mailto:erig...@google.com] 

 In this situation, it will try and succeed. This more closely obeys the 
 intent in the original code (e.g., the comment in the jQuery code), since it 
 creates a non-configurable property on the *Window* W. It does not violate 
 any invariant, since all that's observable on the *WindowProxy* (given the 
 rest of your draft spec, which remain unchanged) is a configurable property 
 of the same name.

Ah, I see! So then another non-intuitive (but invariant-preserving) consequence 
would be:

```js
Object.defineProperty(window, prop, { value: foo });

var propDesc = Object.getOwnPropertyDescriptor(window, prop);

if (propDesc.configurable) {
  Object.defineProperty(window, prop, { value: bar });

  // this will fail, even though the property is supposedly configurable,
  // since when it forwards from the WindowProxy `window` to the underlying
  // Window object, it the Window's [[DefineOwnProperty]] fails.
}
```

Am I getting this right?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-28 Thread Brendan Eich

Mark S. Miller wrote:


Exactly correct. I didn't realize until reading your reply is that
this is all that's necessary -- that it successfully covers all
the cases I was thinking about without any further case division.


Here's another option, not clearly better or worse:


  [[DefineOwnProperty]] (P, Desc)

 1. let R be the result of calling the [[DefineOwnProperty]] internal
method of/W/with arguments/P/and /Desc/.
 2. If/desc/.[[Configurable]] is present and*false*, then throw
a*TypeError*exception.
 3. return R.

This is exactly like your solution, but with the order of the two 
steps switched. Perhaps the next breakage we see will tell us which of 
these to choose. If both are web compatible, then we need only pick 
which one we like better.


I like the shorter one (filling in from cited text below, here it is in 
full:



 [[DefineOwnProperty]] (P, Desc)

1. If /desc/.[[Configurable]] is present and/desc/.[[Configurable]] is
   *false*, then throw a *TypeError* exception.
2. Return the result of calling the [[DefineOwnProperty]] internal
   method of /W/ with arguments /P/ and /Desc/.


Besides being shorter, this doesn't call through to [[DOP]], which could 
have effects, and only then maybe-throw.


/be



as opposed to the behavior I'd understood we were aiming for,
which was:

1)  If the [[Configurable]] field of Desc is not present or
Desc.[[Configurable]] is false, then throw a TypeError exception. 



?  If so, that's certainly a change that is much more likely
to be web-compatible...


Good! It certainly takes care of the one concrete breakage we know
about so far.


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-27 Thread Boris Zbarsky

On 12/4/14 11:49 AM, Mark S. Miller wrote:

On Thu, Dec 4, 2014 at 2:58 AM, Boris Zbarsky bzbar...@mit.edu wrote:

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


So just for the record, jQuery (at least all the 2.* versions I've 
looked at) contains that following bits:


  Data.prototype = {
key: function( owner ) {
...
var descriptor = {},
...
// Secure it in a non-enumerable, non-writable property
try {
descriptor[ this.expando ] = { value: unlock };
Object.defineProperties( owner, descriptor );

// Support: Android  4
// Fallback to a less secure definition
} catch ( e ) {
descriptor[ this.expando ] = unlock;
jQuery.extend( owner, descriptor );
}

This function is called from Data.prototype.get, which is called from 
jQuery.event.add.  So the upshot is that trying to add an event listener 
to the window via the jQuery API will hit this codepath.


Now the good news is that the try/catch _is_ present there, so this 
doesn't immediately break sites.  But it's something to watch out for, 
and we _will_ be changing the behavior of jQuery here in a way that the 
jQuery developers clearly think is undesirable.


-Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-27 Thread Mark S. Miller
Yehuda and I just talked about this code and realized that we can allow
this code to proceed on the success path without violating the invariants.
However, this analysis reveals that the intent stated in the comment is
unwarranted, but even that intent can be adequately honored in the scenario
of interest.

The reason why the intent is unwarranted is that the descriptor omits
configurable: rather than explicitly saying configurable: true. If the
owner object already has a configurable own property of the same name, then
a defineProperty where the configurable: is omitted defines an own
property preserving the configurability of the original own property.

Even if owner could not have already had an own property of this name,
owner might be an ES6 proxy whose target is, say, an empty object. The
handler's defineProperty trap could still first define a configurable own
property of this name, and then proceed with the normal logic.

Since the WindowProxy is not a Proxy, or more relevantly, even if it were a
Proxy, the underlying Window is not its target, we can even do the
following:

When the WindowProxy sees the defineProperty with the omitted
configurable: and determines that the underlying Window does not already
have this property. WindowProxy can even preserve the unwarranted intent
expressed in the comment by actually defining a *non-configurable* own
property on the Window itself. However, the behavior of the WindowProxy is
not observably different than our Proxy example: It acts as if it created a
configurable own property on the WindowProxy of this same name, and then
proceeds with the normal defineProperty behavior, which preserves that
alleged configurability.






On Tue, Jan 27, 2015 at 11:48 AM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 12/4/14 11:49 AM, Mark S. Miller wrote:

 On Thu, Dec 4, 2014 at 2:58 AM, Boris Zbarsky bzbar...@mit.edu wrote:

 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


 So just for the record, jQuery (at least all the 2.* versions I've looked
 at) contains that following bits:

   Data.prototype = {
 key: function( owner ) {
 ...
 var descriptor = {},
 ...
 // Secure it in a non-enumerable, non-writable
 property
 try {
 descriptor[ this.expando ] = { value:
 unlock };
 Object.defineProperties( owner, descriptor
 );

 // Support: Android  4
 // Fallback to a less secure definition
 } catch ( e ) {
 descriptor[ this.expando ] = unlock;
 jQuery.extend( owner, descriptor );
 }

 This function is called from Data.prototype.get, which is called from
 jQuery.event.add.  So the upshot is that trying to add an event listener to
 the window via the jQuery API will hit this codepath.

 Now the good news is that the try/catch _is_ present there, so this
 doesn't immediately break sites.  But it's something to watch out for, and
 we _will_ be changing the behavior of jQuery here in a way that the jQuery
 developers clearly think is undesirable.

 -Boris




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-27 Thread Boris Zbarsky

On 1/27/15 4:44 PM, Mark S. Miller wrote:

Since the WindowProxy is not a Proxy, or more relevantly, even if it
were a Proxy, the underlying Window is not its target, we can even do
the following:

When the WindowProxy sees the defineProperty with the omitted
configurable: and determines that the underlying Window does not
already have this property. WindowProxy can even preserve the
unwarranted intent expressed in the comment by actually defining a
*non-configurable* own property on the Window itself. However, the
behavior of the WindowProxy is not observably different than our Proxy
example: It acts as if it created a configurable own property on the
WindowProxy of this same name, and then proceeds with the normal
defineProperty behavior, which preserves that alleged configurability.


I'd like to understand better the suggestion here, because I'm not sure 
I'm entirely following it.  Specifically, I'd like to understand it in 
terms of the internal methods defined by 
https://github.com/domenic/window-proxy-spec.


Presumably you're proposing that we keep all of that as-is except for 
[[DefineOwnProperty]], right?


For [[DefineOwnProperty]], are we basically talking about changing step 
1 to:


1)  If the [[Configurable]] field of Desc is present and 
Desc.[[Configurable]] is false, then throw a TypeError exception.


while keeping everything else as-is, as opposed to the behavior I'd 
understood we were aiming for, which was:


1)  If the [[Configurable]] field of Desc is not present or 
Desc.[[Configurable]] is false, then throw a TypeError exception.


?  If so, that's certainly a change that is much more likely to be 
web-compatible...


-Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-27 Thread Brendan Eich

Mark S. Miller wrote:
The reason why the intent is unwarranted is that the descriptor omits 
configurable: rather than explicitly saying configurable: true. If 
the owner object already has a configurable own property of the same 
name, then a defineProperty where the configurable: is omitted 
defines an own property preserving the configurability of the original 
own property.


Wild, and genius. How many more narrow escapes can we make and keep both 
web compat and integrity? :-P


Is there any downside? What is the bad case that observably changes 
behavior, if any (not involving proxies)? I'm too tired to search the 
state space right now, throwing this out as a challenge.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-27 Thread Mark S. Miller
On Tue, Jan 27, 2015 at 9:45 PM, Mark S. Miller erig...@google.com wrote:



 On Tue, Jan 27, 2015 at 5:53 PM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 1/27/15 4:44 PM, Mark S. Miller wrote:

 Since the WindowProxy is not a Proxy, or more relevantly, even if it
 were a Proxy, the underlying Window is not its target, we can even do
 the following:

 When the WindowProxy sees the defineProperty with the omitted
 configurable: and determines that the underlying Window does not
 already have this property. WindowProxy can even preserve the
 unwarranted intent expressed in the comment by actually defining a
 *non-configurable* own property on the Window itself. However, the
 behavior of the WindowProxy is not observably different than our Proxy
 example: It acts as if it created a configurable own property on the
 WindowProxy of this same name, and then proceeds with the normal
 defineProperty behavior, which preserves that alleged configurability.


 I'd like to understand better the suggestion here, because I'm not sure
 I'm entirely following it.  Specifically, I'd like to understand it in
 terms of the internal methods defined by https://github.com/domenic/
 window-proxy-spec.

 Presumably you're proposing that we keep all of that as-is except for
 [[DefineOwnProperty]], right?

 For [[DefineOwnProperty]], are we basically talking about changing step 1
 to:

 1)  If the [[Configurable]] field of Desc is present and
 Desc.[[Configurable]] is false, then throw a TypeError exception.

 while keeping everything else as-is,


 Exactly correct. I didn't realize until reading your reply is that this is
 all that's necessary -- that it successfully covers all the cases I was
 thinking about without any further case division.


Here's another option, not clearly better or worse:

[[DefineOwnProperty]] (P, Desc)

   1. let R be the result of calling the [[DefineOwnProperty]] internal
   method of *W* with arguments *P* and *Desc*.
   2. If *desc*.[[Configurable]] is present and *false*, then throw a
   *TypeError* exception.
   3. return R.

This is exactly like your solution, but with the order of the two steps
switched. Perhaps the next breakage we see will tell us which of these to
choose. If both are web compatible, then we need only pick which one we
like better.






 as opposed to the behavior I'd understood we were aiming for, which was:

 1)  If the [[Configurable]] field of Desc is not present or
 Desc.[[Configurable]] is false, then throw a TypeError exception.


 ?  If so, that's certainly a change that is much more likely to be
 web-compatible...


 Good! It certainly takes care of the one concrete breakage we know about
 so far.



 --
 Cheers,
 --MarkM




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-27 Thread Mark S. Miller
On Tue, Jan 27, 2015 at 5:53 PM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 1/27/15 4:44 PM, Mark S. Miller wrote:

 Since the WindowProxy is not a Proxy, or more relevantly, even if it
 were a Proxy, the underlying Window is not its target, we can even do
 the following:

 When the WindowProxy sees the defineProperty with the omitted
 configurable: and determines that the underlying Window does not
 already have this property. WindowProxy can even preserve the
 unwarranted intent expressed in the comment by actually defining a
 *non-configurable* own property on the Window itself. However, the
 behavior of the WindowProxy is not observably different than our Proxy
 example: It acts as if it created a configurable own property on the
 WindowProxy of this same name, and then proceeds with the normal
 defineProperty behavior, which preserves that alleged configurability.


 I'd like to understand better the suggestion here, because I'm not sure
 I'm entirely following it.  Specifically, I'd like to understand it in
 terms of the internal methods defined by https://github.com/domenic/
 window-proxy-spec.

 Presumably you're proposing that we keep all of that as-is except for
 [[DefineOwnProperty]], right?

 For [[DefineOwnProperty]], are we basically talking about changing step 1
 to:

 1)  If the [[Configurable]] field of Desc is present and
 Desc.[[Configurable]] is false, then throw a TypeError exception.

 while keeping everything else as-is,


Exactly correct. I didn't realize until reading your reply is that this is
all that's necessary -- that it successfully covers all the cases I was
thinking about without any further case division.



 as opposed to the behavior I'd understood we were aiming for, which was:

 1)  If the [[Configurable]] field of Desc is not present or
 Desc.[[Configurable]] is false, then throw a TypeError exception.


 ?  If so, that's certainly a change that is much more likely to be
 web-compatible...


Good! It certainly takes care of the one concrete breakage we know about so
far.



-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-27 Thread Mark S. Miller
On Tue, Jan 27, 2015 at 7:22 PM, Brendan Eich bren...@mozilla.org wrote:

 Mark S. Miller wrote:

 The reason why the intent is unwarranted is that the descriptor omits
 configurable: rather than explicitly saying configurable: true. If the
 owner object already has a configurable own property of the same name, then
 a defineProperty where the configurable: is omitted defines an own
 property preserving the configurability of the original own property.


 Wild, and genius.


(blush)



 How many more narrow escapes can we make and keep both web compat and
 integrity? :-P


How many will we need? ;)




 Is there any downside? What is the bad case that observably changes
 behavior, if any (not involving proxies)?


You get the following non-intuitive but allowed behavior.

if (!hasOwnProperty(W, P)) {
  defineProperty(W, P, { value: V })
  console.log(getOwnPropertyDescriptor(W, P).configurable); // true
}

However, you could also get this behavior if W is a proxy, so it doesn't
introduce any new cases beyond what's already possible. It is only
surprising.

That's not much of a downside, and I can't think of any other downside.


I'm too tired to search the state space right now, throwing this out as a
 challenge.



-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-15 Thread Boris Zbarsky

On 1/15/15 1:22 PM, Ian Hickson wrote:

It's what IE does, according to Travis.


I'll let Travis address this.


Care to ask the UA implementors who are clearly not doing anything even
resembling your spec?  Because it might turn out they might have reasons
for it...


I've asked you many times.


I'm not one of those implementors.  What Gecko does right now is more or 
less black-box indistinguishable from your spec, modulo cross-origin 
issues.  However we may be changing what we do; we'll see.



Implementations disagreeing with each other doesn't mean the spec is
undefined.


But it can well mean they're not willing to implement it as written.


It doesn't match _all_ implementations, certainly.


OK, but have you bothered to find out why?


Per the HTML spec, there's two ways that WindowProxy can change. One is
session history traversal. That can never happen with JS on the stack


Are you sure, given showModalDialog?

-Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-15 Thread Ian Hickson
On Thu, 15 Jan 2015, Boris Zbarsky wrote:
  
  It doesn't match _all_ implementations, certainly.
 
 OK, but have you bothered to find out why?

The usual reason is just that there was no spec initially, and that the 
relevant implementations haven't bothered to fix it since the spec was 
written.


  Per the HTML spec, there's two ways that WindowProxy can change. One 
  is session history traversal. That can never happen with JS on the 
  stack
 
 Are you sure, given showModalDialog?

I'm assuming that showModalDialog() is dead. showModalDialog() breaks 
every assumption under the sun and is generally bad news.

-- 
Ian Hickson   U+1047E)\._.,--,'``.fL
http://ln.hixie.ch/   U+263A/,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Ian Hickson
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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Domenic Denicola
From: Travis Leithead [mailto:travis.leith...@microsoft.com] 

 WindowProxies are going to be a challenge when it comes to a pure ES 
 implementation.

Shouldn't be too hard to implement a Direct Proxy that follows this proto-spec: 
https://github.com/domenic/window-proxy-spec

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Boris Zbarsky

On 1/14/15 5:58 PM, Travis Leithead wrote:

The other challenge that just came to mind, is the
document object—at least in Gecko and IE: a document.write call will
“re-init” the object (subbing out the old var for a new one)


What Gecko does on document.open is just create a new Window, just like 
navigation.  This part is actually pretty clearly defined in the HTML spec.


-Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Ian Hickson
On Wed, 14 Jan 2015, Boris Zbarsky 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?

I don't understand what you mean by expressible in ES terms.

It's expressed in English.


  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?

No. WindowProxy isn't an ES Proxy. (The term WindowProxy predates ES 
Proxy). When you have a WindowProxy object, it acts exactly like the 
Window object to which it currently points. It is indistinguishable from 
the Window object. When the WindowProxy changes what it's pointing at, 
it's exactly as if the browser had reached in and changed every 
WindowProxy that pointed to the former and made it point to the latter.


  ...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.

I don't understand how that follows.


  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.

Maybe. Please elaborate.


  There is no way to directly query the WindowProxy.
 
 It doesn't matter.  The user sees the WindowProxy, not the Window.

No. What the author has is a WindowProxy, but in every sense it acts like 
a Window. (Which Window it acts like changes occasionally.)


 After you navigate, you still have the same WindowProxy (e.g. 
 .contentWindow returns something that is === to the thing you had before 
 you navigated).

You have no way to actually test this. Since every reference to the old 
Window is now a reference to the new Window, you have no way to test if 
the WindowProxy references something new. It's just like if the browser 
had reached in and changed all your references from under you.


 But properties it claimed to have that were non-configurable are now 
 gone.  That is precisely a violation of the invariants.

Suppose you have this code:

   // part 1
   let a = {};
   let b = {};
   let c = a;

   // part 2
   c.foo = 1;

   // part 3
   c = b;

   // part 4
   console.log(c.foo);

Is it surprising that the log doesn't log 1?

This is what is going on here, except that part 3 is done by the browser.


  To all intents and purposes, it's not a real object.
 
 It looks like an object and quacks like an object.

It looks and quacks like a Window.


  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.

It turns out that it does have such a type. WindowProxy is it. I agree 
that that makes it a special snowflake.



On Wed, 14 Jan 2015, Mark S. Miller wrote:

 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.
 
 See http://research.google.com/pubs/pub40736.html

If you're exposing your Window object to untrusted code you are so far 
beyond losing that this is the least of your concerns.

-- 
Ian Hickson   U+1047E)\._.,--,'``.fL
http://ln.hixie.ch/   U+263A/,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Mark S. Miller
Hi Travis, I didn't follow. Could you expand, assuming less background
knowledge?  Thanks.
 On Jan 14, 2015 2:58 PM, Travis Leithead travis.leith...@microsoft.com
wrote:

  WindowProxies are going to be a challenge when it comes to a pure ES
 implementation. The other challenge that just came to mind, is the document
 object—at least in Gecko and IE: a document.write call will “re-init” the
 object (subbing out the old var for a new one) while maintaining the ===
 invariant. Chrome appears to have a simpler model for dealing with this.
 I’m not sure what HTML has to say about this currently…



 *From:* Mark S. Miller [mailto:erig...@google.com]
 *Sent:* Wednesday, January 14, 2015 2:44 PM
 *To:* Boris Zbarsky
 *Cc:* Ian Hickson; Travis Leithead; Domenic Denicola;
 public-script-co...@w3.org; es-discuss
 *Subject:* Re: Figuring out the behavior of WindowProxy in the face of
 non-configurable properties



 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.



 See http://research.google.com/pubs/pub40736.html







 On Wed, Jan 14, 2015 at 2:32 PM, Boris Zbarsky bzbar...@mit.edu 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Boris Zbarsky

On 1/14/15 7:40 PM, Ian Hickson wrote:

I don't understand what you mean by expressible in ES terms.


The behavior of ES objects is expressed in terms of various internal 
methods.  That's what you have to do to express what an ES object does.



No. WindowProxy isn't an ES Proxy.


It's an ES object.


It is indistinguishable from the Window object.


It's distinguishable in various ways, including things like if I get 
this property from it in 5 seconds, will I get the same value as from 
the Window?  The answer to that is maybe not.



When the WindowProxy changes what it's pointing at,
it's exactly as if the browser had reached in and changed every
WindowProxy that pointed to the former and made it point to the latter.


You say every WindowProxy, but in practice in an ES implementation you 
have some object, it has some internal methods.  This is the last time 
I'm bothering to go through this with you, since clearly we're getting 
nowhere, as I said in https://www.w3.org/Bugs/Public/show_bug.cgi?id=27128



I don't understand how that follows.


I don't understand how you can possibly not understand, except via your 
assumption that a WindowProxy is not an object.



I think you misunderstand what the invariant is.


Maybe. Please elaborate.


The internal methods of every object must have behavior that preserves 
the invariants.


For ES proxies, the internal methods are defined in the spec in a way 
that preserves the invariant.


For other ES objects they are also defined in the spec.

ES also allows other exotic objects that define some other behavior 
for those internal methods, but requires that the invariants be preserved.



It doesn't matter.  The user sees the WindowProxy, not the Window.


No. What the author has is a WindowProxy, but in every sense it acts like
a Window.


You mean in every sense except what property values you'll get five 
seconds from now.


But again, we agree the author has a WindowProxy.  Good.


After you navigate, you still have the same WindowProxy (e.g.
.contentWindow returns something that is === to the thing you had before
you navigated).


You have no way to actually test this. Since every reference to the old
Window is now a reference to the new Window, you have no way to test if
the WindowProxy references something new.


=== on objects tests object identity.  It's not affected by internal 
methods in any way.  Therefore, if === returns true then you actually 
have the same object.



// part 1
let a = {};
let b = {};
let c = a;

// part 2
c.foo = 1;

// part 3
c = b;

// part 4
console.log(c.foo);

Is it surprising that the log doesn't log 1?


None of this affects the invariants involved.


This is what is going on here, except that part 3 is done by the browser.


No, because in the code above if I do |var d = c;| then the d won't 
change in part 3.  Having an object with sane internal methods here is 
really much simpler than magic update all the references behavior. 
But again, I've said this to you numerous times.


Let me try it again: the fact that the definition in the HTML spec has 
not lead to interop is not an accident.  It's not something browsers can 
sanely achieve interop on because it involves handwavy magic that they 
are extremely likely to interpret differently.  On the other hand, 
defining a single object with internal methods that do what you want 
would be _very_ clear to an DOM or JS engine implementor.



It looks and quacks like a Window.


No, it, doesn't, see above.


It turns out that it does have such a type. WindowProxy is it. I agree
that that makes it a special snowflake.


My point is that this special snowflake is unnecessary and confusing.

-Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Mark S. Miller
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.

See http://research.google.com/pubs/pub40736.html



On Wed, Jan 14, 2015 at 2:32 PM, Boris Zbarsky bzbar...@mit.edu 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Yehuda Katz
bz said:

 ES also allows other exotic objects that define some other behavior
 for those internal methods, but requires that the invariants be
 preserved.

Hixie said:

So one option would be to just say that WindowProxy is not an ES object.

---

If it's available to JavaScript consumers it must look like an object that
obeys ES invariants to JavaScript consumers. No (new, ugh) exceptions.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Boris Zbarsky

On 1/14/15 8:56 PM, Bjoern Hoehrmann wrote:

What are the odds that the behavior observable by web pages can actually
be defined sanely such that ES invariants and compatibility requirements
are satisfied?


My personal best estimate is about 30% chance for the one such 
definition we have so far being web compatible.  But this is mostly 
based on gut feeling.



https://www.w3.org/Bugs/Public/show_bug.cgi?id=27128#c15
indicates, as I understand it, the odds may be quite good. In that case,
looking for a volunteer to come up with a proposal might be a good next
step.


We have a proposal.  It's at https://github.com/domenic/window-proxy-spec

I have an implementation that I've been trying to land in Firefox for a 
few weeks.  I had to fix a bunch of our tests, then restrict the change 
to web pages because it breaks various extensions.  I'm pretty hopeful 
that I can at least get it to the point where I can try doing some web 
compat testing...


https://bugzilla.mozilla.org/show_bug.cgi?id=1107443 for those who want 
to follow along.


-Boris

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Filip Pizlo

 On Jan 14, 2015, at 7:14 PM, Ian Hickson i...@hixie.ch wrote:
 
 On Wed, 14 Jan 2015, Boris Zbarsky wrote:
 
 The behavior of ES objects is expressed in terms of various internal methods.
 That's what you have to do to express what an ES object does.
 
 Not necessarily. We can also just say WindowProxy is its own thing and 
 here is how it works.
 
 
 No. WindowProxy isn't an ES Proxy.
 
 It's an ES object.
 
 That's debatable.
 
 
 It is indistinguishable from the Window object.
 
 It's distinguishable in various ways, including things like if I get 
 this property from it in 5 seconds, will I get the same value as from 
 the Window? The answer to that is maybe not.
 
 No, because by the time it returns a different value, it no longer acts 
 like it's the same object.
 
 You're holding a magical thing that looks and acts exactly like a potted 
 plant. It's indistinguishable from a potted plant. Then five seconds 
 later, you're holding a cat. It's indistinguishable from a cat. You can't 
 tell that the potted plant and the cat are the same thing. You can presume 
 that since you were holding one, and then you were holding the other, they 
 might have some relationship, but there's no way to tell that they're the 
 same thing. Even if the assume they're the same thing, you can't tell the 
 difference between the being the same thing, and someone just quickly 
 stealing the potted plant and replacing it with a cat.
 
 
 When the WindowProxy changes what it's pointing at, it's exactly as if 
 the browser had reached in and changed every WindowProxy that pointed 
 to the former and made it point to the latter.
 
 You say every WindowProxy, but in practice in an ES implementation you 
 have some object, it has some internal methods.  This is the last time 
 I'm bothering to go through this with you, since clearly we're getting 
 nowhere, as I said in 
 https://www.w3.org/Bugs/Public/show_bug.cgi?id=27128
 
 You are dismissing what I'm describing as being a misunderstanding of how 
 things should be considered to work, because they're not the same as what 
 you're describing. But maybe what I'm describing is how things should be 
 considered to work, and what you're describing is wrong. Or maybe both our 
 points of view are valid, and we should figure out which is easiest to 
 describe, or easiest to implement, or simplest to explain to authors, or 
 most compatible with the Web, or least likely to involve contortions 
 around unnecessary invariants, or whatever other priorities we want to 
 apply to this decision.
 
 
 The internal methods of every object must have behavior that preserves 
 the invariants.
 
 For ES proxies, the internal methods are defined in the spec in a way 
 that preserves the invariant.
 
 For other ES objects they are also defined in the spec.
 
 ES also allows other exotic objects that define some other behavior 
 for those internal methods, but requires that the invariants be 
 preserved.
 
 So one option would be to just say that WindowProxy is not an ES object.
 
 
 It doesn't matter.  The user sees the WindowProxy, not the Window.
 
 No. What the author has is a WindowProxy, but in every sense it acts 
 like a Window.
 
 You mean in every sense except what property values you'll get five 
 seconds from now.
 
 Five seconds from now, the author will in every sense appear to have a 
 different Window. It still appears to be a Window. Just a different one.
 
 
 After you navigate, you still have the same WindowProxy (e.g. 
 .contentWindow returns something that is === to the thing you had 
 before you navigated).
 
 You have no way to actually test this. Since every reference to the 
 old Window is now a reference to the new Window, you have no way to 
 test if the WindowProxy references something new.
 
 === on objects tests object identity.
 
 Except on WindowProxy, because WindowProxy forwards all operations to the 
 underlying Window.
 
 
 It's not affected by internal methods in any way.  Therefore, if === 
 returns true then you actually have the same object.
 
 Consider:
 
   let a = {};
   let b = {};
 
   let c = a;
   let d = a;
 
   assert(c === d); // true
 
   opaqueCode();
 
   assert(c === d); // still true
 
 If the opaqueCode() function just does:
 
   function opaqueCode() {
 c = b;
 d = b;
   }
 
 ...then === doesn't help you tell that c and d have changed identity. They 
 are still triple-equals to each other, but they're different objects.

Are you saying that it’s easier to spec having the browser find all variables 
(local or otherwise) that reference some object and replace them with 
references to a different object?

 
 This is exactly what happens with WindowProxy, except that the browser is 
 the code doing opaqueCode().
 
 
// part 1
let a = {};
let b = {};
let c = a;
 
// part 2
c.foo = 1;
 
// part 3
c = b;
 
// part 4
console.log(c.foo);
 
 Is it surprising that the log doesn't log 1?
 
 None of this 

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

2015-01-14 Thread Boris Zbarsky

On 1/14/15 10:14 PM, Ian Hickson wrote:

You are dismissing what I'm describing as being a misunderstanding of how
things should be considered to work,


No, I'm dismissing it as introducing magic that doesn't need to be 
introduced and hence making the platform more complicate than it needs 
to be, for no benefit I can perceive.


I do understand what you're describing, believe me.  I just have no 
plans to implement it or ask anyone else to implement it.



Or maybe both our
points of view are valid, and we should figure out which is easiest to
describe, or easiest to implement, or simplest to explain to authors, or
most compatible with the Web, or least likely to involve contortions
around unnecessary invariants, or whatever other priorities we want to
apply to this decision.


Yes, that's what I've been saying all along.

I will claim that my description is easier to describe rigorously, 
easier to implement, probably just as nasty to explain to authors, can 
completely replicate the observable behavior of your description if 
needed (e.g. by just directly forwarding all internal methods to the 
Window, at the cost of violating the invariants this thread is about), 
so can be just as compatible with the web, and gives at least a chance 
of preserving invariants people care about if that's what people want to do.


Whereas your description basically forecloses all discussion on how 
things should behave, because it locks them in to behaving in the single 
way you like; doing any other behavior requires going to a different model.



ES also allows other exotic objects that define some other behavior
for those internal methods, but requires that the invariants be
preserved.


So one option would be to just say that WindowProxy is not an ES object.


You were talking about explaining something to authors or making it 
implementable, yes?



Except on WindowProxy, because WindowProxy forwards all operations to the
underlying Window.


There is no operation to forward here.  === is literally just bitwise 
memory comparison equality in implementations.



If the opaqueCode() function just does:

function opaqueCode() {
  c = b;
  d = b;


It doesn't have c and d in its scope, so can't do that.

And yes, you're going to say that the browser has everything in scope, 
but the point is that your model involves some sort of non-local 
complicated heap-walking effect whereas changing the target of a proxy 
... not that.



The point is that the invariants apply to the actual objects originally
assigned to a and b, they don't apply to the variables.


variables don't even exist as a useful concept by the time you're 
running the code.  You've got values on the heap, on the stack, in 
registers, etc, etc.  Just saying.



No, because in the code above if I do |var d = c;| then the d won't
change in part 3.


If in the code above you do var d = c, then add d = b to part 3 to
simulate what the browser does.


Yes, I know that's your mental model.  My point is that no sane 
implementation would possibly want to actually implement it that way, 
whereas implementing it in terms of internal methods is what at least 
some implementations actually do.



I'm not actually proposing updating all the references. That's just a
convenient way to think about it


Except it's not a convenient way to think about it!


What is specced is just that you have a placeholder
pseudo-object


Why is it a pseudo-object when an object would do?


I have asked before, but would like to reiterate:

If there is any behaviour that is underdefined by the HTML spec's current
prose, please tell me, so that I can spec it.


Care to ask the UA implementors who are clearly not doing anything even 
resembling your spec?  Because it might turn out they might have reasons 
for it...



Well it predates all the ES6 stuff we're talking about here by several
years


All the stuff involved was in ES5.  It's not new in ES6.  I've also 
pointed this out to you several times now.



it doesn't leave anything undefined.


Implementations seem to disagree by their actions, sadly.


I also disagree that what the spec says doesn't match implementations.


Uh... Have you _tried_ testing this stuff in Safari?  I have; please see 
archives for the results.  They look nothing like your spec.


-Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Mark S. Miller
Thanks. It is great to accumulate such retreats in case we need them.
However, it is also good to remember that, should we run into problems,
that experience will give us specific data that we might not have been able
to anticipate. The least painful retreat may very well take that specific
data into account.

The case of Object.prototype.toString.call(null) was an informative
precedent.



On Wed, Jan 14, 2015 at 9:50 PM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 12/4/14 5:58 AM, Boris Zbarsky wrote:

 OK.  What do we do if we discover that throwing from the defineProperty
 call with a non-configurable property descriptor is not web-compatible?


 Based on a nice long conversation Yehuda and I just had, if we end up
 there and really want to preserve all the current invariants we could try a
 hybrid approach inspided by the Safari implementation.  To whit:

 1)  Assume that we can distinguish when we're inside a window and when
 we're outside it.  For example, compare the current Realm's global to the
 window.

 2)  When inside the window, everything works as normal: you can define a
 non-configurable property on the window you're inside,
 getOwnPropertyDescriptor will claim it's non-configurable, etc.  At least
 while that window is current.  Once it's non-current, I haven't tested what
 Safari does and am not sure what we could/should spec.

 3)  When outside the window, where observing navigations is easy, we try
 to apply one of the possible mitigations: throw on defineProperty that's
 non-configurable or whatnot, report all props as configurable, etc. This
 seems to be all kosher if we assume a membrane between inside and outside
 the window, such that we're actually operating on different objects in the
 two cases...

 This may mitigate the compat impact depending on what compat issues we run
 into.

 Just wanted to get this written down while it's fresh in my mind,
 Boris




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Bjoern Hoehrmann
* Boris Zbarsky wrote:
You say every WindowProxy, but in practice in an ES implementation you 
have some object, it has some internal methods.  This is the last time 
I'm bothering to go through this with you, since clearly we're getting 
nowhere, as I said in https://www.w3.org/Bugs/Public/show_bug.cgi?id=27128

What are the odds that the behavior observable by web pages can actually
be defined sanely such that ES invariants and compatibility requirements
are satisfied? https://www.w3.org/Bugs/Public/show_bug.cgi?id=27128#c15
indicates, as I understand it, the odds may be quite good. In that case,
looking for a volunteer to come up with a proposal might be a good next
step.
-- 
Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de
D-10243 Berlin · PGP Pub. KeyID: 0xA4357E78 · http://www.bjoernsworld.de
 Available for hire in Berlin (early 2015)  · http://www.websitedev.de/ 
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Boris Zbarsky

On 1/14/15 8:49 PM, Travis Leithead wrote:

and existing elements and their document are disconnected from the
window, while a new document and the new elements created from parsing
are put in their place.


More precisely, the old elements are disconnected from the document, the 
document is disconnected from the window, and the document is connected 
to the new window.



Implementations differ on how they handle the scenario. Boris notes that
Gecko just creates a new window (with a new document, etc.)


No, it's the same document.


Boris can correct me if I got this wrong.


You got it wrong.  ;)

-Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Ian Hickson
On Wed, 14 Jan 2015, Boris Zbarsky wrote:
 
 The behavior of ES objects is expressed in terms of various internal methods.
 That's what you have to do to express what an ES object does.

Not necessarily. We can also just say WindowProxy is its own thing and 
here is how it works.


  No. WindowProxy isn't an ES Proxy.
 
 It's an ES object.

That's debatable.


  It is indistinguishable from the Window object.
 
 It's distinguishable in various ways, including things like if I get 
 this property from it in 5 seconds, will I get the same value as from 
 the Window? The answer to that is maybe not.

No, because by the time it returns a different value, it no longer acts 
like it's the same object.

You're holding a magical thing that looks and acts exactly like a potted 
plant. It's indistinguishable from a potted plant. Then five seconds 
later, you're holding a cat. It's indistinguishable from a cat. You can't 
tell that the potted plant and the cat are the same thing. You can presume 
that since you were holding one, and then you were holding the other, they 
might have some relationship, but there's no way to tell that they're the 
same thing. Even if the assume they're the same thing, you can't tell the 
difference between the being the same thing, and someone just quickly 
stealing the potted plant and replacing it with a cat.


  When the WindowProxy changes what it's pointing at, it's exactly as if 
  the browser had reached in and changed every WindowProxy that pointed 
  to the former and made it point to the latter.
 
 You say every WindowProxy, but in practice in an ES implementation you 
 have some object, it has some internal methods.  This is the last time 
 I'm bothering to go through this with you, since clearly we're getting 
 nowhere, as I said in 
 https://www.w3.org/Bugs/Public/show_bug.cgi?id=27128

You are dismissing what I'm describing as being a misunderstanding of how 
things should be considered to work, because they're not the same as what 
you're describing. But maybe what I'm describing is how things should be 
considered to work, and what you're describing is wrong. Or maybe both our 
points of view are valid, and we should figure out which is easiest to 
describe, or easiest to implement, or simplest to explain to authors, or 
most compatible with the Web, or least likely to involve contortions 
around unnecessary invariants, or whatever other priorities we want to 
apply to this decision.


 The internal methods of every object must have behavior that preserves 
 the invariants.
 
 For ES proxies, the internal methods are defined in the spec in a way 
 that preserves the invariant.
 
 For other ES objects they are also defined in the spec.
 
 ES also allows other exotic objects that define some other behavior 
 for those internal methods, but requires that the invariants be 
 preserved.

So one option would be to just say that WindowProxy is not an ES object.


   It doesn't matter.  The user sees the WindowProxy, not the Window.
  
  No. What the author has is a WindowProxy, but in every sense it acts 
  like a Window.
 
 You mean in every sense except what property values you'll get five 
 seconds from now.

Five seconds from now, the author will in every sense appear to have a 
different Window. It still appears to be a Window. Just a different one.


   After you navigate, you still have the same WindowProxy (e.g. 
   .contentWindow returns something that is === to the thing you had 
   before you navigated).
  
  You have no way to actually test this. Since every reference to the 
  old Window is now a reference to the new Window, you have no way to 
  test if the WindowProxy references something new.
 
 === on objects tests object identity.

Except on WindowProxy, because WindowProxy forwards all operations to the 
underlying Window.


 It's not affected by internal methods in any way.  Therefore, if === 
 returns true then you actually have the same object.

Consider:

   let a = {};
   let b = {};

   let c = a;
   let d = a;

   assert(c === d); // true

   opaqueCode();

   assert(c === d); // still true

If the opaqueCode() function just does:

   function opaqueCode() {
 c = b;
 d = b;
   }

...then === doesn't help you tell that c and d have changed identity. They 
are still triple-equals to each other, but they're different objects.

This is exactly what happens with WindowProxy, except that the browser is 
the code doing opaqueCode().
   

  // part 1
  let a = {};
  let b = {};
  let c = a;
  
  // part 2
  c.foo = 1;
  
  // part 3
  c = b;
  
  // part 4
  console.log(c.foo);
  
  Is it surprising that the log doesn't log 1?
 
 None of this affects the invariants involved.

The point is that the invariants apply to the actual objects originally 
assigned to a and b, they don't apply to the variables.


  This is what is going on here, except that part 3 is done by the 
  browser.
 
 No, because in the code 

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

2015-01-14 Thread Boris Zbarsky

On 12/4/14 5:58 AM, Boris Zbarsky wrote:

OK.  What do we do if we discover that throwing from the defineProperty
call with a non-configurable property descriptor is not web-compatible?


Based on a nice long conversation Yehuda and I just had, if we end up 
there and really want to preserve all the current invariants we could 
try a hybrid approach inspided by the Safari implementation.  To whit:


1)  Assume that we can distinguish when we're inside a window and when 
we're outside it.  For example, compare the current Realm's global to 
the window.


2)  When inside the window, everything works as normal: you can define a 
non-configurable property on the window you're inside, 
getOwnPropertyDescriptor will claim it's non-configurable, etc.  At 
least while that window is current.  Once it's non-current, I haven't 
tested what Safari does and am not sure what we could/should spec.


3)  When outside the window, where observing navigations is easy, we try 
to apply one of the possible mitigations: throw on defineProperty that's 
non-configurable or whatnot, report all props as configurable, etc. 
This seems to be all kosher if we assume a membrane between inside and 
outside the window, such that we're actually operating on different 
objects in the two cases...


This may mitigate the compat impact depending on what compat issues we 
run into.


Just wanted to get this written down while it's fresh in my mind,
Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Mark S. Miller
Domenic's https://github.com/domenic/window-proxy-spec seems headed in the
right direction. I suggest starting there.

Test proposals by self-hosting in ES6. Such self hosting would use direct
proxies *not* because the term proxy in WindowProxy has any historical
relation -- it does not -- but because the rest of ES6 is not powerful
enough to self-host its behavior.




On Wed, Jan 14, 2015 at 5:56 PM, Bjoern Hoehrmann derhoe...@gmx.net wrote:

 * Boris Zbarsky wrote:
 You say every WindowProxy, but in practice in an ES implementation you
 have some object, it has some internal methods.  This is the last time
 I'm bothering to go through this with you, since clearly we're getting
 nowhere, as I said in
 https://www.w3.org/Bugs/Public/show_bug.cgi?id=27128

 What are the odds that the behavior observable by web pages can actually
 be defined sanely such that ES invariants and compatibility requirements
 are satisfied? https://www.w3.org/Bugs/Public/show_bug.cgi?id=27128#c15
 indicates, as I understand it, the odds may be quite good. In that case,
 looking for a volunteer to come up with a proposal might be a good next
 step.
 --
 Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de
 D-10243 Berlin · PGP Pub. KeyID: 0xA4357E78 · http://www.bjoernsworld.de
  Available for hire in Berlin (early 2015)  · http://www.websitedev.de/




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2015-01-14 Thread Mark S. Miller
On Wed, Jan 14, 2015 at 7:14 PM, Ian Hickson i...@hixie.ch wrote:

 On Wed, 14 Jan 2015, Boris Zbarsky wrote:
 
  The behavior of ES objects is expressed in terms of various internal
 methods.
  That's what you have to do to express what an ES object does.

 Not necessarily. We can also just say WindowProxy is its own thing and
 here is how it works.


   No. WindowProxy isn't an ES Proxy.
 
  It's an ES object.

 That's debatable.


In the sense that we're debating it, sure.

WindowProxy is however a first class value observable by JS code, and
therefore covered by the ES specs. Further, the various meta-object
operations like Object.defineProperty accept it as an argument. If it isn't
even an object, why is it observable all? Why do methods specified to
operate on object arguments even accept it? Starting from your stance, I'd
argue that all these operations should at least reject it with a TypeError.

Neither does the magic replacement theory excuse it from violating the
spec. See https://mail.mozilla.org/pipermail/es-discuss/2011-May/014150.html
, where we first clarified the difference between momentary and eternal
invariants. Let's test the invariant stated in that message as

The ES5 constraints on updating non configurable properties are eternal
invariants.


by writing test2c, in the same spirit as test2a and test2b:

(function(){use strict;

// assume gopd  is initialization runs first, so these are
// the original functions.
var gopd = Object.getOwnPropertyDescriptor;
var is = Object.is;

function test2c(obj, name, interleave) {
  name = String(name);
  var desc1 = gopd(obj, name);
  interleave();
  var desc2 = gopd(obj, name);
  if (!desc1.configurable) {
assertFalse(desc2.configurable);
assertTrue(desc2.enumerable === desc2.enumerable);
if (gopd(desc1, 'writable')  !desc1.writable) {
  assertFalse(desc2.writable);
  assertTrue(is(desc1.value, desc2.value));
}
  }
}

return test2c;


}());

In a conforming ES6 implementation (or a conforming ES5 one given the std
is polyfill), it must not be possible to call test2c such that these
asserts fail. No where do these specs say unless interleave() replaces all
pointers to obj to point at a different object. If it did, the whole
notion of eternal invariants would be nonsense.






   It is indistinguishable from the Window object.
 
  It's distinguishable in various ways, including things like if I get
  this property from it in 5 seconds, will I get the same value as from
  the Window? The answer to that is maybe not.

 No, because by the time it returns a different value, it no longer acts
 like it's the same object.

 You're holding a magical thing that looks and acts exactly like a potted
 plant. It's indistinguishable from a potted plant. Then five seconds
 later, you're holding a cat. It's indistinguishable from a cat. You can't
 tell that the potted plant and the cat are the same thing. You can presume
 that since you were holding one, and then you were holding the other, they
 might have some relationship, but there's no way to tell that they're the
 same thing. Even if the assume they're the same thing, you can't tell the
 difference between the being the same thing, and someone just quickly
 stealing the potted plant and replacing it with a cat.


   When the WindowProxy changes what it's pointing at, it's exactly as if
   the browser had reached in and changed every WindowProxy that pointed
   to the former and made it point to the latter.
 
  You say every WindowProxy, but in practice in an ES implementation you
  have some object, it has some internal methods.  This is the last time
  I'm bothering to go through this with you, since clearly we're getting
  nowhere, as I said in
  https://www.w3.org/Bugs/Public/show_bug.cgi?id=27128

 You are dismissing what I'm describing as being a misunderstanding of how
 things should be considered to work, because they're not the same as what
 you're describing. But maybe what I'm describing is how things should be
 considered to work, and what you're describing is wrong. Or maybe both our
 points of view are valid, and we should figure out which is easiest to
 describe, or easiest to implement, or simplest to explain to authors, or
 most compatible with the Web, or least likely to involve contortions
 around unnecessary invariants, or whatever other priorities we want to
 apply to this decision.


  The internal methods of every object must have behavior that preserves
  the invariants.
 
  For ES proxies, the internal methods are defined in the spec in a way
  that preserves the invariant.
 
  For other ES objects they are also defined in the spec.
 
  ES also allows other exotic objects that define some other behavior
  for those internal methods, but requires that the invariants be
  preserved.

 So one option would be to just say that WindowProxy is not an ES object.


It doesn't matter.  The user sees the WindowProxy, not the Window.
  
   No. What the author has is 

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

2014-12-04 Thread Boris Zbarsky

On 11/30/14, 6:12 PM, Mark S. Miller wrote:

On Sun, Nov 30, 2014 at 12:21 PM, Boris Zbarsky bzbar...@mit.edu 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-12-04 Thread Mark S. Miller
On Thu, Dec 4, 2014 at 2:58 AM, Boris Zbarsky bzbar...@mit.edu wrote:
 On 11/30/14, 6:12 PM, Mark S. Miller wrote:

 On Sun, Nov 30, 2014 at 12:21 PM, Boris Zbarsky bzbar...@mit.edu 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-12-04 Thread 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-12-04 Thread 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-12-04 Thread Mark Miller
On Thu, Dec 4, 2014 at 4:32 PM, Boris Zbarsky bzbar...@mit.edu 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
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss



-- 
  Cheers,
  --MarkM
___
es-discuss mailing list

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

2014-12-04 Thread Boris Zbarsky

On 12/4/14, 4:45 PM, Mark Miller wrote:

On Thu, Dec 4, 2014 at 4:32 PM, Boris Zbarsky bzbar...@mit.edu 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-12-04 Thread Mark Miller
On Thu, Dec 4, 2014 at 4:49 PM, Boris Zbarsky bzbar...@mit.edu wrote:
 On 12/4/14, 4:45 PM, Mark Miller wrote:

 On Thu, Dec 4, 2014 at 4:32 PM, Boris Zbarsky bzbar...@mit.edu 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-12-02 Thread Andreas Rossberg
On 1 December 2014 at 03:12, Mark S. Miller erig...@google.com wrote:
 On Sun, Nov 30, 2014 at 12:21 PM, Boris Zbarsky bzbar...@mit.edu 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-12-02 Thread David Bruant

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 erig...@google.com wrote:

On Sun, Nov 30, 2014 at 12:21 PM, Boris Zbarsky bzbar...@mit.edu 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-12-02 Thread David Bruant

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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-12-02 Thread Mark 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 bruan...@gmail.com 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
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss



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

  Cheers,
  --MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-12-02 Thread Boris Zbarsky

On 12/2/14, 4:59 AM, Andreas Rossberg wrote:

On 1 December 2014 at 03:12, Mark S. Miller erig...@google.com wrote:

On Sun, Nov 30, 2014 at 12:21 PM, Boris Zbarsky bzbar...@mit.edu 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-12-02 Thread Boris Zbarsky

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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-11-30 Thread Mark S. Miller
On Sun, Nov 30, 2014 at 12:21 PM, Boris Zbarsky bzbar...@mit.edu 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
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss



-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2014-11-30 Thread Mark Miller
On Sun, Nov 30, 2014 at 6:12 PM, Mark S. Miller erig...@google.com 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss