remove proxy and many exotic methods

This commit is contained in:
2025-06-23 15:32:05 -05:00
parent c581935fd8
commit 42087910ab
2 changed files with 21 additions and 167 deletions

View File

@@ -6323,22 +6323,16 @@ static void JS_SetImmutablePrototype(JSContext *ctx, JSValueConst obj)
p->has_immutable_prototype = TRUE;
}
/* Return -1 (exception) or TRUE/FALSE. 'throw_flag' = FALSE indicates
that it is called from Reflect.setPrototypeOf(). */
/* Return -1 (exception) or TRUE. */
static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,
JSValueConst proto_val,
BOOL throw_flag)
JSValueConst proto_val)
{
JSObject *proto, *p, *p1;
JSShape *sh;
if (throw_flag) {
if (JS_VALUE_GET_TAG(obj) == JS_TAG_NULL)
goto not_obj;
} else {
if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
goto not_obj;
}
p = JS_VALUE_GET_OBJ(obj);
if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_OBJECT) {
if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_NULL) {
@@ -6347,57 +6341,30 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,
return -1;
}
proto = NULL;
} else {
} else
proto = JS_VALUE_GET_OBJ(proto_val);
}
if (throw_flag && JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
return TRUE;
if (unlikely(p->is_exotic)) {
const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
int ret;
if (em && em->set_prototype) {
ret = em->set_prototype(ctx, obj, proto_val);
if (ret == 0 && throw_flag) {
JS_ThrowTypeError(ctx, "proxy: bad prototype");
return -1;
} else {
return ret;
}
}
}
sh = p->shape;
if (sh->proto == proto)
return TRUE;
if (unlikely(p->has_immutable_prototype)) {
if (throw_flag) {
JS_ThrowTypeError(ctx, "prototype is immutable");
return -1;
} else {
return FALSE;
}
}
if (unlikely(!p->extensible)) {
if (throw_flag) {
JS_ThrowTypeError(ctx, "object is not extensible");
return -1;
} else {
return FALSE;
}
}
if (proto) {
/* check if there is a cycle */
p1 = proto;
do {
if (p1 == p) {
if (throw_flag) {
JS_ThrowTypeError(ctx, "circular prototype chain");
return -1;
} else {
return FALSE;
}
}
/* Note: for Proxy objects, proto is NULL */
p1 = p1->shape->proto;
@@ -6417,7 +6384,7 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,
/* return -1 (exception) or TRUE/FALSE */
int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val)
{
return JS_SetPrototypeInternal(ctx, obj, proto_val, TRUE);
return JS_SetPrototypeInternal(ctx, obj, proto_val);
}
/* Only works for primitive types, otherwise return JS_NULL. */
@@ -6454,12 +6421,6 @@ JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj)
if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
JSObject *p;
p = JS_VALUE_GET_OBJ(obj);
if (unlikely(p->is_exotic)) {
const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
if (em && em->get_prototype) {
return em->get_prototype(ctx, obj);
}
}
p = p->shape->proto;
if (!p)
val = JS_NULL;
@@ -6709,16 +6670,6 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
} else {
const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
if (em) {
if (em->get_property) {
JSValue obj1, retval;
/* XXX: should pass throw_ref_error */
/* Note: if 'p' is a prototype, it can be
freed in the called function */
obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
retval = em->get_property(ctx, obj1, prop, this_obj);
JS_FreeValue(ctx, obj1);
return retval;
}
if (em->get_own_property) {
JSPropertyDescriptor desc;
int ret;
@@ -6865,39 +6816,6 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
if (flags & JS_GPN_STRING_MASK) {
num_keys_count += js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
}
} else {
const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
if (em && em->get_own_property_names) {
if (em->get_own_property_names(ctx, &tab_exotic, &exotic_count,
JS_MKPTR(JS_TAG_OBJECT, p)))
return -1;
for(i = 0; i < exotic_count; i++) {
atom = tab_exotic[i].atom;
kind = JS_AtomGetKind(ctx, atom);
if (((flags >> kind) & 1) != 0) {
is_enumerable = FALSE;
if (flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY)) {
JSPropertyDescriptor desc;
int res;
/* set the "is_enumerable" field if necessary */
res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom);
if (res < 0) {
JS_FreePropertyEnum(ctx, tab_exotic, exotic_count);
return -1;
}
if (res) {
is_enumerable =
((desc.flags & JS_PROP_ENUMERABLE) != 0);
js_free_desc(ctx, &desc);
}
tab_exotic[i].is_enumerable = is_enumerable;
}
if (!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) {
exotic_keys_count++;
}
}
}
}
}
}
@@ -7115,12 +7033,6 @@ int JS_IsExtensible(JSContext *ctx, JSValueConst obj)
if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))
return FALSE;
p = JS_VALUE_GET_OBJ(obj);
if (unlikely(p->is_exotic)) {
const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
if (em && em->is_extensible) {
return em->is_extensible(ctx, obj);
}
}
return p->extensible;
}
@@ -7132,12 +7044,6 @@ int JS_PreventExtensions(JSContext *ctx, JSValueConst obj)
if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))
return FALSE;
p = JS_VALUE_GET_OBJ(obj);
if (unlikely(p->is_exotic)) {
const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
if (em && em->prevent_extensions) {
return em->prevent_extensions(ctx, obj);
}
}
p->extensible = FALSE;
return TRUE;
}
@@ -7153,16 +7059,6 @@ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop)
return FALSE;
p = JS_VALUE_GET_OBJ(obj);
for(;;) {
if (p->is_exotic) {
const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
if (em && em->has_property) {
/* has_property can free the prototype */
obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
ret = em->has_property(ctx, obj1, prop);
JS_FreeValue(ctx, obj1);
return ret;
}
}
/* JS_GetOwnPropertyInternal can free the prototype */
JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
ret = JS_GetOwnPropertyInternal(ctx, NULL, p, prop);
@@ -7768,15 +7664,6 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
const JSClassExoticMethods *em = ctx->rt->class_array[p1->class_id].exotic;
if (em) {
JSValue obj1;
if (em->set_property) {
/* set_property can free the prototype */
obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));
ret = em->set_property(ctx, obj1, prop,
val, this_obj, flags);
JS_FreeValue(ctx, obj1);
JS_FreeValue(ctx, val);
return ret;
}
if (em->get_own_property) {
/* get_own_property can free the prototype */
obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));
@@ -12003,14 +11890,6 @@ static __exception int JS_CopyDataProperties(JSContext *ctx,
p = JS_VALUE_GET_OBJ(source);
gpn_flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK | JS_GPN_ENUM_ONLY;
if (p->is_exotic) {
const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
/* cannot use JS_GPN_ENUM_ONLY with e.g. proxies because it
introduces a visible change */
if (em && em->get_own_property_names) {
gpn_flags &= ~JS_GPN_ENUM_ONLY;
}
}
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,
gpn_flags))
return -1;
@@ -13836,7 +13715,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sf->cur_pc = pc;
proto = sp[-1];
if (JS_IsObject(proto) || JS_IsNull(proto)) {
if (JS_SetPrototypeInternal(ctx, sp[-2], proto, TRUE) < 0)
if (JS_SetPrototypeInternal(ctx, sp[-2], proto) < 0)
goto exception;
}
JS_FreeValue(ctx, proto);
@@ -27715,7 +27594,7 @@ static JSValue js_object_setPrototypeOf(JSContext *ctx, JSValueConst this_val,
{
JSValueConst obj;
obj = argv[0];
if (JS_SetPrototypeInternal(ctx, obj, argv[1], TRUE) < 0)
if (JS_SetPrototypeInternal(ctx, obj, argv[1]) < 0)
return JS_EXCEPTION;
return JS_DupValue(ctx, obj);
}
@@ -28449,7 +28328,7 @@ static JSValue js_object_set___proto__(JSContext *ctx, JSValueConst this_val,
return JS_ThrowTypeErrorNotAnObject(ctx);
if (!JS_IsObject(proto) && !JS_IsNull(proto))
return JS_NULL;
if (JS_SetPrototypeInternal(ctx, this_val, proto, TRUE) < 0)
if (JS_SetPrototypeInternal(ctx, this_val, proto) < 0)
return JS_EXCEPTION;
else
return JS_NULL;
@@ -28668,7 +28547,7 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,
goto fail1;
proto = JS_DupValue(ctx, realm->class_proto[JS_CLASS_BYTECODE_FUNCTION]);
}
ret = JS_SetPrototypeInternal(ctx, obj, proto, TRUE);
ret = JS_SetPrototypeInternal(ctx, obj, proto);
JS_FreeValue(ctx, proto);
if (ret < 0)
goto fail1;

View File

@@ -455,12 +455,7 @@ typedef struct JSClassExoticMethods {
returned, the property descriptor 'desc' is filled if != NULL. */
int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc,
JSValueConst obj, JSAtom prop);
/* '*ptab' should hold the '*plen' property keys. Return 0 if OK,
-1 if exception. The 'is_enumerable' field is ignored.
*/
int (*get_own_property_names)(JSContext *ctx, JSPropertyEnum **ptab,
uint32_t *plen,
JSValueConst obj);
/* return < 0 if exception, or TRUE/FALSE */
int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop);
/* return < 0 if exception or TRUE/FALSE */
@@ -468,26 +463,6 @@ typedef struct JSClassExoticMethods {
JSAtom prop, JSValueConst val,
JSValueConst getter, JSValueConst setter,
int flags);
/* The following methods can be emulated with the previous ones,
so they are usually not needed */
/* return < 0 if exception or TRUE/FALSE */
int (*has_property)(JSContext *ctx, JSValueConst obj, JSAtom atom);
JSValue (*get_property)(JSContext *ctx, JSValueConst obj, JSAtom atom,
JSValueConst receiver);
/* return < 0 if exception or TRUE/FALSE */
int (*set_property)(JSContext *ctx, JSValueConst obj, JSAtom atom,
JSValueConst value, JSValueConst receiver, int flags);
/* To get a consistent object behavior when get_prototype != NULL,
get_property, set_property and set_prototype must be != NULL
and the object must be created with a JS_NULL prototype. */
JSValue (*get_prototype)(JSContext *ctx, JSValueConst obj);
/* return < 0 if exception or TRUE/FALSE */
int (*set_prototype)(JSContext *ctx, JSValueConst obj, JSValueConst proto_val);
/* return < 0 if exception or TRUE/FALSE */
int (*is_extensible)(JSContext *ctx, JSValueConst obj);
/* return < 0 if exception or TRUE/FALSE */
int (*prevent_extensions)(JSContext *ctx, JSValueConst obj);
} JSClassExoticMethods;
typedef void JSClassFinalizer(JSRuntime *rt, JSValue val);