Skip to content

Simplify modular runtime initialization promise#27059

Open
brendandahl wants to merge 2 commits into
emscripten-core:mainfrom
brendandahl:refactor-init-promise
Open

Simplify modular runtime initialization promise#27059
brendandahl wants to merge 2 commits into
emscripten-core:mainfrom
brendandahl:refactor-init-promise

Conversation

@brendandahl
Copy link
Copy Markdown
Collaborator

Unify and simplify the promise and dependency resolution mechanism for
modularized builds (both MODULARIZE=1 and MODULARIZE=instance).

Previously, the codebase maintained separate tracking variables like
moduleRtn and readyPromiseResolve alongside complex external Promise
wrappers across distinct JS postamble files. This created unnecessary
complexity and redundant boilerplate.

This change replaces ad-hoc external Promise assignment with direct
async/await initialization flows inside the core runtime postamble. This
also fixes the MODULARIZE=instance dependency order issue.

Unify and simplify the promise and dependency resolution mechanism for
modularized builds (both MODULARIZE=1 and MODULARIZE=instance).

Previously, the codebase maintained separate tracking variables like
moduleRtn and readyPromiseResolve alongside complex external Promise
wrappers across distinct JS postamble files. This created unnecessary
complexity and redundant boilerplate.

This change replaces ad-hoc external Promise assignment with direct
async/await initialization flows inside the core runtime postamble. This
also fixes the MODULARIZE=instance dependency order issue.
This is an automatic change generated by tools/maint/rebaseline_tests.py.

The following (10) test expectation files were updated by
running the tests with `--rebaseline`:

```
test/codesize/audio_worklet_wasm.expected.js updated
codesize/test_codesize_minimal_esm.json: 2521 => 2468 [-53 bytes / -2.10%]
codesize/test_codesize_minimal_pthreads.json: 26075 => 26081 [+6 bytes / +0.02%]
codesize/test_codesize_minimal_pthreads_memgrowth.json: 26484 => 26490 [+6 bytes / +0.02%]
codesize/test_minimal_runtime_code_size_audio_worklet.json: 16399 => 16399 [+0 bytes / +0.00%]
codesize/test_minimal_runtime_code_size_hello_webgl2_wasm.json: 13200 => 13161 [-39 bytes / -0.30%]
codesize/test_minimal_runtime_code_size_hello_webgl2_wasm2js.json: 18572 => 18534 [-38 bytes / -0.20%]
codesize/test_minimal_runtime_code_size_hello_webgl2_wasm_singlefile.json: 15046 => 15015 [-31 bytes / -0.21%]
codesize/test_minimal_runtime_code_size_hello_webgl_wasm.json: 12738 => 12699 [-39 bytes / -0.31%]
codesize/test_minimal_runtime_code_size_hello_webgl_wasm2js.json: 18098 => 18060 [-38 bytes / -0.21%]

Average change: -0.36% (-2.10% - +0.02%)
```
@brendandahl brendandahl requested a review from sbc100 June 5, 2026 17:22
Copy link
Copy Markdown
Collaborator

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great!

Comment thread src/postamble.js
#if MODULARIZE
await new Promise((resolve) => {
dependenciesFulfilled = resolve;
});
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this just be a single line await new Promise((resolve) => dependenciesFulfilled = resolve);?

Comment thread src/postamble.js
{
const url = await import('node:url');
const isMainModule = url.pathToFileURL(process.argv[1]).href === import.meta.url;
const isMainModule = process.argv[1] && url.pathToFileURL(process.argv[1]).href === import.meta.url;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I this change related?

readyPromiseResolve = resolve;
readyPromiseReject = reject;
});
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome. Since this file doesn't do anything but inject these assertions now I wonder if it should just be removed (perhaps as a followup)?

Comment thread tools/link.py
if settings.MODULARIZE and settings.MODULARIZE != 'instance':
modularize()
elif settings.USE_CLOSURE_COMPILER:
elif settings.USE_CLOSURE_COMPILER and not settings.MODULARIZE:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this?

Comment thread tools/building.py
if settings.MODULARIZE:
module_extern_file = shared.get_temp_files().get('.js', prefix='emcc_modularize_extern_')
module_extern_file.write(b'/** @suppress {duplicate} */\nvar Module;\n')
module_extern_file.close()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the contents of this file are just constant we can't we just check this in as a file in src/closure-externs/?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just add to the existing modularize-externs.js?

Comment thread src/postamble.js
doRun();
resolve();
}, 1);
});
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code looks kind of weird.. perhaps it should have a comment?

Comment thread src/parseTools.mjs
text = text.replace(/\bawait run\(\)/g, 'EMSCRIPTEN$AWAIT(run())');
text = text.replace(/\bawait instantiatePromise\b/g, 'EMSCRIPTEN$AWAIT(instantiatePromise)');
text = text.replace(/\bawait init\(\)/g, 'EMSCRIPTEN$AWAIT(init())');
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make this new code into its own named function? Something like mangleUnsupportedSyntax ? or some better name?

I wonder what knock on effects it will have that we now do this in processMacros vs preprocess? IIRC there are times when we do one but not the other.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants