Fix for vite bundling with pthreads enabled
Replaces #23607
Fixes: #22394
diff --git a/src/lib/libpthread.js b/src/lib/libpthread.js
index a3c4cb4..c009e99 100644
--- a/src/lib/libpthread.js
+++ b/src/lib/libpthread.js
@@ -29,6 +29,30 @@
#else
globalThis.MAX_PTR = (2 ** 32) - 1
#endif
+// Use a macro to avoid duplicating pthread worker options.
+// We cannot use normal JS variable since the vite bundler requires that worker
+// options be inline.
+// See https://github.com/emscripten-core/emscripten/issues/22394
+globalThis.pthreadWorkerOptions = `{
+#if EXPORT_ES6
+ 'type': 'module',
+#endif
+#if ENVIRONMENT_MAY_BE_NODE
+ // This is the way that we signal to the node worker that it is hosting
+ // a pthread.
+ 'workerData': 'em-pthread',
+#endif
+#if ENVIRONMENT_MAY_BE_WEB || ENVIRONMENT_MAY_BE_WORKER
+ // This is the way that we signal to the Web Worker that it is hosting
+ // a pthread.
+#if ASSERTIONS
+ 'name': 'em-pthread-' + PThread.nextWorkerID,
+#else
+ 'name': 'em-pthread',
+#endif
+#endif
+}`;
+null
}}}
var LibraryPThread = {
@@ -394,25 +418,6 @@
// Creates a new web Worker and places it in the unused worker pool to wait for its use.
allocateUnusedWorker() {
var worker;
- var workerOptions = {
-#if EXPORT_ES6
- 'type': 'module',
-#endif
-#if ENVIRONMENT_MAY_BE_NODE
- // This is the way that we signal to the node worker that it is hosting
- // a pthread.
- 'workerData': 'em-pthread',
-#endif
-#if ENVIRONMENT_MAY_BE_WEB || ENVIRONMENT_MAY_BE_WORKER
- // This is the way that we signal to the Web Worker that it is hosting
- // a pthread.
-#if ASSERTIONS
- 'name': 'em-pthread-' + PThread.nextWorkerID,
-#else
- 'name': 'em-pthread',
-#endif
-#endif
- };
#if EXPORT_ES6 && USE_ES6_IMPORT_META
// If we're using module output, use bundler-friendly pattern.
#if PTHREADS_DEBUG
@@ -427,14 +432,14 @@
createScriptURL: (ignored) => new URL("{{{ TARGET_JS_NAME }}}", import.meta.url)
}
);
- worker = new Worker(p.createScriptURL('ignored'), workerOptions);
+ worker = new Worker(p.createScriptURL('ignored'), {{{ pthreadWorkerOptions }}});
} else
#endif
// We need to generate the URL with import.meta.url as the base URL of the JS file
// 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), workerOptions);
+ worker = new Worker(new URL('{{{ TARGET_JS_NAME }}}', import.meta.url), {{{ pthreadWorkerOptions }}});
#else
var pthreadMainJs = _scriptName;
#if expectToReceiveOnModule('mainScriptUrlOrBlob')
@@ -454,10 +459,10 @@
// Use Trusted Types compatible wrappers.
if (typeof trustedTypes != 'undefined' && trustedTypes.createPolicy) {
var p = trustedTypes.createPolicy('emscripten#workerPolicy2', { createScriptURL: (ignored) => pthreadMainJs });
- worker = new Worker(p.createScriptURL('ignored'), workerOptions);
+ worker = new Worker(p.createScriptURL('ignored'), {{{ pthreadWorkerOptions }}});
} else
#endif
- worker = new Worker(pthreadMainJs, workerOptions);
+ worker = new Worker(pthreadMainJs, {{{ pthreadWorkerOptions }}});
#endif // EXPORT_ES6 && USE_ES6_IMPORT_META
PThread.unusedWorkers.push(worker);
},
diff --git a/test/test_browser.py b/test/test_browser.py
index 20fa6ea..d0d47ff 100644
--- a/test/test_browser.py
+++ b/test/test_browser.py
@@ -5534,10 +5534,11 @@
shutil.copy('webpack/src/hello.wasm', 'webpack/dist/')
self.run_browser('webpack/dist/index.html', '/report_result?exit:0')
+ @also_with_threads
def test_vite(self):
shutil.copytree(test_file('vite'), 'vite')
with common.chdir('vite'):
- self.compile_btest('hello_world.c', ['-sEXPORT_ES6', '-sEXIT_RUNTIME', '-sMODULARIZE', '-o', 'hello.mjs'])
+ self.compile_btest('hello_world.c', ['-sEXPORT_ES6', '-sEXIT_RUNTIME', '-sMODULARIZE', '-sENVIRONMENT=web,worker', '-o', 'hello.mjs'])
self.run_process(shared.get_npm_cmd('vite') + ['build'])
self.run_browser('vite/dist/index.html', '/report_result?exit:0')
diff --git a/test/test_other.py b/test/test_other.py
index 5995a90..8f9d704 100644
--- a/test/test_other.py
+++ b/test/test_other.py
@@ -380,7 +380,7 @@
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.mjs', import.meta.url), workerOptions)", src)
+ self.assertContained("new Worker(new URL('hello_world.mjs', import.meta.url), {", src)
self.assertContained('export default Module;', src)
self.assertContained('hello, world!', self.run_js('subdir/hello_world.mjs'))
@@ -391,7 +391,7 @@
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.mjs', import.meta.url), workerOptions)", src)
+ self.assertContained("new Worker(new URL('hello_world.mjs', import.meta.url), {", src)
self.assertContained('hello, world!', self.run_js('hello_world.mjs'))
def test_emcc_output_mjs_closure(self):