Description
Version of emscripten/emsdk: 4.0.8 (bug introduced in 4.0.0)
Description
I'm compiling with the MODULARIZE=1
flag and using code like the following to instantiate the module in js:
try {
module = await Module({
locateFile,
fetchSettings,
});
} catch (e) {
console.warn(e);
// redirect to error page
}
Before version 4.0, everything worked as expected: if the .wasm
file failed to load, the error was caught and handled.
Since version 4.0, however, when the .wasm
fetch fails, two errors are thrown in sequence. I can only catch one, but another one is thrown later and can't be caught because the catch
block has already run.
Cause
This issue appears to originate from the following line in Module.js
:
var wasmExports = await createWasm();
This line is generated by this one:
emscripten/tools/emscripten.py
Lines 1047 to 1052 in fe95793
This was introduced by this PR #23157
Here’s a minimal reproduction of the Module.js
structure:
// Inside Module.js
function createWasm() {
try {
// code that throws error1
} catch (error1) {
readyPromiseReject(error1);
var error2 = error1; // I'm adding this line to differentiate between the two
return Promise.reject(error2); // <- error2 is caught, error1 is not
}
}
var wasmExports = await createWasm();
// In my application code
try {
await Module();
} catch (e) {
console.warn(e); // Only error2 is caught here
}
// error1 is later thrown unhandled
So error2
is caught by user code, but error1
is thrown after the fact and cannot be intercepted, leading to an unhandled rejection or uncaught error.
Suggested Fix
Modifying the Module.js
file this way fixes the problem:
try {
var wasmExports = await createWasm();
} catch (err) {
readyPromiseReject(err);
return readyPromise;
}
This avoids throwing a second error, but it’s obviously not ideal.
The core issue is mixing a top-level await
with a promise (readyPromise
) that is also being rejected separately. This leads to two separate error flows. In my opinion, the code should use either top-level await
or a returned/rejected promise—not both.