Skip to content

Commit 99abc53

Browse files
authored
Wait for a resume event to run the main() method after a page refresh (#2431)
1 parent d46cf50 commit 99abc53

File tree

8 files changed

+98
-22
lines changed

8 files changed

+98
-22
lines changed

dwds/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## 24.1.0-wip
22

33
- Fix bug where debugging clients are not aware of service extensions when connecting to a new web app. - [#2388](https://github.com/dart-lang/webdev/pull/2388)
4+
- Respect the value of `pause_isolates_on_start` during page-refreshes. - [#2431](https://github.com/dart-lang/webdev/pull/2431)
45

56
## 24.0.0
67

dwds/lib/dart_web_debug_service.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,4 @@ class Dwds {
139139
debugSettings.enableDebugging,
140140
);
141141
}
142-
143-
bool shouldPauseIsolatesOnStart(String appId) =>
144-
_devHandler.shouldPauseIsolatesOnStart(appId);
145142
}

dwds/lib/src/connections/app_connection.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ class AppConnection {
1818
final _startedCompleter = Completer<void>();
1919
final _doneCompleter = Completer<void>();
2020
final SocketConnection _connection;
21+
final Future<void> _readyToRunMain;
2122

22-
AppConnection(this.request, this._connection) {
23+
AppConnection(this.request, this._connection, this._readyToRunMain) {
2324
safeUnawaited(_connection.sink.done.then((v) => _doneCompleter.complete()));
2425
}
2526

@@ -34,6 +35,12 @@ class AppConnection {
3435
if (_startedCompleter.isCompleted) {
3536
throw StateError('Main has already started.');
3637
}
38+
39+
safeUnawaited(_runMain());
40+
}
41+
42+
Future<void> _runMain() async {
43+
await _readyToRunMain;
3744
_connection.sink.add(jsonEncode(serializers.serialize(RunRequest())));
3845
_startedCompleter.complete();
3946
}

dwds/lib/src/dwds_vm_client.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ void _waitForResumeEventToRunMain(
428428
final issuedReadyToRunMainCompleter = Completer<void>();
429429

430430
final resumeEventsSubscription =
431-
chromeProxyService.resumeAfterHotRestartEventsStream.listen((_) async {
431+
chromeProxyService.resumeAfterRestartEventsStream.listen((_) async {
432432
await chromeProxyService.inspector.jsEvaluate('\$dartReadyToRunMain();');
433433
if (!issuedReadyToRunMainCompleter.isCompleted) {
434434
issuedReadyToRunMainCompleter.complete();

dwds/lib/src/handlers/dev_handler.dart

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,6 @@ class DevHandler {
121121
_servicesByAppId.clear();
122122
}();
123123

124-
bool shouldPauseIsolatesOnStart(String appId) =>
125-
_servicesByAppId[appId]?.chromeProxyService.pauseIsolatesOnStart ?? false;
126-
127124
void _emitBuildResults(BuildResult result) {
128125
if (result.status != BuildStatus.succeeded) return;
129126
for (var injectedConnection in _injectedConnections) {
@@ -441,7 +438,12 @@ class DevHandler {
441438
// were previously launched and create the new isolate.
442439
final services = _servicesByAppId[message.appId];
443440
final existingConnection = _appConnectionByAppId[message.appId];
444-
final connection = AppConnection(message, sseConnection);
441+
// Completer to indicate when the app's main() method is ready to be run.
442+
// Its future is passed to the AppConnection so that it can be awaited on
443+
// before running the app's main() method:
444+
final readyToRunMainCompleter = Completer<void>();
445+
final connection =
446+
AppConnection(message, sseConnection, readyToRunMainCompleter.future);
445447

446448
// We can take over a connection if there is no connectedInstanceId (this
447449
// means the client completely disconnected), or if the existing
@@ -460,13 +462,53 @@ class DevHandler {
460462

461463
// Reconnect to existing service.
462464
services.connectedInstanceId = message.instanceId;
465+
466+
if (services.chromeProxyService.pauseIsolatesOnStart) {
467+
// If the pause-isolates-on-start flag is set, we need to wait for
468+
// the resume event to run the app's main() method.
469+
_waitForResumeEventToRunMain(
470+
services.chromeProxyService.resumeAfterRestartEventsStream,
471+
readyToRunMainCompleter,
472+
);
473+
} else {
474+
// Otherwise, we can run the app's main() method immediately.
475+
readyToRunMainCompleter.complete();
476+
}
477+
463478
await services.chromeProxyService.createIsolate(connection);
479+
} else {
480+
// If this is the initial app connection, we can run the app's main()
481+
// method immediately.
482+
readyToRunMainCompleter.complete();
464483
}
465484
_appConnectionByAppId[message.appId] = connection;
466485
_connectedApps.add(connection);
467486
return connection;
468487
}
469488

489+
/// Waits for a resume event to trigger the app's main() method.
490+
///
491+
/// The [readyToRunMainCompleter]'s future will be passed to the
492+
/// [AppConnection] so that it can be awaited on before running the app's
493+
/// main() method.
494+
void _waitForResumeEventToRunMain(
495+
Stream<String> resumeEventsStream,
496+
Completer<void> readyToRunMainCompleter,
497+
) {
498+
final resumeEventsSubscription = resumeEventsStream.listen((_) {
499+
readyToRunMainCompleter.complete();
500+
if (!readyToRunMainCompleter.isCompleted) {
501+
readyToRunMainCompleter.complete();
502+
}
503+
});
504+
505+
safeUnawaited(
506+
readyToRunMainCompleter.future.then((_) {
507+
resumeEventsSubscription.cancel();
508+
}),
509+
);
510+
}
511+
470512
void _handleIsolateExit(AppConnection appConnection) {
471513
_servicesByAppId[appConnection.request.appId]
472514
?.chromeProxyService

dwds/lib/src/services/chrome_proxy_service.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,18 +99,18 @@ class ChromeProxyService implements VmServiceInterface {
9999
/// This value can be updated at runtime via [setFlag].
100100
bool get pauseIsolatesOnStart => _pauseIsolatesOnStart;
101101

102-
final _resumeAfterHotRestartEventsController =
102+
final _resumeAfterRestartEventsController =
103103
StreamController<String>.broadcast();
104104

105105
/// A global stream of resume events.
106106
///
107107
/// The values in the stream are the isolates IDs for the resume event.
108108
///
109-
/// IMPORTANT: This should only be listened to during a hot-restart. The
110-
/// debugger ignores any resume events as long as there is a subscriber to
111-
/// this stream.
112-
Stream<String> get resumeAfterHotRestartEventsStream =>
113-
_resumeAfterHotRestartEventsController.stream;
109+
/// IMPORTANT: This should only be listened to during a hot-restart or page
110+
/// refresh. The debugger ignores any resume events as long as there is a
111+
/// subscriber to this stream.
112+
Stream<String> get resumeAfterRestartEventsStream =>
113+
_resumeAfterRestartEventsController.stream;
114114

115115
final _logger = Logger('ChromeProxyService');
116116

@@ -1147,8 +1147,8 @@ ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").developer.
11471147
}) async {
11481148
// If there is a subscriber listening for a resume event after hot-restart,
11491149
// then add the event to the stream and skip processing it.
1150-
if (_resumeAfterHotRestartEventsController.hasListener) {
1151-
_resumeAfterHotRestartEventsController.add(isolateId);
1150+
if (_resumeAfterRestartEventsController.hasListener) {
1151+
_resumeAfterRestartEventsController.add(isolateId);
11521152
return Success();
11531153
}
11541154
if (inspector.appConnection.isStarted) {

dwds/test/chrome_proxy_service_test.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2070,9 +2070,8 @@ void main() {
20702070
service.setFlag('pause_isolates_on_start', 'true'),
20712071
completion(_isSuccess),
20722072
);
2073-
final appId = context.appConnection.request.appId;
20742073
expect(
2075-
context.dwds!.shouldPauseIsolatesOnStart(appId),
2074+
context.service.pauseIsolatesOnStart,
20762075
equals(true),
20772076
);
20782077
});
@@ -2083,9 +2082,8 @@ void main() {
20832082
service.setFlag('pause_isolates_on_start', 'false'),
20842083
completion(_isSuccess),
20852084
);
2086-
final appId = context.appConnection.request.appId;
20872085
expect(
2088-
context.dwds!.shouldPauseIsolatesOnStart(appId),
2086+
context.service.pauseIsolatesOnStart,
20892087
equals(false),
20902088
);
20912089
});

dwds/test/reload_test.dart

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,8 @@ void main() {
531531
undoEdit();
532532
});
533533

534-
test('does not run app until there is a resume event', () async {
534+
test('after hot-restart, does not run app until there is a resume event',
535+
() async {
535536
await makeEditAndWaitForRebuild();
536537

537538
final eventsDone = expectLater(
@@ -563,6 +564,36 @@ void main() {
563564
final sourceAfterResume = await context.webDriver.pageSource;
564565
expect(sourceAfterResume.contains(newString), isTrue);
565566
});
567+
568+
test('after page refresh, does not run app until there is a resume event',
569+
() async {
570+
await makeEditAndWaitForRebuild();
571+
572+
await context.webDriver.driver.refresh();
573+
574+
final eventsDone = expectLater(
575+
client.onIsolateEvent,
576+
emitsThrough(
577+
emitsInOrder([
578+
_hasKind(EventKind.kIsolateExit),
579+
_hasKind(EventKind.kIsolateStart),
580+
_hasKind(EventKind.kIsolateRunnable),
581+
]),
582+
),
583+
);
584+
585+
await eventsDone;
586+
587+
final sourceBeforeResume = await context.webDriver.pageSource;
588+
expect(sourceBeforeResume.contains(newString), isFalse);
589+
590+
final vm = await client.getVM();
591+
final isolateId = vm.isolates!.first.id!;
592+
await client.resume(isolateId);
593+
594+
final sourceAfterResume = await context.webDriver.pageSource;
595+
expect(sourceAfterResume.contains(newString), isTrue);
596+
});
566597
});
567598
}
568599

0 commit comments

Comments
 (0)