Skip to content

Commit

Permalink
Use a preventative solution with a proper test
Browse files Browse the repository at this point in the history
  • Loading branch information
dustyholmes-wf committed Mar 4, 2024
1 parent 90aea8c commit 242cf97
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 9 deletions.
17 changes: 8 additions & 9 deletions lib/src/lifecycle_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,14 @@ abstract class LifecycleModule extends SimpleModule with Disposable {

final completer = Completer<Null>();
onWillLoadChildModule(childModule).then((_) async {
// It is possible to reach this point due to the asynchrony of onWillLoadChildModule.
// In that case, simply do not load the child module and instead dispose it.
if (isUnloaded || isUnloading) {
await childModule.dispose();
completer.complete();
return;
}

_willLoadChildModuleController.add(childModule);

final childModuleWillUnloadSub = listenToStream(
Expand Down Expand Up @@ -879,15 +887,6 @@ abstract class LifecycleModule extends SimpleModule with Disposable {
@override
@protected
Future<Null> onWillDispose() async {
// It is possible for child modules to be added to the list of children after unload
// but before dispose due to asynchrony. Continuing with dispose will cause these to
// be disposed which will trigger unload and cause exceptions due to the parent being
// partialy disposed. Ensure we give everything a chance to be unloaded before proceeding.
await Future.wait(_childModules
.toList()
.where((child) => !child.isUnloaded)
.map((child) => child.unload()));

if (isInstantiated || isUnloaded) {
return;
}
Expand Down
23 changes: 23 additions & 0 deletions test/lifecycle_module_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1756,6 +1756,29 @@ void runTests(bool runSpanTests) {
childModule.eventList, equals(['willLoad', 'onLoad', 'didLoad']));
});

test('followed by parent unload causes child to dispose and never load',
() async {
parentModule.eventList?.clear();
final load = parentModule.loadChildModule(childModule);

await parentModule.unload();
await load;

expect(
parentModule.eventList,
equals([
'onWillLoadChildModule',
'onShouldUnload',
'willUnload',
'onUnload',
'didUnload',
'onDispose'
]),
);

expect(childModule.eventList, equals(['onDispose']));
});

test('should emit lifecycle log events', () async {
expect(
Logger.root.onRecord,
Expand Down

0 comments on commit 242cf97

Please sign in to comment.