Skip to content

Commit d5fba03

Browse files
authored
Fix -sPROXY_TO_WORKER + -sSINGLE_FILE + node (#22610)
The proxyClient needs to jump through a few more hoops here to load the embedded generated JS file which is encoded as a data URL. This change also fixes the mime type used when we embed JS as a data URL.
1 parent c104419 commit d5fba03

File tree

4 files changed

+41
-10
lines changed

4 files changed

+41
-10
lines changed

src/proxyClient.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,23 @@
1818
#if ENVIRONMENT_MAY_BE_NODE
1919
var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string';
2020
if (ENVIRONMENT_IS_NODE) {
21-
global.Worker = require('worker_threads').Worker;
21+
var NodeWorker = require('worker_threads').Worker;
22+
global.Worker = function(url, options) {
23+
// Special handling for `data:` URL argument, to match the behaviour
24+
// of the Web API.
25+
if (typeof url == 'string' && url.startsWith('data:')) {
26+
#if EXPORT_ES6
27+
// worker_threads always assume data URLs are ES6 modules
28+
url = new URL(url);
29+
#else
30+
// For class modules we decode the data URL and use `eval: true`.
31+
url = Buffer.from(url.split(",")[1], 'base64').toString();
32+
options ||= {}
33+
options.eval = true;
34+
#endif
35+
}
36+
return new NodeWorker(url, options);
37+
}
2238
var Module = Module || {}
2339
} else
2440
#endif

src/shell.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,12 @@ if (ENVIRONMENT_IS_NODE) {
136136
// TODO: Swap all `require()`'s with `import()`'s?
137137
#if EXPORT_ES6 && ENVIRONMENT_MAY_BE_WEB
138138
const { createRequire } = await import('module');
139+
let dirname = import.meta.url;
140+
if (dirname.startsWith("data:")) {
141+
dirname = '/';
142+
}
139143
/** @suppress{duplicate} */
140-
var require = createRequire(import.meta.url);
144+
var require = createRequire(dirname);
141145
#endif
142146

143147
#if PTHREADS || WASM_WORKERS
@@ -235,7 +239,9 @@ if (ENVIRONMENT_IS_NODE) {
235239
// EXPORT_ES6 + ENVIRONMENT_IS_NODE always requires use of import.meta.url,
236240
// since there's no way getting the current absolute path of the module when
237241
// support for that is not available.
238-
scriptDirectory = nodePath.dirname(require('url').fileURLToPath(import.meta.url)) + '/';
242+
if (!import.meta.url.startsWith('data:')) {
243+
scriptDirectory = nodePath.dirname(require('url').fileURLToPath(import.meta.url)) + '/';
244+
}
239245
#else
240246
scriptDirectory = __dirname + '/';
241247
#endif

test/test_other.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14722,8 +14722,13 @@ def test_standalone_whole_archive(self):
1472214722
self.emcc_args += ['-sSTANDALONE_WASM', '-pthread', '-Wl,--whole-archive', '-lbulkmemory', '-lstandalonewasm', '-Wl,--no-whole-archive']
1472314723
self.do_runf('hello_world.c')
1472414724

14725-
def test_proxy_to_worker(self):
14726-
self.do_runf('hello_world.c', emcc_args=['--proxy-to-worker'])
14725+
@parameterized({
14726+
'': ([],),
14727+
'_single_file': (['-sSINGLE_FILE'],),
14728+
'_single_file_es6': (['-sSINGLE_FILE', '-sEXPORT_ES6', '--extern-post-js', test_file('modularize_post_js.js')],),
14729+
})
14730+
def test_proxy_to_worker(self, args):
14731+
self.do_runf('hello_world.c', emcc_args=['--proxy-to-worker'] + args)
1472714732

1472814733
@also_with_standalone_wasm()
1472914734
def test_console_out(self):

tools/link.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2501,7 +2501,7 @@ def generate_traditional_runtime_html(target, options, js_target, target_basenam
25012501
var filename = '%s';
25022502
if ((',' + window.location.search.substr(1) + ',').indexOf(',noProxy,') < 0) {
25032503
console.log('running code in a web worker');
2504-
''' % get_subresource_location(proxy_worker_filename)) + worker_js + '''
2504+
''' % get_subresource_location_js(proxy_worker_filename)) + worker_js + '''
25052505
} else {
25062506
console.log('running code on the main thread');
25072507
var fileBytes = tryParseAsDataURI(filename);
@@ -2569,7 +2569,7 @@ def generate_traditional_runtime_html(target, options, js_target, target_basenam
25692569
// Current browser supports Wasm, proceed with loading the main JS runtime.
25702570
loadMainJs();
25712571
}
2572-
''' % (script.inline, get_subresource_location(wasm_target) + '.js')
2572+
''' % (script.inline, get_subresource_location_js(wasm_target + '.js'))
25732573

25742574
shell = do_replace(shell, '{{{ SCRIPT }}}', script.replacement())
25752575
shell = shell.replace('{{{ SHELL_CSS }}}', utils.read_file(utils.path_from_root('src/shell.css')))
@@ -2645,7 +2645,7 @@ def generate_html(target, options, js_target, target_basename, wasm_target):
26452645
def generate_worker_js(target, js_target, target_basename):
26462646
if settings.SINGLE_FILE:
26472647
# compiler output is embedded as base64 data URL
2648-
proxy_worker_filename = get_subresource_location(js_target)
2648+
proxy_worker_filename = get_subresource_location_js(js_target)
26492649
else:
26502650
# compiler output goes in .worker.js file
26512651
move_file(js_target, shared.replace_suffix(js_target, get_worker_js_suffix()))
@@ -2958,13 +2958,17 @@ def move_file(src, dst):
29582958

29592959

29602960
# Returns the subresource location for run-time access
2961-
def get_subresource_location(path):
2961+
def get_subresource_location(path, mimetype='application/octet-stream'):
29622962
if settings.SINGLE_FILE:
2963-
return 'data:application/octet-stream;base64,' + base64_encode(path)
2963+
return f'data:{mimetype};base64,{base64_encode(path)}'
29642964
else:
29652965
return os.path.basename(path)
29662966

29672967

2968+
def get_subresource_location_js(path):
2969+
return get_subresource_location(path, 'text/javascript')
2970+
2971+
29682972
@ToolchainProfiler.profile()
29692973
def package_files(options, target):
29702974
rtn = []

0 commit comments

Comments
 (0)