Skip to content

Commit

Permalink
fix: Check for removing state while adding a child (#3050)
Browse files Browse the repository at this point in the history
Adding a child component to a parent which is in `removing` state,
caused the lifecycle processing to go into a cyclic dependency when the
parent is re-added. It happens because, while processing the lifecycle
events, child's add event causes itself and the parent to get added to
the blocked list. As a result of this, when the parent's add event is
processed next, it gets skipped due to being in the blocked list.

This PR makes sure that the child does not get enqueued when parent is
about to be removed.
  • Loading branch information
ufrshubham authored Feb 25, 2024
1 parent 892052b commit 3a24a51
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
2 changes: 1 addition & 1 deletion packages/flame/lib/src/components/core/component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ class Component {
_clearRemovingBit();
}
game.enqueueMove(child, this);
} else if (isMounted && !child.isMounted) {
} else if (isMounted && !isRemoving && !child.isMounted) {
child._parent = this;
game.enqueueAdd(child, this);
} else {
Expand Down
21 changes: 21 additions & 0 deletions packages/flame/test/components/component_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,27 @@ void main() {
expect(wrapper.contains(child), true);
},
);

testWithFlameGame('when parent is in removing state', (game) async {
final parent = Component();
final child = Component();

await game.add(parent);
await game.ready();

// Remove the parent and add the child in the same tick.
parent.removeFromParent();
await parent.add(child);

// Timeout is added because processLifecycleEvents of ComponentTreeRoot
// gets blocked in such cases.
expect(game.ready().timeout(const Duration(seconds: 2)), completes);

// Adding the parent again should eventually mount the child as well.
await game.add(parent);
await game.ready();
expect(child.isMounted, true);
});
});

group('Removing components', () {
Expand Down

0 comments on commit 3a24a51

Please sign in to comment.