mirror of
				https://github.com/python/cpython.git
				synced 2025-10-26 03:04:41 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			92 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			92 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #if defined(PY_CALL_TRAMPOLINE)
 | |
| 
 | |
| #include <emscripten.h>             // EM_JS
 | |
| #include <Python.h>
 | |
| #include "pycore_runtime.h"         // _PyRuntime
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * This is the GoogleChromeLabs approved way to feature detect type-reflection:
 | |
|  * https://github.com/GoogleChromeLabs/wasm-feature-detect/blob/main/src/detectors/type-reflection/index.js
 | |
|  */
 | |
| EM_JS(int, _PyEM_detect_type_reflection, (), {
 | |
|     if (!("Function" in WebAssembly)) {
 | |
|         return false;
 | |
|     }
 | |
|     if (WebAssembly.Function.type) {
 | |
|         // Node v20
 | |
|         Module.PyEM_CountArgs = (func) => WebAssembly.Function.type(wasmTable.get(func)).parameters.length;
 | |
|     } else {
 | |
|         // Node >= 22, v8-based browsers
 | |
|         Module.PyEM_CountArgs = (func) => wasmTable.get(func).type().parameters.length;
 | |
|     }
 | |
|     return true;
 | |
| });
 | |
| 
 | |
| void
 | |
| _Py_EmscriptenTrampoline_Init(_PyRuntimeState *runtime)
 | |
| {
 | |
|     runtime->wasm_type_reflection_available = _PyEM_detect_type_reflection();
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Backwards compatible trampoline works with all JS runtimes
 | |
|  */
 | |
| EM_JS(PyObject*,
 | |
| _PyEM_TrampolineCall_JavaScript, (PyCFunctionWithKeywords func,
 | |
|                                   PyObject *arg1,
 | |
|                                   PyObject *arg2,
 | |
|                                   PyObject *arg3),
 | |
| {
 | |
|     return wasmTable.get(func)(arg1, arg2, arg3);
 | |
| }
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * In runtimes with WebAssembly type reflection, count the number of parameters
 | |
|  * and cast to the appropriate signature
 | |
|  */
 | |
| EM_JS(int, _PyEM_CountFuncParams, (PyCFunctionWithKeywords func),
 | |
| {
 | |
|     let n = _PyEM_CountFuncParams.cache.get(func);
 | |
| 
 | |
|     if (n !== undefined) {
 | |
|         return n;
 | |
|     }
 | |
|     n = Module.PyEM_CountArgs(func);
 | |
|     _PyEM_CountFuncParams.cache.set(func, n);
 | |
|     return n;
 | |
| }
 | |
| _PyEM_CountFuncParams.cache = new Map();
 | |
| )
 | |
| 
 | |
| 
 | |
| typedef PyObject* (*zero_arg)(void);
 | |
| typedef PyObject* (*one_arg)(PyObject*);
 | |
| typedef PyObject* (*two_arg)(PyObject*, PyObject*);
 | |
| typedef PyObject* (*three_arg)(PyObject*, PyObject*, PyObject*);
 | |
| 
 | |
| 
 | |
| PyObject*
 | |
| _PyEM_TrampolineCall_Reflection(PyCFunctionWithKeywords func,
 | |
|                                 PyObject* self,
 | |
|                                 PyObject* args,
 | |
|                                 PyObject* kw)
 | |
| {
 | |
|     switch (_PyEM_CountFuncParams(func)) {
 | |
|         case 0:
 | |
|             return ((zero_arg)func)();
 | |
|         case 1:
 | |
|             return ((one_arg)func)(self);
 | |
|         case 2:
 | |
|             return ((two_arg)func)(self, args);
 | |
|         case 3:
 | |
|             return ((three_arg)func)(self, args, kw);
 | |
|         default:
 | |
|             PyErr_SetString(PyExc_SystemError,
 | |
|                             "Handler takes too many arguments");
 | |
|             return NULL;
 | |
|     }
 | |
| }
 | |
| 
 | |
| #endif
 | 
