-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
javascript URLs that do not return strings is apparently wrong #1896
Comments
"wrong" is a slightly loaded term. What I will claim is that the current spec does not match non-Gecko UAs, which it claimed to do, and is not web-compatible. The latter problem is described in in #1895 For the former, a quick check suggests that at least Chrome and Safari seem to convert non-string values to the string "" and then proceed to load that as the response body. They also treat exceptions in the javascript: as "". Here's the testcase I used:
This is one possible thing that could be specified, and would not suffer from the problem described in #1895. It would not match longstanding IE/Gecko/Netscape behavior for I haven't tested what Chrome/Safari do in other cases of interest, like:
or whatever other cases currently get commoned up into the "return value is not string" codepath. |
Oh, and the point is that the "script is disabled" and "CSP blocks the execution" cases can still have it be observable whether the load event fires, so the interaction there would need to be specified not matter what, even if we take the Blink/WebKit approach for the cases in the testcase I pasted above. |
What I don't understand is why this is different from the current spec, which says
I'm probably just missing something, but that's the largest source of my confusion. |
Oh, duh, it's because 204s abort in the next algorithm. I get it, sorry. |
Right, exactly. |
OK, here is the problem. Your test case, with loading things into iframe I don't really know what to make of this. Is this distinction make elsewhere in navigation? How do Blink and WebKit actually implement this!? |
DO NOT MERGE until we settle #1896; see #1896 (comment).
Well. See my (somewhat lazy, not backed by testing) comments about "not-initial javascript: loads" in #1895 (comment). But of course my testcase in this bug also has non-initial loads.
Last I looked, really crazily. ;) Starting with "not in navigation, unlike the spec". That's mostly what you can make of this.
Not particularly, no. Note that it's worth testing what location.href sets do as well; those may have yet another behavior. Or maybe we're lucky and they match anchor clicks. One piece of good news is that for web compat purposes we don't need to duplicate WebKit/Blink here in general.... The problem is that we're not sure what a saner web-compatible behavior is, apart from the current Firefox or Edge ones (which are different, note; I have no idea what Edge really does!). |
At this point I'm leaning toward the current Firefox behavior, as it sounds rather easy to spec. But I feel like I should probably do more research and testing and noodling over the spec to see what variations would be less invasive... |
Does using javascript: URLs in the following ways cause navigation? A per-browser breakdown.
Leaving Safari as ?s since I don't have my Safari tech preview computer for the weekend, but my guess is it's going to be the same as Chrome. I might have gotten turned around, but this implies that Edge and Firefox are compatible with the current spec. But @bzbarsky, you say that that's not web-compatible? Despite Edge and Firefox shipping it to stable? |
The main web compat requirement I'm aware of for the non-string case is this:
needs to fire a load event. Certainly when In terms of what's shipped, Firefox until Firefox 49 fired the load event in that situation for non-undefined return values, because it did a navigation (to the ToString() of the return value). Firefox 49 aligned with the spec, which does NOT fire a load event in that situation, and this broke a bunch of websites; we did not get any bug reports until shipping to stable because all the sites involved require an account and we didn't have any pre-release users with accounts on those sites who noticed the issue, apparently. :( We're likely to do a point release of Firefox 49 soon, backing out my change to align with the current spec. All the non-release branches have already been updated with the backout. As for Edge, I have verified that it does fire a load event in the case of:
but I have not investigated in detail whether it performs a navigation or not, in that situation and others; testing Edge on my end is a bit of a pain. |
So to be clear, the known-web-compatible "Firefox behavior" is not found in current release Firefox 49, nor in Firefox nightlies from a few days ago (before the backout). You can see it in a nightly from 2016-10-15 (today), though. |
And note that "non-string" in the Firefox behavior contains two buckets that have different behaviors: there's |
When exactly does |
Unclear. The failure symptoms on the web were that if it never fired one, sites would "hang" because they were waiting for that event to do other stuff. https://bugzilla.mozilla.org/show_bug.cgi?id=1307420#c9 has a quote of the relevant jQuery plugin code. You may be able to find other information in https://bugzilla.mozilla.org/show_bug.cgi?id=1306472 and its various duplicates... It's possible that treating this load as a 204 but still firing a load event like we would for no src at all or src="about:blank" might be good enough. I just can't tell you.
Unknown. Worth checking whether it does in browsers. |
<!DOCTYPE html>
<script>w("before iframe")</script>
<iframe onload=w('load') src=javascript:false></iframe>
<script>w("after iframe")</script> With <!DOCTYPE html>
<iframe onload=w('load')></iframe>
<script>
setTimeout(() => {
w("timeout")
document.querySelector("iframe").src = "javascript:false"
w("after src")
}, 200)
</script> Ends up as |
As far as Chrome and Safari go, they do weird sync stuff with javascript: even in the string case. Most simply:
logs: Also note that this testcase:
shows that the load of
though that one is treated as a 204 in Firefox and Edge. |
I'd be okay with just loading an empty 200. I guess effectively treating them as navigating to about:blank? |
I guess we have no indication that "sync stuff happens" based on those testcases, as opposed to "iframe with javascript: src blocks the parser until its src runs". But this testcase:
shows that it really is "sync stuff happens", complete with the two firings of onload.
For which cases?
Whatever cases these are, why not just treat them as if the javascript: returned "" for simplicity, instead of having to shoehorn about:blank in there? Note that I did point out some of these aspects of the behavior in #1896 (comment) along with my list of things that still need testing... |
Per https://bugzilla.mozilla.org/show_bug.cgi?id=1382035 there is now a web-compat requirement that It would be good to get this thing sorted out, given that it's causing real-life compat pain. @domenic can Chrome align closer to the spec for its javascript: handling, or failing that create good documentation for what it's actually doing? |
:( I can ask around about aligning Chrome closer to the spec, although it sounds like the spec is not web-compatible and we'd need to work on a better spec first. I haven't had time for that myself; again I can ask around, but perhaps Mozilla could help? As for Chrome creating documentation on what we're doing, again I can ask around. I suppose Chrome engineers are better positioned to read their source code and transcribe it into prose than other folks would be... |
The part of the spec that is not web-compatible is the load event behavior, not the handling of javascript: per se, for what it's worth. |
But in general, I can obviously spec what Firefox does, say. The question is whether Chrome would be willing to implement it. If not, what are the constraints on what Chrome is willing to implement? |
Hmm I guess I don't understand the load event connection, but maybe I need to page more of this area/thread into my memory. I know @zetafunction was looking in to modernizing Chrome's javascript: handling, specifically wanting to make it async, in #3730. That does indeed point to some constraints, or at least wishes. Let me try to get him specifically to chime in. |
The load event connection is described in #1895 |
I think we're willing to implement what Firefox specs. Unfortunately, there's a lot of things that are broken about javascript: URLs in Chrome. From my perspective, the two things we should fix first are:
@bzbarsky Am I correct in understanding that Firefox matches the spec queues a task to run the javascript: URL steps in https://html.spec.whatwg.org/multipage/browsing-the-web.html#javascript-protocol? I'd like to make sure that any changes we make here bring us closer to the spec and Firefox. |
So generally speaking, what Firefox implements aims to match the current spec, with to my knowledge two exceptions. One is what the final URL of a javascript: navigation is, and we are planning to align to the spec on that. The other is that https://html.spec.whatwg.org/multipage/browsing-the-web.html#javascript-protocol step 12 is instead:
There might be some complications around the exception-reporting part in terms of sync vs async. |
@zetafunction do we have an open issue for "run the Javascript URL processing steps asynchronously"? It looks to at a glance like nothing in https://wpt.fyi/results/html/browsers/browsing-the-web/navigating-across-documents is targeting this behavior, does anyone know if there are other tests for it? @bzbarsky, perhaps in Gecko? |
We have #3730 but last I asked @zetafunction he said that @annevk convinced him that was not the right way to go. If so maybe closing that one and opening a new one more targeted at javascript: URLs would be helpful. |
I was thinking of an issue on crbug.com, but sounds like any change is still blocked on some spec changes? |
See @bzbarsky's comment at #1107 (comment).
@bzbarsky could you explain in more detail how the current spec is wrong? Is the idea that the response status should not be 204, and that it should have a Content-Type header, but it should still have the empty body?
The text was updated successfully, but these errors were encountered: