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

Use DDC runtime debugger API #2159

Merged
merged 30 commits into from
Aug 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
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
200 changes: 100 additions & 100 deletions .github/workflows/dart.yml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dwds/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Require clients to specify the `basePath` on `AssetReader`. - [#2160](https://github.com/dart-lang/webdev/pull/2160)
- Update SDK constraint to `>=3.1.0-254.0.dev <4.0.0`. - [#2169](https://github.com/dart-lang/webdev/pull/2169)
- Require min `build_web_compilers` version `4.0.4` - [#2171](https://github.com/dart-lang/webdev/pull/2171)
- Switch to using new debugging API from DDC to support new type system. - [#2159](https://github.com/dart-lang/webdev/pull/2159)

## 19.0.2

Expand Down
2 changes: 1 addition & 1 deletion dwds/debug_extension/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: >-
A chrome extension for Dart debugging.
environment:
sdk: ">=3.1.0-254.0.dev <4.0.0"
sdk: ">=3.1.0-340.0.dev <4.0.0"

dependencies:
async: ^2.3.0
Expand Down
2 changes: 1 addition & 1 deletion dwds/debug_extension_mv3/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: >-
A Chrome extension for Dart debugging.
environment:
sdk: ">=3.1.0-254.0.dev <4.0.0"
sdk: ">=3.1.0-340.0.dev <4.0.0"

dependencies:
built_value: ^8.3.0
Expand Down
139 changes: 24 additions & 115 deletions dwds/lib/src/debugging/classes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,88 +77,12 @@ class ClassHelper extends Domain {

if (libraryUri == null || classId == null || className == null) return null;

final rawName = className.split('<').first;
final expression = '''
(function() {
${globalLoadStrategy.loadLibrarySnippet(libraryUri)}
var result = {};
var clazz = library["$rawName"];
var descriptor = {
'name': clazz.name,
'dartName': sdkUtils.typeName(clazz)
};

// TODO(grouma) - we display all inherited methods since we don't provide
// the superClass information. This is technically not correct.
var proto = clazz.prototype;
var methodNames = [];
for (; proto != null; proto = Object.getPrototypeOf(proto)) {
var methods = Object.getOwnPropertyNames(proto);
for (var i = 0; i < methods.length; i++) {
if (methodNames.indexOf(methods[i]) == -1
&& methods[i] != 'constructor') {
methodNames.push(methods[i]);
}
}
if (proto.constructor.name == 'Object') break;
}

descriptor['methods'] = {};
for (var name of methodNames) {
descriptor['methods'][name] = {
// TODO(jakemac): how can we get actual const info?
"isConst": false,
"isStatic": false,
}
}

var fields = sdkUtils.getFields(clazz);
var fieldNames = fields ? Object.keys(fields) : [];
descriptor['fields'] = {};
for (var name of fieldNames) {
var field = fields[name];
var libraryUri = Object.getOwnPropertySymbols(fields[name]["type"])
.find(x => x.description == "libraryUri");
descriptor['fields'][name] = {
// TODO(jakemac): how can we get actual const info?
"isConst": false,
"isFinal": field.isFinal,
"isStatic": false,
"classRefName": fields[name]["type"]["name"],
"classRefDartName": sdkUtils.typeName(fields[name]["type"]),
"classRefLibraryId" : field["type"][libraryUri],
}
}

// TODO(elliette): The following static member information is minimal and
// should be replaced once DDC provides full symbol information (see
// https://github.com/dart-lang/sdk/issues/40273):

descriptor['staticFields'] = {};
var staticFieldNames = sdkUtils.getStaticFields(clazz) ?? [];
for (const name of staticFieldNames) {
descriptor['staticFields'][name] = {
"isStatic": true,
// DDC only provides names of static members, we set isConst/isFinal
// to false even though they could be true.
"isConst": false,
"isFinal": false,
}
}

descriptor['staticMethods'] = {};
var staticMethodNames = sdkUtils.getStaticMethods(clazz) ?? [];
for (var name of staticMethodNames) {
descriptor['methods'][name] = {
// DDC only provides names of static members, we set isConst
// to false even though it could be true.
"isConst": false,
"isStatic": true,
}
}

return descriptor;
})()
(function() {
const sdk = ${globalLoadStrategy.loadModuleSnippet}('dart_sdk');
const dart = sdk.dart;
return dart.getClassMetadata('$libraryUri', '$className');
})()
''';

RemoteObject result;
Expand All @@ -176,35 +100,34 @@ class ClassHelper extends Domain {
final methodRefs = <FuncRef>[];
final methodDescriptors =
classDescriptor['methods'] as Map<String, dynamic>;
final staticMethodDescriptors =
classDescriptor['staticMethods'] as Map<String, dynamic>;
methodDescriptors.addAll(staticMethodDescriptors);
methodDescriptors.forEach((name, descriptor) {
final methodId = 'methods|$classId|$name';
methodRefs.add(
FuncRef(
id: methodId,
name: name,
owner: classRef,
isConst: descriptor['isConst'] as bool,
isStatic: descriptor['isStatic'] as bool,
// TODO(annagrin): get information about getters and setters from symbols.
// https://github.com/dart-lang/sdk/issues/46723
implicit: false,
isConst: descriptor['isConst'] as bool? ?? false,
isStatic: descriptor['isStatic'] as bool? ?? false,
implicit: descriptor['isImplicit'] as bool? ?? false,
isAbstract: descriptor['isAbstract'] as bool? ?? false,
isGetter: descriptor['isGetter'] as bool? ?? false,
isSetter: descriptor['isSetter'] as bool? ?? false,
),
);
});
final fieldRefs = <FieldRef>[];

final fieldDescriptors = classDescriptor['fields'] as Map<String, dynamic>;
fieldDescriptors.forEach((name, descriptor) {
final classMetaData = ClassMetaData(
jsName: descriptor['classRefName'],
runtimeKind: RuntimeObjectKind.type,
classRef: classRefFor(
descriptor['classRefLibraryId'],
descriptor['classRefDartName'],
descriptor['classLibraryId'],
descriptor['className'],
),
);

fieldRefs.add(
FieldRef(
name: name,
Expand All @@ -215,34 +138,19 @@ class ClassHelper extends Domain {
kind: classMetaData.kind,
classRef: classMetaData.classRef,
),
isConst: descriptor['isConst'] as bool,
isFinal: descriptor['isFinal'] as bool,
isStatic: descriptor['isStatic'] as bool,
isConst: descriptor['isConst'] as bool? ?? false,
isFinal: descriptor['isFinal'] as bool? ?? false,
isStatic: descriptor['isStatic'] as bool? ?? false,
id: createId(),
),
);
});

final staticFieldDescriptors =
classDescriptor['staticFields'] as Map<String, dynamic>;
staticFieldDescriptors.forEach((name, descriptor) {
fieldRefs.add(
FieldRef(
name: name,
owner: classRef,
declaredType: InstanceRef(
identityHashCode: createId().hashCode,
id: createId(),
kind: InstanceKind.kType,
classRef: classRef,
),
isConst: descriptor['isConst'] as bool,
isFinal: descriptor['isFinal'] as bool,
isStatic: descriptor['isStatic'] as bool,
id: createId(),
),
);
});
final superClassLibraryId = classDescriptor['superClassLibraryId'];
final superClassName = classDescriptor['superClassName'];
final superClassRef = superClassName == null
? null
: classRefFor(superClassLibraryId, superClassName);

// TODO: Implement the rest of these
// https://github.com/dart-lang/webdev/issues/176.
Expand All @@ -257,6 +165,7 @@ class ClassHelper extends Domain {
subclasses: [],
id: classId,
traceAllocations: false,
superClass: superClassRef,
);
}
}
47 changes: 16 additions & 31 deletions dwds/lib/src/debugging/inspector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -349,11 +349,14 @@ class AppInspector implements AppInspectorInterface {
throwInvalidParam('invoke', 'library uri is null');
}
final findLibrary = '''
(function() {
${globalLoadStrategy.loadLibrarySnippet(libraryUri)};
return library;
})();
''';
(function() {
const sdk = ${globalLoadStrategy.loadModuleSnippet}('dart_sdk');
const dart = sdk.dart;
const library = dart.getLibrary('$libraryUri');
if (!library) throw 'cannot find library for $libraryUri';
return library;
})();
''';
final remoteLibrary = await jsEvaluate(findLibrary);
return jsCallFunctionOn(remoteLibrary, jsFunction, arguments);
}
Expand Down Expand Up @@ -601,15 +604,6 @@ class AppInspector implements AppInspectorInterface {
.toList();
}

/// Compute the last possible element index in the range of [offset]..end
/// that includes [count] elements, if available.
static int? _calculateRangeEnd({
int? count,
required int offset,
required int length,
}) =>
count == null ? null : math.min(offset + count, length);

/// Calculate the number of available elements in the range.
static int _calculateRangeCount({
int? count,
Expand All @@ -634,30 +628,21 @@ class AppInspector implements AppInspectorInterface {
// TODO(#809): Sometimes we already know the type of the object, and
// we could take advantage of that to short-circuit.
final receiver = remoteObjectFor(id);
final end =
_calculateRangeEnd(count: count, offset: offset, length: length);
final rangeCount =
_calculateRangeCount(count: count, offset: offset, length: length);
final args =
[offset, rangeCount, end].map(dartIdFor).map(remoteObjectFor).toList();
[offset, rangeCount].map(dartIdFor).map(remoteObjectFor).toList();
// If this is a List, just call sublist. If it's a Map, get the entries, but
// avoid doing a toList on a large map using skip/take to get the section we
// want. To make those alternatives easier in JS, pass both count and end.
final expression = '''
function (offset, count, end) {
const sdk = ${globalLoadStrategy.loadModuleSnippet}("dart_sdk");
if (sdk.core.Map.is(this)) {
const entries = sdk.dart.dload(this, "entries");
const skipped = sdk.dart.dsend(entries, "skip", [offset])
const taken = sdk.dart.dsend(skipped, "take", [count]);
return sdk.dart.dsend(taken, "toList", []);
} else if (sdk.core.List.is(this)) {
return sdk.dart.dsendRepl(this, "sublist", [offset, end]);
} else {
return this;
}
}
''';
function (offset, count) {
const sdk = ${globalLoadStrategy.loadModuleSnippet}("dart_sdk");
const dart = sdk.dart;
return dart.getSubRange(this, offset, count);
}
''';

return await jsCallFunctionOn(receiver, expression, args);
}

Expand Down
Loading
Loading