mirror of
https://github.com/DoneJS-Runtime/quickjs-done-nextgen.git
synced 2025-01-09 17:43:15 +00:00
Fix FinalizationRegistry refcounting bug (#656)
Introduced in commit61c8fe6
from last month that moved the callback into the job queue: 1. It leaked `fre->held_val` when no job was enqueued 2. It fumbled the reference count when enqueuing; JS_EnqueueJob already takes care of incrementing and decrementing it Reverts commit0a70623
from earlier today because that didn't turn out to be a complete fix. Fixes: https://github.com/quickjs-ng/quickjs/issues/648
This commit is contained in:
parent
aedd829e61
commit
9c5c441744
2 changed files with 17 additions and 6 deletions
10
quickjs.c
10
quickjs.c
|
@ -2107,6 +2107,8 @@ void JS_FreeRuntime(JSRuntime *rt)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
assert(list_empty(&rt->gc_obj_list));
|
||||||
|
|
||||||
/* free the classes */
|
/* free the classes */
|
||||||
for(i = 0; i < rt->class_count; i++) {
|
for(i = 0; i < rt->class_count; i++) {
|
||||||
JSClass *cl = &rt->class_array[i];
|
JSClass *cl = &rt->class_array[i];
|
||||||
|
@ -2239,9 +2241,6 @@ void JS_FreeRuntime(JSRuntime *rt)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FinalizationRegistry finalizers have run, no objects should remain
|
|
||||||
assert(list_empty(&rt->gc_obj_list));
|
|
||||||
|
|
||||||
{
|
{
|
||||||
JSMallocState *ms = &rt->malloc_state;
|
JSMallocState *ms = &rt->malloc_state;
|
||||||
rt->mf.js_free(ms->opaque, rt);
|
rt->mf.js_free(ms->opaque, rt);
|
||||||
|
@ -54985,9 +54984,7 @@ static const JSClassShortDef js_finrec_class_def[] = {
|
||||||
|
|
||||||
static JSValue js_finrec_job(JSContext *ctx, int argc, JSValue *argv)
|
static JSValue js_finrec_job(JSContext *ctx, int argc, JSValue *argv)
|
||||||
{
|
{
|
||||||
JSValue ret = JS_Call(ctx, argv[0], JS_UNDEFINED, 1, &argv[1]);
|
return JS_Call(ctx, argv[0], JS_UNDEFINED, 1, &argv[1]);
|
||||||
JS_FreeValue(ctx, argv[1]);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JS_AddIntrinsicWeakRef(JSContext *ctx)
|
void JS_AddIntrinsicWeakRef(JSContext *ctx)
|
||||||
|
@ -55078,6 +55075,7 @@ static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref)
|
||||||
args[1] = fre->held_val;
|
args[1] = fre->held_val;
|
||||||
JS_EnqueueJob(frd->ctx, js_finrec_job, 2, args);
|
JS_EnqueueJob(frd->ctx, js_finrec_job, 2, args);
|
||||||
}
|
}
|
||||||
|
JS_FreeValueRT(rt, fre->held_val);
|
||||||
JS_FreeValueRT(rt, fre->token);
|
JS_FreeValueRT(rt, fre->token);
|
||||||
js_free_rt(rt, fre);
|
js_free_rt(rt, fre);
|
||||||
break;
|
break;
|
||||||
|
|
13
tests/bug648.js
Normal file
13
tests/bug648.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/*---
|
||||||
|
negative:
|
||||||
|
phase: runtime
|
||||||
|
type: Error
|
||||||
|
---*/
|
||||||
|
let finrec = new FinalizationRegistry(v => {})
|
||||||
|
let object = {object:"object"}
|
||||||
|
finrec.register(object, {held:"held"}, {token:"token"})
|
||||||
|
object = undefined
|
||||||
|
// abrupt termination should not leak |held|
|
||||||
|
// unfortunately only shows up in qjs, not run-test262,
|
||||||
|
// but still good to have a regression test
|
||||||
|
throw Error("ok")
|
Loading…
Reference in a new issue