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
This commit is contained in:
Ben Noordhuis 2024-11-06 22:54:47 +01:00 committed by GitHub
parent 0a706236d7
commit 83fe8f1166
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 10 additions and 2 deletions

View file

@ -54737,10 +54737,12 @@ typedef struct JSWeakRefData {
JSValue obj; JSValue obj;
} JSWeakRefData; } JSWeakRefData;
static JSWeakRefData js_weakref_sentinel;
static void js_weakref_finalizer(JSRuntime *rt, JSValue val) static void js_weakref_finalizer(JSRuntime *rt, JSValue val)
{ {
JSWeakRefData *wrd = JS_GetOpaque(val, JS_CLASS_WEAK_REF); JSWeakRefData *wrd = JS_GetOpaque(val, JS_CLASS_WEAK_REF);
if (!wrd) if (!wrd || wrd == &js_weakref_sentinel)
return; return;
/* Delete weak ref */ /* 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); JSWeakRefData *wrd = JS_GetOpaque2(ctx, this_val, JS_CLASS_WEAK_REF);
if (!wrd) if (!wrd)
return JS_EXCEPTION; return JS_EXCEPTION;
if (wrd == &js_weakref_sentinel)
return JS_UNDEFINED;
return js_dup(wrd->target); return js_dup(wrd->target);
} }
@ -55055,7 +55059,7 @@ static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref)
break; break;
case JS_WEAK_REF_KIND_WEAK_REF: case JS_WEAK_REF_KIND_WEAK_REF:
wrd = wr->u.weak_ref_data; wrd = wr->u.weak_ref_data;
JS_SetOpaque(wrd->obj, NULL); JS_SetOpaque(wrd->obj, &js_weakref_sentinel);
js_free_rt(rt, wrd); js_free_rt(rt, wrd);
break; break;
case JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY: { case JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY: {

4
tests/bug652.js Normal file
View file

@ -0,0 +1,4 @@
import { assert } from "./assert.js"
const ref = new WeakRef({})
const val = ref.deref() // should not throw
assert(val, undefined)