Skip to content

Support blob URLs on ES6 with USE_ES6_IMPORT_META enabled #23804

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

Closed

Conversation

JoeOsborn
Copy link
Contributor

Per the discussion in #23769, implement this policy:

  • If mainScriptUrlOrBlob is set, create the worker as in the old non-use-import-meta case
  • If import.meta.url is a blob url, use it for the worker script
  • Otherwise, use new URL(TARGET_JS_NAME, import.meta.url)

I know I didn't add any automated tests; I'd appreciate pointers on how to implement tests for this.

if (Module['mainScriptUrlOrBlob']) {
var pthreadMainJs = Module['mainScriptUrlOrBlob'];
if (typeof pthreadMainJs != 'string') {
pthreadMainJs = URL.createObjectURL(pthreadMainJs);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like pthreadMainJs it not being used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I had a typo on the next line. Should have read new Worker(pThreadMainJS). I’ll submit a fix soon.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve corrected it but I’m also ok to throw an error in case mainScriptUrlOrBlob is set under ES6_MODULES given -sASSERTIONS.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we split this up and into a PR just for mainScriptUrlOrBlob support? And include a test for that?

I think the change to use new Worker(import.meta.url..) can / should be separate .. and might take a longer to land since we want to confirm that it works in all the different bundlers.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, can you remove the USE_ES6_IMPORT_META from the title (that setting was removed).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I can do this.

// instead of just using new URL(import.meta.url) because bundler's only recognize
// the first case in their bundling step. The latter ends up producing an invalid
// URL to import from the server (e.g., for webpack the file:// path).
worker = new Worker(new URL('{{{ TARGET_JS_NAME }}}', import.meta.url), {{{ pthreadWorkerOptions }}});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Man.. this limitation of the bundlers really makes our generated code nasty. I wonder if the bundlers can be fixed... its really a shame to have all this extra stuff just to make them happy.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we could just fix webpack to support new Worker(import.meta.url) which is what we actually want to write here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found a webpack bug from way back about this: webpack/webpack#12638

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding from webpack/webpack#12638 (comment) is that this is fixed now, so what’s the move? To keep the mainScriptUrlOrBlob path and default to new Worker(import.meta.url, options), eliminating the new URL calls/paths?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic. I think we should probably check with all the different bundlers, but assuming we can go with new Worker(import.meta.ur) that sounds like the best solution.

Re-adding support for mainScriptUrlOrBlob sounds good too.

{
if (import.meta.url.startsWith('blob:')) {
// If our import.meta.url is a blob, we should just use it.
worker = new Worker(import.meta.url, {{{ pthreadWorkerOptions }}});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this syntax is not currently supported by webpack :( Although it does look like it now is support by vite, which is good!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't there be some mechanism to make emscripten use worker = new Worker(import.meta.url, ...)?

i was excited to hear about USE_ES6_IMPORT_META but it seems that's the bundler hack with import.meta.url as the base.

@schlawg
Copy link

schlawg commented Mar 4, 2025

While you're tinkering there, why isn't mainScriptUrlOrBlob honored in the EXPORT_ES6 code path when it's just a string? It seems consistent and uncontroversial to do that.

Per the discussion in emscripten-core#23769, implement this policy:

- If mainScriptUrlOrBlob is set, create the worker as in the old non-use-import-meta case
- Otherwise, use import.meta.url
@JoeOsborn
Copy link
Contributor Author

Closing in favor of #23890 , #23889 .

@JoeOsborn JoeOsborn closed this Mar 11, 2025
sbc100 pushed a commit that referenced this pull request Mar 15, 2025
Spun out from #23804 .

This is a fix for #23769 which was introduced by #23171 , where the use
of the bundler pattern hard-coding a script name was made to apply to
all ES6 exports.

`mainScriptUrlOrBlob` is necessary under es6 exports to support running
a threaded emscripten module from another origin, e.g. to distribute an
emscripten module on a CDN (the script will load for the main thread but
won’t be allowed to create workers). Using blobs is an effective
workaround.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants