webassembly/api: Allocate code data on C heap when running Python code.

Otherwise Emscripten allocates it on the Emscripten C stack, which will
overflow for large amounts of code.

Fixes issue #14307.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George
2024-04-17 14:25:48 +10:00
parent 45848f77ca
commit 9c7f0659e2
2 changed files with 16 additions and 8 deletions

View File

@@ -127,23 +127,31 @@ export async function loadMicroPython(options) {
}, },
pyimport: pyimport, pyimport: pyimport,
runPython(code) { runPython(code) {
const len = Module.lengthBytesUTF8(code);
const buf = Module._malloc(len + 1);
Module.stringToUTF8(code, buf, len + 1);
const value = Module._malloc(3 * 4); const value = Module._malloc(3 * 4);
Module.ccall( Module.ccall(
"mp_js_do_exec", "mp_js_do_exec",
"number", "number",
["string", "pointer"], ["pointer", "number", "pointer"],
[code, value], [buf, len, value],
); );
Module._free(buf);
return proxy_convert_mp_to_js_obj_jsside_with_free(value); return proxy_convert_mp_to_js_obj_jsside_with_free(value);
}, },
runPythonAsync(code) { runPythonAsync(code) {
const len = Module.lengthBytesUTF8(code);
const buf = Module._malloc(len + 1);
Module.stringToUTF8(code, buf, len + 1);
const value = Module._malloc(3 * 4); const value = Module._malloc(3 * 4);
Module.ccall( Module.ccall(
"mp_js_do_exec_async", "mp_js_do_exec_async",
"number", "number",
["string", "pointer"], ["pointer", "number", "pointer"],
[code, value], [buf, len, value],
); );
Module._free(buf);
return proxy_convert_mp_to_js_obj_jsside_with_free(value); return proxy_convert_mp_to_js_obj_jsside_with_free(value);
}, },
replInit() { replInit() {

View File

@@ -104,7 +104,7 @@ void mp_js_do_import(const char *name, uint32_t *out) {
} }
} }
void mp_js_do_exec(const char *src, uint32_t *out) { void mp_js_do_exec(const char *src, size_t len, uint32_t *out) {
// Collect at the top-level, where there are no root pointers from stack/registers. // Collect at the top-level, where there are no root pointers from stack/registers.
gc_collect_start(); gc_collect_start();
gc_collect_end(); gc_collect_end();
@@ -112,7 +112,7 @@ void mp_js_do_exec(const char *src, uint32_t *out) {
mp_parse_input_kind_t input_kind = MP_PARSE_FILE_INPUT; mp_parse_input_kind_t input_kind = MP_PARSE_FILE_INPUT;
nlr_buf_t nlr; nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) { if (nlr_push(&nlr) == 0) {
mp_lexer_t *lex = mp_lexer_new_from_str_len_dedent(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); mp_lexer_t *lex = mp_lexer_new_from_str_len_dedent(MP_QSTR__lt_stdin_gt_, src, len, 0);
qstr source_name = lex->source_name; qstr source_name = lex->source_name;
mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
mp_obj_t module_fun = mp_compile(&parse_tree, source_name, false); mp_obj_t module_fun = mp_compile(&parse_tree, source_name, false);
@@ -125,9 +125,9 @@ void mp_js_do_exec(const char *src, uint32_t *out) {
} }
} }
void mp_js_do_exec_async(const char *src, uint32_t *out) { void mp_js_do_exec_async(const char *src, size_t len, uint32_t *out) {
mp_compile_allow_top_level_await = true; mp_compile_allow_top_level_await = true;
mp_js_do_exec(src, out); mp_js_do_exec(src, len, out);
mp_compile_allow_top_level_await = false; mp_compile_allow_top_level_await = false;
} }