@@ -8,72 +8,10 @@ typedef PyObject *(*TrampolineFunc)(int *success, PyCFunctionWithKeywords func,
88 PyObject * arg1 , PyObject * arg2 ,
99 PyObject * arg3 );
1010
11- EMSCRIPTEN_KEEPALIVE const char _PyEM_trampoline_inner_wasm [] = {
12- #embed "Python/emscripten_trampoline_inner.wasm"
13- };
14-
15- EMSCRIPTEN_KEEPALIVE const int _PyEM_trampoline_inner_wasm_length =
16- sizeof (trampoline_inner_wasm );
17-
18- // Offset of emscripten_count_args_function in _PyRuntimeState. There's a couple
19- // of alternatives:
20- // 1. Just make emscripten_count_args_function a real C global variable instead
21- // of a field of _PyRuntimeState. This would violate our rule against mutable
22- // globals.
23- // 2. #define a preprocessor constant equal to a hard coded number and make a
24- // _Static_assert(offsetof(_PyRuntimeState, emscripten_count_args_function)
25- // == OURCONSTANT) This has the disadvantage that we have to update the hard
26- // coded constant when _PyRuntimeState changes
27- //
28- // So putting the mutable constant in _PyRuntime and using a immutable global to
29- // record the offset so we can access it from JS is probably the best way.
30- EMSCRIPTEN_KEEPALIVE const int _PyEM_EMSCRIPTEN_TRAMPOLINE_OFFSET =
31- offsetof(_PyRuntimeState , emscripten_trampoline );
32-
33- EM_JS (TrampolineFunc , _PyEM_GetTrampolinePtr , (void ) , {
34- return Module ._PyEM_CountArgsPtr ; // initialized below
35- }
36-
37- function getPyEMTrampolinePtr () {
38- // Starting with iOS 18.3.1, WebKit on iOS has an issue with the garbage
39- // collector that breaks the call trampoline. See #130418 and
40- // https://bugs.webkit.org/show_bug.cgi?id=293113 for details.
41- let isIOS = globalThis .navigator && (
42- /iPad |iPhone |iPod /.test (navigator .userAgent ) ||
43- // Starting with iPadOS 13, iPads might send a platform string that looks like a desktop Mac.
44- // To differentiate, we check if the platform is 'MacIntel' (common for Macs and newer iPads)
45- // AND if the device has multi-touch capabilities (navigator.maxTouchPoints > 1)
46- (navigator .platform == = 'MacIntel' && typeof navigator .maxTouchPoints != = 'undefined' && navigator .maxTouchPoints > 1 )
47- );
48- if (isIOS ) {
49- return 0 ;
50- }
51- const code = HEAP8 .subarray (
52- __PyEM_trampoline_inner_wasm ,
53- __PyEM_trampoline_inner_wasm + HEAP32 [__PyEM_trampoline_inner_wasm_length / 4 ]);
54- try {
55- const mod = new WebAssembly .Module (code );
56- const inst = new WebAssembly .Instance (mod , { e : { t : wasmTable } });
57- return addFunction (inst .exports .trampoline_call );
58- } catch (e ) {
59- // If something goes wrong, we'll null out _PyEM_CountFuncParams and fall
60- // back to the JS trampoline.
61- return 0 ;
62- }
63- }
64-
65- addOnPreRun (() = > {
66- const ptr = getPyEMTrampolinePtr ();
67- Module ._PyEM_CountArgsPtr = ptr ;
68- const offset = HEAP32 [__PyEM_EMSCRIPTEN_TRAMPOLINE_OFFSET / 4 ];
69- HEAP32 [(__PyRuntime + offset ) / 4 ] = ptr ;
70- });
71- );
7211
7312void
7413_Py_EmscriptenTrampoline_Init (_PyRuntimeState * runtime )
7514{
76- runtime -> emscripten_trampoline = _PyEM_GetTrampolinePtr ();
7715}
7816
7917// We have to be careful to work correctly with memory snapshots. Even if we are
@@ -84,9 +22,17 @@ _Py_EmscriptenTrampoline_Init(_PyRuntimeState *runtime)
8422/**
8523 * Backwards compatible trampoline works with all JS runtimes
8624 */
87- EM_JS (PyObject * , _PyEM_TrampolineCall_JS , (PyCFunctionWithKeywords func , PyObject * arg1 , PyObject * arg2 , PyObject * arg3 ), {
25+ EM_JS (PyObject * , _PyEM_TrampolineCall_inner , (int * success , PyCFunctionWithKeywords func , PyObject * arg1 , PyObject * arg2 , PyObject * arg3 ), {
8826 return wasmTable .get (func )(arg1 , arg2 , arg3 );
89- });
27+ }
28+ try {
29+ const trampolineModule = getWasmTrampolineModule ();
30+ const trampolineInstance = new WebAssembly .Instance (trampolineModule , {
31+ env : { __indirect_function_table : wasmTable , memory : wasmMemory },
32+ });
33+ _PyEM_TrampolineCall_inner = trampolineInstance .exports .trampoline_call ;
34+ } catch (e ) {}
35+ );
9036
9137typedef PyObject * (* zero_arg )(void );
9238typedef PyObject * (* one_arg )(PyObject * );
@@ -99,12 +45,8 @@ _PyEM_TrampolineCall(PyCFunctionWithKeywords func,
9945 PyObject * args ,
10046 PyObject * kw )
10147{
102- TrampolineFunc trampoline = _PyRuntime .emscripten_trampoline ;
103- if (trampoline == 0 ) {
104- return _PyEM_TrampolineCall_JS (func , self , args , kw );
105- }
106- int success = 0 ;
107- PyObject * result = trampoline (& success , func , self , args , kw );
48+ int success = 1 ;
49+ PyObject * result = _PyEM_TrampolineCall_inner (& success , func , self , args , kw );
10850 if (!success ) {
10951 PyErr_SetString (PyExc_SystemError , "Handler takes too many arguments" );
11052 }
0 commit comments