diff --git a/src/lib/libpthread.js b/src/lib/libpthread.js index badc551048420..765c052a2f575 100644 --- a/src/lib/libpthread.js +++ b/src/lib/libpthread.js @@ -423,6 +423,15 @@ var LibraryPThread = { var p = trustedTypes.createPolicy('emscripten#workerPolicy1', { createScriptURL: (ignored) => import.meta.url }); worker = new Worker(p.createScriptURL('ignored'), {{{ pthreadWorkerOptions }}}); } else +#endif +#if expectToReceiveOnModule('mainScriptUrlOrBlob') + if (Module['mainScriptUrlOrBlob']) { + var pthreadMainJs = Module['mainScriptUrlOrBlob']; + if (typeof pthreadMainJs != 'string') { + pthreadMainJs = URL.createObjectURL(pthreadMainJs); + } + worker = new Worker(pthreadMainJs, {{{ 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 diff --git a/test/pthread/main_js_as_blob_loader.html b/test/pthread/main_js_with_loader.html similarity index 91% rename from test/pthread/main_js_as_blob_loader.html rename to test/pthread/main_js_with_loader.html index 2ec93f75ec0ff..0112c5e356902 100644 --- a/test/pthread/main_js_as_blob_loader.html +++ b/test/pthread/main_js_with_loader.html @@ -147,28 +147,6 @@ }; - + diff --git a/test/test_browser.py b/test/test_browser.py index 8dbfe4e5221ca..f37fe694cc87c 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -4756,18 +4756,55 @@ def test_pthread_growth(self, emcc_args): def test_pthread_reltime(self): self.btest_exit('pthread/test_pthread_reltime.cpp', emcc_args=['-pthread', '-sPTHREAD_POOL_SIZE']) - # Tests that it is possible to load the main .js file of the application manually via a Blob URL, + # Tests that it is possible to load the main .js file of the application manually via mainScriptUrlOrBlob, # and still use pthreads. - def test_load_js_from_blob_with_pthreads(self): + @parameterized({ + 'blob': (False, True), + 'url': (False, False), + 'blob_es6': (True, True), + 'url_es6': (True, False), + }) + def test_mainScriptUrlOrBlob(self, es6, use_blob): # TODO: enable this with wasm, currently pthreads/atomics have limitations self.set_setting('EXIT_RUNTIME') + js_name = 'hello_thread_with_loader.%s' % ('mjs' if es6 else 'js') + if es6: + self.emcc_args += ['-sEXPORT_ES6'] + if es6 and use_blob: + create_file('loader.mjs', ''' + Module['locateFile'] = (path,_prefix) => path; + let blob = await (await fetch('hello_thread_with_loader.mjs')).blob(); + Module['mainScriptUrlOrBlob'] = blob; + (await import(URL.createObjectURL(blob))).default(Module); + ''') + elif use_blob: + create_file('loader.mjs', ''' + let blob = await (await fetch('hello_thread_with_loader.js')).blob(); + Module['mainScriptUrlOrBlob'] = blob; + var script = document.createElement('script'); + script.src = URL.createObjectURL(blob); + document.body.appendChild(script); + ''') + elif es6: + create_file('loader.mjs', ''' + Module['mainScriptUrlOrBlob'] = 'hello_thread_with_loader.mjs'; + (await import('./hello_thread_with_loader.mjs')).default(Module); + ''') + else: + create_file('loader.mjs', ''' + var script = document.createElement('script'); + Module['mainScriptUrlOrBlob'] = 'hello_thread_with_loader.js'; + script.src = Module['mainScriptUrlOrBlob']; + document.body.appendChild(script); + ''') + self.compile_btest('pthread/hello_thread.c', ['-pthread', '-o', 'out.js'], reporting=Reporting.JS_ONLY) # Now run the test with the JS file renamed and with its content # stored in Module['mainScriptUrlOrBlob']. - shutil.move('out.js', 'hello_thread_with_blob_url.js') - shutil.copy(test_file('pthread/main_js_as_blob_loader.html'), 'hello_thread_with_blob_url.html') - self.run_browser('hello_thread_with_blob_url.html', '/report_result?exit:0') + shutil.move('out.js', js_name) + shutil.copy(test_file('pthread/main_js_with_loader.html'), 'hello_thread_with_loader.html') + self.run_browser('hello_thread_with_loader.html', '/report_result?exit:0') # Tests that SINGLE_FILE works as intended in generated HTML (with and without Worker) @also_with_proxying diff --git a/test/test_other.py b/test/test_other.py index 798c1bbadd605..1bb2d711738be 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -15865,15 +15865,26 @@ def test_rollup(self): def test_rlimit(self): self.do_other_test('test_rlimit.c', emcc_args=['-O1']) - def test_mainScriptUrlOrBlob(self): + @parameterized({ + '': (False,), + 'es6': (True,), + }) + def test_mainScriptUrlOrBlob(self, es6): + ext = "js" + args = [] + if es6: + ext = "mjs" + args = ['-sEXPORT_ES6', '--extern-post-js', test_file('modularize_post_js.js')] + outfile = ('a.out.%s' % ext) # Use `foo.js` instead of the current script name when creating new threads - create_file('pre.js', 'Module = { mainScriptUrlOrBlob: "./foo.js" }') - self.run_process([EMCC, test_file('hello_world.c'), '-sEXIT_RUNTIME', '-sPROXY_TO_PTHREAD', '-pthread', '--pre-js=pre.js']) + create_file('pre.js', 'Module = { mainScriptUrlOrBlob: "./foo.%s" }' % ext) - # First run without foo.js present to verify that the pthread creation fails - err = self.run_js('a.out.js', assert_returncode=NON_ZERO) - self.assertContained('Cannot find module.*foo.js', err, regex=True) + self.run_process([EMCC, test_file('hello_world.c'), '-sEXIT_RUNTIME', '-sPROXY_TO_PTHREAD', '-pthread', '--pre-js=pre.js', '-o', outfile] + args) + + # First run without foo.[m]js present to verify that the pthread creation fails + err = self.run_js(outfile, assert_returncode=NON_ZERO) + self.assertContained('Cannot find module.*foo\\.', err, regex=True) - # Now create foo.js and the program should run as expected. - shutil.copy('a.out.js', 'foo.js') - self.assertContained('hello, world', self.run_js('a.out.js')) + # Now create foo.[m]js and the program should run as expected. + shutil.copy(outfile, ('foo.%s' % ext)) + self.assertContained('hello, world', self.run_js(outfile))