2
2
// for details. All rights reserved. Use of this source code is governed by a
3
3
// BSD-style license that can be found in the LICENSE file.import 'dart:async';
4
4
5
- // @dart = 2.9
6
-
5
+ import 'package:collection/collection.dart' ;
7
6
import 'package:logging/logging.dart' ;
8
7
import 'package:vm_service/vm_service.dart' ;
8
+ import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart' ;
9
9
10
10
import '../loaders/strategy.dart' ;
11
11
import '../utilities/domain.dart' ;
12
+ import '../services/chrome_debug_exception.dart' ;
12
13
import 'metadata/class.dart' ;
13
14
14
15
/// Keeps track of Dart libraries available in the running application.
@@ -21,24 +22,24 @@ class LibraryHelper extends Domain {
21
22
/// Map of libraryRef ID to [LibraryRef] .
22
23
final _libraryRefsById = < String , LibraryRef > {};
23
24
24
- LibraryRef _rootLib;
25
+ LibraryRef ? _rootLib;
25
26
26
27
LibraryHelper (AppInspectorInterface appInspector) {
27
28
inspector = appInspector;
28
29
}
29
30
30
31
Future <LibraryRef > get rootLib async {
31
- if (_rootLib != null ) return _rootLib;
32
+ if (_rootLib != null ) return _rootLib! ;
32
33
// TODO: read entrypoint from app metadata.
33
34
// Issue: https://github.com/dart-lang/webdev/issues/1290
34
35
final libraries = await libraryRefs;
35
- _rootLib = libraries. firstWhere ((lib) => lib.name. contains ( 'org-dartlang' ),
36
- orElse : ( ) => null );
36
+ _rootLib = libraries
37
+ . firstWhereOrNull ((lib ) => lib.name ? . contains ( 'org-dartlang' ) ?? false );
37
38
_rootLib = _rootLib ??
38
- libraries. firstWhere ((lib) => lib.name. contains ( 'main' ),
39
- orElse : ( ) => null );
39
+ libraries
40
+ . firstWhereOrNull ((lib ) => lib.name ? . contains ( 'main' ) ?? false );
40
41
_rootLib = _rootLib ?? (libraries.isNotEmpty ? libraries.last : null );
41
- return _rootLib;
42
+ return _rootLib! ;
42
43
}
43
44
44
45
/// Returns all libraryRefs in the app.
@@ -56,22 +57,29 @@ class LibraryHelper extends Domain {
56
57
return _libraryRefsById.values.toList ();
57
58
}
58
59
59
- Future <Library > libraryFor (LibraryRef libraryRef) async {
60
- final library = _librariesById[libraryRef.id];
61
- if (library != null ) return library;
62
- return _librariesById[libraryRef.id] = await _constructLibrary (libraryRef);
60
+ Future <Library ?> libraryFor (LibraryRef libraryRef) async {
61
+ final libraryId = libraryRef.id;
62
+ if (libraryId == null ) return null ;
63
+ final library =
64
+ _librariesById[libraryId] ?? await _constructLibrary (libraryRef);
65
+ if (library == null ) return null ;
66
+ return _librariesById[libraryId] = library;
63
67
}
64
68
65
- Future <LibraryRef > libraryRefFor (String objectId) async {
69
+ Future <LibraryRef ? > libraryRefFor (String objectId) async {
66
70
if (_libraryRefsById.isEmpty) await libraryRefs;
67
71
return _libraryRefsById[objectId];
68
72
}
69
73
70
- Future <Library > _constructLibrary (LibraryRef libraryRef) async {
74
+ Future <Library ?> _constructLibrary (LibraryRef libraryRef) async {
75
+ final libraryId = libraryRef.id;
76
+ final libraryUri = libraryRef.uri;
77
+ if (libraryId == null || libraryUri == null ) return null ;
78
+
71
79
// Fetch information about all the classes in this library.
72
80
final expression = '''
73
81
(function() {
74
- ${globalLoadStrategy .loadLibrarySnippet (libraryRef . uri )}
82
+ ${globalLoadStrategy .loadLibrarySnippet (libraryUri )}
75
83
var result = {};
76
84
var classes = Object.values(Object.getOwnPropertyDescriptors(library))
77
85
.filter((p) => 'value' in p)
@@ -88,41 +96,41 @@ class LibraryHelper extends Domain {
88
96
return result;
89
97
})()
90
98
''' ;
91
- final result =
92
- await inspector.remoteDebugger.sendCommand ('Runtime.evaluate' , params: {
93
- 'expression' : expression,
94
- 'returnByValue' : true ,
95
- 'contextId' : await inspector.contextId,
96
- });
97
- List <ClassRef > classRefs;
98
- if (result.result.containsKey ('exceptionDetails' )) {
99
+ RemoteObject ? result;
100
+ try {
101
+ result = await inspector.jsEvaluate (expression, returnByValue: true );
102
+ } on ChromeDebugException catch (_) {
99
103
// Unreferenced libraries are not loaded at runtime,
100
104
// return empty library object for consistency among
101
105
// VM Service implementations.
102
106
// TODO: Collect library and class information from debug symbols.
103
107
_logger.warning ('Library ${libraryRef .uri } is not loaded. '
104
108
'This can happen for unreferenced libraries.' );
105
- } else {
109
+ }
110
+ List <ClassRef >? classRefs;
111
+ if (result != null ) {
106
112
final classDescriptors =
107
- (result.result[ 'result' ][ ' value' ] ['classes' ] as List )
108
- .cast <Map <String , Object >>();
109
- classRefs = classDescriptors.map <ClassRef >((classDescriptor) {
113
+ (( result.value as Map < String , dynamic >) ['classes' ] as List ? )
114
+ ? .cast <Map <String , Object >>();
115
+ classRefs = classDescriptors? .map <ClassRef >((classDescriptor) {
110
116
final classMetaData = ClassMetaData (
111
- jsName: classDescriptor['name' ],
112
- libraryId: libraryRef.id,
113
- dartName: classDescriptor['dartName' ]);
117
+ jsName: classDescriptor['name' ],
118
+ libraryId: libraryRef.id,
119
+ dartName: classDescriptor['dartName' ],
120
+ );
114
121
return classMetaData.classRef;
115
122
}).toList ();
116
123
}
117
124
return Library (
118
- name: libraryRef.name,
119
- uri: libraryRef.uri,
120
- debuggable: true ,
121
- dependencies: [],
122
- scripts: await inspector.scriptRefsForLibrary (libraryRef.id),
123
- variables: [],
124
- functions: [],
125
- classes: classRefs,
126
- id: libraryRef.id);
125
+ name: libraryRef.name,
126
+ uri: libraryRef.uri,
127
+ debuggable: true ,
128
+ dependencies: [],
129
+ scripts: await inspector.scriptRefsForLibrary (libraryId),
130
+ variables: [],
131
+ functions: [],
132
+ classes: classRefs,
133
+ id: libraryId,
134
+ );
127
135
}
128
136
}
0 commit comments