Add js_resolve_proxy (#293)

- simplify `JS_IsArray` for proxy chains
- remove `js_proxy_isArray`
This commit is contained in:
Charlie Gordon 2024-05-09 14:14:50 +02:00 committed by GitHub
parent f3f2f42717
commit 97be5a32af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1175,9 +1175,10 @@ static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx);
static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj); static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj);
static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
JSValueConst proto_val, BOOL throw_flag); JSValueConst proto_val, BOOL throw_flag);
static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, int throw_exception);
static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj); static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj);
static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj); static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj);
static int js_proxy_isArray(JSContext *ctx, JSValueConst obj);
static int JS_CreateProperty(JSContext *ctx, JSObject *p, static int JS_CreateProperty(JSContext *ctx, JSObject *p,
JSAtom prop, JSValueConst val, JSAtom prop, JSValueConst val,
JSValueConst getter, JSValueConst setter, JSValueConst getter, JSValueConst setter,
@ -12109,15 +12110,14 @@ static __maybe_unused void JS_PrintValue(JSContext *ctx,
} }
/* return -1 if exception (proxy case) or TRUE/FALSE */ /* return -1 if exception (proxy case) or TRUE/FALSE */
// TODO: should take flags to make proxy resolution and exceptions optional
int JS_IsArray(JSContext *ctx, JSValueConst val) int JS_IsArray(JSContext *ctx, JSValueConst val)
{ {
JSObject *p; if (js_resolve_proxy(ctx, &val, TRUE))
return -1;
if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) {
p = JS_VALUE_GET_OBJ(val); JSObject *p = JS_VALUE_GET_OBJ(val);
if (unlikely(p->class_id == JS_CLASS_PROXY)) return p->class_id == JS_CLASS_ARRAY;
return js_proxy_isArray(ctx, val);
else
return p->class_id == JS_CLASS_ARRAY;
} else { } else {
return FALSE; return FALSE;
} }
@ -46713,20 +46713,35 @@ static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj,
return ret; return ret;
} }
static int js_proxy_isArray(JSContext *ctx, JSValueConst obj) /* `js_resolve_proxy`: resolve the proxy chain
{ `*pval` is updated with to ultimate proxy target
JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY); `throw_exception` controls whether exceptions are thown or not
if (!s) - return -1 in case of error
return FALSE; - otherwise return 0
if (js_check_stack_overflow(ctx->rt, 0)) { */
JS_ThrowStackOverflow(ctx); static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, BOOL throw_exception) {
return -1; int depth = 0;
JSObject *p;
JSProxyData *s;
while (JS_VALUE_GET_TAG(*pval) == JS_TAG_OBJECT) {
p = JS_VALUE_GET_OBJ(*pval);
if (p->class_id != JS_CLASS_PROXY)
break;
if (depth++ > 1000) {
if (throw_exception)
JS_ThrowStackOverflow(ctx);
return -1;
}
s = p->u.opaque;
if (s->is_revoked) {
if (throw_exception)
JS_ThrowTypeErrorRevokedProxy(ctx);
return -1;
}
*pval = s->target;
} }
if (s->is_revoked) { return 0;
JS_ThrowTypeErrorRevokedProxy(ctx);
return -1;
}
return JS_IsArray(ctx, s->target);
} }
static const JSClassExoticMethods js_proxy_exotic_methods = { static const JSClassExoticMethods js_proxy_exotic_methods = {