Skip to content

Commit 3748707

Browse files
Merge pull request #21189 from emberjs/copilot/fix-stale-references-metadata
[BUGFIX] clear stale metadata references after destruction to allow GC
2 parents dd9479c + 4215d0d commit 3748707

2 files changed

Lines changed: 19 additions & 1 deletion

File tree

packages/@glimmer/destroyable/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ export function destroy(destroyable: Destroyable) {
189189
function removeChildFromParent(child: Destroyable, parent: Destroyable) {
190190
let parentMeta = getDestroyableMeta(parent);
191191

192-
if (parentMeta.state === LIVE_STATE) {
192+
if (parentMeta.state !== DESTROYED_STATE) {
193193
parentMeta.children = remove(
194194
parentMeta.children,
195195
child,

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('parent no longer references child after cascaded destruction', (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 releases child reference during cascaded 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)