WICG / document-policy

https://wicg.github.io/document-policy/
Other
19 stars 8 forks source link

Allowing cases where document.write is "ok" #18

Open jakearchibald opened 5 years ago

jakearchibald commented 5 years ago

Ok ok, hear me out.

I'm assuming we're allowing developers to block document.write because injecting into the browser's streaming parser is a slow path, and can break things like look-ahead parsing.

https://jakearchibald.com/2016/fun-hacks-faster-content/ - here I use document.write in an about:blank iframe to hook into the streaming parser, but I'm pretty sure it doesn't negatively impact the parent page.

Maybe document.write should be allowed if document.open() is called either explicitly or implicitly during the life of the document. In spec terms, I think this means document.write should be allowed if the document open steps have run for this document.

triblondon commented 5 years ago

Perhaps it might be simpler in cases like this to just allow the document-write policy on the relevant origin.

foolip commented 5 years ago

I came here to file this issue, but I'd like to go further. Probably the most problematic aspect is the ability to document.write(<script src=script.js>)... which is parser-blocking and thus blocks the main thread on the fetch of script.js, much like sync XHR. https://wpt.fyi/results/html/webappapis/dynamic-markup-insertion/document-write/script_007.html is a simple demonstration of this.

https://developers.google.com/web/updates/2016/08/removing-document-write describes an intervention of parser-blocking scripts when a lot of conditions are met.

Should we have a policy for only the parser-blocking behavior of document.write?

jakearchibald commented 5 years ago

That's what I was trying to define with:

Maybe document.write should be allowed if document.open() is called either explicitly or implicitly during the life of the document. In spec terms, I think this means document.write should be allowed if the document open steps have run for this document.

foolip commented 5 years ago

@jakearchibald I see, glad to hear you were also shooting for the same thing!

Trying to figure out what the most surgical restriction of bad document.write behavior would be I came across sync-script which is a policy for parser-blocking scripts.

If that policy also applies to document.write-added scripts, which I presume it does, then are there any remaining performance issues with document.write?

and thus blocks the main thread on the fetch of script.js, much like sync XHR

I made a mistake here, these scripts block the parser, but the document.write call returns before the script is fetched and timers still run, so it's not blocking the main thread, but is blocking important events. (Demo: https://software.hixie.ch/utilities/js/live-dom-viewer/saved/6940)

foolip commented 5 years ago

@clelland, looking at https://github.com/w3c/webappsec-feature-policy/blob/master/policies/document-write.md, I wonder if some of that isn't more about sync-script than document-write. It says:

anti-pattern, parser-blocking JavaScript API

However, is the parser-blocking behavior not covered by sync-script? Is there a problem with document.write in addition to that?

Jamesernator commented 5 years ago

Isn't one of the pros of Feature-Policy so that browsers can not even bother loading chunks of their engine when they see features aren't needed? And hence speed up performance of sites they know aren't using certain features.

This feels like that would defeat that, given engines would need to load it anyway as a call to document.open could still occur at any time.

I think it would be a way better idea to investigate solutions to the use cases of document.write and create a new API that solves them instead of weakening Feature-Policy.

jakearchibald commented 5 years ago

Isn't one of the pros of Feature-Policy so that browsers can not even bother loading chunks of their engine when they see features aren't needed?

I don't know if that's the case here.

I think it would be a way better idea to investigate solutions to the use cases of document.write and create a new API that solves them instead of weakening Feature-Policy.

That's reasonable, but the new thing should be in place before the deprecation of the old thing.

Jamesernator commented 5 years ago

I don't know if that's the case here.

I can't imagine much by itself (although there seems to be interest in getting rid of it), however combined with other policies (e.g. sync-script/sync-xhr) I can imagine whole parts of the HTML parsing algorithm might be able to be turned off.

but the new thing should be in place before the deprecation of the old thing.

It's not clear to me if document.write is deprecated proper or not, nevertheless Feature-Policy is an opt-in mechanism, if you want to use document.write just don't include document-write 'none' in your Feature-Policy (or specify the domains allowed).

foolip commented 5 years ago

Basically what document.write does is to add text to the input stream of the parser just as if it had arrived on the network (and been decoded) so knowing it won't be called unfortunately wouldn't allow much simplification.

Given enough knowledge of unreachable code it's possible certain fast paths could be enabled, but I don't know that anyone has given this much thought.