tag array coverage
This commit is contained in:
2
Makefile
2
Makefile
@@ -56,7 +56,7 @@ static:
|
|||||||
# Bootstrap: build cell from scratch using meson (only needed once)
|
# Bootstrap: build cell from scratch using meson (only needed once)
|
||||||
# Also installs core scripts to ~/.cell/core
|
# Also installs core scripts to ~/.cell/core
|
||||||
bootstrap:
|
bootstrap:
|
||||||
meson setup build_bootstrap -Dbuildtype=debugoptimized
|
meson setup build_bootstrap -Dbuildtype=debugoptimized -Db_sanitize=address
|
||||||
meson compile -C build_bootstrap
|
meson compile -C build_bootstrap
|
||||||
cp build_bootstrap/cell .
|
cp build_bootstrap/cell .
|
||||||
cp build_bootstrap/libcell_runtime.dylib .
|
cp build_bootstrap/libcell_runtime.dylib .
|
||||||
|
|||||||
@@ -5048,10 +5048,11 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Free intrinsic array (JS_TAG_ARRAY) */
|
/* Free intrinsic array (JS_TAG_ARRAY) */
|
||||||
static void free_array(JSRuntime *rt, JSArray *arr)
|
static void free_array(JSRuntime *rt, JSArray *arr)
|
||||||
{
|
{
|
||||||
|
assert(arr->header.gc_obj_type == JS_GC_OBJ_TYPE_ARRAY);
|
||||||
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for (i = 0; i < arr->len; i++) {
|
for (i = 0; i < arr->len; i++) {
|
||||||
JS_FreeValueRT(rt, arr->values[i]);
|
JS_FreeValueRT(rt, arr->values[i]);
|
||||||
@@ -5063,25 +5064,34 @@ static void free_array(JSRuntime *rt, JSArray *arr)
|
|||||||
|
|
||||||
static int js_intrinsic_array_ensure_capacity(JSContext *ctx, JSArray *arr, uint32_t min_cap)
|
static int js_intrinsic_array_ensure_capacity(JSContext *ctx, JSArray *arr, uint32_t min_cap)
|
||||||
{
|
{
|
||||||
if (min_cap <= arr->cap)
|
if (min_cap <= arr->cap) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
uint32_t new_cap = arr->cap ? arr->cap : JS_ARRAY_INITIAL_SIZE;
|
uint32_t old_cap = arr->cap;
|
||||||
while (new_cap < min_cap) {
|
uint32_t new_cap = old_cap ? old_cap : JS_ARRAY_INITIAL_SIZE;
|
||||||
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);
|
while (new_cap < min_cap) {
|
||||||
if (!new_values)
|
if (new_cap > UINT32_MAX / 2) { new_cap = min_cap; break; }
|
||||||
return -1;
|
new_cap *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
arr->values = new_values;
|
JSValue *new_values = js_realloc(ctx, arr->values, sizeof(JSValue) * new_cap);
|
||||||
arr->cap = new_cap;
|
if (!new_values) return -1;
|
||||||
return 0;
|
|
||||||
|
for (uint32_t i = old_cap; i < new_cap; i++) new_values[i] = JS_NULL;
|
||||||
|
|
||||||
|
arr->values = new_values;
|
||||||
|
arr->cap = new_cap;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int js_intrinsic_array_push(JSContext *ctx, JSArray *arr, JSValue val)
|
||||||
|
{
|
||||||
|
if (js_intrinsic_array_ensure_capacity(ctx, arr, arr->len + 1) < 0) {
|
||||||
|
JS_FreeValue(ctx, val);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
arr->values[arr->len++] = val;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int js_intrinsic_array_set(JSContext *ctx, JSArray *arr, uint32_t idx, JSValue val)
|
static int js_intrinsic_array_set(JSContext *ctx, JSArray *arr, uint32_t idx, JSValue val)
|
||||||
@@ -5109,23 +5119,6 @@ static int js_intrinsic_array_set(JSContext *ctx, JSArray *arr, uint32_t idx, JS
|
|||||||
return TRUE;
|
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)
|
|
||||||
{
|
|
||||||
if (arr->len >= arr->cap) {
|
|
||||||
uint32_t new_cap = arr->cap ? arr->cap * 2 : JS_ARRAY_INITIAL_SIZE;
|
|
||||||
JSValue *new_values = js_realloc(ctx, arr->values, sizeof(JSValue) * new_cap);
|
|
||||||
if (!new_values) {
|
|
||||||
JS_FreeValue(ctx, val);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
arr->values = new_values;
|
|
||||||
arr->cap = new_cap;
|
|
||||||
}
|
|
||||||
arr->values[arr->len++] = val;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void js_c_function_finalizer(JSRuntime *rt, JSValue val)
|
static void js_c_function_finalizer(JSRuntime *rt, JSValue val)
|
||||||
{
|
{
|
||||||
JSObject *p = JS_VALUE_GET_OBJ(val);
|
JSObject *p = JS_VALUE_GET_OBJ(val);
|
||||||
@@ -5219,6 +5212,8 @@ static void free_object(JSRuntime *rt, JSObject *p)
|
|||||||
JSShape *sh;
|
JSShape *sh;
|
||||||
JSShapeProperty *pr;
|
JSShapeProperty *pr;
|
||||||
|
|
||||||
|
assert(p->header.gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT);
|
||||||
|
|
||||||
p->free_mark = 1; /* used to tell the object is invalid when
|
p->free_mark = 1; /* used to tell the object is invalid when
|
||||||
freeing cycles */
|
freeing cycles */
|
||||||
/* free all the fields */
|
/* free all the fields */
|
||||||
@@ -7580,7 +7575,8 @@ static int JS_DefineGlobalFunction(JSContext *ctx, JSAtom prop,
|
|||||||
JSValueConst func, int def_flags)
|
JSValueConst func, int def_flags)
|
||||||
{
|
{
|
||||||
(void)def_flags;
|
(void)def_flags;
|
||||||
if (JS_SetPropertyInternal(ctx, ctx->global_obj, prop, func) < 0)
|
/* JS_SetPropertyInternal consumes the value, so we must dup it */
|
||||||
|
if (JS_SetPropertyInternal(ctx, ctx->global_obj, prop, JS_DupValue(ctx, func)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -8102,6 +8098,7 @@ static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val)
|
|||||||
case JS_TAG_NULL:
|
case JS_TAG_NULL:
|
||||||
ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val));
|
ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val));
|
||||||
break;
|
break;
|
||||||
|
case JS_TAG_ARRAY:
|
||||||
case JS_TAG_OBJECT:
|
case JS_TAG_OBJECT:
|
||||||
JS_FreeValue(ctx, val);
|
JS_FreeValue(ctx, val);
|
||||||
return JS_ThrowTypeError(ctx, "cannot convert object to number");
|
return JS_ThrowTypeError(ctx, "cannot convert object to number");
|
||||||
@@ -8558,6 +8555,7 @@ static JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToP
|
|||||||
return JS_AtomToString(ctx, JS_ATOM_null);
|
return JS_AtomToString(ctx, JS_ATOM_null);
|
||||||
case JS_TAG_EXCEPTION:
|
case JS_TAG_EXCEPTION:
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
|
case JS_TAG_ARRAY:
|
||||||
case JS_TAG_OBJECT:
|
case JS_TAG_OBJECT:
|
||||||
return JS_AtomToString(ctx, JS_ATOM_true);
|
return JS_AtomToString(ctx, JS_ATOM_true);
|
||||||
case JS_TAG_FUNCTION_BYTECODE:
|
case JS_TAG_FUNCTION_BYTECODE:
|
||||||
@@ -9245,6 +9243,9 @@ static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
|
|||||||
case JS_GC_OBJ_TYPE_JS_CONTEXT:
|
case JS_GC_OBJ_TYPE_JS_CONTEXT:
|
||||||
printf("[js_context]");
|
printf("[js_context]");
|
||||||
break;
|
break;
|
||||||
|
case JS_GC_OBJ_TYPE_ARRAY:
|
||||||
|
printf("[array]");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("[unknown %d]", p->gc_obj_type);
|
printf("[unknown %d]", p->gc_obj_type);
|
||||||
break;
|
break;
|
||||||
@@ -9585,6 +9586,12 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case JS_TAG_ARRAY:
|
||||||
|
if (tag1 != tag2)
|
||||||
|
res = FALSE;
|
||||||
|
else
|
||||||
|
res = JS_VALUE_GET_PTR(op1) == JS_VALUE_GET_PTR(op2);
|
||||||
|
break;
|
||||||
case JS_TAG_OBJECT:
|
case JS_TAG_OBJECT:
|
||||||
if (tag1 != tag2)
|
if (tag1 != tag2)
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
@@ -11844,9 +11851,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
}
|
}
|
||||||
ret = js_method_set_properties(ctx, sp[-1], atom, 0, obj);
|
ret = js_method_set_properties(ctx, sp[-1], atom, 0, obj);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
|
/* JS_SetProperty consumes value, so don't free sp[-1] on success */
|
||||||
ret = JS_SetProperty(ctx, obj, atom, value);
|
ret = JS_SetProperty(ctx, obj, atom, value);
|
||||||
|
} else {
|
||||||
|
JS_FreeValue(ctx, sp[-1]);
|
||||||
}
|
}
|
||||||
JS_FreeValue(ctx, sp[-1]);
|
|
||||||
if (is_computed) {
|
if (is_computed) {
|
||||||
JS_FreeAtom(ctx, atom);
|
JS_FreeAtom(ctx, atom);
|
||||||
JS_FreeValue(ctx, sp[-2]);
|
JS_FreeValue(ctx, sp[-2]);
|
||||||
|
|||||||
@@ -3462,7 +3462,9 @@ return {
|
|||||||
|
|
||||||
test_gc_cycle_array_self: function() {
|
test_gc_cycle_array_self: function() {
|
||||||
var arr = []
|
var arr = []
|
||||||
push(arr, arr)
|
for (var i = 0; i < 10; i++) {
|
||||||
|
push(arr, arr)
|
||||||
|
}
|
||||||
if (arr[0] != arr) throw "array self cycle failed"
|
if (arr[0] != arr) throw "array self cycle failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user