Skip to content

Commit b887407

Browse files
committed
Support breakpoints for hot reload
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. 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.
1 parent 6759806 commit b887407

File tree

15 files changed

+832
-282
lines changed

15 files changed

+832
-282
lines changed

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)