Skip to content

Commit 02fe7c8

Browse files
committed
Inline ww.js file into the main output file
Similar to what we did for pthreads in emscripten-core#21701. This is win for both code size and complexity.
1 parent 279f298 commit 02fe7c8

22 files changed

+137
-176
lines changed

src/lib/libwasm_worker.js

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,6 @@
44
* SPDX-License-Identifier: MIT
55
*/
66

7-
#if WASM_WORKERS == 2
8-
// Helpers for _wasmWorkerBlobUrl used in WASM_WORKERS == 2 mode
9-
{{{
10-
const captureModuleArg = () => MODULARIZE ? '' : 'self.Module=d;';
11-
const instantiateModule = () => MODULARIZE ? `${EXPORT_NAME}(d);` : '';
12-
const instantiateWasm = () => MINIMAL_RUNTIME ? '' : 'd[`instantiateWasm`]=(i,r)=>{var n=new WebAssembly.Instance(d[`wasm`],i);return r(n,d[`wasm`]);};';
13-
}}}
14-
#endif
15-
167
#if WASM_WORKERS
178

189
#if !SHARED_MEMORY
@@ -34,14 +25,19 @@
3425
{{{
3526
const workerSupportsFutexWait = () => AUDIO_WORKLET ? "typeof AudioWorkletGlobalScope === 'undefined'" : '1';
3627
const wasmWorkerJs = `
37-
#if WASM_WORKERS == 2
38-
_wasmWorkerBlobUrl
39-
#elif MINIMAL_RUNTIME
28+
#if MINIMAL_RUNTIME
4029
Module['$wb']
4130
#else
42-
locateFile('${WASM_WORKER_FILE}')
31+
locateFile('${TARGET_JS_NAME}')
4332
#endif
4433
`;
34+
const wasmWorkerOptions = `{
35+
#if ENVIRONMENT_MAY_BE_NODE
36+
// This is the way that we signal to the node worker that it is hosting
37+
// a wasm worker.
38+
'workerData': 'em-ww',
39+
#endif
40+
}`;
4541
}}}
4642

4743
#endif // ~WASM_WORKERS
@@ -83,7 +79,7 @@ addToLibrary({
8379
#endif
8480
],
8581
$_wasmWorkerInitializeRuntime: () => {
86-
let m = Module;
82+
let m = wasmWorkerArgs;
8783
#if ASSERTIONS
8884
assert(m['sb'] % 16 == 0);
8985
assert(m['sz'] % 16 == 0);
@@ -142,20 +138,9 @@ addToLibrary({
142138
#endif
143139
},
144140

145-
#if WASM_WORKERS == 2
146-
// In WASM_WORKERS == 2 build mode, we create the Wasm Worker global scope
147-
// script from a string bundled in the main application JS file. This
148-
// simplifies the number of deployed JS files with the app, but has a downside
149-
// that the generated build output will no longer be csp-eval compliant.
150-
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_eval_expressions
151-
$_wasmWorkerBlobUrl: "URL.createObjectURL(new Blob(['onmessage=function(d){onmessage=null;d=d.data;{{{ captureModuleArg() }}}{{{ instantiateWasm() }}}importScripts(d.js);{{{ instantiateModule() }}}d.wasm=d.mem=d.js=0;}'],{type:'application/javascript'}))",
152-
#endif
153141
_emscripten_create_wasm_worker__deps: [
154142
'$_wasmWorkers', '$_wasmWorkersID',
155143
'$_wasmWorkerAppendToQueue', '$_wasmWorkerRunPostMessage',
156-
#if WASM_WORKERS == 2
157-
'$_wasmWorkerBlobUrl',
158-
#endif
159144
#if ASSERTIONS
160145
'emscripten_has_threading_support',
161146
#endif
@@ -167,7 +152,7 @@ if (ENVIRONMENT_IS_WASM_WORKER
167152
&& !ENVIRONMENT_IS_AUDIO_WORKLET
168153
#endif
169154
) {
170-
_wasmWorkers[0] = this;
155+
_wasmWorkers[0] = globalThis;
171156
addEventListener("message", _wasmWorkerAppendToQueue);
172157
}`,
173158
_emscripten_create_wasm_worker: (stackLowestAddress, stackSize) => {
@@ -184,10 +169,10 @@ if (ENVIRONMENT_IS_WASM_WORKER
184169
var p = trustedTypes.createPolicy(
185170
'emscripten#workerPolicy1', { createScriptURL: (ignored) => {{{ wasmWorkerJs }}}}
186171
);
187-
worker = _wasmWorkers[_wasmWorkersID] = new Worker(p.createScriptURL('ignored'));
172+
worker = _wasmWorkers[_wasmWorkersID] = new Worker(p.createScriptURL('ignored'), {{{ wasmWorkerOptions }}});
188173
} else
189174
#endif
190-
worker = _wasmWorkers[_wasmWorkersID] = new Worker({{{ wasmWorkerJs }}});
175+
worker = _wasmWorkers[_wasmWorkersID] = new Worker({{{ wasmWorkerJs }}}, {{{ wasmWorkerOptions }}});
191176
// Craft the Module object for the Wasm Worker scope:
192177
worker.postMessage({
193178
// Signal with a non-zero value that this Worker will be a Wasm Worker,

src/postamble_minimal.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ var wasmExports;
9595
var wasmModule;
9696
#endif
9797

98-
#if PTHREADS
98+
#if PTHREADS || WASM_WORKERS
9999
function loadModule() {
100100
assignWasmImports();
101101
#endif
@@ -255,12 +255,10 @@ WebAssembly.instantiate(Module['wasm'], imports).then((output) => {
255255
#endif // ASSERTIONS || WASM == 2
256256
);
257257

258-
#if PTHREADS
258+
#if PTHREADS || WASM_WORKERS
259259
}
260260

261-
if (!ENVIRONMENT_IS_PTHREAD) {
262-
// When running in a pthread we delay module loading untill we have
263-
// received the module via postMessage
264-
loadModule();
265-
}
261+
// When running in a background thread we delay module loading until we have
262+
// received the module via postMessage
263+
{{{ runIfMainThread('loadModule();') }}}
266264
#endif

src/preamble.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,7 @@ function exitRuntime() {
248248
#if STACK_OVERFLOW_CHECK
249249
checkStackCookie();
250250
#endif
251-
#if PTHREADS
252-
if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread.
253-
#endif
251+
{{{ runIfWorkerThread('return;') }}} // PThreads reuse the runtime from the main thread.
254252
#if !STANDALONE_WASM
255253
___funcs_on_exit(); // Native atexit() functions
256254
#endif
@@ -266,9 +264,7 @@ function postRun() {
266264
#if STACK_OVERFLOW_CHECK
267265
checkStackCookie();
268266
#endif
269-
#if PTHREADS
270-
if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread.
271-
#endif
267+
{{{ runIfWorkerThread('return;') }}} // PThreads reuse the runtime from the main thread.
272268

273269
#if expectToReceiveOnModule('postRun')
274270
if (Module['postRun']) {
@@ -823,7 +819,7 @@ async function instantiateAsync(binary, binaryFile, imports) {
823819

824820
#if !WASM_ESM_INTEGRATION
825821
function getWasmImports() {
826-
#if PTHREADS
822+
#if PTHREADS || WASM_WORKERS
827823
assignWasmImports();
828824
#endif
829825
#if ASYNCIFY && (ASSERTIONS || ASYNCIFY == 2)
@@ -1008,8 +1004,8 @@ function getWasmImports() {
10081004
}
10091005
#endif
10101006

1011-
#if PTHREADS
1012-
if (ENVIRONMENT_IS_PTHREAD) {
1007+
#if PTHREADS || WASM_WORKERS
1008+
if ({{{ ENVIRONMENT_IS_WORKER_THREAD() }}}) {
10131009
return new Promise((resolve) => {
10141010
wasmModuleReceived = (module) => {
10151011
// Instantiate from the module posted from the main thread.

src/runtime_debug.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ var runtimeDebug = true; // Switch to false at runtime to disable logging at the
193193
// Used by XXXXX_DEBUG settings to output debug messages.
194194
function dbg(...args) {
195195
if (!runtimeDebug && typeof runtimeDebug != 'undefined') return;
196-
#if ENVIRONMENT_MAY_BE_NODE && PTHREADS
196+
#if ENVIRONMENT_MAY_BE_NODE && (PTHREADS || WASM_WORKERS)
197197
// Avoid using the console for debugging in multi-threaded node applications
198198
// See https://github.com/emscripten-core/emscripten/issues/14804
199199
if (ENVIRONMENT_IS_NODE) {

src/runtime_init_memory.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212
// check for full engine support (use string 'subarray' to avoid closure compiler confusion)
1313

1414
function initMemory() {
15-
#if PTHREADS
16-
if (ENVIRONMENT_IS_PTHREAD) return;
17-
#endif // PTHREADS
15+
{{{ runIfWorkerThread('return') }}}
1816

1917
#if expectToReceiveOnModule('wasmMemory')
2018
if (Module['wasmMemory']) {

src/runtime_pthread.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ var sharedModules = {};
2121
#endif
2222

2323
if (ENVIRONMENT_IS_PTHREAD) {
24-
#if !MINIMAL_RUNTIME
25-
var wasmModuleReceived;
26-
#endif
27-
2824
#if ENVIRONMENT_MAY_BE_NODE
2925
// Node.js support
3026
if (ENVIRONMENT_IS_NODE) {

src/runtime_shared.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,18 @@
2121
#include "runtime_asan.js"
2222
#endif
2323

24+
#if !MINIMAL_RUNTIME && (PTHREADS || WASM_WORKERS)
25+
var wasmModuleReceived;
26+
#endif
27+
2428
#if PTHREADS
2529
#include "runtime_pthread.js"
2630
#endif
2731

32+
#if WASM_WORKERS
33+
#include "wasm_worker.js"
34+
#endif
35+
2836
#if LOAD_SOURCE_MAP
2937
var wasmSourceMap;
3038
#include "source_map_support.js"

src/settings.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,13 +1637,9 @@ var USE_SQLITE3 = false;
16371637
// [compile+link] - affects user code at compile and system libraries at link.
16381638
var SHARED_MEMORY = false;
16391639

1640-
// If 1, enables support for Wasm Workers. Wasm Workers enable applications
1640+
// Enables support for Wasm Workers. Wasm Workers enable applications
16411641
// to create threads using a lightweight web-specific API that builds on top
1642-
// of Wasm SharedArrayBuffer + Atomics API. When enabled, a new build output
1643-
// file a.ww.js will be generated to bootstrap the Wasm Worker JS contexts.
1644-
// If 2, enables support for Wasm Workers, but without using a separate a.ww.js
1645-
// file on the side. This can simplify deployment of builds, but will have a
1646-
// downside that the generated build will no longer be csp-eval compliant.
1642+
// of Wasm SharedArrayBuffer + Atomics API.
16471643
// [compile+link] - affects user code at compile and system libraries at link.
16481644
var WASM_WORKERS = 0;
16491645

src/settings_internal.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,6 @@ var USER_EXPORTS = [];
134134
// name of the file containing wasm binary, if relevant
135135
var WASM_BINARY_FILE = '';
136136

137-
// name of the file containing the Wasm Worker *.ww.js, if relevant
138-
var WASM_WORKER_FILE = '';
139-
140137
// name of the file containing the Audio Worklet *.aw.js, if relevant
141138
var AUDIO_WORKLET_FILE = '';
142139

src/shell.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ if (ENVIRONMENT_IS_PTHREAD) {
102102
#endif
103103
#endif
104104

105+
#if WASM_WORKERS
106+
// The way we signal to a worker that it is hosting a pthread is to construct
107+
// it with a specific name.
108+
var ENVIRONMENT_IS_WASM_WORKER = ENVIRONMENT_IS_WORKER && self.name?.startsWith('em-ww');
109+
#endif
110+
105111
#if ENVIRONMENT_MAY_BE_NODE
106112
if (ENVIRONMENT_IS_NODE) {
107113
#if EXPORT_ES6
@@ -121,14 +127,13 @@ if (ENVIRONMENT_IS_NODE) {
121127
// is hosting a pthread.
122128
ENVIRONMENT_IS_PTHREAD = ENVIRONMENT_IS_WORKER && worker_threads['workerData'] == 'em-pthread'
123129
#endif // PTHREADS
130+
#if WASM_WORKERS
131+
ENVIRONMENT_IS_WASM_WORKER = ENVIRONMENT_IS_WORKER && worker_threads['workerData'] == 'em-ww'
132+
#endif
124133
#endif // PTHREADS || WASM_WORKERS
125134
}
126135
#endif // ENVIRONMENT_MAY_BE_NODE
127136

128-
#if WASM_WORKERS
129-
var ENVIRONMENT_IS_WASM_WORKER = !!Module['$ww'];
130-
#endif
131-
132137
// --pre-jses are emitted after the Module integration code, so that they can
133138
// refer to Module (if they choose; they can also define Module)
134139
{{{ preJS() }}}

src/wasm_worker.js

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1-
// N.B. The contents of this file are duplicated in src/library_wasm_worker.js
2-
// in variable "_wasmWorkerBlobUrl" (where the contents are pre-minified) If
3-
// doing any changes to this file, be sure to update the contents there too.
4-
5-
'use strict';
1+
if (ENVIRONMENT_IS_WASM_WORKER) {
62

73
#if ENVIRONMENT_MAY_BE_NODE
84
// Node.js support
9-
var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string' && process.type != 'renderer';
105
if (ENVIRONMENT_IS_NODE) {
116
// Create as web-worker-like an environment as we can.
127

@@ -28,52 +23,40 @@ if (ENVIRONMENT_IS_NODE) {
2823
return f;
2924
}
3025

31-
var fs = require('fs');
32-
var vm = require('vm');
33-
34-
Object.assign(global, {
26+
Object.assign(globalThis, {
3527
self: global,
36-
require,
37-
#if !EXPORT_ES6
38-
// `vm.runInThisContext` global scope lacks `__filename` and `__dirname`
39-
__filename,
40-
__dirname,
41-
#endif
42-
Worker: nodeWorkerThreads.Worker,
43-
importScripts: (f) => vm.runInThisContext(fs.readFileSync(f, 'utf8'), {filename: f}),
4428
postMessage: (msg) => parentPort.postMessage(msg),
45-
performance: global.performance || { now: Date.now },
4629
addEventListener: (name, handler) => parentPort.on(name, wrapMsgHandler(handler)),
4730
removeEventListener: (name, handler) => parentPort.off(name, wrapMsgHandler(handler)),
4831
});
4932
}
5033
#endif // ENVIRONMENT_MAY_BE_NODE
5134

35+
var wasmWorkerArgs;
36+
5237
{{{ implicitSelf() }}}onmessage = function(d) {
5338
// The first message sent to the Worker is always the bootstrap message.
5439
// Drop this message listener, it served its purpose of bootstrapping
5540
// the Wasm Module load, and is no longer needed. Let user code register
5641
// any desired message handlers from now on.
5742
{{{ implicitSelf() }}}onmessage = null;
58-
d = d.data;
59-
#if !MODULARIZE
60-
self.{{{ EXPORT_NAME }}} = d;
61-
#endif
62-
#if !MINIMAL_RUNTIME
63-
d['instantiateWasm'] = (info, receiveInstance) => { var instance = new WebAssembly.Instance(d['wasm'], info); return receiveInstance(instance, d['wasm']); }
43+
#if RUNTIME_DEBUG
44+
dbg('wasm worker initial onmessage');
6445
#endif
65-
#if TRUSTED_TYPES
66-
// Use Trusted Types compatible wrappers.
67-
if (typeof trustedTypes != 'undefined' && trustedTypes.createPolicy) {
68-
var p = trustedTypes.createPolicy('emscripten#scriptPolicy1', { createScriptURL: (ignored) => d.js });
69-
importScripts(p.createScriptURL('ignored'));
70-
} else
71-
#endif
72-
importScripts(d.js);
46+
d = d.data;
7347
#if MODULARIZE
7448
{{{ EXPORT_NAME }}}(d);
49+
#else
50+
wasmWorkerArgs = d;
51+
wasmMemory = d['wasmMemory'];
52+
updateMemoryViews();
53+
#endif
54+
#if !MINIMAL_RUNTIME
55+
wasmModuleReceived(d['wasm']);
7556
#endif
7657
// Drop now unneeded references to from the Module object in this Worker,
7758
// these are not needed anymore.
78-
d.wasm = d.mem = d.js = 0;
59+
d.wasm = d.mem = 0;
60+
}
61+
7962
}

0 commit comments

Comments
 (0)