Skip to content

Commit dd6321f

Browse files
committed
Fix crash in FinalizationRegistry when the observed object is GC'd
In the pathological case shown in #367 both the object and the registry will be destroyed as part of the GC phase of JS_FreeRuntime. When the GC sweep happens it's possible we are holding on to a corpse so avoid calling the registry callback in that case. This is similar to how Weak{Map,Set} deal with iterators being freed as part of a cycle. Fixes: #367
1 parent b20aad8 commit dd6321f

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

quickjs.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52141,11 +52141,16 @@ static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref)
5214152141
fre = wr->u.fin_rec_entry;
5214252142
JSFinalizationRegistryData *frd = JS_GetOpaque(fre->obj, JS_CLASS_FINALIZATION_REGISTRY);
5214352143
assert(frd != NULL);
52144-
JSValue func = js_dup(frd->cb);
52145-
JSValue ret = JS_Call(frd->ctx, func, JS_UNDEFINED, 1, &fre->held_val);
52146-
JS_FreeValueRT(rt, func);
52147-
JS_FreeValueRT(rt, ret);
52148-
JS_FreeValueRT(rt, fre->held_val);
52144+
/**
52145+
* During the GC sweep phase the held object might be collected first.
52146+
*/
52147+
if (JS_IsLiveObject(frd->ctx->rt, fre->held_val)) {
52148+
JSValue func = js_dup(frd->cb);
52149+
JSValue ret = JS_Call(frd->ctx, func, JS_UNDEFINED, 1, &fre->held_val);
52150+
JS_FreeValueRT(rt, func);
52151+
JS_FreeValueRT(rt, ret);
52152+
JS_FreeValueRT(rt, fre->held_val);
52153+
}
5214952154
JS_FreeValueRT(rt, fre->token);
5215052155
js_free_rt(rt, fre);
5215152156
break;

0 commit comments

Comments
 (0)