diff --git a/ChangeLog.md b/ChangeLog.md index 612d47b20afa4..175e829ad94e7 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -20,6 +20,8 @@ See docs/process.md for more on how version tagging works. 4.0.20 (in development) ----------------------- +- Added new `emscripten_queue_microtask()` API to call the JS `queueMicrotask()` + function. (#25741) 4.0.19 - 11/04/25 ----------------- diff --git a/src/lib/libhtml5.js b/src/lib/libhtml5.js index 0d110367b4fe9..d323dc1e38a92 100644 --- a/src/lib/libhtml5.js +++ b/src/lib/libhtml5.js @@ -2374,6 +2374,15 @@ var LibraryHTML5 = { return requestAnimationFrame(tick); }, + emscripten_queue_microtask__deps: ['$callUserCallback'], + emscripten_queue_microtask: (cb, userData) => { + {{{ runtimeKeepalivePush(); }}} + return queueMicrotask(() => { + {{{ runtimeKeepalivePop(); }}} + callUserCallback(() => {{{ makeDynCall('vp', 'cb') }}}(userData)); + }); + }, + emscripten_get_device_pixel_ratio__proxy: 'sync', emscripten_get_device_pixel_ratio: () => { #if ENVIRONMENT_MAY_BE_NODE || ENVIRONMENT_MAY_BE_SHELL diff --git a/src/lib/libsigs.js b/src/lib/libsigs.js index e2b5f43371de6..ceaa7c207f1e2 100644 --- a/src/lib/libsigs.js +++ b/src/lib/libsigs.js @@ -731,6 +731,7 @@ sigs = { emscripten_promise_race__sig: 'ppp', emscripten_promise_resolve__sig: 'vpip', emscripten_promise_then__sig: 'ppppp', + emscripten_queue_microtask__sig: 'vpp', emscripten_random__sig: 'f', emscripten_request_animation_frame__sig: 'ipp', emscripten_request_animation_frame_loop__sig: 'vpp', diff --git a/system/include/emscripten/html5.h b/system/include/emscripten/html5.h index 6fb863e2f77b9..8bffacd395ca4 100644 --- a/system/include/emscripten/html5.h +++ b/system/include/emscripten/html5.h @@ -466,6 +466,8 @@ int emscripten_request_animation_frame(bool (*cb)(double time, void *userData), void emscripten_cancel_animation_frame(int requestAnimationFrameId); void emscripten_request_animation_frame_loop(bool (*cb)(double time, void *userData), void *userData); +void emscripten_queue_microtask(void (*cb)(void *userData), void *userData); + double emscripten_date_now(void); double emscripten_performance_now(void); diff --git a/test/emscripten_queue_microtask.c b/test/emscripten_queue_microtask.c new file mode 100644 index 0000000000000..1f2ed693b9d74 --- /dev/null +++ b/test/emscripten_queue_microtask.c @@ -0,0 +1,25 @@ +/* + * Copyright 2025 The Emscripten Authors. All rights reserved. + * Emscripten is available under two separate licenses, the MIT license and the + * University of Illinois/NCSA Open Source License. Both these licenses can be + * found in the LICENSE file. + */ + +// Test emscripten_queue_microtask() behavior + +#include +#include +#include +#include + +void cb(void *userData) { + printf("cb\n"); + assert(userData == (void*)42); + emscripten_force_exit(0); +} + +int main() { + emscripten_queue_microtask(cb, (void*)42); + emscripten_exit_with_live_runtime(); + return 99; // We won't reach here, but return non-zero value to guard against refactors that might exit() with this value. +} diff --git a/test/test_browser.py b/test/test_browser.py index 1686fd3cd9c2e..963193e24687a 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -5016,6 +5016,13 @@ def test_emscripten_request_animation_frame_loop(self): def test_request_animation_frame(self): self.btest_exit('test_request_animation_frame.c') + @parameterized({ + '': ([],), + 'proxy_to_pthread': (['-pthread', '-sPROXY_TO_PTHREAD'],), + }) + def test_emscripten_queue_microtask(self, flags): + self.btest_exit('emscripten_queue_microtask.c', cflags=cflags) + @requires_shared_array_buffer def test_emscripten_set_timeout(self): self.btest_exit('emscripten_set_timeout.c', cflags=['-pthread', '-sPROXY_TO_PTHREAD'])