diff --git a/quickjs.c b/quickjs.c index a104aaf6..a886ee23 100644 --- a/quickjs.c +++ b/quickjs.c @@ -2107,6 +2107,8 @@ void JS_FreeRuntime(JSRuntime *rt) } #endif + assert(list_empty(&rt->gc_obj_list)); + /* free the classes */ for(i = 0; i < rt->class_count; i++) { JSClass *cl = &rt->class_array[i]; @@ -2239,9 +2241,6 @@ void JS_FreeRuntime(JSRuntime *rt) } #endif - // FinalizationRegistry finalizers have run, no objects should remain - assert(list_empty(&rt->gc_obj_list)); - { JSMallocState *ms = &rt->malloc_state; 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) { - JSValue ret = JS_Call(ctx, argv[0], JS_UNDEFINED, 1, &argv[1]); - JS_FreeValue(ctx, argv[1]); - return ret; + return JS_Call(ctx, argv[0], JS_UNDEFINED, 1, &argv[1]); } 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; JS_EnqueueJob(frd->ctx, js_finrec_job, 2, args); } + JS_FreeValueRT(rt, fre->held_val); JS_FreeValueRT(rt, fre->token); js_free_rt(rt, fre); break; diff --git a/tests/bug648.js b/tests/bug648.js new file mode 100644 index 00000000..cb0a7d38 --- /dev/null +++ b/tests/bug648.js @@ -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")