diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index b1e70178286f6..ac6ee32f2d6b3 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -685,6 +685,9 @@ var LibraryDylink = { if (!resolved) { resolved = moduleExports[sym]; } + if (resolved.orig) { + resolved = resolved.orig; + } #if ASSERTIONS assert(resolved, `undefined symbol '${sym}'. perhaps a side module was not linked in? if this global was expected to arrive from a system library, try to build the MAIN_MODULE with EMCC_FORCE_STDLIBS=1 in the environment`); #endif @@ -734,10 +737,21 @@ var LibraryDylink = { // when first called. if (!(prop in stubs)) { var resolved; +#if JSPI + var func = (...args) => { + resolved ||= resolveSymbol(prop); + try { + resolved = WebAssembly.promising(resolved); + } catch(e) {} + return resolved(...args); + } + stubs[prop] = new WebAssembly.Suspending(func); +#else stubs[prop] = (...args) => { resolved ||= resolveSymbol(prop); return resolved(...args); }; +#endif } return stubs[prop]; } diff --git a/test/core/test_dlfcn_jspi.c b/test/core/test_dlfcn_jspi.c index 0c73aa6250fb7..0458ddb5ba550 100644 --- a/test/core/test_dlfcn_jspi.c +++ b/test/core/test_dlfcn_jspi.c @@ -3,27 +3,59 @@ // University of Illinois/NCSA Open Source License. Both these licenses can be // found in the LICENSE file. +#include #include #include #include -EM_ASYNC_JS(int, test, (), { +EM_ASYNC_JS(int, test_suspending, (), { console.log("sleeping"); await new Promise(res => setTimeout(res, 0)); console.log("slept"); return 77; }); -int test_wrapper() { - return test(); +int test_suspending_wrapper() { + return test_suspending(); } +EM_JS(int, test_sync, (), { + console.log("sync"); + return 77; +}) + +int test_sync_wrapper() { + return test_sync(); +} + + typedef int (*F)(); +typedef int (*G)(F f); + +void helper(F f) { + void* handle = dlopen("side_a.so", RTLD_NOW|RTLD_GLOBAL); + assert(handle != NULL); + G side_module_trampolinea = dlsym(handle, "side_module_trampoline_a"); + assert(side_module_trampolinea != NULL); + int res = side_module_trampolinea(f); + printf("okay %d\n", res); +} + + +EMSCRIPTEN_KEEPALIVE void not_promising() { + helper(test_sync_wrapper); +} + +EM_JS(void, js_trampoline, (), { + _not_promising(); +}) int main() { - void* handle = dlopen("side.so", RTLD_NOW|RTLD_GLOBAL); - F side_module_trampoline = dlsym(handle, "side_module_trampoline"); - int res = side_module_trampoline(); - printf("done %d\n", res); + printf("Suspending test\n"); + helper(test_suspending_wrapper); + printf("Non suspending test\n"); + js_trampoline(); + printf("done\n"); return 0; } + diff --git a/test/core/test_dlfcn_jspi.out b/test/core/test_dlfcn_jspi.out index 8daf1b9e7f8bf..6b7fe1dbd519a 100644 --- a/test/core/test_dlfcn_jspi.out +++ b/test/core/test_dlfcn_jspi.out @@ -1,4 +1,12 @@ -side_module_trampoline +Suspending test +side_module_trampoline_a +side_module_trampoline_b sleeping slept -done 77 +okay 77 +Non suspending test +side_module_trampoline_a +side_module_trampoline_b +sync +okay 77 +done diff --git a/test/core/test_dlfcn_jspi_side_a.c b/test/core/test_dlfcn_jspi_side_a.c new file mode 100644 index 0000000000000..ae9c04be15735 --- /dev/null +++ b/test/core/test_dlfcn_jspi_side_a.c @@ -0,0 +1,10 @@ +#include + +typedef int (*F)(); + +int side_module_trampoline_b(F f); + +int side_module_trampoline_a(F f) { + printf("side_module_trampoline_a\n"); + return side_module_trampoline_b(f); +} diff --git a/test/core/test_dlfcn_jspi_side_b.c b/test/core/test_dlfcn_jspi_side_b.c new file mode 100644 index 0000000000000..16354428cd417 --- /dev/null +++ b/test/core/test_dlfcn_jspi_side_b.c @@ -0,0 +1,8 @@ +#include + +typedef int (*F)(); + +int side_module_trampoline_b(F f) { + printf("side_module_trampoline_b\n"); + return f(); +} diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index a5755921eac44..27dfac602e314 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -11735 +11736 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index c82e0d84da885..7cb5c3b2b7ba6 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -27774 +27776 diff --git a/test/test_core.py b/test/test_core.py index 7addc63783af4..b48a88e4fefcf 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -3789,13 +3789,24 @@ def test_dlfcn_jspi(self): self.run_process( [ EMCC, - "-o", - "side.so", - test_file("core/test_dlfcn_jspi_side.c"), - "-sSIDE_MODULE", - ] + self.get_emcc_args() + '-o', + 'side_b.so', + test_file('core/test_dlfcn_jspi_side_b.c'), + '-sSIDE_MODULE', + ] + + self.get_emcc_args() + ) + self.run_process( + [ + EMCC, + '-o', + 'side_a.so', + test_file('core/test_dlfcn_jspi_side_a.c'), + '-sSIDE_MODULE', + ] + + self.get_emcc_args() ) - self.do_run_in_out_file_test("core/test_dlfcn_jspi.c", emcc_args=["side.so", "-sMAIN_MODULE=2"]) + self.do_run_in_out_file_test('core/test_dlfcn_jspi.c', emcc_args=['side_a.so', 'side_b.so', '-sMAIN_MODULE=2', '-g']) @needs_dylink def test_dlfcn_rtld_local(self):