fix: Clear removing state on the moved child instead of its new parent#3958
Merged
Conversation
spydon
force-pushed
the
fix/lifecycle-removing-state
branch
from
July 21, 2026 22:27
3acc287 to
5841631
Compare
Contributor
There was a problem hiding this comment.
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._addChildto clear the removing state on the moved child (after dequeuing its removal), rather than incorrectly clearing it on the new parent. - Fixes
ComponentTreeRoot._blockedto storeComponentinstances (identity equality) instead ofidentityHashCodeints, avoiding rare but real hash-collision blocking bugs. - Adds tests covering equal-priority stable ordering, move-while-removing lifecycle behavior, and
componentsAtPointiteration 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.
erickzanardo
approved these changes
Jul 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Two lifecycle fixes found while investigating #3957 (Phase 0), plus golden tests that pin behavior the later phases must preserve.
Fixes
Component._addChildcalled_clearRemovingBit()onthis(the new parent) instead of on thechildbeing 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._blockedstoredidentityHashCodeints. 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
onRemove, twoonMounts).componentsAtPointyields top-most first and tolerates tree mutations while the iterable is being consumed (removals are deferred).Checklist
docsand added dartdoc comments with///.examplesordocs.Breaking Change?
Related Issues
Related to #3957