fix tests
This commit is contained in:
@@ -4885,6 +4885,54 @@ static void free_array(JSRuntime *rt, JSArray *arr)
|
||||
js_free_rt(rt, arr);
|
||||
}
|
||||
|
||||
static int js_intrinsic_array_ensure_capacity(JSContext *ctx, JSArray *arr, uint32_t min_cap)
|
||||
{
|
||||
if (min_cap <= arr->cap)
|
||||
return 0;
|
||||
|
||||
uint32_t new_cap = arr->cap ? arr->cap : JS_ARRAY_INITIAL_SIZE;
|
||||
while (new_cap < min_cap) {
|
||||
if (new_cap > UINT32_MAX / 2) {
|
||||
new_cap = min_cap;
|
||||
break;
|
||||
}
|
||||
new_cap *= 2;
|
||||
}
|
||||
|
||||
JSValue *new_values = js_realloc(ctx, arr->values, sizeof(JSValue) * new_cap);
|
||||
if (!new_values)
|
||||
return -1;
|
||||
|
||||
arr->values = new_values;
|
||||
arr->cap = new_cap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int js_intrinsic_array_set(JSContext *ctx, JSArray *arr, uint32_t idx, JSValue val)
|
||||
{
|
||||
if (arr->stone) {
|
||||
JS_FreeValue(ctx, val);
|
||||
JS_ThrowInternalError(ctx, "cannot set on a stoned array");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (js_intrinsic_array_ensure_capacity(ctx, arr, idx + 1) < 0) {
|
||||
JS_FreeValue(ctx, val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (idx >= arr->len) {
|
||||
for (uint32_t i = arr->len; i < idx; i++) {
|
||||
arr->values[i] = JS_NULL;
|
||||
}
|
||||
arr->len = idx + 1;
|
||||
arr->values[idx] = val;
|
||||
} else {
|
||||
set_value(ctx, &arr->values[idx], val);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Push element to intrinsic array, growing if needed. Returns -1 on error, 0 on success. */
|
||||
static int js_intrinsic_array_push(JSContext *ctx, JSArray *arr, JSValue val)
|
||||
{
|
||||
@@ -6612,24 +6660,19 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
|
||||
int JS_SetPropertyNumber(JSContext *js, JSValueConst obj, int idx, JSValue val)
|
||||
{
|
||||
if (JS_VALUE_GET_TAG(obj) != JS_TAG_ARRAY) {
|
||||
JS_FreeValue(js, val);
|
||||
JS_ThrowInternalError(js, "cannot set with a number on a non array");
|
||||
return -1;
|
||||
}
|
||||
|
||||
JSArray *a = JS_VALUE_GET_ARRAY(obj);
|
||||
int len = a->len;
|
||||
if (idx < 0 || idx >= len) {
|
||||
JS_ThrowInternalError(js, "index out of bounds");
|
||||
if (idx < 0) {
|
||||
JS_FreeValue(js, val);
|
||||
JS_ThrowRangeError(js, "array index out of bounds");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (a->stone) {
|
||||
JS_ThrowInternalError(js, "cannot set on a stoned array");
|
||||
return -1;
|
||||
}
|
||||
|
||||
a->values[idx] = JS_DupValue(js, val);
|
||||
return TRUE;
|
||||
return js_intrinsic_array_set(js, a, (uint32_t)idx, val);
|
||||
}
|
||||
|
||||
JSValue JS_GetPropertyNumber(JSContext *js, JSValueConst obj, int idx)
|
||||
@@ -6868,15 +6911,13 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, JSValue pr
|
||||
if (likely(this_tag == JS_TAG_ARRAY && prop_tag == JS_TAG_INT)) {
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY(this_obj);
|
||||
int32_t signed_idx = JS_VALUE_GET_INT(prop);
|
||||
/* Throw for negative index or out of bounds */
|
||||
if (signed_idx < 0 || (uint32_t)signed_idx >= arr->len) {
|
||||
if (signed_idx < 0) {
|
||||
JS_FreeValue(ctx, val);
|
||||
JS_ThrowRangeError(ctx, "array index %d out of bounds (length %u)",
|
||||
signed_idx, arr->len);
|
||||
return -1;
|
||||
}
|
||||
set_value(ctx, &arr->values[signed_idx], val);
|
||||
return TRUE;
|
||||
return js_intrinsic_array_set(ctx, arr, (uint32_t)signed_idx, val);
|
||||
}
|
||||
|
||||
/* Intrinsic array slow path - handle non-int index */
|
||||
@@ -6894,13 +6935,12 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, JSValue pr
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY(this_obj);
|
||||
JS_FreeValue(ctx, prop);
|
||||
uint32_t idx = (uint32_t)d;
|
||||
if (d < 0 || d != (double)idx || idx >= arr->len) {
|
||||
if (d < 0 || d != (double)idx) {
|
||||
JS_FreeValue(ctx, val);
|
||||
JS_ThrowRangeError(ctx, "array index out of bounds");
|
||||
return -1;
|
||||
}
|
||||
set_value(ctx, &arr->values[idx], val);
|
||||
return TRUE;
|
||||
return js_intrinsic_array_set(ctx, arr, idx, val);
|
||||
}
|
||||
JS_FreeValue(ctx, prop);
|
||||
JS_FreeValue(ctx, val);
|
||||
|
||||
@@ -1119,11 +1119,11 @@ return {
|
||||
if (!caught) throw "stone object should prevent modification"
|
||||
},
|
||||
|
||||
test_stone_p_frozen: function() {
|
||||
test_is_stone_frozen: function() {
|
||||
var obj = {x: 10}
|
||||
if (stone.p(obj)) throw "stone.p should return false before freezing"
|
||||
if (is_stone(obj)) throw "stone.p should return false before freezing"
|
||||
stone(obj)
|
||||
if (!stone.p(obj)) throw "stone.p should return true after freezing"
|
||||
if (!is_stone(obj)) throw "stone.p should return true after freezing"
|
||||
},
|
||||
|
||||
test_stone_array: function() {
|
||||
@@ -3093,30 +3093,6 @@ return {
|
||||
// STONE FUNCTION (Additional Tests)
|
||||
// ============================================================================
|
||||
|
||||
test_stone_nested_object: function() {
|
||||
var obj = {inner: {value: 42}}
|
||||
stone(obj)
|
||||
var caught = false
|
||||
try {
|
||||
obj.inner.value = 99
|
||||
} catch (e) {
|
||||
caught = true
|
||||
}
|
||||
if (!caught) throw "stone should freeze nested objects"
|
||||
},
|
||||
|
||||
test_stone_nested_array: function() {
|
||||
var obj = {arr: [1, 2, 3]}
|
||||
stone(obj)
|
||||
var caught = false
|
||||
try {
|
||||
obj.arr[0] = 99
|
||||
} catch (e) {
|
||||
caught = true
|
||||
}
|
||||
if (!caught) throw "stone should freeze nested arrays"
|
||||
},
|
||||
|
||||
test_stone_returns_value: function() {
|
||||
var obj = {x: 1}
|
||||
var result = stone(obj)
|
||||
@@ -3127,7 +3103,7 @@ return {
|
||||
var obj = {x: 1}
|
||||
stone(obj)
|
||||
stone(obj)
|
||||
if (!stone.p(obj)) throw "stone should be idempotent"
|
||||
if (!is_stone(obj)) throw "stone should be idempotent"
|
||||
},
|
||||
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user