Skip to content
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

importScripts should be able to fetch in parallel and execute synchronously #3775

Open
nilpatelmicrosoft opened this issue Jun 26, 2018 · 7 comments · May be fixed by #3827
Open

importScripts should be able to fetch in parallel and execute synchronously #3775

nilpatelmicrosoft opened this issue Jun 26, 2018 · 7 comments · May be fixed by #3827

Comments

@nilpatelmicrosoft
Copy link

nilpatelmicrosoft commented Jun 26, 2018

Hi,

I'm looking to change the spec so that importScripts("a.js", "b.js") will download a.js and b.js in parallel and then execute synchronously.

Today, the spec forces vendors to download a.js, execute a.js, and then start downloading b.js before executing b.js. This forced serialization is unoptimized. Instead, the spec should only stipulate the execution order and place no requirements on download order. OR, force vendors to download in parallel.

Is there some reason it has been written such that script downloads wait for previous script execution?

Thanks

@domenic
Copy link
Member

domenic commented Jun 26, 2018

I'm not sure why it's written this way, but here are some guesses:

  • It makes it so that importScripts(a, b) is just sugar for importScripts(a); importScripts(b)
  • It was envisioned that browsers might optimize in the way you describe despite the specification, because historically it was not very observable, and these kind of "preload scanner" optimizations have been sort-of allowed and implemented. For <script> elements this is even explicitly allowed; search for the text "For performance reasons, user agents may start fetching the classic script or module graph (as defined above) as soon as the src attribute is set"

I'd be in favor of loosening the spec here, if there are multiple vendors on board (or maybe some already implement this way). Based on your username, maybe you have some insight into the Edge team's implementation?

However, it might not be worth changing this, given that the future lies in module workers---which have a much more robust script-importing mechanism that already works in the way you desire. We'll see what folks think.

/cc @wanderview from Gecko and @nhiroki from Blink to get their perspective.

@nilpatelmicrosoft
Copy link
Author

Edge team is onboard (I did speak with them) and blink team seems to be onboard as well: https://bugs.chromium.org/p/chromium/issues/detail?id=856488#c3

Thanks

@nilpatelmicrosoft
Copy link
Author

This may be useful to some while we wait for proper module worker support to roll out over the next whatever chunk of time. This feature can be implemented much more quickly.

@wanderview
Copy link
Member

Firefox already implements parallel fetching for importScripts(). It loops on the array of URLs and starts an asynchronous fetch on each one here:

https://searchfox.org/mozilla-central/rev/14cb8f1c238735ba1abe18ad44e39808983c2572/dom/workers/ScriptLoader.cpp#900-907

It requires that they execute in order, though. That is enforced in this code:

https://searchfox.org/mozilla-central/rev/14cb8f1c238735ba1abe18ad44e39808983c2572/dom/workers/ScriptLoader.cpp#1401-1452

AFAICT this behavior has been there since the first worker implementation in gecko.

@wanderview
Copy link
Member

Note, when parallel fetching was implemented I don't think it was observable. It probably is observable now, though, via FetchEvent if the worker is controlled.

@domenic
Copy link
Member

domenic commented Jul 16, 2018

What should happen in the following scenario?

  • importScripts("a", "b", "c")
  • a and c load fine in 1 second
  • b network errors after 500 milliseconds

Seems like the result should be to run the contents of a, throw a "NetworkError" DOMException, and do not run the contents of c. Right? Working on a PR with those semantics now...

@nileshp87
Copy link

I think given the fact that its considered syntactic sugar, that makes sense as the caller script should fail out.

domenic added a commit that referenced this issue Jul 16, 2018
Fixes #3775.

As noted there in more detail, this doesn't change much of the
semantics. Execution order is still synchronous, and errors are still
thrown in the same deterministic fashion for both network failures and
script-running failures. Indeed, Gecko already implements these
semantics.

It's likely that at the time this specification was originally written,
whether these fetches were in parallel or sequential was not observable,
at least by client-side code. However, these days, with the web
performance APIs and with service workers, it's very observable, and we
should be sure that parallel fetching is allowed.

For reference, here is a 2015-08-27 snapshot of this method, before any
of the script-loading refactorings and changes due to module scripts:

https://html.spec.whatwg.org/commit-snapshots/c9e804f04d03a0658bfa689cb0f368a4d2e37936/#dom-workerglobalscope-importscripts

You can see that it was sequential even then.
@domenic domenic linked a pull request Jul 16, 2018 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

4 participants