diff --git a/ChangeLog.md b/ChangeLog.md index 71ec1fba5a206..a2ca3d135c708 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -32,6 +32,10 @@ See docs/process.md for more on how version tagging works. for chrome, or emrun --browser=firefox --browser-args=-headless [..] for firefox. (#24537) +- When JSPI is enabled `async` library functions are no longer automatically + wrapped with `WebAssembly.Suspending` functions. To automatically wrap library + functions for use with JSPI they must now explicitly set + `myLibraryFunction__async: true`. 4.0.10 - 06/07/25 ----------------- diff --git a/src/jsifier.mjs b/src/jsifier.mjs index 8d24a4bb99595..0d76946dd838d 100644 --- a/src/jsifier.mjs +++ b/src/jsifier.mjs @@ -534,9 +534,7 @@ function(${args}) { if (ASYNCIFY) { const original = LibraryManager.library[symbol]; if (typeof original == 'function') { - isAsyncFunction = - LibraryManager.library[symbol + '__async'] || - original.constructor.name == 'AsyncFunction'; + isAsyncFunction = LibraryManager.library[symbol + '__async']; } if (isAsyncFunction) { asyncFuncs.push(symbol); diff --git a/src/lib/libasync.js b/src/lib/libasync.js index 5183a840273da..92111159e3614 100644 --- a/src/lib/libasync.js +++ b/src/lib/libasync.js @@ -559,6 +559,7 @@ addToLibrary({ #endif _load_secondary_module__sig: 'v', + _load_secondary_module__async: true, _load_secondary_module: async function() { // Mark the module as loading for the wasm module (so it doesn't try to load it again). wasmExports['load_secondary_module_status'].value = 1; diff --git a/src/lib/libpthread.js b/src/lib/libpthread.js index 6d979627efe31..c3002671dad56 100644 --- a/src/lib/libpthread.js +++ b/src/lib/libpthread.js @@ -1015,6 +1015,9 @@ var LibraryPThread = { '$runtimeKeepaliveCounter', #endif ], +#if ASYNCIFY + $invokeEntryPoint__async: true, +#endif $invokeEntryPoint: {{{ asyncIf(ASYNCIFY == 2) }}}(ptr, arg) => { #if PTHREADS_DEBUG dbg(`invokeEntryPoint: ${ptrToString(ptr)}`); diff --git a/src/lib/libwasmfs_opfs.js b/src/lib/libwasmfs_opfs.js index 4dd7598226298..405891b05d0d6 100644 --- a/src/lib/libwasmfs_opfs.js +++ b/src/lib/libwasmfs_opfs.js @@ -69,6 +69,7 @@ addToLibrary({ }, _wasmfs_opfs_init_root_directory__deps: ['$wasmfsOPFSDirectoryHandles', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_init_root_directory__async: {{{ !PTHREADS }}}, _wasmfs_opfs_init_root_directory: async function(ctx) { // allocated.length starts off as 1 since 0 is a reserved handle if (wasmfsOPFSDirectoryHandles.allocated.length == 1) { @@ -88,6 +89,7 @@ addToLibrary({ // corresponding to the error. $wasmfsOPFSGetOrCreateFile__deps: ['$wasmfsOPFSDirectoryHandles', '$wasmfsOPFSFileHandles'], + $wasmfsOPFSGetOrCreateFile__async: {{{ !PTHREADS }}}, $wasmfsOPFSGetOrCreateFile: async function(parent, name, create) { let parentHandle = wasmfsOPFSDirectoryHandles.get(parent); let fileHandle; @@ -112,6 +114,7 @@ addToLibrary({ // it if it doesn't exist and `create` or otherwise return a negative error // code corresponding to the error. $wasmfsOPFSGetOrCreateDir__deps: ['$wasmfsOPFSDirectoryHandles'], + $wasmfsOPFSGetOrCreateDir__async: {{{ !PTHREADS }}}, $wasmfsOPFSGetOrCreateDir: async function(parent, name, create) { let parentHandle = wasmfsOPFSDirectoryHandles.get(parent); let childHandle; @@ -135,6 +138,7 @@ addToLibrary({ _wasmfs_opfs_get_child__deps: ['$wasmfsOPFSGetOrCreateFile', '$wasmfsOPFSGetOrCreateDir', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_get_child__async: {{{ !PTHREADS }}}, _wasmfs_opfs_get_child: async function(ctx, parent, namePtr, childTypePtr, childIDPtr) { let name = UTF8ToString(namePtr); @@ -155,6 +159,7 @@ addToLibrary({ '$stackRestore', '_wasmfs_opfs_record_entry', ], + _wasmfs_opfs_get_entries__async: {{{ !PTHREADS }}}, _wasmfs_opfs_get_entries: async function(ctx, dirID, entriesPtr, errPtr) { let dirHandle = wasmfsOPFSDirectoryHandles.get(dirID); @@ -179,6 +184,7 @@ addToLibrary({ }, _wasmfs_opfs_insert_file__deps: ['$wasmfsOPFSGetOrCreateFile', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_insert_file__async: {{{ !PTHREADS }}}, _wasmfs_opfs_insert_file: async function(ctx, parent, namePtr, childIDPtr) { let name = UTF8ToString(namePtr); let childID = await wasmfsOPFSGetOrCreateFile(parent, name, true); @@ -187,6 +193,7 @@ addToLibrary({ }, _wasmfs_opfs_insert_directory__deps: ['$wasmfsOPFSGetOrCreateDir', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_insert_directory__async: {{{ !PTHREADS }}}, _wasmfs_opfs_insert_directory: async function(ctx, parent, namePtr, childIDPtr) { let name = UTF8ToString(namePtr); @@ -198,6 +205,7 @@ addToLibrary({ _wasmfs_opfs_move_file__deps: ['$wasmfsOPFSFileHandles', '$wasmfsOPFSDirectoryHandles', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_move_file__async: {{{ !PTHREADS }}}, _wasmfs_opfs_move_file: async function(ctx, fileID, newParentID, namePtr, errPtr) { let name = UTF8ToString(namePtr); let fileHandle = wasmfsOPFSFileHandles.get(fileID); @@ -212,6 +220,7 @@ addToLibrary({ }, _wasmfs_opfs_remove_child__deps: ['$wasmfsOPFSDirectoryHandles', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_remove_child__async: {{{ !PTHREADS }}}, _wasmfs_opfs_remove_child: async function(ctx, dirID, namePtr, errPtr) { let name = UTF8ToString(namePtr); let dirHandle = wasmfsOPFSDirectoryHandles.get(dirID); @@ -240,6 +249,7 @@ addToLibrary({ '$wasmfsOPFSCreateAsyncAccessHandle' #endif ], + _wasmfs_opfs_open_access__async: {{{ !PTHREADS }}}, _wasmfs_opfs_open_access: async function(ctx, fileID, accessIDPtr) { let fileHandle = wasmfsOPFSFileHandles.get(fileID); let accessID; @@ -279,6 +289,7 @@ addToLibrary({ _wasmfs_opfs_open_blob__deps: ['$wasmfsOPFSFileHandles', '$wasmfsOPFSBlobs', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_open_blob__async: {{{ !PTHREADS }}}, _wasmfs_opfs_open_blob: async function(ctx, fileID, blobIDPtr) { let fileHandle = wasmfsOPFSFileHandles.get(fileID); let blobID; @@ -300,6 +311,7 @@ addToLibrary({ }, _wasmfs_opfs_close_access__deps: ['$wasmfsOPFSAccessHandles', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_close_access__async: {{{ !PTHREADS }}}, _wasmfs_opfs_close_access: async function(ctx, accessID, errPtr) { let accessHandle = wasmfsOPFSAccessHandles.get(accessID); try { @@ -319,6 +331,7 @@ addToLibrary({ _wasmfs_opfs_read_access__i53abi: true, _wasmfs_opfs_read_access__deps: ['$wasmfsOPFSAccessHandles'], + _wasmfs_opfs_read_access__async: {{{ !PTHREADS }}}, _wasmfs_opfs_read_access: {{{ asyncIf(!PTHREADS) }}}function(accessID, bufPtr, len, pos) { let accessHandle = wasmfsOPFSAccessHandles.get(accessID); let data = HEAPU8.subarray(bufPtr, bufPtr + len); @@ -337,6 +350,7 @@ addToLibrary({ _wasmfs_opfs_read_blob__i53abi: true, _wasmfs_opfs_read_blob__deps: ['$wasmfsOPFSBlobs', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_read_blob__async: {{{ !PTHREADS }}}, _wasmfs_opfs_read_blob: async function(ctx, blobID, bufPtr, len, pos, nreadPtr) { let blob = wasmfsOPFSBlobs.get(blobID); let slice = blob.slice(pos, pos + len); @@ -367,6 +381,7 @@ addToLibrary({ _wasmfs_opfs_write_access__i53abi: true, _wasmfs_opfs_write_access__deps: ['$wasmfsOPFSAccessHandles'], + _wasmfs_opfs_write_access__async: {{{ !PTHREADS }}}, _wasmfs_opfs_write_access: {{{ asyncIf(!PTHREADS) }}}function(accessID, bufPtr, len, pos) { let accessHandle = wasmfsOPFSAccessHandles.get(accessID); let data = HEAPU8.subarray(bufPtr, bufPtr + len); @@ -384,6 +399,7 @@ addToLibrary({ }, _wasmfs_opfs_get_size_access__deps: ['$wasmfsOPFSAccessHandles', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_get_size_access__async: {{{ !PTHREADS }}}, _wasmfs_opfs_get_size_access: async function(ctx, accessID, sizePtr) { let accessHandle = wasmfsOPFSAccessHandles.get(accessID); let size; @@ -404,6 +420,7 @@ addToLibrary({ }, _wasmfs_opfs_get_size_file__deps: ['$wasmfsOPFSFileHandles', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_get_size_file__async: {{{ !PTHREADS }}}, _wasmfs_opfs_get_size_file: async function(ctx, fileID, sizePtr) { let fileHandle = wasmfsOPFSFileHandles.get(fileID); let size; @@ -418,6 +435,7 @@ addToLibrary({ _wasmfs_opfs_set_size_access__i53abi: true, _wasmfs_opfs_set_size_access__deps: ['$wasmfsOPFSAccessHandles', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_set_size_access__async: {{{ !PTHREADS }}}, _wasmfs_opfs_set_size_access: async function(ctx, accessID, size, errPtr) { let accessHandle = wasmfsOPFSAccessHandles.get(accessID); try { @@ -431,6 +449,7 @@ addToLibrary({ _wasmfs_opfs_set_size_file__i53abi: true, _wasmfs_opfs_set_size_file__deps: ['$wasmfsOPFSFileHandles', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_set_size_file__async: {{{ !PTHREADS }}}, _wasmfs_opfs_set_size_file: async function(ctx, fileID, size, errPtr) { let fileHandle = wasmfsOPFSFileHandles.get(fileID); try { @@ -445,6 +464,7 @@ addToLibrary({ }, _wasmfs_opfs_flush_access__deps: ['$wasmfsOPFSAccessHandles', '$wasmfsOPFSProxyFinish'], + _wasmfs_opfs_flush_access__async: {{{ !PTHREADS }}}, _wasmfs_opfs_flush_access: async function(ctx, accessID, errPtr) { let accessHandle = wasmfsOPFSAccessHandles.get(accessID); try { diff --git a/test/test_other.py b/test/test_other.py index 5639a2c86f394..c8eb02bbbbcf3 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -3484,6 +3484,32 @@ def test_jspi_add_function(self): '-Wno-experimental'] self.do_runf('other/test_jspi_add_function.c', 'done') + @requires_jspi + def test_jspi_async_function(self): + # Make sure async library functions are not automatically JSPI'd. + create_file('lib.js', r''' + addToLibrary({ + foo: async function(f) { await Promise.resolve(); }, + }); + ''') + create_file('main.c', r''' + #include + extern void foo(); + EMSCRIPTEN_KEEPALIVE void test() { + foo(); + } + ''') + create_file('post.js', r''' + Module.onRuntimeInitialized = () => { + _test() + console.log('done'); + }; + ''') + self.do_runf('main.c', 'done', emcc_args=['-sJSPI', + '--js-library=lib.js', + '-Wno-experimental', + '--post-js=post.js']) + @requires_dev_dependency('typescript') @parameterized({ 'commonjs': [['-sMODULARIZE'], ['--module', 'commonjs', '--moduleResolution', 'node']],