Răsfoiți Sursa

emscripten: Fix navigator.getGamepads crash in worker threads

The three EM_JS functions (SDL_GetEmscriptenJoystickVendor,
SDL_GetEmscriptenJoystickProduct, SDL_IsEmscriptenJoystickXInput)
call navigator.getGamepads() which is only available on the main
browser thread. With PROXY_TO_PTHREAD, the joystick callbacks are
dispatched to a worker where the Gamepad API is not available,
causing a TypeError.

Convert these from EM_JS to static functions using
MAIN_THREAD_EM_ASM_INT, which proxies the JavaScript execution to
the main browser thread. This matches the pattern already used by
other navigator.getGamepads() calls in the same file.

(cherry picked from commit be8643f739c3a70f459d6dfb9b7bcfd09bc5fea9)
Christian Semmler 5 zile în urmă
părinte
comite
5be888591c
1 a modificat fișierele cu 49 adăugiri și 40 ștergeri
  1. 49 40
      src/joystick/emscripten/SDL_sysjoystick.c

+ 49 - 40
src/joystick/emscripten/SDL_sysjoystick.c

@@ -35,53 +35,62 @@ static SDL_joylist_item *SDL_joylist = NULL;
 static SDL_joylist_item *SDL_joylist_tail = NULL;
 static int numjoysticks = 0;
 
-EM_JS(int, SDL_GetEmscriptenJoystickVendor, (int device_index), {
+static int SDL_GetEmscriptenJoystickVendor(int device_index)
+{
     // Let's assume that if we're calling these function then the gamepad object definitely exists
-    let gamepad = navigator['getGamepads']()[device_index];
-
-    // Chrome, Edge, Opera: Wireless Controller (STANDARD GAMEPAD Vendor: 054c Product: 09cc)
-    let vendor_str = 'Vendor: ';
-    if (gamepad['id']['indexOf'](vendor_str) > 0) {
-        let vendor_str_index = gamepad['id']['indexOf'](vendor_str) + vendor_str['length'];
-        return parseInt(gamepad['id']['substr'](vendor_str_index, 4), 16);
-    }
-
-    // Firefox, Safari: 046d-c216-Logitech Dual Action (or 46d-c216-Logicool Dual Action)
-    let id_split = gamepad['id']['split']('-');
-    if (id_split['length'] > 1 && !isNaN(parseInt(id_split[0], 16))) {
-        return parseInt(id_split[0], 16);
-    }
-
-    return 0;
-});
+    return MAIN_THREAD_EM_ASM_INT({
+        let gamepad = navigator['getGamepads']()[$0];
+
+        // Chrome, Edge, Opera: Wireless Controller (STANDARD GAMEPAD Vendor: 054c Product: 09cc)
+        let vendor_str = 'Vendor: ';
+        if (gamepad['id']['indexOf'](vendor_str) > 0) {
+            let vendor_str_index = gamepad['id']['indexOf'](vendor_str) + vendor_str['length'];
+            return parseInt(gamepad['id']['substr'](vendor_str_index, 4), 16);
+        }
 
-EM_JS(int, SDL_GetEmscriptenJoystickProduct, (int device_index), {
-    let gamepad = navigator['getGamepads']()[device_index];
+        // Firefox, Safari: 046d-c216-Logitech Dual Action (or 46d-c216-Logicool Dual Action)
+        let id_split = gamepad['id']['split']('-');
+        if (id_split['length'] > 1 && !isNaN(parseInt(id_split[0], 16))) {
+            return parseInt(id_split[0], 16);
+        }
 
-    // Chrome, Edge, Opera: Wireless Controller (STANDARD GAMEPAD Vendor: 054c Product: 09cc)
-    let product_str = 'Product: ';
-    if (gamepad['id']['indexOf'](product_str) > 0) {
-        let product_str_index = gamepad['id']['indexOf'](product_str) + product_str['length'];
-        return parseInt(gamepad['id']['substr'](product_str_index, 4), 16);
-    }
+        return 0;
+    }, device_index);
+}
 
-    // Firefox, Safari: 046d-c216-Logitech Dual Action (or 46d-c216-Logicool Dual Action)
-    let id_split = gamepad['id']['split']('-');
-    if (id_split['length'] > 1 && !isNaN(parseInt(id_split[1], 16))) {
-        return parseInt(id_split[1], 16);
-    }
+static int SDL_GetEmscriptenJoystickProduct(int device_index)
+{
+    return MAIN_THREAD_EM_ASM_INT({
+        let gamepad = navigator['getGamepads']()[$0];
+
+        // Chrome, Edge, Opera: Wireless Controller (STANDARD GAMEPAD Vendor: 054c Product: 09cc)
+        let product_str = 'Product: ';
+        if (gamepad['id']['indexOf'](product_str) > 0) {
+            let product_str_index = gamepad['id']['indexOf'](product_str) + product_str['length'];
+            return parseInt(gamepad['id']['substr'](product_str_index, 4), 16);
+        }
 
-    return 0;
-});
+        // Firefox, Safari: 046d-c216-Logitech Dual Action (or 46d-c216-Logicool Dual Action)
+        let id_split = gamepad['id']['split']('-');
+        if (id_split['length'] > 1 && !isNaN(parseInt(id_split[1], 16))) {
+            return parseInt(id_split[1], 16);
+        }
 
-EM_JS(int, SDL_IsEmscriptenJoystickXInput, (int device_index), {
-    let gamepad = navigator['getGamepads']()[device_index];
+        return 0;
+    }, device_index);
+}
 
-    // Chrome, Edge, Opera: Xbox 360 Controller (XInput STANDARD GAMEPAD)
-    // Firefox: xinput
-    // TODO: Safari
-    return gamepad['id']['toLowerCase']()['indexOf']('xinput') >= 0;
-});
+static int SDL_IsEmscriptenJoystickXInput(int device_index)
+{
+    return MAIN_THREAD_EM_ASM_INT({
+        let gamepad = navigator['getGamepads']()[$0];
+
+        // Chrome, Edge, Opera: Xbox 360 Controller (XInput STANDARD GAMEPAD)
+        // Firefox: xinput
+        // TODO: Safari
+        return gamepad['id']['toLowerCase']()['indexOf']('xinput') >= 0;
+    }, device_index);
+}
 
 static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
 {