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:
@@ -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() {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user