RE: Figuring out the behavior of WindowProxy in the face of non-configurable properties
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
* 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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