[3.14] gh-124621: Emscripten: Add support for async input devices (GH-136822) (GH-136935)

This is useful for implementing proper `input()`. It requires the
JavaScript engine to support the wasm JSPI spec which is now stage 4.
It is supported on Chrome since version 137 and on Firefox and node
behind a flag.

We override the `__wasi_fd_read()` syscall with our own variant that
checks for a readAsync operation. If it has it, we use our own async
variant of `fd_read()`, otherwise we use the original `fd_read()`.
We also add a variant of `FS.createDevice()` called
`FS.createAsyncInputDevice()`.

Finally, if JSPI is available, we wrap the `main()` symbol with
`WebAssembly.promising()` so that we can stack switch from `fd_read()`.
If JSPI is not available, attempting to read from an AsyncInputDevice
will raise an `OSError`.
(cherry picked from commit 7ae4749d06)

Co-authored-by: Hood Chatham <roberthoodchatham@gmail.com>
This commit is contained in:
Miss Islington (bot) 2025-07-22 11:51:02 +02:00 committed by GitHub
parent 8e43b130f7
commit d118bc061b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 252 additions and 1 deletions

View file

@ -274,10 +274,20 @@ def configure_emscripten_python(context, working_dir):
REALPATH=abs_path
fi
# Before node 24, --experimental-wasm-jspi uses different API,
# After node 24 JSPI is on by default.
ARGS=$({host_runner} -e "$(cat <<"EOF"
const major_version = Number(process.version.split(".")[0].slice(1));
if (major_version === 24) {{
process.stdout.write("--experimental-wasm-jspi");
}}
EOF
)")
# We compute our own path, not following symlinks and pass it in so that
# node_entry.mjs can set sys.executable correctly.
# Intentionally allow word splitting on NODEFLAGS.
exec {host_runner} $NODEFLAGS {node_entry} --this-program="$($REALPATH "$0")" "$@"
exec {host_runner} $NODEFLAGS $ARGS {node_entry} --this-program="$($REALPATH "$0")" "$@"
"""
)
)