diff --git a/src/SDL_utils.c b/src/SDL_utils.c index fea504ceea..66b043796e 100644 --- a/src/SDL_utils.c +++ b/src/SDL_utils.c @@ -26,6 +26,14 @@ #include "joystick/SDL_joystick_c.h" // For SDL_GetGamepadTypeFromVIDPID() +#ifdef SDL_PLATFORM_EMSCRIPTEN +#include + +EMSCRIPTEN_KEEPALIVE void Emscripten_force_free(void *ptr) +{ + free(ptr); // This should NOT be SDL_free() +} +#endif // Common utility functions that aren't in the public API diff --git a/src/SDL_utils_c.h b/src/SDL_utils_c.h index 7138b605e2..266eb09249 100644 --- a/src/SDL_utils_c.h +++ b/src/SDL_utils_c.h @@ -93,4 +93,11 @@ extern char *SDL_CreateDeviceName(Uint16 vendor, Uint16 product, const char *ven // Log what backend a subsystem chose, if a hint was set to do so. Useful for debugging. extern void SDL_DebugLogBackend(const char *subsystem, const char *backend); +#ifdef SDL_PLATFORM_EMSCRIPTEN +// even though we reference the C runtime's free() in other places, it appears +// to be inlined more aggressively in Emscripten 4, so we need a reference to +// it here, too, so inlined Javascript doesn't fail to find it. +extern void Emscripten_force_free(void *ptr); +#endif + #endif // SDL_utils_h_ diff --git a/src/main/emscripten/SDL_sysmain_runapp.c b/src/main/emscripten/SDL_sysmain_runapp.c index 026075a873..0564240ac8 100644 --- a/src/main/emscripten/SDL_sysmain_runapp.c +++ b/src/main/emscripten/SDL_sysmain_runapp.c @@ -28,11 +28,6 @@ EM_JS_DEPS(sdlrunapp, "$dynCall,$stringToNewUTF8"); -// even though we reference the C runtime's free() in other places, it appears -// to be inlined more aggressively in Emscripten 4, so we need a reference to -// it here, too, so the inlined Javascript doesn't fail to find it. -EMSCRIPTEN_KEEPALIVE void force_free(void *ptr) { free(ptr); } // This should NOT be SDL_free() - int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void * reserved) { (void)reserved; @@ -51,8 +46,8 @@ int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void * reserv //console.log("Setting SDL env var '" + key + "' to '" + value + "' ..."); dynCall('iiii', $0, [ckey, cvalue, 1]); } - _force_free(ckey); // these must use free(), not SDL_free()! - _force_free(cvalue); + _Emscripten_force_free(ckey); // these must use free(), not SDL_free()! + _Emscripten_force_free(cvalue); } } }, SDL_setenv_unsafe); diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index 41a172b33a..4d91b7904b 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -1164,13 +1164,17 @@ static void Emscripten_set_drag_event_callbacks(SDL_WindowData *data) target.addEventListener("dragover", SDL3.eventHandlerDropDragover); SDL3.drop_count = 0; - FS.mkdir("/tmp/filedrop"); + + // FS.* functions throw exceptions when there are errors (such as the temp dir already existing), + // but we ignore all of these in a catch handler; you just won't get the drop event if there's a problem. + try { FS.mkdir("/tmp/filedrop"); } catch (e) {} + SDL3.eventHandlerDropDrop = function(event) { event.preventDefault(); if (event.dataTransfer.types.includes("text/plain")) { let plain_text = stringToNewUTF8(event.dataTransfer.getData("text/plain")); _Emscripten_SendDragTextEvent(data, plain_text); - _free(plain_text); + _Emscripten_force_free(plain_text); } else if (event.dataTransfer.types.includes("Files")) { let files_read = 0; const files_to_read = event.dataTransfer.files.length; @@ -1186,13 +1190,16 @@ static void Emscripten_set_drag_event_callbacks(SDL_WindowData *data) const c_fs_filepath = stringToNewUTF8(fs_filepath); const contents_array8 = new Uint8Array(event.target.result); - FS.mkdir(fs_dropdir); - var stream = FS.open(fs_filepath, "w"); - FS.write(stream, contents_array8, 0, contents_array8.length, 0); - FS.close(stream); - - _Emscripten_SendDragFileEvent(data, c_fs_filepath); - _free(c_fs_filepath); + try { + FS.mkdir(fs_dropdir); + var stream = FS.open(fs_filepath, "w"); + FS.write(stream, contents_array8, 0, contents_array8.length, 0); + FS.close(stream); + _Emscripten_SendDragFileEvent(data, c_fs_filepath); + } catch (e) { + // if this threw an exception at any point, we skip this drop event. Sorry! + } + _Emscripten_force_free(c_fs_filepath); onFileRead(); }; file_reader.onerror = function(event) {