mirror of
https://github.com/python/cpython.git
synced 2025-12-09 10:37:17 +00:00
gh-124621: Emscripten: Add support for async input devices (GH-136822)
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`.
This commit is contained in:
parent
1ba23244f3
commit
7ae4749d06
4 changed files with 245 additions and 1 deletions
|
|
@ -2345,6 +2345,37 @@ incref_decref_delayed(PyObject *self, PyObject *op)
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include "emscripten.h"
|
||||
|
||||
EM_JS(int, emscripten_set_up_async_input_device_js, (void), {
|
||||
let idx = 0;
|
||||
const encoder = new TextEncoder();
|
||||
const bufs = [
|
||||
encoder.encode("ab\n"),
|
||||
encoder.encode("fi\n"),
|
||||
encoder.encode("xy\n"),
|
||||
];
|
||||
function sleep(t) {
|
||||
return new Promise(res => setTimeout(res, t));
|
||||
}
|
||||
FS.createAsyncInputDevice("/dev", "blah", async () => {
|
||||
await sleep(5);
|
||||
return bufs[(idx ++) % 3];
|
||||
});
|
||||
return !!WebAssembly.promising;
|
||||
});
|
||||
|
||||
static PyObject *
|
||||
emscripten_set_up_async_input_device(PyObject *self, PyObject *Py_UNUSED(ignored)) {
|
||||
if (emscripten_set_up_async_input_device_js()) {
|
||||
Py_RETURN_TRUE;
|
||||
} else {
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static PyMethodDef module_functions[] = {
|
||||
{"get_configs", get_configs, METH_NOARGS},
|
||||
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
|
||||
|
|
@ -2447,6 +2478,9 @@ static PyMethodDef module_functions[] = {
|
|||
{"is_static_immortal", is_static_immortal, METH_O},
|
||||
{"incref_decref_delayed", incref_decref_delayed, METH_O},
|
||||
GET_NEXT_DICT_KEYS_VERSION_METHODDEF
|
||||
#ifdef __EMSCRIPTEN__
|
||||
{"emscripten_set_up_async_input_device", emscripten_set_up_async_input_device, METH_NOARGS},
|
||||
#endif
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue