Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions tests/memory-leak.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@ import { VideoPlaybackModel } from "../src/track-lab/model/VideoPlaybackModel.js
import { PlaybackControlsNode } from "../src/track-lab/view/PlaybackControlsNode.js";

/**
* Force garbage collection with multiple passes. When `earlyExitRef` is supplied
* the loop bails as soon as the object is confirmed collected. The setTimeout(0)
* yield after a live deref() avoids the WeakRef macrotask-liveness pin.
* Force garbage collection with multiple passes. When `earlyExitRefs` is supplied
* the loop bails as soon as every referenced object is confirmed collected. The
* setTimeout(0) yield after a live deref() avoids the WeakRef macrotask-liveness pin.
* Without early-exit refs the loop always runs all passes, which on a slow `gc()`
* can exceed the Vitest testTimeout — always pass refs when you have them.
*/
async function forceGC(earlyExitRef?: WeakRef<object>): Promise<void> {
async function forceGC(earlyExitRefs?: WeakRef<object> | readonly WeakRef<object>[]): Promise<void> {
const refs = earlyExitRefs === undefined ? [] : Array.isArray(earlyExitRefs) ? earlyExitRefs : [earlyExitRefs];
for (let i = 0; i < 15; i++) {
globalThis.gc?.();
await new Promise<void>((r) => setTimeout(r, 50));
if (earlyExitRef !== undefined && earlyExitRef.deref() === undefined) {
if (refs.length > 0 && refs.every((ref) => ref.deref() === undefined)) {
return;
}
if (earlyExitRef !== undefined) {
if (refs.length > 0) {
await new Promise<void>((r) => setTimeout(r, 0));
}
}
Expand Down Expand Up @@ -151,7 +154,7 @@ describe("Memory leak regression", () => {
for (let i = 0; i < 10; i++) {
refs.push(createAndDisposeGraphControlsPanel());
}
await forceGC();
await forceGC(refs);
const survivors = refs.filter((r) => r.deref() !== undefined).length;
expect(survivors).toBe(0);
});
Expand Down