Skip to content

Commit

Permalink
Load Workers with {type:'module'} in ESM mode (#20452)
Browse files Browse the repository at this point in the history
Even in ESM mode, we use dynamic import to load main code from the Web Worker, so, technically, our Workers dont *have* to be ESM as well - they're compatible with regular script mode too.

Unfortunately, unlike browsers, some bundlers care about the distinction and don't bundle Workers correctly when `new Worker(...)` is used without `{type: 'module'}`. Some recent examples where I've seen this:

- issue with parcel bundler: parcel-bundler/parcel#8727 (comment)
 - issue with esbuild bundler used by popular vite toolchain: GoogleChromeLabs/web-gphoto2#12

In both cases adding `{type: 'module'}` fixes the build.

One difference this change will make is that `{type: 'module'}` forces Worker to be loaded as a module which always runs in strict JS mode.

Our main code should already be compatible with `use strict`, or it wouldn't work as ESM at all, and our `src/worker.js` code has `use strict` at the top, so it's compatible too, so I don't expect any issues, but it's something worth keeping in mind if we get breakage reports.

Also note that older browsers without Module Workers support will ignore `{type: 'module'}` and run Workers in script mode, so as long as we don't use static imports or `import.meta.url` in `src/worker.js`, this is a backward-compatible change.
  • Loading branch information
RReverser committed Oct 16, 2023
1 parent 5b24a09 commit 31b71a5
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 5 deletions.
6 changes: 3 additions & 3 deletions src/library_pthread.js
Original file line number Diff line number Diff line change
Expand Up @@ -452,10 +452,10 @@ var LibraryPThread = {
createScriptURL: (ignored) => new URL('{{{ PTHREAD_WORKER_FILE }}}', import.meta.url);
}
);
worker = new Worker(p.createScriptURL('ignored'));
worker = new Worker(p.createScriptURL('ignored'), {type: 'module'});
} else
#endif
worker = new Worker(new URL('{{{ PTHREAD_WORKER_FILE }}}', import.meta.url));
worker = new Worker(new URL('{{{ PTHREAD_WORKER_FILE }}}', import.meta.url), {type: 'module'});
} else {
#endif
// Allow HTML module to configure the location where the 'worker.js' file will be loaded from,
Expand Down Expand Up @@ -568,7 +568,7 @@ var LibraryPThread = {
// Called when a thread needs to be strongly referenced.
// Currently only used for:
// - keeping the "main" thread alive in PROXY_TO_PTHREAD mode;
// - crashed threads that needs to propagate the uncaught exception
// - crashed threads that needs to propagate the uncaught exception
// back to the main thread.
#if ENVIRONMENT_MAY_BE_NODE
if (ENVIRONMENT_IS_NODE) {
Expand Down
4 changes: 2 additions & 2 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ def test_emcc_output_worker_mjs(self, args):
test_file('hello_world.c')] + args)
src = read_file('subdir/hello_world.mjs')
self.assertContained("new URL('hello_world.wasm', import.meta.url)", src)
self.assertContained("new Worker(new URL('hello_world.worker.js', import.meta.url))", src)
self.assertContained("new Worker(new URL('hello_world.worker.js', import.meta.url), {type: 'module'})", src)
self.assertContained('export default Module;', src)
src = read_file('subdir/hello_world.worker.js')
self.assertContained("import('./hello_world.mjs')", src)
Expand All @@ -317,7 +317,7 @@ def test_emcc_output_worker_mjs_single_file(self):
test_file('hello_world.c'), '-sSINGLE_FILE'])
src = read_file('hello_world.mjs')
self.assertNotContained("new URL('data:", src)
self.assertContained("new Worker(new URL('hello_world.worker.js', import.meta.url))", src)
self.assertContained("new Worker(new URL('hello_world.worker.js', import.meta.url), {type: 'module'})", src)
self.assertContained('hello, world!', self.run_js('hello_world.mjs'))

def test_emcc_output_mjs_closure(self):
Expand Down

0 comments on commit 31b71a5

Please sign in to comment.