From 83fe8f11665550fa573513c1a083d3579004a473 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 6 Nov 2024 22:54:47 +0100 Subject: [PATCH] Fix exception in WeakRef.prototype.deref (#653) Set the object's opaque to a sentinel value instead of NULL, to stop JS_GetOpaque2 from raising an "illegal class" exception. Fixes: https://github.com/quickjs-ng/quickjs/issues/651 --- quickjs.c | 8 ++++++-- tests/bug652.js | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 tests/bug652.js diff --git a/quickjs.c b/quickjs.c index af26d12..6c073b1 100644 --- a/quickjs.c +++ b/quickjs.c @@ -54737,10 +54737,12 @@ typedef struct JSWeakRefData { JSValue obj; } JSWeakRefData; +static JSWeakRefData js_weakref_sentinel; + static void js_weakref_finalizer(JSRuntime *rt, JSValue val) { JSWeakRefData *wrd = JS_GetOpaque(val, JS_CLASS_WEAK_REF); - if (!wrd) + if (!wrd || wrd == &js_weakref_sentinel) return; /* Delete weak ref */ @@ -54796,6 +54798,8 @@ static JSValue js_weakref_deref(JSContext *ctx, JSValue this_val, int argc, JSVa JSWeakRefData *wrd = JS_GetOpaque2(ctx, this_val, JS_CLASS_WEAK_REF); if (!wrd) return JS_EXCEPTION; + if (wrd == &js_weakref_sentinel) + return JS_UNDEFINED; return js_dup(wrd->target); } @@ -55055,7 +55059,7 @@ static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref) break; case JS_WEAK_REF_KIND_WEAK_REF: wrd = wr->u.weak_ref_data; - JS_SetOpaque(wrd->obj, NULL); + JS_SetOpaque(wrd->obj, &js_weakref_sentinel); js_free_rt(rt, wrd); break; case JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY: { diff --git a/tests/bug652.js b/tests/bug652.js new file mode 100644 index 0000000..27dea3b --- /dev/null +++ b/tests/bug652.js @@ -0,0 +1,4 @@ +import { assert } from "./assert.js" +const ref = new WeakRef({}) +const val = ref.deref() // should not throw +assert(val, undefined)