Skip to content

Commit ca38a3a

Browse files
authored
Prepare DWDS 23.0.0+1 hotfix (#2355)
1 parent fd6ec44 commit ca38a3a

16 files changed

+618
-203
lines changed

dwds/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 23.0.0+1
2+
3+
- Filter out internal type properties from the new DDC type system. - [#2348](https://github.com/dart-lang/webdev/pull/2348)
4+
- Fix errors on displaying getters when debugging in VS Code. - [#2343](https://github.com/dart-lang/webdev/pull/2343)
5+
16
## 23.0.0
27
- Restructure `LoadStrategy` to provide build settings. - [#2270](https://github.com/dart-lang/webdev/pull/2270)
38
- Add `FrontendServerLegacyStrategyProvider` and update bootstrap generation logic for `LegacyStrategy` - [#2285](https://github.com/dart-lang/webdev/pull/2285)

dwds/lib/src/debugging/dart_scope.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ final ddcTemporaryTypeVariableRegExp = RegExp(r'^__t[\$\w*]+$');
2020
final previousDdcTemporaryVariableRegExp =
2121
RegExp(r'^(t[0-9]+\$?[0-9]*|__t[\$\w*]+)$');
2222

23-
/// Find the visible Dart properties from a JS Scope Chain, coming from the
23+
/// Find the visible Dart variables from a JS Scope Chain, coming from the
2424
/// scopeChain attribute of a Chrome CallFrame corresponding to [frame].
2525
///
2626
/// See chromedevtools.github.io/devtools-protocol/tot/Debugger#type-CallFrame.
27-
Future<List<Property>> visibleProperties({
27+
Future<List<Property>> visibleVariables({
2828
required AppInspectorInterface inspector,
2929
required WipCallFrame frame,
3030
}) async {

dwds/lib/src/debugging/debugger.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ class Debugger extends Domain {
405405
Future<List<BoundVariable>> variablesFor(WipCallFrame frame) async {
406406
// TODO(alanknight): Can these be moved to dart_scope.dart?
407407
final properties =
408-
await visibleProperties(inspector: inspector, frame: frame);
408+
await visibleVariables(inspector: inspector, frame: frame);
409409
final boundVariables = await Future.wait(
410410
properties.map(_boundVariable),
411411
);

dwds/lib/src/debugging/inspector.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,9 +601,18 @@ class AppInspector implements AppInspectorInterface {
601601
);
602602
return jsProperties
603603
.map<Property>((each) => Property(each as Map<String, dynamic>))
604+
.where(_isVisibleProperty)
604605
.toList();
605606
}
606607

608+
bool _isVisibleProperty(Property property) {
609+
// Filter out any RTI objects from the new DDC type system. See:
610+
// https://github.com/dart-lang/webdev/issues/2316
611+
final isRtiObject =
612+
property.value?.className?.startsWith('dart_rti.Rti') ?? false;
613+
return !isRtiObject;
614+
}
615+
607616
/// Calculate the number of available elements in the range.
608617
static int _calculateRangeCount({
609618
int? count,

dwds/lib/src/debugging/instance.dart

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -238,29 +238,49 @@ class InstanceHelper extends Domain {
238238
final objectId = remoteObject.objectId;
239239
if (objectId == null) return null;
240240

241+
final fields = await _getInstanceFields(
242+
metaData,
243+
remoteObject,
244+
offset: offset,
245+
count: count,
246+
);
247+
248+
final result = Instance(
249+
kind: InstanceKind.kPlainInstance,
250+
id: objectId,
251+
identityHashCode: remoteObject.objectId.hashCode,
252+
classRef: metaData.classRef,
253+
fields: fields,
254+
);
255+
return result;
256+
}
257+
258+
Future<List<BoundField>> _getInstanceFields(
259+
ClassMetaData metaData,
260+
RemoteObject remoteObject, {
261+
int? offset,
262+
int? count,
263+
}) async {
264+
final objectId = remoteObject.objectId;
265+
if (objectId == null) throw StateError('Object id is null for instance');
266+
241267
final properties = await inspector.getProperties(
242268
objectId,
243269
offset: offset,
244270
count: count,
245271
length: metaData.length,
246272
);
273+
247274
final dartProperties = await _dartFieldsFor(properties, remoteObject);
248-
var boundFields = await Future.wait(
275+
final boundFields = await Future.wait(
249276
dartProperties
250277
.map<Future<BoundField>>((p) => _fieldFor(p, metaData.classRef)),
251278
);
252-
boundFields = boundFields
279+
280+
return boundFields
253281
.where((bv) => inspector.isDisplayableObject(bv.value))
254282
.toList()
255283
..sort(_compareBoundFields);
256-
final result = Instance(
257-
kind: InstanceKind.kPlainInstance,
258-
id: objectId,
259-
identityHashCode: remoteObject.objectId.hashCode,
260-
classRef: metaData.classRef,
261-
fields: boundFields,
262-
);
263-
return result;
264284
}
265285

266286
int _compareBoundFields(BoundField a, BoundField b) {
@@ -700,7 +720,13 @@ class InstanceHelper extends Domain {
700720
final objectId = remoteObject.objectId;
701721
if (objectId == null) return null;
702722

703-
final fields = await _typeFields(metaData.classRef, remoteObject);
723+
final fields = await _getInstanceFields(
724+
metaData,
725+
remoteObject,
726+
offset: offset,
727+
count: count,
728+
);
729+
704730
return Instance(
705731
identityHashCode: objectId.hashCode,
706732
kind: InstanceKind.kType,
@@ -714,36 +740,6 @@ class InstanceHelper extends Domain {
714740
);
715741
}
716742

717-
/// The field types for a Dart RecordType.
718-
///
719-
/// Returns a range of [count] field types, if available, starting from
720-
/// the [offset].
721-
///
722-
/// If [offset] is `null`, assumes 0 offset.
723-
/// If [count] is `null`, return all field types starting from the offset.
724-
Future<List<BoundField>> _typeFields(
725-
ClassRef classRef,
726-
RemoteObject type,
727-
) async {
728-
// Present the type as an instance of `core.Type` class and
729-
// hide the internal implementation.
730-
final expression = _jsRuntimeFunctionCall('getTypeFields(this)');
731-
732-
final result = await inspector.jsCallFunctionOn(type, expression, []);
733-
final hashCodeObject = await inspector.loadField(result, 'hashCode');
734-
final runtimeTypeObject = await inspector.loadField(result, 'runtimeType');
735-
736-
final properties = [
737-
Property({'name': 'hashCode', 'value': hashCodeObject}),
738-
Property({'name': 'runtimeType', 'value': runtimeTypeObject}),
739-
];
740-
741-
final boundFields = await Future.wait(
742-
properties.map<Future<BoundField>>((p) => _fieldFor(p, classRef)),
743-
);
744-
return boundFields;
745-
}
746-
747743
/// Return the available count of elements in the requested range.
748744
/// Return `null` if the range includes the whole object.
749745
/// [count] is the range length requested by the `getObject` call.

dwds/lib/src/debugging/metadata/provider.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class MetadataProvider {
4444
'dart:_js_primitives',
4545
'dart:_metadata',
4646
'dart:_native_typed_data',
47+
'dart:_rti',
4748
'dart:async',
4849
'dart:collection',
4950
'dart:convert',

dwds/lib/src/services/chrome_proxy_service.dart

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,35 @@ ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").developer.
618618
await isCompilerInitialized;
619619
_checkIsolate('evaluate', isolateId);
620620

621-
final library = await inspector.getLibrary(targetId);
621+
late Obj object;
622+
try {
623+
object = await inspector.getObject(targetId);
624+
} catch (_) {
625+
return ErrorRef(
626+
kind: 'error',
627+
message: 'Evaluate is called on an unsupported target:'
628+
'$targetId',
629+
id: createId(),
630+
);
631+
}
632+
633+
final library =
634+
object is Library ? object : inspector.isolate.rootLib;
635+
636+
if (object is Instance) {
637+
// Evaluate is called on a target - convert this to a dart
638+
// expression and scope by adding a target variable to the
639+
// expression and the scope, for example:
640+
//
641+
// Library: 'package:hello_world/main.dart'
642+
// Expression: 'hashCode' => 'x.hashCode'
643+
// Scope: {} => { 'x' : targetId }
644+
645+
final target = _newVariableForScope(scope);
646+
expression = '$target.$expression';
647+
scope = (scope ?? {})..addAll({target: targetId});
648+
}
649+
622650
return await _getEvaluationResult(
623651
isolateId,
624652
() => evaluator.evaluateExpression(
@@ -631,7 +659,7 @@ ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").developer.
631659
);
632660
}
633661
throw RPCError(
634-
'evaluateInFrame',
662+
'evaluate',
635663
RPCErrorKind.kInvalidRequest.code,
636664
'Expression evaluation is not supported for this configuration.',
637665
);
@@ -640,6 +668,15 @@ ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").developer.
640668
);
641669
}
642670

671+
String _newVariableForScope(Map<String, String>? scope) {
672+
// Find a new variable not in scope.
673+
var candidate = 'x';
674+
while (scope?.containsKey(candidate) ?? false) {
675+
candidate += '\$1';
676+
}
677+
return candidate;
678+
}
679+
643680
@override
644681
Future<Response> evaluateInFrame(
645682
String isolateId,

dwds/test/evaluate_common.dart

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ void testAll({
320320
await getInstanceRef(event.topFrame!.index!, 'stream');
321321
final instance = await getInstance(instanceRef);
322322

323-
expect(instance, matchInstance('_AsBroadcastStream<int>'));
323+
expect(instance, matchInstanceClassName('_AsBroadcastStream<int>'));
324324
});
325325
});
326326

@@ -667,24 +667,24 @@ void testAll({
667667
tearDown(() async {});
668668

669669
evaluate(
670-
libraryId,
670+
targetId,
671671
expr, {
672672
scope,
673673
}) async =>
674674
await context.service.evaluate(
675675
isolateId,
676-
libraryId,
676+
targetId,
677677
expr,
678678
scope: scope,
679679
);
680680

681681
getInstanceRef(
682-
libraryId,
682+
targetId,
683683
expr, {
684684
scope,
685685
}) async {
686686
final result = await evaluate(
687-
libraryId,
687+
targetId,
688688
expr,
689689
scope: scope,
690690
);
@@ -698,6 +698,28 @@ void testAll({
698698
return isolate.rootLib!.id!;
699699
}
700700

701+
test(
702+
'RecordType getters',
703+
() async {
704+
final libraryId = getRootLibraryId();
705+
706+
final type = await getInstanceRef(libraryId, '(0,1).runtimeType');
707+
final result = await getInstanceRef(type.id, 'hashCode');
708+
709+
expect(result, matchInstanceRefKind('Double'));
710+
},
711+
skip: 'https://github.com/dart-lang/sdk/issues/54609',
712+
);
713+
714+
test('Object getters', () async {
715+
final libraryId = getRootLibraryId();
716+
717+
final type = await getInstanceRef(libraryId, 'Object()');
718+
final result = await getInstanceRef(type.id, 'hashCode');
719+
720+
expect(result, matchInstanceRefKind('Double'));
721+
});
722+
701723
test('with scope', () async {
702724
final libraryId = getRootLibraryId();
703725

@@ -761,15 +783,13 @@ void testAll({
761783
final evaluation2 = evaluate(libraryId, 'MainClass(1,1).toString()');
762784

763785
final results = await Future.wait([evaluation1, evaluation2]);
764-
765786
expect(
766787
results[0],
767-
matchErrorRef(contains('No batch result object ID')),
768-
);
769-
expect(
770-
results[1],
771-
matchErrorRef(contains('No batch result object ID')),
788+
matchErrorRef(
789+
contains('Evaluate is called on an unsupported target'),
790+
),
772791
);
792+
expect(results[1], matchInstanceRef('1, 1'));
773793
});
774794

775795
test('with scope override', () async {
@@ -900,13 +920,20 @@ Future<String> _setBreakpointInInjectedClient(WipDebugger debugger) async {
900920
return result.json['result']['breakpointId'];
901921
}
902922

903-
Matcher matchInstanceRef(dynamic value) => isA<InstanceRef>().having(
904-
(instance) => instance.valueAsString,
905-
'valueAsString',
906-
value,
923+
Matcher matchInstanceRefKind(String kind) =>
924+
isA<InstanceRef>().having((instance) => instance.kind, 'kind', kind);
925+
926+
Matcher matchInstanceRef(dynamic value) => isA<InstanceRef>()
927+
.having((instance) => instance.valueAsString, 'valueAsString', value);
928+
929+
Matcher matchInstanceClassName(dynamic className) => isA<Instance>().having(
930+
(instance) => instance.classRef!.name,
931+
'class name',
932+
className,
907933
);
908934

909-
Matcher matchInstance(dynamic className) => isA<Instance>().having(
935+
Matcher matchInstanceRefClassName(dynamic className) =>
936+
isA<InstanceRef>().having(
910937
(instance) => instance.classRef!.name,
911938
'class name',
912939
className,

dwds/test/inspector_test.dart

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import 'package:dwds/src/debugging/inspector.dart';
1111
import 'package:dwds/src/utilities/conversions.dart';
1212
import 'package:test/test.dart';
1313
import 'package:test_common/test_sdk_configuration.dart';
14-
import 'package:test_common/utilities.dart';
1514
import 'package:vm_service/vm_service.dart';
1615
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
1716

@@ -161,10 +160,6 @@ void main() {
161160
final names =
162161
properties.map((p) => p.name).where((x) => x != '__proto__').toList();
163162
final expected = [
164-
if (dartSdkIsAtLeast(
165-
newDdcTypeSystemVersion,
166-
))
167-
'\$ti',
168163
'_privateField',
169164
'abstractField',
170165
'closure',

0 commit comments

Comments
 (0)