From 2b51417f85fd020333c9da300e86928bdf5833d7 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Tue, 16 Jan 2024 09:08:06 -0800 Subject: [PATCH 1/9] Fix test faliures --- .../src/services/chrome_proxy_service.dart | 41 ++++++++++++++++- dwds/test/evaluate_common.dart | 46 +++++++++++++------ 2 files changed, 70 insertions(+), 17 deletions(-) diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart index 9a6051cce..33b12ea11 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -618,7 +618,35 @@ ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").developer. await isCompilerInitialized; _checkIsolate('evaluate', isolateId); - final library = await inspector.getLibrary(targetId); + late Obj object; + try { + object = await inspector.getObject(targetId); + } catch (_) { + return ErrorRef( + kind: 'error', + message: 'Evaluate is called on an unsupported target:' + '$targetId', + id: createId(), + ); + } + + final library = + object is Library ? object : inspector.isolate.rootLib; + + if (object is Instance) { + // Evaluate is called on a target - convert this to a dart + // expression and scope by adding a target variable to the + // expression and the scope, for example: + // + // Library: 'package:hello_world/main.dart' + // Expression: 'hashCode' => 'x.hashCode' + // Scope: {} => { 'x' : targetId } + + final target = _newVariableForScope(scope); + expression = '$target.$expression'; + scope = (scope ?? {})..addAll({target: targetId}); + } + return await _getEvaluationResult( isolateId, () => evaluator.evaluateExpression( @@ -631,7 +659,7 @@ ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").developer. ); } throw RPCError( - 'evaluateInFrame', + 'evaluate', RPCErrorKind.kInvalidRequest.code, 'Expression evaluation is not supported for this configuration.', ); @@ -640,6 +668,15 @@ ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").developer. ); } + String _newVariableForScope(Map? scope) { + // Find a new variable not in scope. + var candidate = 'x'; + while (scope?.containsKey(candidate) ?? false) { + candidate += '\$1'; + } + return candidate; + } + @override Future evaluateInFrame( String isolateId, diff --git a/dwds/test/evaluate_common.dart b/dwds/test/evaluate_common.dart index 7c3c9c984..7e3c6db50 100644 --- a/dwds/test/evaluate_common.dart +++ b/dwds/test/evaluate_common.dart @@ -668,24 +668,24 @@ void testAll({ tearDown(() async {}); evaluate( - libraryId, + targetId, expr, { scope, }) async => await context.service.evaluate( isolateId, - libraryId, + targetId, expr, scope: scope, ); getInstanceRef( - libraryId, + targetId, expr, { scope, }) async { final result = await evaluate( - libraryId, + targetId, expr, scope: scope, ); @@ -699,6 +699,24 @@ void testAll({ return isolate.rootLib!.id!; } + test('RecordType getters', () async { + final libraryId = getRootLibraryId(); + + final type = await getInstanceRef(libraryId, '(0,1).runtimeType'); + final result = await getInstanceRef(type.id, 'hashCode'); + + expect(result, matchInstanceRefKind('Double')); + }, skip: 'https://github.com/dart-lang/sdk/issues/54609'); + + test('Object getters', () async { + final libraryId = getRootLibraryId(); + + final type = await getInstanceRef(libraryId, 'Object()'); + final result = await getInstanceRef(type.id, 'hashCode'); + + expect(result, matchInstanceRefKind('Double')); + }); + test('with scope', () async { final libraryId = getRootLibraryId(); @@ -762,15 +780,13 @@ void testAll({ final evaluation2 = evaluate(libraryId, 'MainClass(1,1).toString()'); final results = await Future.wait([evaluation1, evaluation2]); - expect( results[0], - matchErrorRef(contains('No batch result object ID')), - ); - expect( - results[1], - matchErrorRef(contains('No batch result object ID')), + matchErrorRef( + contains('Evaluate is called on an unsupported target'), + ), ); + expect(results[1], matchInstanceRef('1, 1')); }); test('with scope override', () async { @@ -902,11 +918,11 @@ Future _setBreakpointInInjectedClient(WipDebugger debugger) async { return result.json['result']['breakpointId']; } -Matcher matchInstanceRef(dynamic value) => isA().having( - (instance) => instance.valueAsString, - 'valueAsString', - value, - ); +Matcher matchInstanceRefKind(String kind) => + isA().having((instance) => instance.kind, 'kind', kind); + +Matcher matchInstanceRef(dynamic value) => isA() + .having((instance) => instance.valueAsString, 'valueAsString', value); Matcher matchInstance(dynamic className) => isA().having( (instance) => instance.classRef!.name, From 2dcdc6d806e76d30031b25e1b4f0f2b5a0c8e5f6 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Tue, 16 Jan 2024 09:11:39 -0800 Subject: [PATCH 2/9] Update changelog --- dwds/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index f0922afee..d9f670f7d 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -2,6 +2,7 @@ - Send untruncated `dart:developer` logs to debugging clients. - [#2333](https://github.com/dart-lang/webdev/pull/2333) - Enabling tests that run with the DDC module system and exposing `utilities/ddc_names.dart` - [#2295](https://github.com/dart-lang/webdev/pull/2295) +- Fix errors on displaying getters. - [#2343](https://github.com/dart-lang/webdev/pull/2343) ## 23.1.1 From a0c1d34c22157f66b5de23a097aeba24c4b9dad1 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Tue, 16 Jan 2024 10:48:59 -0800 Subject: [PATCH 3/9] Fixe analyzer errors --- dwds/test/evaluate_common.dart | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/dwds/test/evaluate_common.dart b/dwds/test/evaluate_common.dart index 7e3c6db50..c27a14711 100644 --- a/dwds/test/evaluate_common.dart +++ b/dwds/test/evaluate_common.dart @@ -699,14 +699,18 @@ void testAll({ return isolate.rootLib!.id!; } - test('RecordType getters', () async { - final libraryId = getRootLibraryId(); + test( + 'RecordType getters', + () async { + final libraryId = getRootLibraryId(); - final type = await getInstanceRef(libraryId, '(0,1).runtimeType'); - final result = await getInstanceRef(type.id, 'hashCode'); + final type = await getInstanceRef(libraryId, '(0,1).runtimeType'); + final result = await getInstanceRef(type.id, 'hashCode'); - expect(result, matchInstanceRefKind('Double')); - }, skip: 'https://github.com/dart-lang/sdk/issues/54609'); + expect(result, matchInstanceRefKind('Double')); + }, + skip: 'https://github.com/dart-lang/sdk/issues/54609', + ); test('Object getters', () async { final libraryId = getRootLibraryId(); From 7f1de93dea9774df3ef9573e8fb62083f48a9f0c Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Thu, 18 Jan 2024 10:03:36 -0800 Subject: [PATCH 4/9] Display type instanses as common instances --- dwds/lib/src/debugging/instance.dart | 78 +++++++++++++--------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/dwds/lib/src/debugging/instance.dart b/dwds/lib/src/debugging/instance.dart index 9db9c78c9..27fa81a1b 100644 --- a/dwds/lib/src/debugging/instance.dart +++ b/dwds/lib/src/debugging/instance.dart @@ -238,29 +238,49 @@ class InstanceHelper extends Domain { final objectId = remoteObject.objectId; if (objectId == null) return null; + final fields = await _getInstanceFields( + metaData, + remoteObject, + offset: offset, + count: count, + ); + + final result = Instance( + kind: InstanceKind.kPlainInstance, + id: objectId, + identityHashCode: remoteObject.objectId.hashCode, + classRef: metaData.classRef, + fields: fields, + ); + return result; + } + + Future> _getInstanceFields( + ClassMetaData metaData, + RemoteObject remoteObject, { + int? offset, + int? count, + }) async { + final objectId = remoteObject.objectId; + if (objectId == null) throw StateError('Object id is null for instance'); + final properties = await inspector.getProperties( objectId, offset: offset, count: count, length: metaData.length, ); + final dartProperties = await _dartFieldsFor(properties, remoteObject); - var boundFields = await Future.wait( + final boundFields = await Future.wait( dartProperties .map>((p) => _fieldFor(p, metaData.classRef)), ); - boundFields = boundFields + + return boundFields .where((bv) => inspector.isDisplayableObject(bv.value)) .toList() ..sort(_compareBoundFields); - final result = Instance( - kind: InstanceKind.kPlainInstance, - id: objectId, - identityHashCode: remoteObject.objectId.hashCode, - classRef: metaData.classRef, - fields: boundFields, - ); - return result; } int _compareBoundFields(BoundField a, BoundField b) { @@ -700,7 +720,13 @@ class InstanceHelper extends Domain { final objectId = remoteObject.objectId; if (objectId == null) return null; - final fields = await _typeFields(metaData.classRef, remoteObject); + final fields = await _getInstanceFields( + metaData, + remoteObject, + offset: offset, + count: count, + ); + return Instance( identityHashCode: objectId.hashCode, kind: InstanceKind.kType, @@ -714,36 +740,6 @@ class InstanceHelper extends Domain { ); } - /// The field types for a Dart RecordType. - /// - /// Returns a range of [count] field types, if available, starting from - /// the [offset]. - /// - /// If [offset] is `null`, assumes 0 offset. - /// If [count] is `null`, return all field types starting from the offset. - Future> _typeFields( - ClassRef classRef, - RemoteObject type, - ) async { - // Present the type as an instance of `core.Type` class and - // hide the internal implementation. - final expression = _jsRuntimeFunctionCall('getTypeFields(this)'); - - final result = await inspector.jsCallFunctionOn(type, expression, []); - final hashCodeObject = await inspector.loadField(result, 'hashCode'); - final runtimeTypeObject = await inspector.loadField(result, 'runtimeType'); - - final properties = [ - Property({'name': 'hashCode', 'value': hashCodeObject}), - Property({'name': 'runtimeType', 'value': runtimeTypeObject}), - ]; - - final boundFields = await Future.wait( - properties.map>((p) => _fieldFor(p, classRef)), - ); - return boundFields; - } - /// Return the available count of elements in the requested range. /// Return `null` if the range includes the whole object. /// [count] is the range length requested by the `getObject` call. From 8f59e8f8b95b7c509a4194bdfb4fc16425548fe0 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Thu, 18 Jan 2024 14:12:16 -0800 Subject: [PATCH 5/9] Added getters checks to instance tests --- dwds/test/evaluate_common.dart | 11 +- .../common/instance_inspection_common.dart | 63 +++++++--- .../common/patterns_inspection_common.dart | 2 +- .../common/record_type_inspection_common.dart | 12 +- .../test/instances/common/test_inspector.dart | 58 ++++++--- .../common/type_inspection_common.dart | 110 ++++++++++++++---- 6 files changed, 196 insertions(+), 60 deletions(-) diff --git a/dwds/test/evaluate_common.dart b/dwds/test/evaluate_common.dart index c27a14711..2b48fe5fc 100644 --- a/dwds/test/evaluate_common.dart +++ b/dwds/test/evaluate_common.dart @@ -321,7 +321,7 @@ void testAll({ await getInstanceRef(event.topFrame!.index!, 'stream'); final instance = await getInstance(instanceRef); - expect(instance, matchInstance('_AsBroadcastStream')); + expect(instance, matchInstanceClassName('_AsBroadcastStream')); }); }); @@ -928,7 +928,14 @@ Matcher matchInstanceRefKind(String kind) => Matcher matchInstanceRef(dynamic value) => isA() .having((instance) => instance.valueAsString, 'valueAsString', value); -Matcher matchInstance(dynamic className) => isA().having( +Matcher matchInstanceClassName(dynamic className) => isA().having( + (instance) => instance.classRef!.name, + 'class name', + className, + ); + +Matcher matchInstanceRefClassName(dynamic className) => + isA().having( (instance) => instance.classRef!.name, 'class name', className, diff --git a/dwds/test/instances/common/instance_inspection_common.dart b/dwds/test/instances/common/instance_inspection_common.dart index 5a0a499ed..312c6a5b6 100644 --- a/dwds/test/instances/common/instance_inspection_common.dart +++ b/dwds/test/instances/common/instance_inspection_common.dart @@ -189,14 +189,32 @@ void runTests({ final instanceId = instanceRef.id!; expect(await getObject(instanceId), matchListInstance(type: 'int')); - expect(await getFields(instanceRef), [0, 1, 2]); - expect(await getFields(instanceRef, offset: 1, count: 0), []); - expect(await getFields(instanceRef, offset: 0), [0, 1, 2]); - expect(await getFields(instanceRef, offset: 0, count: 1), [0]); - expect(await getFields(instanceRef, offset: 1), [1, 2]); - expect(await getFields(instanceRef, offset: 1, count: 1), [1]); - expect(await getFields(instanceRef, offset: 1, count: 3), [1, 2]); - expect(await getFields(instanceRef, offset: 3, count: 3), []); + expect( + await getFields(instanceRef), + {0: 0.0, 1: 1.0, 2: 2.0}, + ); + expect(await getFields(instanceRef, offset: 1, count: 0), {}); + expect( + await getFields(instanceRef, offset: 0), + {0: 0.0, 1: 1.0, 2: 2.0}, + ); + expect( + await getFields(instanceRef, offset: 0, count: 1), + {0: 0.0}, + ); + expect( + await getFields(instanceRef, offset: 1), + {0: 1.0, 1: 2.0}, + ); + expect( + await getFields(instanceRef, offset: 1, count: 1), + {0: 1.0}, + ); + expect( + await getFields(instanceRef, offset: 1, count: 3), + {0: 1.0, 1: 2.0}, + ); + expect(await getFields(instanceRef, offset: 3, count: 3), {}); }); }); @@ -284,13 +302,28 @@ void runTests({ matchSetInstance(type: '_HashSet'), ); - expect(await getFields(instanceRef), [1, 4, 5, 7]); - expect(await getFields(instanceRef, offset: 0), [1, 4, 5, 7]); - expect(await getFields(instanceRef, offset: 1, count: 2), [4, 5]); - expect(await getFields(instanceRef, offset: 2), [5, 7]); - expect(await getFields(instanceRef, offset: 2, count: 10), [5, 7]); - expect(await getFields(instanceRef, offset: 1, count: 0), []); - expect(await getFields(instanceRef, offset: 10, count: 2), []); + expect( + await getFields(instanceRef), + {0: 1.0, 1: 4.0, 2: 5.0, 3: 7.0}, + ); + expect( + await getFields(instanceRef, offset: 0), + {0: 1.0, 1: 4.0, 2: 5.0, 3: 7.0}, + ); + expect( + await getFields(instanceRef, offset: 1, count: 2), + {0: 4.0, 1: 5.0}, + ); + expect( + await getFields(instanceRef, offset: 2), + {0: 5.0, 1: 7.0}, + ); + expect( + await getFields(instanceRef, offset: 2, count: 10), + {0: 5.0, 1: 7.0}, + ); + expect(await getFields(instanceRef, offset: 1, count: 0), {}); + expect(await getFields(instanceRef, offset: 10, count: 2), {}); }); }); diff --git a/dwds/test/instances/common/patterns_inspection_common.dart b/dwds/test/instances/common/patterns_inspection_common.dart index b4e14c41d..9a303a632 100644 --- a/dwds/test/instances/common/patterns_inspection_common.dart +++ b/dwds/test/instances/common/patterns_inspection_common.dart @@ -105,7 +105,7 @@ void runTests({ final frame = event.topFrame!; final frameIndex = frame.index!; final instanceRef = await getInstanceRef(frameIndex, 'obj'); - expect(await getFields(instanceRef), [0, 1]); + expect(await getFields(instanceRef), {0: 0.0, 1: 1.0}); expect(await getFrameVariables(frame), { 'obj': matchListInstance(type: 'int'), diff --git a/dwds/test/instances/common/record_type_inspection_common.dart b/dwds/test/instances/common/record_type_inspection_common.dart index 9e5eb9189..aeb0e0a09 100644 --- a/dwds/test/instances/common/record_type_inspection_common.dart +++ b/dwds/test/instances/common/record_type_inspection_common.dart @@ -88,7 +88,7 @@ void runTests({ expect(await getObject(instanceId), matchRecordTypeInstance(length: 2)); final classId = instanceRef.classRef!.id; - expect(await getObject(classId), matchRecordTypeClass); + expect(await getObject(classId), matchTypeClass); }); }); @@ -136,7 +136,7 @@ void runTests({ expect(await getObject(instanceId), matchRecordTypeInstance(length: 3)); final classId = instanceRef.classRef!.id; - expect(await getObject(classId), matchRecordTypeClass); + expect(await getObject(classId), matchTypeClass); }); }); @@ -188,7 +188,7 @@ void runTests({ expect(await getObject(instanceId), matchRecordTypeInstance(length: 3)); final classId = instanceRef.classRef!.id; - expect(await getObject(classId), matchRecordTypeClass); + expect(await getObject(classId), matchTypeClass); }); }); @@ -241,7 +241,7 @@ void runTests({ expect(await getObject(instanceId), matchRecordTypeInstance(length: 2)); final classId = instanceRef.classRef!.id; - expect(await getObject(classId), matchRecordTypeClass); + expect(await getObject(classId), matchTypeClass); }); }); @@ -299,7 +299,7 @@ void runTests({ expect(instance, matchRecordTypeInstance(length: 2)); final classId = instanceRef.classRef!.id; - expect(await getObject(classId), matchRecordTypeClass); + expect(await getObject(classId), matchTypeClass); }); }); @@ -336,7 +336,7 @@ void runTests({ final instance = await getObject(instanceRef.id!); final typeClassId = instance.classRef!.id; - expect(await getObject(typeClassId), matchRecordTypeClass); + expect(await getObject(typeClassId), matchTypeClass); final typeStringRef = await getInstanceRef(frame, 'record.runtimeType.toString()'); diff --git a/dwds/test/instances/common/test_inspector.dart b/dwds/test/instances/common/test_inspector.dart index 17714617b..5905ad809 100644 --- a/dwds/test/instances/common/test_inspector.dart +++ b/dwds/test/instances/common/test_inspector.dart @@ -42,7 +42,7 @@ class TestInspector { } } - Future getFields( + Future> getFields( String isolateId, InstanceRef instanceRef, { int? offset, @@ -87,7 +87,7 @@ class TestInspector { depth--; } if (depth == 0) { - return elements == null ? fieldRefs : fieldRefs.values.toList(); + return fieldRefs; } final fieldValues = {}; @@ -99,7 +99,25 @@ class TestInspector { depth: depth, ); } - return elements == null ? fieldValues : fieldValues.values.toList(); + return fieldValues; + } + + Future> getGetters( + String isolateId, + InstanceRef instanceRef, + ) async { + final cls = + await service.getObject(isolateId, instanceRef.classRef!.id!) as Class; + final getters = + cls.functions?.where((f) => f.isGetter ?? false).toList() ?? []; + + final results = await Future.wait([ + for (var getter in getters) + service.evaluate(isolateId, instanceRef.id!, getter.name!), + ]); + + return Map.fromIterables( + getters.map((e) => e.name!), results.map((e) => e as InstanceRef)); } Future getInstanceRef( @@ -160,7 +178,7 @@ class TestInspector { await service.invoke(isolateId, instanceId, 'toString', []) as InstanceRef; - Future> getDisplayedFields( + Future> getDisplayedFields( String isolateId, InstanceRef ref, ) async { @@ -172,7 +190,22 @@ class TestInspector { (await getDisplayedRef(isolateId, ref.id!)).valueAsString; final fields = await Future.wait(fieldRefs.values.map(toStringValue)); - return fields.toList(); + return Map.fromIterables(fieldRefs.keys, fields); + } + + Future> getDisplayedGetters( + String isolateId, + InstanceRef ref, + ) async { + final fieldRefs = + await getGetters(isolateId, ref) as Map; + + Future toStringValue(InstanceRef ref) async => + ref.valueAsString ?? + (await getDisplayedRef(isolateId, ref.id!)).valueAsString; + + final fields = await Future.wait(fieldRefs.values.map(toStringValue)); + return Map.fromIterables(fieldRefs.keys, fields); } Future> getElements( @@ -218,7 +251,7 @@ Matcher matchRecordInstanceRef({required int length}) => isA() Matcher matchRecordTypeInstanceRef({required int length}) => isA() .having((e) => e.kind, 'kind', InstanceKind.kRecordType) .having((e) => e.length, 'length', length) - .having((e) => e.classRef!, 'classRef', matchRecordTypeClassRef); + .having((e) => e.classRef!, 'classRef', matchTypeClassRef); Matcher matchTypeInstanceRef(dynamic name) => isA() .having((e) => e.kind, 'kind', InstanceKind.kType) @@ -267,7 +300,7 @@ Matcher matchRecordInstance({required int length}) => isA() Matcher matchRecordTypeInstance({required int length}) => isA() .having((e) => e.kind, 'kind', InstanceKind.kRecordType) .having((e) => e.length, 'length', length) - .having((e) => e.classRef, 'classRef', matchRecordTypeClassRef); + .having((e) => e.classRef, 'classRef', matchTypeClassRef); Matcher matchTypeStringInstance(dynamic name) => matchPrimitiveInstance(kind: InstanceKind.kString, value: name); @@ -279,8 +312,6 @@ Matcher matchTypeInstance(dynamic name) => isA() Matcher matchRecordClass = matchClass(name: matchRecordClassName, libraryId: _dartCoreLibrary); -Matcher matchRecordTypeClass = - matchClass(name: matchRecordTypeClassName, libraryId: _dartRuntimeLibrary); Matcher matchTypeClass = matchClass(name: matchTypeClassName, libraryId: _dartCoreLibrary); @@ -290,12 +321,11 @@ Matcher matchClass({dynamic name, String? libraryId}) => isA() Matcher matchRecordClassRef = matchClassRef(name: matchRecordClassName, libraryId: _dartCoreLibrary); -Matcher matchRecordTypeClassRef = matchClassRef( - name: matchRecordTypeClassName, - libraryId: _dartRuntimeLibrary, +Matcher matchRecordTypeClassRef = matchTypeClassRef; +Matcher matchTypeClassRef = matchClassRef( + name: matchTypeClassName, + libraryId: _dartCoreLibrary, ); -Matcher matchTypeClassRef = - matchClassRef(name: matchTypeClassName, libraryId: _dartCoreLibrary); Matcher matchListClassRef(String type) => matchClassRef( name: matchListClassName(type), libraryId: _matchListLibraryName, diff --git a/dwds/test/instances/common/type_inspection_common.dart b/dwds/test/instances/common/type_inspection_common.dart index aadf4a828..e46747dec 100644 --- a/dwds/test/instances/common/type_inspection_common.dart +++ b/dwds/test/instances/common/type_inspection_common.dart @@ -7,6 +7,7 @@ import 'package:test_common/logging.dart'; import 'package:test_common/test_sdk_configuration.dart'; import 'package:vm_service/vm_service.dart'; +import '../../evaluate_common.dart'; import '../../fixtures/context.dart'; import '../../fixtures/project.dart'; import '../../fixtures/utilities.dart'; @@ -40,6 +41,9 @@ void runTests({ getDisplayedFields(instanceRef) => testInspector.getDisplayedFields(isolateId, instanceRef); + getDisplayedGetters(instanceRef) => + testInspector.getDisplayedGetters(isolateId, instanceRef); + getInstanceRef(frame, expression) => testInspector.getInstanceRef(isolateId, frame, expression); @@ -55,15 +59,19 @@ void runTests({ getElements(String instanceId) => testInspector.getElements(isolateId, instanceId); - final matchTypeObject = { - 'hashCode': matchPrimitiveInstanceRef(kind: InstanceKind.kDouble), - 'runtimeType': matchTypeInstanceRef(matchTypeClassName), + final matchTypeObjectFields = { + '_rti': matchInstanceRefClassName('Rti'), + }; + + final matchDisplayedTypeObjectFields = { + '_rti': 'Instance of \'Rti\'', + }; + + final matchDisplayedTypeObjectGetters = { + 'hashCode': matches('[0-9]*'), + 'runtimeType': matchTypeClassName, }; - final matchDisplayedTypeObject = [ - matches('[0-9]*'), - matchTypeClassName, - ]; group('$compilationMode |', () { setUpAll(() async { setCurrentLogWriter(debug: debug); @@ -108,8 +116,18 @@ void runTests({ final classId = instanceRef.classRef!.id; expect(await getObject(classId), matchTypeClass); - expect(await getFields(instanceRef, depth: 1), matchTypeObject); - expect(await getDisplayedFields(instanceRef), matchDisplayedTypeObject); + expect( + await getFields(instanceRef, depth: 1), + matchTypeObjectFields, + ); + expect( + await getDisplayedFields(instanceRef), + matchDisplayedTypeObjectFields, + ); + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); }); }); @@ -125,8 +143,18 @@ void runTests({ final classId = instanceRef.classRef!.id; expect(await getObject(classId), matchTypeClass); - expect(await getFields(instanceRef, depth: 1), matchTypeObject); - expect(await getDisplayedFields(instanceRef), matchDisplayedTypeObject); + expect( + await getFields(instanceRef, depth: 1), + matchTypeObjectFields, + ); + expect( + await getDisplayedFields(instanceRef), + matchDisplayedTypeObjectFields, + ); + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); }); }); @@ -142,8 +170,18 @@ void runTests({ final classId = instanceRef.classRef!.id; expect(await getObject(classId), matchTypeClass); - expect(await getFields(instanceRef, depth: 1), matchTypeObject); - expect(await getDisplayedFields(instanceRef), matchDisplayedTypeObject); + expect( + await getFields(instanceRef, depth: 1), + matchTypeObjectFields, + ); + expect( + await getDisplayedFields(instanceRef), + matchDisplayedTypeObjectFields, + ); + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); }); }); @@ -160,8 +198,15 @@ void runTests({ final classId = instanceRef.classRef!.id; expect(await getObject(classId), matchTypeClass); - expect(await getFields(instanceRef, depth: 1), matchTypeObject); - expect(await getDisplayedFields(instanceRef), matchDisplayedTypeObject); + expect(await getFields(instanceRef, depth: 1), matchTypeObjectFields); + expect( + await getDisplayedFields(instanceRef), + matchDisplayedTypeObjectFields, + ); + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); }); }); @@ -177,8 +222,18 @@ void runTests({ final classId = instanceRef.classRef!.id; expect(await getObject(classId), matchTypeClass); - expect(await getFields(instanceRef, depth: 1), matchTypeObject); - expect(await getDisplayedFields(instanceRef), matchDisplayedTypeObject); + expect( + await getFields(instanceRef, depth: 1), + matchTypeObjectFields, + ); + expect( + await getDisplayedFields(instanceRef), + matchDisplayedTypeObjectFields, + ); + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); }); }); @@ -197,14 +252,18 @@ void runTests({ ); final classId = instanceRef.classRef!.id; - expect(await getObject(classId), matchRecordTypeClass); + expect(await getObject(classId), matchTypeClass); expect( await getFields(instanceRef, depth: 2), - {1: matchTypeObject, 2: matchTypeObject}, + {1: matchTypeObjectFields, 2: matchTypeObjectFields}, ); expect( await getDisplayedFields(instanceRef), - ['int', 'String'], + {1: 'int', 2: 'String'}, + ); + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, ); }); }); @@ -222,8 +281,15 @@ void runTests({ final classId = instanceRef.classRef!.id; expect(await getObject(classId), matchTypeClass); - expect(await getFields(instanceRef, depth: 1), matchTypeObject); - expect(await getDisplayedFields(instanceRef), matchDisplayedTypeObject); + expect(await getFields(instanceRef, depth: 1), matchTypeObjectFields); + expect( + await getDisplayedFields(instanceRef), + matchDisplayedTypeObjectFields, + ); + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); }); }); }); From 91aac43bbf974c2134818908babc76015cd7e2cb Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Thu, 18 Jan 2024 14:22:31 -0800 Subject: [PATCH 6/9] Fixed analyzer errors --- dwds/test/instances/common/test_inspector.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dwds/test/instances/common/test_inspector.dart b/dwds/test/instances/common/test_inspector.dart index 5905ad809..7bcdfc875 100644 --- a/dwds/test/instances/common/test_inspector.dart +++ b/dwds/test/instances/common/test_inspector.dart @@ -117,7 +117,9 @@ class TestInspector { ]); return Map.fromIterables( - getters.map((e) => e.name!), results.map((e) => e as InstanceRef)); + getters.map((e) => e.name!), + results.map((e) => e as InstanceRef), + ); } Future getInstanceRef( @@ -359,13 +361,11 @@ Object? _getValue(InstanceRef instanceRef) { } final _dartCoreLibrary = 'dart:core'; -final _dartRuntimeLibrary = 'dart:_runtime'; final _dartInterceptorsLibrary = 'dart:_interceptors'; final _dartJsHelperLibrary = 'dart:_js_helper'; final _dartCollectionLibrary = 'dart:collection'; final matchRecordClassName = 'Record'; -final matchRecordTypeClassName = 'RecordType'; /// Match types for old and new type systems. /// - Old type system has `dart:_interceptors|List` and `dart:_runtime|_Type`. From c4a192563a650a4128fd672a9b2da0134a9fe96e Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Fri, 19 Jan 2024 14:58:04 -0800 Subject: [PATCH 7/9] Add dart:_rti to the list of sdk libraries --- dwds/lib/src/debugging/metadata/provider.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/dwds/lib/src/debugging/metadata/provider.dart b/dwds/lib/src/debugging/metadata/provider.dart index 677bde885..62e2455e9 100644 --- a/dwds/lib/src/debugging/metadata/provider.dart +++ b/dwds/lib/src/debugging/metadata/provider.dart @@ -44,6 +44,7 @@ class MetadataProvider { 'dart:_js_primitives', 'dart:_metadata', 'dart:_native_typed_data', + 'dart:_rti', 'dart:async', 'dart:collection', 'dart:convert', From e237beff7128572ce1ff438a6596fd0cc977347c Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Mon, 22 Jan 2024 10:41:15 -0800 Subject: [PATCH 8/9] Fix failing tests --- .../common/record_type_inspection_common.dart | 128 ++++++++++++++++-- .../test/instances/common/test_inspector.dart | 35 ++++- 2 files changed, 143 insertions(+), 20 deletions(-) diff --git a/dwds/test/instances/common/record_type_inspection_common.dart b/dwds/test/instances/common/record_type_inspection_common.dart index aeb0e0a09..f47bf9c47 100644 --- a/dwds/test/instances/common/record_type_inspection_common.dart +++ b/dwds/test/instances/common/record_type_inspection_common.dart @@ -5,6 +5,7 @@ import 'package:test/test.dart'; import 'package:test_common/logging.dart'; import 'package:test_common/test_sdk_configuration.dart'; +import 'package:test_common/utilities.dart'; import 'package:vm_service/vm_service.dart'; import '../../fixtures/context.dart'; @@ -43,9 +44,17 @@ void runTests({ getDisplayedFields(InstanceRef ref) => testInspector.getDisplayedFields(isolateId, ref); + getDisplayedGetters(InstanceRef ref) => + testInspector.getDisplayedGetters(isolateId, ref); + getElements(String instanceId) => testInspector.getElements(isolateId, instanceId); + final matchDisplayedTypeObjectGetters = { + 'hashCode': matches('[0-9]*'), + 'runtimeType': matchTypeClassName, + }; + group('$compilationMode |', () { setUpAll(() async { setCurrentLogWriter(debug: debug); @@ -88,7 +97,7 @@ void runTests({ expect(await getObject(instanceId), matchRecordTypeInstance(length: 2)); final classId = instanceRef.classRef!.id; - expect(await getObject(classId), matchTypeClass); + expect(await getObject(classId), matchRecordTypeClass); }); }); @@ -104,11 +113,27 @@ void runTests({ ); expect( await getDisplayedFields(instanceRef), - ['bool', 'int'], + {1: 'bool', 2: 'int'}, ); }); }); + test( + 'simple record type getters', + () async { + await onBreakPoint('printSimpleLocalRecord', (event) async { + final frame = event.topFrame!.index!; + final instanceRef = await getInstanceRef(frame, 'record.runtimeType'); + + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); + }); + }, + skip: !dartSdkIsAtLeast('3.4.0-56.0.dev'), + ); + test('simple record type display', () async { await onBreakPoint('printSimpleLocalRecord', (event) async { final frame = event.topFrame!.index!; @@ -136,7 +161,7 @@ void runTests({ expect(await getObject(instanceId), matchRecordTypeInstance(length: 3)); final classId = instanceRef.classRef!.id; - expect(await getObject(classId), matchTypeClass); + expect(await getObject(classId), matchRecordTypeClass); }); }); @@ -156,11 +181,27 @@ void runTests({ ); expect( await getDisplayedFields(instanceRef), - ['bool', 'int', 'IdentityMap'], + {1: 'bool', 2: 'int', 3: 'IdentityMap'}, ); }); }); + test( + 'complex record type getters', + () async { + await onBreakPoint('printComplexLocalRecord', (event) async { + final frame = event.topFrame!.index!; + final instanceRef = await getInstanceRef(frame, 'record.runtimeType'); + + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); + }); + }, + skip: !dartSdkIsAtLeast('3.4.0-56.0.dev'), + ); + test('complex record type display', () async { await onBreakPoint('printComplexLocalRecord', (event) async { final frame = event.topFrame!.index!; @@ -188,11 +229,11 @@ void runTests({ expect(await getObject(instanceId), matchRecordTypeInstance(length: 3)); final classId = instanceRef.classRef!.id; - expect(await getObject(classId), matchTypeClass); + expect(await getObject(classId), matchRecordTypeClass); }); }); - test('complex record type with named fields elements', () async { + test('complex record type with named fields elements', () async { await onBreakPoint('printComplexNamedLocalRecord', (event) async { final frame = event.topFrame!.index!; final instanceRef = await getInstanceRef(frame, 'record.runtimeType'); @@ -209,11 +250,27 @@ void runTests({ expect( await getDisplayedFields(instanceRef), - ['bool', 'int', 'IdentityMap'], + {1: 'bool', 2: 'int', 'array': 'IdentityMap'}, ); }); }); + test( + 'complex record type with named fields getters', + () async { + await onBreakPoint('printComplexNamedLocalRecord', (event) async { + final frame = event.topFrame!.index!; + final instanceRef = await getInstanceRef(frame, 'record.runtimeType'); + + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); + }); + }, + skip: !dartSdkIsAtLeast('3.4.0-56.0.dev'), + ); + test('complex record type with named fields display', () async { await onBreakPoint('printComplexNamedLocalRecord', (event) async { final frame = event.topFrame!.index!; @@ -241,7 +298,7 @@ void runTests({ expect(await getObject(instanceId), matchRecordTypeInstance(length: 2)); final classId = instanceRef.classRef!.id; - expect(await getObject(classId), matchTypeClass); + expect(await getObject(classId), matchRecordTypeClass); }); }); @@ -262,15 +319,36 @@ void runTests({ ); expect( await getDisplayedFields(instanceRef), - ['bool', '(bool, int)'], + {1: 'bool', 2: '(bool, int)'}, ); expect( await getDisplayedFields(elements[1]), - ['bool', 'int'], + {1: 'bool', 2: 'int'}, ); }); }); + test( + 'nested record type getters', + () async { + await onBreakPoint('printNestedLocalRecord', (event) async { + final frame = event.topFrame!.index!; + final instanceRef = await getInstanceRef(frame, 'record.runtimeType'); + final elements = await getElements(instanceRef.id!); + + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); + expect( + await getDisplayedGetters(elements[1]), + matchDisplayedTypeObjectGetters, + ); + }); + }, + skip: !dartSdkIsAtLeast('3.4.0-56.0.dev'), + ); + test('nested record type display', () async { await onBreakPoint('printNestedLocalRecord', (event) async { final frame = event.topFrame!.index!; @@ -299,7 +377,7 @@ void runTests({ expect(instance, matchRecordTypeInstance(length: 2)); final classId = instanceRef.classRef!.id; - expect(await getObject(classId), matchTypeClass); + expect(await getObject(classId), matchRecordTypeClass); }); }); @@ -320,15 +398,37 @@ void runTests({ ); expect( await getDisplayedFields(instanceRef), - ['bool', '(bool, int)'], + {1: 'bool', 'inner': '(bool, int)'}, ); + expect( await getDisplayedFields(elements[1]), - ['bool', 'int'], + {1: 'bool', 2: 'int'}, ); }); }); + test( + 'nested record type with named fields getters', + () async { + await onBreakPoint('printNestedNamedLocalRecord', (event) async { + final frame = event.topFrame!.index!; + final instanceRef = await getInstanceRef(frame, 'record.runtimeType'); + final elements = await getElements(instanceRef.id!); + + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); + expect( + await getDisplayedGetters(elements[1]), + matchDisplayedTypeObjectGetters, + ); + }); + }, + skip: !dartSdkIsAtLeast('3.4.0-56.0.dev'), + ); + test('nested record type with named fields display', () async { await onBreakPoint('printNestedNamedLocalRecord', (event) async { final frame = event.topFrame!.index!; @@ -336,7 +436,7 @@ void runTests({ final instance = await getObject(instanceRef.id!); final typeClassId = instance.classRef!.id; - expect(await getObject(typeClassId), matchTypeClass); + expect(await getObject(typeClassId), matchRecordTypeClass); final typeStringRef = await getInstanceRef(frame, 'record.runtimeType.toString()'); diff --git a/dwds/test/instances/common/test_inspector.dart b/dwds/test/instances/common/test_inspector.dart index 7bcdfc875..9b7773d8c 100644 --- a/dwds/test/instances/common/test_inspector.dart +++ b/dwds/test/instances/common/test_inspector.dart @@ -253,7 +253,7 @@ Matcher matchRecordInstanceRef({required int length}) => isA() Matcher matchRecordTypeInstanceRef({required int length}) => isA() .having((e) => e.kind, 'kind', InstanceKind.kRecordType) .having((e) => e.length, 'length', length) - .having((e) => e.classRef!, 'classRef', matchTypeClassRef); + .having((e) => e.classRef!, 'classRef', matchRecordTypeClassRef); Matcher matchTypeInstanceRef(dynamic name) => isA() .having((e) => e.kind, 'kind', InstanceKind.kType) @@ -302,7 +302,7 @@ Matcher matchRecordInstance({required int length}) => isA() Matcher matchRecordTypeInstance({required int length}) => isA() .having((e) => e.kind, 'kind', InstanceKind.kRecordType) .having((e) => e.length, 'length', length) - .having((e) => e.classRef, 'classRef', matchTypeClassRef); + .having((e) => e.classRef, 'classRef', matchRecordTypeClassRef); Matcher matchTypeStringInstance(dynamic name) => matchPrimitiveInstance(kind: InstanceKind.kString, value: name); @@ -317,13 +317,28 @@ Matcher matchRecordClass = Matcher matchTypeClass = matchClass(name: matchTypeClassName, libraryId: _dartCoreLibrary); +/// TODO(annagrin): record type class is reported incorrectly +/// in ddc https://github.com/dart-lang/sdk/issues/54609, +/// remove when fixed. +Matcher matchRecordTypeClass = anyOf( + matchTypeClass, + matchClass(name: matchRecordTypeClassName, libraryId: _dartRuntimeLibrary), +); + Matcher matchClass({dynamic name, String? libraryId}) => isA() .having((e) => e.name, 'class name', name) .having((e) => e.library, 'library', matchLibraryRef(libraryId)); Matcher matchRecordClassRef = matchClassRef(name: matchRecordClassName, libraryId: _dartCoreLibrary); -Matcher matchRecordTypeClassRef = matchTypeClassRef; + +/// TODO(annagrin): record type class is reported incorrectly +/// in ddc https://github.com/dart-lang/sdk/issues/54609, +/// remove when fixed. +Matcher matchRecordTypeClassRef = anyOf( + matchTypeClassRef, + matchClassRef(name: matchRecordTypeClassName, libraryId: _dartRuntimeLibrary), +); Matcher matchTypeClassRef = matchClassRef( name: matchTypeClassName, libraryId: _dartCoreLibrary, @@ -364,14 +379,22 @@ final _dartCoreLibrary = 'dart:core'; final _dartInterceptorsLibrary = 'dart:_interceptors'; final _dartJsHelperLibrary = 'dart:_js_helper'; final _dartCollectionLibrary = 'dart:collection'; +final _dartRuntimeLibrary = 'dart:_runtime'; final matchRecordClassName = 'Record'; /// Match types for old and new type systems. -/// - Old type system has `dart:_interceptors|List` and `dart:_runtime|_Type`. -/// - New type system has `dart:_interceptors|JSArray` and `dart:core|Type`. -/// TODO(annagrin): update when DDC enables new type system. +/// - Old type system has +/// - for arrays: `dart:_interceptors|List` +/// - for type: `dart:_runtime|_Type`. +/// - New type system has +/// - for arrays: dart:_interceptors|JSArray`, and +/// - for type: `dart:core|Type`. +/// TODO(annagrin): remove old matchers when DDC enables new type system. +/// TODO(annagrin): `matchTypeClassName` is reported incorrectly +/// in ddc https://github.com/dart-lang/sdk/issues/54609, final matchTypeClassName = anyOf(['Type', '_Type']); +final matchRecordTypeClassName = 'RecordType'; Matcher matchListClassName(String elementType) => anyOf(['JSArray<$elementType>', 'List<$elementType>']); From 01fb5c394d2bde5a98450df28fb40ef732c7a4d9 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Mon, 22 Jan 2024 11:03:29 -0800 Subject: [PATCH 9/9] Fixed failing tests --- .../common/type_inspection_common.dart | 127 ++++++++++++++---- 1 file changed, 102 insertions(+), 25 deletions(-) diff --git a/dwds/test/instances/common/type_inspection_common.dart b/dwds/test/instances/common/type_inspection_common.dart index e46747dec..e0616796c 100644 --- a/dwds/test/instances/common/type_inspection_common.dart +++ b/dwds/test/instances/common/type_inspection_common.dart @@ -5,6 +5,7 @@ import 'package:test/test.dart'; import 'package:test_common/logging.dart'; import 'package:test_common/test_sdk_configuration.dart'; +import 'package:test_common/utilities.dart'; import 'package:vm_service/vm_service.dart'; import '../../evaluate_common.dart'; @@ -124,13 +125,25 @@ void runTests({ await getDisplayedFields(instanceRef), matchDisplayedTypeObjectFields, ); - expect( - await getDisplayedGetters(instanceRef), - matchDisplayedTypeObjectGetters, - ); }); }); + test( + 'String type getters', + () async { + await onBreakPoint('printSimpleLocalRecord', (event) async { + final frame = event.topFrame!.index!; + final instanceRef = await getInstanceRef(frame, "'1'.runtimeType"); + + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); + }); + }, + skip: !dartSdkIsAtLeast('3.4.0-56.0.dev'), + ); + test('int type', () async { await onBreakPoint('printSimpleLocalRecord', (event) async { final frame = event.topFrame!.index!; @@ -151,13 +164,25 @@ void runTests({ await getDisplayedFields(instanceRef), matchDisplayedTypeObjectFields, ); - expect( - await getDisplayedGetters(instanceRef), - matchDisplayedTypeObjectGetters, - ); }); }); + test( + 'int type getters', + () async { + await onBreakPoint('printSimpleLocalRecord', (event) async { + final frame = event.topFrame!.index!; + final instanceRef = await getInstanceRef(frame, '1.runtimeType'); + + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); + }); + }, + skip: !dartSdkIsAtLeast('3.4.0-56.0.dev'), + ); + test('list type', () async { await onBreakPoint('printSimpleLocalRecord', (event) async { final frame = event.topFrame!.index!; @@ -203,13 +228,26 @@ void runTests({ await getDisplayedFields(instanceRef), matchDisplayedTypeObjectFields, ); - expect( - await getDisplayedGetters(instanceRef), - matchDisplayedTypeObjectGetters, - ); }); }); + test( + 'map type getters', + () async { + await onBreakPoint('printSimpleLocalRecord', (event) async { + final frame = event.topFrame!.index!; + final instanceRef = + await getInstanceRef(frame, '{}.runtimeType'); + + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); + }); + }, + skip: !dartSdkIsAtLeast('3.4.0-56.0.dev'), + ); + test('set type', () async { await onBreakPoint('printSimpleLocalRecord', (event) async { final frame = event.topFrame!.index!; @@ -230,13 +268,26 @@ void runTests({ await getDisplayedFields(instanceRef), matchDisplayedTypeObjectFields, ); - expect( - await getDisplayedGetters(instanceRef), - matchDisplayedTypeObjectGetters, - ); }); }); + test( + 'set type getters', + () async { + await onBreakPoint('printSimpleLocalRecord', (event) async { + final frame = event.topFrame!.index!; + final instanceRef = + await getInstanceRef(frame, '{}.runtimeType'); + + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); + }); + }, + skip: !dartSdkIsAtLeast('3.4.0-56.0.dev'), + ); + test('record type', () async { await onBreakPoint('printSimpleLocalRecord', (event) async { final frame = event.topFrame!.index!; @@ -252,7 +303,7 @@ void runTests({ ); final classId = instanceRef.classRef!.id; - expect(await getObject(classId), matchTypeClass); + expect(await getObject(classId), matchRecordTypeClass); expect( await getFields(instanceRef, depth: 2), {1: matchTypeObjectFields, 2: matchTypeObjectFields}, @@ -261,13 +312,26 @@ void runTests({ await getDisplayedFields(instanceRef), {1: 'int', 2: 'String'}, ); - expect( - await getDisplayedGetters(instanceRef), - matchDisplayedTypeObjectGetters, - ); }); }); + test( + 'record type getters', + () async { + await onBreakPoint('printSimpleLocalRecord', (event) async { + final frame = event.topFrame!.index!; + final instanceRef = + await getInstanceRef(frame, "(0,'a').runtimeType"); + + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); + }); + }, + skip: !dartSdkIsAtLeast('3.4.0-56.0.dev'), + ); + test('class type', () async { await onBreakPoint('printSimpleLocalRecord', (event) async { final frame = event.topFrame!.index!; @@ -286,11 +350,24 @@ void runTests({ await getDisplayedFields(instanceRef), matchDisplayedTypeObjectFields, ); - expect( - await getDisplayedGetters(instanceRef), - matchDisplayedTypeObjectGetters, - ); }); }); + + test( + 'class type getters', + () async { + await onBreakPoint('printSimpleLocalRecord', (event) async { + final frame = event.topFrame!.index!; + final instanceRef = + await getInstanceRef(frame, "Uri.file('').runtimeType"); + + expect( + await getDisplayedGetters(instanceRef), + matchDisplayedTypeObjectGetters, + ); + }); + }, + skip: !dartSdkIsAtLeast('3.4.0-56.0.dev'), + ); }); }