From ab43ab0d2c98b9eee6552162a33d0c50dbbf5e3c Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Thu, 19 Feb 2026 01:37:54 -0600 Subject: [PATCH] aot fix --- mcode.cm | 82 +++++++++++++++++++++++++- source/cell.c | 14 +---- source/mach.c | 17 +----- source/qbe_helpers.c | 3 - source/runtime.c | 135 +++++++++++++++++++++---------------------- 5 files changed, 148 insertions(+), 103 deletions(-) diff --git a/mcode.cm b/mcode.cm index f8423373..e4551ce3 100644 --- a/mcode.cm +++ b/mcode.cm @@ -1008,7 +1008,7 @@ var mcode = function(ast) { var inline_reduce = true // --- Helper: emit a reduce loop body --- - // r = {acc, i, arr, fn, len}; emits loop updating acc in-place. + // r = {acc, i, arr, fn, len, fn_arity}; emits loop updating acc in-place. // Caller must emit the done_label after calling this. var emit_reduce_loop = function(r, forward, done_label) { var acc = r.acc @@ -1016,29 +1016,51 @@ var mcode = function(ast) { var arr_slot = r.arr var fn_slot = r.fn var len = r.len + var fn_arity = r.fn_arity var check = alloc_slot() var item = alloc_slot() var null_s = alloc_slot() var one = alloc_slot() var zero = alloc_slot() + var arity_is_zero = alloc_slot() + var arity_is_one = alloc_slot() var f = alloc_slot() var loop_label = gen_label("reduce_loop") + var call_one_label = gen_label("reduce_call_one") + var call_two_label = gen_label("reduce_call_two") + var call_done_label = gen_label("reduce_call_done") emit_2("int", one, 1) + emit_2("int", zero, 0) emit_1("null", null_s) emit_label(loop_label) if (forward) { emit_3("lt_int", check, i, len) } else { - emit_2("int", zero, 0) emit_3("ge_int", check, i, zero) } emit_jump_cond("jump_false", check, done_label) emit_3("load_index", item, arr_slot, i) + emit_3("eq_int", arity_is_zero, fn_arity, zero) + emit_jump_cond("jump_false", arity_is_zero, call_one_label) + emit_3("frame", f, fn_slot, 0) + emit_3("setarg", f, 0, null_s) + emit_2("invoke", f, acc) + emit_jump(call_done_label) + emit_label(call_one_label) + emit_3("eq_int", arity_is_one, fn_arity, one) + emit_jump_cond("jump_false", arity_is_one, call_two_label) + emit_3("frame", f, fn_slot, 1) + emit_3("setarg", f, 0, null_s) + emit_3("setarg", f, 1, acc) + emit_2("invoke", f, acc) + emit_jump(call_done_label) + emit_label(call_two_label) emit_3("frame", f, fn_slot, 2) emit_3("setarg", f, 0, null_s) emit_3("setarg", f, 1, acc) emit_3("setarg", f, 2, item) emit_2("invoke", f, acc) + emit_label(call_done_label) if (forward) { emit_3("add", i, i, one) } else { @@ -1054,17 +1076,21 @@ var mcode = function(ast) { var check = alloc_slot() var item = alloc_slot() var fn_arity = alloc_slot() + var arity_is_zero = alloc_slot() var arity_is_one = alloc_slot() var null_s = alloc_slot() + var zero = alloc_slot() var one = alloc_slot() var f = alloc_slot() var discard = alloc_slot() var loop_label = gen_label("arrfor_loop") var done_label = gen_label("arrfor_done") + var call_one_label = gen_label("arrfor_call_one") var call_two_label = gen_label("arrfor_call_two") var call_done_label = gen_label("arrfor_call_done") emit_2("length", len, arr_slot) emit_2("int", i, 0) + emit_2("int", zero, 0) emit_2("int", one, 1) emit_1("null", null_s) emit_2("length", fn_arity, fn_slot) @@ -1072,6 +1098,13 @@ var mcode = function(ast) { emit_3("lt_int", check, i, len) emit_jump_cond("jump_false", check, done_label) emit_3("load_index", item, arr_slot, i) + emit_3("eq_int", arity_is_zero, fn_arity, zero) + emit_jump_cond("jump_false", arity_is_zero, call_one_label) + emit_3("frame", f, fn_slot, 0) + emit_3("setarg", f, 0, null_s) + emit_2("invoke", f, discard) + emit_jump(call_done_label) + emit_label(call_one_label) emit_3("eq_int", arity_is_one, fn_arity, one) emit_jump_cond("jump_false", arity_is_one, call_two_label) emit_3("frame", f, fn_slot, 1) @@ -1099,26 +1132,41 @@ var mcode = function(ast) { var i = alloc_slot() var check = alloc_slot() var item = alloc_slot() + var fn_arity = alloc_slot() + var arity_is_zero = alloc_slot() var null_s = alloc_slot() + var zero = alloc_slot() var one = alloc_slot() var f = alloc_slot() var val = alloc_slot() var loop_label = gen_label("every_loop") + var call_one_label = gen_label("every_call_one") + var call_done_label = gen_label("every_call_done") var ret_true = gen_label("every_true") var ret_false = gen_label("every_false") var done_label = gen_label("every_done") emit_2("length", len, arr_slot) emit_2("int", i, 0) + emit_2("int", zero, 0) emit_2("int", one, 1) emit_1("null", null_s) + emit_2("length", fn_arity, fn_slot) emit_label(loop_label) emit_3("lt_int", check, i, len) emit_jump_cond("jump_false", check, ret_true) emit_3("load_index", item, arr_slot, i) + emit_3("eq_int", arity_is_zero, fn_arity, zero) + emit_jump_cond("jump_false", arity_is_zero, call_one_label) + emit_3("frame", f, fn_slot, 0) + emit_3("setarg", f, 0, null_s) + emit_2("invoke", f, val) + emit_jump(call_done_label) + emit_label(call_one_label) emit_3("frame", f, fn_slot, 1) emit_3("setarg", f, 0, null_s) emit_3("setarg", f, 1, item) emit_2("invoke", f, val) + emit_label(call_done_label) emit_jump_cond("jump_false", val, ret_false) emit_3("add", i, i, one) emit_jump(loop_label) @@ -1137,26 +1185,41 @@ var mcode = function(ast) { var i = alloc_slot() var check = alloc_slot() var item = alloc_slot() + var fn_arity = alloc_slot() + var arity_is_zero = alloc_slot() var null_s = alloc_slot() + var zero = alloc_slot() var one = alloc_slot() var f = alloc_slot() var val = alloc_slot() var loop_label = gen_label("some_loop") + var call_one_label = gen_label("some_call_one") + var call_done_label = gen_label("some_call_done") var ret_true = gen_label("some_true") var ret_false = gen_label("some_false") var done_label = gen_label("some_done") emit_2("length", len, arr_slot) emit_2("int", i, 0) + emit_2("int", zero, 0) emit_2("int", one, 1) emit_1("null", null_s) + emit_2("length", fn_arity, fn_slot) emit_label(loop_label) emit_3("lt_int", check, i, len) emit_jump_cond("jump_false", check, ret_false) emit_3("load_index", item, arr_slot, i) + emit_3("eq_int", arity_is_zero, fn_arity, zero) + emit_jump_cond("jump_false", arity_is_zero, call_one_label) + emit_3("frame", f, fn_slot, 0) + emit_3("setarg", f, 0, null_s) + emit_2("invoke", f, val) + emit_jump(call_done_label) + emit_label(call_one_label) emit_3("frame", f, fn_slot, 1) emit_3("setarg", f, 0, null_s) emit_3("setarg", f, 1, item) emit_2("invoke", f, val) + emit_label(call_done_label) emit_jump_cond("jump_true", val, ret_true) emit_3("add", i, i, one) emit_jump(loop_label) @@ -1177,12 +1240,15 @@ var mcode = function(ast) { var check = alloc_slot() var item = alloc_slot() var fn_arity = alloc_slot() + var arity_is_zero = alloc_slot() var arity_is_one = alloc_slot() var null_s = alloc_slot() + var zero = alloc_slot() var one = alloc_slot() var f = alloc_slot() var val = alloc_slot() var loop_label = gen_label("filter_loop") + var call_one_label = gen_label("filter_call_one") var call_two_label = gen_label("filter_call_two") var call_done_label = gen_label("filter_call_done") var skip_label = gen_label("filter_skip") @@ -1190,6 +1256,7 @@ var mcode = function(ast) { add_instr(["array", result, 0]) emit_2("length", len, arr_slot) emit_2("int", i, 0) + emit_2("int", zero, 0) emit_2("int", one, 1) emit_1("null", null_s) emit_2("length", fn_arity, fn_slot) @@ -1197,6 +1264,13 @@ var mcode = function(ast) { emit_3("lt_int", check, i, len) emit_jump_cond("jump_false", check, done_label) emit_3("load_index", item, arr_slot, i) + emit_3("eq_int", arity_is_zero, fn_arity, zero) + emit_jump_cond("jump_false", arity_is_zero, call_one_label) + emit_3("frame", f, fn_slot, 0) + emit_3("setarg", f, 0, null_s) + emit_2("invoke", f, val) + emit_jump(call_done_label) + emit_label(call_one_label) emit_3("eq_int", arity_is_one, fn_arity, one) emit_jump_cond("jump_false", arity_is_one, call_two_label) emit_3("frame", f, fn_slot, 1) @@ -1227,6 +1301,7 @@ var mcode = function(ast) { var fn_slot = args.fn var init_slot = args.init var rev_slot = args.rev + var fn_arity = alloc_slot() var len = alloc_slot() var acc = alloc_slot() var i = alloc_slot() @@ -1244,9 +1319,10 @@ var mcode = function(ast) { var d4 = null var r = null emit_2("length", len, arr_slot) + emit_2("length", fn_arity, fn_slot) emit_2("int", zero, 0) emit_2("int", one, 1) - r = {acc: acc, i: i, arr: arr_slot, fn: fn_slot, len: len} + r = {acc: acc, i: i, arr: arr_slot, fn: fn_slot, len: len, fn_arity: fn_arity} if (nargs == 2) { null_label = gen_label("reduce_null") d1 = gen_label("reduce_d1") diff --git a/source/cell.c b/source/cell.c index f515331d..0bb7d4c2 100644 --- a/source/cell.c +++ b/source/cell.c @@ -13,7 +13,6 @@ #define BOOTSTRAP_MCODE "boot/bootstrap.cm.mcode" #define ENGINE_SRC "internal/engine.cm" -#define ENGINE_CACHE_VERSION "engine-cache-v2" #define CELL_SHOP_DIR ".cell" #define CELL_CORE_DIR "packages/core" @@ -223,18 +222,7 @@ static char *try_engine_cache(size_t *out_size) { char *src = load_core_file(ENGINE_SRC, &src_size); if (!src) return NULL; - size_t ver_len = strlen(ENGINE_CACHE_VERSION); - size_t salted_size = src_size + 1 + ver_len; - char *salted = malloc(salted_size); - if (!salted) { - free(src); - return NULL; - } - memcpy(salted, src, src_size); - salted[src_size] = '\n'; - memcpy(salted + src_size + 1, ENGINE_CACHE_VERSION, ver_len); - char *hex = compute_blake2_hex(salted, salted_size); - free(salted); + char *hex = compute_blake2_hex(src, src_size); free(src); if (!hex) return NULL; char *cpath = build_cache_path(hex); diff --git a/source/mach.c b/source/mach.c index ec8364be..fa541599 100644 --- a/source/mach.c +++ b/source/mach.c @@ -85,9 +85,6 @@ static JSValue *mach_materialize_cpool(JSContext *ctx, MachCPoolEntry *entries, static int mach_check_call_arity(JSContext *ctx, JSFunction *fn, int argc) { if (unlikely(fn->length >= 0 && argc > fn->length)) { char buf[KEY_GET_STR_BUF_SIZE]; - fprintf(stderr, "[arity-mach] callee=%s expected=%d got=%d\n", - JS_KeyGetStr(ctx, buf, KEY_GET_STR_BUF_SIZE, fn->name), - fn->length, argc); JS_RaiseDisrupt(ctx, "too many arguments for %s: expected %d, got %d", JS_KeyGetStr(ctx, buf, KEY_GET_STR_BUF_SIZE, fn->name), fn->length, argc); return 0; @@ -2183,13 +2180,8 @@ vm_dispatch: int c_argc = (nr >= 2) ? nr - 2 : 0; JSValue fn_val = fr->function; JSFunction *fn = JS_VALUE_GET_FUNCTION(fn_val); - if (!mach_check_call_arity(ctx, fn, c_argc)) { - fprintf(stderr, "[arity-mach] caller=%s file=%s pc=%u op=invoke argc=%d\n", - code->name_cstr ? code->name_cstr : "?", - code->filename_cstr ? code->filename_cstr : "?", - (unsigned)(pc > 0 ? pc - 1 : 0), c_argc); + if (!mach_check_call_arity(ctx, fn, c_argc)) goto disrupt; - } if (fn->kind == JS_FUNC_KIND_REGISTER) { /* Register function: switch frames inline (fast path) */ @@ -2261,13 +2253,8 @@ vm_dispatch: int c_argc = (nr >= 2) ? nr - 2 : 0; JSValue fn_val = fr->function; JSFunction *fn = JS_VALUE_GET_FUNCTION(fn_val); - if (!mach_check_call_arity(ctx, fn, c_argc)) { - fprintf(stderr, "[arity-mach] caller=%s file=%s pc=%u op=goinvoke argc=%d\n", - code->name_cstr ? code->name_cstr : "?", - code->filename_cstr ? code->filename_cstr : "?", - (unsigned)(pc > 0 ? pc - 1 : 0), c_argc); + if (!mach_check_call_arity(ctx, fn, c_argc)) goto disrupt; - } if (fn->kind == JS_FUNC_KIND_REGISTER) { JSCodeRegister *fn_code = JS_VALUE_GET_CODE(fn->u.cell.code)->u.reg.code; diff --git a/source/qbe_helpers.c b/source/qbe_helpers.c index 5a3a021e..72e0ec16 100644 --- a/source/qbe_helpers.c +++ b/source/qbe_helpers.c @@ -771,9 +771,6 @@ void cell_rt_signal_tail_call(JSContext *ctx, void *fp, int64_t frame_slot) { static int cell_check_call_arity(JSContext *ctx, JSFunction *fn, int argc) { if (unlikely(fn->length >= 0 && argc > fn->length)) { char buf[KEY_GET_STR_BUF_SIZE]; - fprintf(stderr, "[arity-qbe] callee=%s expected=%d got=%d\n", - JS_KeyGetStr(ctx, buf, KEY_GET_STR_BUF_SIZE, fn->name), - fn->length, argc); JS_RaiseDisrupt(ctx, "too many arguments for %s: expected %d, got %d", JS_KeyGetStr(ctx, buf, KEY_GET_STR_BUF_SIZE, fn->name), fn->length, argc); diff --git a/source/runtime.c b/source/runtime.c index 9bc46d5d..3f669910 100644 --- a/source/runtime.c +++ b/source/runtime.c @@ -4736,6 +4736,11 @@ JSValue JS_CallInternal (JSContext *ctx, JSValue func_obj, JSValue this_obj, if (!JS_IsFunction (func_obj)) return JS_RaiseDisrupt (ctx, "not a function"); JSFunction *f = JS_VALUE_GET_FUNCTION (func_obj); + if (unlikely (f->length >= 0 && argc > f->length)) { + char buf[KEY_GET_STR_BUF_SIZE]; + return JS_RaiseDisrupt (ctx, "too many arguments for %s: expected %d, got %d", + JS_KeyGetStr (ctx, buf, KEY_GET_STR_BUF_SIZE, f->name), f->length, argc); + } switch (f->kind) { case JS_FUNC_KIND_C: case JS_FUNC_KIND_C_DATA: @@ -4750,6 +4755,16 @@ JSValue JS_CallInternal (JSContext *ctx, JSValue func_obj, JSValue this_obj, } } +/* Call helper used by runtime callback intrinsics. + Caps argc to function arity so helper callbacks never rely on over-arity calls. */ +static inline JSValue js_call_internal_capped (JSContext *ctx, JSValue func_obj, JSValue this_obj, + int argc, JSValue *argv) { + JSFunction *f = JS_VALUE_GET_FUNCTION (func_obj); + if (f->length >= 0 && argc > f->length) + argc = f->length; + return JS_CallInternal (ctx, func_obj, this_obj, argc, argc > 0 ? argv : NULL, 0); +} + JSValue JS_Call (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv) { if (js_poll_interrupts (ctx)) return JS_EXCEPTION; if (unlikely (!JS_IsFunction (func_obj))) @@ -8245,7 +8260,7 @@ static JSValue js_cell_array (JSContext *ctx, JSValue this_val, int argc, JSValu MAP_STORE (val); } } - } else { + } else if (arity == 1) { if (reverse) { for (int i = len - 1; i >= 0; i--) { arr = JS_VALUE_GET_ARRAY (arg0_ref.val); @@ -8267,6 +8282,26 @@ static JSValue js_cell_array (JSContext *ctx, JSValue this_val, int argc, JSValu MAP_STORE (val); } } + } else { + if (reverse) { + for (int i = len - 1; i >= 0; i--) { + arr = JS_VALUE_GET_ARRAY (arg0_ref.val); + if (i >= (int)arr->len) continue; + JSValue val = JS_CallInternal (ctx, arg1_ref.val, JS_NULL, 0, NULL, 0); + if (JS_IsException (val)) { MAP_ERR (); } + if (!JS_IsNull (exit_val) && js_strict_eq (ctx, val, exit_val)) break; + MAP_STORE (val); + } + } else { + for (int i = 0; i < len; i++) { + arr = JS_VALUE_GET_ARRAY (arg0_ref.val); + if (i >= (int)arr->len) break; + JSValue val = JS_CallInternal (ctx, arg1_ref.val, JS_NULL, 0, NULL, 0); + if (JS_IsException (val)) { MAP_ERR (); } + if (!JS_IsNull (exit_val) && js_strict_eq (ctx, val, exit_val)) break; + MAP_STORE (val); + } + } } #undef MAP_STORE #undef MAP_ERR @@ -8626,6 +8661,7 @@ static JSValue js_cell_array_reduce (JSContext *ctx, JSValue this_val, int argc, JSArray *arr = JS_VALUE_GET_ARRAY (argv[0]); word_t len = arr->len; + JSValue fn = argv[1]; int reverse = argc > 3 && JS_ToBool (ctx, argv[3]); JSGCRef acc_ref; @@ -8642,7 +8678,7 @@ static JSValue js_cell_array_reduce (JSContext *ctx, JSValue this_val, int argc, if (i - 1 >= arr->len) continue; JSValue args[2] = { acc, arr->values[i - 1] }; JS_PUSH_VALUE (ctx, acc); - JSValue new_acc = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0); + JSValue new_acc = js_call_internal_capped (ctx, fn, JS_NULL, 2, args); JS_POP_VALUE (ctx, acc); if (JS_IsException (new_acc)) return JS_EXCEPTION; acc = new_acc; @@ -8654,7 +8690,7 @@ static JSValue js_cell_array_reduce (JSContext *ctx, JSValue this_val, int argc, if (i >= arr->len) break; JSValue args[2] = { acc, arr->values[i] }; JS_PUSH_VALUE (ctx, acc); - JSValue new_acc = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0); + JSValue new_acc = js_call_internal_capped (ctx, fn, JS_NULL, 2, args); JS_POP_VALUE (ctx, acc); if (JS_IsException (new_acc)) return JS_EXCEPTION; acc = new_acc; @@ -8670,7 +8706,7 @@ static JSValue js_cell_array_reduce (JSContext *ctx, JSValue this_val, int argc, if (i - 1 >= arr->len) continue; JSValue args[2] = { acc, arr->values[i - 1] }; JS_PUSH_VALUE (ctx, acc); - JSValue new_acc = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0); + JSValue new_acc = js_call_internal_capped (ctx, fn, JS_NULL, 2, args); JS_POP_VALUE (ctx, acc); if (JS_IsException (new_acc)) return JS_EXCEPTION; acc = new_acc; @@ -8681,7 +8717,7 @@ static JSValue js_cell_array_reduce (JSContext *ctx, JSValue this_val, int argc, if (i >= arr->len) break; JSValue args[2] = { acc, arr->values[i] }; JS_PUSH_VALUE (ctx, acc); - JSValue new_acc = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0); + JSValue new_acc = js_call_internal_capped (ctx, fn, JS_NULL, 2, args); JS_POP_VALUE (ctx, acc); if (JS_IsException (new_acc)) return JS_EXCEPTION; acc = new_acc; @@ -8706,23 +8742,14 @@ static JSValue js_cell_array_for (JSContext *ctx, JSValue this_val, int argc, JS int reverse = argc > 2 && JS_ToBool (ctx, argv[2]); JSValue exit_val = argc > 3 ? argv[3] : JS_NULL; - /* Determine function arity */ - int arity = ((JSFunction *)JS_VALUE_GET_FUNCTION (argv[1]))->length; - if (reverse) { for (word_t i = len; i > 0; i--) { arr = JS_VALUE_GET_ARRAY (argv[0]); if (i - 1 >= arr->len) continue; - JSValue result; - if (arity == 1) { - JSValue item = arr->values[i - 1]; - result = JS_CallInternal (ctx, argv[1], JS_NULL, 1, &item, 0); - } else { - JSValue args[2]; - args[0] = arr->values[i - 1]; - args[1] = JS_NewInt32 (ctx, (int32_t)(i - 1)); - result = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0); - } + JSValue args[2]; + args[0] = arr->values[i - 1]; + args[1] = JS_NewInt32 (ctx, (int32_t)(i - 1)); + JSValue result = js_call_internal_capped (ctx, argv[1], JS_NULL, 2, args); if (JS_IsException (result)) return JS_EXCEPTION; if (!JS_IsNull (exit_val) && js_strict_eq (ctx, result, exit_val)) return result; @@ -8731,16 +8758,10 @@ static JSValue js_cell_array_for (JSContext *ctx, JSValue this_val, int argc, JS for (word_t i = 0; i < len; i++) { arr = JS_VALUE_GET_ARRAY (argv[0]); if (i >= arr->len) break; - JSValue result; - if (arity == 1) { - JSValue item = arr->values[i]; - result = JS_CallInternal (ctx, argv[1], JS_NULL, 1, &item, 0); - } else { - JSValue args[2]; - args[0] = arr->values[i]; - args[1] = JS_NewInt32 (ctx, (int32_t)i); - result = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0); - } + JSValue args[2]; + args[0] = arr->values[i]; + args[1] = JS_NewInt32 (ctx, (int32_t)i); + JSValue result = js_call_internal_capped (ctx, argv[1], JS_NULL, 2, args); if (JS_IsException (result)) return JS_EXCEPTION; if (!JS_IsNull (exit_val) && js_strict_eq (ctx, result, exit_val)) return result; @@ -8787,47 +8808,23 @@ static JSValue js_cell_array_find (JSContext *ctx, JSValue this_val, int argc, J } /* Use function predicate — re-chase after each call */ - int arity = ((JSFunction *)JS_VALUE_GET_FUNCTION (argv[1]))->length; - - if (arity == 2) { - if (reverse) { - for (int32_t i = from; i >= 0; i--) { - arr = JS_VALUE_GET_ARRAY (argv[0]); - if ((word_t)i >= arr->len) continue; - JSValue args[2] = { arr->values[i], JS_NewInt32 (ctx, i) }; - JSValue result = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0); - if (JS_IsException (result)) return JS_EXCEPTION; - if (JS_ToBool (ctx, result)) return JS_NewInt32 (ctx, i); - } - } else { - for (word_t i = (word_t)from; i < len; i++) { - arr = JS_VALUE_GET_ARRAY (argv[0]); - if (i >= arr->len) break; - JSValue args[2] = { arr->values[i], JS_NewInt32 (ctx, (int32_t)i) }; - JSValue result = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0); - if (JS_IsException (result)) return JS_EXCEPTION; - if (JS_ToBool (ctx, result)) return JS_NewInt32 (ctx, (int32_t)i); - } + if (reverse) { + for (int32_t i = from; i >= 0; i--) { + arr = JS_VALUE_GET_ARRAY (argv[0]); + if ((word_t)i >= arr->len) continue; + JSValue args[2] = { arr->values[i], JS_NewInt32 (ctx, i) }; + JSValue result = js_call_internal_capped (ctx, argv[1], JS_NULL, 2, args); + if (JS_IsException (result)) return JS_EXCEPTION; + if (JS_ToBool (ctx, result)) return JS_NewInt32 (ctx, i); } } else { - if (reverse) { - for (int32_t i = from; i >= 0; i--) { - arr = JS_VALUE_GET_ARRAY (argv[0]); - if ((word_t)i >= arr->len) continue; - JSValue item = arr->values[i]; - JSValue result = JS_CallInternal (ctx, argv[1], JS_NULL, 1, &item, 0); - if (JS_IsException (result)) return JS_EXCEPTION; - if (JS_ToBool (ctx, result)) return JS_NewInt32 (ctx, i); - } - } else { - for (word_t i = (word_t)from; i < len; i++) { - arr = JS_VALUE_GET_ARRAY (argv[0]); - if (i >= arr->len) break; - JSValue item = arr->values[i]; - JSValue result = JS_CallInternal (ctx, argv[1], JS_NULL, 1, &item, 0); - if (JS_IsException (result)) return JS_EXCEPTION; - if (JS_ToBool (ctx, result)) return JS_NewInt32 (ctx, (int32_t)i); - } + for (word_t i = (word_t)from; i < len; i++) { + arr = JS_VALUE_GET_ARRAY (argv[0]); + if (i >= arr->len) break; + JSValue args[2] = { arr->values[i], JS_NewInt32 (ctx, (int32_t)i) }; + JSValue result = js_call_internal_capped (ctx, argv[1], JS_NULL, 2, args); + if (JS_IsException (result)) return JS_EXCEPTION; + if (JS_ToBool (ctx, result)) return JS_NewInt32 (ctx, (int32_t)i); } } @@ -9264,7 +9261,7 @@ static JSValue js_cell_object (JSContext *ctx, JSValue this_val, int argc, JSVal val = JS_TRUE; } else if (is_func) { JSValue arg_key = key; - val = JS_CallInternal (ctx, func_ref.val, JS_NULL, 1, &arg_key, 0); + val = js_call_internal_capped (ctx, func_ref.val, JS_NULL, 1, &arg_key); if (JS_IsException (val)) { JS_PopGCRef (ctx, &result_ref); JS_PopGCRef (ctx, &func_ref); @@ -11317,7 +11314,7 @@ static JSValue js_cell_every (JSContext *ctx, JSValue this_val, int argc, JSValu JSArray *arr = JS_VALUE_GET_ARRAY (argv[0]); for (int i = 0; i < arr->len; i++) { JSValue elem = arr->values[i]; - JSValue r = JS_CallInternal (ctx, argv[1], JS_NULL, 1, &elem, 0); + JSValue r = js_call_internal_capped (ctx, argv[1], JS_NULL, 1, &elem); arr = JS_VALUE_GET_ARRAY (argv[0]); if (JS_IsException (r)) return r; if (!JS_ToBool (ctx, r)) return JS_FALSE;