Modernize dependency system with Promise-based run blockers#27028
Modernize dependency system with Promise-based run blockers#27028sbc100 wants to merge 1 commit into
Conversation
|
I'm petty happy about this change. Its something I've tried to do over the years several times and always given up in the end. This time with gemini's help I was able to get to the end of it. The legacy versions of this API are also still supported which is nice. The |
b0f8006 to
b66f862
Compare
| var LibraryFetch = { | ||
| $Fetch__postset: 'Fetch.init();', | ||
| $Fetch__deps: ['$HandleAllocator'], | ||
| $Fetch__deps: ['$HandleAllocator', '$addRunBlocker'], |
|
|
||
|
|
||
|
|
||
| var resolve; |
There was a problem hiding this comment.
Why is there so much whitespace here?
| runDependencies--; | ||
|
|
||
|
|
||
|
|
|
|
||
| #if MAIN_READS_PARAMS | ||
| function run(args = programArgs) { | ||
| async function run(args = programArgs) { |
There was a problem hiding this comment.
Does making this function async change the API from the user's point of view? I don't recall if we allow users to call it directly.
…ependencies
Simplify the file packager and LZ4 loading code by leveraging modern
async/await features.
Previously, we tracked the loading of each individual preloaded file by
adding and removing separate run dependencies (`fp ${name}`). This
introduced complexity and extra boilerplate.
Now, we make `loadPackage` and `processPackageData` async functions and
directly `await` the preloading of each file (including running any
preload plugins). The main package-level run dependency
(`datafile_${name}`) is held until all files are fully processed and
then removed.
This reduces code complexity, eliminates the need for granular run
dependencies, and reduces the generated JS code size by ~100 bytes.
Split out from emscripten-core#27028
Simplify the file packager and LZ4 loading code by leveraging modern
async/await features.
Previously, we tracked the loading of each individual preloaded file by
adding and removing separate run dependencies (`fp ${name}`). This
introduced complexity and extra boilerplate.
Now, we make `loadPackage` and `processPackageData` async functions and
directly `await` the preloading of each file (including running any
preload plugins). The main package-level run dependency
(`datafile_${name}`) is held until all files are fully processed and
then removed.
This reduces code complexity, eliminates the need for granular run
dependencies, and reduces the generated JS code size by ~100 bytes.
Split out from #27028
…27075) When `WASM_ASYNC_COMPILATION` is enabled `createWasm` returns a promise. However we were not always waiting on this and instead using the `addRunDependency` system to block the running of main. This change simplifies things by always awaiting the promise when it exists. This is kind of a followup to #27059 and a pre-cursor to #27028 which is a much larger change. Comes with a nice little codesize saving too, since it avoid the whole `addRunDependency` in most simple programs.
Replace the callback-based dependenciesFulfilled/runDependencies system with a modern async/await approach using "run blockers" (Promises). This modernizes the startup sequence, ensuring preRun and other startup hooks are executed exactly once by pausing and resuming execution flow instead of re-running the entry point. To maintain backward compatibility, a bridge is implemented for the existing addRunDependency and removeRunDependency APIs, routing them through the new Promise-based blocking mechanism. - Make run() in postamble.js async to support await. - Implement $addRunBlocker and $resolveRunBlockers in libcore.js. - Bridge $addRunDependency and $removeRunDependency to use $addRunBlocker. - Wrap runDependencies == 0 check in ASSERTIONS guard to avoid empty block in optimized builds (fixes Closure Compiler warnings). The following (18) test expectation files were updated by running the tests with `--rebaseline`: ``` codesize/test_codesize_cxx_ctors1.json: 151867 => 151979 [+112 bytes / +0.07%] codesize/test_codesize_cxx_ctors2.json: 151270 => 151382 [+112 bytes / +0.07%] codesize/test_codesize_cxx_except.json: 195760 => 195873 [+113 bytes / +0.06%] codesize/test_codesize_cxx_except_wasm.json: 166991 => 167103 [+112 bytes / +0.07%] codesize/test_codesize_cxx_except_wasm_legacy.json: 164875 => 164987 [+112 bytes / +0.07%] codesize/test_codesize_cxx_lto.json: 120708 => 120820 [+112 bytes / +0.09%] codesize/test_codesize_cxx_mangle.json: 262239 => 262352 [+113 bytes / +0.04%] codesize/test_codesize_cxx_noexcept.json: 153867 => 153979 [+112 bytes / +0.07%] codesize/test_codesize_cxx_wasmfs.json: 179724 => 179741 [+17 bytes / +0.01%] test/codesize/test_codesize_file_preload.expected.js updated codesize/test_codesize_file_preload.json: 23823 => 23697 [-126 bytes / -0.53%] codesize/test_codesize_files_js_fs.json: 18247 => 18342 [+95 bytes / +0.52%] codesize/test_codesize_hello_O0.json: 38598 => 38578 [-20 bytes / -0.05%] codesize/test_codesize_hello_dylink.json: 44132 => 44228 [+96 bytes / +0.22%] codesize/test_codesize_hello_dylink_all.json: 855885 => 855967 [+82 bytes / +0.01%] test/codesize/test_codesize_minimal_O0.expected.js updated codesize/test_codesize_minimal_O0.json: 19738 => 19658 [-80 bytes / -0.41%] codesize/test_unoptimized_code_size.json: 176480 => 176351 [-129 bytes / -0.07%] Average change: +0.02% (-0.53% - +0.52%) ```
|
I think I found a simpler, more elegant, solution that does not involve changing any external APIs: #27171 |
Replace the callback-based dependenciesFulfilled/runDependencies system
with a modern async/await approach using "run blockers" (Promises).
This modernizes the startup sequence, ensuring preRun and other startup
hooks are executed exactly once by pausing and resuming execution flow
instead of re-running the entry point.
To maintain backward compatibility, a bridge is implemented for the
existing addRunDependency and removeRunDependency APIs, routing them
through the new Promise-based blocking mechanism.
The following (18) test expectation files were updated by
running the tests with
--rebaseline: