New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OrdinarySetPrototypeOf and the HTML spec #683

Open
saambarati opened this Issue Sep 2, 2016 · 30 comments

Comments

Projects
None yet
8 participants
@saambarati

saambarati commented Sep 2, 2016

Currently, OrdinarySetPrototypeOf bails from its cycle checking loop early if it sees a [[GetPrototypeOf]] which isn't the default implementation. I'm guessing this is in awareness of the Proxy's [[GetPrototypeOf]]. Is that correct? If not, what is the reasoning behind this decision?
I'm looking at: https://tc39.github.io/ecma262/#sec-ordinarysetprototypeof

The HTML spec overrides [[GetPrototypeOf]] on the window proxy. Calling [[SetPrototypeOf]] on an object who's [[Prototype]] is WindowProxy can lead to cycles now.
I'm looking at: https://html.spec.whatwg.org/#windowproxy-getprototypeof

Like so:

let o = {__proto__: window};
window.__proto__.__proto__.__proto__.__proto__ = o

(I believe this throws cycle exceptions in browsers, however, it should not according to the spec, if I'm reading it correctly, and have constructed my example correctly.)

I believe that if we don't consider the browser, it's impossible to get a cycle if you directly loop over the [[Prototype]] property. However, with the HTML spec, I believe that's no longer true.

I wonder if the function can be more restrictive, and only bail out on the loop if we encounter a ProxyObject.[[GetPrototypeOf]] internal method, instead of bailing once we see the non-default [[GetPrototypeOf]].

What are people's thoughts? I'm mostly posting here to bring awareness to this issue and to understand previous discussions of it, or to have new discussions about it. We're currently running into issues with this property inside WebKit.

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Sep 2, 2016

Member

I think @jswalden also ran into this, judging by https://blog.whatwg.org/windowproxy-window-and-location#comments ...

(I have not taken the time to form an opinion on this. In general I think anything that is web-compatible is probably fine in these kind of edge cases?)

Member

domenic commented Sep 2, 2016

I think @jswalden also ran into this, judging by https://blog.whatwg.org/windowproxy-window-and-location#comments ...

(I have not taken the time to form an opinion on this. In general I think anything that is web-compatible is probably fine in these kind of edge cases?)

@littledan

This comment has been minimized.

Show comment
Hide comment
@littledan
Member

littledan commented Sep 3, 2016

@allenwb

This comment has been minimized.

Show comment
Hide comment
@allenwb

allenwb Sep 8, 2016

Member

see https://bugs.ecmascript.org/show_bug.cgi?id=2437 for the background of this semantics

It seems perfectly reasonable for the HTML spec to provide modifications to steps of 8.c.i-ii of OrdinarySetPrototypeOf that take the WindowProxy object into account

Member

allenwb commented Sep 8, 2016

see https://bugs.ecmascript.org/show_bug.cgi?id=2437 for the background of this semantics

It seems perfectly reasonable for the HTML spec to provide modifications to steps of 8.c.i-ii of OrdinarySetPrototypeOf that take the WindowProxy object into account

@bterlson

This comment has been minimized.

Show comment
Hide comment
@bterlson

bterlson Sep 8, 2016

Member

The rationale wasn't entirely proxy-based - generally, exotic objects can have a [[GetPrototypeOf]] implementation that can do arbitrary things and it's impossible to enforce that there are no observable circularities. Proxies are an obvious case where this can happen however.

That said, it totally makes sense that an embedding would want exotic objects with overridden [[GetPrototypeOf]] slots to nonetheless behave as if [[GetPrototypeOf]] were ordinary for the purposes of circularity checks. I can't think of a clean way to expose this through 262's layering API however. Another alternative is for HTML to ammend OrdinarySetPrototypeOf Step 8.c.i to state something like "If the [[GetPrototypeOf]] internal method of p is not the ordinary object internal method defined in 9.1.1 and not WindowProxy's [[GetPrototypeOf]] internal method, let done be true." Since this is so edge-casey I don't think this is too bad.

Member

bterlson commented Sep 8, 2016

The rationale wasn't entirely proxy-based - generally, exotic objects can have a [[GetPrototypeOf]] implementation that can do arbitrary things and it's impossible to enforce that there are no observable circularities. Proxies are an obvious case where this can happen however.

That said, it totally makes sense that an embedding would want exotic objects with overridden [[GetPrototypeOf]] slots to nonetheless behave as if [[GetPrototypeOf]] were ordinary for the purposes of circularity checks. I can't think of a clean way to expose this through 262's layering API however. Another alternative is for HTML to ammend OrdinarySetPrototypeOf Step 8.c.i to state something like "If the [[GetPrototypeOf]] internal method of p is not the ordinary object internal method defined in 9.1.1 and not WindowProxy's [[GetPrototypeOf]] internal method, let done be true." Since this is so edge-casey I don't think this is too bad.

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Sep 8, 2016

Member

I still haven't taken the time to understand this issue in full, so I'm just assuming that you guys are right that this is the best solution :). But I would really prefer not to have that kind of monkeypatch and willful violation. Instead could we define something like a "non-circular exotic [[GetPrototypeOf]] internal method", change ES to have "is not the ordinary object internal method defined in 9.1.1 and is not a non-circular exotic [[GetPrototypeOf]] internal method", and then say in HTML that the [[GetPrototypeOf]] for WindowProxy and Location are non-circular exotic [[GetPrototypeOf]] internal methods?

Member

domenic commented Sep 8, 2016

I still haven't taken the time to understand this issue in full, so I'm just assuming that you guys are right that this is the best solution :). But I would really prefer not to have that kind of monkeypatch and willful violation. Instead could we define something like a "non-circular exotic [[GetPrototypeOf]] internal method", change ES to have "is not the ordinary object internal method defined in 9.1.1 and is not a non-circular exotic [[GetPrototypeOf]] internal method", and then say in HTML that the [[GetPrototypeOf]] for WindowProxy and Location are non-circular exotic [[GetPrototypeOf]] internal methods?

@bterlson

This comment has been minimized.

Show comment
Hide comment
@bterlson

bterlson Sep 8, 2016

Member

@domenic that would work too, but it's a lot of verbage to support this edge case. We also don't have a notion of special "kinds" for internal methods in the spec and I'd not like to add it just for this. It's a lot of conceptual overhead.

Member

bterlson commented Sep 8, 2016

@domenic that would work too, but it's a lot of verbage to support this edge case. We also don't have a notion of special "kinds" for internal methods in the spec and I'd not like to add it just for this. It's a lot of conceptual overhead.

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Sep 8, 2016

Member

Then could we add a reference directly to WindowProxy's [[GetPrototypeOf]] to the ES spec?

Member

domenic commented Sep 8, 2016

Then could we add a reference directly to WindowProxy's [[GetPrototypeOf]] to the ES spec?

@allenwb

This comment has been minimized.

Show comment
Hide comment
@allenwb

allenwb Sep 8, 2016

Member

@domenic

Then could we add a reference directly to WindowProxy's [[GetPrototypeOf]] to the ES spec?

That would give special status to HTML. Whose to say that some other host environment spec. might not want to do something similar. It seems cleaner to me, to leave to such host environment specification to say what they require (and to negotiate with engines to support it).

Member

allenwb commented Sep 8, 2016

@domenic

Then could we add a reference directly to WindowProxy's [[GetPrototypeOf]] to the ES spec?

That would give special status to HTML. Whose to say that some other host environment spec. might not want to do something similar. It seems cleaner to me, to leave to such host environment specification to say what they require (and to negotiate with engines to support it).

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Sep 8, 2016

Member

Yes, that's exactly the negotation we're performing here :). I'd just like to get it written into the spec. As you say, other host environments might have the same requirement, so it'd be good if the spec had a mechanism for doing so.

Member

domenic commented Sep 8, 2016

Yes, that's exactly the negotation we're performing here :). I'd just like to get it written into the spec. As you say, other host environments might have the same requirement, so it'd be good if the spec had a mechanism for doing so.

@cdumez

This comment has been minimized.

Show comment
Hide comment
@cdumez

cdumez Sep 8, 2016

FYI, this is not just HTML's WindowProxy that is affected but also HTML's Location object.

cdumez commented Sep 8, 2016

FYI, this is not just HTML's WindowProxy that is affected but also HTML's Location object.

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Sep 8, 2016

Member

We also don't have a notion of special "kinds" for internal methods in the spec and I'd not like to add it just for this.

We could also define a special kind of exotic object (the precedent being immutable prototype exotic objects) and test if p is one of those. E.g. a "circular-prototype-checked exotic object"

Member

domenic commented Sep 8, 2016

We also don't have a notion of special "kinds" for internal methods in the spec and I'd not like to add it just for this.

We could also define a special kind of exotic object (the precedent being immutable prototype exotic objects) and test if p is one of those. E.g. a "circular-prototype-checked exotic object"

@allenwb

This comment has been minimized.

Show comment
Hide comment
@allenwb

allenwb Sep 8, 2016

Member

I'd just like to get it written into the spec. As you say, other host environments might have the same requirement, so it'd be good if the spec had a mechanism for doing so.

My point was more that other environments might have different requirements or requirements relating to other parts of the ES spec. Trying to accommodate such implementation specific requirements adds spec. complexity that impacts everybody. (arguably, this current issue relates to existing complexity that was added as an implementor accommodation). In addition, such accommodations can be seen as sanctioning such extensions, when we might prefer to discourage them.

Finally, look at it from an architectural layering perspective. Many environments can be layered on top of ES. Architecturally "down links" rather than "up links" are preferable and more maintainable.

Member

allenwb commented Sep 8, 2016

I'd just like to get it written into the spec. As you say, other host environments might have the same requirement, so it'd be good if the spec had a mechanism for doing so.

My point was more that other environments might have different requirements or requirements relating to other parts of the ES spec. Trying to accommodate such implementation specific requirements adds spec. complexity that impacts everybody. (arguably, this current issue relates to existing complexity that was added as an implementor accommodation). In addition, such accommodations can be seen as sanctioning such extensions, when we might prefer to discourage them.

Finally, look at it from an architectural layering perspective. Many environments can be layered on top of ES. Architecturally "down links" rather than "up links" are preferable and more maintainable.

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Sep 8, 2016

Member

I just don't think it's reasonable to say that for something as basic as OrdinaryGetPrototypeOf, web browsers cannot look at the ES spec, and must instead implement the HTML spec's version. If we set that kind of precedent, then the ES spec becomes entirely unreliable as a guide to what implementations should implement and the behaviors and invariants developers can assume. @erights has commented on this in the past in other issues.

Instead, I'd like to use the tried-and-true practice of decoupling dependencies via agnostic, targeted hooks of the sort described.

If we want to be even more generic, to accomodate those varying options you describe, then I guess the canonical path is to create a HostOrdinarySetPrototypeOfSteps(O, V) operation, and insert it after step 8 of OrdinarySetPrototypeOf. That seems like over-engineering to me compared to adding a special kind of exotic object, or similar. But if that's what the editor would prefer I'm happy to do that too.

Member

domenic commented Sep 8, 2016

I just don't think it's reasonable to say that for something as basic as OrdinaryGetPrototypeOf, web browsers cannot look at the ES spec, and must instead implement the HTML spec's version. If we set that kind of precedent, then the ES spec becomes entirely unreliable as a guide to what implementations should implement and the behaviors and invariants developers can assume. @erights has commented on this in the past in other issues.

Instead, I'd like to use the tried-and-true practice of decoupling dependencies via agnostic, targeted hooks of the sort described.

If we want to be even more generic, to accomodate those varying options you describe, then I guess the canonical path is to create a HostOrdinarySetPrototypeOfSteps(O, V) operation, and insert it after step 8 of OrdinarySetPrototypeOf. That seems like over-engineering to me compared to adding a special kind of exotic object, or similar. But if that's what the editor would prefer I'm happy to do that too.

@bterlson

This comment has been minimized.

Show comment
Hide comment
@bterlson

bterlson Sep 8, 2016

Member

IIUC circular-prototype-checked exotic object isn't right - the ability to depend on GetPrototypeOf for circularity checks is orthogonal to the exoticness of an object. In other words, a named exotic object is just an object with a specific set of non-standard slots so a circular-prototype-checked exotic object wouldn't work because it actually describes a constraint on the behavior of [[GetPrototypeOf]] rather than a particular slot value.

Another option would be a slot flag for ordinary objects, something like [[GetPrototypeOfReliableForCircularityChecks]]. Its value is true for ordinary objects and false for proxy objects. Problem I see with this design is that it assumes that objects that override [[GetPrototypeOf]] are reliable when probably assuming the opposite is safest.

I still feel that any option is a lot of machinery for an edge case with a pretty tiny spec patch :-P It makes 262 harder to understand and doesn't help HTML all that much.

Member

bterlson commented Sep 8, 2016

IIUC circular-prototype-checked exotic object isn't right - the ability to depend on GetPrototypeOf for circularity checks is orthogonal to the exoticness of an object. In other words, a named exotic object is just an object with a specific set of non-standard slots so a circular-prototype-checked exotic object wouldn't work because it actually describes a constraint on the behavior of [[GetPrototypeOf]] rather than a particular slot value.

Another option would be a slot flag for ordinary objects, something like [[GetPrototypeOfReliableForCircularityChecks]]. Its value is true for ordinary objects and false for proxy objects. Problem I see with this design is that it assumes that objects that override [[GetPrototypeOf]] are reliable when probably assuming the opposite is safest.

I still feel that any option is a lot of machinery for an edge case with a pretty tiny spec patch :-P It makes 262 harder to understand and doesn't help HTML all that much.

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Sep 8, 2016

Member

I still feel that any option is a lot of machinery for an edge case with a pretty tiny spec patch :-P It makes 262 harder to understand and doesn't help HTML all that much.

I am really having trouble understanding this perspective. Similarly, I find it a bit baffling that you are calling this an edge case, given how we have multiple implementers who have complained about this. Sure, from a web developer's point of view it probably won't come up much, but we've heard twice that this complicates engines significantly.

262 could become very easy to understand if we just replaced OrdinarySetPrototypeOf with the text "set the prototype please". That wouldn't make it accurate, or reflect what implementations implement. I think the goal should not be ease of understanding, but ease of understanding given that we are speccing what engines implement.

It helps HTML a lot; getting the exotic behaviors of WindowProxy and Location correct is a huge win for the web platform, as they have historically been underspecified and a source of security issues. We wrote a blog post about this at https://blog.whatwg.org/windowproxy-window-and-location. Making sure specs actually align with the implementations here has been a big project, and to have it stall on the finish line because ES isn't willing to open up and do its part is quite frustrating.

I'm begging you to give me a hook here. I don't care whether it's special [[SetPrototypeOf]] internal methods, special object types, special internal slots, or HostIsGetPrototypeOfIsReliableForCircularityChecks. I will do the work and PR anything you agree to. Let's just actually get this working, and not dismiss the problem and encourage more willful violations of ES from HTML.

Member

domenic commented Sep 8, 2016

I still feel that any option is a lot of machinery for an edge case with a pretty tiny spec patch :-P It makes 262 harder to understand and doesn't help HTML all that much.

I am really having trouble understanding this perspective. Similarly, I find it a bit baffling that you are calling this an edge case, given how we have multiple implementers who have complained about this. Sure, from a web developer's point of view it probably won't come up much, but we've heard twice that this complicates engines significantly.

262 could become very easy to understand if we just replaced OrdinarySetPrototypeOf with the text "set the prototype please". That wouldn't make it accurate, or reflect what implementations implement. I think the goal should not be ease of understanding, but ease of understanding given that we are speccing what engines implement.

It helps HTML a lot; getting the exotic behaviors of WindowProxy and Location correct is a huge win for the web platform, as they have historically been underspecified and a source of security issues. We wrote a blog post about this at https://blog.whatwg.org/windowproxy-window-and-location. Making sure specs actually align with the implementations here has been a big project, and to have it stall on the finish line because ES isn't willing to open up and do its part is quite frustrating.

I'm begging you to give me a hook here. I don't care whether it's special [[SetPrototypeOf]] internal methods, special object types, special internal slots, or HostIsGetPrototypeOfIsReliableForCircularityChecks. I will do the work and PR anything you agree to. Let's just actually get this working, and not dismiss the problem and encourage more willful violations of ES from HTML.

@allenwb

This comment has been minimized.

Show comment
Hide comment
@allenwb

allenwb Sep 8, 2016

Member

@bterlson
Note that the check for the ordinary [[GetPrototypeOf]] in step 8.c.i is essentially a guard to ensure that the object has a [[Prototype]] internal slot that contains the value that [[GetPrototypeOf]] returns when called. That's what implementations actually care about, that following such prototype chains (skipping actually calling [[GetPrototypeOf]] will never produce a circularity.

Member

allenwb commented Sep 8, 2016

@bterlson
Note that the check for the ordinary [[GetPrototypeOf]] in step 8.c.i is essentially a guard to ensure that the object has a [[Prototype]] internal slot that contains the value that [[GetPrototypeOf]] returns when called. That's what implementations actually care about, that following such prototype chains (skipping actually calling [[GetPrototypeOf]] will never produce a circularity.

@bterlson

This comment has been minimized.

Show comment
Hide comment
@bterlson

bterlson Sep 8, 2016

Member

@domenic given all of the changes that have landed in 262 for layering purposes I don't think it's right to claim that we're not opening up or doing our part.

Member

bterlson commented Sep 8, 2016

@domenic given all of the changes that have landed in 262 for layering purposes I don't think it's right to claim that we're not opening up or doing our part.

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Sep 8, 2016

Member

@bterlson certainly I didn't mean to imply that! I was talking about this specific instance. Part of the reason it's so surprising to see these kinds of attitudes is precisely because of the past collaboration.

Member

domenic commented Sep 8, 2016

@bterlson certainly I didn't mean to imply that! I was talking about this specific instance. Part of the reason it's so surprising to see these kinds of attitudes is precisely because of the past collaboration.

@bterlson

This comment has been minimized.

Show comment
Hide comment
@bterlson

bterlson Sep 8, 2016

Member

We're collaborating - I've even made a proposal! My feelings on the matter should not be interpreted as a "No way" - I often don't get my way :) Anyway, let's not make this into a political issue and focus on finding the best way to spec this in 262. We can worry about politics if we think it needs-consensus :-P

Member

bterlson commented Sep 8, 2016

We're collaborating - I've even made a proposal! My feelings on the matter should not be interpreted as a "No way" - I often don't get my way :) Anyway, let's not make this into a political issue and focus on finding the best way to spec this in 262. We can worry about politics if we think it needs-consensus :-P

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Sep 8, 2016

Member

OK, sorry about that! I guess I was just frustrated by some specific wording around "edge case" and "doesn't help" and so on. Apologies for letting that spill out. Let's indeed continue to work together and move past my outburst :)

I am liking the direction of some sort of "reliable for circularity checks" flag. I think it's probably safe to assume that exotic objects defined in specs will be reliable in that way, and so set the default to reliable for non-proxies, but I can understand being cautious instead. The HostIsGetPrototypeOfIsReliableForCircularityChecks idea I alluded to above might be a way of flipping that default, by making the default behavior be to return false.

Member

domenic commented Sep 8, 2016

OK, sorry about that! I guess I was just frustrated by some specific wording around "edge case" and "doesn't help" and so on. Apologies for letting that spill out. Let's indeed continue to work together and move past my outburst :)

I am liking the direction of some sort of "reliable for circularity checks" flag. I think it's probably safe to assume that exotic objects defined in specs will be reliable in that way, and so set the default to reliable for non-proxies, but I can understand being cautious instead. The HostIsGetPrototypeOfIsReliableForCircularityChecks idea I alluded to above might be a way of flipping that default, by making the default behavior be to return false.

@saambarati

This comment has been minimized.

Show comment
Hide comment
@saambarati

saambarati Sep 9, 2016

@allenwb
What about making ProxyObject start with [[Prototype]] of null (note, the only place a ProxyObject's [[Prototype]] will be checked is in this loop). Then, the loop can loop over [[Prototype]] instead of checking the value of [[GetPrototypeOf]].
Thoughts?

saambarati commented Sep 9, 2016

@allenwb
What about making ProxyObject start with [[Prototype]] of null (note, the only place a ProxyObject's [[Prototype]] will be checked is in this loop). Then, the loop can loop over [[Prototype]] instead of checking the value of [[GetPrototypeOf]].
Thoughts?

@allenwb

This comment has been minimized.

Show comment
Hide comment
@allenwb

allenwb Sep 9, 2016

Member

@saambarati
ProxyObjects don't have a [[Prototype]] internal slot and more generally exotic objects may or may not have such a slot.
But regardless, the WindowProxy apparently isn't an actual ProxyObject.

Member

allenwb commented Sep 9, 2016

@saambarati
ProxyObjects don't have a [[Prototype]] internal slot and more generally exotic objects may or may not have such a slot.
But regardless, the WindowProxy apparently isn't an actual ProxyObject.

@allenwb

This comment has been minimized.

Show comment
Hide comment
@allenwb

allenwb Sep 9, 2016

Member

@domenic
exposing the ordinary Object [[GetPrototypeOf]] and a [[Prototype]] internal property is essentially the tag that means "reliable for circularity checks". So instead of over-riding [[GetPrototypeOf]] why not use the ordinary Object [[GetPrototypeOf]] plus a [[Prototype]] slot and when you set up a WindowProxy, cache the value currently computed by https://html.spec.whatwg.org/#windowproxy-getprototypeof in the ProxyObject's [[Prototype]].

Member

allenwb commented Sep 9, 2016

@domenic
exposing the ordinary Object [[GetPrototypeOf]] and a [[Prototype]] internal property is essentially the tag that means "reliable for circularity checks". So instead of over-riding [[GetPrototypeOf]] why not use the ordinary Object [[GetPrototypeOf]] plus a [[Prototype]] slot and when you set up a WindowProxy, cache the value currently computed by https://html.spec.whatwg.org/#windowproxy-getprototypeof in the ProxyObject's [[Prototype]].

@claudepache

This comment has been minimized.

Show comment
Hide comment
@claudepache

claudepache Sep 9, 2016

Contributor

Interestingly, in Firefox, even without the cycle check, it is impossible to have a prototype chain cycle involving window or any object in its prototype chain, because the entire prototype chain of window is locked down https://bugzilla.mozilla.org/show_bug.cgi?id=1052139.

There is still the issue of the Location objects; although I wonder whether it makes sense to have a mutable prototype chain on such objects anyway.

Contributor

claudepache commented Sep 9, 2016

Interestingly, in Firefox, even without the cycle check, it is impossible to have a prototype chain cycle involving window or any object in its prototype chain, because the entire prototype chain of window is locked down https://bugzilla.mozilla.org/show_bug.cgi?id=1052139.

There is still the issue of the Location objects; although I wonder whether it makes sense to have a mutable prototype chain on such objects anyway.

@saambarati

This comment has been minimized.

Show comment
Hide comment
@saambarati

saambarati Sep 9, 2016

@allenwb
I understand that ProxyObject does not have a [[Prototype]] slot. I'm proposing that we make it null (and other objects in the future that may fall into the same category). I know WindowProxy is unrelated to ProxyObject, however, if we only consider the TC39 spec, ProxyObject is the only type of object that overrides [[GetPrototypeOf]], that's what I meant by having that loop be over [[Prototype]] instead of checking the [[GetPrototypeOf]] method.

saambarati commented Sep 9, 2016

@allenwb
I understand that ProxyObject does not have a [[Prototype]] slot. I'm proposing that we make it null (and other objects in the future that may fall into the same category). I know WindowProxy is unrelated to ProxyObject, however, if we only consider the TC39 spec, ProxyObject is the only type of object that overrides [[GetPrototypeOf]], that's what I meant by having that loop be over [[Prototype]] instead of checking the [[GetPrototypeOf]] method.

@jswalden

This comment has been minimized.

Show comment
Hide comment
@jswalden

jswalden Oct 5, 2016

Contributor

FWIW. There are only two classes of objects with overridden [[GetPrototypeOf]] in HTML: every global object that can load scripts, and window.location. Because of https://bugzilla.mozilla.org/show_bug.cgi?id=1052139 and #308 noted earlier, [[Prototype]] mutation on any object that might form a cycle through a global will fail, so no cycle there. Only window.location can participate in cycles.

Functionally, internally I turned the "the [[GetPrototypeOf]] internal method of p is not the ordinary object internal method defined in 9.1.1" check into a new proxy trap. (This new trap was already required to implement this language with respect to Proxy objects. HTML's overridden-[[Prototype]] objects just defined fresh versions of that existing trap.) This is as easy as adding any new trap to SpiderMonkey -- easier, even, because existing [[GetPrototypeOf]] trap definitions pointed out all the places to change (not always true of new traps). Some definitions of the trap are tricky because DOM window objects are represented in a funky way in the presence of the hated document.domain -- but not super-tricky. If "we've heard twice that this complicates engines significantly" is meant to include SpiderMonkey/Gecko, I think that overstates it. The extra engineering time wasn't "significant".

I have no love for [[Prototype]] cycles through window.location. The wry WHATWG blog comment was more for entertainment and amusement at a bizarre quirk, primarily for myself but also for the few others so deep in the weeds, or willing to go there to understand a joke. It was not a claim that window.location cycles were difficult to implement or significantly complicated SpiderMonkey.

Short of additionally making the [[Prototype]] of Location.prototype immutable (it's the only object in window.location's chain with a mutable [[Prototype]]), I see no fix that would require no complexifying MOP alterations. [[Prototype]] mutation is generally stupid, this case especially so, so that change would be fine with me, if we wanted to avoid cyclic [[Prototype]] chains in this one weird case. But I'm quite unbothered if things stayed as-is.

Contributor

jswalden commented Oct 5, 2016

FWIW. There are only two classes of objects with overridden [[GetPrototypeOf]] in HTML: every global object that can load scripts, and window.location. Because of https://bugzilla.mozilla.org/show_bug.cgi?id=1052139 and #308 noted earlier, [[Prototype]] mutation on any object that might form a cycle through a global will fail, so no cycle there. Only window.location can participate in cycles.

Functionally, internally I turned the "the [[GetPrototypeOf]] internal method of p is not the ordinary object internal method defined in 9.1.1" check into a new proxy trap. (This new trap was already required to implement this language with respect to Proxy objects. HTML's overridden-[[Prototype]] objects just defined fresh versions of that existing trap.) This is as easy as adding any new trap to SpiderMonkey -- easier, even, because existing [[GetPrototypeOf]] trap definitions pointed out all the places to change (not always true of new traps). Some definitions of the trap are tricky because DOM window objects are represented in a funky way in the presence of the hated document.domain -- but not super-tricky. If "we've heard twice that this complicates engines significantly" is meant to include SpiderMonkey/Gecko, I think that overstates it. The extra engineering time wasn't "significant".

I have no love for [[Prototype]] cycles through window.location. The wry WHATWG blog comment was more for entertainment and amusement at a bizarre quirk, primarily for myself but also for the few others so deep in the weeds, or willing to go there to understand a joke. It was not a claim that window.location cycles were difficult to implement or significantly complicated SpiderMonkey.

Short of additionally making the [[Prototype]] of Location.prototype immutable (it's the only object in window.location's chain with a mutable [[Prototype]]), I see no fix that would require no complexifying MOP alterations. [[Prototype]] mutation is generally stupid, this case especially so, so that change would be fine with me, if we wanted to avoid cyclic [[Prototype]] chains in this one weird case. But I'm quite unbothered if things stayed as-is.

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Nov 8, 2016

Member

@jswalden

There are only two classes of objects with overridden [[GetPrototypeOf]] in HTML: every global object that can load scripts, and window.location

Can you explain why the former is "every global object that can load scripts", and not just WindowProxy?

However, maybe it is moot, because since the global object prototype chains are immutable now, they cannot be involved in cycles. So Location is the only problem.

Member

domenic commented Nov 8, 2016

@jswalden

There are only two classes of objects with overridden [[GetPrototypeOf]] in HTML: every global object that can load scripts, and window.location

Can you explain why the former is "every global object that can load scripts", and not just WindowProxy?

However, maybe it is moot, because since the global object prototype chains are immutable now, they cannot be involved in cycles. So Location is the only problem.

@jswalden

This comment has been minimized.

Show comment
Hide comment
@jswalden

jswalden Dec 15, 2016

Contributor

@domenic Actually, it probably is just WindowProxy -- looking back now, I think I misspoke. But yes, that particular nuance is moot because non-WindowProxy global objects have immutable prototypes and so can't be in cycles.

Contributor

jswalden commented Dec 15, 2016

@domenic Actually, it probably is just WindowProxy -- looking back now, I think I misspoke. But yes, that particular nuance is moot because non-WindowProxy global objects have immutable prototypes and so can't be in cycles.

@littledan

This comment has been minimized.

Show comment
Hide comment
@littledan

littledan Dec 15, 2016

Member

@jswalden I think it's just Location.prototype that would be affected, actually. That's not an immutable prototype exotic object. By contrast, any mutation to a WindowProxy's proto needs to fail, even if it doesn't form a cycle.

Member

littledan commented Dec 15, 2016

@jswalden I think it's just Location.prototype that would be affected, actually. That's not an immutable prototype exotic object. By contrast, any mutation to a WindowProxy's proto needs to fail, even if it doesn't form a cycle.

@jswalden

This comment has been minimized.

Show comment
Hide comment
@jswalden

jswalden Dec 17, 2016

Contributor

Yes. I think we're both on the same page, just that there's a bit of pronoun trouble going on, and separate references to distinct bits of oddity.

Contributor

jswalden commented Dec 17, 2016

Yes. I think we're both on the same page, just that there's a bit of pronoun trouble going on, and separate references to distinct bits of oddity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment