[VM/Service] Add isGetter and isSetter properties to @Function and Function

TEST=pkg/vm_service/test/get_object_rpc_test.dart and
vm/cc/PrintJSONPrimitives

Fixes: https://github.com/dart-lang/sdk/issues/52920
Change-Id: Id3786e48c8827911e7c49af6ab2f0bf0cd97279f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/313642
Reviewed-by: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Derek Xu 2023-07-17 15:01:21 +00:00 committed by Commit Queue
parent ce5210bac9
commit 24e65bee37
10 changed files with 156 additions and 27 deletions

View file

@ -1 +1 @@
version=4.10
version=4.11

View file

@ -28,7 +28,7 @@ export 'snapshot_graph.dart'
HeapSnapshotObjectNoData,
HeapSnapshotObjectNullData;
const String vmServiceVersion = '4.10.0';
const String vmServiceVersion = '4.11.0';
/// @optional
const String optional = 'optional';
@ -5087,6 +5087,12 @@ class FuncRef extends ObjRef {
/// Is this function an abstract method?
bool? isAbstract;
/// Is this function a getter?
bool? isGetter;
/// Is this function a setter?
bool? isSetter;
/// The location of this function in the source code.
///
/// Note: this may not agree with the location of `owner` if this is a
@ -5102,6 +5108,8 @@ class FuncRef extends ObjRef {
this.isConst,
this.implicit,
this.isAbstract,
this.isGetter,
this.isSetter,
required String id,
this.location,
}) : super(
@ -5116,6 +5124,8 @@ class FuncRef extends ObjRef {
isConst = json['const'] ?? false;
implicit = json['implicit'] ?? false;
isAbstract = json['abstract'] ?? false;
isGetter = json['isGetter'] ?? false;
isSetter = json['isSetter'] ?? false;
location = createServiceObject(json['location'], const ['SourceLocation'])
as SourceLocation?;
}
@ -5134,6 +5144,8 @@ class FuncRef extends ObjRef {
'const': isConst ?? false,
'implicit': implicit ?? false,
'abstract': isAbstract ?? false,
'isGetter': isGetter ?? false,
'isSetter': isSetter ?? false,
});
_setIfNotNull(json, 'location', location?.toJson());
return json;
@ -5146,9 +5158,7 @@ class FuncRef extends ObjRef {
bool operator ==(Object other) => other is FuncRef && id == other.id;
@override
String toString() => '[FuncRef ' //
'id: $id, name: $name, owner: $owner, isStatic: $isStatic, ' //
'isConst: $isConst, implicit: $implicit, isAbstract: $isAbstract]';
String toString() => '[FuncRef]';
}
/// A `Func` represents a Dart language function.
@ -5186,6 +5196,14 @@ class Func extends Obj implements FuncRef {
@override
bool? isAbstract;
/// Is this function a getter?
@override
bool? isGetter;
/// Is this function a setter?
@override
bool? isSetter;
/// The location of this function in the source code.
///
/// Note: this may not agree with the location of `owner` if this is a
@ -5209,6 +5227,8 @@ class Func extends Obj implements FuncRef {
this.isConst,
this.implicit,
this.isAbstract,
this.isGetter,
this.isSetter,
this.signature,
required String id,
this.location,
@ -5225,6 +5245,8 @@ class Func extends Obj implements FuncRef {
isConst = json['const'] ?? false;
implicit = json['implicit'] ?? false;
isAbstract = json['abstract'] ?? false;
isGetter = json['isGetter'] ?? false;
isSetter = json['isSetter'] ?? false;
location = createServiceObject(json['location'], const ['SourceLocation'])
as SourceLocation?;
signature = createServiceObject(json['signature'], const ['InstanceRef'])
@ -5246,6 +5268,8 @@ class Func extends Obj implements FuncRef {
'const': isConst ?? false,
'implicit': implicit ?? false,
'abstract': isAbstract ?? false,
'isGetter': isGetter ?? false,
'isSetter': isSetter ?? false,
'signature': signature?.toJson(),
});
_setIfNotNull(json, 'location', location?.toJson());
@ -5260,9 +5284,7 @@ class Func extends Obj implements FuncRef {
bool operator ==(Object other) => other is Func && id == other.id;
@override
String toString() => '[Func ' //
'id: $id, name: $name, owner: $owner, isStatic: $isStatic, ' //
'isConst: $isConst, implicit: $implicit, isAbstract: $isAbstract, signature: $signature]';
String toString() => '[Func]';
}
/// `InstanceRef` is a reference to an `Instance`.

View file

@ -27,6 +27,8 @@ base class _DummyClass extends _DummyAbstractBaseClass {
static var dummyVarWithInit = foo();
late String dummyLateVarWithInit = 'bar';
late String dummyLateVar;
int get dummyVarGetter => dummyVar;
set dummyVarSetter(int value) => dummyVar = value;
@override
void dummyFunction(int a, [bool b = false]) {}
void dummyGenericFunction<K, V>(K a, {required V param}) {}
@ -904,7 +906,7 @@ var tests = <IsolateTest>[
expect(result.interfaces!.length, 0);
expect(result.mixin, isNull);
expect(result.fields!.length, 5);
expect(result.functions!.length, 10);
expect(result.functions!.length, 12);
expect(result.subclasses!.length, 2);
final json = result.json!;
expect(json['_vmName'], startsWith('_DummyClass@'));
@ -1262,7 +1264,8 @@ var tests = <IsolateTest>[
(VmService service, IsolateRef isolateRef) async {
final isolateId = isolateRef.id!;
final isolate = await service.getIsolate(isolateId);
// Call eval to get a class id.
// Call [invoke] to get an [InstanceRef], and then use the ID of its
// [classRef] field to build a function ID.
final evalResult = await service.invoke(
isolateId, isolate.rootLib!.id!, 'getDummyClass', []) as InstanceRef;
final objectId = "${evalResult.classRef!.id!}/functions/dummyFunction";
@ -1273,6 +1276,8 @@ var tests = <IsolateTest>[
expect(result.isConst, equals(false));
expect(result.implicit, equals(false));
expect(result.isAbstract, equals(false));
expect(result.isGetter, false);
expect(result.isSetter, false);
final signature = result.signature!;
expect(signature.typeParameters, isNull);
expect(signature.returnType, isNotNull);
@ -1297,7 +1302,8 @@ var tests = <IsolateTest>[
(VmService service, IsolateRef isolateRef) async {
final isolateId = isolateRef.id!;
final isolate = await service.getIsolate(isolateId);
// Call eval to get a class id.
// Call [invoke] to get an [InstanceRef], and then use the ID of its
// [classRef] field to build a function ID.
final evalResult = await service.invoke(
isolateId, isolate.rootLib!.id!, 'getDummyClass', []) as InstanceRef;
final objectId =
@ -1309,6 +1315,8 @@ var tests = <IsolateTest>[
expect(result.isConst, equals(false));
expect(result.implicit, equals(false));
expect(result.isAbstract, equals(false));
expect(result.isGetter, false);
expect(result.isSetter, false);
final signature = result.signature!;
expect(signature.typeParameters!.length, 2);
expect(signature.returnType, isNotNull);
@ -1362,6 +1370,8 @@ var tests = <IsolateTest>[
expect(funcResult.isConst, equals(false));
expect(funcResult.implicit, equals(false));
expect(funcResult.isAbstract, equals(true));
expect(funcResult.isGetter, false);
expect(funcResult.isSetter, false);
final signature = funcResult.signature!;
expect(signature.typeParameters, isNull);
expect(signature.returnType, isNotNull);
@ -1421,11 +1431,84 @@ var tests = <IsolateTest>[
expect(json['_guardLength'], isNotNull);
},
// getter
(VmService service, IsolateRef isolateRef) async {
final isolateId = isolateRef.id!;
final isolate = await service.getIsolate(isolateId);
// Call [invoke] to get an [InstanceRef], and then use the ID of its
// [classRef] field to build a function ID.
final evalResult = await service.invoke(
isolateId, isolate.rootLib!.id!, 'getDummyClass', []) as InstanceRef;
final objectId =
"${evalResult.classRef!.id!}/functions/get${Uri.encodeComponent(':')}dummyVarGetter";
final result = await service.getObject(isolateId, objectId) as Func;
expect(result.id, objectId);
expect(result.name, 'dummyVarGetter');
expect(result.isStatic, false);
expect(result.isConst, false);
expect(result.implicit, false);
expect(result.isAbstract, false);
expect(result.isGetter, true);
expect(result.isSetter, false);
final signature = result.signature!;
expect(signature.typeParameters, isNull);
expect(signature.returnType, isNotNull);
final parameters = signature.parameters!;
expect(parameters.length, 1);
expect(result.location, isNotNull);
expect(result.code, isNotNull);
final json = result.json!;
expect(json['_kind'], 'GetterFunction');
expect(json['_optimizable'], true);
expect(json['_inlinable'], true);
expect(json['_usageCounter'], 0);
expect(json['_optimizedCallSiteCount'], 0);
expect(json['_deoptimizations'], 0);
},
// setter
(VmService service, IsolateRef isolateRef) async {
final isolateId = isolateRef.id!;
final isolate = await service.getIsolate(isolateId);
// Call [invoke] to get an [InstanceRef], and then use the ID of its
// [classRef] field to build a function ID.
final evalResult = await service.invoke(
isolateId, isolate.rootLib!.id!, 'getDummyClass', []) as InstanceRef;
final objectId =
"${evalResult.classRef!.id!}/functions/set${Uri.encodeComponent(':')}dummyVarSetter";
final result = await service.getObject(isolateId, objectId) as Func;
expect(result.id, objectId);
expect(result.name, 'dummyVarSetter=');
expect(result.isStatic, false);
expect(result.isConst, false);
expect(result.implicit, false);
expect(result.isAbstract, false);
expect(result.isGetter, false);
expect(result.isSetter, true);
final signature = result.signature!;
expect(signature.typeParameters, isNull);
expect(signature.returnType, isNotNull);
final parameters = signature.parameters!;
expect(parameters.length, 2);
expect(parameters[1].parameterType!.name, equals('int'));
expect(parameters[1].fixed, isTrue);
expect(result.location, isNotNull);
expect(result.code, isNotNull);
final json = result.json!;
expect(json['_kind'], 'SetterFunction');
expect(json['_optimizable'], true);
expect(json['_inlinable'], true);
expect(json['_usageCounter'], 0);
expect(json['_optimizedCallSiteCount'], 0);
expect(json['_deoptimizations'], 0);
},
// static field initializer
(VmService service, IsolateRef isolateRef) async {
final isolateId = isolateRef.id!;
final isolate = await service.getIsolate(isolateId);
// Call eval to get a class id.
// Call [invoke] to get an [InstanceRef], and then use the ID of its
// [classRef] field to build a function ID.
final evalResult = await service.invoke(
isolateId, isolate.rootLib!.id!, 'getDummyClass', []) as InstanceRef;
final objectId = "${evalResult.classRef!.id!}/field_inits/dummyVarWithInit";
@ -1436,6 +1519,8 @@ var tests = <IsolateTest>[
expect(result.isConst, equals(false));
expect(result.implicit, equals(false));
expect(result.isAbstract, equals(false));
expect(result.isGetter, false);
expect(result.isSetter, false);
final signature = result.signature!;
expect(signature.typeParameters, isNull);
expect(signature.returnType, isNotNull);
@ -1455,7 +1540,8 @@ var tests = <IsolateTest>[
(VmService service, IsolateRef isolateRef) async {
final isolateId = isolateRef.id!;
final isolate = await service.getIsolate(isolateId);
// Call eval to get a class id.
// Call [invoke] to get an [InstanceRef], and then use the ID of its
// [classRef] field to build a function ID.
final evalResult = await service.invoke(
isolateId, isolate.rootLib!.id!, 'getDummyClass', []) as InstanceRef;
final objectId =
@ -1467,6 +1553,8 @@ var tests = <IsolateTest>[
expect(result.isConst, equals(false));
expect(result.implicit, equals(false));
expect(result.isAbstract, equals(false));
expect(result.isGetter, false);
expect(result.isSetter, false);
final signature = result.signature!;
expect(signature.typeParameters, isNull);
expect(signature.returnType, isNotNull);
@ -1547,9 +1635,11 @@ var tests = <IsolateTest>[
final isolateId = isolateRef.id!;
final isolate = await service.getIsolate(isolateId);
// Call eval to get a UserTag id.
final evalResult = await service.invoke(
isolateId, isolate.rootLib!.id!, 'getUserTag', []) as InstanceRef;
final result = await service.getObject(isolateId, evalResult.id!) as Instance;
final evalResult =
await service.invoke(isolateId, isolate.rootLib!.id!, 'getUserTag', [])
as InstanceRef;
final result =
await service.getObject(isolateId, evalResult.id!) as Instance;
expect(result.label, equals('Test Tag'));
},

View file

@ -12,7 +12,7 @@ var tests = <VMTest>[
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
expect(result['type'], 'Version');
expect(result['major'], 4);
expect(result['minor'], 10);
expect(result['minor'], 11);
expect(result['_privateMajor'], 0);
expect(result['_privateMinor'], 0);
},

View file

@ -12,7 +12,7 @@ var tests = <VMTest>[
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
expect(result['type'], equals('Version'));
expect(result['major'], equals(4));
expect(result['minor'], equals(10));
expect(result['minor'], equals(11));
expect(result['_privateMajor'], equals(0));
expect(result['_privateMinor'], equals(0));
},

View file

@ -371,6 +371,8 @@ void Function::PrintJSONImpl(JSONStream* stream, bool ref) const {
jsobj.AddProperty("abstract", is_abstract());
jsobj.AddProperty("_intrinsic", is_intrinsic());
jsobj.AddProperty("_native", is_native());
jsobj.AddProperty("isGetter", kind() == UntaggedFunction::kGetterFunction);
jsobj.AddProperty("isSetter", kind() == UntaggedFunction::kSetterFunction);
const Script& script = Script::Handle(this->script());
if (!script.IsNull()) {

View file

@ -6085,8 +6085,8 @@ ISOLATE_UNIT_TEST_CASE(PrintJSONPrimitives) {
"\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
"\"_kind\":\"RegularFunction\",\"static\":false,\"const\":false,"
"\"implicit\":false,\"abstract\":false,"
"\"_intrinsic\":false,\"_native\":false,"
"\"location\":{\"type\":\"SourceLocation\","
"\"_intrinsic\":false,\"_native\":false,\"isGetter\":false,"
"\"isSetter\":false,\"location\":{\"type\":\"SourceLocation\","
"\"script\":{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
"\"uri\":\"dart:core\\/bool.dart\",\"_kind\":\"kernel\"}}}",
buffer);

View file

@ -17,7 +17,7 @@
namespace dart {
#define SERVICE_PROTOCOL_MAJOR_VERSION 4
#define SERVICE_PROTOCOL_MINOR_VERSION 10
#define SERVICE_PROTOCOL_MINOR_VERSION 11
class Array;
class EmbedderServiceHandler;

View file

@ -1,8 +1,8 @@
# Dart VM Service Protocol 4.10
# Dart VM Service Protocol 4.11
> Please post feedback to the [observatory-discuss group][discuss-list]
This document describes of _version 4.9_ of the Dart VM Service Protocol. This
This document describes of _version 4.11_ of the Dart VM Service Protocol. This
protocol is used to communicate with a running Dart Virtual Machine.
To use the Service Protocol, start the VM with the *--observe* flag.
@ -2776,6 +2776,12 @@ class @Function extends @Object {
// Is this function an abstract method?
bool abstract;
// Is this function a getter?
bool isGetter;
// Is this function a setter?
bool isSetter;
// The location of this function in the source code.
//
// Note: this may not agree with the location of `owner` if this is a function
@ -2811,6 +2817,12 @@ class Function extends Object {
// Is this function an abstract method?
bool abstract;
// Is this function a getter?
bool isGetter;
// Is this function a setter?
bool isSetter;
// The location of this function in the source code.
//
// Note: this may not agree with the location of `owner` if this is a function
@ -4706,5 +4718,6 @@ version | comments
4.8 | Added `getIsolatePauseEvent` RPC.
4.9 | Added `isolateGroup` property to `Event`.
4.10 | Deprecated `isSyntheticAsyncContinuation` on `Breakpoint`.
4.11 | Added `isGetter` and `isSetter` properties to `@Function` and `Function`.
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss

View file

@ -604,7 +604,8 @@ ISOLATE_UNIT_TEST_CASE(SourceReport_CallSites_SimpleCall) {
"\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"},"
"\"_kind\":\"RegularFunction\",\"static\":true,\"const\":false,"
"\"implicit\":false,\"abstract\":false,"
"\"_intrinsic\":false,\"_native\":false,\"location\":{\"type\":"
"\"_intrinsic\":false,\"_native\":false,\"isGetter\":false,"
"\"isSetter\":false,\"location\":{\"type\":"
"\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
"\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
"\"tokenPos\":0,\"endTokenPos\":11,\"line\":1,\"column\":1}},\"count\":1}"
@ -689,7 +690,7 @@ ISOLATE_UNIT_TEST_CASE(SourceReport_CallSites_PolymorphicCall) {
"},\"_kind\":\"RegularFunction\","
"\"static\":false,\"const\":false,\"implicit\":false,\"abstract\":"
"false,\"_intrinsic\":false,"
"\"_native\":false,"
"\"_native\":false,\"isGetter\":false,\"isSetter\":false,"
"\"location\":{\"type\":\"SourceLocation\","
"\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
"\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\","
@ -725,7 +726,7 @@ ISOLATE_UNIT_TEST_CASE(SourceReport_CallSites_PolymorphicCall) {
"},\"_kind\":\"RegularFunction\","
"\"static\":false,\"const\":false,\"implicit\":false,\"abstract\":"
"false,\"_intrinsic\":false,"
"\"_native\":false,"
"\"_native\":false,\"isGetter\":false,\"isSetter\":false,"
"\"location\":{\"type\":\"SourceLocation\","
"\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
"\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\","
@ -783,7 +784,8 @@ ISOLATE_UNIT_TEST_CASE(SourceReport_MultipleReports) {
"\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"},\"_"
"kind\":\"RegularFunction\",\"static\":true,\"const\":false,\"implicit\":"
"false,\"abstract\":false,\"_"
"intrinsic\":false,\"_native\":false,\"location\":{\"type\":"
"intrinsic\":false,\"_native\":false,\"isGetter\":false,"
"\"isSetter\":false,\"location\":{\"type\":"
"\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
"\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
"\"tokenPos\":0,\"endTokenPos\":11,\"line\":1,\"column\":1}},\"count\":1}"