From 06f779115952e6f366f2279e406ef1d0a27d0671 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Mon, 26 Jan 2026 11:44:21 -0600 Subject: [PATCH] use internal calls for internals --- source/quickjs.c | 691 ++++++++++++++++++++++++----------------------- source/quickjs.h | 5 + 2 files changed, 355 insertions(+), 341 deletions(-) diff --git a/source/quickjs.c b/source/quickjs.c index 8206f6fc..143e2c93 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -27633,42 +27633,47 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val, /* array(number) - create array of size */ /* array(number, initial_value) - create array with initial values */ - if (tag == JS_TAG_INT || tag == JS_TAG_FLOAT64) { - double d; - if (JS_ToFloat64(ctx, &d, arg)) - return JS_NULL; - if (d < 0) return JS_NULL; - int64_t len = (int64_t)floor(d); + if (JS_IsNumber(arg)) { + if (!JS_IsInteger(arg)) + return JS_ThrowTypeError(ctx, "Array expected an integer."); + + int len = JS_VALUE_GET_INT(arg); + if (len < 0) return JS_NULL; JSValue result = JS_NewArrayLen(ctx, len); if (JS_IsException(result)) return result; + JSArray *out = JS_VALUE_GET_ARRAY(result); - if (JS_IsFunction(argv[1])) { + if (argc > 1 && JS_IsFunction(argv[1])) { /* Fill with function results */ JSValueConst func = argv[1]; - int arity = 0; - JSValue len_val = JS_GetPropertyStr(ctx, func, "length"); - if (!JS_IsException(len_val)) { - JS_ToInt32(ctx, &arity, len_val); - JS_FreeValue(ctx, len_val); - } + int arity = ((JSFunction*)JS_VALUE_GET_FUNCTION(func))->length; - for (int64_t i = 0; i < len; i++) { - JSValue args[1] = { JS_NewInt64(ctx, i) }; - JSValue val = arity >= 1 ? JS_Call(ctx, func, JS_NULL, 1, args) - : JS_Call(ctx, func, JS_NULL, 0, NULL); - JS_FreeValue(ctx, args[0]); - if (JS_IsException(val)) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; + if (arity >= 1) { + for (int i = 0; i < len; i++) { + JSValue idx_arg = JS_NewInt32(ctx, i); + JSValue val = JS_CallInternal(ctx, func, JS_NULL, 1, &idx_arg, 0); + JS_FreeValue(ctx, idx_arg); + if (JS_IsException(val)) { + JS_FreeValue(ctx, result); + return JS_EXCEPTION; + } + out->values[i] = val; + } + } else { + for (int i = 0; i < len; i++) { + JSValue val = JS_CallInternal(ctx, func, JS_NULL, 0, NULL, 0); + if (JS_IsException(val)) { + JS_FreeValue(ctx, result); + return JS_EXCEPTION; + } + out->values[i] = val; } - JS_SetPropertyInt64(ctx, result, i, val); } - } else { + } else if (argc > 1) { /* Fill with value */ - for (int64_t i = 0; i < len; i++) { - JS_SetPropertyInt64(ctx, result, i, JS_DupValue(ctx, argv[1])); - } + for (int i = 0; i < len; i++) + out->values[i] = JS_DupValue(ctx, argv[1]); } return result; } @@ -27678,88 +27683,98 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val, /* array(array, another_array) - concat */ /* array(array, from, to) - slice */ if (JS_IsArray(ctx, arg)) { - int64_t len; - if (js_get_length64(ctx, &len, arg)) - return JS_EXCEPTION; + JSArray *arr = JS_VALUE_GET_ARRAY(arg); + int len = arr->len; if (argc < 2 || JS_IsNull(argv[1])) { + /* Copy */ JSValue result = JS_NewArrayLen(ctx, len); if (JS_IsException(result)) return result; - for (int64_t i = 0; i < len; i++) { - JSValue val = JS_GetPropertyInt64(ctx, arg, i); - if (JS_IsException(val)) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } - JS_SetPropertyInt64(ctx, result, i, val); + JSArray *out = JS_VALUE_GET_ARRAY(result); + for (int i = 0; i < len; i++) { + out->values[i] = JS_DupValue(ctx, arr->values[i]); } + out->len = len; return result; } if (JS_IsFunction(argv[1])) { /* Map */ JSValueConst func = argv[1]; - int arity = (JSFunction*)JS_VALUE_GET_FUNCTION(argv[1])->length; - + int arity = ((JSFunction*)JS_VALUE_GET_FUNCTION(argv[1]))->length; + int reverse = argc > 2 && JS_ToBool(ctx, argv[2]); JSValue exit_val = argc > 3 ? argv[3] : JS_NULL; - JSValue result = JS_NewArrayLen(ctx, len); + JSValue result = JS_NewArray(ctx); if (JS_IsException(result)) return result; + JSArray *out = JS_VALUE_GET_ARRAY(result); - if (reverse) { - int64_t out_idx = 0; - for (int64_t i = len - 1; i >= 0; i--) { - JSValue item = JS_GetPropertyInt64(ctx, arg, i); - if (JS_IsException(item)) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } - JSValue val; - if (arity >= 2) { - JSValue args[2] = { item, JS_NewInt64(ctx, i) }; - val = JS_Call(ctx, func, JS_NULL, 2, args); + if (arity >= 2) { + if (reverse) { + for (int i = len - 1; i >= 0; i--) { + JSValue args[2] = { JS_DupValue(ctx, arr->values[i]), JS_NewInt32(ctx, i) }; + JSValue val = JS_CallInternal(ctx, func, JS_NULL, 2, args, 0); + JS_FreeValue(ctx, args[0]); JS_FreeValue(ctx, args[1]); - } else { - val = JS_Call(ctx, func, JS_NULL, 1, &item); + if (JS_IsException(val)) { + JS_FreeValue(ctx, result); + return JS_EXCEPTION; + } + if (!JS_IsNull(exit_val) && js_strict_eq(ctx, val, exit_val)) { + JS_FreeValue(ctx, val); + break; + } + js_intrinsic_array_push(ctx, out, val); } - JS_FreeValue(ctx, item); - if (JS_IsException(val)) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; + } else { + for (int i = 0; i < len; i++) { + JSValue args[2] = { JS_DupValue(ctx, arr->values[i]), JS_NewInt32(ctx, i) }; + JSValue val = JS_CallInternal(ctx, func, JS_NULL, 2, args, 0); + JS_FreeValue(ctx, args[0]); + JS_FreeValue(ctx, args[1]); + if (JS_IsException(val)) { + JS_FreeValue(ctx, result); + return JS_EXCEPTION; + } + if (!JS_IsNull(exit_val) && js_strict_eq(ctx, val, exit_val)) { + JS_FreeValue(ctx, val); + break; + } + js_intrinsic_array_push(ctx, out, val); } - if (!JS_IsNull(exit_val) && js_strict_eq(ctx, val, exit_val)) { - JS_FreeValue(ctx, val); - break; - } - JS_SetPropertyInt64(ctx, result, out_idx++, val); } } else { - int64_t out_idx = 0; - for (int64_t i = 0; i < len; i++) { - JSValue item = JS_GetPropertyInt64(ctx, arg, i); - if (JS_IsException(item)) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; + if (reverse) { + for (int i = len - 1; i >= 0; i--) { + JSValue item = JS_DupValue(ctx, arr->values[i]); + JSValue val = JS_CallInternal(ctx, func, JS_NULL, 1, &item, 0); + JS_FreeValue(ctx, item); + if (JS_IsException(val)) { + JS_FreeValue(ctx, result); + return JS_EXCEPTION; + } + if (!JS_IsNull(exit_val) && js_strict_eq(ctx, val, exit_val)) { + JS_FreeValue(ctx, val); + break; + } + js_intrinsic_array_push(ctx, out, val); } - JSValue val; - if (arity >= 2) { - JSValue args[2] = { item, JS_NewInt64(ctx, i) }; - val = JS_Call(ctx, func, JS_NULL, 2, args); - JS_FreeValue(ctx, args[1]); - } else { - val = JS_Call(ctx, func, JS_NULL, 1, &item); + } else { + for (int i = 0; i < len; i++) { + JSValue item = JS_DupValue(ctx, arr->values[i]); + JSValue val = JS_CallInternal(ctx, func, JS_NULL, 1, &item, 0); + JS_FreeValue(ctx, item); + if (JS_IsException(val)) { + JS_FreeValue(ctx, result); + return JS_EXCEPTION; + } + if (!JS_IsNull(exit_val) && js_strict_eq(ctx, val, exit_val)) { + JS_FreeValue(ctx, val); + break; + } + js_intrinsic_array_push(ctx, out, val); } - JS_FreeValue(ctx, item); - if (JS_IsException(val)) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } - if (!JS_IsNull(exit_val) && js_strict_eq(ctx, val, exit_val)) { - JS_FreeValue(ctx, val); - break; - } - JS_SetPropertyInt64(ctx, result, out_idx++, val); } } return result; @@ -27767,64 +27782,51 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val, if (JS_IsArray(ctx, argv[1])) { /* Concat */ - int64_t len2; - if (js_get_length64(ctx, &len2, argv[1])) - return JS_EXCEPTION; + JSArray *arr2 = JS_VALUE_GET_ARRAY(argv[1]); + int len2 = arr2->len; JSValue result = JS_NewArrayLen(ctx, len + len2); if (JS_IsException(result)) return result; + JSArray *out = JS_VALUE_GET_ARRAY(result); - int64_t idx = 0; - for (int64_t i = 0; i < len; i++) { - JSValue val = JS_GetPropertyInt64(ctx, arg, i); - if (JS_IsException(val)) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } - JS_SetPropertyInt64(ctx, result, idx++, val); + for (int i = 0; i < len; i++) { + out->values[i] = JS_DupValue(ctx, arr->values[i]); } - for (int64_t i = 0; i < len2; i++) { - JSValue val = JS_GetPropertyInt64(ctx, argv[1], i); - if (JS_IsException(val)) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } - JS_SetPropertyInt64(ctx, result, idx++, val); + for (int i = 0; i < len2; i++) { + out->values[len + i] = JS_DupValue(ctx, arr2->values[i]); } + out->len = len + len2; return result; } - if (tag == JS_TAG_INT || tag == JS_TAG_FLOAT64 || - JS_VALUE_GET_TAG(argv[1]) == JS_TAG_INT || - JS_VALUE_GET_TAG(argv[1]) == JS_TAG_FLOAT64) { + if (JS_IsNumber(argv[1])) { /* Slice */ - int from, to; - if (JS_ToInt32(ctx, &from, argv[1])) + if (!JS_IsInteger(argv[1])) return JS_NULL; + int from = JS_VALUE_GET_INT(argv[1]); + int to; if (argc > 2 && !JS_IsNull(argv[2])) { - if (JS_ToInt32(ctx, &to, argv[2])) + if (!JS_IsNumber(argv[2]) || !JS_IsInteger(argv[2])) return JS_NULL; + to = JS_VALUE_GET_INT(argv[2]); } else { to = len; } if (from < 0) from += len; if (to < 0) to += len; - if (from < 0 || from > to || to > len) + if (from < 0 || from > len || to < 0 || to > len || from > to) return JS_NULL; - JSValue result = JS_NewArrayLen(ctx, to - from); + int slice_len = to - from; + JSValue result = JS_NewArrayLen(ctx, slice_len); if (JS_IsException(result)) return result; + JSArray *out = JS_VALUE_GET_ARRAY(result); - int64_t idx = 0; - for (int i = from; i < to; i++) { - JSValue val = JS_GetPropertyInt64(ctx, arg, i); - if (JS_IsException(val)) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } - JS_SetPropertyInt64(ctx, result, idx++, val); + for (int i = 0; i < slice_len; i++) { + out->values[i] = JS_DupValue(ctx, arr->values[from + i]); } + out->len = slice_len; return result; } @@ -27851,14 +27853,16 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val, if (JS_IsException(result)) { return result; } + JSArray *out = JS_VALUE_GET_ARRAY(result); for (int i = 0; i < len; i++) { JSValue ch = js_sub_string(ctx, p, i, i + 1); if (JS_IsException(ch)) { JS_FreeValue(ctx, result); return JS_EXCEPTION; } - JS_SetPropertyInt64(ctx, result, i, ch); + out->values[i] = ch; } + out->len = len; return result; } @@ -28099,46 +28103,34 @@ static JSValue js_cell_array_reduce(JSContext *ctx, JSValueConst this_val, if (!JS_IsArray(ctx, argv[0])) return JS_NULL; if (!JS_IsFunction(argv[1])) return JS_NULL; - JSValueConst arr = argv[0]; + JSArray *arr = JS_VALUE_GET_ARRAY(argv[0]); JSValueConst func = argv[1]; - int64_t len; - if (js_get_length64(ctx, &len, arr)) - return JS_EXCEPTION; + int len = arr->len; int reverse = argc > 3 && JS_ToBool(ctx, argv[3]); JSValue acc; if (argc < 3 || JS_IsNull(argv[2])) { if (len == 0) return JS_NULL; - if (len == 1) return JS_GetPropertyInt64(ctx, arr, 0); + if (len == 1) return JS_DupValue(ctx, arr->values[0]); if (reverse) { - acc = JS_GetPropertyInt64(ctx, arr, len - 1); - for (int64_t i = len - 2; i >= 0; i--) { - JSValue item = JS_GetPropertyInt64(ctx, arr, i); - if (JS_IsException(item)) { - JS_FreeValue(ctx, acc); - return JS_EXCEPTION; - } - JSValue args[2] = { acc, item }; - JSValue new_acc = JS_Call(ctx, func, JS_NULL, 2, args); - JS_FreeValue(ctx, acc); - JS_FreeValue(ctx, item); + acc = JS_DupValue(ctx, arr->values[len - 1]); + for (int i = len - 2; i >= 0; i--) { + JSValue args[2] = { acc, JS_DupValue(ctx, arr->values[i]) }; + JSValue new_acc = JS_CallInternal(ctx, func, JS_NULL, 2, args, 0); + JS_FreeValue(ctx, args[0]); + JS_FreeValue(ctx, args[1]); if (JS_IsException(new_acc)) return JS_EXCEPTION; acc = new_acc; } } else { - acc = JS_GetPropertyInt64(ctx, arr, 0); - for (int64_t i = 1; i < len; i++) { - JSValue item = JS_GetPropertyInt64(ctx, arr, i); - if (JS_IsException(item)) { - JS_FreeValue(ctx, acc); - return JS_EXCEPTION; - } - JSValue args[2] = { acc, item }; - JSValue new_acc = JS_Call(ctx, func, JS_NULL, 2, args); - JS_FreeValue(ctx, acc); - JS_FreeValue(ctx, item); + acc = JS_DupValue(ctx, arr->values[0]); + for (int i = 1; i < len; i++) { + JSValue args[2] = { acc, JS_DupValue(ctx, arr->values[i]) }; + JSValue new_acc = JS_CallInternal(ctx, func, JS_NULL, 2, args, 0); + JS_FreeValue(ctx, args[0]); + JS_FreeValue(ctx, args[1]); if (JS_IsException(new_acc)) return JS_EXCEPTION; acc = new_acc; } @@ -28148,30 +28140,20 @@ static JSValue js_cell_array_reduce(JSContext *ctx, JSValueConst this_val, acc = JS_DupValue(ctx, argv[2]); if (reverse) { - for (int64_t i = len - 1; i >= 0; i--) { - JSValue item = JS_GetPropertyInt64(ctx, arr, i); - if (JS_IsException(item)) { - JS_FreeValue(ctx, acc); - return JS_EXCEPTION; - } - JSValue args[2] = { acc, item }; - JSValue new_acc = JS_Call(ctx, func, JS_NULL, 2, args); - JS_FreeValue(ctx, acc); - JS_FreeValue(ctx, item); + for (int i = len - 1; i >= 0; i--) { + JSValue args[2] = { acc, JS_DupValue(ctx, arr->values[i]) }; + JSValue new_acc = JS_CallInternal(ctx, func, JS_NULL, 2, args, 0); + JS_FreeValue(ctx, args[0]); + JS_FreeValue(ctx, args[1]); if (JS_IsException(new_acc)) return JS_EXCEPTION; acc = new_acc; } } else { - for (int64_t i = 0; i < len; i++) { - JSValue item = JS_GetPropertyInt64(ctx, arr, i); - if (JS_IsException(item)) { - JS_FreeValue(ctx, acc); - return JS_EXCEPTION; - } - JSValue args[2] = { acc, item }; - JSValue new_acc = JS_Call(ctx, func, JS_NULL, 2, args); - JS_FreeValue(ctx, acc); - JS_FreeValue(ctx, item); + for (int i = 0; i < len; i++) { + JSValue args[2] = { acc, JS_DupValue(ctx, arr->values[i]) }; + JSValue new_acc = JS_CallInternal(ctx, func, JS_NULL, 2, args, 0); + JS_FreeValue(ctx, args[0]); + JS_FreeValue(ctx, args[1]); if (JS_IsException(new_acc)) return JS_EXCEPTION; acc = new_acc; } @@ -28199,7 +28181,7 @@ static JSValue js_cell_array_for(JSContext *ctx, JSValueConst this_val, JSValue exit_val = argc > 3 ? argv[3] : JS_NULL; /* Determine function arity */ - int arity = (JSFunction*)JS_VALUE_GET_FUNCTION(argv[1])->length; + int arity = ((JSFunction*)JS_VALUE_GET_FUNCTION(argv[1]))->length; if (reverse) { for (int i = len - 1; i >= 0; i--) { @@ -28257,15 +28239,13 @@ static JSValue js_cell_array_find(JSContext *ctx, JSValueConst this_val, if (argc < 2) return JS_NULL; if (!JS_IsArray(ctx, argv[0])) return JS_NULL; - JSValueConst arr = argv[0]; - int64_t len; - if (js_get_length64(ctx, &len, arr)) - return JS_EXCEPTION; + JSArray *arr = JS_VALUE_GET_ARRAY(argv[0]); + int len = arr->len; int reverse = argc > 2 && JS_ToBool(ctx, argv[2]); - int64_t from; + int from; if (argc > 3 && !JS_IsNull(argv[3])) { - if (JS_ToInt64(ctx, &from, argv[3])) + if (JS_ToInt32(ctx, &from, argv[3])) return JS_NULL; } else { from = reverse ? len - 1 : 0; @@ -28275,24 +28255,14 @@ static JSValue js_cell_array_find(JSContext *ctx, JSValueConst this_val, /* Compare exactly */ JSValue target = argv[1]; if (reverse) { - for (int64_t i = from; i >= 0; i--) { - JSValue item = JS_GetPropertyInt64(ctx, arr, i); - if (JS_IsException(item)) return JS_EXCEPTION; - if (js_strict_eq(ctx, item, target)) { - JS_FreeValue(ctx, item); - return JS_NewInt64(ctx, i); - } - JS_FreeValue(ctx, item); + for (int i = from; i >= 0; i--) { + if (js_strict_eq(ctx, arr->values[i], target)) + return JS_NewInt32(ctx, i); } } else { - for (int64_t i = from; i < len; i++) { - JSValue item = JS_GetPropertyInt64(ctx, arr, i); - if (JS_IsException(item)) return JS_EXCEPTION; - if (js_strict_eq(ctx, item, target)) { - JS_FreeValue(ctx, item); - return JS_NewInt64(ctx, i); - } - JS_FreeValue(ctx, item); + for (int i = from; i < len; i++) { + if (js_strict_eq(ctx, arr->values[i], target)) + return JS_NewInt32(ctx, i); } } return JS_NULL; @@ -28300,48 +28270,61 @@ static JSValue js_cell_array_find(JSContext *ctx, JSValueConst this_val, /* Use function predicate */ JSValueConst func = argv[1]; - int arity = (JSFunction*)JS_VALUE_GET_FUNCTION(argv[1])->length; - if (reverse) { - for (int64_t i = from; i >= 0; i--) { - JSValue item = JS_GetPropertyInt64(ctx, arr, i); - if (JS_IsException(item)) return JS_EXCEPTION; - JSValue result; - if (arity == 2) { - JSValue args[2] = { item, JS_NewInt64(ctx, i) }; - result = JS_Call(ctx, func, JS_NULL, 2, args); - JS_FreeValue(ctx, args[1]); - } else { - result = JS_Call(ctx, func, JS_NULL, 1, &item); - } - JS_FreeValue(ctx, item); + int arity = ((JSFunction*)JS_VALUE_GET_FUNCTION(argv[1]))->length; - if (JS_IsException(result)) return JS_EXCEPTION; - if (JS_ToBool(ctx, result)) { + if (arity == 2) { + if (reverse) { + for (int i = from; i >= 0; i--) { + JSValue args[2] = { JS_DupValue(ctx, arr->values[i]), JS_NewInt32(ctx, i) }; + JSValue result = JS_CallInternal(ctx, func, JS_NULL, 2, args, 0); + JS_FreeValue(ctx, args[0]); + JS_FreeValue(ctx, args[1]); + if (JS_IsException(result)) return JS_EXCEPTION; + if (JS_ToBool(ctx, result)) { + JS_FreeValue(ctx, result); + return JS_NewInt32(ctx, i); + } + JS_FreeValue(ctx, result); + } + } else { + for (int i = from; i < len; i++) { + JSValue args[2] = { JS_DupValue(ctx, arr->values[i]), JS_NewInt32(ctx, i) }; + JSValue result = JS_CallInternal(ctx, func, JS_NULL, 2, args, 0); + JS_FreeValue(ctx, args[0]); + JS_FreeValue(ctx, args[1]); + if (JS_IsException(result)) return JS_EXCEPTION; + if (JS_ToBool(ctx, result)) { + JS_FreeValue(ctx, result); + return JS_NewInt32(ctx, i); + } JS_FreeValue(ctx, result); - return JS_NewInt64(ctx, i); } - JS_FreeValue(ctx, result); } } else { - for (int64_t i = from; i < len; i++) { - JSValue item = JS_GetPropertyInt64(ctx, arr, i); - if (JS_IsException(item)) return JS_EXCEPTION; - JSValue result; - if (arity == 2) { - JSValue args[2] = { item, JS_NewInt64(ctx, i) }; - result = JS_Call(ctx, func, JS_NULL, 2, args); - JS_FreeValue(ctx, args[1]); - } else { - result = JS_Call(ctx, func, JS_NULL, 1, &item); - } - JS_FreeValue(ctx, item); - - if (JS_IsException(result)) return JS_EXCEPTION; - if (JS_ToBool(ctx, result)) { + if (reverse) { + for (int i = from; i >= 0; i--) { + JSValue item = JS_DupValue(ctx, arr->values[i]); + JSValue result = JS_CallInternal(ctx, func, JS_NULL, 1, &item, 0); + JS_FreeValue(ctx, item); + if (JS_IsException(result)) return JS_EXCEPTION; + if (JS_ToBool(ctx, result)) { + JS_FreeValue(ctx, result); + return JS_NewInt32(ctx, i); + } + JS_FreeValue(ctx, result); + } + } else { + for (int i = from; i < len; i++) { + JSValue item = JS_DupValue(ctx, arr->values[i]); + JSValue result = JS_CallInternal(ctx, func, JS_NULL, 1, &item, 0); + JS_FreeValue(ctx, item); + if (JS_IsException(result)) return JS_EXCEPTION; + if (JS_ToBool(ctx, result)) { + JS_FreeValue(ctx, result); + return JS_NewInt32(ctx, i); + } JS_FreeValue(ctx, result); - return JS_NewInt64(ctx, i); } - JS_FreeValue(ctx, result); } } @@ -28356,52 +28339,81 @@ static JSValue js_cell_array_filter(JSContext *ctx, JSValueConst this_val, if (!JS_IsArray(ctx, argv[0])) return JS_NULL; if (!JS_IsFunction(argv[1])) return JS_NULL; - JSValueConst arr = argv[0]; + JSArray *arr = JS_VALUE_GET_ARRAY(argv[0]); JSValueConst func = argv[1]; - int64_t len; - if (js_get_length64(ctx, &len, arr)) - return JS_EXCEPTION; + int len = arr->len; JSValue result = JS_NewArray(ctx); if (JS_IsException(result)) return result; + JSArray *out = JS_VALUE_GET_ARRAY(result); int arity = ((JSFunction*)JS_VALUE_GET_FUNCTION(func))->length; - int64_t out_idx = 0; - for (int64_t i = 0; i < len; i++) { - JSValue item = JS_GetPropertyInt64(ctx, arr, i); - if (JS_IsException(item)) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } - JSValue val; - if (arity == 0) { - val = JS_Call(ctx, func, JS_NULL, 0, NULL); - } else if (arity == 1) { - val = JS_Call(ctx, func, JS_NULL, 1, &item); - } else { - JSValue args[2] = { item, JS_NewInt64(ctx, i) }; - val = JS_Call(ctx, func, JS_NULL, 2, args); + if (arity >= 2) { + for (int i = 0; i < len; i++) { + JSValue args[2] = { JS_DupValue(ctx, arr->values[i]), JS_NewInt32(ctx, i) }; + JSValue val = JS_CallInternal(ctx, func, JS_NULL, 2, args, 0); JS_FreeValue(ctx, args[1]); + if (JS_IsException(val)) { + JS_FreeValue(ctx, args[0]); + JS_FreeValue(ctx, result); + return JS_EXCEPTION; + } + if (JS_VALUE_GET_TAG(val) == JS_TAG_BOOL) { + if (JS_VALUE_GET_BOOL(val)) { + js_intrinsic_array_push(ctx, out, args[0]); + } else { + JS_FreeValue(ctx, args[0]); + } + } else { + JS_FreeValue(ctx, args[0]); + JS_FreeValue(ctx, val); + JS_FreeValue(ctx, result); + return JS_NULL; + } + JS_FreeValue(ctx, val); } - if (JS_IsException(val)) { - JS_FreeValue(ctx, item); - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } - if (JS_VALUE_GET_TAG(val) == JS_TAG_BOOL) { - if (JS_VALUE_GET_BOOL(val)) { - JS_SetPropertyInt64(ctx, result, out_idx++, item); + } else if (arity == 1) { + for (int i = 0; i < len; i++) { + JSValue item = JS_DupValue(ctx, arr->values[i]); + JSValue val = JS_CallInternal(ctx, func, JS_NULL, 1, &item, 0); + if (JS_IsException(val)) { + JS_FreeValue(ctx, item); + JS_FreeValue(ctx, result); + return JS_EXCEPTION; + } + if (JS_VALUE_GET_TAG(val) == JS_TAG_BOOL) { + if (JS_VALUE_GET_BOOL(val)) { + js_intrinsic_array_push(ctx, out, item); + } else { + JS_FreeValue(ctx, item); + } } else { JS_FreeValue(ctx, item); + JS_FreeValue(ctx, val); + JS_FreeValue(ctx, result); + return JS_NULL; + } + JS_FreeValue(ctx, val); + } + } else { + for (int i = 0; i < len; i++) { + JSValue val = JS_CallInternal(ctx, func, JS_NULL, 0, NULL, 0); + if (JS_IsException(val)) { + JS_FreeValue(ctx, result); + return JS_EXCEPTION; + } + if (JS_VALUE_GET_TAG(val) == JS_TAG_BOOL) { + if (JS_VALUE_GET_BOOL(val)) { + js_intrinsic_array_push(ctx, out, JS_DupValue(ctx, arr->values[i])); + } + } else { + JS_FreeValue(ctx, val); + JS_FreeValue(ctx, result); + return JS_NULL; } - } else { - JS_FreeValue(ctx, item); JS_FreeValue(ctx, val); - JS_FreeValue(ctx, result); - return JS_NULL; } - JS_FreeValue(ctx, val); } return result; @@ -28414,10 +28426,8 @@ static JSValue js_cell_array_sort(JSContext *ctx, JSValueConst this_val, if (argc < 1) return JS_NULL; if (!JS_IsArray(ctx, argv[0])) return JS_NULL; - JSValueConst arr = argv[0]; - int64_t len; - if (js_get_length64(ctx, &len, arr)) - return JS_EXCEPTION; + JSArray *arr = JS_VALUE_GET_ARRAY(argv[0]); + int len = arr->len; /* Copy array */ JSValue result = JS_NewArrayLen(ctx, len); @@ -28425,6 +28435,7 @@ static JSValue js_cell_array_sort(JSContext *ctx, JSValueConst this_val, if (len == 0) return result; + JSArray *out = JS_VALUE_GET_ARRAY(result); JSValue *items = js_malloc(ctx, sizeof(JSValue) * len); double *keys = js_malloc(ctx, sizeof(double) * len); char **str_keys = NULL; @@ -28437,16 +28448,14 @@ static JSValue js_cell_array_sort(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } + /* Check if we have a key selector array */ + JSArray *key_arr = NULL; + if (argc >= 2 && JS_IsArray(ctx, argv[1])) + key_arr = JS_VALUE_GET_ARRAY(argv[1]); + /* Extract keys */ - for (int64_t i = 0; i < len; i++) { - items[i] = JS_GetPropertyInt64(ctx, arr, i); - if (JS_IsException(items[i])) { - for (int64_t j = 0; j < i; j++) JS_FreeValue(ctx, items[j]); - js_free(ctx, items); - js_free(ctx, keys); - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } + for (int i = 0; i < len; i++) { + items[i] = JS_DupValue(ctx, arr->values[i]); JSValue key; if (argc < 2 || JS_IsNull(argv[1])) { @@ -28455,17 +28464,28 @@ static JSValue js_cell_array_sort(JSContext *ctx, JSValueConst this_val, /* Numeric index - use for nested arrays */ int32_t idx; JS_ToInt32(ctx, &idx, argv[1]); - key = JS_GetPropertyInt64(ctx, items[i], idx); + if (JS_IsArray(ctx, items[i])) { + JSArray *nested = JS_VALUE_GET_ARRAY(items[i]); + if (idx >= 0 && idx < (int)nested->len) + key = JS_DupValue(ctx, nested->values[idx]); + else + key = JS_NULL; + } else { + key = JS_GetPropertyInt64(ctx, items[i], idx); + } } else if (JS_VALUE_GET_TAG(argv[1]) == JS_TAG_STRING) { key = JS_GetProperty(ctx, items[i], JS_ValueToAtom(ctx, argv[1])); - } else if (JS_IsArray(ctx, argv[1])) { - key = JS_GetPropertyInt64(ctx, argv[1], i); + } else if (key_arr) { + if (i < (int)key_arr->len) + key = JS_DupValue(ctx, key_arr->values[i]); + else + key = JS_NULL; } else { key = JS_DupValue(ctx, items[i]); } if (JS_IsException(key)) { - for (int64_t j = 0; j <= i; j++) JS_FreeValue(ctx, items[j]); + for (int j = 0; j <= i; j++) JS_FreeValue(ctx, items[j]); js_free(ctx, items); js_free(ctx, keys); JS_FreeValue(ctx, result); @@ -28482,7 +28502,7 @@ static JSValue js_cell_array_sort(JSContext *ctx, JSValueConst this_val, str_keys = js_malloc(ctx, sizeof(char*) * len); if (!str_keys) { JS_FreeValue(ctx, key); - for (int64_t j = 0; j <= i; j++) JS_FreeValue(ctx, items[j]); + for (int j = 0; j <= i; j++) JS_FreeValue(ctx, items[j]); js_free(ctx, items); js_free(ctx, keys); JS_FreeValue(ctx, result); @@ -28494,11 +28514,11 @@ static JSValue js_cell_array_sort(JSContext *ctx, JSValueConst this_val, } } else { JS_FreeValue(ctx, key); - for (int64_t j = 0; j <= i; j++) JS_FreeValue(ctx, items[j]); + for (int j = 0; j <= i; j++) JS_FreeValue(ctx, items[j]); js_free(ctx, items); js_free(ctx, keys); if (str_keys) { - for (int64_t j = 0; j < i; j++) JS_FreeCString(ctx, str_keys[j]); + for (int j = 0; j < i; j++) JS_FreeCString(ctx, str_keys[j]); js_free(ctx, str_keys); } JS_FreeValue(ctx, result); @@ -28508,24 +28528,24 @@ static JSValue js_cell_array_sort(JSContext *ctx, JSValueConst this_val, } /* Create index array */ - int64_t *indices = js_malloc(ctx, sizeof(int64_t) * len); + int *indices = js_malloc(ctx, sizeof(int) * len); if (!indices) { - for (int64_t j = 0; j < len; j++) JS_FreeValue(ctx, items[j]); + for (int j = 0; j < len; j++) JS_FreeValue(ctx, items[j]); js_free(ctx, items); js_free(ctx, keys); if (str_keys) { - for (int64_t j = 0; j < len; j++) JS_FreeCString(ctx, str_keys[j]); + for (int j = 0; j < len; j++) JS_FreeCString(ctx, str_keys[j]); js_free(ctx, str_keys); } JS_FreeValue(ctx, result); return JS_EXCEPTION; } - for (int64_t i = 0; i < len; i++) indices[i] = i; + for (int i = 0; i < len; i++) indices[i] = i; /* Simple insertion sort (stable) */ - for (int64_t i = 1; i < len; i++) { - int64_t temp = indices[i]; - int64_t j = i - 1; + for (int i = 1; i < len; i++) { + int temp = indices[i]; + int j = i - 1; while (j >= 0) { int cmp; if (is_string) { @@ -28541,18 +28561,19 @@ static JSValue js_cell_array_sort(JSContext *ctx, JSValueConst this_val, indices[j + 1] = temp; } - /* Build sorted array */ - for (int64_t i = 0; i < len; i++) { - JS_SetPropertyInt64(ctx, result, i, JS_DupValue(ctx, items[indices[i]])); + /* Build sorted array directly into output */ + for (int i = 0; i < len; i++) { + out->values[i] = JS_DupValue(ctx, items[indices[i]]); } + out->len = len; /* Cleanup */ - for (int64_t i = 0; i < len; i++) JS_FreeValue(ctx, items[i]); + for (int i = 0; i < len; i++) JS_FreeValue(ctx, items[i]); js_free(ctx, items); js_free(ctx, keys); js_free(ctx, indices); if (str_keys) { - for (int64_t i = 0; i < len; i++) JS_FreeCString(ctx, str_keys[i]); + for (int i = 0; i < len; i++) JS_FreeCString(ctx, str_keys[i]); js_free(ctx, str_keys); } @@ -28648,18 +28669,11 @@ static JSValue js_cell_object(JSContext *ctx, JSValueConst this_val, JSValue result = JS_NewObject(ctx); if (JS_IsException(result)) return result; - int64_t len; - if (js_get_length64(ctx, &len, argv[1])) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } + JSArray *keys = JS_VALUE_GET_ARRAY(argv[1]); + int len = keys->len; - for (int64_t i = 0; i < len; i++) { - JSValue key = JS_GetPropertyInt64(ctx, argv[1], i); - if (JS_IsException(key)) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } + for (int i = 0; i < len; i++) { + JSValue key = keys->values[i]; int key_tag = JS_VALUE_GET_TAG(key); if (key_tag == JS_TAG_STRING || key_tag == JS_TAG_STRING_ROPE) { JSAtom atom = JS_ValueToAtom(ctx, key); @@ -28672,7 +28686,6 @@ static JSValue js_cell_object(JSContext *ctx, JSValueConst this_val, } JS_FreeAtom(ctx, atom); } - JS_FreeValue(ctx, key); } return result; } @@ -28682,30 +28695,28 @@ static JSValue js_cell_object(JSContext *ctx, JSValueConst this_val, /* object(array_of_keys, value) - value set */ /* object(array_of_keys, function) - functional value set */ if (JS_IsArray(ctx, arg)) { - int64_t len; - if (js_get_length64(ctx, &len, arg)) - return JS_EXCEPTION; + JSArray *keys = JS_VALUE_GET_ARRAY(arg); + int len = keys->len; JSValue result = JS_NewObject(ctx); if (JS_IsException(result)) return result; - for (int64_t i = 0; i < len; i++) { - JSValue key = JS_GetPropertyInt64(ctx, arg, i); - if (JS_IsException(key)) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } + int is_func = argc >= 2 && JS_IsFunction(argv[1]); + + for (int i = 0; i < len; i++) { + JSValue key = keys->values[i]; int key_tag = JS_VALUE_GET_TAG(key); if (key_tag == JS_TAG_STRING || key_tag == JS_TAG_STRING_ROPE) { JSAtom atom = JS_ValueToAtom(ctx, key); JSValue val; if (argc < 2 || JS_IsNull(argv[1])) { val = JS_TRUE; - } else if (JS_IsFunction(argv[1])) { - val = JS_Call(ctx, argv[1], JS_NULL, 1, &key); + } else if (is_func) { + JSValue arg_key = JS_DupValue(ctx, key); + val = JS_CallInternal(ctx, argv[1], JS_NULL, 1, &arg_key, 0); + JS_FreeValue(ctx, arg_key); if (JS_IsException(val)) { JS_FreeAtom(ctx, atom); - JS_FreeValue(ctx, key); JS_FreeValue(ctx, result); return JS_EXCEPTION; } @@ -28715,7 +28726,6 @@ static JSValue js_cell_object(JSContext *ctx, JSValueConst this_val, JS_SetProperty(ctx, result, atom, val); JS_FreeAtom(ctx, atom); } - JS_FreeValue(ctx, key); } return result; } @@ -28737,34 +28747,35 @@ static JSValue js_cell_fn_apply(JSContext *ctx, JSValueConst this_val, JSValueConst func = argv[0]; if (argc < 2) { - return JS_Call(ctx, func, JS_NULL, 0, NULL); + return JS_CallInternal(ctx, func, JS_NULL, 0, NULL, 0); } JSValue args_val = argv[1]; if (!JS_IsArray(ctx, args_val)) { /* Wrap single value in array */ - return JS_Call(ctx, func, JS_NULL, 1, &args_val); + JSValue arg = JS_DupValue(ctx, args_val); + JSValue result = JS_CallInternal(ctx, func, JS_NULL, 1, &arg, 0); + JS_FreeValue(ctx, arg); + return result; } - int64_t len; - if (js_get_length64(ctx, &len, args_val)) - return JS_EXCEPTION; + JSArray *arr = JS_VALUE_GET_ARRAY(args_val); + int len = arr->len; - JSValue *args = js_malloc(ctx, sizeof(JSValue) * (len > 0 ? len : 1)); + if (len == 0) { + return JS_CallInternal(ctx, func, JS_NULL, 0, NULL, 0); + } + + JSValue *args = js_malloc(ctx, sizeof(JSValue) * len); if (!args) return JS_EXCEPTION; - for (int64_t i = 0; i < len; i++) { - args[i] = JS_GetPropertyInt64(ctx, args_val, i); - if (JS_IsException(args[i])) { - for (int64_t j = 0; j < i; j++) JS_FreeValue(ctx, args[j]); - js_free(ctx, args); - return JS_EXCEPTION; - } + for (int i = 0; i < len; i++) { + args[i] = JS_DupValue(ctx, arr->values[i]); } - JSValue result = JS_Call(ctx, func, JS_NULL, len, args); + JSValue result = JS_CallInternal(ctx, func, JS_NULL, len, args, 0); - for (int64_t i = 0; i < len; i++) JS_FreeValue(ctx, args[i]); + for (int i = 0; i < len; i++) JS_FreeValue(ctx, args[i]); js_free(ctx, args); return result; @@ -29419,16 +29430,16 @@ static JSValue js_cell_reverse(JSContext *ctx, JSValueConst this_val, /* Handle arrays */ if (JS_IsArray(ctx, value)) { - int64_t len; - if (js_get_length64(ctx, &len, value)) - return JS_NULL; + JSArray *arr = JS_VALUE_GET_ARRAY(value); + int len = arr->len; JSValue result = JS_NewArrayLen(ctx, len); if (JS_IsException(result)) return result; - for (int64_t i = len - 1, j = 0; i >= 0; i--, j++) { - JSValue elem = JS_GetPropertyInt64(ctx, value, i); - JS_SetPropertyInt64(ctx, result, j, elem); + JSArray *out = JS_VALUE_GET_ARRAY(result); + for (int i = len - 1, j = 0; i >= 0; i--, j++) { + out->values[j] = JS_DupValue(ctx, arr->values[i]); } + out->len = len; return result; } @@ -29758,10 +29769,8 @@ static JSValue js_cell_length(JSContext *ctx, JSValueConst this_val, /* Arrays return element count */ if (JS_IsArray(ctx, val)) { - int64_t len; - if (js_get_length64(ctx, &len, val) < 0) - return JS_EXCEPTION; - return JS_NewInt64(ctx, len); + JSArray *arr = JS_VALUE_GET_ARRAY(val); + return JS_NewInt32(ctx, arr->len); } /* Objects with length property */ @@ -29804,7 +29813,7 @@ static JSValue js_cell_call(JSContext *ctx, JSValueConst this_val, this_arg = argv[1]; if (argc < 3 || JS_IsNull(argv[2])) - return JS_Call(ctx, func, this_arg, 0, NULL); + return JS_CallInternal(ctx, func, this_arg, 0, NULL, 0); if (!JS_IsArray(ctx, argv[2])) return JS_ThrowTypeError(ctx, "third argument must be an array"); @@ -29814,7 +29823,7 @@ static JSValue js_cell_call(JSContext *ctx, JSValueConst this_val, if (!tab) return JS_EXCEPTION; - JSValue ret = JS_Call(ctx, func, this_arg, len, (JSValueConst *)tab); + JSValue ret = JS_CallInternal(ctx, func, this_arg, len, tab, 0); free_arg_list(ctx, tab, len); return ret; } diff --git a/source/quickjs.h b/source/quickjs.h index 50e7ebab..4cf56fa2 100644 --- a/source/quickjs.h +++ b/source/quickjs.h @@ -545,6 +545,11 @@ static inline JS_BOOL JS_IsFunction(JSValueConst v) return JS_VALUE_GET_TAG(v) == JS_TAG_FUNCTION; } +static inline JS_BOOL JS_IsInteger(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_INT; +} + static inline JS_BOOL JS_IsObject(JSValueConst v) { return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT;