Skip to content

Commit 2cfc714

Browse files
committed
Fix the WASM Worker cannot start in node.js environment
`emscripten_malloc_wasm_worker` and `emscripten_create_wasm_worker` functions adapted to the nodejs environment and modified the core related tests.
1 parent 01c4612 commit 2cfc714

11 files changed

+99
-33
lines changed

emscripten.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,7 @@ def create_pointer_conversion_wrappers(metadata):
891891
'__main_argc_argv': '__PP',
892892
'emscripten_stack_set_limits': '_pp',
893893
'__set_stack_limits': '_pp',
894+
'__set_thread_state': '_p___',
894895
'__cxa_can_catch': '_ppp',
895896
'__cxa_increment_exception_refcount': '_p',
896897
'__cxa_decrement_exception_refcount': '_p',

src/library_wasm_worker.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,12 @@ addToLibrary({
4747
$_wasmWorkerRunPostMessage: (e) => {
4848
// '_wsc' is short for 'wasm call', trying to use an identifier name that
4949
// will never conflict with user code
50-
let data = e.data, wasmCall = data['_wsc'];
50+
#if ENVIRONMENT_MAY_BE_NODE
51+
let data = ENVIRONMENT_IS_NODE ? e : e.data;
52+
#else
53+
let data = e.data;
54+
#endif
55+
let wasmCall = data['_wsc'];
5156
wasmCall && getWasmTableEntry(wasmCall)(...data['x']);
5257
},
5358

@@ -155,6 +160,12 @@ if (ENVIRONMENT_IS_WASM_WORKER) {
155160
#endif
156161
'sb': stackLowestAddress, // sb = stack bottom (lowest stack address, SP points at this when stack is full)
157162
'sz': stackSize, // sz = stack size
163+
#if USE_OFFSET_CONVERTER
164+
'wasmOffsetData': wasmOffsetConverter,
165+
#endif
166+
#if LOAD_SOURCE_MAP
167+
'wasmSourceMapData': wasmSourceMap,
168+
#endif
158169
});
159170
worker.onmessage = _wasmWorkerRunPostMessage;
160171
return _wasmWorkersID++;

src/parseTools.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,18 @@ function runIfMainThread(text) {
734734
}
735735
}
736736

737+
function runIfWorkerThread(text) {
738+
if (WASM_WORKERS && PTHREADS) {
739+
return 'if (ENVIRONMENT_IS_WASM_WORKER || ENVIRONMENT_IS_PTHREAD) { ' + text + ' }';
740+
} else if (WASM_WORKERS) {
741+
return 'if (ENVIRONMENT_IS_WASM_WORKER) { ' + text + ' }';
742+
} else if (PTHREADS) {
743+
return 'if (ENVIRONMENT_IS_PTHREAD) { ' + text + ' }';
744+
} else {
745+
return '';
746+
}
747+
}
748+
737749
// Legacy name for runIfMainThread.
738750
// TODO(remove).
739751
const runOnMainThread = runIfMainThread;

src/preamble.js

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,6 @@ function initRuntime() {
226226
#endif
227227
runtimeInitialized = true;
228228

229-
#if WASM_WORKERS
230-
if (ENVIRONMENT_IS_WASM_WORKER) return _wasmWorkerInitializeRuntime();
231-
#endif
232-
233229
#if PTHREADS
234230
if (ENVIRONMENT_IS_PTHREAD) return;
235231
#endif
@@ -246,6 +242,13 @@ function initRuntime() {
246242
callRuntimeCallbacks(__RELOC_FUNCS__);
247243
#endif
248244
<<< ATINITS >>>
245+
246+
#if WASM_WORKERS
247+
if (ENVIRONMENT_IS_WASM_WORKER) {
248+
return _wasmWorkerInitializeRuntime();
249+
}
250+
#endif
251+
249252
callRuntimeCallbacks(__ATINIT__);
250253
}
251254

@@ -792,7 +795,7 @@ function instantiateSync(file, info) {
792795
}
793796
#endif
794797

795-
#if PTHREADS && (LOAD_SOURCE_MAP || USE_OFFSET_CONVERTER)
798+
#if (PTHREADS || WASM_WORKERS) && (LOAD_SOURCE_MAP || USE_OFFSET_CONVERTER)
796799
// When using postMessage to send an object, it is processed by the structured
797800
// clone algorithm. The prototype, and hence methods, on that object is then
798801
// lost. This function adds back the lost prototype. This does not work with
@@ -1090,22 +1093,18 @@ function createWasm() {
10901093
// path.
10911094
if (Module['instantiateWasm']) {
10921095

1093-
#if USE_OFFSET_CONVERTER && PTHREADS
1094-
if (ENVIRONMENT_IS_PTHREAD) {
1096+
#if USE_OFFSET_CONVERTER
10951097
#if ASSERTIONS
1096-
assert(Module['wasmOffsetData'], 'wasmOffsetData not found on Module object');
1098+
{{{ runIfWorkerThread("assert(Module['wasmOffsetData'], 'wasmOffsetData not found on Module object');") }}}
10971099
#endif
1098-
wasmOffsetConverter = resetPrototype(WasmOffsetConverter, Module['wasmOffsetData']);
1099-
}
1100+
{{{ runIfWorkerThread("wasmOffsetConverter = resetPrototype(WasmOffsetConverter, Module['wasmOffsetData']);") }}}
11001101
#endif
11011102

1102-
#if LOAD_SOURCE_MAP && PTHREADS
1103-
if (ENVIRONMENT_IS_PTHREAD) {
1103+
#if LOAD_SOURCE_MAP
11041104
#if ASSERTIONS
1105-
assert(Module['wasmSourceMapData'], 'wasmSourceMapData not found on Module object');
1105+
{{{ runIfWorkerThread("assert(Module['wasmSourceMapData'], 'wasmSourceMapData not found on Module object');") }}}
11061106
#endif
1107-
wasmSourceMap = resetPrototype(WasmSourceMap, Module['wasmSourceMapData']);
1108-
}
1107+
{{{ runIfWorkerThread("wasmSourceMap = resetPrototype(WasmSourceMap, Module['wasmSourceMapData']);") }}}
11091108
#endif
11101109

11111110
try {

src/wasm_worker.js

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,51 @@
11
// N.B. The contents of this file are duplicated in src/library_wasm_worker.js
22
// in variable "_wasmWorkerBlobUrl" (where the contents are pre-minified) If
33
// doing any changes to this file, be sure to update the contents there too.
4-
onmessage = function(d) {
4+
5+
'use strict';
6+
7+
#if ENVIRONMENT_MAY_BE_NODE
8+
// Node.js support
9+
var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string';
10+
if (ENVIRONMENT_IS_NODE) {
11+
// Create as web-worker-like an environment as we can.
12+
13+
var nodeWorkerThreads = require('worker_threads');
14+
15+
var parentPort = nodeWorkerThreads.parentPort;
16+
17+
parentPort.on('message', (data) => typeof onmessage === "function" && onmessage({ data: data }));
18+
19+
var fs = require('fs');
20+
21+
Object.assign(global, {
22+
self: global,
23+
require,
24+
location: {
25+
href: __filename
26+
},
27+
Worker: nodeWorkerThreads.Worker,
28+
importScripts: (f) => (0, eval)(fs.readFileSync(f, 'utf8') + '//# sourceURL=' + f),
29+
postMessage: (msg) => parentPort.postMessage(msg),
30+
performance: global.performance || { now: Date.now },
31+
addEventListener: (name, handler) => parentPort.on(name, handler),
32+
removeEventListener: (name, handler) => parentPort.off(name, handler),
33+
});
34+
}
35+
#endif // ENVIRONMENT_MAY_BE_NODE
36+
37+
self.onmessage = function(d) {
538
// The first message sent to the Worker is always the bootstrap message.
639
// Drop this message listener, it served its purpose of bootstrapping
740
// the Wasm Module load, and is no longer needed. Let user code register
841
// any desired message handlers from now on.
9-
onmessage = null;
42+
self.onmessage = null;
1043
d = d.data;
1144
#if !MODULARIZE
1245
self.{{{ EXPORT_NAME }}} = d;
1346
#endif
1447
#if !MINIMAL_RUNTIME
15-
d['instantiateWasm'] = (info, receiveInstance) => { var instance = new WebAssembly.Instance(d['wasm'], info); receiveInstance(instance, d['wasm']); return instance.exports; }
48+
d['instantiateWasm'] = (info, receiveInstance) => { var instance = new WebAssembly.Instance(d['wasm'], info); return receiveInstance(instance, d['wasm']); }
1649
#endif
1750
importScripts(d.js);
1851
#if MODULARIZE

test/code_size/math_wasm.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
"a.html.gz": 431,
44
"a.js": 111,
55
"a.js.gz": 127,
6-
"a.wasm": 2727,
7-
"a.wasm.gz": 1673,
8-
"total": 3511,
9-
"total_gz": 2231
6+
"a.wasm": 2728,
7+
"a.wasm.gz": 1672,
8+
"total": 3512,
9+
"total_gz": 2230
1010
}
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"a.html": 12774,
3-
"a.html.gz": 6965,
4-
"total": 12774,
5-
"total_gz": 6965
2+
"a.html": 12766,
3+
"a.html.gz": 6930,
4+
"total": 12766,
5+
"total_gz": 6930
66
}
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"a.html": 17351,
3-
"a.html.gz": 7549,
4-
"total": 17351,
5-
"total_gz": 7549
2+
"a.html": 17344,
3+
"a.html.gz": 7545,
4+
"total": 17344,
5+
"total_gz": 7545
66
}

test/test_core.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9793,16 +9793,24 @@ def test_emscripten_async_load_script(self):
97939793
self.run_process([FILE_PACKAGER, 'test.data', '--preload', 'file1.txt', 'file2.txt', '--from-emcc', '--js-output=script2.js'])
97949794
self.do_runf(test_file('test_emscripten_async_load_script.c'), emcc_args=['-sFORCE_FILESYSTEM'])
97959795

9796+
def prep_wasm_worker_in_node(self):
9797+
# Auto exit after 3 seconds in Nodejs environment to get WASM Worker stdout
9798+
# TODO: remove this is if/when wasm worker tests exit cleanly under node
9799+
self.add_pre_run("setTimeout(()=>process.exit(), 3000);")
9800+
97969801
@node_pthreads
97979802
def test_wasm_worker_hello(self):
9798-
self.do_runf(test_file('wasm_worker/hello_wasm_worker.c'), emcc_args=['-sWASM_WORKERS'])
9803+
self.prep_wasm_worker_in_node()
9804+
self.do_run_in_out_file_test(test_file('wasm_worker/hello_wasm_worker.c'), emcc_args=['-sWASM_WORKERS'])
97999805

98009806
@node_pthreads
98019807
def test_wasm_worker_malloc(self):
9802-
self.do_runf(test_file('wasm_worker/malloc_wasm_worker.c'), emcc_args=['-sWASM_WORKERS'])
9808+
self.prep_wasm_worker_in_node()
9809+
self.do_run_in_out_file_test(test_file('wasm_worker/malloc_wasm_worker.c'), emcc_args=['-sWASM_WORKERS'])
98039810

98049811
@node_pthreads
98059812
def test_wasm_worker_wait_async(self):
9813+
self.prep_wasm_worker_in_node()
98069814
self.do_runf(test_file('wasm_worker/wait_async.c'), emcc_args=['-sWASM_WORKERS'])
98079815

98089816

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello from wasm worker!
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello from wasm worker!

0 commit comments

Comments
 (0)