-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Comments
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?) |
Cc @verwaest |
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 |
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. |
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? |
@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. |
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). |
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. |
FYI, this is not just HTML's WindowProxy that is affected but also HTML's Location object. |
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" |
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. |
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. |
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. |
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. |
@bterlson |
@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. |
@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. |
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 |
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. |
@allenwb |
@saambarati |
@domenic |
Interestingly, in Firefox, even without the cycle check, it is impossible to have a prototype chain cycle involving 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. |
@allenwb |
FWIW. There are only two classes of objects with overridden Functionally, internally I turned the "the I have no love for Short of additionally making the |
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. |
@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. |
@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 |
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. |
This is both a long and old thread; could someone clarify if there's still something that needs to be done here? |
@ljharb basically, what should the behavior for
be, I think, and does that require changes to ECMAScript? It seems that in Firefox and Safari |
Since the spec now has language for "immutable prototype exotic objects", could |
Ah, I suspect so. Would be great if @jswalden could confirm that's indeed what we've done for Firefox (and perhaps @saambarati for Safari given they raised this), as I'm not entirely confident in my testing. |
Remaining outstanding issue of tc39/ecma262#683.
Created a PR for IDL assuming I'm correct: whatwg/webidl#606. |
Update at whatwg/webidl#606 (comment). I was wrong, the problematic code is So we're back to 1) implementers willing to change |
I chatted with @jswalden once more and at least Firefox doesn't consider the current state of things to be a problem here. Web-platform-tests already covers this in @saambarati @syg is this something that can be fixed in Safari and Chrome, respectively? I.e., allow cycles for |
@saambarati @syg ping. |
Some background on WebKit issue: we have a few helpers that determine if a fast path can be taken. As an example, for For performance reasons, these helpers need to get However, these helpers should also bail for
and implement it. I will submit a patch once the last helper that doesn't check for non-ordinary |
@shvaikalesh would that mean WebKit will then pass the WPT test? If so, we can close this and #1986. |
@annevk That's right. Cyclic prototype chains are already a thing because of Please track this bug for progress on that (probably) last helper, which is a blocker for the |
Maybe @yuki3 can comment on the Chromium/V8 side of this? |
Let me check my understanding first. We'd like to support cyclic prototype chains for WindowProxy, Location, and Proxy at least because their I think that this is an area of V8. If V8 team is going to provide appropriate behaviors and APIs, I can make changes in Blink accordingly (just use the new APIs). I filed a V8 issue. Please add comments to correct my understanding and/or add more contexts. |
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:
(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.
The text was updated successfully, but these errors were encountered: