@@ -155,6 +155,14 @@ class InstanceHelper extends Domain {
155
155
count: count,
156
156
length: metaData.length,
157
157
);
158
+ } else if (metaData.isRecordType) {
159
+ return await _recordTypeInstanceFor (
160
+ classRef,
161
+ remoteObject,
162
+ offset: offset,
163
+ count: count,
164
+ length: metaData.length,
165
+ );
158
166
} else if (metaData.isSet) {
159
167
return await _setInstanceFor (
160
168
classRef,
@@ -416,16 +424,16 @@ class InstanceHelper extends Domain {
416
424
int ? count,
417
425
int ? length,
418
426
}) async {
419
- // Filter out all non-indexed properties
420
- final elements = _indexedListProperties (
421
- await debugger.getProperties (
422
- list.objectId! ,
423
- offset: offset,
424
- count: count,
425
- length: length,
426
- ),
427
+ final properties = await debugger.getProperties (
428
+ list.objectId! ,
429
+ offset: offset,
430
+ count: count,
431
+ length: length,
427
432
);
428
433
434
+ // Filter out all non-indexed properties
435
+ final elements = _indexedListProperties (properties);
436
+
429
437
final rangeCount = _calculateRangeCount (
430
438
count: count,
431
439
elementCount: elements.length,
@@ -546,19 +554,19 @@ class InstanceHelper extends Domain {
546
554
await instanceFor (valuesObject, offset: offset, count: count);
547
555
final valueElements = valuesInstance? .elements ?? [];
548
556
549
- if (fieldNameElements.length != valueElements.length) {
550
- _logger.warning ('Record fields and values are not the same length.' );
551
- return [];
552
- }
553
-
554
557
return _elementsToBoundFields (fieldNameElements, valueElements);
555
558
}
556
559
557
560
/// Create a list of `BoundField` s from field [names] and [values] .
558
- static List <BoundField > _elementsToBoundFields (
561
+ List <BoundField > _elementsToBoundFields (
559
562
List <dynamic > names,
560
563
List <dynamic > values,
561
564
) {
565
+ if (names.length != values.length) {
566
+ _logger.warning ('Bound field names and values are not the same length.' );
567
+ return [];
568
+ }
569
+
562
570
final boundFields = < BoundField > [];
563
571
Map .fromIterables (names, values).forEach ((name, value) {
564
572
boundFields.add (BoundField (name: name, value: value));
@@ -608,6 +616,89 @@ class InstanceHelper extends Domain {
608
616
..fields = fields;
609
617
}
610
618
619
+ /// Create a RecordType instance with class [classRef] from [remoteObject] .
620
+ ///
621
+ /// Returns an instance containing [count] fields, if available,
622
+ /// starting from the [offset] .
623
+ ///
624
+ /// If [offset] is `null` , assumes 0 offset.
625
+ /// If [count] is `null` , return all fields starting from the offset.
626
+ /// [length] is the expected length of the whole object, read from
627
+ /// the [ClassMetaData] .
628
+ Future <Instance ?> _recordTypeInstanceFor (
629
+ ClassRef classRef,
630
+ RemoteObject remoteObject, {
631
+ int ? offset,
632
+ int ? count,
633
+ int ? length,
634
+ }) async {
635
+ final objectId = remoteObject.objectId;
636
+ if (objectId == null ) return null ;
637
+ // Records are complicated, do an eval to get names and values.
638
+ final fields =
639
+ await _recordTypeFields (remoteObject, offset: offset, count: count);
640
+ final rangeCount = _calculateRangeCount (
641
+ count: count,
642
+ elementCount: fields.length,
643
+ length: length,
644
+ );
645
+ return Instance (
646
+ identityHashCode: remoteObject.objectId.hashCode,
647
+ kind: InstanceKind .kRecordType,
648
+ id: objectId,
649
+ classRef: classRef,
650
+ )
651
+ ..length = length
652
+ ..offset = offset
653
+ ..count = rangeCount
654
+ ..fields = fields;
655
+ }
656
+
657
+ /// The field types for a Dart RecordType.
658
+ ///
659
+ /// Returns a range of [count] field types, if available, starting from
660
+ /// the [offset] .
661
+ ///
662
+ /// If [offset] is `null` , assumes 0 offset.
663
+ /// If [count] is `null` , return all field types starting from the offset.
664
+ Future <List <BoundField >> _recordTypeFields (
665
+ RemoteObject record, {
666
+ int ? offset,
667
+ int ? count,
668
+ }) async {
669
+ // We do this in in awkward way because we want the names and types, but we
670
+ // can't return things by value or some Dart objects will come back as
671
+ // values that we need to be RemoteObject, e.g. a List of int.
672
+ final expression = '''
673
+ function() {
674
+ var sdkUtils = ${globalLoadStrategy .loadModuleSnippet }('dart_sdk').dart;
675
+ var shape = sdkUtils.dloadRepl(this, "shape");
676
+ var positionalCount = sdkUtils.dloadRepl(shape, "positionals");
677
+ var named = sdkUtils.dloadRepl(shape, "named");
678
+ named = named == null? null: sdkUtils.dsendRepl(named, "toList", []);
679
+ var types = sdkUtils.dloadRepl(this, "types");
680
+ types = types.map(t => sdkUtils.wrapType(t));
681
+ types = sdkUtils.dsendRepl(types, "toList", []);
682
+
683
+ return {
684
+ positionalCount: positionalCount,
685
+ named: named,
686
+ types: types
687
+ };
688
+ }
689
+ ''' ;
690
+ final result = await inspector.jsCallFunctionOn (record, expression, []);
691
+ final fieldNameElements =
692
+ await _recordShapeFields (result, offset: offset, count: count);
693
+
694
+ final typesObject = await inspector.loadField (result, 'types' );
695
+ final typesInstance =
696
+ await instanceFor (typesObject, offset: offset, count: count);
697
+ final typeElements = typesInstance? .elements ?? [];
698
+
699
+ return _elementsToBoundFields (fieldNameElements, typeElements);
700
+ }
701
+
611
702
Future <Instance ?> _setInstanceFor (
612
703
ClassRef classRef,
613
704
RemoteObject remoteObject, {
@@ -801,6 +892,14 @@ class InstanceHelper extends Domain {
801
892
classRef: metaData.classRef,
802
893
)..length = metaData.length;
803
894
}
895
+ if (metaData.isRecordType) {
896
+ return InstanceRef (
897
+ kind: InstanceKind .kRecordType,
898
+ id: objectId,
899
+ identityHashCode: remoteObject.objectId.hashCode,
900
+ classRef: metaData.classRef,
901
+ )..length = metaData.length;
902
+ }
804
903
if (metaData.isSet) {
805
904
return InstanceRef (
806
905
kind: InstanceKind .kSet,
0 commit comments