Skip to content

Commit d8f3334

Browse files
authored
Allow pthread-based programs to be loaded cross-origin (#25581)
For some reason creating new workers across origins is not allowed, even when `importScripts` is. Added a test case which was confirmed to fail without this PR. Fixes: #21937
1 parent 29bf936 commit d8f3334

File tree

5 files changed

+71
-1
lines changed

5 files changed

+71
-1
lines changed

ChangeLog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ See docs/process.md for more on how version tagging works.
2222
-----------------------
2323
- `-sUSE_WEBGPU` was removed in favor of the external port Emdawnwebgpu which
2424
are used via `--use-port=emdawnwebgpu`. See 4.0.10 release notes for details.
25+
- A new `CROSS_ORIGIN` setting was added in order to work around issues hosting
26+
emscripten programs across different origins (#25581)
2527

2628
4.0.17 - 10/17/25
2729
-----------------

site/source/docs/tools_reference/settings_reference.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3341,3 +3341,15 @@ It's currently only available under a flag in certain browsers,
33413341
so we disable it by default to save on code size.
33423342

33433343
Default value: false
3344+
3345+
.. _cross_origin:
3346+
3347+
CROSS_ORIGIN
3348+
============
3349+
3350+
If the emscripten-generated program is hosted on separate origin then
3351+
starting new pthread worker can violate CSP rules. Enabling
3352+
CROSS_ORIGIN uses an inline worker to instead load the worker script
3353+
indirectly using `importScripts`
3354+
3355+
Default value: false

src/lib/libpthread.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,16 @@ var LibraryPThread = {
454454
worker = new Worker(new URL('{{{ pthreadWorkerScript }}}', import.meta.url), {{{ pthreadWorkerOptions }}});
455455
#else // EXPORT_ES6
456456
var pthreadMainJs = _scriptName;
457+
#if CROSS_ORIGIN && ENVIRONMENT_MAY_BE_WEB
458+
// In order to support cross origin loading of worker threads load the
459+
// worker via a tiny inline `importScripts` call. For some reason its
460+
// fine to `importScripts` across origins, in cases where new Worker
461+
// itself does not allow this.
462+
// https://github.com/emscripten-core/emscripten/issues/21937
463+
if (ENVIRONMENT_IS_WEB) {
464+
pthreadMainJs = URL.createObjectURL(new Blob([`importScripts('${_scriptName}')`], { type: 'application/javascript' }));
465+
}
466+
#endif
457467
#if expectToReceiveOnModule('mainScriptUrlOrBlob')
458468
// We can't use makeModuleReceiveWithVar here since we want to also
459469
// call URL.createObjectURL on the mainScriptUrlOrBlob.

src/settings.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2187,6 +2187,12 @@ var GROWABLE_ARRAYBUFFERS = false;
21872187
// so we disable it by default to save on code size.
21882188
var WASM_JS_TYPES = false;
21892189

2190+
// If the emscripten-generated program is hosted on separate origin then
2191+
// starting new pthread worker can violate CSP rules. Enabling
2192+
// CROSS_ORIGIN uses an inline worker to instead load the worker script
2193+
// indirectly using `importScripts`
2194+
var CROSS_ORIGIN = false;
2195+
21902196
// For renamed settings the format is:
21912197
// [OLD_NAME, NEW_NAME]
21922198
// For removed settings (which now effectively have a fixed value and can no

test/test_browser.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import unittest
1616
import zlib
1717
from functools import wraps
18-
from http.server import BaseHTTPRequestHandler, HTTPServer
18+
from http.server import BaseHTTPRequestHandler, HTTPServer, ThreadingHTTPServer, SimpleHTTPRequestHandler
1919
from pathlib import Path
2020
from urllib.request import urlopen
2121

@@ -5631,6 +5631,46 @@ def test_rollup(self):
56315631
shutil.copy('hello.wasm', 'dist/')
56325632
self.run_browser('index.html', '/report_result?exit:0')
56335633

5634+
def test_cross_origin(self):
5635+
# Verfies that the emscripten-generted JS and Wasm can be hosted on a different origin.
5636+
# This test create a second HTTP server running on port 9999 that servers files from `subdir`.
5637+
# The main html is the servers from the normal 8888 server while the JS and Wasm are hosted
5638+
# on at 9999.
5639+
os.mkdir('subdir')
5640+
create_file('subdir/foo.txt', 'hello')
5641+
self.compile_btest('hello_world.c', ['-o', 'subdir/hello.js', '-sCROSS_ORIGIN', '-sPROXY_TO_PTHREAD', '-pthread', '-sEXIT_RUNTIME'])
5642+
5643+
class MyReqestHandler(SimpleHTTPRequestHandler):
5644+
def __init__(self, *args, **kwargs):
5645+
super().__init__(*args, directory='subdir', **kwargs)
5646+
5647+
# Add COOP, COEP, CORP, and no-caching headers
5648+
def end_headers(self):
5649+
self.send_header('Accept-Ranges', 'bytes')
5650+
self.send_header('Access-Control-Allow-Origin', '*')
5651+
self.send_header('Cross-Origin-Opener-Policy', 'same-origin')
5652+
self.send_header('Cross-Origin-Embedder-Policy', 'require-corp')
5653+
self.send_header('Cross-Origin-Resource-Policy', 'cross-origin')
5654+
5655+
self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate, private, max-age=0')
5656+
self.send_header('Expires', '0')
5657+
self.send_header('Pragma', 'no-cache')
5658+
self.send_header('Vary', '*') # Safari insists on caching if this header is not present in addition to the above
5659+
5660+
return SimpleHTTPRequestHandler.end_headers(self)
5661+
5662+
create_file('test.html', '''
5663+
<script src="http://localhost:9999/hello.js"></script>
5664+
''')
5665+
5666+
server = HttpServerThread(ThreadingHTTPServer(('localhost', 9999), MyReqestHandler))
5667+
server.start()
5668+
try:
5669+
self.run_browser('test.html', '/report_result?exit:0')
5670+
finally:
5671+
server.stop()
5672+
server.join()
5673+
56345674

56355675
class emrun(RunnerCore):
56365676
def test_emrun_info(self):

0 commit comments

Comments
 (0)