Skip to content

Commit 6bbc231

Browse files
committed
Defer execution of main until resume for hot restart with DDC library bundle format
pause_isolates_on_start tells DWDS and the client that during a hot restart or a hot reload, the VM service will pause and is actively waiting for the client to remove existing breakpoints, reregister them, and then resume. It lets the client know by sending a kPausePostRequest event. In order to do this in DWDS, we need to defer the execution of main until that resume. So, like we do with the require restarter, we wait for a completer to finish before we call main after a hot restart. This completer is only provided when the flag is enabled. Fixes existing code that marks the completer as completed before running main. The previous code canceled the subscription in an unawaited Future. This may result in us recalling main because the event stream could still have a listener. An example is if we hit a breakpoint immediately after main and call resume. Also fixes an issue where metadata information isn't recomputed on a hot restart. This is needed when new files are added. Adds tests for: - Modifying a line with a breakpoint and restarting. - Adding a line before a breakpoint and restarting. - Removing a line before a breakpoint and restarting. - Adding a file and putting a breakpoint in it before restarting.
1 parent 5dbb30e commit 6bbc231

File tree

12 files changed

+844
-585
lines changed

12 files changed

+844
-585
lines changed

dwds/lib/src/dwds_vm_client.dart

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import 'package:dwds/src/events.dart';
99
import 'package:dwds/src/services/chrome_debug_exception.dart';
1010
import 'package:dwds/src/services/chrome_proxy_service.dart';
1111
import 'package:dwds/src/services/debug_service.dart';
12-
import 'package:dwds/src/utilities/shared.dart';
1312
import 'package:dwds/src/utilities/synchronized.dart';
1413
import 'package:logging/logging.dart';
1514
import 'package:uuid/uuid.dart';
@@ -443,24 +442,14 @@ Future<Map<String, dynamic>> _hotRestart(
443442
}
444443

445444
void _waitForResumeEventToRunMain(ChromeProxyService chromeProxyService) {
446-
final issuedReadyToRunMainCompleter = Completer<void>();
447-
448-
final resumeEventsSubscription = chromeProxyService
449-
.resumeAfterRestartEventsStream
445+
StreamSubscription<String>? resumeEventsSubscription;
446+
resumeEventsSubscription = chromeProxyService.resumeAfterRestartEventsStream
450447
.listen((_) async {
448+
await resumeEventsSubscription!.cancel();
451449
await chromeProxyService.inspector.jsEvaluate(
452450
'\$dartReadyToRunMain();',
453451
);
454-
if (!issuedReadyToRunMainCompleter.isCompleted) {
455-
issuedReadyToRunMainCompleter.complete();
456-
}
457452
});
458-
459-
safeUnawaited(
460-
issuedReadyToRunMainCompleter.future.then((_) {
461-
resumeEventsSubscription.cancel();
462-
}),
463-
);
464453
}
465454

466455
Future<Map<String, dynamic>> _fullReload(

dwds/lib/src/handlers/dev_handler.dart

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -538,18 +538,11 @@ class DevHandler {
538538
Stream<String> resumeEventsStream,
539539
Completer<void> readyToRunMainCompleter,
540540
) {
541-
final resumeEventsSubscription = resumeEventsStream.listen((_) {
541+
StreamSubscription<String>? resumeEventsSubscription;
542+
resumeEventsSubscription = resumeEventsStream.listen((_) async {
543+
await resumeEventsSubscription!.cancel();
542544
readyToRunMainCompleter.complete();
543-
if (!readyToRunMainCompleter.isCompleted) {
544-
readyToRunMainCompleter.complete();
545-
}
546545
});
547-
548-
safeUnawaited(
549-
readyToRunMainCompleter.future.then((_) {
550-
resumeEventsSubscription.cancel();
551-
}),
552-
);
553546
}
554547

555548
void _handleIsolateExit(AppConnection appConnection) {

0 commit comments

Comments
 (0)