Skip to content

Commit 5f86a68

Browse files
authored
[embind] Fix JSPI dynCalls. (#23853)
WebAssembly.promising requires a wasm function argument, previously we were passing in a wrapper JS function that caused an error. Move wrapping the wasm function with WebAssembly.promising into embind__requireFunction and also handle it in dynCall. Fixes #23834
1 parent 706f15c commit 5f86a68

File tree

3 files changed

+35
-25
lines changed

3 files changed

+35
-25
lines changed

src/lib/libcore.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1785,14 +1785,17 @@ addToLibrary({
17851785
// All callers should use direct table access where possible and only fall
17861786
// back to this function if needed.
17871787
$getDynCaller__deps: ['$dynCall'],
1788-
$getDynCaller: (sig, ptr) => {
1788+
$getDynCaller: (sig, ptr, promising = false) => {
17891789
#if ASSERTIONS && !DYNCALLS
17901790
assert(sig.includes('j') || sig.includes('p'), 'getDynCaller should only be called with i64 sigs')
17911791
#endif
1792-
return (...args) => dynCall(sig, ptr, args);
1792+
return (...args) => dynCall(sig, ptr, args, promising);
17931793
},
17941794

1795-
$dynCall: (sig, ptr, args = []) => {
1795+
$dynCall: (sig, ptr, args = [], promising = false) => {
1796+
#if ASSERTIONS && (DYNCALLS || !WASM_BIGINT || !JSPI)
1797+
assert(!promising, 'async dynCall is not supported in this mode')
1798+
#endif
17961799
#if MEMORY64
17971800
// With MEMORY64 we have an additional step to convert `p` arguments to
17981801
// bigint. This is the runtime equivalent of the wrappers we create for wasm
@@ -1815,7 +1818,13 @@ addToLibrary({
18151818
#if ASSERTIONS
18161819
assert(getWasmTableEntry(ptr), `missing table entry in dynCall: ${ptr}`);
18171820
#endif
1818-
var rtn = getWasmTableEntry(ptr)(...args);
1821+
var func = getWasmTableEntry(ptr);
1822+
#if JSPI
1823+
if (promising) {
1824+
func = WebAssembly.promising(func);
1825+
}
1826+
#endif
1827+
var rtn = func(...args);
18191828
#endif
18201829
#if MEMORY64
18211830
return sig[0] == 'p' ? Number(rtn) : rtn;

src/lib/libembind.js

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -772,13 +772,6 @@ var LibraryEmbind = {
772772
#if ASSERTIONS && ASYNCIFY != 2
773773
assert(!isAsync, 'Async bindings are only supported with JSPI.');
774774
#endif
775-
776-
#if ASYNCIFY == 2
777-
if (isAsync) {
778-
cppInvokerFunc = Asyncify.makeAsyncFunction(cppInvokerFunc);
779-
}
780-
#endif
781-
782775
var isClassMethodFunc = (argTypes[1] !== null && classType !== null);
783776

784777
// Free functions with signature "void function()" do not need an invoker that marshalls between wire types.
@@ -894,11 +887,15 @@ var LibraryEmbind = {
894887
},
895888

896889
$embind__requireFunction__deps: ['$readLatin1String', '$throwBindingError'
897-
#if DYNCALLS || !WASM_BIGINT || MEMORY64
890+
#if DYNCALLS || !WASM_BIGINT || MEMORY64 || CAN_ADDRESS_2GB
898891
, '$getDynCaller'
899892
#endif
900893
],
901-
$embind__requireFunction: (signature, rawFunction) => {
894+
$embind__requireFunction: (signature, rawFunction, isAsync = false) => {
895+
#if ASSERTIONS && ASYNCIFY != 2
896+
assert(!isAsync, 'Async bindings are only supported with JSPI.');
897+
#endif
898+
902899
signature = readLatin1String(signature);
903900

904901
function makeDynCaller() {
@@ -912,10 +909,16 @@ var LibraryEmbind = {
912909
#endif
913910
#if MEMORY64 || CAN_ADDRESS_2GB
914911
if (signature.includes('p')) {
915-
return getDynCaller(signature, rawFunction);
912+
return getDynCaller(signature, rawFunction, isAsync);
913+
}
914+
#endif
915+
var rtn = getWasmTableEntry(rawFunction);
916+
#if JSPI
917+
if (isAsync) {
918+
rtn = WebAssembly.promising(rtn);
916919
}
917920
#endif
918-
return getWasmTableEntry(rawFunction);
921+
return rtn;
919922
#endif
920923
}
921924

@@ -935,7 +938,7 @@ var LibraryEmbind = {
935938
name = readLatin1String(name);
936939
name = getFunctionName(name);
937940

938-
rawInvoker = embind__requireFunction(signature, rawInvoker);
941+
rawInvoker = embind__requireFunction(signature, rawInvoker, isAsync);
939942

940943
exposePublicSymbol(name, function() {
941944
throwUnboundTypeError(`Cannot call ${name} due to unbound types`, argTypes);
@@ -1938,7 +1941,7 @@ var LibraryEmbind = {
19381941
var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
19391942
methodName = readLatin1String(methodName);
19401943
methodName = getFunctionName(methodName);
1941-
rawInvoker = embind__requireFunction(invokerSignature, rawInvoker);
1944+
rawInvoker = embind__requireFunction(invokerSignature, rawInvoker, isAsync);
19421945

19431946
whenDependentTypesAreResolved([], [rawClassType], (classType) => {
19441947
classType = classType[0];
@@ -2075,7 +2078,7 @@ var LibraryEmbind = {
20752078
var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
20762079
methodName = readLatin1String(methodName);
20772080
methodName = getFunctionName(methodName);
2078-
rawInvoker = embind__requireFunction(invokerSignature, rawInvoker);
2081+
rawInvoker = embind__requireFunction(invokerSignature, rawInvoker, isAsync);
20792082
whenDependentTypesAreResolved([], [rawClassType], (classType) => {
20802083
classType = classType[0];
20812084
var humanName = `${classType.name}.${methodName}`;

test/test_other.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3257,15 +3257,13 @@ def test_embind_asyncify(self):
32573257
self.do_runf('main.cpp', 'done', emcc_args=['-lembind', '-sASYNCIFY', '--post-js', 'post.js'])
32583258

32593259
@parameterized({
3260-
'': ['-sDYNAMIC_EXECUTION=1'],
3261-
'no_dynamic': ['-sDYNAMIC_EXECUTION=0'],
3260+
'': [['-sDYNAMIC_EXECUTION=1']],
3261+
'no_dynamic': [['-sDYNAMIC_EXECUTION=0']],
3262+
'dyncall': [['-sALLOW_MEMORY_GROWTH', '-sMAXIMUM_MEMORY=4GB']],
32623263
})
32633264
@requires_jspi
3264-
def test_embind_jspi(self, extra):
3265-
self.emcc_args += ['-lembind', '-g']
3266-
self.emcc_args += [extra]
3267-
3268-
self.do_runf('embind/embind_jspi_test.cpp', 'done')
3265+
def test_embind_jspi(self, args):
3266+
self.do_runf('embind/embind_jspi_test.cpp', 'done', emcc_args=['-lembind', '-g'] + args)
32693267

32703268
def test_embind_no_function(self):
32713269
create_file('post.js', '''

0 commit comments

Comments
 (0)