Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
148 commits
Select commit Hold shift + click to select a range
0a58ce7
WIP: await promise code from sync c
hedwigz Dec 1, 2024
36207f3
rebaseline sigs
hedwigz Dec 1, 2024
88341ba
protect against misuse
hedwigz Dec 6, 2024
c153f10
capture promise returned value
hedwigz Dec 6, 2024
2a01546
test promise error handled
hedwigz Dec 6, 2024
c471c05
doc
hedwigz Dec 6, 2024
9b9a08b
2024
hedwigz Dec 6, 2024
07f9d26
rm
hedwigz Dec 6, 2024
f970811
CR
hedwigz Dec 14, 2024
44995e2
simplified
hedwigz Dec 17, 2024
1d5c680
Update system/lib/pthread/proxying.c
hedwigz Dec 18, 2024
9814fa4
CR
hedwigz Dec 18, 2024
c1c9862
Merge branch 'inline-javascript-sync-awaitable-promises' of github.co…
hedwigz Dec 18, 2024
b63534e
Add test for `GLOBAL_BASE` and `SIDE_MODULE` error message. NFC (#23029)
sbc100 Dec 2, 2024
3a79133
Cleanup library_sdl.js. NFC (#23030)
sbc100 Dec 2, 2024
ddd6317
[NFC] Fix typos discovered by codespell in the tools directory (#23039)
cclauss Dec 2, 2024
a50e926
Trying to create a directory in a file should return ENOTDIR not EPER…
hoodmane Dec 2, 2024
81bd3ce
Support cmake LINK_LIBRARY:WHOLE_ARCHIVE (#22975)
eagleoflqj Dec 2, 2024
9536cc8
Rebaseline codesize expectations. NFC
sbc100 Dec 3, 2024
6329052
[wasm64] Remove table64 lowering by default (#23051)
sbc100 Dec 3, 2024
e03a18c
Rebaseline codesize expectations. NFC
sbc100 Dec 3, 2024
cccf87b
Refactor lookupPath to avoid recursion. NFC (#23017)
hoodmane Dec 3, 2024
84841ad
[NFC] Fix a typo from #23051 (#23062)
kripken Dec 3, 2024
ea39818
Rebaseline codesize expectations. NFC
sbc100 Dec 3, 2024
86b0e1b
Remove unnecessary forced exports. NFC (#23060)
sbc100 Dec 3, 2024
7ec8611
Add wcsftime from musl. NFC (#23061)
sbc100 Dec 3, 2024
5f17fe8
Convert asyncLoad from callbacks to promise. NFC (#23065)
sbc100 Dec 4, 2024
d53907f
Unify two separate clock_getres and clock_gettime implementations. NF…
sbc100 Dec 4, 2024
1d7fe55
Parameterize test_webgl_offscreen_framebuffer_state_restoration. NFC …
sbc100 Dec 4, 2024
941b0f9
Fix false positive writability check on cache directory (#23049)
sbc100 Dec 4, 2024
e254271
Remove redundant call to `.then()` on `Promise.resolve()`. NFC (#23067)
sbc100 Dec 4, 2024
c0e6d8e
Restore changelog entry mistakenly removed in #23017. NFC (#23071)
kleisauke Dec 4, 2024
2e54fd4
Add nodefs readdir handling for directories that contain exotic entri…
hoodmane Dec 4, 2024
c449557
Handle trailing % in strftime (#23045)
hoodmane Dec 4, 2024
160c97f
Ruff rules for comprehensions, performance, and simplicity (#23040)
cclauss Dec 4, 2024
2337a41
[tsgen] Ignore checking library types when generating TS definitions.…
brendandahl Dec 4, 2024
109ed8d
[tsgen] Make commonjs module output compatible with tsc. (#22988)
brendandahl Dec 4, 2024
8aa4f76
JS file system: distinguish between atime, mtime, and ctime (#22998)
hoodmane Dec 4, 2024
f03b8da
Use encodeURIComponent in browser_reporting. NFC (#23075)
sbc100 Dec 4, 2024
5bb9aeb
Rebaseline codesize expectations. NFC
sbc100 Dec 4, 2024
4c547eb
Convert instantiateAsync form callbacks to promises. NFC (#23066)
sbc100 Dec 4, 2024
6004495
Make readdir on /proc/self/fd work (#23073)
hoodmane Dec 5, 2024
d79b117
Rebaseline codesize expectations. NFC
sbc100 Dec 5, 2024
cc6a66b
Move changelog entry from #22998. NFC (#23079)
sbc100 Dec 5, 2024
6adccb9
Bump minimum supported chrome version from 32 to 33 (#23077)
sbc100 Dec 5, 2024
9c6d6b4
Cleanup test_remove. NFC (#23081)
sbc100 Dec 5, 2024
855640b
When opening broken symlink with O_CREAT, create file at target (#23002)
hoodmane Dec 5, 2024
d28128d
Fix renaming a file on top of an existing file in memfs and nodefs (#…
hoodmane Dec 5, 2024
c5f61fa
Remove path.normalize from node file reading code. NFC (#23087)
sbc100 Dec 5, 2024
315b487
Optimize library_nodepath.js. NFC (#23086)
sbc100 Dec 5, 2024
87915c7
Micro-optimize memfs readdir. NFC (#23076)
sbc100 Dec 5, 2024
0c8657b
[test] Avoid seeding random number generators with time. NFC (#23050)
sbc100 Dec 5, 2024
a242412
Fix path resolution for symlinks (#23072)
hoodmane Dec 6, 2024
3e2141a
Disable test_fs_enotdir on Windows (#23095)
dschuff Dec 6, 2024
b5d866c
PEP 621: Migrate .coveragerc and .mypy.ini into pyproject.toml (#23089)
cclauss Dec 6, 2024
b7e3d54
Add emscripten_builtin_realloc (#23091)
sbc100 Dec 6, 2024
0b2ba3f
Cleanup some filesystem tests. NFC (#23088)
sbc100 Dec 6, 2024
f583ce0
Skip symlink tests on Windows (#23097)
dschuff Dec 6, 2024
9dfed24
Rebaseline codesize expectations. NFC
sbc100 Dec 6, 2024
bdd6649
Disable new clang warning in libicu (#23099)
dschuff Dec 6, 2024
ae49149
Cleanup test_offset_converter. NFC (#23098)
sbc100 Dec 7, 2024
57054fc
Simplify asyncLoad. NFC (#23100)
sbc100 Dec 7, 2024
5d8a411
Fix for flakiness in socket tests. NFC (#23103)
sbc100 Dec 7, 2024
f53fb9f
Python lint: Use ruff instead of flake8. NFC (#23085)
cclauss Dec 9, 2024
69cf863
Error on `--emrun` with `EXIT_RUNTIME=0` (#23096)
sbc100 Dec 9, 2024
c943dd3
Cleanup test_modularize_init_error. NFC (#23105)
sbc100 Dec 9, 2024
188eff5
Refactor startup code to avoid duplication between wasm workers and p…
sbc100 Dec 9, 2024
07a8870
Initial usage of async/await in JS library code. NFC (#23104)
sbc100 Dec 9, 2024
89e869e
Wrap runDependencyWatcher in `#if ASSERTIONS`. NFC (#23111)
sbc100 Dec 9, 2024
c929af8
Remove OFFSCREEN_FRAMEBUFFER_FORBID_VAO_PATH. NFC (#23056)
sbc100 Dec 10, 2024
1a95597
mark test_fs_dev_random as crossplatform (#23116)
dschuff Dec 10, 2024
6701fa2
[test] Remove (broken) EMTEST_BROWSER_PORT test setting (#23113)
sbc100 Dec 10, 2024
5ba5d74
Rebaseline codesize expectations. NFC
sbc100 Dec 10, 2024
3cd60b2
Use async/await instead of promises for wasm loading. NFC (#23068)
sbc100 Dec 10, 2024
cac7b09
Rebaseline codesize expectations. NFC
sbc100 Dec 10, 2024
dabaa31
[emmalloc] Fix verbose output (#23069)
kleisauke Dec 10, 2024
7d68c2f
Default to -mno-bulk-memory-opt (#23126)
sbc100 Dec 10, 2024
4fb76c0
Add some slack to test_extern_prepost. NFC (#23127)
sbc100 Dec 11, 2024
0bd899b
Remove basic_string<unsigned char> from embind (#23070)
aheejin Dec 11, 2024
548fd87
Fix UB in test_unistd_write_broken_link (#23125)
dschuff Dec 11, 2024
ff528bb
Rebaseline codesize expectations. NFC
sbc100 Dec 12, 2024
685ad3c
[docs] Update docs on closure to match current behavior. (#23142)
brendandahl Dec 12, 2024
88d7180
Rebaseline test_INCOMING_MODULE_JS_API. NFC (#23145)
sbc100 Dec 12, 2024
88b9f03
Simplify jsmath.c. NFC (#23144)
sbc100 Dec 12, 2024
f342e51
[NFC] Grammar fixes in webaudio comments (#23141)
slowriot Dec 12, 2024
8852761
[test] Remove EMSCRIPTEN_KEEPALIVE from _ReportResult. NFC (#23119)
sbc100 Dec 12, 2024
1aea351
[AUDIO_WORKLET] Fix when compiling with STRICT (#23130)
cwoffenden Dec 12, 2024
872488d
Remove unnecessary functions from jsmath.c. NFC (#23143)
sbc100 Dec 13, 2024
fff332b
Remove polyfills for Fetch and Object.assign (#23118)
sbc100 Dec 13, 2024
972c67e
Use `em_math.h` functions in `jsmath.c` (#23147)
sbc100 Dec 13, 2024
2a52a0b
Use async/await for internal readAsync function. NFC (#23120)
sbc100 Dec 13, 2024
596f2c3
Rebaseline test_small_js_flags. NFC (#23156)
sbc100 Dec 13, 2024
f9abcba
Remove rint from jsmath library. NFC (#23148)
sbc100 Dec 13, 2024
f6ab157
JS optimizer: Fix scoping issues with non-defined functions (#23159)
kripken Dec 13, 2024
f655151
Remove `target_environment_may_be` helper. NFC (#23160)
sbc100 Dec 14, 2024
6c4dec6
Mark 3.1.74 as released (#23164)
emscripten-bot Dec 14, 2024
1ea2e49
Enable ruff check E303 (#23155)
cclauss Dec 14, 2024
d871458
Allow avxintrin.h to be used by C compiler (#22850)
jkl1337 Dec 16, 2024
7e604e7
Unify code for setting up nodefs tests. NFC (#23167)
sbc100 Dec 16, 2024
c408029
Use assert in test_unlink.cpp NFC (#23174)
hoodmane Dec 16, 2024
fce707c
Remove `createRequire` in favor of ES6 `import` (#23169)
sbc100 Dec 16, 2024
bc78e00
[NFC] Give some JS optimizer tests nice names (#23161)
kripken Dec 16, 2024
06e2426
Remove unnecessary checks on the existence of `fetch`. NFC (#23166)
sbc100 Dec 16, 2024
efea9d0
[NFC] Remove confusing bullet point in changelog (#23181)
kripken Dec 16, 2024
745b35d
Rebaseline codesize expectations. NFC
sbc100 Dec 16, 2024
f61e538
Fix some WasmFS APIs for BIGINT support (#23183)
dschuff Dec 16, 2024
c161a59
Use CI skip on release-marking PRs (#23165)
dschuff Dec 16, 2024
010c5bf
Fix some source map and name section behavior (#23182)
dschuff Dec 16, 2024
b81bba5
Don't inject assertions onto the ready promise (#23176)
sbc100 Dec 16, 2024
cc4efb4
[test] Remove also_with_wasmfs_js. NFC (#23185)
sbc100 Dec 16, 2024
6046fec
More use of async/await keywords in JS library code. NFC (#23150)
sbc100 Dec 16, 2024
9852ae8
Elide `findWasmBinary` in `-sSINGLE_FILE` mode. NFC (#23186)
sbc100 Dec 17, 2024
954a450
Add maintenance script to automate test rebaselining. NFC (#23162)
sbc100 Dec 17, 2024
aa13bd4
Automatic rebaseline of codesize expectations. NFC (#23188)
sbc100 Dec 17, 2024
6a959c6
Remove extra newline in rebaseline_tests.py. NFC (#23189)
sbc100 Dec 17, 2024
b80de20
Parameterize test_legalize_js_ffi (#23190)
dschuff Dec 17, 2024
e974058
rebaseline_tests.py: Add --new-branch and --clear-cache. NFC (#23192)
sbc100 Dec 17, 2024
7a96ebc
Don't normalize path in PATH.basename() (#23180)
hoodmane Dec 17, 2024
2941b58
Automatic rebaseline of codesize expectations. NFC (#23199)
sbc100 Dec 17, 2024
77a9a66
Bump Binaryen to 120 (#23197)
aheejin Dec 17, 2024
f000f76
[test] Add new decorators for running tests under different FS backen…
sbc100 Dec 17, 2024
b0faf91
Remove unnecessary `shouldRunNow` global variable. NFC (#23191)
sbc100 Dec 17, 2024
a716fcb
WasmFS: Enable wasm64.test_unistd_access under wasmfs (#23203)
sbc100 Dec 17, 2024
b0151e0
Remove the need for `runCaller`. NFC (#23193)
sbc100 Dec 17, 2024
6ca0bf4
CI: Fix indentation in tag-release.yml. NFC (#23202)
sbc100 Dec 17, 2024
0dca6bf
Remove pinned version of lxml from requirements-dev.txt. NFC (#23204)
sbc100 Dec 17, 2024
bb5f723
Automatic rebaseline of codesize expectations. NFC
sbc100 Dec 17, 2024
23247db
CI: Check that test expectations are up-to-date (#23201)
sbc100 Dec 17, 2024
6dcefb9
Run `npm audit fix` to update `package-lock.json`. NFC (#23206)
sbc100 Dec 17, 2024
3061363
Remove old warning about firefox bug (#23209)
sbc100 Dec 18, 2024
ef51061
Bump Binaryen version to 121 (#23207)
aheejin Dec 18, 2024
49c52d8
Avoid excessive variable reuse in `modularize` function. NFC (#23208)
sbc100 Dec 18, 2024
950fed1
Fix `mkdir("a/b/..")` should return `EEXIST` (#23136)
hoodmane Dec 18, 2024
ffbad25
Add codesize test for EXPORT_ES6. NFC (#23215)
sbc100 Dec 18, 2024
e3dc0be
WIP: await promise code from sync c
hedwigz Dec 1, 2024
b7d9bcc
rebaseline sigs
hedwigz Dec 1, 2024
d870176
protect against misuse
hedwigz Dec 6, 2024
74a9647
capture promise returned value
hedwigz Dec 6, 2024
5bb54a0
test promise error handled
hedwigz Dec 6, 2024
7ccf45c
doc
hedwigz Dec 6, 2024
9588130
2024
hedwigz Dec 6, 2024
823bb78
rm
hedwigz Dec 6, 2024
6cafb26
CR
hedwigz Dec 14, 2024
aa7e419
simplified
hedwigz Dec 17, 2024
0686f66
CR
hedwigz Dec 18, 2024
8440022
Remove unnecessary forced exports. NFC (#23060)
sbc100 Dec 3, 2024
372bee3
More use of async/await keywords in JS library code. NFC (#23150)
sbc100 Dec 16, 2024
5aef76b
Merge branch 'inline-javascript-sync-awaitable-promises' of github.co…
hedwigz Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/jsifier.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ function(${args}) {
return `
${async_}function(${args}) {
if (ENVIRONMENT_IS_PTHREAD)
return ${proxyFunc}(${proxiedFunctionTable.length}, 0, ${+sync}${args ? ', ' : ''}${args});
return ${proxyFunc}(${proxiedFunctionTable.length}, 0, ${+sync}, 0${args ? ', ' : ''}${args});
${body}
}\n`;
});
Expand Down
17 changes: 15 additions & 2 deletions src/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -1631,7 +1631,7 @@ addToLibrary({
'$proxyToMainThread'
#endif
],
$runMainThreadEmAsm: (emAsmAddr, sigPtr, argbuf, sync) => {
$runMainThreadEmAsm: (emAsmAddr, sigPtr, argbuf, sync, asnycAwait) => {
var args = readEmAsmArgs(sigPtr, argbuf);
#if PTHREADS
if (ENVIRONMENT_IS_PTHREAD) {
Expand All @@ -1644,7 +1644,7 @@ addToLibrary({
// of using __proxy. (And dor simplicity, do the same in the sync
// case as well, even though it's not strictly necessary, to keep the two
// code paths as similar as possible on both sides.)
return proxyToMainThread(0, emAsmAddr, sync, ...args);
return proxyToMainThread(0, emAsmAddr, sync, asnycAwait, ...args);
}
#endif
#if ASSERTIONS
Expand All @@ -1655,6 +1655,19 @@ addToLibrary({
emscripten_asm_const_int_sync_on_main_thread__deps: ['$runMainThreadEmAsm'],
emscripten_asm_const_int_sync_on_main_thread: (emAsmAddr, sigPtr, argbuf) => runMainThreadEmAsm(emAsmAddr, sigPtr, argbuf, 1),

emscripten_asm_const_int_await_on_main_thread__deps: ['$runMainThreadEmAsm'],
emscripten_asm_const_int_await_on_main_thread: (emAsmAddr, sigPtr, argbuf) => {
#if PTHREADS
if (ENVIRONMENT_IS_PTHREAD) {
return runMainThreadEmAsm(emAsmAddr, sigPtr, argbuf, /*sync=*/1, /*asyncAwait=*/1);
}
#endif
#if ASSERTIONS
assert((typeof ENVIRONMENT_IS_PTHREAD !== 'undefined' && ENVIRONMENT_IS_PTHREAD), "emscripten_asm_const_int_await_on_main_thread is not available on the main thread");
#endif
return runMainThreadEmAsm(emAsmAddr, sigPtr, argbuf, /*sync*/1, /*asyncAwait=*/1);
},

emscripten_asm_const_ptr_sync_on_main_thread__deps: ['$runMainThreadEmAsm'],
emscripten_asm_const_ptr_sync_on_main_thread: (emAsmAddr, sigPtr, argbuf) => runMainThreadEmAsm(emAsmAddr, sigPtr, argbuf, 1),

Expand Down
31 changes: 27 additions & 4 deletions src/library_pthread.js
Original file line number Diff line number Diff line change
Expand Up @@ -893,9 +893,9 @@ var LibraryPThread = {
$proxyToMainThreadPtr: (...args) => BigInt(proxyToMainThread(...args)),
#endif

$proxyToMainThread__deps: ['$stackSave', '$stackRestore', '$stackAlloc', '_emscripten_run_on_main_thread_js', ...i53ConversionDeps],
$proxyToMainThread__deps: ['$stackSave', '$stackRestore', '$stackAlloc', '_emscripten_run_on_main_thread_js', '_emscripten_await_on_main_thread_js', ...i53ConversionDeps],
$proxyToMainThread__docs: '/** @type{function(number, (number|boolean), ...number)} */',
$proxyToMainThread: (funcIndex, emAsmAddr, sync, ...callArgs) => {
$proxyToMainThread: (funcIndex, emAsmAddr, sync, asyncAwait, ...callArgs) => {
// EM_ASM proxying is done by passing a pointer to the address of the EM_ASM
// content as `emAsmAddr`. JS library proxying is done by passing an index
// into `proxiedJSCallArgs` as `funcIndex`. If `emAsmAddr` is non-zero then
Expand Down Expand Up @@ -933,7 +933,12 @@ var LibraryPThread = {
HEAPF64[b + i] = arg;
#endif
}
var rtn = __emscripten_run_on_main_thread_js(funcIndex, emAsmAddr, serializedNumCallArgs, args, sync);
var rtn;
if (asyncAwait) {
rtn = __emscripten_await_on_main_thread_js(funcIndex, emAsmAddr, serializedNumCallArgs, args);
} else {
rtn = __emscripten_run_on_main_thread_js(funcIndex, emAsmAddr, serializedNumCallArgs, args, sync);
}
stackRestore(sp);
return rtn;
},
Expand All @@ -944,7 +949,7 @@ var LibraryPThread = {
_emscripten_receive_on_main_thread_js__deps: [
'$proxyToMainThread',
'$proxiedJSCallArgs'],
_emscripten_receive_on_main_thread_js: (funcIndex, emAsmAddr, callingThread, numCallArgs, args) => {
_emscripten_receive_on_main_thread_js: (funcIndex, emAsmAddr, callingThread, numCallArgs, args, promiseCtx) => {
// Sometimes we need to backproxy events to the calling thread (e.g.
// HTML5 DOM events handlers such as
// emscripten_set_mousemove_callback()), so keep track in a globally
Expand Down Expand Up @@ -983,6 +988,24 @@ var LibraryPThread = {
PThread.currentProxiedOperationCallerThread = callingThread;
var rtn = func(...proxiedJSCallArgs);
PThread.currentProxiedOperationCallerThread = 0;
if (promiseCtx) {
#if ASSERTIONS
assert(!!rtn.then, 'Return value of proxied function expected to be a Promise but got' + rtn);
#endif
rtn.then(res => {
#if MEMORY64
// In memory64 mode some proxied functions return bigint/pointer but
// our return type is i53/double.
if (typeof res == "bigint") {
res = bigintToI53Checked(res);
}
#endif
__emscripten_proxy_promise_finish(promiseCtx, res);
}).catch(err => {
__emscripten_proxy_promise_finish(promiseCtx, err);
});
return;
}
#if MEMORY64
// In memory64 mode some proxied functions return bigint/pointer but
// our return type is i53/double.
Expand Down
3 changes: 2 additions & 1 deletion src/library_sigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ sigs = {
_emscripten_notify_mailbox_postmessage__sig: 'vpp',
_emscripten_push_main_loop_blocker__sig: 'vppp',
_emscripten_push_uncounted_main_loop_blocker__sig: 'vppp',
_emscripten_receive_on_main_thread_js__sig: 'dippip',
_emscripten_receive_on_main_thread_js__sig: 'dippipp',
_emscripten_runtime_keepalive_clear__sig: 'v',
_emscripten_set_offscreencanvas_size__sig: 'ipii',
_emscripten_system__sig: 'ip',
Expand Down Expand Up @@ -569,6 +569,7 @@ sigs = {
emscripten_asm_const_double__sig: 'dppp',
emscripten_asm_const_double_sync_on_main_thread__sig: 'dppp',
emscripten_asm_const_int__sig: 'ippp',
emscripten_asm_const_int_await_on_main_thread__sig: 'ippp',
emscripten_asm_const_int_sync_on_main_thread__sig: 'ippp',
emscripten_asm_const_ptr__sig: 'pppp',
emscripten_asm_const_ptr_sync_on_main_thread__sig: 'pppp',
Expand Down
11 changes: 11 additions & 0 deletions system/include/emscripten/em_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ __attribute__((nothrow))
int emscripten_asm_const_int_sync_on_main_thread(
const char* code, const char* arg_sigs, ...);
__attribute__((nothrow))
int emscripten_asm_const_int_await_on_main_thread(
const char* code, const char* arg_sigs, ...);
__attribute__((nothrow))
void* emscripten_asm_const_ptr_sync_on_main_thread(
const char* code, const char* arg_sigs, ...);
__attribute__((nothrow))
Expand All @@ -51,6 +54,7 @@ void emscripten_asm_const_async_on_main_thread(
#define EM_ASM_PTR(...) EM_ASM_ERROR
#define EM_ASM_DOUBLE(...) EM_ASM_ERROR
#define MAIN_THREAD_EM_ASM(...) EM_ASM_ERROR
#define MAIN_THREAD_EM_ASM_AWAIT(...) EM_ASM_ERROR
#define MAIN_THREAD_EM_ASM_INT(...) EM_ASM_ERROR
#define MAIN_THREAD_EM_ASM_PTR(...) EM_ASM_ERROR
#define MAIN_THREAD_EM_ASM_DOUBLE(...) EM_ASM_ERROR
Expand Down Expand Up @@ -250,6 +254,13 @@ const char __em_asm_sig_builder<__em_asm_type_tuple<Args...> >::buffer[] = { __e
// functions.
#define MAIN_THREAD_EM_ASM(code, ...) ((void)emscripten_asm_const_int_sync_on_main_thread(CODE_EXPR(#code) _EM_ASM_PREP_ARGS(__VA_ARGS__)))

// Runs the given Javascript code on the main browser thread.
// It must be called from a non-main thread.
// The code must return a promise, and this function will wait for the promise
// to resolve or reject, essentially blocking the calling thread until then.
// In either case the function will return an integer, which is the result of the promise.
#define MAIN_THREAD_EM_ASM_AWAIT(code, ...) emscripten_asm_const_int_await_on_main_thread(CODE_EXPR(#code) _EM_ASM_PREP_ARGS(__VA_ARGS__))

// Runs the given JavaScript code synchronously on the main browser thread, and
// returns an integer back.
// The same considerations apply as with MAIN_THREAD_EM_ASM().
Expand Down
67 changes: 56 additions & 11 deletions system/lib/pthread/proxying.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include "em_task_queue.h"
#include "thread_mailbox.h"
Expand All @@ -35,6 +36,20 @@ static em_proxying_queue system_proxying_queue = {
.capacity = 0,
};

typedef struct proxied_js_func_t {
int funcIndex;
void* emAsmAddr;
pthread_t callingThread;
int numArgs;
double* argBuffer;
double result;
bool owned;
// Only used when when the underlying JS function is async and ctx need to be
// resolved on promise end.
// should be NULL if the function is sync.
em_proxying_ctx * ctx;
} proxied_js_func_t;

em_proxying_queue* emscripten_proxy_get_system_queue(void) {
return &system_proxying_queue;
}
Expand Down Expand Up @@ -397,6 +412,14 @@ static void call_then_finish_task(em_proxying_ctx* ctx, void* arg) {
emscripten_proxy_finish(ctx);
}

static void call_proxied_js_task_with_ctx(em_proxying_ctx* ctx, void* arg) {
// Stash the context on the proxied_js_func_t argument.
task* t = arg;
proxied_js_func_t* p = t->arg;
p->ctx = ctx;
t->func(t->arg);
}

int emscripten_proxy_sync(em_proxying_queue* q,
pthread_t target_thread,
void (*func)(void*),
Expand Down Expand Up @@ -583,20 +606,10 @@ em_promise_t emscripten_proxy_promise(em_proxying_queue* q,
&block->promise_ctx);
}

typedef struct proxied_js_func_t {
int funcIndex;
void* emAsmAddr;
pthread_t callingThread;
int numArgs;
double* argBuffer;
double result;
bool owned;
} proxied_js_func_t;

static void run_js_func(void* arg) {
proxied_js_func_t* f = (proxied_js_func_t*)arg;
f->result = _emscripten_receive_on_main_thread_js(
f->funcIndex, f->emAsmAddr, f->callingThread, f->numArgs, f->argBuffer);
f->funcIndex, f->emAsmAddr, f->callingThread, f->numArgs, f->argBuffer, f->ctx);
if (f->owned) {
free(f->argBuffer);
free(f);
Expand All @@ -615,6 +628,7 @@ double _emscripten_run_on_main_thread_js(int func_index,
.numArgs = num_args,
.argBuffer = buffer,
.owned = false,
.ctx = NULL,
};

em_proxying_queue* q = emscripten_proxy_get_system_queue();
Expand Down Expand Up @@ -642,3 +656,34 @@ double _emscripten_run_on_main_thread_js(int func_index,
}
return 0;
}

double _emscripten_await_on_main_thread_js(int func_index,
void* em_asm_addr,
int num_args,
double* buffer) {
em_proxying_queue* q = emscripten_proxy_get_system_queue();
pthread_t target = emscripten_main_runtime_thread_id();

proxied_js_func_t f = {
.funcIndex = func_index,
.emAsmAddr = em_asm_addr,
.callingThread = pthread_self(),
.numArgs = num_args,
.argBuffer = buffer,
.owned = false,
};
task t = {.func = run_js_func, .arg = &f};

if (!emscripten_proxy_sync_with_ctx(q, target, call_proxied_js_task_with_ctx, &t)) {
assert(false && "emscripten_proxy_sync_with_ctx failed");
return 0;
}
return f.result;
}

void _emscripten_proxy_promise_finish(em_proxying_ctx* ctx, void* res) {
task* t = (task*)ctx->arg;
proxied_js_func_t* func = (proxied_js_func_t*)t->arg;
func->result = (double)(intptr_t)res;
emscripten_proxy_finish(ctx);
}
2 changes: 1 addition & 1 deletion system/lib/pthread/threading_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ int __pthread_create_js(struct __pthread *thread, const pthread_attr_t *attr, vo
int _emscripten_default_pthread_stack_size();
void __set_thread_state(pthread_t ptr, int is_main, int is_runtime, int can_block);

double _emscripten_receive_on_main_thread_js(int funcIndex, void* emAsmAddr, pthread_t callingThread, int numCallArgs, double* args);
double _emscripten_receive_on_main_thread_js(int funcIndex, void* emAsmAddr, pthread_t callingThread, int numCallArgs, double* args, void *ctx);

// Return non-zero if the calling thread supports Atomic.wait (For example
// if called from the main browser thread, this function will return zero
Expand Down
25 changes: 25 additions & 0 deletions test/core/test_main_thread_async_em_asm_await.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2024 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.

#include <emscripten.h>
#include <stdio.h>

int main()
{
printf("Before MAIN_THREAD_EM_ASM_AWAIT\n");
int res = MAIN_THREAD_EM_ASM_AWAIT({
out('Inside MAIN_THREAD_EM_ASM_AWAIT: ' + $0 + ' ' + $1);
const asyncOp = new Promise((resolve,reject) => {
setTimeout(() => {
out('Inside asyncOp');
resolve(2);
}, 1000);
});
return asyncOp;
}, 42, 3.5);
printf("After MAIN_THREAD_EM_ASM_AWAIT\n");
printf("result: %d\n", res);
return 0;
}
5 changes: 5 additions & 0 deletions test/core/test_main_thread_async_em_asm_await.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Before MAIN_THREAD_EM_ASM_AWAIT
Inside MAIN_THREAD_EM_ASM_AWAIT: 42 3.5
Inside asyncOp
After MAIN_THREAD_EM_ASM_AWAIT
result: 2
34 changes: 34 additions & 0 deletions test/core/test_main_thread_async_em_asm_await_reject.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2024 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.

#include <emscripten.h>
#include <stdio.h>
#include <pthread.h>

int main()
{
// start new thread
pthread_t thread;
pthread_create(&thread, NULL, [](void*) -> void* {
printf("Before MAIN_THREAD_EM_ASM_AWAIT\n");
int res = MAIN_THREAD_EM_ASM_AWAIT({
out('Inside MAIN_THREAD_EM_ASM_AWAIT: ' + $0 + ' ' + $1);
const asyncOp = new Promise((resolve,reject) => {
setTimeout(() => {
out('Inside asyncOp');
reject(2);
}, 1000);
});
return asyncOp;
}, 42, 3.5);
printf("After MAIN_THREAD_EM_ASM_AWAIT rejected\n");
printf("result: %d\n", res);
return NULL;
}, NULL);

// wait for thread to finish
pthread_join(thread, NULL);
return 0;
}
5 changes: 5 additions & 0 deletions test/core/test_main_thread_async_em_asm_await_reject.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Before MAIN_THREAD_EM_ASM_AWAIT
Inside MAIN_THREAD_EM_ASM_AWAIT: 42 3.5
Inside asyncOp
After MAIN_THREAD_EM_ASM_AWAIT rejected
result: 2
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_pthreads.size
Original file line number Diff line number Diff line change
@@ -1 +1 @@
19487
19495
2 changes: 1 addition & 1 deletion test/other/test_unoptimized_code_size.js.size
Original file line number Diff line number Diff line change
@@ -1 +1 @@
53709
53980
2 changes: 1 addition & 1 deletion test/other/test_unoptimized_code_size_no_asserts.js.size
Original file line number Diff line number Diff line change
@@ -1 +1 @@
29018
29400
2 changes: 1 addition & 1 deletion test/other/test_unoptimized_code_size_strict.js.size
Original file line number Diff line number Diff line change
@@ -1 +1 @@
52531
52776
20 changes: 20 additions & 0 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1878,6 +1878,26 @@ def test_main_thread_em_asm(self, args):
def test_main_thread_async_em_asm(self, args, force_c=False):
self.do_core_test('test_main_thread_async_em_asm.cpp', emcc_args=args, force_c=force_c)

@needs_dylink
@parameterized({
'': (['-sASSERTIONS'], False),
'pthreads': (['-pthread', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME'], False),
})
def test_main_thread_async_em_asm_await(self, args, force_c=False):
if '-sPROXY_TO_PTHREAD' not in args:
# expect runtime to error
output = self.do_runf('core/test_main_thread_async_em_asm_await.cpp', expected_output=None, assert_returncode=NON_ZERO, emcc_args=args)
self.assertContained('emscripten_asm_const_int_await_on_main_thread is not available on the main thread', output)
else:
self.do_core_test('test_main_thread_async_em_asm_await.cpp', emcc_args=args, force_c=force_c)

@needs_dylink
@parameterized({
'pthreads': (['-pthread', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME', '-sASSERTIONS'], False),
})
def test_main_thread_async_em_asm_await_reject(self, args, force_c=False):
self.do_core_test('test_main_thread_async_em_asm_await_reject.cpp', emcc_args=args, force_c=force_c)

# Tests MAIN_THREAD_EM_ASM_INT() function call with different signatures.
def test_main_thread_em_asm_signatures(self):
self.do_core_test('test_em_asm_signatures.cpp', assert_returncode=NON_ZERO)
Expand Down
2 changes: 2 additions & 0 deletions tools/emscripten.py
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,8 @@ def create_pointer_conversion_wrappers(metadata):
'_wasmfs_read_file': 'pp',
'__dl_seterr': '_pp',
'_emscripten_run_on_main_thread_js': '__p_p_',
'_emscripten_await_on_main_thread_js': '__p_p_',
'_emscripten_proxy_promise_finish': 'pp',
'_emscripten_proxy_execute_task_queue': '_p',
'_emscripten_thread_exit': '_p',
'_emscripten_thread_init': '_p_____',
Expand Down
Loading
Loading