intrinsic arrays
This commit is contained in:
6
fd.c
6
fd.c
@@ -502,10 +502,9 @@ JSC_SCALL(fd_readdir,
|
||||
ret = JS_ThrowInternalError(js, "FindFirstFile failed for %s", path);
|
||||
} else {
|
||||
ret = JS_NewArray(js);
|
||||
int i = 0;
|
||||
do {
|
||||
if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0) continue;
|
||||
JS_SetPropertyUint32(js, ret, i++, JS_NewString(js, ffd.cFileName));
|
||||
JS_ArrayPush(js, ret,JS_NewString(js, ffd.cFileName));
|
||||
} while (FindNextFile(hFind, &ffd) != 0);
|
||||
FindClose(hFind);
|
||||
}
|
||||
@@ -515,10 +514,9 @@ JSC_SCALL(fd_readdir,
|
||||
d = opendir(str);
|
||||
if (d) {
|
||||
ret = JS_NewArray(js);
|
||||
int i = 0;
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) continue;
|
||||
JS_SetPropertyUint32(js, ret, i++, JS_NewString(js, dir->d_name));
|
||||
JS_ArrayPush(js, ret, JS_NewString(js, dir->d_name));
|
||||
}
|
||||
closedir(d);
|
||||
} else {
|
||||
|
||||
@@ -304,31 +304,4 @@ int uncaught_exception(JSContext *js, JSValue v)
|
||||
JS_FreeValue(js, exp);
|
||||
JS_FreeValue(js, v);
|
||||
return 0;
|
||||
|
||||
|
||||
exp = JS_GetException(js);
|
||||
if (JS_IsNull(rt->on_exception)) {
|
||||
const char *str = JS_ToCString(js, exp);
|
||||
if (str) {
|
||||
printf("Uncaught exception: %s\n", str);
|
||||
JS_FreeCString(js, str);
|
||||
}
|
||||
|
||||
JSValue stack = JS_GetPropertyStr(js, exp, "stack");
|
||||
if (!JS_IsNull(stack)) {
|
||||
const char *stack_str = JS_ToCString(js, stack);
|
||||
if (stack_str) {
|
||||
printf("Stack trace:\n%s\n", stack_str);
|
||||
JS_FreeCString(js, stack_str);
|
||||
}
|
||||
}
|
||||
JS_FreeValue(js, stack);
|
||||
} else {
|
||||
JSValue ret = JS_Call(js, rt->on_exception, JS_NULL, 1, &exp);
|
||||
JS_FreeValue(js, ret);
|
||||
}
|
||||
|
||||
JS_FreeValue(js, exp);
|
||||
JS_FreeValue(js, v);
|
||||
return 0;
|
||||
}
|
||||
@@ -275,8 +275,7 @@ static char *decode_wota_value(JSContext *ctx, char *data_ptr, JSValue *out_val,
|
||||
case WOTA_ARR: {
|
||||
long long c;
|
||||
data_ptr = wota_read_array(&c, data_ptr);
|
||||
JSValue arr = JS_NewArray(ctx);
|
||||
JS_SetLength(ctx, arr, c);
|
||||
JSValue arr = JS_NewArrayLen(ctx, c);
|
||||
for (long long i = 0; i < c; i++) {
|
||||
JSValue elem_val = JS_NULL;
|
||||
JSAtom idx_atom = JS_NewAtomUInt32(ctx, (uint32_t)i);
|
||||
|
||||
367
source/quickjs.c
367
source/quickjs.c
@@ -876,8 +876,6 @@ static __maybe_unused void JS_DumpShapes(JSRuntime *rt);
|
||||
static void js_dump_value_write(void *opaque, const char *buf, size_t len);
|
||||
static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv, int magic);
|
||||
static void js_array_finalizer(JSRuntime *rt, JSValue val);
|
||||
static void js_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
|
||||
static void free_array(JSRuntime *rt, JSArray *arr);
|
||||
static void js_c_function_finalizer(JSRuntime *rt, JSValue val);
|
||||
static void js_c_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
|
||||
@@ -920,6 +918,12 @@ static JSValue JS_ToObject(JSContext *ctx, JSValueConst val);
|
||||
static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val);
|
||||
static JSValue js_cell_text(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv);
|
||||
static JSValue js_cell_push(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv);
|
||||
static JSValue js_cell_pop(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv);
|
||||
static JSValue js_cell_array_find(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv);
|
||||
static JSProperty *add_property(JSContext *ctx,
|
||||
JSObject *p, JSAtom prop, int prop_flags);
|
||||
JSValue JS_ThrowOutOfMemory(JSContext *ctx);
|
||||
@@ -4751,7 +4755,7 @@ JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto)
|
||||
}
|
||||
|
||||
/* Create an intrinsic array with specified capacity */
|
||||
static JSValue JS_NewArrayLen(JSContext *ctx, uint32_t len)
|
||||
JSValue JS_NewArrayLen(JSContext *ctx, uint32_t len)
|
||||
{
|
||||
JSRuntime *rt = ctx->rt;
|
||||
JSArray *arr;
|
||||
@@ -5093,27 +5097,6 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref)
|
||||
}
|
||||
}
|
||||
|
||||
static void js_array_finalizer(JSRuntime *rt, JSValue val)
|
||||
{
|
||||
JSObject *p = JS_VALUE_GET_OBJ(val);
|
||||
int i;
|
||||
|
||||
for(i = 0; i < p->u.array.count; i++) {
|
||||
JS_FreeValueRT(rt, p->u.array.u.values[i]);
|
||||
}
|
||||
js_free_rt(rt, p->u.array.u.values);
|
||||
}
|
||||
|
||||
static void js_array_mark(JSRuntime *rt, JSValueConst val,
|
||||
JS_MarkFunc *mark_func)
|
||||
{
|
||||
JSObject *p = JS_VALUE_GET_OBJ(val);
|
||||
int i;
|
||||
|
||||
for(i = 0; i < p->u.array.count; i++) {
|
||||
JS_MarkValue(rt, p->u.array.u.values[i], mark_func);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free intrinsic array (JS_TAG_ARRAY) */
|
||||
static void free_array(JSRuntime *rt, JSArray *arr)
|
||||
@@ -6698,6 +6681,18 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
||||
return JS_NULL;
|
||||
case JS_TAG_EXCEPTION:
|
||||
return JS_EXCEPTION;
|
||||
case JS_TAG_ARRAY:
|
||||
{
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY(obj);
|
||||
/* Only integer indexed access is allowed on arrays */
|
||||
if (__JS_AtomIsTaggedInt(prop)) {
|
||||
uint32_t idx = __JS_AtomToUInt32(prop);
|
||||
if (idx < arr->len) {
|
||||
return JS_DupValue(ctx, arr->values[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return JS_NULL;
|
||||
case JS_TAG_STRING:
|
||||
{
|
||||
JSString *p1 = JS_VALUE_GET_STRING(obj);
|
||||
@@ -7129,6 +7124,19 @@ JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val)
|
||||
return atom;
|
||||
}
|
||||
|
||||
static uint32_t js_string_get_length(JSValueConst val)
|
||||
{
|
||||
if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) {
|
||||
JSString *p = JS_VALUE_GET_STRING(val);
|
||||
return p->len;
|
||||
} else if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING_ROPE) {
|
||||
JSStringRope *r = JS_VALUE_GET_PTR(val);
|
||||
return r->len;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
|
||||
JSValue prop)
|
||||
{
|
||||
@@ -7138,37 +7146,38 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
|
||||
int this_tag = JS_VALUE_GET_TAG(this_obj);
|
||||
|
||||
if (this_tag == JS_TAG_NULL) {
|
||||
JS_FreeValue(js, prop);
|
||||
JS_FreeValue(ctx, prop);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
if (this_tag == JS_TAG_ARRAY) {
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY(this_obj);
|
||||
if (prop_tag == JS_TAG_INT) {
|
||||
int idx = JS_VALUE_GET_INT(prop);
|
||||
if (idx < 0 || idx >= JS_VALUE_GET_ARRAY(this_obj)->len) {
|
||||
if (idx < 0 || (uint32_t)idx >= arr->len) {
|
||||
return JS_NULL;
|
||||
}
|
||||
return JS_DupValue(ctx, JS_VALUE_GET_ARRAY(this_obj)->values[idx]);
|
||||
return JS_DupValue(ctx, arr->values[idx]);
|
||||
}
|
||||
|
||||
if (prop_tag == JS_TAG_FLOAT64) {
|
||||
double d = JS_VALUE_GET_FLOAT64(prop);
|
||||
if (d < 0 || d >= JS_VALUE_GET_ARRAY(this_obj)->len) {
|
||||
uint32_t idx = (uint32_t)d;
|
||||
if (d < 0 || d != (double)idx || idx >= arr->len) {
|
||||
return JS_NULL;
|
||||
}
|
||||
return JS_DupValue(ctx, JS_VALUE_GET_ARRAY(this_obj)->values[(int)d]);
|
||||
return JS_DupValue(ctx, arr->values[idx]);
|
||||
}
|
||||
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
if (this_tag == JS_TAG_OBJECT) {
|
||||
|
||||
JS_FreeValue(ctx, prop);
|
||||
return JS_ThrowTypeError(ctx, "array index must be a number");
|
||||
}
|
||||
|
||||
if (this_tag == JS_TAG_OBJECT) {
|
||||
/* Records only accept string or object keys */
|
||||
if (prop_tag == JS_TAG_INT || prop_tag == JS_TAG_FLOAT64) {
|
||||
return JS_EXCEPTION;
|
||||
JS_FreeValue(ctx, prop);
|
||||
return JS_ThrowTypeError(ctx, "record index must be text or record");
|
||||
}
|
||||
|
||||
if (prop_tag == JS_TAG_STRING || prop_tag == JS_TAG_STRING_ROPE) {
|
||||
@@ -7178,7 +7187,48 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
|
||||
JS_FreeAtom(ctx, atom);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (prop_tag == JS_TAG_OBJECT) {
|
||||
/* Object key - handled via symbol lookup */
|
||||
atom = JS_ValueToAtom(ctx, prop);
|
||||
JS_FreeValue(ctx, prop);
|
||||
if (atom == JS_ATOM_NULL)
|
||||
return JS_EXCEPTION;
|
||||
ret = JS_GetProperty(ctx, this_obj, atom);
|
||||
JS_FreeAtom(ctx, atom);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JS_FreeValue(ctx, prop);
|
||||
return JS_ThrowTypeError(ctx, "record index must be text or record");
|
||||
}
|
||||
|
||||
if (this_tag == JS_TAG_STRING || this_tag == JS_TAG_STRING_ROPE) {
|
||||
if (prop_tag == JS_TAG_INT) {
|
||||
int idx = JS_VALUE_GET_INT(prop);
|
||||
uint32_t len = js_string_get_length(this_obj);
|
||||
if (idx < 0 || (uint32_t)idx >= len) {
|
||||
return JS_NULL;
|
||||
}
|
||||
return js_sub_string(ctx, JS_VALUE_GET_STRING(this_obj), idx, idx + 1);
|
||||
}
|
||||
|
||||
if (prop_tag == JS_TAG_FLOAT64) {
|
||||
double d = JS_VALUE_GET_FLOAT64(prop);
|
||||
uint32_t idx = (uint32_t)d;
|
||||
uint32_t len = js_string_get_length(this_obj);
|
||||
if (d < 0 || d != (double)idx || idx >= len) {
|
||||
return JS_NULL;
|
||||
}
|
||||
return js_sub_string(ctx, JS_VALUE_GET_STRING(this_obj), idx, idx + 1);
|
||||
}
|
||||
|
||||
JS_FreeValue(ctx, prop);
|
||||
return JS_ThrowTypeError(ctx, "string index must be a number");
|
||||
}
|
||||
|
||||
JS_FreeValue(ctx, prop);
|
||||
return JS_ThrowTypeError(ctx, "cannot read property of this value: %d", this_tag);
|
||||
}
|
||||
|
||||
JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
|
||||
@@ -7405,6 +7455,23 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
||||
|
||||
tag = JS_VALUE_GET_TAG(this_obj);
|
||||
if (unlikely(tag != JS_TAG_OBJECT)) {
|
||||
if (tag == JS_TAG_ARRAY) {
|
||||
/* Arrays only accept integer index via JS_SetPropertyValue */
|
||||
JS_FreeValue(ctx, val);
|
||||
if (__JS_AtomIsTaggedInt(prop)) {
|
||||
uint32_t idx = __JS_AtomToUInt32(prop);
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY(this_obj);
|
||||
if (idx < arr->len) {
|
||||
/* This path shouldn't be used for arrays - use JS_SetPropertyValue */
|
||||
JS_ThrowTypeError(ctx, "use JS_SetPropertyValue for array element access");
|
||||
} else {
|
||||
JS_ThrowRangeError(ctx, "array index out of bounds");
|
||||
}
|
||||
} else {
|
||||
JS_ThrowTypeError(ctx, "array index must be a number");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
|
||||
p = NULL;
|
||||
p1 = JS_VALUE_GET_OBJ(obj);
|
||||
@@ -7545,6 +7612,8 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
||||
static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
|
||||
JSValue prop, JSValue val, int flags)
|
||||
{
|
||||
JSAtom atom;
|
||||
int ret;
|
||||
uint32_t prop_tag = JS_VALUE_GET_TAG(prop);
|
||||
int this_tag = JS_VALUE_GET_TAG(this_obj);
|
||||
|
||||
@@ -7577,12 +7646,13 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
|
||||
double d = JS_VALUE_GET_FLOAT64(prop);
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY(this_obj);
|
||||
JS_FreeValue(ctx, prop);
|
||||
if (d < 0 || d >= arr->len || d != (double)(uint32_t)d) {
|
||||
uint32_t idx = (uint32_t)d;
|
||||
if (d < 0 || d != (double)idx || idx >= arr->len) {
|
||||
JS_FreeValue(ctx, val);
|
||||
JS_ThrowRangeError(ctx, "array index out of bounds");
|
||||
return -1;
|
||||
}
|
||||
set_value(ctx, &arr->values[(uint32_t)d], val);
|
||||
set_value(ctx, &arr->values[idx], val);
|
||||
return TRUE;
|
||||
}
|
||||
JS_FreeValue(ctx, prop);
|
||||
@@ -7592,7 +7662,9 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
|
||||
|
||||
if (this_tag == JS_TAG_OBJECT) {
|
||||
if (prop_tag != JS_TAG_STRING && prop_tag != JS_TAG_STRING_ROPE && prop_tag != JS_TAG_OBJECT) {
|
||||
JS_ThrowTypeError(ctx, "record index must be a text or record");
|
||||
JS_FreeValue(ctx, prop);
|
||||
JS_FreeValue(ctx, val);
|
||||
JS_ThrowTypeError(ctx, "record index must be text or record");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -7606,6 +7678,12 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
|
||||
JS_FreeAtom(ctx, atom);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Not an array or object */
|
||||
JS_FreeValue(ctx, prop);
|
||||
JS_FreeValue(ctx, val);
|
||||
JS_ThrowTypeError(ctx, "cannot set property on this value");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
|
||||
@@ -7848,6 +7926,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
|
||||
return -1;
|
||||
}
|
||||
JS_ThrowTypeError(ctx, "intrinsic arrays only support numeric indices");
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -7983,26 +8062,9 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
|
||||
prs->flags &= ~(JS_PROP_TMASK | JS_PROP_WRITABLE);
|
||||
}
|
||||
} else if (prs->flags & JS_PROP_LENGTH) {
|
||||
if (flags & JS_PROP_HAS_VALUE) {
|
||||
/* Note: no JS code is executable because
|
||||
'val' is guaranted to be a Uint32 */
|
||||
res = set_array_length(ctx, p, JS_DupValue(ctx, val),
|
||||
flags);
|
||||
} else {
|
||||
res = TRUE;
|
||||
}
|
||||
/* still need to reset the writable flag if
|
||||
needed. The JS_PROP_LENGTH is kept because the
|
||||
Uint32 test is still done if the length
|
||||
property is read-only. */
|
||||
if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) ==
|
||||
JS_PROP_HAS_WRITABLE) {
|
||||
prs = get_shape_prop(p->shape);
|
||||
if (js_update_property_flags(ctx, p, &prs,
|
||||
prs->flags & ~JS_PROP_WRITABLE))
|
||||
return -1;
|
||||
}
|
||||
return res;
|
||||
/* Object-based arrays removed - length property not supported */
|
||||
JS_ThrowTypeError(ctx, "cannot set length property");
|
||||
return -1;
|
||||
} else {
|
||||
if (flags & JS_PROP_HAS_VALUE) {
|
||||
JS_FreeValue(ctx, pr->u.value);
|
||||
@@ -8438,6 +8500,15 @@ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags)
|
||||
JSObject *p;
|
||||
int res;
|
||||
|
||||
/* Arrays do not support property deletion */
|
||||
if (JS_VALUE_GET_TAG(obj) == JS_TAG_ARRAY) {
|
||||
if (flags & (JS_PROP_THROW | JS_PROP_THROW_STRICT)) {
|
||||
JS_ThrowTypeError(ctx, "cannot delete array element");
|
||||
return -1;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
obj1 = JS_ToObject(ctx, obj);
|
||||
if (JS_IsException(obj1))
|
||||
return -1;
|
||||
@@ -8446,7 +8517,7 @@ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags)
|
||||
JS_FreeValue(ctx, obj1);
|
||||
if (res != FALSE)
|
||||
return res;
|
||||
if (flags & JS_PROP_THROW ||
|
||||
if (flags & JS_PROP_THROW ||
|
||||
flags & JS_PROP_THROW_STRICT) {
|
||||
JS_ThrowTypeError(ctx, "could not delete property");
|
||||
return -1;
|
||||
@@ -9467,19 +9538,6 @@ static void js_print_float64(JSPrintValueState *s, double d)
|
||||
s->write_func(s->write_opaque, buf, len);
|
||||
}
|
||||
|
||||
static uint32_t js_string_get_length(JSValueConst val)
|
||||
{
|
||||
if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) {
|
||||
JSString *p = JS_VALUE_GET_STRING(val);
|
||||
return p->len;
|
||||
} else if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING_ROPE) {
|
||||
JSStringRope *r = JS_VALUE_GET_PTR(val);
|
||||
return r->len;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void js_dump_char(JSPrintValueState *s, int c, int sep)
|
||||
{
|
||||
if (c == sep || c == '\\') {
|
||||
@@ -9867,6 +9925,29 @@ static void js_print_value(JSPrintValueState *s, JSValueConst val)
|
||||
js_putc(s, ')');
|
||||
}
|
||||
break;
|
||||
case JS_TAG_ARRAY:
|
||||
{
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY(val);
|
||||
uint32_t i, count;
|
||||
js_putc(s, '[');
|
||||
count = min_uint32(arr->len, s->options.max_item_count);
|
||||
for (i = 0; i < count; i++) {
|
||||
if (i > 0)
|
||||
js_puts(s, ", ");
|
||||
if (s->level < s->options.max_depth) {
|
||||
s->level++;
|
||||
js_print_value(s, arr->values[i]);
|
||||
s->level--;
|
||||
} else {
|
||||
js_puts(s, "...");
|
||||
}
|
||||
}
|
||||
if (arr->len > count) {
|
||||
js_printf(s, ", ... %u more", arr->len - count);
|
||||
}
|
||||
js_putc(s, ']');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
js_printf(s, "[unknown tag %d]", tag);
|
||||
break;
|
||||
@@ -24460,6 +24541,18 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)
|
||||
if (JS_WriteFunctionTag(s, obj))
|
||||
goto fail;
|
||||
break;
|
||||
case JS_TAG_ARRAY:
|
||||
{
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY(obj);
|
||||
uint32_t i;
|
||||
bc_put_u8(s, BC_TAG_ARRAY);
|
||||
bc_put_leb128(s, arr->len);
|
||||
for (i = 0; i < arr->len; i++) {
|
||||
if (JS_WriteObjectRec(s, arr->values[i]))
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JS_TAG_OBJECT:
|
||||
{
|
||||
JSObject *p = JS_VALUE_GET_OBJ(obj);
|
||||
@@ -25158,38 +25251,39 @@ static JSValue JS_ReadArray(BCReaderState *s, int tag)
|
||||
JSValue obj;
|
||||
uint32_t len, i;
|
||||
JSValue val;
|
||||
int ret, prop_flags;
|
||||
BOOL is_template;
|
||||
|
||||
obj = JS_NewArray(ctx);
|
||||
if (BC_add_object_ref(s, obj))
|
||||
goto fail;
|
||||
is_template = (tag == BC_TAG_TEMPLATE_OBJECT);
|
||||
|
||||
if (bc_get_leb128(s, &len))
|
||||
goto fail;
|
||||
for(i = 0; i < len; i++) {
|
||||
return JS_EXCEPTION;
|
||||
|
||||
/* Create intrinsic array with preallocated capacity */
|
||||
obj = JS_NewArrayLen(ctx, len);
|
||||
if (JS_IsException(obj))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
/* Note: intrinsic arrays don't support object reference tracking
|
||||
for circular references - they're simpler value containers */
|
||||
|
||||
/* Read and set each element directly */
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY(obj);
|
||||
for (i = 0; i < len; i++) {
|
||||
val = JS_ReadObjectRec(s);
|
||||
if (JS_IsException(val))
|
||||
goto fail;
|
||||
if (is_template)
|
||||
prop_flags = JS_PROP_ENUMERABLE;
|
||||
else
|
||||
prop_flags = JS_PROP_C_W_E;
|
||||
ret = JS_DefinePropertyValueUint32(ctx, obj, i, val,
|
||||
prop_flags);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
/* Replace the null placeholder with the read value */
|
||||
JS_FreeValue(ctx, arr->values[i]);
|
||||
arr->values[i] = val;
|
||||
}
|
||||
|
||||
/* Template objects have additional 'raw' property - not supported for intrinsic arrays */
|
||||
if (is_template) {
|
||||
val = JS_ReadObjectRec(s);
|
||||
if (JS_IsException(val))
|
||||
goto fail;
|
||||
if (!JS_IsNull(val)) {
|
||||
ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_raw, val, 0);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
}
|
||||
JS_PreventExtensions(ctx, obj);
|
||||
/* Skip the raw property for intrinsic arrays */
|
||||
JS_FreeValue(ctx, val);
|
||||
}
|
||||
return obj;
|
||||
fail:
|
||||
@@ -26570,32 +26664,8 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
t = JS_NewInt32(ctx, (capture[0] - str_buf) >> shift);
|
||||
if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_index, t, prop_flags) < 0)
|
||||
goto fail;
|
||||
|
||||
|
||||
t = str_val, str_val = JS_NULL;
|
||||
if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_input, t, prop_flags) < 0)
|
||||
goto fail;
|
||||
|
||||
t = groups, groups = JS_NULL;
|
||||
if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_groups,
|
||||
t, prop_flags) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!JS_IsNull(indices)) {
|
||||
t = indices_groups, indices_groups = JS_NULL;
|
||||
if (JS_DefinePropertyValue(ctx, indices, JS_ATOM_groups,
|
||||
t, prop_flags) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
t = indices, indices = JS_NULL;
|
||||
if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_indices,
|
||||
t, prop_flags) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = obj;
|
||||
obj = JS_NULL;
|
||||
@@ -29188,8 +29258,6 @@ static JSValue js_cell_text_extract(JSContext *ctx, JSValueConst this_val,
|
||||
}
|
||||
|
||||
JS_DefinePropertyValueUint32(ctx, arr, 0, match, JS_PROP_C_W_E);
|
||||
JS_DefinePropertyValueStr(ctx, arr, "index", JS_NewInt32(ctx, pos), JS_PROP_C_W_E);
|
||||
JS_DefinePropertyValueStr(ctx, arr, "input", JS_DupValue(ctx, str), JS_PROP_C_W_E);
|
||||
|
||||
/* str removed - arg not owned */
|
||||
return arr;
|
||||
@@ -29218,13 +29286,10 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
|
||||
if (d < 0) return JS_NULL;
|
||||
int64_t len = (int64_t)floor(d);
|
||||
|
||||
JSValue result = JS_NewArray(ctx);
|
||||
JSValue result = JS_NewArrayLen(ctx, len);
|
||||
if (JS_IsException(result)) return result;
|
||||
|
||||
if (argc < 2 || JS_IsNull(argv[1])) {
|
||||
/* Just set length */
|
||||
JS_SetPropertyStr(ctx, result, "length", JS_NewInt64(ctx, len > 100 ? 100 : len));
|
||||
} else if (JS_IsFunction(ctx, argv[1])) {
|
||||
if (JS_IsFunction(ctx, argv[1])) {
|
||||
/* Fill with function results */
|
||||
JSValueConst func = argv[1];
|
||||
int arity = 0;
|
||||
@@ -29264,8 +29329,7 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_EXCEPTION;
|
||||
|
||||
if (argc < 2 || JS_IsNull(argv[1])) {
|
||||
/* Copy */
|
||||
JSValue result = JS_NewArray(ctx);
|
||||
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);
|
||||
@@ -29284,7 +29348,7 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
|
||||
int reverse = argc > 2 && JS_ToBool(ctx, argv[2]);
|
||||
JSValue exit_val = argc > 3 ? argv[3] : JS_NULL;
|
||||
|
||||
JSValue result = JS_NewArray(ctx);
|
||||
JSValue result = JS_NewArrayLen(ctx, len);
|
||||
if (JS_IsException(result)) return result;
|
||||
|
||||
if (reverse) {
|
||||
@@ -29340,7 +29404,7 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
|
||||
if (js_get_length64(ctx, &len2, argv[1]))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
JSValue result = JS_NewArray(ctx);
|
||||
JSValue result = JS_NewArrayLen(ctx, len + len2);
|
||||
if (JS_IsException(result)) return result;
|
||||
|
||||
int64_t idx = 0;
|
||||
@@ -29417,7 +29481,7 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
|
||||
|
||||
if (argc < 2 || JS_IsNull(argv[1])) {
|
||||
/* Split into characters */
|
||||
JSValue result = JS_NewArray(ctx);
|
||||
JSValue result = JS_NewArrayLen(ctx, len);
|
||||
if (JS_IsException(result)) {
|
||||
return result;
|
||||
}
|
||||
@@ -29444,7 +29508,23 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
JSValue result = JS_NewArray(ctx);
|
||||
size_t sep_len = strlen(sep);
|
||||
|
||||
/* Count the number of parts first */
|
||||
int64_t count = 0;
|
||||
if (sep_len == 0) {
|
||||
count = len;
|
||||
} else {
|
||||
const char *pos = cstr;
|
||||
const char *found;
|
||||
count = 1;
|
||||
while ((found = strstr(pos, sep)) != NULL) {
|
||||
count++;
|
||||
pos = found + sep_len;
|
||||
}
|
||||
}
|
||||
|
||||
JSValue result = JS_NewArrayLen(ctx, count);
|
||||
if (JS_IsException(result)) {
|
||||
JS_FreeCString(ctx, cstr);
|
||||
JS_FreeCString(ctx, sep);
|
||||
@@ -29452,7 +29532,6 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
|
||||
}
|
||||
|
||||
int64_t idx = 0;
|
||||
size_t sep_len = strlen(sep);
|
||||
const char *pos = cstr;
|
||||
const char *found;
|
||||
|
||||
@@ -31035,7 +31114,7 @@ static JSValue js_cell_reverse(JSContext *ctx, JSValueConst this_val,
|
||||
* proto() function - get prototype of an object
|
||||
* ============================================================================ */
|
||||
|
||||
static JSValue js_cell_pop(JSContext *ctx, JSValueConst this_val,
|
||||
static JSValue js_cell_pop(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
if (argc < 1)
|
||||
@@ -31050,11 +31129,33 @@ static JSValue js_cell_reverse(JSContext *ctx, JSValueConst this_val,
|
||||
if (arr->len == 0)
|
||||
return JS_NULL;
|
||||
|
||||
JSValue last = JS_DupValue(ctx, arr->values[arr->len-1]);
|
||||
/* Transfer ownership: take value without dup, clear slot, decrement len */
|
||||
JSValue last = arr->values[arr->len - 1];
|
||||
arr->values[arr->len - 1] = JS_NULL;
|
||||
arr->len--;
|
||||
return last;
|
||||
}
|
||||
|
||||
JSValue JS_ArrayPush(JSContext *ctx, JSValueConst obj, JSValueConst val)
|
||||
{
|
||||
if (!JS_IsArray(ctx, obj))
|
||||
return JS_ThrowTypeError(ctx, "not an array");
|
||||
|
||||
JSValue stack[2];
|
||||
stack[0] = obj;
|
||||
stack[1] = val;
|
||||
|
||||
return js_cell_push(ctx, JS_NULL, 2, stack);
|
||||
}
|
||||
|
||||
JSValue JS_ArrayPop(JSContext *ctx, JSValueConst obj)
|
||||
{
|
||||
if (!JS_IsArray(ctx, obj))
|
||||
return JS_ThrowTypeError(ctx, "not an array");
|
||||
|
||||
return js_cell_pop(ctx, JS_NULL, 1, &obj);
|
||||
}
|
||||
|
||||
static JSValue js_cell_push(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
|
||||
@@ -669,9 +669,12 @@ JSValue JS_NewObject(JSContext *ctx);
|
||||
JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val);
|
||||
|
||||
JSValue JS_NewArray(JSContext *ctx);
|
||||
JSValue JS_NewArrayLen(JSContext *ctx, uint32_t len);
|
||||
int JS_IsArray(JSContext *ctx, JSValueConst val);
|
||||
int JS_GetLength(JSContext *ctx, JSValueConst obj, int64_t *pres);
|
||||
int JS_SetLength(JSContext *ctx, JSValueConst obj, int64_t len);
|
||||
JSValue JS_ArrayPush(JSContext *ctx, JSValueConst obj, JSValueConst val);
|
||||
JSValue JS_ArrayPop(JSContext *ctx, JSValueConst obj);
|
||||
|
||||
JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
||||
JSAtom prop, JSValueConst receiver,
|
||||
|
||||
Reference in New Issue
Block a user