Skip to content

fix: Clear removing state on the moved child instead of its new parent#3958

Merged
spydon merged 1 commit into
mainfrom
fix/lifecycle-removing-state
Jul 22, 2026
Merged

fix: Clear removing state on the moved child instead of its new parent#3958
spydon merged 1 commit into
mainfrom
fix/lifecycle-removing-state

Conversation

@spydon

@spydon spydon commented Jul 21, 2026

Copy link
Copy Markdown
Member

Description

Two lifecycle fixes found while investigating #3957 (Phase 0), plus golden tests that pin behavior the later phases must preserve.

Fixes

  • Component._addChild called _clearRemovingBit() on this (the new parent) instead of on the child being re-parented. Re-parenting a child that was scheduled for removal therefore corrupted the new parent's removing state (it could be silently taken out of its own pending removal), while the child kept its stale removing flag until the move was processed. The bit is now cleared on the child, right when its pending removal is dequeued.
  • ComponentTreeRoot._blocked stored identityHashCode ints. Two distinct components can share an identity hash, in which case an unrelated component's lifecycle events would be spuriously blocked for a tick. The set now stores the components themselves (identity equality, same performance).

New tests

  • Moving a component that is scheduled for removal cancels the removal (exactly one onRemove, two onMounts).
  • Regression test for the removing-state corruption described above (fails without the fix).
  • Equal-priority children keep insertion order, both initially and after a sibling's priority change.
  • componentsAtPoint yields top-most first and tolerates tree mutations while the iterable is being consumed (removals are deferred).

Checklist

  • I have followed the Contributor Guide when preparing my PR.
  • I have updated/added tests for ALL new/updated/fixed functionality.
  • [-] I have updated/added relevant documentation in docs and added dartdoc comments with ///.
  • [-] I have updated/added relevant examples in examples or docs.

Breaking Change?

  • Yes, this PR is a breaking change.
  • No, this PR is not a breaking change.

Related Issues

Related to #3957

@spydon
spydon force-pushed the fix/lifecycle-removing-state branch from 3acc287 to 5841631 Compare July 21, 2026 22:27
@spydon
spydon requested a review from Copilot July 21, 2026 22:34
@spydon
spydon requested a review from luanpotter July 21, 2026 22:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses two lifecycle correctness issues in Flame’s component tree processing (re-parenting during removal, and lifecycle-event blocking), and adds regression tests to lock in ordering and hit-testing behaviors relevant to the ongoing component-system efficiency work.

Changes:

  • Fixes Component._addChild to clear the removing state on the moved child (after dequeuing its removal), rather than incorrectly clearing it on the new parent.
  • Fixes ComponentTreeRoot._blocked to store Component instances (identity equality) instead of identityHashCode ints, avoiding rare but real hash-collision blocking bugs.
  • Adds tests covering equal-priority stable ordering, move-while-removing lifecycle behavior, and componentsAtPoint iteration order + mutation tolerance.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
packages/flame/lib/src/components/core/component.dart Corrects removing-flag handling when re-parenting a child that was scheduled for removal.
packages/flame/lib/src/components/core/component_tree_root.dart Makes lifecycle-event blocking robust by tracking blocked components directly (identity) instead of hash integers.
packages/flame/test/components/component_test.dart Adds lifecycle and hit-testing regression tests for move-while-removing and mutation-during-hit-test iteration.
packages/flame/test/components/priority_test.dart Adds stable ordering tests for equal-priority components, including after a priority change.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@spydon
spydon merged commit 8bd8475 into main Jul 22, 2026
9 checks passed
@spydon
spydon deleted the fix/lifecycle-removing-state branch July 22, 2026 07:28
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.

3 participants