Skip to content

Commit a5cfb78

Browse files
committed
[esm-integration] Allow for module argument processing
This change delays module argument processing until the init function is run. This means that at least some INCOMING_MODULE_JS_API properties can be supported with ESM integration.
1 parent 7787d7a commit a5cfb78

File tree

77 files changed

+180
-147
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+180
-147
lines changed

src/jsifier.mjs

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import assert from 'node:assert';
1111
import * as fs from 'node:fs/promises';
1212
import {
13+
ATPREINITS,
1314
ATEXITS,
1415
ATINITS,
1516
ATPOSTCTORS,
@@ -873,6 +874,7 @@ var proxiedFunctionTable = [
873874
asyncFuncs,
874875
libraryDefinitions: LibraryManager.libraryDefinitions,
875876
ATPRERUNS: ATPRERUNS.join('\n'),
877+
ATPREINITS: ATPREINITS.join('\n'),
876878
ATINITS: ATINITS.join('\n'),
877879
ATPOSTCTORS: ATPOSTCTORS.join('\n'),
878880
ATMAINS: ATMAINS.join('\n'),

src/lib/libcore.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -2283,7 +2283,8 @@ addToLibrary({
22832283
$wasmTable: undefined,
22842284
#endif
22852285

2286-
$noExitRuntime: "{{{ makeModuleReceiveExpr('noExitRuntime', !EXIT_RUNTIME) }}}",
2286+
$noExitRuntime__postset: () => addAtPreInit(makeModuleReceive('noExitRuntime')),
2287+
$noExitRuntime: {{{ !EXIT_RUNTIME }}},
22872288

22882289
// The following addOn<X> functions are for adding runtime callbacks at
22892290
// various executions points. Each addOn<X> function has a corresponding

src/lib/libfs_shared.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
*/
66

77
addToLibrary({
8-
$preloadPlugins: "{{{ makeModuleReceiveExpr('preloadPlugins', '[]') }}}",
8+
$preloadPlugins__postset: () => addAtPreInit(makeModuleReceive('preloadPlugins')),
9+
$preloadPlugins: [],
910

1011
#if !MINIMAL_RUNTIME
1112
// Tries to handle an input byteArray using preload plugins. Returns true if

src/modules.mjs

+7-13
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
mergeInto,
2323
localFile,
2424
} from './utility.mjs';
25-
import {preprocess, processMacros} from './parseTools.mjs';
25+
import {addAtPreInit, preprocess, processMacros} from './parseTools.mjs';
2626

2727
// Various namespace-like modules
2828

@@ -401,7 +401,6 @@ function addMissingLibraryStubs(unusedLibSymbols) {
401401
rtn += ` '${sym}',\n`;
402402
}
403403
rtn += '];\n';
404-
rtn += 'missingLibrarySymbols.forEach(missingLibrarySymbol)\n';
405404
return rtn;
406405
}
407406

@@ -515,9 +514,7 @@ function exportRuntime() {
515514
// in ASSERTIONS mode we show a useful error if it is used without being
516515
// exported. See `unexportedRuntimeSymbol` in runtime_debug.js.
517516
const unusedLibSymbols = getUnusedLibrarySymbols();
518-
if (unusedLibSymbols.size) {
519-
results.push(addMissingLibraryStubs(unusedLibSymbols));
520-
}
517+
results.push(addMissingLibraryStubs(unusedLibSymbols));
521518

522519
const unexported = [];
523520
for (const name of runtimeElements) {
@@ -526,15 +523,12 @@ function exportRuntime() {
526523
}
527524
}
528525

529-
if (unexported.length || unusedLibSymbols.size) {
530-
let unexportedStubs = 'var unexportedSymbols = [\n';
531-
for (const sym of unexported) {
532-
unexportedStubs += ` '${sym}',\n`;
533-
}
534-
unexportedStubs += '];\n';
535-
unexportedStubs += 'unexportedSymbols.forEach(unexportedRuntimeSymbol);\n';
536-
results.push(unexportedStubs);
526+
let unexportedStubs = 'var unexportedSymbols = [\n';
527+
for (const sym of unexported) {
528+
unexportedStubs += ` '${sym}',\n`;
537529
}
530+
unexportedStubs += '];\n';
531+
results.push(unexportedStubs);
538532
}
539533

540534
return results.join('\n') + '\n';

src/parseTools.mjs

+17-13
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,14 @@ function makeEval(code) {
720720
return ret;
721721
}
722722

723+
// Add code that runs before the wasm modules is loaded. This is the first
724+
// point at which the global `Module` object is guaranteed to exist. This hook
725+
// is mostly used to read incoming `Module` properties.
726+
export const ATPREINITS = [];
727+
export function addAtPreInit(code) {
728+
ATPREINITS.push(code);
729+
}
730+
723731
// Add code to run soon after the Wasm module has been loaded. This is the first
724732
// injection point before all the other addAt<X> functions below. The code will
725733
// be executed after the runtime `onPreRuns` callbacks.
@@ -888,7 +896,7 @@ function makeModuleReceive(localName, moduleName) {
888896
if (expectToReceiveOnModule(moduleName)) {
889897
// Usually the local we use is the same as the Module property name,
890898
// but sometimes they must differ.
891-
ret = `\nif (Module['${moduleName}']) ${localName} = Module['${moduleName}'];`;
899+
ret = `if (Module['${moduleName}']) ${localName} = Module['${moduleName}'];`;
892900
}
893901
ret += makeRemovedModuleAPIAssert(moduleName, localName);
894902
return ret;
@@ -907,20 +915,15 @@ function makeModuleReceiveWithVar(localName, moduleName, defaultValue, noAssert)
907915
moduleName ||= localName;
908916
checkReceiving(moduleName);
909917
let ret = `var ${localName}`;
910-
if (!expectToReceiveOnModule(moduleName)) {
911-
if (defaultValue) {
912-
ret += ` = ${defaultValue}`;
913-
}
914-
ret += ';';
915-
} else {
916-
if (defaultValue) {
917-
ret += ` = Module['${moduleName}'] || ${defaultValue};`;
918-
} else {
919-
ret += ` = Module['${moduleName}'];`;
920-
}
918+
if (defaultValue) {
919+
ret += ` = ${defaultValue}`;
920+
}
921+
ret += ';';
922+
if (expectToReceiveOnModule(moduleName)) {
923+
addAtPreInit(`if (Module['${moduleName}']) ${localName} = Module['${moduleName}'];`);
921924
}
922925
if (!noAssert) {
923-
ret += makeRemovedModuleAPIAssert(moduleName, localName);
926+
addAtPreInit(makeRemovedModuleAPIAssert(moduleName, localName));
924927
}
925928
return ret;
926929
}
@@ -1129,6 +1132,7 @@ addToCompileTimeContext({
11291132
ENVIRONMENT_IS_WORKER_THREAD,
11301133
addAtExit,
11311134
addAtPreRun,
1135+
addAtPreInit,
11321136
addAtInit,
11331137
addAtPostCtor,
11341138
addAtPreMain,

src/postamble.js

+4-15
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ function run() {
199199
#endif
200200

201201
#if HAS_MAIN
202-
{{{ makeModuleReceiveWithVar('noInitialRun', undefined, !INVOKE_RUN) }}}
202+
var noInitialRun = {{{ makeModuleReceiveExpr('noInitialRun', !INVOKE_RUN) }}};
203203
#if MAIN_READS_PARAMS
204204
if (!noInitialRun) callMain(args);
205205
#else
@@ -287,26 +287,15 @@ function checkUnflushedContent() {
287287
#endif // EXIT_RUNTIME
288288
#endif // ASSERTIONS
289289

290-
#if expectToReceiveOnModule('preInit')
291-
if (Module['preInit']) {
292-
if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
293-
while (Module['preInit'].length > 0) {
294-
Module['preInit'].shift()();
295-
}
296-
}
297-
#if ASSERTIONS
298-
consumedModuleProp('preInit');
299-
#endif
300-
#endif
301-
302-
303290
#if WASM_ESM_INTEGRATION
304291
export default function init(moduleArg = {}) {
305-
// TODO(sbc): moduleArg processing
292+
Module = moduleArg;
306293
updateMemoryViews();
294+
processModuleArgs();
307295
run();
308296
}
309297
#else
298+
processModuleArgs();
310299
run();
311300
#endif
312301

src/postamble_minimal.js

+2
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ WebAssembly.instantiateStreaming(fetch('{{{ TARGET_BASENAME }}}.wasm'), imports)
136136
if (!Module['wasm']) throw 'Must load WebAssembly Module in to variable Module.wasm before adding compiled output .js script to the DOM';
137137
#endif
138138

139+
<<< ATPREINITS >>>
140+
139141
WebAssembly.instantiate(Module['wasm'], imports).then((output) => {
140142
#endif
141143

src/preamble.js

+56-6
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,6 @@ assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' &
158158
#if IMPORTED_MEMORY
159159
// In non-standalone/normal mode, we create the memory here.
160160
#include "runtime_init_memory.js"
161-
#elif ASSERTIONS
162-
// If memory is defined in wasm, the user can't provide it, or set INITIAL_MEMORY
163-
assert(!Module['wasmMemory'], 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally');
164-
assert(!Module['INITIAL_MEMORY'], 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically');
165161
#endif // !IMPORTED_MEMORY && ASSERTIONS
166162

167163
#if RELOCATABLE
@@ -461,8 +457,8 @@ var FS = {
461457

462458
ErrnoError() { FS.error() },
463459
};
464-
Module['FS_createDataFile'] = FS.createDataFile;
465-
Module['FS_createPreloadedFile'] = FS.createPreloadedFile;
460+
//Module['FS_createDataFile'] = FS.createDataFile;
461+
//Module['FS_createPreloadedFile'] = FS.createPreloadedFile;
466462
#endif
467463

468464
#if ASSERTIONS
@@ -1086,3 +1082,57 @@ function getCompilerSetting(name) {
10861082
// dynamic linker as symbols are loaded.
10871083
var asyncifyStubs = {};
10881084
#endif
1085+
1086+
function processModuleArgs() {
1087+
#if ASSERTIONS
1088+
checkIncomingModuleAPI();
1089+
#endif
1090+
1091+
<<< ATPREINITS >>>
1092+
1093+
#if expectToReceiveOnModule('preInit')
1094+
if (Module['preInit']) {
1095+
if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
1096+
while (Module['preInit'].length > 0) {
1097+
Module['preInit'].shift()();
1098+
}
1099+
}
1100+
#if ASSERTIONS
1101+
consumedModuleProp('preInit');
1102+
#endif
1103+
#endif
1104+
1105+
{{{ makeModuleReceive('arguments_', 'arguments') }}}
1106+
{{{ makeModuleReceive('thisProgram') }}}
1107+
1108+
1109+
#if ASSERTIONS
1110+
// Assertions on removed incoming Module JS APIs.
1111+
assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead');
1112+
assert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead');
1113+
assert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead');
1114+
assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead');
1115+
assert(typeof Module['read'] == 'undefined', 'Module.read option was removed');
1116+
assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)');
1117+
assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)');
1118+
assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)');
1119+
assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY');
1120+
assert(typeof Module['ENVIRONMENT'] == 'undefined', 'Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)');
1121+
assert(typeof Module['STACK_SIZE'] == 'undefined', 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time')
1122+
#if !IMPORTED_MEMORY
1123+
// If memory is defined in wasm, the user can't provide it, or set INITIAL_MEMORY
1124+
assert(typeof Module['wasmMemory'] == 'undefined', 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally');
1125+
assert(typeof Module['INITIAL_MEMORY'] == 'undefined', 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically');
1126+
#endif
1127+
{{{ makeRemovedModuleAPIAssert('asm', 'wasmExports', false) }}}
1128+
{{{ makeRemovedModuleAPIAssert('readAsync') }}}
1129+
{{{ makeRemovedModuleAPIAssert('readBinary') }}}
1130+
{{{ makeRemovedModuleAPIAssert('setWindowTitle') }}}
1131+
1132+
#if !EXPORT_ALL
1133+
unexportedSymbols.forEach(unexportedRuntimeSymbol);
1134+
missingLibrarySymbols.forEach(missingLibrarySymbol);
1135+
#endif
1136+
1137+
#endif // ASSERTIONS
1138+
}

src/shell.js

+3-29
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
// before the code. Then that object will be used in the code, and you
2222
// can continue to use Module afterwards as well.
2323
#if WASM_ESM_INTEGRATION
24-
var Module = {};
24+
var Module;
2525
#elif MODULARIZE
2626
var Module = moduleArg;
2727
#elif USE_CLOSURE_COMPILER
@@ -403,35 +403,7 @@ if (ENVIRONMENT_IS_NODE) {
403403
#endif
404404

405405
#if ASSERTIONS
406-
checkIncomingModuleAPI();
407-
#endif
408406

409-
// Emit code to handle expected values on the Module object. This applies Module.x
410-
// to the proper local x. This has two benefits: first, we only emit it if it is
411-
// expected to arrive, and second, by using a local everywhere else that can be
412-
// minified.
413-
{{{ makeModuleReceive('arguments_', 'arguments') }}}
414-
{{{ makeModuleReceive('thisProgram') }}}
415-
416-
// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message
417-
#if ASSERTIONS
418-
// Assertions on removed incoming Module JS APIs.
419-
assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead');
420-
assert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead');
421-
assert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead');
422-
assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead');
423-
assert(typeof Module['read'] == 'undefined', 'Module.read option was removed');
424-
assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)');
425-
assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)');
426-
assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)');
427-
assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY');
428-
assert(typeof Module['ENVIRONMENT'] == 'undefined', 'Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)');
429-
assert(typeof Module['STACK_SIZE'] == 'undefined', 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time')
430-
431-
{{{ makeRemovedModuleAPIAssert('asm', 'wasmExports', false) }}}
432-
{{{ makeRemovedModuleAPIAssert('readAsync') }}}
433-
{{{ makeRemovedModuleAPIAssert('readBinary') }}}
434-
{{{ makeRemovedModuleAPIAssert('setWindowTitle') }}}
435407
{{{ makeRemovedFSAssert('IDBFS') }}}
436408
{{{ makeRemovedFSAssert('PROXYFS') }}}
437409
{{{ makeRemovedFSAssert('WORKERFS') }}}
@@ -444,6 +416,8 @@ assert(typeof Module['STACK_SIZE'] == 'undefined', 'STACK_SIZE can no longer be
444416
{{{ makeRemovedFSAssert('NODEFS') }}}
445417
#endif
446418

419+
// perform assertions in shell.js after we set up out() and err(), as otherwise
420+
// if an assertion fails it cannot print the message
447421
#if PTHREADS
448422
assert(
449423
#if AUDIO_WORKLET
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8233
1+
8257
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
19989
1+
20052
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8220
1+
8245
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
19967
1+
20030
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
9231
1+
9259
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
23726
1+
23789
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8176
1+
8198
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
19881
1+
19945
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8176
1+
8198
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
19881
1+
19945
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8245
1+
8269
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20063
1+
20127
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
9269
1+
9297
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
23840
1+
23903
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8233
1+
8257
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
19989
1+
20052
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3436
1+
3451
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7425
1+
7487
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7540
1+
7563
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
18547
1+
18615
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2681
1+
2704
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5749
1+
5814
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7934
1+
7823
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
21291
1+
21026

0 commit comments

Comments
 (0)