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

Accessing `document.currentScript` in async chunks returns null in Firefox #10510

Open
Justineo opened this issue Mar 6, 2020 · 4 comments
Open

Comments

@Justineo
Copy link

@Justineo Justineo commented Mar 6, 2020

Bug report

What is the current behavior?

If modules in an async chunk calls document.currentScript, the result will be null in Firefox while other browsers returns the expected <script> element.

If the current behavior is a bug, please provide the steps to reproduce.

The details of the issue is at this repo.

What is the expected behavior?

Developers should have a way to workaround Firefox's potential bug. eg. webpack provide a __webpack_current_script__ inside each async chunk.

Details

The entry file is index.js which contains only:

import("./async")

Where async.js calls document.currentScript:

console.log(document.currentScript);

document.getElementById("output").textContent = document.currentScript
  ? document.currentScript.src
  : "null";

After we compiled index.js with webpack, two files will be produce into the dist folder:

dist/
  1.js
  main.js

After introducing the main.js in index.html, we'll notice that in Chrome, we can see the correct script src:

$PROJECT_PATH/dist/1.js

While in Firefox we got null.

After I did a little investigation, the only difference I found is that Firefox is treating scripts run inside a micro task the same way as those in timeout callbacks, making document.currentScript being evaluated as null. While in other browsers, it's evaluated to the expected script element.

Per the HTML spec:

(document.currentScript) Returns null if the Document is not currently executing a script or SVG script element (e.g., because the running script is an event handler, or a timeout), or if the currently executing script or SVG script element represents a module script.

I'd say it's a little ambiguous about whether for micro tasks it should return null. Plus this section is labelled as "non-normative". But it's indeed unexpected that browsers handle this differently. I've filed an issue on Bugzilla here.

Though it's a potential bug on the Firefox side, but I think we have a chance to fix this on the webpack side.

When webpack generates an async chunk, we can evaluate document.currentScript synchronously upfront, and save it to a private variable like __webpack_current_script__ so that if developers have a chance to work this around by try accessing __webpack_current_script__ instead of document.currentScript.

Thanks for your time!

Other relevant information:
webpack version: 4.42.0
Node.js version: 12.13.1
Operating System: macOS 10.15.1
Additional tools: /

@sokra
Copy link
Member

@sokra sokra commented Mar 6, 2020

why do you need access to the currect script?

@Justineo
Copy link
Author

@Justineo Justineo commented Mar 7, 2020

Currently when building with Vue CLI's lib mode, document.currentScript is used to help set publicPath for __webpack_require__ so that assets can be imported dynamically. When importing a lib built with such setup in webpack-based projects, we may reproduce this issue. A fix on Vue CLI's side is already proposed (vuejs/vue-cli#5247) but the fix is kind of cumbersome and other projects may come across same problem.

@sokra
Copy link
Member

@sokra sokra commented Mar 9, 2020

so that assets can be imported dynamically

So this helper need to imported before any async chunk. But why do you need document.currentScript in an async chunk?

@Justineo
Copy link
Author

@Justineo Justineo commented Mar 9, 2020

For example, if a library built with Vue CLI () is imported in a project and is later bundled inside an async chunk, document.currentScript will be evaluated inside an async chunk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.