rm autoinit

This commit is contained in:
2026-01-22 09:16:01 -06:00
parent 45d82438ca
commit 6c1f53ec5f
2 changed files with 17 additions and 219 deletions

View File

@@ -399,10 +399,6 @@ typedef struct JSVarRef {
};
} JSVarRef;
typedef enum {
JS_AUTOINIT_ID_PROP,
} JSAutoInitIDEnum;
/* must be large enough to have a negligible runtime cost and small
enough to call the interrupt callback often. */
#define JS_INTERRUPT_COUNTER_INIT 10000
@@ -699,13 +695,6 @@ typedef struct JSBoundFunction {
JSValue argv[0];
} JSBoundFunction;
/* Used by js_object_keys and related functions */
typedef enum JSIteratorKindEnum {
JS_ITERATOR_KIND_KEY,
JS_ITERATOR_KIND_VALUE,
JS_ITERATOR_KIND_KEY_AND_VALUE,
} JSIteratorKindEnum;
typedef struct JSRegExp {
JSString *pattern;
JSString *bytecode; /* also contains the flags */
@@ -719,13 +708,6 @@ typedef struct JSProperty {
JSObject *setter; /* NULL if undefined */
} getset;
JSVarRef *var_ref; /* JS_PROP_VARREF */
struct { /* JS_PROP_AUTOINIT */
/* in order to use only 2 pointers, we compress the realm
and the init function pointer */
uintptr_t realm_and_id; /* realm and init_id (JS_AUTOINIT_ID_x)
in the 2 low bits */
void *opaque;
} init;
} u;
} JSProperty;
@@ -4886,7 +4868,6 @@ static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
p->u.cfunc.length = length;
p->u.cfunc.cproto = cproto;
p->u.cfunc.magic = magic;
/* Note: is_constructor bit removed - constructors are called as regular functions */
if (!name)
name = "";
name_atom = JS_NewAtom(ctx, name);
@@ -4993,27 +4974,6 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
return func_obj;
}
static JSContext *js_autoinit_get_realm(JSProperty *pr)
{
return (JSContext *)(pr->u.init.realm_and_id & ~3);
}
static JSAutoInitIDEnum js_autoinit_get_id(JSProperty *pr)
{
return pr->u.init.realm_and_id & 3;
}
static void js_autoinit_free(JSRuntime *rt, JSProperty *pr)
{
JS_FreeContext(js_autoinit_get_realm(pr));
}
static void js_autoinit_mark(JSRuntime *rt, JSProperty *pr,
JS_MarkFunc *mark_func)
{
mark_func(rt, &js_autoinit_get_realm(pr)->header);
}
static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags)
{
if (unlikely(prop_flags & JS_PROP_TMASK)) {
@@ -5024,8 +4984,6 @@ static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags)
JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));
} else if ((prop_flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
free_var_ref(rt, pr->u.var_ref);
} else if ((prop_flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
js_autoinit_free(rt, pr);
}
} else {
JS_FreeValueRT(rt, pr->u.value);
@@ -5417,8 +5375,6 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
/* Note: the tag does not matter
provided it is a GC object */
mark_func(rt, &pr->u.var_ref->header);
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
js_autoinit_mark(rt, pr, mark_func);
}
} else {
JS_MarkValue(rt, pr->u.value, mark_func);
@@ -6632,39 +6588,6 @@ static JSValue JS_GetPrototypeFree(JSContext *ctx, JSValue obj)
return obj1;
}
/* return the value associated to the autoinit property or an exception */
typedef JSValue JSAutoInitFunc(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);
static JSAutoInitFunc *js_autoinit_func_table[] = {
JS_InstantiateFunctionListItem2, /* JS_AUTOINIT_ID_PROP */
};
/* warning: 'prs' is reallocated after it */
static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop,
JSProperty *pr, JSShapeProperty *prs)
{
JSValue val;
JSContext *realm;
JSAutoInitFunc *func;
JSAutoInitIDEnum id;
if (js_shape_prepare_update(ctx, p, &prs))
return -1;
realm = js_autoinit_get_realm(pr);
id = js_autoinit_get_id(pr);
func = js_autoinit_func_table[id];
/* 'func' shall not modify the object properties 'pr' */
val = func(realm, p, prop, pr->u.init.opaque);
js_autoinit_free(ctx->rt, pr);
prs->flags &= ~JS_PROP_TMASK;
pr->u.value = JS_NULL;
if (JS_IsException(val))
return -1;
pr->u.value = val;
return 0;
}
JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
JSAtom prop, JSValueConst this_obj,
BOOL throw_ref_error)
@@ -6744,11 +6667,6 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
if (unlikely(JS_IsUninitialized(val)))
return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);
return JS_DupValue(ctx, val);
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
/* Instantiate property and retry */
if (JS_AutoInitProperty(ctx, p, prop, pr, prs))
return JS_EXCEPTION;
continue;
}
} else {
return JS_DupValue(ctx, pr->u.value);
@@ -6980,11 +6898,6 @@ retry:
return -1;
}
desc->value = JS_DupValue(ctx, val);
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
/* Instantiate property and retry */
if (JS_AutoInitProperty(ctx, p, prop, pr, prs))
return -1;
goto retry;
}
} else {
desc->value = JS_DupValue(ctx, pr->u.value);
@@ -6996,8 +6909,6 @@ retry:
JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);
return -1;
}
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
/* nothing to do: delay instantiation until actual value and/or attributes are read */
}
}
return TRUE;
@@ -7507,13 +7418,6 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
set_value(ctx, pr->u.var_ref->pvalue, val);
return TRUE;
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
/* Instantiate property and retry (potentially useless) */
if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) {
JS_FreeValue(ctx, val);
return -1;
}
goto retry;
} else {
goto read_only_prop;
}
@@ -7530,11 +7434,6 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
if (prs) {
if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {
return call_setter(ctx, pr->u.getset.setter, this_obj, val, flags);
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
/* Instantiate property and retry (potentially useless) */
if (JS_AutoInitProperty(ctx, p1, prop, pr, prs))
return -1;
goto retry2;
} else if (!(prs->flags & JS_PROP_WRITABLE)) {
goto read_only_prop;
} else {
@@ -7958,13 +7857,6 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable");
}
if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
/* Instantiate property and retry */
if (JS_AutoInitProperty(ctx, p, prop, pr, prs))
return -1;
goto redo_prop_update;
}
if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE |
JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {
if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {
@@ -8093,36 +7985,6 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
return JS_CreateProperty(ctx, p, prop, val, getter, setter, flags);
}
static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj,
JSAtom prop, JSAutoInitIDEnum id,
void *opaque, int flags)
{
JSObject *p;
JSProperty *pr;
if (JS_VALUE_GET_TAG(this_obj) != JS_TAG_OBJECT)
return FALSE;
p = JS_VALUE_GET_OBJ(this_obj);
if (find_own_property(&pr, p, prop)) {
/* property already exists */
abort();
return FALSE;
}
/* Specialized CreateProperty */
pr = add_property(ctx, p, prop, (flags & JS_PROP_C_W_E) | JS_PROP_AUTOINIT);
if (unlikely(!pr))
return -1;
pr->u.init.realm_and_id = (uintptr_t)JS_DupContext(ctx);
assert((pr->u.init.realm_and_id & 3) == 0);
assert(id <= 3);
pr->u.init.realm_and_id |= id;
pr->u.init.opaque = opaque;
return TRUE;
}
/* shortcut to add or redefine a new property value */
int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj,
JSAtom prop, JSValue val, int flags)
@@ -8270,7 +8132,6 @@ static int JS_CheckDefineGlobalVar(JSContext *ctx, JSAtom prop, int flags)
p = JS_VALUE_GET_OBJ(ctx->global_obj);
prs = find_own_property1(p, prop);
/* XXX: should handle JS_PROP_AUTOINIT */
if (flags & DEFINE_GLOBAL_LEX_VAR) {
if (prs && !(prs->flags & JS_PROP_CONFIGURABLE))
goto fail_redeclaration;
@@ -8386,7 +8247,6 @@ static int JS_GetGlobalVarRef(JSContext *ctx, JSAtom prop, JSValue *sp)
p = JS_VALUE_GET_OBJ(ctx->global_var_obj);
prs = find_own_property(&pr, p, prop);
if (prs) {
/* XXX: should handle JS_PROP_AUTOINIT properties? */
/* XXX: conformance: do these tests in
OP_put_var_ref/OP_get_var_ref ? */
if (unlikely(JS_IsUninitialized(pr->u.value))) {
@@ -8446,7 +8306,6 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val,
p = JS_VALUE_GET_OBJ(ctx->global_var_obj);
prs = find_own_property(&pr, p, prop);
if (prs) {
/* XXX: should handle JS_PROP_AUTOINIT properties? */
if (flag != 1) {
if (unlikely(JS_IsUninitialized(pr->u.value))) {
JS_FreeValue(ctx, val);
@@ -9792,17 +9651,6 @@ static void js_print_object(JSPrintValueState *s, JSObject *p)
} else {
js_print_value(s, *pr->u.var_ref->pvalue);
}
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
if (s->options.raw_dump) {
js_printf(s, "[autoinit %p %d %p]",
(void *)js_autoinit_get_realm(pr),
js_autoinit_get_id(pr),
(void *)pr->u.init.opaque);
} else {
/* XXX: could autoinit but need to restart
the iteration */
js_printf(s, "[autoinit]");
}
} else {
js_print_value(s, pr->u.value);
}
@@ -13956,8 +13804,6 @@ typedef enum JSParseFunctionEnum {
JS_PARSE_FUNC_SETTER,
JS_PARSE_FUNC_METHOD,
JS_PARSE_FUNC_CLASS_STATIC_INIT,
JS_PARSE_FUNC_CLASS_CONSTRUCTOR,
JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR,
} JSParseFunctionEnum;
typedef struct JSFunctionDef {
@@ -25576,13 +25422,10 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
}
break;
case JS_DEF_CFUNC:
if (atom == JS_ATOM_Symbol_toPrimitive) {
/* Symbol.toPrimitive functions are not writable */
prop_flags = JS_PROP_CONFIGURABLE;
}
JS_DefineAutoInitProperty(ctx, obj, atom, JS_AUTOINIT_ID_PROP,
(void *)e, prop_flags);
return 0;
if (atom == JS_ATOM_Symbol_toPrimitive) prop_flags = JS_PROP_CONFIGURABLE;
val = JS_NewCFunction2(ctx, e->u.func.cfunc.generic, e->name,
e->u.func.length, e->u.func.cproto, e->magic);
break;
case JS_DEF_CGETSET: /* XXX: use autoinit again ? */
case JS_DEF_CGETSET_MAGIC:
{
@@ -25620,10 +25463,14 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
val = JS_NULL;
break;
case JS_DEF_PROP_STRING:
val = JS_NewAtomString(ctx, e->u.str);
break;
case JS_DEF_OBJECT:
JS_DefineAutoInitProperty(ctx, obj, atom, JS_AUTOINIT_ID_PROP,
(void *)e, prop_flags);
return 0;
val = JS_NewObject(ctx);
if (JS_IsException(val)) return -1;
JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len);
break;
default:
abort();
}
@@ -25673,7 +25520,7 @@ static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val)
}
static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1,
int flags, int kind)
int flags)
{
JSValue obj, r, val, key, value;
JSObject *p;
@@ -25707,34 +25554,10 @@ static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1,
if (!(desc.flags & JS_PROP_ENUMERABLE))
continue;
}
switch(kind) {
default:
case JS_ITERATOR_KIND_KEY:
val = JS_AtomToValue(ctx, atom);
if (JS_IsException(val))
goto exception;
break;
case JS_ITERATOR_KIND_VALUE:
val = JS_GetProperty(ctx, obj, atom);
if (JS_IsException(val))
goto exception;
break;
case JS_ITERATOR_KIND_KEY_AND_VALUE:
val = JS_NewArray(ctx);
if (JS_IsException(val))
goto exception;
key = JS_AtomToValue(ctx, atom);
if (JS_IsException(key))
goto exception1;
if (JS_CreateDataPropertyUint32(ctx, val, 0, key, JS_PROP_THROW) < 0)
goto exception1;
value = JS_GetProperty(ctx, obj, atom);
if (JS_IsException(value))
goto exception1;
if (JS_CreateDataPropertyUint32(ctx, val, 1, value, JS_PROP_THROW) < 0)
goto exception1;
break;
}
if (JS_CreateDataPropertyUint32(ctx, r, j++, val, 0) < 0)
goto exception;
}
@@ -25751,13 +25574,6 @@ done:
return r;
}
static JSValue js_object_keys(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int kind)
{
return JS_GetOwnPropertyNames2(ctx, argv[0],
JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK, kind);
}
static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int freeze_flag)
{
@@ -25853,25 +25669,10 @@ static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
return JS_ToLengthFree(ctx, pres, len_val);
}
static __exception int js_set_length64(JSContext *ctx, JSValueConst obj,
int64_t len)
{
/* Intrinsic arrays have fixed length - cannot set */
if (JS_VALUE_GET_TAG(obj) == JS_TAG_ARRAY) {
JS_ThrowTypeError(ctx, "cannot change length of array");
return -1;
}
return JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, len));
}
int JS_GetLength(JSContext *ctx, JSValueConst obj, int64_t *pres) {
return js_get_length64(ctx, pres, obj);
}
int JS_SetLength(JSContext *ctx, JSValueConst obj, int64_t len) {
return js_set_length64(ctx, obj, len);
}
static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len)
{
uint32_t i;
@@ -27292,7 +27093,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
if (!JS_IsNull(jsc->property_list))
tab = JS_DupValue(ctx, jsc->property_list);
else
tab = js_object_keys(ctx, JS_NULL, 1, (JSValueConst *)&val, JS_ITERATOR_KIND_KEY);
tab = JS_GetOwnPropertyNames2(ctx, val, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK);
if (JS_IsException(tab))
goto exception;
if (js_get_length64(ctx, &len, tab))
@@ -29468,8 +29269,7 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
if (JS_IsObject(arg) && !JS_IsArray(ctx, arg)) {
/* Return object keys */
return JS_GetOwnPropertyNames2(ctx, arg,
JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK,
JS_ITERATOR_KIND_KEY);
JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK);
}
/* array(text) - split into characters */

View File

@@ -282,7 +282,6 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
#define JS_PROP_NORMAL (0 << 4)
#define JS_PROP_GETSET (1 << 4)
#define JS_PROP_VARREF (2 << 4) /* used internally */
#define JS_PROP_AUTOINIT (3 << 4) /* used internally */
/* flags for JS_DefineProperty */
#define JS_PROP_HAS_SHIFT 8
@@ -672,7 +671,6 @@ 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);