Skip to content

Commit 12ebfa7

Browse files
fix(@glimmer/destroyable): clear stale metadata references after destruction to allow GC
Co-authored-by: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
1 parent 5c631c2 commit 12ebfa7

2 files changed

Lines changed: 24 additions & 0 deletions

File tree

packages/@glimmer/destroyable/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,12 @@ export function destroy(destroyable: Destroyable) {
183183
});
184184

185185
meta.state = DESTROYED_STATE;
186+
187+
// Release references so GC can reclaim the destroyed tree
188+
meta.parents = null;
189+
meta.children = null;
190+
meta.eagerDestructors = null;
191+
meta.destructors = null;
186192
});
187193
}
188194

packages/@glimmer/destroyable/test/destroyables-test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { DEBUG } from '@glimmer/env';
22
import type { GlobalContext } from '@glimmer/global-context';
33
import { unwrap } from '@glimmer/debug-util';
44
import {
5+
_hasDestroyableChildren,
56
assertDestroyablesDestroyed,
67
associateDestroyableChild,
78
destroy,
@@ -384,6 +385,23 @@ module('Destroyables', (hooks) => {
384385
assert.verifySteps(['child destructor', 'parent destructor'], 'destructors run bottom up');
385386
});
386387

388+
test('metadata children reference is cleared after destruction completes', (assert) => {
389+
const parent = {};
390+
const child = {};
391+
392+
associateDestroyableChild(parent, child);
393+
394+
assert.true(_hasDestroyableChildren(parent), 'parent has children before destruction');
395+
396+
destroy(parent);
397+
flush();
398+
399+
assert.false(
400+
_hasDestroyableChildren(parent),
401+
'parent metadata clears children reference after destruction, allowing GC to reclaim the tree'
402+
);
403+
});
404+
387405
if (DEBUG) {
388406
test('attempting to unregister a destructor that was not registered throws an error', (assert) => {
389407
assert.throws(() => {

0 commit comments

Comments
 (0)