Skip to content

Commit 7e3e35c

Browse files
committed
Detect and report late assignment of Module API elements
We had some bug reports recently when we switched to using async/await in MODULUARIZE mode. One of the side effects was the `--post-js` code then runs after module instantiation and startup, which means assignment of properties like `onRuntimeInitialized` is too late if it happens in `--post-js`. This was always the case for sync instantiation too. We now detect this too-late-assignment at abort with a useful error. See #23626 and #23420
1 parent 242af00 commit 7e3e35c

8 files changed

+37
-4
lines changed

src/postamble.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ function run() {
199199
#endif
200200
#if expectToReceiveOnModule('onRuntimeInitialized')
201201
Module['onRuntimeInitialized']?.();
202+
#if ASSERTIONS
203+
consumedModuleProp('onRuntimeInitialized');
204+
#endif
202205
#endif
203206

204207
#if HAS_MAIN
@@ -297,6 +300,9 @@ if (Module['preInit']) {
297300
Module['preInit'].pop()();
298301
}
299302
}
303+
#if ASSERTIONS
304+
consumedModuleProp('preInit');
305+
#endif
300306
#endif
301307

302308
run();

src/preamble.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ function preRun() {
181181
addOnPreRun(Module['preRun'].shift());
182182
}
183183
}
184+
#if ASSERTIONS
185+
consumedModuleProp('preRun');
186+
#endif
184187
#endif
185188
<<< ATPRERUNS >>>
186189
}
@@ -276,6 +279,9 @@ function postRun() {
276279
addOnPostRun(Module['postRun'].shift());
277280
}
278281
}
282+
#if ASSERTIONS
283+
consumedModuleProp('postRun');
284+
#endif
279285
#endif
280286

281287
<<< ATPOSTRUNS >>>

src/runtime_debug.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ function legacyModuleProp(prop, newName, incoming=true) {
3333
}
3434
}
3535

36+
function consumedModuleProp(prop) {
37+
if (!Object.getOwnPropertyDescriptor(Module, prop)) {
38+
Object.defineProperty(Module, prop, {
39+
configurable: true,
40+
set() {
41+
abort(`Attempt to set \`Module.${prop}\` after it has already been processed. This can happen, for example, when code is injected via '--post-js' rather than '--pre-js'`);
42+
43+
}
44+
});
45+
}
46+
}
47+
3648
function ignoredModuleProp(prop) {
3749
if (Object.getOwnPropertyDescriptor(Module, prop)) {
3850
abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7872
1+
7985
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20962
1+
21341
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
51969
1+
52492
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
50401
1+
50780

test/test_other.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15607,3 +15607,12 @@ def test_instantiate_wasm(self):
1560715607
return {}; // Compiling asynchronously, no exports.
1560815608
}''')
1560915609
self.do_runf('test_manual_wasm_instantiate.c', emcc_args=['--pre-js=pre.js'])
15610+
15611+
def test_late_module_api_assignment(self):
15612+
# When sync instantiation is used (or when async/await is used in MODULARIZE mode) certain
15613+
# Module properties cannot be assigned in `--post-js` code because its too late by the time
15614+
# it runs.
15615+
for prop in ('onRuntimeInitialized', 'postRun', 'preRun', 'preInit'):
15616+
create_file('post.js', f'Module.{prop} = () => console.log("will never fire since assigned too late")')
15617+
expected = f"Aborted(Attempt to set `Module.{prop}` after it has already been processed. This can happen, for example, when code is injected via '--post-js' rather than '--pre-js')"
15618+
self.do_runf(test_file('hello_world.c'), expected, emcc_args=['--post-js=post.js', '-sWASM_ASYNC_COMPILATION=0'], assert_returncode=NON_ZERO)

0 commit comments

Comments
 (0)