[3.0 alpha][VM/Service] Update VM Service spec to v4.0

This is a reland of commit c21f7c847c,
BUT the `setExceptionPauseMode` procedure is no longer deleted in this
commit. We are not ready to delete that procedure yet, because deleting
it breaks IDE support: https://github.com/flutter/flutter/issues/117526.

TEST=CI

Original change's description:
> [3.0 alpha][VM/Service] Update VM Service spec to v4.0
>
> This CL updates the VM Service spec to version 4.0 in order to add
> support for records. Some deprecated procedures and properties will also
> be removed in v4.0.
>
> As described in service.md's changelog, this CL:
> Adds `Record` and `RecordType` `InstanceKind`s, adds a deprecation
> notice to the `decl` property of `BoundField`, adds `name` property to
> `BoundField`, adds a deprecation notice to the `parentListIndex`
> property of `InboundReference`, changes the type of the `parentField`
> property of `InboundReference` from `@Field` to `@Field|string|int`,
> adds a deprecation notice to the `parentListIndex` property of
> `RetainingObject`, changes the type of the `parentField` property of
> `RetainingObject` from `string` to `string|int`, removes the deprecated
> `setExceptionPauseMode` procedure, removes the deprecated `timeSpan`
> property from `CpuSamples`, and removes the deprecated `timeSpan`
> property from `CpuSamplesEvent.
>
> TEST=CI
>
> Issue: https://github.com/dart-lang/sdk/issues/49725
> Change-Id: I7bf61c1ba11a0c7fd95a10c9c02c14282062b802
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/268521
> Commit-Queue: Derek Xu <derekx@google.com>
> Reviewed-by: Ben Konyi <bkonyi@google.com>

Change-Id: Ieb96d426b622745e653afd6ca8c9718b1deae0a1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/278160
Commit-Queue: Derek Xu <derekx@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Derek Xu 2023-01-03 16:16:18 +00:00 committed by Commit Queue
parent 2bb495462b
commit e738858aae
18 changed files with 134 additions and 107 deletions

View file

@ -200,7 +200,6 @@ class CachedCpuSamples extends CpuSamples {
required int? samplePeriod,
required int? maxStackDepth,
required int? sampleCount,
required int? timeSpan,
required int? timeOriginMicros,
required int? timeExtentMicros,
required int? pid,
@ -210,7 +209,6 @@ class CachedCpuSamples extends CpuSamples {
samplePeriod: samplePeriod,
maxStackDepth: maxStackDepth,
sampleCount: sampleCount,
timeSpan: timeSpan,
timeOriginMicros: timeOriginMicros,
timeExtentMicros: timeExtentMicros,
pid: pid,
@ -225,7 +223,6 @@ class CachedCpuSamples extends CpuSamples {
samplePeriod: json['samplePeriod'] ?? -1,
maxStackDepth: json['maxStackDepth'] ?? -1,
sampleCount: json['sampleCount'] ?? -1,
timeSpan: json['timeSpan'] ?? -1,
timeOriginMicros: json['timeOriginMicros'] ?? -1,
timeExtentMicros: json['timeExtentMicros'] ?? -1,
pid: json['pid'] ?? -1,

View file

@ -587,17 +587,17 @@ public class VmServiceTest {
private static void vmPauseOnException(IsolateRef isolate, ExceptionPauseMode mode) {
System.out.println("Request pause on exception: " + mode);
final OpLatch latch = new OpLatch();
vmService.setExceptionPauseMode(isolate.getId(), mode, new SuccessConsumer() {
@Override
public void onError(RPCError error) {
showRPCError(error);
}
vmService.setIsolatePauseMode(isolate.getId(), mode, new SuccessConsumer() {
@Override
public void onError(RPCError error) {
showRPCError(error);
}
@Override
public void received(Success response) {
System.out.println("Successfully set pause on exception");
latch.opComplete();
}
@Override
public void received(Success response) {
System.out.println("Successfully set pause on exception");
latch.opComplete();
}
});
latch.waitAndAssertOpComplete();
}

View file

@ -1 +1 @@
version=3.62
version=4.0

View file

@ -26,7 +26,7 @@ export 'snapshot_graph.dart'
HeapSnapshotObjectNoData,
HeapSnapshotObjectNullData;
const String vmServiceVersion = '3.62.0';
const String vmServiceVersion = '4.0.0';
/// @optional
const String optional = 'optional';
@ -1101,9 +1101,6 @@ abstract class VmServiceInterface {
/// The `shouldPauseOnExit` parameter specify whether the target isolate
/// should pause on exit.
///
/// The `setExceptionPauseMode` RPC is used to control if an isolate pauses
/// when an exception is thrown.
///
/// mode | meaning
/// ---- | -------
/// None | Do not pause isolate on thrown exceptions
@ -2717,6 +2714,9 @@ class InstanceKind {
static const String kFloat32x4List = 'Float32x4List';
static const String kFloat64x2List = 'Float64x2List';
/// An instance of the Dart class Record.
static const String kRecord = 'Record';
/// An instance of the Dart class StackTrace.
static const String kStackTrace = 'StackTrace';
@ -2748,6 +2748,9 @@ class InstanceKind {
/// An instance of the Dart class FunctionType.
static const String kFunctionType = 'FunctionType';
/// An instance of the Dart class RecordType.
static const String kRecordType = 'RecordType';
/// An instance of the Dart class BoundedType.
static const String kBoundedType = 'BoundedType';
@ -2907,18 +2910,29 @@ class BoundField {
static BoundField? parse(Map<String, dynamic>? json) =>
json == null ? null : BoundField._fromJson(json);
/// Provided for fields of instances that are NOT of the following instance
/// kinds:
/// - Record
///
/// Note: this property is deprecated and will be replaced by `name`.
FieldRef? decl;
/// [name] can be one of [String] or [int].
dynamic name;
/// [value] can be one of [InstanceRef] or [Sentinel].
dynamic value;
BoundField({
this.decl,
this.name,
this.value,
});
BoundField._fromJson(Map<String, dynamic> json) {
decl = createServiceObject(json['decl'], const ['FieldRef']) as FieldRef?;
name =
createServiceObject(json['name'], const ['String', 'int']) as dynamic;
value =
createServiceObject(json['value'], const ['InstanceRef', 'Sentinel'])
as dynamic;
@ -2928,12 +2942,14 @@ class BoundField {
final json = <String, dynamic>{};
json.addAll({
'decl': decl?.toJson(),
'name': name?.toJson(),
'value': value?.toJson(),
});
return json;
}
String toString() => '[BoundField decl: ${decl}, value: ${value}]';
String toString() =>
'[BoundField decl: ${decl}, name: ${name}, value: ${value}]';
}
/// A `BoundVariable` represents a local variable bound to a particular value in
@ -3626,13 +3642,6 @@ class CpuSamples extends Response {
/// The number of samples returned.
int? sampleCount;
/// The timespan the set of returned samples covers, in microseconds
/// (deprecated).
///
/// Note: this property is deprecated and will always return -1. Use
/// `timeExtentMicros` instead.
int? timeSpan;
/// The start of the period of time in which the returned samples were
/// collected.
int? timeOriginMicros;
@ -3656,7 +3665,6 @@ class CpuSamples extends Response {
this.samplePeriod,
this.maxStackDepth,
this.sampleCount,
this.timeSpan,
this.timeOriginMicros,
this.timeExtentMicros,
this.pid,
@ -3668,7 +3676,6 @@ class CpuSamples extends Response {
samplePeriod = json['samplePeriod'] ?? -1;
maxStackDepth = json['maxStackDepth'] ?? -1;
sampleCount = json['sampleCount'] ?? -1;
timeSpan = json['timeSpan'] ?? -1;
timeOriginMicros = json['timeOriginMicros'] ?? -1;
timeExtentMicros = json['timeExtentMicros'] ?? -1;
pid = json['pid'] ?? -1;
@ -3692,7 +3699,6 @@ class CpuSamples extends Response {
'samplePeriod': samplePeriod ?? -1,
'maxStackDepth': maxStackDepth ?? -1,
'sampleCount': sampleCount ?? -1,
'timeSpan': timeSpan ?? -1,
'timeOriginMicros': timeOriginMicros ?? -1,
'timeExtentMicros': timeExtentMicros ?? -1,
'pid': pid ?? -1,
@ -3702,7 +3708,9 @@ class CpuSamples extends Response {
return json;
}
String toString() => '[CpuSamples]';
String toString() => '[CpuSamples ' //
'samplePeriod: ${samplePeriod}, maxStackDepth: ${maxStackDepth}, ' //
'sampleCount: ${sampleCount}, timeOriginMicros: ${timeOriginMicros}, timeExtentMicros: ${timeExtentMicros}, pid: ${pid}, functions: ${functions}, samples: ${samples}]';
}
class CpuSamplesEvent {
@ -3718,13 +3726,6 @@ class CpuSamplesEvent {
/// The number of samples returned.
int? sampleCount;
/// The timespan the set of returned samples covers, in microseconds
/// (deprecated).
///
/// Note: this property is deprecated and will always return -1. Use
/// `timeExtentMicros` instead.
int? timeSpan;
/// The start of the period of time in which the returned samples were
/// collected.
int? timeOriginMicros;
@ -3748,7 +3749,6 @@ class CpuSamplesEvent {
this.samplePeriod,
this.maxStackDepth,
this.sampleCount,
this.timeSpan,
this.timeOriginMicros,
this.timeExtentMicros,
this.pid,
@ -3760,7 +3760,6 @@ class CpuSamplesEvent {
samplePeriod = json['samplePeriod'] ?? -1;
maxStackDepth = json['maxStackDepth'] ?? -1;
sampleCount = json['sampleCount'] ?? -1;
timeSpan = json['timeSpan'] ?? -1;
timeOriginMicros = json['timeOriginMicros'] ?? -1;
timeExtentMicros = json['timeExtentMicros'] ?? -1;
pid = json['pid'] ?? -1;
@ -3778,7 +3777,6 @@ class CpuSamplesEvent {
'samplePeriod': samplePeriod ?? -1,
'maxStackDepth': maxStackDepth ?? -1,
'sampleCount': sampleCount ?? -1,
'timeSpan': timeSpan ?? -1,
'timeOriginMicros': timeOriginMicros ?? -1,
'timeExtentMicros': timeExtentMicros ?? -1,
'pid': pid ?? -1,
@ -3788,7 +3786,9 @@ class CpuSamplesEvent {
return json;
}
String toString() => '[CpuSamplesEvent]';
String toString() => '[CpuSamplesEvent ' //
'samplePeriod: ${samplePeriod}, maxStackDepth: ${maxStackDepth}, ' //
'sampleCount: ${sampleCount}, timeOriginMicros: ${timeOriginMicros}, timeExtentMicros: ${timeExtentMicros}, pid: ${pid}, functions: ${functions}, samples: ${samples}]';
}
/// See [getCpuSamples] and [CpuSamples].
@ -6023,15 +6023,24 @@ class InboundReference {
/// The object holding the inbound reference.
ObjRef? source;
/// If source is a List, parentListIndex is the index of the inbound
/// reference.
/// If source is a List, parentListIndex is the index of the inbound reference
/// (deprecated).
///
/// Note: this property is deprecated and will be replaced by `parentField`.
@optional
int? parentListIndex;
/// If source is a field of an object, parentField is the field containing the
/// inbound reference.
/// If `source` is a `List`, `parentField` is the index of the inbound
/// reference. If `source` is a record, `parentField` is the field name of the
/// inbound reference. If `source` is an instance of any other kind,
/// `parentField` is the field containing the inbound reference.
///
/// Note: In v5.0 of the spec, `@Field` will no longer be a part of this
/// property's type, i.e. the type will become `string|int`.
///
/// [parentField] can be one of [FieldRef], [String] or [int].
@optional
FieldRef? parentField;
dynamic parentField;
InboundReference({
this.source,
@ -6042,8 +6051,8 @@ class InboundReference {
InboundReference._fromJson(Map<String, dynamic> json) {
source = createServiceObject(json['source'], const ['ObjRef']) as ObjRef?;
parentListIndex = json['parentListIndex'];
parentField = createServiceObject(json['parentField'], const ['FieldRef'])
as FieldRef?;
parentField = createServiceObject(
json['parentField'], const ['FieldRef', 'String', 'int']) as dynamic;
}
Map<String, dynamic> toJson() {
@ -7141,7 +7150,9 @@ class RetainingObject {
ObjRef? value;
/// If `value` is a List, `parentListIndex` is the index where the previous
/// object on the retaining path is located.
/// object on the retaining path is located (deprecated).
///
/// Note: this property is deprecated and will be replaced by `parentField`.
@optional
int? parentListIndex;
@ -7152,8 +7163,10 @@ class RetainingObject {
/// If `value` is a non-List, non-Map object, `parentField` is the name of the
/// field containing the previous object on the retaining path.
///
/// [parentField] can be one of [String] or [int].
@optional
String? parentField;
dynamic parentField;
RetainingObject({
this.value,
@ -7167,7 +7180,9 @@ class RetainingObject {
parentListIndex = json['parentListIndex'];
parentMapKey =
createServiceObject(json['parentMapKey'], const ['ObjRef']) as ObjRef?;
parentField = json['parentField'];
parentField =
createServiceObject(json['parentField'], const ['String', 'int'])
as dynamic;
}
Map<String, dynamic> toJson() {
@ -7177,7 +7192,7 @@ class RetainingObject {
});
_setIfNotNull(json, 'parentListIndex', parentListIndex);
_setIfNotNull(json, 'parentMapKey', parentMapKey?.toJson());
_setIfNotNull(json, 'parentField', parentField);
_setIfNotNull(json, 'parentField', parentField?.toJson());
return json;
}

View file

@ -7,6 +7,7 @@
library get_object_rpc_test;
import 'dart:collection';
import 'dart:convert' show base64Decode;
import 'dart:typed_data';
@ -693,19 +694,23 @@ var tests = <IsolateTest>[
as InstanceRef;
final objectId = evalResult.id!;
final result = await service.getObject(isolateId, objectId) as Instance;
expect(result.kind, '_Record');
expect(result.kind, InstanceKind.kRecord);
expect(result.json!['_vmType'], 'Record');
expect(result.id, startsWith('objects/'));
expect(result.valueAsString, isNull);
expect(result.classRef!.name, '_Record');
expect(result.size, isPositive);
final fields = result.fields!;
expect(fields.length, 4);
// TODO(derekx): Include field names in this test once they are accessible
// through package:vm_service.
Set<String> fieldValues =
Set.from(fields.map((f) => f.value.valueAsString));
expect(fieldValues.containsAll(['1', '2', '3.0', '4.0']), true);
final fieldsMap = HashMap.fromEntries(
result.fields!.map((f) => MapEntry(f.name, f.value)));
expect(fieldsMap.keys.length, 4);
expect(fieldsMap.containsKey(0), true);
expect(fieldsMap[0].valueAsString, '1');
expect(fieldsMap.containsKey("x"), true);
expect(fieldsMap["x"].valueAsString, '2');
expect(fieldsMap.containsKey(1), true);
expect(fieldsMap[1].valueAsString, '3.0');
expect(fieldsMap.containsKey("y"), true);
expect(fieldsMap["y"].valueAsString, '4.0');
},
// library.

View file

@ -637,7 +637,7 @@ class SetCommand extends DebuggerCommand {
};
static Future _setBreakOnException(debugger, name, value) async {
var result = await debugger.isolate.setExceptionPauseMode(value);
var result = await debugger.isolate.setIsolatePauseMode(value);
if (result.isError) {
debugger.console.print(result.toString());
} else {

View file

@ -1886,8 +1886,8 @@ class Isolate extends ServiceObjectOwner implements M.Isolate {
return invokeRpc('setName', {'name': newName});
}
Future setExceptionPauseMode(String mode) {
return invokeRpc('setExceptionPauseMode', {'mode': mode});
Future setIsolatePauseMode(String mode) {
return invokeRpc('setIsolatePauseMode', {'exceptionPauseMode': mode});
}
Future<ServiceMap> getStack({int? limit}) {

View file

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

View file

@ -52,8 +52,8 @@ var tests = <IsolateTest>[
bool shouldBeCaught) async {
print("Evaluating $expression with pause on $pauseMode exception");
expect((await isolate.setExceptionPauseMode(pauseMode)) is DartError,
isFalse);
expect(
(await isolate.setIsolatePauseMode(pauseMode)) is DartError, isFalse);
var t;
if (shouldPause) {

View file

@ -632,7 +632,7 @@ class SetCommand extends DebuggerCommand {
};
static Future _setBreakOnException(debugger, name, value) async {
var result = await debugger.isolate.setExceptionPauseMode(value);
var result = await debugger.isolate.setIsolatePauseMode(value);
if (result.isError) {
debugger.console.print(result.toString());
} else {

View file

@ -1894,8 +1894,8 @@ class Isolate extends ServiceObjectOwner implements M.Isolate {
return invokeRpc('setName', {'name': newName});
}
Future setExceptionPauseMode(String mode) {
return invokeRpc('setExceptionPauseMode', {'mode': mode});
Future setIsolatePauseMode(String mode) {
return invokeRpc('setIsolatePauseMode', {'exceptionPauseMode': mode});
}
Future<ServiceMap> getStack({int limit}) {

View file

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

View file

@ -52,8 +52,8 @@ var tests = <IsolateTest>[
bool shouldBeCaught) async {
print("Evaluating $expression with pause on $pauseMode exception");
expect((await isolate.setExceptionPauseMode(pauseMode)) is DartError,
isFalse);
expect(
(await isolate.setIsolatePauseMode(pauseMode)) is DartError, isFalse);
var t;
if (shouldPause) {

View file

@ -1124,8 +1124,8 @@ void Instance::PrintSharedInstanceJSON(JSONObject* jsobj,
if (!field.is_static()) {
field_value = GetField(field);
JSONObject jsfield(&jsarr);
jsfield.AddProperty("type", "BoundField");
jsfield.AddProperty("decl", field);
jsfield.AddProperty("name", field.UserVisibleNameCString());
jsfield.AddProperty("value", field_value);
}
}
@ -1219,7 +1219,7 @@ void FunctionType::PrintJSONImpl(JSONStream* stream, bool ref) const {
void RecordType::PrintJSONImpl(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
PrintSharedInstanceJSON(&jsobj, ref);
jsobj.AddProperty("kind", "_RecordType");
jsobj.AddProperty("kind", "RecordType");
if (ref) {
return;
}
@ -1630,7 +1630,7 @@ void Closure::PrintJSONImpl(JSONStream* stream, bool ref) const {
void Record::PrintJSONImpl(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
PrintSharedInstanceJSON(&jsobj, ref);
jsobj.AddProperty("kind", "_Record");
jsobj.AddProperty("kind", "Record");
if (ref) {
return;
}

View file

@ -1559,9 +1559,6 @@ void Profile::PrintHeaderJSON(JSONObject* obj) {
obj->AddProperty("maxStackDepth",
static_cast<intptr_t>(FLAG_max_profile_depth));
obj->AddProperty("sampleCount", sample_count());
// TODO(bkonyi): remove timeSpan after next major revision.
ASSERT(SERVICE_PROTOCOL_MAJOR_VERSION == 3);
obj->AddProperty64("timeSpan", -1);
obj->AddPropertyTimeMicros("timeOriginMicros", min_time());
obj->AddPropertyTimeMicros("timeExtentMicros", GetTimeSpan());
obj->AddProperty64("pid", pid);

View file

@ -2321,6 +2321,7 @@ static void PrintInboundReferences(Thread* thread,
(slot_offset.Value() - Array::element_offset(0)) /
Array::kBytesPerElement;
jselement.AddProperty("parentListIndex", element_index);
jselement.AddProperty("parentField", element_index);
} else if (source.IsRecord()) {
AddParentFieldToResponseBasedOnRecord(thread, &field_names, &name,
jselement, Record::Cast(source),
@ -2351,6 +2352,7 @@ static void PrintInboundReferences(Thread* thread,
(slot_offset.Value() - Context::variable_offset(0)) /
Context::kBytesPerElement;
jselement.AddProperty("parentListIndex", element_index);
jselement.AddProperty("parentField", element_index);
} else {
jselement.AddProperty("_parentWordOffset", slot_offset.Value());
}
@ -2445,6 +2447,7 @@ static void PrintRetainingPath(Thread* thread,
(slot_offset.Value() - Array::element_offset(0)) /
Array::kBytesPerElement;
jselement.AddProperty("parentListIndex", element_index);
jselement.AddProperty("parentField", element_index);
} else if (element.IsRecord()) {
AddParentFieldToResponseBasedOnRecord(thread, &field_names, &name,
jselement, Record::Cast(element),
@ -2491,6 +2494,7 @@ static void PrintRetainingPath(Thread* thread,
(slot_offset.Value() - Context::variable_offset(0)) /
Context::kBytesPerElement;
jselement.AddProperty("parentListIndex", element_index);
jselement.AddProperty("parentField", element_index);
} else {
jselement.AddProperty("_parentWordOffset", slot_offset.Value());
}

View file

@ -16,8 +16,8 @@
namespace dart {
#define SERVICE_PROTOCOL_MAJOR_VERSION 3
#define SERVICE_PROTOCOL_MINOR_VERSION 62
#define SERVICE_PROTOCOL_MAJOR_VERSION 4
#define SERVICE_PROTOCOL_MINOR_VERSION 0
class Array;
class EmbedderServiceHandler;

View file

@ -1,8 +1,8 @@
# Dart VM Service Protocol 3.62
# Dart VM Service Protocol 4.0
> Please post feedback to the [observatory-discuss group][discuss-list]
This document describes of _version 3.62_ of the Dart VM Service Protocol. This
This document describes of _version 4.0_ 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.
@ -121,7 +121,7 @@ The Service Protocol uses [JSON-RPC 2.0][].
- [NativeFunction](#nativefunction)
- [Null](#null)
- [Object](#object)
- [Parameter](#parameter)[
- [Parameter](#parameter)
- [PortList](#portlist)
- [ReloadReport](#reloadreport)
- [Response](#response)
@ -144,7 +144,7 @@ The Service Protocol uses [JSON-RPC 2.0][].
- [TimelineFlags](#timelineflags)
- [Timestamp](#timestamp)
- [TypeArguments](#typearguments)
- [TypeParameters](#typeparameters)[
- [TypeParameters](#typeparameters)
- [UnresolvedSourceLocation](#unresolvedsourcelocation)
- [UriList](#urilist)
- [Version](#version)
@ -1384,6 +1384,7 @@ The returned [Breakpoint](#breakpoint) is the updated breakpoint with its new
values.
See [Breakpoint](#breakpoint).
### setExceptionPauseMode
```
@ -1417,9 +1418,6 @@ pause due to a change in execution state.
The _shouldPauseOnExit_ parameter specify whether the target isolate should pause on exit.
The _setExceptionPauseMode_ RPC is used to control if an isolate pauses when
an exception is thrown.
mode | meaning
---- | -------
None | Do not pause isolate on thrown exceptions
@ -1708,7 +1706,12 @@ class AllocationProfile extends Response {
```
class BoundField {
// Provided for fields of instances that are NOT of the following instance kinds:
// Record
//
// Note: this property is deprecated and will be replaced by `name`.
@Field decl;
string|int name;
@Instance|Sentinel value;
}
```
@ -1980,12 +1983,6 @@ class CpuSamples extends Response {
// The number of samples returned.
int sampleCount;
// The timespan the set of returned samples covers, in microseconds (deprecated).
//
// Note: this property is deprecated and will always return -1. Use `timeExtentMicros`
// instead.
int timeSpan;
// The start of the period of time in which the returned samples were
// collected.
int timeOriginMicros;
@ -2022,12 +2019,6 @@ class CpuSamplesEvent {
// The number of samples returned.
int sampleCount;
// The timespan the set of returned samples covers, in microseconds (deprecated).
//
// Note: this property is deprecated and will always return -1. Use `timeExtentMicros`
// instead.
int timeSpan;
// The start of the period of time in which the returned samples were
// collected.
int timeOriginMicros;
@ -3133,6 +3124,9 @@ enum InstanceKind {
Float32x4List,
Float64x2List,
// An instance of the Dart class Record.
Record,
// An instance of the Dart class StackTrace.
StackTrace,
@ -3164,6 +3158,9 @@ enum InstanceKind {
// An instance of the Dart class FunctionType.
FunctionType,
// An instance of the Dart class RecordType.
RecordType,
// An instance of the Dart class BoundedType.
BoundedType,
@ -3344,12 +3341,21 @@ class InboundReference {
// The object holding the inbound reference.
@Object source;
// If source is a List, parentListIndex is the index of the inbound reference.
// If source is a List, parentListIndex is the index of the inbound reference (deprecated).
//
// Note: this property is deprecated and will be replaced by `parentField`.
int parentListIndex [optional];
// If source is a field of an object, parentField is the field containing the
// inbound reference.
@Field parentField [optional];
// If `source` is a `List`, `parentField` is the index of the inbound
// reference.
// If `source` is a record, `parentField` is the field name of the inbound
// reference.
// If `source` is an instance of any other kind, `parentField` is the field
// containing the inbound reference.
//
// Note: In v5.0 of the spec, `@Field` will no longer be a part of this
// property's type, i.e. the type will become `string|int`.
@Field|string|int parentField [optional];
}
```
@ -3761,7 +3767,9 @@ class RetainingObject {
@Object value;
// If `value` is a List, `parentListIndex` is the index where the previous
// object on the retaining path is located.
// object on the retaining path is located (deprecated).
//
// Note: this property is deprecated and will be replaced by `parentField`.
int parentListIndex [optional];
// If `value` is a Map, `parentMapKey` is the key mapping to the previous
@ -3770,7 +3778,7 @@ class RetainingObject {
// If `value` is a non-List, non-Map object, `parentField` is the name of the
// field containing the previous object on the retaining path.
string parentField [optional];
string|int parentField [optional];
}
```
@ -4415,5 +4423,6 @@ version | comments
3.60 | Added `gcType` property to `Event`.
3.61 | Added `isolateGroupId` property to `@Isolate` and `Isolate`.
3.62 | Added `Set` to `InstanceKind`.
4.0 | Added `Record` and `RecordType` `InstanceKind`s, added a deprecation notice to the `decl` property of `BoundField`, added `name` property to `BoundField`, added a deprecation notice to the `parentListIndex` property of `InboundReference`, changed the type of the `parentField` property of `InboundReference` from `@Field` to `@Field\|string\|int`, added a deprecation notice to the `parentListIndex` property of `RetainingObject`, changed the type of the `parentField` property of `RetainingObject` from `string` to `string\|int`, removed the deprecated `timeSpan` property from `CpuSamples`, and removed the deprecated `timeSpan` property from `CpuSamplesEvent`.
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss