@@ -13,6 +13,7 @@ import 'package:dwds/src/debugging/execution_context.dart';
13
13
import 'package:dwds/src/debugging/instance.dart' ;
14
14
import 'package:dwds/src/debugging/libraries.dart' ;
15
15
import 'package:dwds/src/debugging/location.dart' ;
16
+ import 'package:dwds/src/debugging/metadata/provider.dart' ;
16
17
import 'package:dwds/src/debugging/remote_debugger.dart' ;
17
18
import 'package:dwds/src/loaders/ddc_library_bundle.dart' ;
18
19
import 'package:dwds/src/readers/asset_reader.dart' ;
@@ -34,7 +35,9 @@ import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
34
35
class AppInspector implements AppInspectorInterface {
35
36
var _scriptCacheMemoizer = AsyncMemoizer <List <ScriptRef >>();
36
37
37
- Future <List <ScriptRef >> get scriptRefs => _populateScriptCaches ();
38
+ Future <List <ScriptRef >> getScriptRefs ([
39
+ InvalidatedModuleReport ? invalidatedModuleReport,
40
+ ]) => _populateScriptCaches (invalidatedModuleReport);
38
41
39
42
final _logger = Logger ('AppInspector' );
40
43
@@ -103,24 +106,35 @@ class AppInspector implements AppInspectorInterface {
103
106
104
107
/// Reset all caches and recompute any mappings.
105
108
///
106
- /// Should be called across hot reloads.
107
- Future <void > initialize () async {
109
+ /// Should be called across hot reloads with a valid [invalidatedModuleReport] .
110
+ Future <void > initialize ([
111
+ InvalidatedModuleReport ? invalidatedModuleReport,
112
+ ]) async {
108
113
_scriptCacheMemoizer = AsyncMemoizer <List <ScriptRef >>();
109
- _scriptRefsById.clear ();
110
- _serverPathToScriptRef.clear ();
111
- _scriptIdToLibraryId.clear ();
112
- _libraryIdToScriptRefs.clear ();
113
114
114
- _libraryHelper = LibraryHelper (this );
115
+ // TODO(srujzs): We can invalidate these in a smarter way instead of
116
+ // reinitializing when doing a hot reload, but these helpers recompute info
117
+ // on demand and therefore are not in the critical path.
115
118
_classHelper = ClassHelper (this );
116
119
_instanceHelper = InstanceHelper (this );
117
120
121
+ if (invalidatedModuleReport != null ) {
122
+ // Invalidate `_libraryHelper` as we use it populate any script caches.
123
+ _libraryHelper.invalidate (invalidatedModuleReport);
124
+ } else {
125
+ _libraryHelper = LibraryHelper (this );
126
+ _scriptRefsById.clear ();
127
+ _serverPathToScriptRef.clear ();
128
+ _scriptIdToLibraryId.clear ();
129
+ _libraryIdToScriptRefs.clear ();
130
+ }
131
+
118
132
final libraries = await _libraryHelper.libraryRefs;
119
133
isolate.rootLib = await _libraryHelper.rootLib;
120
134
isolate.libraries? .clear ();
121
135
isolate.libraries? .addAll (libraries);
122
136
123
- final scripts = await scriptRefs ;
137
+ final scripts = await getScriptRefs (invalidatedModuleReport) ;
124
138
125
139
await DartUri .initialize ();
126
140
DartUri .recordAbsoluteUris (libraries.map ((lib) => lib.uri).nonNulls);
@@ -583,7 +597,7 @@ class AppInspector implements AppInspectorInterface {
583
597
/// All the scripts in the isolate.
584
598
@override
585
599
Future <ScriptList > getScripts () async {
586
- return ScriptList (scripts: await scriptRefs );
600
+ return ScriptList (scripts: await getScriptRefs () );
587
601
}
588
602
589
603
/// Calls the Chrome Runtime.getProperties API for the object with [objectId] .
@@ -714,19 +728,50 @@ class AppInspector implements AppInspectorInterface {
714
728
///
715
729
/// This will get repopulated on restarts and reloads.
716
730
///
731
+ /// If [invalidatedModuleReport] is provided, only invalidates and
732
+ /// recalculates caches for the invalidated libraries.
733
+ ///
717
734
/// Returns the list of scripts refs cached.
718
- Future <List <ScriptRef >> _populateScriptCaches () {
735
+ Future <List <ScriptRef >> _populateScriptCaches ([
736
+ InvalidatedModuleReport ? invalidatedModuleReport,
737
+ ]) {
719
738
return _scriptCacheMemoizer.runOnce (() async {
720
739
final scripts =
721
740
await globalToolConfiguration.loadStrategy
722
741
.metadataProviderFor (appConnection.request.entrypointPath)
723
742
.scripts;
743
+ final invalidatedLibraries = invalidatedModuleReport? .deletedLibraries
744
+ .union (invalidatedModuleReport.reloadedLibraries);
745
+ if (invalidatedLibraries != null ) {
746
+ for (final libraryUri in invalidatedLibraries) {
747
+ final libraryRef = await _libraryHelper.libraryRefFor (libraryUri);
748
+ final libraryId = libraryRef? .id;
749
+ if (libraryId == null ) continue ;
750
+ final scriptRefs = _libraryIdToScriptRefs.remove (libraryId);
751
+ if (scriptRefs == null ) continue ;
752
+ for (final scriptRef in scriptRefs) {
753
+ final scriptId = scriptRef.id;
754
+ final scriptUri = scriptRef.uri;
755
+ if (scriptId != null && scriptUri != null ) {
756
+ _scriptRefsById.remove (scriptId);
757
+ _scriptIdToLibraryId.remove (scriptId);
758
+ _serverPathToScriptRef.remove (
759
+ DartUri (scriptUri, _root).serverPath,
760
+ );
761
+ }
762
+ }
763
+ }
764
+ }
724
765
// For all the non-dart: libraries, find their parts and create scriptRefs
725
766
// for them.
726
767
final userLibraries = _userLibraryUris (
727
768
isolate.libraries ?? < LibraryRef > [],
728
769
);
729
770
for (final uri in userLibraries) {
771
+ if (invalidatedLibraries != null &&
772
+ ! invalidatedLibraries.contains (uri)) {
773
+ continue ;
774
+ }
730
775
final parts = scripts[uri];
731
776
final scriptRefs = [
732
777
ScriptRef (uri: uri, id: createId ()),
0 commit comments