[ddc] Fix exception on pausing in library with late globals

Closes: https://github.com/dart-lang/sdk/issues/53603
Change-Id: If2c9b62204dc00c5d0316e66ab34bf10855e9c92
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/327823
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Commit-Queue: Anna Gringauze <annagrin@google.com>
This commit is contained in:
Anna Gringauze 2023-09-28 19:59:02 +00:00 committed by Commit Queue
parent ec6def53de
commit e1efba011e
3 changed files with 349 additions and 406 deletions

View file

@ -184,12 +184,14 @@ class ExpressionEvaluationTestDriver {
var sound = ${setup.soundNullSafety};
var sdk = dart_library.import('dart_sdk');
if (!sound) {
if (sound) {
sdk.dart.nativeNonNullAsserts(true);
} else {
sdk.dart.weakNullSafetyWarnings(false);
sdk.dart.weakNullSafetyErrors(false);
sdk.dart.nonNullAsserts(true);
}
sdk.dart.nonNullAsserts(true);
sdk.dart.nativeNonNullAsserts(true);
sdk._debugger.registerDevtoolsFormatter();
dart_library.start('$appName', '$uuid', '$moduleName', '$mainLibraryName',
false);
@ -235,12 +237,14 @@ class ExpressionEvaluationTestDriver {
function(sdk, app) {
'use strict';
if (!sound) {
sdk.dart.weakNullSafetyWarnings(false);
sdk.dart.weakNullSafetyErrors(false);
if (sound) {
sdk.dart.nativeNonNullAsserts(true);
} else {
sdk.dart.weakNullSafetyWarnings(false);
sdk.dart.weakNullSafetyErrors(false);
sdk.dart.nonNullAsserts(true);
}
sdk.dart.nonNullAsserts(true);
sdk.dart.nativeNonNullAsserts(true);
sdk._debugger.registerDevtoolsFormatter();
app.$mainLibraryName.main([]);
});
@ -479,14 +483,36 @@ class ExpressionEvaluationTestDriver {
/// only primitive values, lists or maps, etc.
///
/// TODO(annagrin): Add recursive check for nested objects.
Future<void> checkRuntime({
Future<void> checkRuntimeInFrame({
required String breakpointId,
required String expression,
required dynamic expectedResult,
dynamic expectedError,
dynamic expectedResult,
}) async {
assert(expectedError == null || expectedResult == null,
'Cannot expect both an error and result.');
return await _onBreakpoint(breakpointId, onPause: (event) async {
var actual = await _evaluateJsExpression(event, expression);
expect(actual.json, expectedResult);
var evalResult = await _evaluateJsExpression(event, expression);
var error = evalResult.json['error'];
if (error != null) {
expect(
expectedError,
isNotNull,
reason: 'Unexpected expression evaluation failure:\n$error',
);
expect(error, _matches(expectedError!));
} else {
expect(
expectedResult,
isNotNull,
reason:
'Unexpected expression evaluation success:\n${evalResult.json}',
);
var actual = evalResult.value;
expect(actual, _matches(equals(expectedResult!)));
}
});
}
@ -577,24 +603,23 @@ class ExpressionEvaluationTestDriver {
var frame = event.getCallFrames().first;
var jsExpression = '''
(function () {
try {
var sdk = ${setup.loadModule}('dart_sdk');
var dart = sdk.dart;
var interceptors = sdk._interceptors;
return $expression;
} catch (error) {
return "Runtime API call failed: " + error.name +
": " + error.message + ": " + error.stack;
}
})()
(function () {
var sdk = ${setup.loadModule}('dart_sdk');
var dart = sdk.dart;
var interceptors = sdk._interceptors;
return $expression;
})()
''';
return await debugger.evaluateOnCallFrame(
frame.callFrameId,
jsExpression,
returnByValue: returnByValue,
);
try {
return await debugger.evaluateOnCallFrame(
frame.callFrameId,
jsExpression,
returnByValue: returnByValue,
);
} on wip.ExceptionDetails catch (e) {
return _createRuntimeError(e);
}
}
Future<TestCompilationResult> _compileDartExpressionInFrame(
@ -705,15 +730,20 @@ class ExpressionEvaluationTestDriver {
if (obj.subtype == 'null') {
return 'null';
}
var properties =
await connection.runtime.getProperties(obj, ownProperties: true);
var filteredProps = <String, String?>{};
for (var prop in properties) {
if (prop.value != null && prop.name != '__proto__') {
filteredProps[prop.name] = await stringifyRemoteObject(prop.value!);
try {
var properties =
await connection.runtime.getProperties(obj, ownProperties: true);
var filteredProps = <String, String?>{};
for (var prop in properties) {
if (prop.value != null && prop.name != '__proto__') {
filteredProps[prop.name] =
await stringifyRemoteObject(prop.value!);
}
}
str = '${obj.description} $filteredProps';
} catch (e, s) {
throw StateError('Failed to stringify remote object $obj: $e:$s');
}
str = '${obj.description} $filteredProps';
break;
default:
str = '${obj.value}';
@ -734,8 +764,8 @@ class ExpressionEvaluationTestDriver {
.getProperties(scope.object, ownProperties: true);
for (var prop in response) {
var propKey = prop.name;
var propValue = '${prop.value!.value}';
if (prop.value!.type == 'string') {
var propValue = '${prop.value?.value}';
if (prop.value?.type == 'string') {
propValue = "'$propValue'";
} else if (propValue == 'null') {
propValue = propKey;

View file

@ -41,6 +41,9 @@ void main(List<String> args) async {
}
const simpleClassSource = '''
int get globalField { print('globalField access!'); return 0; }
late final int globalLateFinalField;
class BaseClass {
static const int staticConstField = 0;
static int staticField = 1;
@ -130,289 +133,261 @@ void runSharedTests(
});
test('getLibraryMetadata', () async {
await driver.checkRuntime(
breakpointId: 'BP',
expression: 'dart.getLibraryMetadata("package:eval_test/test.dart")',
expectedResult: {
'type': 'object',
'value': ['BaseClass', 'DerivedClass', 'AnotherClass']
});
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getLibraryMetadata("package:eval_test/test.dart")',
expectedResult: ['BaseClass', 'DerivedClass', 'AnotherClass'],
);
});
test('getClassMetadata (object)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getClassMetadata("dart:core", "Object")',
expectedResult: {
'type': 'object',
'value': {
'className': 'Object',
'fields': {},
'methods': {
'_equals': {},
'toString': {},
'noSuchMethod': {},
'hashCode': {'isGetter': true},
'runtimeType': {'isGetter': true},
'is': {'isStatic': true},
'as': {'isStatic': true},
'hash': {'isStatic': true},
'hashAll': {'isStatic': true},
'hashAllUnordered': {'isStatic': true}
}
'className': 'Object',
'fields': {},
'methods': {
'_equals': {},
'toString': {},
'noSuchMethod': {},
'hashCode': {'isGetter': true},
'runtimeType': {'isGetter': true},
'is': {'isStatic': true},
'as': {'isStatic': true},
'hash': {'isStatic': true},
'hashAll': {'isStatic': true},
'hashAllUnordered': {'isStatic': true},
}
});
});
test('getClassMetadata (base class)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression:
'dart.getClassMetadata("package:eval_test/test.dart", "BaseClass")',
expectedResult: {
'type': 'object',
'value': {
'className': 'BaseClass',
'superClassName': 'Object',
'superClassLibraryId': 'dart:core',
'fields': {
'field': {'className': 'int', 'classLibraryId': 'dart:core'},
'functionField': {'className': '() => void'},
'nullableField': {
'className': 'BaseClass?',
'classLibraryId': 'package:eval_test/test.dart'
},
'nonNullableField': {
'className': 'AnotherClass',
'classLibraryId': 'package:eval_test/test.dart'
},
'_field': {'className': 'int', 'classLibraryId': 'dart:core'},
'_unusedField': {
'className': 'int',
'classLibraryId': 'dart:core'
},
'lateFinalField': {
'className': 'int?',
'classLibraryId': 'dart:core'
},
'staticConstField': {'isStatic': true},
'staticField': {'isStatic': true},
'_staticField': {'isStatic': true},
'_unusedStaticField': {'isStatic': true}
'className': 'BaseClass',
'superClassName': 'Object',
'superClassLibraryId': 'dart:core',
'fields': {
'field': {'className': 'int', 'classLibraryId': 'dart:core'},
'functionField': {'className': '() => void'},
'nullableField': {
'className': 'BaseClass?',
'classLibraryId': 'package:eval_test/test.dart',
},
'methods': {
'method': {},
'_privateMethod': {},
'lateFinalField': {'isGetter': true},
'getter': {'isGetter': true},
'_privateGetter': {'isGetter': true},
'factory': {'isStatic': true},
'staticMethod': {'isStatic': true}
}
}
'nonNullableField': {
'className': 'AnotherClass',
'classLibraryId': 'package:eval_test/test.dart',
},
'_field': {'className': 'int', 'classLibraryId': 'dart:core'},
'_unusedField': {
'className': 'int',
'classLibraryId': 'dart:core',
},
'lateFinalField': {
'className': 'int?',
'classLibraryId': 'dart:core',
},
'staticConstField': {'isStatic': true},
'staticField': {'isStatic': true},
'_staticField': {'isStatic': true},
'_unusedStaticField': {'isStatic': true},
},
'methods': {
'method': {},
'_privateMethod': {},
'lateFinalField': {'isGetter': true},
'getter': {'isGetter': true},
'_privateGetter': {'isGetter': true},
'factory': {'isStatic': true},
'staticMethod': {'isStatic': true},
},
});
});
test('getClassMetadata (derived class)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression:
'dart.getClassMetadata("package:eval_test/test.dart", "DerivedClass")',
expectedResult: {
'type': 'object',
'value': {
'className': 'DerivedClass',
'superClassName': 'BaseClass',
'superClassLibraryId': 'package:eval_test/test.dart',
'fields': {
'newPublicField': {
'isFinal': true,
'className': 'int',
'classLibraryId': 'dart:core'
},
'_newPrivateField': {
'isFinal': true,
'className': 'int',
'classLibraryId': 'dart:core'
},
'_newStaticConstPrivateField': {'isStatic': true}
'className': 'DerivedClass',
'superClassName': 'BaseClass',
'superClassLibraryId': 'package:eval_test/test.dart',
'fields': {
'newPublicField': {
'isFinal': true,
'className': 'int',
'classLibraryId': 'dart:core',
},
'methods': {
'additionalMethod': {},
'lateFinalField': {'isGetter': true},
'getter': {'isGetter': true},
'_privateGetter': {'isGetter': true},
'factory': {'isStatic': true},
'staticMethod': {'isStatic': true}
}
}
'_newPrivateField': {
'isFinal': true,
'className': 'int',
'classLibraryId': 'dart:core',
},
'_newStaticConstPrivateField': {'isStatic': true},
},
'methods': {
'additionalMethod': {},
'lateFinalField': {'isGetter': true},
'getter': {'isGetter': true},
'_privateGetter': {'isGetter': true},
'factory': {'isStatic': true},
'staticMethod': {'isStatic': true},
},
});
});
test('getClassMetadata (Record)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getClassMetadata("dart:core", "Record")',
expectedResult: {
'type': 'object',
'value': {
'className': 'Record',
'superClassName': 'Object',
'superClassLibraryId': 'dart:core',
'fields': {},
'methods': {
'_equals': {},
'toString': {},
'noSuchMethod': {},
'hashCode': {'isGetter': true},
'runtimeType': {'isGetter': true},
'is': {'isStatic': true},
'as': {'isStatic': true},
'hash': {'isStatic': true},
'hashAll': {'isStatic': true},
'hashAllUnordered': {'isStatic': true}
}
'className': 'Record',
'superClassName': 'Object',
'superClassLibraryId': 'dart:core',
'fields': {},
'methods': {
'_equals': {},
'toString': {},
'noSuchMethod': {},
'hashCode': {'isGetter': true},
'runtimeType': {'isGetter': true},
'is': {'isStatic': true},
'as': {'isStatic': true},
'hash': {'isStatic': true},
'hashAll': {'isStatic': true},
'hashAllUnordered': {'isStatic': true},
}
});
});
test('getObjectMetadata (int)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(x)',
expectedResult: {'type': 'object', 'value': {}});
expectedResult: {});
});
test('getObjectMetadata (object)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(object)',
expectedResult: {
'type': 'object',
'value': {
'className': 'Object',
'libraryId': 'dart:core',
'runtimeKind': 'object',
}
'className': 'Object',
'libraryId': 'dart:core',
'runtimeKind': 'object',
});
});
test('getObjectMetadata (object of derived class)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(base)',
expectedResult: {
'type': 'object',
'value': {
'className': 'BaseClass',
'libraryId': 'package:eval_test/test.dart',
'runtimeKind': 'object',
}
'className': 'BaseClass',
'libraryId': 'package:eval_test/test.dart',
'runtimeKind': 'object',
});
});
test('getObjectMetadata (Set)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(set)',
expectedResult: {
'type': 'object',
'value': {
'className': '_HashSet<String>',
'libraryId': 'dart:collection',
'runtimeKind': 'set',
'length': 3
}
'className': '_HashSet<String>',
'libraryId': 'dart:collection',
'runtimeKind': 'set',
'length': 3,
});
});
test('getObjectMetadata (List)', () async {
await driver.checkRuntime(
test('getObjectMetadata (List) (new types)', () async {
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(list)',
expectedResult: {
'type': 'object',
'value': {
'className': 'JSArray<int>',
'libraryId': 'dart:_interceptors',
'runtimeKind': 'list',
'length': 3
}
'className': 'JSArray<int>',
'libraryId': 'dart:_interceptors',
'runtimeKind': 'list',
'length': 3,
});
// Old type system incorrectly returns 'dart:_interceptors|_List<int>'
// Old type system incorrectly returns 'dart:_interceptors|List<int>'
}, skip: !setup.canaryFeatures);
test('getObjectMetadata (List) (old types)', () async {
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(list)',
expectedResult: {
'className': 'List<int>',
'libraryId': 'dart:_interceptors',
'runtimeKind': 'list',
'length': 3,
});
// Old type system incorrectly returns 'dart:_interceptors|List<int>'
}, skip: setup.canaryFeatures);
test('getObjectMetadata (Map)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(map)',
expectedResult: {
'type': 'object',
'value': {
'className': 'IdentityMap<String, int>',
'libraryId': 'dart:_js_helper',
'runtimeKind': 'map',
'length': 2
}
'className': 'IdentityMap<String, int>',
'libraryId': 'dart:_js_helper',
'runtimeKind': 'map',
'length': 2,
});
});
test('getObjectMetadata (Record)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(record)',
expectedResult: {
'type': 'object',
'value': {
'className': 'Record',
'libraryId': 'dart:core',
'runtimeKind': 'record',
'length': 3
}
'className': 'Record',
'libraryId': 'dart:core',
'runtimeKind': 'record',
'length': 3,
});
});
test('getObjectMetadata (LegacyJavaScriptObject)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression:
'dart.getObjectMetadata(new interceptors.LegacyJavaScriptObject.new())',
expectedResult: {
'type': 'object',
'value': {
'className': 'LegacyJavaScriptObject',
'libraryId': 'dart:_interceptors',
'runtimeKind': 'nativeObject',
}
'className': 'LegacyJavaScriptObject',
'libraryId': 'dart:_interceptors',
'runtimeKind': 'nativeObject',
});
});
test('getObjectMetadata (NativeError)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression:
'dart.getObjectMetadata(new interceptors.NativeError.new())',
expectedResult: {
'type': 'object',
'value': {
'className': 'NativeError',
'libraryId': 'dart:_interceptors',
'runtimeKind': 'nativeError',
}
'className': 'NativeError',
'libraryId': 'dart:_interceptors',
'runtimeKind': 'nativeError',
});
});
test('getObjectMetadata (DartError)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(new dart.DartError())',
expectedResult: {
'type': 'object',
'value': {
'className': 'NativeError',
'libraryId': 'dart:_interceptors',
'runtimeKind': 'nativeError',
}
'className': 'NativeError',
'libraryId': 'dart:_interceptors',
'runtimeKind': 'nativeError',
});
});
@ -437,17 +412,14 @@ void runSharedTests(
breakpointId: 'BP',
expression: 'xType.toString()',
);
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(xType)',
expectedResult: {
'type': 'object',
'value': {
'className': 'Type',
'libraryId': 'dart:core',
'runtimeKind': 'type',
'typeName': typeName,
}
'className': 'Type',
'libraryId': 'dart:core',
'runtimeKind': 'type',
'typeName': typeName,
});
});
@ -456,17 +428,14 @@ void runSharedTests(
breakpointId: 'BP',
expression: 'baseType.toString()',
);
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(baseType)',
expectedResult: {
'type': 'object',
'value': {
'className': 'Type',
'libraryId': 'dart:core',
'runtimeKind': 'type',
'typeName': typeName,
}
'className': 'Type',
'libraryId': 'dart:core',
'runtimeKind': 'type',
'typeName': typeName,
});
});
@ -475,17 +444,14 @@ void runSharedTests(
breakpointId: 'BP',
expression: 'baseTypeType.toString()',
);
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(baseTypeType)',
expectedResult: {
'type': 'object',
'value': {
'className': 'Type',
'libraryId': 'dart:core',
'runtimeKind': 'type',
'typeName': typeName,
}
'className': 'Type',
'libraryId': 'dart:core',
'runtimeKind': 'type',
'typeName': typeName,
});
});
@ -494,17 +460,14 @@ void runSharedTests(
breakpointId: 'BP',
expression: 'setType.toString()',
);
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(setType)',
expectedResult: {
'type': 'object',
'value': {
'className': 'Type',
'libraryId': 'dart:core',
'runtimeKind': 'type',
'typeName': typeName,
}
'className': 'Type',
'libraryId': 'dart:core',
'runtimeKind': 'type',
'typeName': typeName,
});
});
@ -513,17 +476,14 @@ void runSharedTests(
breakpointId: 'BP',
expression: 'listType.toString()',
);
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(listType)',
expectedResult: {
'type': 'object',
'value': {
'className': 'Type',
'libraryId': 'dart:core',
'runtimeKind': 'type',
'typeName': typeName,
}
'className': 'Type',
'libraryId': 'dart:core',
'runtimeKind': 'type',
'typeName': typeName,
});
});
@ -532,161 +492,131 @@ void runSharedTests(
breakpointId: 'BP',
expression: 'mapType.toString()',
);
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(mapType)',
expectedResult: {
'type': 'object',
'value': {
'className': 'Type',
'libraryId': 'dart:core',
'runtimeKind': 'type',
'typeName': typeName,
}
'className': 'Type',
'libraryId': 'dart:core',
'runtimeKind': 'type',
'typeName': typeName,
});
});
test('getObjectMetadata (Record type)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectMetadata(recordType)',
expectedResult: {
'type': 'object',
'value': {
'className': 'RecordType',
'libraryId': 'dart:_runtime',
'runtimeKind': 'recordType',
'length': 3
}
'className': 'RecordType',
'libraryId': 'dart:_runtime',
'runtimeKind': 'recordType',
'length': 3,
});
});
test('getObjectFieldNames (object)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectFieldNames(object)',
expectedResult: {'type': 'object', 'value': []});
expectedResult: []);
});
test('getObjectFieldNames (derived class)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectFieldNames(derived)',
expectedResult: {
'type': 'object',
'value': [
'_field',
'_newPrivateField',
'_unusedField',
'field',
'functionField',
'lateFinalField',
'newPublicField',
'nonNullableField',
'nullableField',
]
});
expectedResult: [
'_field',
'_newPrivateField',
'_unusedField',
'field',
'functionField',
'lateFinalField',
'newPublicField',
'nonNullableField',
'nullableField',
]);
});
test('getObjectFieldNames (base class)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getObjectFieldNames(base)',
expectedResult: {
'type': 'object',
'value': [
'_field',
'_unusedField',
'field',
'functionField',
'lateFinalField',
'nonNullableField',
'nullableField',
]
});
expectedResult: [
'_field',
'_unusedField',
'field',
'functionField',
'lateFinalField',
'nonNullableField',
'nullableField',
]);
});
test('getSetElements', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getSetElements(set)',
expectedResult: {
'type': 'object',
'value': {
'entries': ['a', 'b', 'c']
}
'entries': ['a', 'b', 'c'],
});
});
test('getMapElements', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getMapElements(map)',
expectedResult: {
'type': 'object',
'value': {
'keys': ['a', 'b'],
'values': [1, 2]
}
'keys': ['a', 'b'],
'values': [1, 2],
});
});
// TODO(annagrin): Add recursive check for nested objects.
test('getTypeFields', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getTypeFields(baseType)',
expectedResult: {
'type': 'object',
'value': {'hashCode': isA<int>(), 'runtimeType': {}}
});
expectedResult: {'hashCode': isA<int>(), 'runtimeType': {}});
});
// TODO(annagrin): Add recursive check for nested objects.
test('getTypeFields (nested)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getTypeFields(baseTypeType)',
expectedResult: {
'type': 'object',
'value': {'hashCode': isA<int>(), 'runtimeType': {}}
});
expectedResult: {'hashCode': isA<int>(), 'runtimeType': {}});
});
test('getRecordFields', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getRecordFields(record)',
expectedResult: {
'type': 'object',
'value': {
'positionalCount': 2,
'named': ['name'],
'values': [0, 2, 'cat']
}
'positionalCount': 2,
'named': ['name'],
'values': [0, 2, 'cat'],
});
});
// TODO(annagrin): Add recursive check for nested objects.
test('getRecordTypeFields', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getRecordTypeFields(recordType)',
expectedResult: {
'type': 'object',
'value': {
'positionalCount': 2,
'named': ['name'],
'types': [{}, {}, {}]
}
'positionalCount': 2,
'named': ['name'],
'types': [{}, {}, {}],
});
});
test('getFunctionMetadata (method)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getFunctionMetadata(base.method)',
expectedResult: {'type': 'string', 'value': 'method'});
expectedResult: 'method');
});
test('getFunctionMetadata (static method)', () async {
@ -695,11 +625,11 @@ void runSharedTests(
const className = 'BaseClass';
const function = 'staticMethod';
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression:
'dart.getFunctionMetadata(dart.getModuleLibraries("$module")["$library"]["$className"]["$function"])',
expectedResult: {'type': 'string', 'value': 'staticMethod'});
expectedResult: 'staticMethod');
});
test('getFunctionName (global method)', () async {
@ -707,89 +637,68 @@ void runSharedTests(
const library = 'package:eval_test/test.dart';
const function = 'globalFunction';
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression:
'dart.getFunctionMetadata(dart.getModuleLibraries("$module")["$library"]["$function"])',
expectedResult: {'type': 'string', 'value': 'globalFunction'});
expectedResult: 'globalFunction');
});
test('getSubRange (set)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getSubRange(set, 0, 3)',
expectedResult: {
'type': 'object',
'value': ['a', 'b', 'c']
});
expectedResult: ['a', 'b', 'c']);
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getSubRange(set, 1, 2)',
expectedResult: {
'type': 'object',
'value': ['b', 'c']
});
expectedResult: ['b', 'c']);
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getSubRange(set, 1, 5)',
expectedResult: {
'type': 'object',
'value': ['b', 'c']
});
expectedResult: ['b', 'c']);
});
test('getSubRange (list)', () async {
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getSubRange(list, 0, 3)',
expectedResult: {
'type': 'object',
'value': [1, 2, 3]
});
expectedResult: [1, 2, 3]);
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getSubRange(list, 1, 2)',
expectedResult: {
'type': 'object',
'value': [2, 3]
});
expectedResult: [2, 3]);
await driver.checkRuntime(
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getSubRange(list, 1, 5)',
expectedResult: {
'type': 'object',
'value': [2, 3]
});
expectedResult: [2, 3]);
});
test('getSubRange (map)', () async {
await driver.checkRuntime(
breakpointId: 'BP',
expression: 'dart.getSubRange(map, 0, 3)',
expectedResult: {
'type': 'object',
'value': isA<List>().having((p) => p.length, 'length', equals(2)),
});
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getSubRange(map, 0, 3)',
expectedResult:
isA<List>().having((p) => p.length, 'length', equals(2)),
);
await driver.checkRuntime(
breakpointId: 'BP',
expression: 'dart.getSubRange(map, 1, 2)',
expectedResult: {
'type': 'object',
'value': isA<List>().having((p) => p.length, 'length', equals(1)),
});
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getSubRange(map, 1, 2)',
expectedResult:
isA<List>().having((p) => p.length, 'length', equals(1)),
);
await driver.checkRuntime(
breakpointId: 'BP',
expression: 'dart.getSubRange(map, 1, 5)',
expectedResult: {
'type': 'object',
'value': isA<List>().having((p) => p.length, 'length', equals(1)),
});
await driver.checkRuntimeInFrame(
breakpointId: 'BP',
expression: 'dart.getSubRange(map, 1, 5)',
expectedResult:
isA<List>().having((p) => p.length, 'length', equals(1)),
);
});
});
}

View file

@ -37,12 +37,10 @@ class RuntimeObjectKind {
/// descriptors for all classes in a library:
///
/// ```
/// {
/// classes: [
/// { 'className': <dart class name> },
/// [
/// <dart class name>,
/// ...
/// ]
/// }
/// ]
/// ```
///
/// TODO(annagrin): remove when debugger consumes debug symbols.
@ -52,11 +50,17 @@ List<String> getLibraryMetadata(@notNull String libraryUri) {
var library = getLibrary('$libraryUri');
if (library == null) throw 'cannot find library for $libraryUri';
var classes = <String>[];
final classes = <String>[];
for (var name in getOwnPropertyNames(library)) {
var cls = _get<Object?>(library, name);
if (cls != null && _isDartClassObject(cls)) {
classes.add(_dartClassName(cls));
final field = name as String;
var descriptor = getOwnPropertyDescriptor(library, field);
// Filter out all getters prevent causing side-effects by calling them.
if (_get<Object?>(descriptor, 'value') != null &&
_get<Object?>(descriptor, 'get') == null) {
final cls = _get<Object?>(library, field);
if (cls != null && _isDartClassObject(cls)) {
classes.add(_dartClassName(cls));
}
}
}
return classes;
@ -64,7 +68,7 @@ List<String> getLibraryMetadata(@notNull String libraryUri) {
/// Collect class metadata.
///
/// Returns a JavaScript descriptor for the [className] class in [libraryUri].
/// Returns a JavaScript descriptor for the class [name] class in [libraryUri].
///
/// /// ```
/// {