@@ -6,10 +6,12 @@ import 'package:dwds/src/debugging/remote_debugger.dart';
6
6
import 'package:dwds/src/loaders/strategy.dart' ;
7
7
import 'package:dwds/src/services/chrome_debug_exception.dart' ;
8
8
import 'package:dwds/src/utilities/domain.dart' ;
9
+ import 'package:logging/logging.dart' ;
9
10
import 'package:vm_service/vm_service.dart' ;
10
11
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart' ;
11
12
12
13
const _dartCoreLibrary = 'dart:core' ;
14
+ const _dartInterceptorsLibrary = 'dart:_interceptors' ;
13
15
14
16
/// A hard-coded ClassRef for the Closure class.
15
17
final classRefForClosure = classRefFor (_dartCoreLibrary, 'Closure' );
@@ -20,6 +22,31 @@ final classRefForString = classRefFor(_dartCoreLibrary, InstanceKind.kString);
20
22
/// A hard-coded ClassRef for a (non-existent) class called Unknown.
21
23
final classRefForUnknown = classRefFor (_dartCoreLibrary, 'Unknown' );
22
24
25
+ /// A hard-coded ClassRef for a JS exception.
26
+ ///
27
+ /// Exceptions are instances of NativeError and its subtypes.
28
+ /// We detect their common base type in class metadata and replace their
29
+ /// classRef by hard-coded reference in instances and instance refs.
30
+ ///
31
+ /// TODO(annagrin): this breaks on name changes for JS types.
32
+ /// https://github.com/dart-lang/sdk/issues/51583
33
+ final classRefForNativeJsError =
34
+ classRefFor (_dartInterceptorsLibrary, 'NativeError' );
35
+
36
+ /// Returns true for non-dart JavaScript classes.
37
+ ///
38
+ /// TODO(annagrin): this breaks on name changes for JS types.
39
+ /// https://github.com/dart-lang/sdk/issues/51583
40
+ bool isNativeJsObjectRef (ClassRef ? classRef) {
41
+ final className = classRef? .name;
42
+ final libraryUri = classRef? .library? .uri;
43
+ // Non-dart JS objects are all instances of JavaScriptObject
44
+ // and its subtypes with names that end with 'JavaScriptObject'.
45
+ return className != null &&
46
+ libraryUri == _dartInterceptorsLibrary &&
47
+ className.endsWith ('JavaScriptObject' );
48
+ }
49
+
23
50
/// A hard-coded LibraryRef for a a dart:core library.
24
51
final libraryRefForCore = LibraryRef (
25
52
id: _dartCoreLibrary,
@@ -43,6 +70,8 @@ ClassRef classRefFor(String libraryId, String? name) => ClassRef(
43
70
44
71
/// Meta data for a remote Dart class in Chrome.
45
72
class ClassMetaData {
73
+ static final _logger = Logger ('ClassMetadata' );
74
+
46
75
/// The name of the JS constructor for the object.
47
76
///
48
77
/// This may be a constructor for a Dart, but it's still a JS name. For
@@ -67,6 +96,7 @@ class ClassMetaData {
67
96
Object ? length,
68
97
bool isFunction = false ,
69
98
bool isRecord = false ,
99
+ bool isNativeError = false ,
70
100
}) {
71
101
return ClassMetaData ._(
72
102
jsName as String ? ,
@@ -75,6 +105,7 @@ class ClassMetaData {
75
105
int .tryParse ('$length ' ),
76
106
isFunction,
77
107
isRecord,
108
+ isNativeError,
78
109
);
79
110
}
80
111
@@ -85,6 +116,7 @@ class ClassMetaData {
85
116
this .length,
86
117
this .isFunction,
87
118
this .isRecord,
119
+ this .isNativeError,
88
120
);
89
121
90
122
/// Returns the ID of the class.
@@ -100,18 +132,22 @@ class ClassMetaData {
100
132
try {
101
133
final evalExpression = '''
102
134
function(arg) {
103
- const sdkUtils = ${globalLoadStrategy .loadModuleSnippet }('dart_sdk').dart;
104
- const classObject = sdkUtils.getReifiedType(arg);
105
- const isFunction = classObject instanceof sdkUtils.AbstractFunctionType;
106
- const isRecord = classObject instanceof sdkUtils.RecordType;
135
+ const sdk = ${globalLoadStrategy .loadModuleSnippet }('dart_sdk');
136
+ const dart = sdk.dart;
137
+ const interceptors = sdk._interceptors;
138
+ const classObject = dart.getReifiedType(arg);
139
+ const isFunction = classObject instanceof dart.AbstractFunctionType;
140
+ const isRecord = classObject instanceof dart.RecordType;
141
+ const isNativeError = dart.is(arg, interceptors.NativeError);
107
142
const result = {};
108
143
var name = isFunction ? 'Function' : classObject.name;
109
144
110
145
result['name'] = name;
111
- result['libraryId'] = sdkUtils .getLibraryUri(classObject);
112
- result['dartName'] = sdkUtils .typeName(classObject);
146
+ result['libraryId'] = dart .getLibraryUri(classObject);
147
+ result['dartName'] = dart .typeName(classObject);
113
148
result['isFunction'] = isFunction;
114
149
result['isRecord'] = isRecord;
150
+ result['isNativeError'] = isNativeError;
115
151
result['length'] = arg['length'];
116
152
117
153
if (isRecord) {
@@ -136,9 +172,12 @@ class ClassMetaData {
136
172
dartName: metadata['dartName' ],
137
173
isFunction: metadata['isFunction' ],
138
174
isRecord: metadata['isRecord' ],
175
+ isNativeError: metadata['isNativeError' ],
139
176
length: metadata['length' ],
140
177
);
141
- } on ChromeDebugException {
178
+ } on ChromeDebugException catch (e, s) {
179
+ _logger.fine (
180
+ 'Could not create class metadata for ${remoteObject .json }' , e, s);
142
181
return null ;
143
182
}
144
183
}
@@ -162,4 +201,8 @@ class ClassMetaData {
162
201
163
202
/// True if this class refers to a record type.
164
203
bool isRecord;
204
+
205
+ /// True is this class refers to a native JS type.
206
+ /// i.e. inherits from NativeError.
207
+ bool isNativeError;
165
208
}
0 commit comments