mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 16:37:43 +00:00
Revert "[3.0 alpha][VM/Service] Update VM Service spec to v4.0"
This reverts commit c21f7c847c
.
Reason for revert: Appears to cause issues when flutter app is launched with VSCode or Android Studio, please see https://github.com/flutter/flutter/issues/117526
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>
# Not skipping CQ checks because original CL landed > 1 day ago.
Issue: https://github.com/dart-lang/sdk/issues/49725
Change-Id: Ieb2a09653192e165ea8cf68965647e346e3a318b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/277181
Reviewed-by: Derek Xu <derekx@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
Auto-Submit: Siva Annamalai <asiva@google.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
This commit is contained in:
parent
59ec6a3d46
commit
dcaf392d34
|
@ -200,6 +200,7 @@ 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,
|
||||
|
@ -209,6 +210,7 @@ class CachedCpuSamples extends CpuSamples {
|
|||
samplePeriod: samplePeriod,
|
||||
maxStackDepth: maxStackDepth,
|
||||
sampleCount: sampleCount,
|
||||
timeSpan: timeSpan,
|
||||
timeOriginMicros: timeOriginMicros,
|
||||
timeExtentMicros: timeExtentMicros,
|
||||
pid: pid,
|
||||
|
@ -223,6 +225,7 @@ 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,
|
||||
|
|
1
pkg/vm_service/java/.gitignore
vendored
1
pkg/vm_service/java/.gitignore
vendored
|
@ -34,6 +34,7 @@ src/org/dartlang/vm/service/consumer/ReloadSourcesConsumer.java
|
|||
src/org/dartlang/vm/service/consumer/RemoveBreakpointConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/RequestHeapSnapshotConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/ResumeConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/SetExceptionPauseModeConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/SetFlagConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/SetIsolatePauseModeConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/SetLibraryDebuggableConsumer.java
|
||||
|
|
|
@ -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.setIsolatePauseMode(isolate.getId(), mode, new SuccessConsumer() {
|
||||
@Override
|
||||
public void onError(RPCError error) {
|
||||
showRPCError(error);
|
||||
}
|
||||
vmService.setExceptionPauseMode(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();
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
version=4.0
|
||||
version=3.62
|
||||
|
|
|
@ -26,7 +26,7 @@ export 'snapshot_graph.dart'
|
|||
HeapSnapshotObjectNoData,
|
||||
HeapSnapshotObjectNullData;
|
||||
|
||||
const String vmServiceVersion = '4.0.0';
|
||||
const String vmServiceVersion = '3.62.0';
|
||||
|
||||
/// @optional
|
||||
const String optional = 'optional';
|
||||
|
@ -236,6 +236,7 @@ Map<String, List<String>> _methodReturnTypes = {
|
|||
'requestHeapSnapshot': const ['Success'],
|
||||
'resume': const ['Success'],
|
||||
'setBreakpointState': const ['Breakpoint'],
|
||||
'setExceptionPauseMode': const ['Success'],
|
||||
'setIsolatePauseMode': const ['Success'],
|
||||
'setFlag': const ['Success', 'Error'],
|
||||
'setLibraryDebuggable': const ['Success'],
|
||||
|
@ -1076,12 +1077,33 @@ abstract class VmServiceInterface {
|
|||
Future<Breakpoint> setBreakpointState(
|
||||
String isolateId, String breakpointId, bool enable);
|
||||
|
||||
/// 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
|
||||
/// Unhandled | Pause isolate on unhandled exceptions
|
||||
/// All | Pause isolate on all thrown exceptions
|
||||
///
|
||||
/// If `isolateId` refers to an isolate which has exited, then the `Collected`
|
||||
/// [Sentinel] is returned.
|
||||
///
|
||||
/// This method will throw a [SentinelException] in the case a [Sentinel] is
|
||||
/// returned.
|
||||
@Deprecated('Use setIsolatePauseMode instead')
|
||||
Future<Success> setExceptionPauseMode(
|
||||
String isolateId, /*ExceptionPauseMode*/ String mode);
|
||||
|
||||
/// The `setIsolatePauseMode` RPC is used to control if or when an isolate
|
||||
/// will 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
|
||||
|
@ -1576,6 +1598,13 @@ class VmServerConnection {
|
|||
params['enable'],
|
||||
);
|
||||
break;
|
||||
case 'setExceptionPauseMode':
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
response = await _serviceImplementation.setExceptionPauseMode(
|
||||
params!['isolateId'],
|
||||
params['mode'],
|
||||
);
|
||||
break;
|
||||
case 'setIsolatePauseMode':
|
||||
response = await _serviceImplementation.setIsolatePauseMode(
|
||||
params!['isolateId'],
|
||||
|
@ -2120,6 +2149,12 @@ class VmService implements VmServiceInterface {
|
|||
'enable': enable
|
||||
});
|
||||
|
||||
@Deprecated('Use setIsolatePauseMode instead')
|
||||
@override
|
||||
Future<Success> setExceptionPauseMode(
|
||||
String isolateId, /*ExceptionPauseMode*/ String mode) =>
|
||||
_call('setExceptionPauseMode', {'isolateId': isolateId, 'mode': mode});
|
||||
|
||||
@override
|
||||
Future<Success> setIsolatePauseMode(String isolateId,
|
||||
{/*ExceptionPauseMode*/ String? exceptionPauseMode,
|
||||
|
@ -2682,9 +2717,6 @@ 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';
|
||||
|
||||
|
@ -2716,9 +2748,6 @@ 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';
|
||||
|
||||
|
@ -2878,29 +2907,18 @@ 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;
|
||||
|
@ -2910,14 +2928,12 @@ class BoundField {
|
|||
final json = <String, dynamic>{};
|
||||
json.addAll({
|
||||
'decl': decl?.toJson(),
|
||||
'name': name?.toJson(),
|
||||
'value': value?.toJson(),
|
||||
});
|
||||
return json;
|
||||
}
|
||||
|
||||
String toString() =>
|
||||
'[BoundField decl: ${decl}, name: ${name}, value: ${value}]';
|
||||
String toString() => '[BoundField decl: ${decl}, value: ${value}]';
|
||||
}
|
||||
|
||||
/// A `BoundVariable` represents a local variable bound to a particular value in
|
||||
|
@ -3610,6 +3626,13 @@ 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;
|
||||
|
@ -3633,6 +3656,7 @@ class CpuSamples extends Response {
|
|||
this.samplePeriod,
|
||||
this.maxStackDepth,
|
||||
this.sampleCount,
|
||||
this.timeSpan,
|
||||
this.timeOriginMicros,
|
||||
this.timeExtentMicros,
|
||||
this.pid,
|
||||
|
@ -3644,6 +3668,7 @@ 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;
|
||||
|
@ -3667,6 +3692,7 @@ 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,
|
||||
|
@ -3676,9 +3702,7 @@ class CpuSamples extends Response {
|
|||
return json;
|
||||
}
|
||||
|
||||
String toString() => '[CpuSamples ' //
|
||||
'samplePeriod: ${samplePeriod}, maxStackDepth: ${maxStackDepth}, ' //
|
||||
'sampleCount: ${sampleCount}, timeOriginMicros: ${timeOriginMicros}, timeExtentMicros: ${timeExtentMicros}, pid: ${pid}, functions: ${functions}, samples: ${samples}]';
|
||||
String toString() => '[CpuSamples]';
|
||||
}
|
||||
|
||||
class CpuSamplesEvent {
|
||||
|
@ -3694,6 +3718,13 @@ 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;
|
||||
|
@ -3717,6 +3748,7 @@ class CpuSamplesEvent {
|
|||
this.samplePeriod,
|
||||
this.maxStackDepth,
|
||||
this.sampleCount,
|
||||
this.timeSpan,
|
||||
this.timeOriginMicros,
|
||||
this.timeExtentMicros,
|
||||
this.pid,
|
||||
|
@ -3728,6 +3760,7 @@ 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;
|
||||
|
@ -3745,6 +3778,7 @@ class CpuSamplesEvent {
|
|||
'samplePeriod': samplePeriod ?? -1,
|
||||
'maxStackDepth': maxStackDepth ?? -1,
|
||||
'sampleCount': sampleCount ?? -1,
|
||||
'timeSpan': timeSpan ?? -1,
|
||||
'timeOriginMicros': timeOriginMicros ?? -1,
|
||||
'timeExtentMicros': timeExtentMicros ?? -1,
|
||||
'pid': pid ?? -1,
|
||||
|
@ -3754,9 +3788,7 @@ class CpuSamplesEvent {
|
|||
return json;
|
||||
}
|
||||
|
||||
String toString() => '[CpuSamplesEvent ' //
|
||||
'samplePeriod: ${samplePeriod}, maxStackDepth: ${maxStackDepth}, ' //
|
||||
'sampleCount: ${sampleCount}, timeOriginMicros: ${timeOriginMicros}, timeExtentMicros: ${timeExtentMicros}, pid: ${pid}, functions: ${functions}, samples: ${samples}]';
|
||||
String toString() => '[CpuSamplesEvent]';
|
||||
}
|
||||
|
||||
/// See [getCpuSamples] and [CpuSamples].
|
||||
|
@ -5991,24 +6023,15 @@ class InboundReference {
|
|||
/// The object holding the inbound reference.
|
||||
ObjRef? source;
|
||||
|
||||
/// 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`.
|
||||
/// If source is a List, parentListIndex is the index of the inbound
|
||||
/// reference.
|
||||
@optional
|
||||
int? parentListIndex;
|
||||
|
||||
/// 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].
|
||||
/// If source is a field of an object, parentField is the field containing the
|
||||
/// inbound reference.
|
||||
@optional
|
||||
dynamic parentField;
|
||||
FieldRef? parentField;
|
||||
|
||||
InboundReference({
|
||||
this.source,
|
||||
|
@ -6019,8 +6042,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', 'String', 'int']) as dynamic;
|
||||
parentField = createServiceObject(json['parentField'], const ['FieldRef'])
|
||||
as FieldRef?;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
@ -7118,9 +7141,7 @@ class RetainingObject {
|
|||
ObjRef? value;
|
||||
|
||||
/// If `value` is a List, `parentListIndex` is the index where the previous
|
||||
/// object on the retaining path is located (deprecated).
|
||||
///
|
||||
/// Note: this property is deprecated and will be replaced by `parentField`.
|
||||
/// object on the retaining path is located.
|
||||
@optional
|
||||
int? parentListIndex;
|
||||
|
||||
|
@ -7131,10 +7152,8 @@ 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
|
||||
dynamic parentField;
|
||||
String? parentField;
|
||||
|
||||
RetainingObject({
|
||||
this.value,
|
||||
|
@ -7148,9 +7167,7 @@ class RetainingObject {
|
|||
parentListIndex = json['parentListIndex'];
|
||||
parentMapKey =
|
||||
createServiceObject(json['parentMapKey'], const ['ObjRef']) as ObjRef?;
|
||||
parentField =
|
||||
createServiceObject(json['parentField'], const ['String', 'int'])
|
||||
as dynamic;
|
||||
parentField = json['parentField'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
@ -7160,7 +7177,7 @@ class RetainingObject {
|
|||
});
|
||||
_setIfNotNull(json, 'parentListIndex', parentListIndex);
|
||||
_setIfNotNull(json, 'parentMapKey', parentMapKey?.toJson());
|
||||
_setIfNotNull(json, 'parentField', parentField?.toJson());
|
||||
_setIfNotNull(json, 'parentField', parentField);
|
||||
return json;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
library get_object_rpc_test;
|
||||
|
||||
import 'dart:collection';
|
||||
import 'dart:convert' show base64Decode;
|
||||
import 'dart:typed_data';
|
||||
|
||||
|
@ -694,23 +693,19 @@ var tests = <IsolateTest>[
|
|||
as InstanceRef;
|
||||
final objectId = evalResult.id!;
|
||||
final result = await service.getObject(isolateId, objectId) as Instance;
|
||||
expect(result.kind, InstanceKind.kRecord);
|
||||
expect(result.kind, '_Record');
|
||||
expect(result.json!['_vmType'], 'Record');
|
||||
expect(result.id, startsWith('objects/'));
|
||||
expect(result.valueAsString, isNull);
|
||||
expect(result.classRef!.name, '_Record');
|
||||
expect(result.size, isPositive);
|
||||
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');
|
||||
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);
|
||||
},
|
||||
|
||||
// library.
|
||||
|
|
112
pkg/vm_service/test/pause_on_exceptions_legacy_test.dart
Normal file
112
pkg/vm_service/test/pause_on_exceptions_legacy_test.dart
Normal file
|
@ -0,0 +1,112 @@
|
|||
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vm_service/vm_service.dart';
|
||||
|
||||
import 'common/test_helper.dart';
|
||||
|
||||
doThrow() {
|
||||
throw "TheException"; // Line 13.
|
||||
}
|
||||
|
||||
doCaught() {
|
||||
try {
|
||||
doThrow();
|
||||
} catch (e) {
|
||||
return "end of doCaught";
|
||||
}
|
||||
}
|
||||
|
||||
doUncaught() {
|
||||
doThrow();
|
||||
return "end of doUncaught";
|
||||
}
|
||||
|
||||
final tests = <IsolateTest>[
|
||||
(VmService service, IsolateRef isolateRef) async {
|
||||
final isolate = await service.getIsolate(isolateRef.id!);
|
||||
final lib = await service.getObject(isolateRef.id!, isolate.rootLib!.id!);
|
||||
|
||||
Completer? onPaused;
|
||||
Completer? onResume;
|
||||
|
||||
final stream = service.onDebugEvent;
|
||||
final subscription = stream.listen((Event event) {
|
||||
print("Event $event");
|
||||
if (event.kind == EventKind.kPauseException) {
|
||||
if (onPaused == null) throw "Unexpected pause event $event";
|
||||
final t = onPaused;
|
||||
onPaused = null;
|
||||
t!.complete(event);
|
||||
}
|
||||
if (event.kind == EventKind.kResume) {
|
||||
if (onResume == null) throw "Unexpected resume event $event";
|
||||
final t = onResume;
|
||||
onResume = null;
|
||||
t!.complete(event);
|
||||
}
|
||||
});
|
||||
await service.streamListen(EventStreams.kDebug);
|
||||
|
||||
test(String pauseMode, String expression, bool shouldPause,
|
||||
bool shouldBeCaught) async {
|
||||
print("Evaluating $expression with pause on $pauseMode exception");
|
||||
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
await service.setExceptionPauseMode(isolate.id!, pauseMode);
|
||||
|
||||
late Completer t;
|
||||
if (shouldPause) {
|
||||
t = Completer();
|
||||
onPaused = t;
|
||||
}
|
||||
final fres = service.evaluate(isolate.id!, lib.id!, expression);
|
||||
if (shouldPause) {
|
||||
await t.future;
|
||||
|
||||
final stack = await service.getStack(isolate.id!);
|
||||
expect(stack.frames![0].function!.name, 'doThrow');
|
||||
|
||||
t = Completer();
|
||||
onResume = t;
|
||||
await service.resume(isolate.id!);
|
||||
await t.future;
|
||||
}
|
||||
|
||||
dynamic res = await fres;
|
||||
if (shouldBeCaught) {
|
||||
expect(res is InstanceRef, true);
|
||||
expect(res.kind, 'String');
|
||||
expect(res.valueAsString, equals("end of doCaught"));
|
||||
} else {
|
||||
print(res.json);
|
||||
expect(res is ErrorRef, true);
|
||||
res = await service.getObject(isolate.id!, res.id!);
|
||||
expect(res is Error, true);
|
||||
expect(res.exception.kind, 'String');
|
||||
expect(res.exception.valueAsString, equals("TheException"));
|
||||
}
|
||||
}
|
||||
|
||||
await test("All", "doCaught()", true, true);
|
||||
await test("All", "doUncaught()", true, false);
|
||||
|
||||
await test("Unhandled", "doCaught()", false, true);
|
||||
await test("Unhandled", "doUncaught()", true, false);
|
||||
|
||||
await test("None", "doCaught()", false, true);
|
||||
await test("None", "doUncaught()", false, false);
|
||||
|
||||
await subscription.cancel();
|
||||
},
|
||||
];
|
||||
|
||||
main([args = const <String>[]]) => runIsolateTests(
|
||||
args,
|
||||
tests,
|
||||
'pause_on_exceptions_test.dart',
|
||||
);
|
|
@ -637,7 +637,7 @@ class SetCommand extends DebuggerCommand {
|
|||
};
|
||||
|
||||
static Future _setBreakOnException(debugger, name, value) async {
|
||||
var result = await debugger.isolate.setIsolatePauseMode(value);
|
||||
var result = await debugger.isolate.setExceptionPauseMode(value);
|
||||
if (result.isError) {
|
||||
debugger.console.print(result.toString());
|
||||
} else {
|
||||
|
|
|
@ -1886,8 +1886,8 @@ class Isolate extends ServiceObjectOwner implements M.Isolate {
|
|||
return invokeRpc('setName', {'name': newName});
|
||||
}
|
||||
|
||||
Future setIsolatePauseMode(String mode) {
|
||||
return invokeRpc('setIsolatePauseMode', {'exceptionPauseMode': mode});
|
||||
Future setExceptionPauseMode(String mode) {
|
||||
return invokeRpc('setExceptionPauseMode', {'mode': mode});
|
||||
}
|
||||
|
||||
Future<ServiceMap> getStack({int? limit}) {
|
||||
|
|
|
@ -11,8 +11,8 @@ var tests = <VMTest>[
|
|||
(VM vm) async {
|
||||
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
|
||||
expect(result['type'], 'Version');
|
||||
expect(result['major'], 4);
|
||||
expect(result['minor'], 0);
|
||||
expect(result['major'], 3);
|
||||
expect(result['minor'], 62);
|
||||
expect(result['_privateMajor'], 0);
|
||||
expect(result['_privateMinor'], 0);
|
||||
},
|
||||
|
|
|
@ -52,8 +52,8 @@ var tests = <IsolateTest>[
|
|||
bool shouldBeCaught) async {
|
||||
print("Evaluating $expression with pause on $pauseMode exception");
|
||||
|
||||
expect(
|
||||
(await isolate.setIsolatePauseMode(pauseMode)) is DartError, isFalse);
|
||||
expect((await isolate.setExceptionPauseMode(pauseMode)) is DartError,
|
||||
isFalse);
|
||||
|
||||
var t;
|
||||
if (shouldPause) {
|
||||
|
|
|
@ -632,7 +632,7 @@ class SetCommand extends DebuggerCommand {
|
|||
};
|
||||
|
||||
static Future _setBreakOnException(debugger, name, value) async {
|
||||
var result = await debugger.isolate.setIsolatePauseMode(value);
|
||||
var result = await debugger.isolate.setExceptionPauseMode(value);
|
||||
if (result.isError) {
|
||||
debugger.console.print(result.toString());
|
||||
} else {
|
||||
|
|
|
@ -1894,8 +1894,8 @@ class Isolate extends ServiceObjectOwner implements M.Isolate {
|
|||
return invokeRpc('setName', {'name': newName});
|
||||
}
|
||||
|
||||
Future setIsolatePauseMode(String mode) {
|
||||
return invokeRpc('setIsolatePauseMode', {'exceptionPauseMode': mode});
|
||||
Future setExceptionPauseMode(String mode) {
|
||||
return invokeRpc('setExceptionPauseMode', {'mode': mode});
|
||||
}
|
||||
|
||||
Future<ServiceMap> getStack({int limit}) {
|
||||
|
|
|
@ -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(4));
|
||||
expect(result['minor'], equals(0));
|
||||
expect(result['major'], equals(3));
|
||||
expect(result['minor'], equals(62));
|
||||
expect(result['_privateMajor'], equals(0));
|
||||
expect(result['_privateMinor'], equals(0));
|
||||
},
|
||||
|
|
|
@ -52,8 +52,8 @@ var tests = <IsolateTest>[
|
|||
bool shouldBeCaught) async {
|
||||
print("Evaluating $expression with pause on $pauseMode exception");
|
||||
|
||||
expect(
|
||||
(await isolate.setIsolatePauseMode(pauseMode)) is DartError, isFalse);
|
||||
expect((await isolate.setExceptionPauseMode(pauseMode)) is DartError,
|
||||
isFalse);
|
||||
|
||||
var t;
|
||||
if (shouldPause) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1559,6 +1559,9 @@ 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);
|
||||
|
|
|
@ -2321,7 +2321,6 @@ 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),
|
||||
|
@ -2352,7 +2351,6 @@ 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());
|
||||
}
|
||||
|
@ -2447,7 +2445,6 @@ 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),
|
||||
|
@ -2494,7 +2491,6 @@ 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());
|
||||
}
|
||||
|
@ -5419,6 +5415,27 @@ static const MethodParameter* const set_exception_pause_mode_params[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static void SetExceptionPauseMode(Thread* thread, JSONStream* js) {
|
||||
const char* mode = js->LookupParam("mode");
|
||||
if (mode == NULL) {
|
||||
PrintMissingParamError(js, "mode");
|
||||
return;
|
||||
}
|
||||
Dart_ExceptionPauseInfo info =
|
||||
EnumMapper(mode, exception_pause_mode_names, exception_pause_mode_values);
|
||||
if (info == kInvalidExceptionPauseInfo) {
|
||||
PrintInvalidParamError(js, "mode");
|
||||
return;
|
||||
}
|
||||
Isolate* isolate = thread->isolate();
|
||||
isolate->debugger()->SetExceptionPauseInfo(info);
|
||||
if (Service::debug_stream.enabled()) {
|
||||
ServiceEvent event(isolate, ServiceEvent::kDebuggerSettingsUpdate);
|
||||
Service::HandleEvent(&event);
|
||||
}
|
||||
PrintSuccess(js);
|
||||
}
|
||||
|
||||
static const MethodParameter* const set_isolate_pause_mode_params[] = {
|
||||
ISOLATE_PARAMETER,
|
||||
new EnumParameter("exceptionPauseMode", false, exception_pause_mode_names),
|
||||
|
@ -5872,6 +5889,8 @@ static const ServiceMethodDescriptor service_methods_[] = {
|
|||
evaluate_compiled_expression_params },
|
||||
{ "setBreakpointState", SetBreakpointState,
|
||||
set_breakpoint_state_params },
|
||||
{ "setExceptionPauseMode", SetExceptionPauseMode,
|
||||
set_exception_pause_mode_params },
|
||||
{ "setIsolatePauseMode", SetIsolatePauseMode,
|
||||
set_isolate_pause_mode_params },
|
||||
{ "setFlag", SetFlag,
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
namespace dart {
|
||||
|
||||
#define SERVICE_PROTOCOL_MAJOR_VERSION 4
|
||||
#define SERVICE_PROTOCOL_MINOR_VERSION 0
|
||||
#define SERVICE_PROTOCOL_MAJOR_VERSION 3
|
||||
#define SERVICE_PROTOCOL_MINOR_VERSION 62
|
||||
|
||||
class Array;
|
||||
class EmbedderServiceHandler;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Dart VM Service Protocol 4.0
|
||||
# Dart VM Service Protocol 3.62
|
||||
|
||||
> Please post feedback to the [observatory-discuss group][discuss-list]
|
||||
|
||||
This document describes of _version 4.0_ of the Dart VM Service Protocol. This
|
||||
This document describes of _version 3.62_ 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.
|
||||
|
@ -71,6 +71,7 @@ The Service Protocol uses [JSON-RPC 2.0][].
|
|||
- [removeBreakpoint](#removebreakpoint)
|
||||
- [resume](#resume)
|
||||
- [setBreakpointState](#setbreakpointstate)
|
||||
- [setExceptionPauseMode](#setexceptionpausemode)
|
||||
- [setFlag](#setflag)
|
||||
- [setLibraryDebuggable](#setlibrarydebuggable)
|
||||
- [setName](#setname)
|
||||
|
@ -120,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)
|
||||
|
@ -143,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)
|
||||
|
@ -1383,6 +1384,25 @@ The returned [Breakpoint](#breakpoint) is the updated breakpoint with its new
|
|||
values.
|
||||
|
||||
See [Breakpoint](#breakpoint).
|
||||
### setExceptionPauseMode
|
||||
|
||||
```
|
||||
@deprecated('Use setIsolatePauseMode instead')
|
||||
Success|Sentinel setExceptionPauseMode(string isolateId,
|
||||
ExceptionPauseMode mode)
|
||||
```
|
||||
|
||||
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
|
||||
Unhandled | Pause isolate on unhandled exceptions
|
||||
All | Pause isolate on all thrown exceptions
|
||||
|
||||
If _isolateId_ refers to an isolate which has exited, then the
|
||||
_Collected_ [Sentinel](#sentinel) is returned.
|
||||
|
||||
### setIsolatePauseMode
|
||||
|
||||
|
@ -1397,6 +1417,9 @@ 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
|
||||
|
@ -1685,12 +1708,7 @@ 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;
|
||||
}
|
||||
```
|
||||
|
@ -1962,6 +1980,12 @@ 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;
|
||||
|
@ -1998,6 +2022,12 @@ 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;
|
||||
|
@ -3103,9 +3133,6 @@ enum InstanceKind {
|
|||
Float32x4List,
|
||||
Float64x2List,
|
||||
|
||||
// An instance of the Dart class Record.
|
||||
Record,
|
||||
|
||||
// An instance of the Dart class StackTrace.
|
||||
StackTrace,
|
||||
|
||||
|
@ -3137,9 +3164,6 @@ 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,
|
||||
|
||||
|
@ -3320,21 +3344,12 @@ class InboundReference {
|
|||
// The object holding the inbound reference.
|
||||
@Object source;
|
||||
|
||||
// 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`.
|
||||
// If source is a List, parentListIndex is the index of the inbound reference.
|
||||
int parentListIndex [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];
|
||||
// If source is a field of an object, parentField is the field containing the
|
||||
// inbound reference.
|
||||
@Field parentField [optional];
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -3746,9 +3761,7 @@ class RetainingObject {
|
|||
@Object value;
|
||||
|
||||
// If `value` is a List, `parentListIndex` is the index where the previous
|
||||
// object on the retaining path is located (deprecated).
|
||||
//
|
||||
// Note: this property is deprecated and will be replaced by `parentField`.
|
||||
// object on the retaining path is located.
|
||||
int parentListIndex [optional];
|
||||
|
||||
// If `value` is a Map, `parentMapKey` is the key mapping to the previous
|
||||
|
@ -3757,7 +3770,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|int parentField [optional];
|
||||
string parentField [optional];
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -4402,6 +4415,5 @@ 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 `setExceptionPauseMode` procedure, 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
|
||||
|
|
Loading…
Reference in a new issue