Skip to content

Unlink a removed node from its parents when it was stale - #427

Merged
tim-smart merged 1 commit into
tim-smart:mainfrom
janecakemaster:fix/remove-unlinks-stale-parents
Sep 25, 2026
Merged

tim-smart merged 1 commit into
tim-smart:mainfrom
janecakemaster:fix/remove-unlinks-stale-parents

Conversation

@janecakemaster

@janecakemaster janecakemaster commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Backport of Effect-TS/effect#7535, which fixed the same line in Effect v4's AtomRegistry on Aug 30.

Summary

  • Node.remove() returned early when lifetime was undefined, so it never called removeChild on the node's previousParents.
  • Those parents kept a removed node in children, so canBeRemoved stayed false and they, and every node above them, stayed in registry.nodes for good.
  • The fix deletes the early return. disposeLifetime() already handles an undefined lifetime, so remove() now always unlinks previousParents.

Why

invalidate() on a lazy node with no listeners calls disposeLifetime(), which clears lifetime and moves parents into previousParents without recomputing. If the node is removed before it recomputes (for example, unmount and then a parent update in the same tick), remove() hit the early return and left the parents linked to it. In our app this kept a large derived value alive after every page visit.

Validation

  • pnpm vitest run packages/atom/test/Atom.test.ts -t "invalidated before removal": fails before the fix (parent node still registered), passes after.
  • pnpm test --run: 8 files, 105 tests passed.
  • pnpm lint: passed.
  • pnpm check: passed.

@janecakemaster
janecakemaster force-pushed the fix/remove-unlinks-stale-parents branch from a45508d to a82515b Compare September 25, 2026 04:21
@tim-smart
tim-smart merged commit 5c4a0a9 into tim-smart:main Sep 25, 2026
3 checks passed
@github-actions github-actions Bot mentioned this pull request Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants