remove proxy and many exotic methods
This commit is contained in:
141
source/quickjs.c
141
source/quickjs.c
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user