Skip to content

Commit 2172ba7

Browse files
authored
Support breakpoints for hot reload (#2627)
Adds support for properly reregistering breakpoints across a hot reload. Like with hot restart, leverages the kPausePostRequest event in order to reregister breakpoints. DWDS does the initial work to load the new sources in ("hotReloadStart"), and pauses and sends the request. Upon disabling existing breakpoint, reregistering and registering new breakpoints and resuming, DWDS will resume the app and push the new sources into the runtime ("hotReloadEnd"). Also reinitializes some cached information in order to compute new sources. Note that it's very conservative for now. A future change should optimize the invalidation. See #2628 for that work. Adds tests for the following cases: Editing a line with a breakpoint. Adding a line before a breakpoint. Removing a line before a breakpoint. Adding a new file with a breakpoint in it. Breakpoint in previously captured code is removed. There's no pause when pause_isolates_on_start is false. dart-lang/sdk#60186 Includes a light refactor of testing to create temp directories wherever the TestProject needs to be edited. TestProjects should specify whether it's meant to be edited via editable and list its dependencies so they can be copied too.
1 parent 7f376d2 commit 2172ba7

File tree

70 files changed

+1540
-1012
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1540
-1012
lines changed

dwds/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## 24.4.0-wip
22

3+
- Added support for breakpoint registering on a hot reload with the DDC library bundle format using PausePostRequests.
4+
35
## 24.3.11
46

57
- Changed DWDS to always inject the client and added `useDwdsWebSocketConnection` flag to control communication protocol: when true uses socket-based implementation, when false uses Chrome-based communication protocol.

dwds/lib/src/debugging/inspector.dart

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
3232
/// Provides information about currently loaded scripts and objects and support
3333
/// for eval.
3434
class AppInspector implements AppInspectorInterface {
35-
final _scriptCacheMemoizer = AsyncMemoizer<List<ScriptRef>>();
35+
var _scriptCacheMemoizer = AsyncMemoizer<List<ScriptRef>>();
3636

3737
Future<List<ScriptRef>> get scriptRefs => _populateScriptCaches();
3838

@@ -68,9 +68,9 @@ class AppInspector implements AppInspectorInterface {
6868

6969
final ExecutionContext _executionContext;
7070

71-
late final LibraryHelper _libraryHelper;
72-
late final ClassHelper _classHelper;
73-
late final InstanceHelper _instanceHelper;
71+
late LibraryHelper _libraryHelper;
72+
late ClassHelper _classHelper;
73+
late InstanceHelper _instanceHelper;
7474

7575
final AssetReader _assetReader;
7676
final Locations _locations;
@@ -99,15 +99,25 @@ class AppInspector implements AppInspectorInterface {
9999
this._locations,
100100
this._root,
101101
this._executionContext,
102-
) : _isolateRef = _toIsolateRef(_isolate) {
102+
) : _isolateRef = _toIsolateRef(_isolate);
103+
104+
/// Reset all caches and recompute any mappings.
105+
///
106+
/// Should be called across hot reloads.
107+
Future<void> initialize() async {
108+
_scriptCacheMemoizer = AsyncMemoizer<List<ScriptRef>>();
109+
_scriptRefsById.clear();
110+
_serverPathToScriptRef.clear();
111+
_scriptIdToLibraryId.clear();
112+
_libraryIdToScriptRefs.clear();
113+
103114
_libraryHelper = LibraryHelper(this);
104115
_classHelper = ClassHelper(this);
105116
_instanceHelper = InstanceHelper(this);
106-
}
107117

108-
Future<void> initialize() async {
109118
final libraries = await _libraryHelper.libraryRefs;
110119
isolate.rootLib = await _libraryHelper.rootLib;
120+
isolate.libraries?.clear();
111121
isolate.libraries?.addAll(libraries);
112122

113123
final scripts = await scriptRefs;
@@ -702,8 +712,7 @@ class AppInspector implements AppInspectorInterface {
702712
/// This populates [_scriptRefsById], [_scriptIdToLibraryId],
703713
/// [_libraryIdToScriptRefs] and [_serverPathToScriptRef].
704714
///
705-
/// It is a one-time operation, because if we do a
706-
/// reload the inspector will get re-created.
715+
/// This will get repopulated on restarts and reloads.
707716
///
708717
/// Returns the list of scripts refs cached.
709718
Future<List<ScriptRef>> _populateScriptCaches() {

0 commit comments

Comments
 (0)