@@ -1175,9 +1175,10 @@ static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx);
11751175static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj);
11761176static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
11771177 JSValueConst proto_val, BOOL throw_flag);
1178+
1179+ static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, int throw_exception);
11781180static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj);
11791181static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj);
1180- static int js_proxy_isArray(JSContext *ctx, JSValueConst obj);
11811182static int JS_CreateProperty(JSContext *ctx, JSObject *p,
11821183 JSAtom prop, JSValueConst val,
11831184 JSValueConst getter, JSValueConst setter,
@@ -12109,15 +12110,14 @@ static __maybe_unused void JS_PrintValue(JSContext *ctx,
1210912110}
1211012111
1211112112/* return -1 if exception (proxy case) or TRUE/FALSE */
12113+ // TODO: should take flags to make proxy resolution and exceptions optional
1211212114int JS_IsArray(JSContext *ctx, JSValueConst val)
1211312115{
12114- JSObject *p;
12116+ if (js_resolve_proxy(ctx, &val, TRUE))
12117+ return -1;
1211512118 if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) {
12116- p = JS_VALUE_GET_OBJ(val);
12117- if (unlikely(p->class_id == JS_CLASS_PROXY))
12118- return js_proxy_isArray(ctx, val);
12119- else
12120- return p->class_id == JS_CLASS_ARRAY;
12119+ JSObject *p = JS_VALUE_GET_OBJ(val);
12120+ return p->class_id == JS_CLASS_ARRAY;
1212112121 } else {
1212212122 return FALSE;
1212312123 }
@@ -46713,20 +46713,35 @@ static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj,
4671346713 return ret;
4671446714}
4671546715
46716- static int js_proxy_isArray(JSContext *ctx, JSValueConst obj)
46717- {
46718- JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY);
46719- if (!s)
46720- return FALSE;
46721- if (js_check_stack_overflow(ctx->rt, 0)) {
46722- JS_ThrowStackOverflow(ctx);
46723- return -1;
46724- }
46725- if (s->is_revoked) {
46726- JS_ThrowTypeErrorRevokedProxy(ctx);
46727- return -1;
46716+ /* `js_resolve_proxy`: resolve the proxy chain
46717+ `*pval` is updated with to ultimate proxy target
46718+ `throw_exception` controls whether exceptions are thown or not
46719+ - return -1 in case of error
46720+ - otherwise return 0
46721+ */
46722+ static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, BOOL throw_exception) {
46723+ int depth = 0;
46724+ JSObject *p;
46725+ JSProxyData *s;
46726+
46727+ while (JS_VALUE_GET_TAG(*pval) == JS_TAG_OBJECT) {
46728+ p = JS_VALUE_GET_OBJ(*pval);
46729+ if (p->class_id != JS_CLASS_PROXY)
46730+ break;
46731+ if (depth++ > 1000) {
46732+ if (throw_exception)
46733+ JS_ThrowStackOverflow(ctx);
46734+ return -1;
46735+ }
46736+ s = p->u.opaque;
46737+ if (s->is_revoked) {
46738+ if (throw_exception)
46739+ JS_ThrowTypeErrorRevokedProxy(ctx);
46740+ return -1;
46741+ }
46742+ *pval = s->target;
4672846743 }
46729- return JS_IsArray(ctx, s->target) ;
46744+ return 0 ;
4673046745}
4673146746
4673246747static const JSClassExoticMethods js_proxy_exotic_methods = {
0 commit comments