Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor record shape processing out of calculating record bound fields #2074

Merged
merged 4 commits into from
Apr 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dwds/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## 19.0.1-dev

- Do not show async frame errors on evaluation. - [#2073](https://github.com/dart-lang/webdev/pull/2073)
- Refactor code for presenting record instances. - [#2074](https://github.com/dart-lang/webdev/pull/2074)

## 19.0.0

Expand Down
94 changes: 60 additions & 34 deletions dwds/lib/src/debugging/instance.dart
Original file line number Diff line number Diff line change
Expand Up @@ -446,52 +446,32 @@ class InstanceHelper extends Domain {
.where((p) => p.name != null && int.tryParse(p.name!) != null)
.toList();

/// The fields for a Dart Record.
/// The field names for a Dart record shape.
///
/// Returns a range of [count] fields, if available, starting from
/// the [offset].
///
/// If [offset] is `null`, assumes 0 offset.
/// If [count] is `null`, return all fields starting from the offset.
Future<List<BoundField>> _recordFields(
RemoteObject record, {
/// The [shape] object describes the shape using `positionalCount`
/// and `named` fields.
///
/// Returns list of field names for the record shape.
Future<List<dynamic>> _recordShapeFields(
RemoteObject shape, {
int? offset,
int? count,
}) async {
// We do this in in awkward way because we want the keys and values, but we
// can't return things by value or some Dart objects will come back as
// values that we need to be RemoteObject, e.g. a List of int.
final expression = '''
function() {
var sdkUtils = ${globalLoadStrategy.loadModuleSnippet}('dart_sdk').dart;
var shape = sdkUtils.dloadRepl(this, "shape");
var positionalCount = sdkUtils.dloadRepl(shape, "positionals");
var named = sdkUtils.dloadRepl(shape, "named");
named = named == null? null: sdkUtils.dsendRepl(named, "toList", []);
var values = sdkUtils.dloadRepl(this, "values");
values = sdkUtils.dsendRepl(values, "toList", []);

return {
positionalCount: positionalCount,
named: named,
values: values
};
}
''';
final result = await inspector.jsCallFunctionOn(record, expression, []);
final positionalCountObject =
await inspector.loadField(result, 'positionalCount');
await inspector.loadField(shape, 'positionalCount');
if (positionalCountObject == null || positionalCountObject.value is! int) {
_logger.warning(
'Unexpected positional count from record: $positionalCountObject',
);
return [];
}

final namedObject = await inspector.loadField(result, 'named');
final valuesObject = await inspector.loadField(result, 'values');

// Collect positional fields in the requested range.
final namedObject = await inspector.loadField(shape, 'named');
final positionalCount = positionalCountObject.value as int;
final positionalOffset = offset ?? 0;
final positionalAvailable =
Expand Down Expand Up @@ -519,11 +499,49 @@ class InstanceHelper extends Domain {
final namedElements =
namedInstance?.elements?.map((e) => e.valueAsString) ?? [];

final fieldNameElements = [
return [
...positionalElements,
...namedElements,
];
}

/// The fields for a Dart Record.
///
/// Returns a range of [count] fields, if available, starting from
/// the [offset].
///
/// If [offset] is `null`, assumes 0 offset.
/// If [count] is `null`, return all fields starting from the offset.
Future<List<BoundField>> _recordFields(
RemoteObject record, {
int? offset,
int? count,
}) async {
// We do this in in awkward way because we want the keys and values, but we
// can't return things by value or some Dart objects will come back as
// values that we need to be RemoteObject, e.g. a List of int.
final expression = '''
function() {
var sdkUtils = ${globalLoadStrategy.loadModuleSnippet}('dart_sdk').dart;
var shape = sdkUtils.dloadRepl(this, "shape");
var positionalCount = sdkUtils.dloadRepl(shape, "positionals");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are the Repl versions of these dload calls used? The repl and regular versions should be identical because the fields are not private but it appears we are using the wrong version.

var named = sdkUtils.dloadRepl(shape, "named");
named = named == null? null: sdkUtils.dsendRepl(named, "toList", []);
var values = sdkUtils.dloadRepl(this, "values");
values = sdkUtils.dsendRepl(values, "toList", []);

return {
positionalCount: positionalCount,
named: named,
values: values
};
}
''';
final result = await inspector.jsCallFunctionOn(record, expression, []);
final fieldNameElements =
await _recordShapeFields(result, offset: offset, count: count);

final valuesObject = await inspector.loadField(result, 'values');
final valuesInstance =
await instanceFor(valuesObject, offset: offset, count: count);
final valueElements = valuesInstance?.elements ?? [];
Expand All @@ -533,11 +551,19 @@ class InstanceHelper extends Domain {
return [];
}

final fields = <BoundField>[];
Map.fromIterables(fieldNameElements, valueElements).forEach((key, value) {
fields.add(BoundField(name: key, value: value));
return _elementsToBoundFields(fieldNameElements, valueElements);
}

/// Create a list of `BoundField`s from field [names] and [values].
static List<BoundField> _elementsToBoundFields(
List<dynamic> names,
List<dynamic> values,
) {
final boundFields = <BoundField>[];
Map.fromIterables(names, values).forEach((name, value) {
boundFields.add(BoundField(name: name, value: value));
});
return fields;
return boundFields;
}

static int _remainingCount(int collected, int requested) {
Expand Down