From b5a1bdf972a507157aec8479d21cf93d274302f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Wed, 4 Sep 2024 21:17:48 +0300 Subject: [PATCH] Add JSPI support to MINIMAL_RUNTIME build mode. --- src/postamble_minimal.js | 59 ++++++++++++++++++++++++++-------------- src/preamble_minimal.js | 7 +++++ test/test_browser.py | 2 ++ 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/postamble_minimal.js b/src/postamble_minimal.js index f34830f0cbd5..259efd550026 100644 --- a/src/postamble_minimal.js +++ b/src/postamble_minimal.js @@ -8,39 +8,50 @@ {{{ exportRuntime() }}} #if HAS_MAIN // Only if user is exporting a C main(), we will generate a run() function that can be used to launch main. -function run() { -#if MEMORYPROFILER - emscriptenMemoryProfiler.onPreloadComplete(); -#endif - - <<< ATMAINS >>> - -#if PROXY_TO_PTHREAD - // User requested the PROXY_TO_PTHREAD option, so call a stub main which - // pthread_create()s a new thread that will call the user's real main() for - // the application. - var ret = __emscripten_proxy_main(); -#else - var ret = _main(); #if EXIT_RUNTIME +function exitRuntime(ret) { callRuntimeCallbacks(__ATEXIT__); <<< ATEXITS >>> #if PTHREADS PThread.terminateAllThreads(); #endif -#endif - -#if EXIT_RUNTIME - #if ASSERTIONS runtimeExited = true; #endif _proc_exit(ret); + +#if STACK_OVERFLOW_CHECK + checkStackCookie(); +#endif +} +#endif + +function run() { +#if MEMORYPROFILER + emscriptenMemoryProfiler.onPreloadComplete(); #endif -#endif // PROXY_TO_PTHREAD + + <<< ATMAINS >>> + +#if PROXY_TO_PTHREAD + // User requested the PROXY_TO_PTHREAD option, so call a stub main which + // pthread_create()s a new thread that will call the user's real main() for + // the application. + __emscripten_proxy_main(); +#elif ASYNCIFY == 2 && EXIT_RUNTIME + // In JSPI-enabled build mode, the main() function will return a Promise, + // which resolves to the process exit code. + _main().then(exitRuntime); +#elif EXIT_RUNTIME + // In regular exitRuntime mode, exit with the given return code from main(). + exitRuntime(_main()); +#else + // Run a persistent (never-exiting) application starting at main(). + _main(); +#endif #if STACK_OVERFLOW_CHECK checkStackCookie(); @@ -101,6 +112,10 @@ function loadModule() { assignWasmImports(); #endif +#if ASYNCIFY +Asyncify.instrumentWasmImports(wasmImports); +#endif + var imports = { #if MINIFY_WASM_IMPORTED_MODULES 'a': wasmImports, @@ -138,7 +153,7 @@ if (!Module['wasm']) throw 'Must load WebAssembly Module in to variable Module.w WebAssembly.instantiate(Module['wasm'], imports).then((output) => { #endif -#if !LibraryManager.has('library_exports.js') +#if !LibraryManager.has('library_exports.js') && ASYNCIFY != 1 // If not using the emscripten_get_exported_function() API, keep the // `wasmExports` variable in local scope to this instantiate function to save // code size. (otherwise access it without to export it to outer scope) @@ -169,6 +184,10 @@ WebAssembly.instantiate(Module['wasm'], imports).then((output) => { wasmExports = output.instance.exports; #endif +#if ASYNCIFY + wasmExports = Asyncify.instrumentWasmExports(wasmExports); +#endif + #if MEMORY64 || CAN_ADDRESS_2GB wasmExports = applySignatureConversions(wasmExports); #endif diff --git a/src/preamble_minimal.js b/src/preamble_minimal.js index f110870d2b77..64aa75e5652f 100644 --- a/src/preamble_minimal.js +++ b/src/preamble_minimal.js @@ -23,8 +23,15 @@ function assert(condition, text) { } #endif +#if ASYNCIFY == 1 // ASYNCIFY-mode requires checking ABORT variable to avoid operating if code has aborted during an unwind +var ABORT = 0; +#endif + /** @param {string|number=} what */ function abort(what) { +#if ASYNCIFY == 1 + ABORT = 1; +#endif throw {{{ ASSERTIONS ? 'new Error(what)' : 'what' }}}; } diff --git a/test/test_browser.py b/test/test_browser.py index bd3729447e89..95fcf4c1eb3a 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -3153,8 +3153,10 @@ def test_cocos2d_hello(self): @parameterized({ 'asyncify': (['-sASYNCIFY=1'],), + 'asyncify_minimal_runtime': (['-sMINIMAL_RUNTIME', '-sASYNCIFY=1'],), 'jspi': (['-sASYNCIFY=2', '-Wno-experimental'],), 'jspi_wasm_bigint': (['-sASYNCIFY=2', '-sWASM_BIGINT', '-Wno-experimental'],), + 'jspi_wasm_bigint_minimal_runtime': (['-sMINIMAL_RUNTIME', '-sASYNCIFY=2', '-sWASM_BIGINT', '-Wno-experimental'],), }) def test_async(self, args): if is_jspi(args) and not is_chrome():