[VM/Service] Add getQueuedMicrotasks RPC
TEST=pkg/vm_service/test/get_queued_microtasks_rpc_test CoreLibraryReviewExempt: This CL does not include any core library API changes, only VM Service implementation changes within sdk/lib/vmservice/. Change-Id: Ie5488f498e4d0f3d201e3f31423fd5029b74a726 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425160 Commit-Queue: Derek Xu <derekx@google.com> Reviewed-by: Ben Konyi <bkonyi@google.com>
This commit is contained in:
@@ -43,6 +43,7 @@ abstract class RpcErrorCodes {
|
||||
static const kExpressionCompilationError = 113;
|
||||
|
||||
// static const kInvalidTimelineRequest = 114;
|
||||
// static const kCannotGetQueuedMicrotasks = 115;
|
||||
static const kCustomStreamDoesNotExist = 130;
|
||||
static const kCoreStreamNotAllowed = 131;
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ vm_service/test/get_allocation_traces_test: SkipByDesign # Debugger is disabled
|
||||
vm_service/test/get_instances_as_*: SkipByDesign # Debugger is disabled in AOT mode
|
||||
vm_service/test/get_instances_rpc_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
vm_service/test/get_object_rpc_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
vm_service/test/get_queued_microtasks_rpc_test: SkipByDesign # In AOT mode, the debugger is disabled, and there's no other way to pause the testee at a point when the microtask queue is non-empty.
|
||||
vm_service/test/get_source_report_const_coverage_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
vm_service/test/get_source_report_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
vm_service/test/get_source_report_with_mixin_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
## 15.0.1
|
||||
- Update to version `4.17` of the spec.
|
||||
## 15.0.1-wip
|
||||
- Update to version `4.19` of the spec.
|
||||
- Add `Timer` stream.
|
||||
- Add `TimerSignificantlyOverdue` event kind.
|
||||
- Add `details` property to `Event`.
|
||||
- Add `getQueuedMicrotasks` RPC.
|
||||
- Add `Microtask` and `QueuedMicrotasks` types.
|
||||
- Add `RPCErrorKind.kCannotGetQueuedMicrotasks`.
|
||||
|
||||
## 15.0.0
|
||||
- Update type of `CodeRef.function` from `FuncRef` to `dynamic` to allow for `NativeFunction`
|
||||
|
||||
@@ -35,6 +35,7 @@ src/org/dartlang/vm/service/consumer/PerfettoTimelineConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/PortListConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/ProcessMemoryUsageConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/ProtocolListConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/QueuedMicrotasksConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/ReloadSourcesConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/RemoveBreakpointConsumer.java
|
||||
src/org/dartlang/vm/service/consumer/RequestHeapSnapshotConsumer.java
|
||||
@@ -105,6 +106,7 @@ src/org/dartlang/vm/service/element/LogRecord.java
|
||||
src/org/dartlang/vm/service/element/MapAssociation.java
|
||||
src/org/dartlang/vm/service/element/MemoryUsage.java
|
||||
src/org/dartlang/vm/service/element/Message.java
|
||||
src/org/dartlang/vm/service/element/Microtask.java
|
||||
src/org/dartlang/vm/service/element/NativeFunction.java
|
||||
src/org/dartlang/vm/service/element/Null.java
|
||||
src/org/dartlang/vm/service/element/NullRef.java
|
||||
@@ -119,6 +121,7 @@ src/org/dartlang/vm/service/element/ProcessMemoryUsage.java
|
||||
src/org/dartlang/vm/service/element/ProfileFunction.java
|
||||
src/org/dartlang/vm/service/element/Protocol.java
|
||||
src/org/dartlang/vm/service/element/ProtocolList.java
|
||||
src/org/dartlang/vm/service/element/QueuedMicrotasks.java
|
||||
src/org/dartlang/vm/service/element/ReloadReport.java
|
||||
src/org/dartlang/vm/service/element/Response.java
|
||||
src/org/dartlang/vm/service/element/RetainingObject.java
|
||||
|
||||
@@ -1 +1 @@
|
||||
version=4.18
|
||||
version=4.19
|
||||
|
||||
@@ -27,7 +27,7 @@ export 'snapshot_graph.dart'
|
||||
HeapSnapshotObjectNoData,
|
||||
HeapSnapshotObjectNullData;
|
||||
|
||||
const String vmServiceVersion = '4.18.0';
|
||||
const String vmServiceVersion = '4.19.0';
|
||||
|
||||
/// @optional
|
||||
const String optional = 'optional';
|
||||
@@ -151,6 +151,7 @@ final _typeFactories = <String, Function>{
|
||||
'MapAssociation': MapAssociation.parse,
|
||||
'MemoryUsage': MemoryUsage.parse,
|
||||
'Message': Message.parse,
|
||||
'Microtask': Microtask.parse,
|
||||
'NativeFunction': NativeFunction.parse,
|
||||
'@Null': NullValRef.parse,
|
||||
'Null': NullVal.parse,
|
||||
@@ -165,6 +166,7 @@ final _typeFactories = <String, Function>{
|
||||
'Protocol': Protocol.parse,
|
||||
'ProcessMemoryUsage': ProcessMemoryUsage.parse,
|
||||
'ProcessMemoryItem': ProcessMemoryItem.parse,
|
||||
'QueuedMicrotasks': QueuedMicrotasks.parse,
|
||||
'ReloadReport': ReloadReport.parse,
|
||||
'RetainingObject': RetainingObject.parse,
|
||||
'RetainingPath': RetainingPath.parse,
|
||||
@@ -226,6 +228,7 @@ final _methodReturnTypes = <String, List<String>>{
|
||||
'getPorts': const ['PortList'],
|
||||
'getRetainingPath': const ['RetainingPath'],
|
||||
'getProcessMemoryUsage': const ['ProcessMemoryUsage'],
|
||||
'getQueuedMicrotasks': const ['QueuedMicrotasks'],
|
||||
'getStack': const ['Stack'],
|
||||
'getSupportedProtocols': const ['ProtocolList'],
|
||||
'getSourceReport': const ['SourceReport'],
|
||||
@@ -1255,6 +1258,28 @@ class VmService {
|
||||
Future<ProcessMemoryUsage> getProcessMemoryUsage() =>
|
||||
_call('getProcessMemoryUsage');
|
||||
|
||||
/// The `getQueuedMicrotasks` RPC returns a snapshot containing information
|
||||
/// about the microtasks that were queued in the specified isolate when the
|
||||
/// snapshot was taken.
|
||||
///
|
||||
/// If the VM was not started with the flag `--profile-microtasks`, this RPC
|
||||
/// will return [RPCError] 100 "Feature is disabled".
|
||||
///
|
||||
/// If an exception has gone unhandled in the specified isolate, this RPC will
|
||||
/// return [RPCError] 115 "Cannot get queued microtasks".
|
||||
///
|
||||
/// If custom `dart:async` `Zone`s are used to redirect microtasks to be
|
||||
/// queued elsewhere than the root `dart:async` `Zone`'s microtask queue,
|
||||
/// information about those redirected microtasks will not be returned by this
|
||||
/// function.
|
||||
///
|
||||
/// If `isolateId` refers to an isolate that has exited, then the `Collected`
|
||||
/// [Sentinel] will be returned.
|
||||
///
|
||||
/// See [QueuedMicrotasks].
|
||||
Future<QueuedMicrotasks> getQueuedMicrotasks(String isolateId) =>
|
||||
_call('getQueuedMicrotasks', {'isolateId': isolateId});
|
||||
|
||||
/// The `getStack` RPC is used to retrieve the current execution stack and
|
||||
/// message queue for an isolate. The isolate does not need to be paused.
|
||||
///
|
||||
@@ -2150,6 +2175,11 @@ enum RPCErrorKind {
|
||||
message:
|
||||
'Invalid timeline request for the current timeline configuration'),
|
||||
|
||||
/// Information about the microtasks queued in the specified isolate cannot be
|
||||
/// retrieved.
|
||||
kCannotGetQueuedMicrotasks(
|
||||
code: 115, message: 'Cannot get queued microtasks'),
|
||||
|
||||
/// The custom stream does not exist.
|
||||
kCustomStreamDoesNotExist(code: 130, message: 'Custom stream does not exist'),
|
||||
|
||||
@@ -6654,6 +6684,51 @@ class Message extends Response {
|
||||
'size: $size]';
|
||||
}
|
||||
|
||||
/// A `Microtask` represents a Dart microtask.
|
||||
///
|
||||
/// See [QueuedMicrotasks].
|
||||
class Microtask extends Response {
|
||||
static Microtask? parse(Map<String, dynamic>? json) =>
|
||||
json == null ? null : Microtask._fromJson(json);
|
||||
|
||||
/// The numeric ID for this microtask.
|
||||
///
|
||||
/// This ID uniquely identifies a microtask within an isolate.
|
||||
int? id;
|
||||
|
||||
/// A stack trace that was collected when this microtask was enqueued.
|
||||
String? stackTrace;
|
||||
|
||||
Microtask({
|
||||
this.id,
|
||||
this.stackTrace,
|
||||
});
|
||||
|
||||
Microtask._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
|
||||
id = json['id'] ?? -1;
|
||||
stackTrace = json['stackTrace'] ?? '';
|
||||
}
|
||||
|
||||
@override
|
||||
String get type => 'Microtask';
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => <String, Object?>{
|
||||
'type': type,
|
||||
'id': id ?? -1,
|
||||
'stackTrace': stackTrace ?? '',
|
||||
};
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => other is Microtask && id == other.id;
|
||||
|
||||
@override
|
||||
String toString() => '[Microtask id: $id, stackTrace: $stackTrace]';
|
||||
}
|
||||
|
||||
/// A `NativeFunction` object is used to represent native functions in profiler
|
||||
/// samples. See [CpuSamples];
|
||||
class NativeFunction {
|
||||
@@ -7302,6 +7377,51 @@ class ProcessMemoryItem {
|
||||
'name: $name, description: $description, size: $size, children: $children]';
|
||||
}
|
||||
|
||||
/// A `QueuedMicrotasks` object is a snapshot containing information about the
|
||||
/// microtasks that were queued in a certain isolate at a certain time.
|
||||
///
|
||||
/// See [VmService.getQueuedMicrotasks] and [Microtask].
|
||||
class QueuedMicrotasks extends Response {
|
||||
static QueuedMicrotasks? parse(Map<String, dynamic>? json) =>
|
||||
json == null ? null : QueuedMicrotasks._fromJson(json);
|
||||
|
||||
/// The time at which this snapshot of the microtask queue was taken,
|
||||
/// represented as microseconds since the "Unix epoch".
|
||||
int? timestamp;
|
||||
|
||||
/// The microtasks that were in the queue when this snapshot was taken. The
|
||||
/// microtask at the front of the queue (i.e. the one that will run earliest)
|
||||
/// is the one at index 0 of this list.
|
||||
List<Microtask>? microtasks;
|
||||
|
||||
QueuedMicrotasks({
|
||||
this.timestamp,
|
||||
this.microtasks,
|
||||
});
|
||||
|
||||
QueuedMicrotasks._fromJson(Map<String, dynamic> json)
|
||||
: super._fromJson(json) {
|
||||
timestamp = json['timestamp'] ?? -1;
|
||||
microtasks = List<Microtask>.from(
|
||||
createServiceObject(json['microtasks'], const ['Microtask']) as List? ??
|
||||
[]);
|
||||
}
|
||||
|
||||
@override
|
||||
String get type => 'QueuedMicrotasks';
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => <String, Object?>{
|
||||
'type': type,
|
||||
'timestamp': timestamp ?? -1,
|
||||
'microtasks': microtasks?.map((f) => f.toJson()).toList(),
|
||||
};
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'[QueuedMicrotasks timestamp: $timestamp, microtasks: $microtasks]';
|
||||
}
|
||||
|
||||
class ReloadReport extends Response {
|
||||
static ReloadReport? parse(Map<String, dynamic>? json) =>
|
||||
json == null ? null : ReloadReport._fromJson(json);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: vm_service
|
||||
version: 15.0.0
|
||||
version: 15.0.1-wip
|
||||
description: >-
|
||||
A library to communicate with a service implementing the Dart VM
|
||||
service protocol.
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2025, 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 'dart:developer';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vm_service/vm_service.dart';
|
||||
|
||||
import 'common/service_test_common.dart';
|
||||
import 'common/test_helper.dart';
|
||||
|
||||
const String shortFile = 'get_queued_microtasks_rpc_test.dart';
|
||||
const int numberOfMicrotasksToSchedule = 5;
|
||||
|
||||
Future<void> testeeMain() async {
|
||||
for (int i = 0; i < numberOfMicrotasksToSchedule; i++) {
|
||||
scheduleMicrotask(() {});
|
||||
debugger();
|
||||
// Give the microtask that we just scheduled an opportunity to run.
|
||||
await Future.delayed(const Duration(milliseconds: 1));
|
||||
}
|
||||
}
|
||||
|
||||
final tests = <IsolateTest>[
|
||||
(VmService service, IsolateRef isolateRef) async {
|
||||
for (int i = 0; i < numberOfMicrotasksToSchedule; i++) {
|
||||
await hasStoppedAtBreakpoint(service, isolateRef);
|
||||
final result = await service.getQueuedMicrotasks(
|
||||
isolateRef.id!,
|
||||
);
|
||||
|
||||
expect(result.timestamp, isPositive);
|
||||
expect(result.microtasks!.length, 1);
|
||||
expect(result.microtasks!.first.id, i);
|
||||
expect(result.microtasks!.first.stackTrace, contains(shortFile));
|
||||
await service.resume(isolateRef.id!);
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
Future<void> main([args = const <String>[]]) => runIsolateTests(
|
||||
args,
|
||||
tests,
|
||||
shortFile,
|
||||
testeeConcurrent: testeeMain,
|
||||
extraArgs: ['--profile-microtasks'],
|
||||
);
|
||||
@@ -334,6 +334,10 @@ enum RPCErrorKind {
|
||||
kInvalidTimelineRequest(code: 114,
|
||||
message: 'Invalid timeline request for the current timeline configuration'),
|
||||
|
||||
/// Information about the microtasks queued in the specified isolate cannot be
|
||||
/// retrieved.
|
||||
kCannotGetQueuedMicrotasks(code: 115, message: 'Cannot get queued microtasks'),
|
||||
|
||||
/// The custom stream does not exist.
|
||||
kCustomStreamDoesNotExist(code: 130, message: 'Custom stream does not exist'),
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import 'service_extension_registry.dart';
|
||||
|
||||
export 'service_extension_registry.dart' show ServiceExtensionRegistry;
|
||||
|
||||
const String vmServiceVersion = '4.18.0';
|
||||
const String vmServiceVersion = '4.19.0';
|
||||
|
||||
/// A class representation of the Dart VM Service Protocol.
|
||||
abstract interface class VmServiceInterface {
|
||||
@@ -784,6 +784,27 @@ abstract interface class VmServiceInterface {
|
||||
/// addition of any bucket.
|
||||
Future<ProcessMemoryUsage> getProcessMemoryUsage();
|
||||
|
||||
/// The `getQueuedMicrotasks` RPC returns a snapshot containing information
|
||||
/// about the microtasks that were queued in the specified isolate when the
|
||||
/// snapshot was taken.
|
||||
///
|
||||
/// If the VM was not started with the flag `--profile-microtasks`, this RPC
|
||||
/// will return [RPCError] 100 "Feature is disabled".
|
||||
///
|
||||
/// If an exception has gone unhandled in the specified isolate, this RPC will
|
||||
/// return [RPCError] 115 "Cannot get queued microtasks".
|
||||
///
|
||||
/// If custom `dart:async` `Zone`s are used to redirect microtasks to be
|
||||
/// queued elsewhere than the root `dart:async` `Zone`'s microtask queue,
|
||||
/// information about those redirected microtasks will not be returned by this
|
||||
/// function.
|
||||
///
|
||||
/// If `isolateId` refers to an isolate that has exited, then the `Collected`
|
||||
/// [Sentinel] will be returned.
|
||||
///
|
||||
/// See [QueuedMicrotasks].
|
||||
Future<QueuedMicrotasks> getQueuedMicrotasks(String isolateId);
|
||||
|
||||
/// The `getStack` RPC is used to retrieve the current execution stack and
|
||||
/// message queue for an isolate. The isolate does not need to be paused.
|
||||
///
|
||||
@@ -1606,6 +1627,11 @@ class VmServerConnection {
|
||||
case 'getProcessMemoryUsage':
|
||||
response = await _serviceImplementation.getProcessMemoryUsage();
|
||||
break;
|
||||
case 'getQueuedMicrotasks':
|
||||
response = await _serviceImplementation.getQueuedMicrotasks(
|
||||
params!['isolateId'],
|
||||
);
|
||||
break;
|
||||
case 'getStack':
|
||||
response = await _serviceImplementation.getStack(
|
||||
params!['isolateId'],
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace dart {
|
||||
|
||||
// This flag is defined in "vm/microtask_mirror_queues.cc".
|
||||
// This flag is defined in "runtime/vm/microtask_mirror_queues.cc".
|
||||
DECLARE_FLAG(bool, profile_microtasks);
|
||||
|
||||
DEFINE_NATIVE_ENTRY(AsyncStarMoveNext_debuggerStepCheck, 0, 1) {
|
||||
|
||||
@@ -12,7 +12,7 @@ var tests = <VMTest>[
|
||||
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
|
||||
expect(result['type'], 'Version');
|
||||
expect(result['major'], 4);
|
||||
expect(result['minor'], 18);
|
||||
expect(result['minor'], 19);
|
||||
expect(result['_privateMajor'], 0);
|
||||
expect(result['_privateMinor'], 0);
|
||||
},
|
||||
|
||||
@@ -136,6 +136,8 @@ static const char* GetJSONRpcErrorMessage(intptr_t code) {
|
||||
case kInvalidTimelineRequest:
|
||||
return "The timeline related request could not be completed due to the "
|
||||
"current configuration";
|
||||
case kCannotGetQueuedMicrotasks:
|
||||
return "Cannot get queued microtasks";
|
||||
default:
|
||||
return "Extension error";
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ enum JSONRpcErrorCode {
|
||||
kServiceDisappeared = 112,
|
||||
kExpressionCompilationError = 113,
|
||||
kInvalidTimelineRequest = 114,
|
||||
kCannotGetQueuedMicrotasks = 115,
|
||||
|
||||
// Experimental (used in private rpcs).
|
||||
kFileSystemAlreadyExists = 1001,
|
||||
|
||||
@@ -79,6 +79,22 @@ void MicrotaskMirrorQueue::OnAsyncCallbackComplete(int64_t start_time,
|
||||
}
|
||||
}
|
||||
|
||||
void MicrotaskMirrorQueue::PrintJSON(JSONStream& js) const {
|
||||
ASSERT(!is_disabled_);
|
||||
|
||||
JSONObject jsobj_topLevel(&js);
|
||||
jsobj_topLevel.AddProperty("type", "QueuedMicrotasks");
|
||||
jsobj_topLevel.AddProperty64("timestamp", OS::GetCurrentTimeMicros());
|
||||
|
||||
JSONArray jsarr(&jsobj_topLevel, "microtasks");
|
||||
queue_.ForEach([&jsarr](const MicrotaskMirrorQueueEntry& entry) {
|
||||
JSONObject jsobj_entry(&jsarr);
|
||||
jsobj_entry.AddProperty("type", "Microtask");
|
||||
jsobj_entry.AddProperty("id", entry.id());
|
||||
jsobj_entry.AddProperty("stackTrace", entry.stack_trace().get());
|
||||
});
|
||||
}
|
||||
|
||||
Mutex MicrotaskMirrorQueues::isolate_id_to_queue_lock_;
|
||||
|
||||
SimpleHashMap MicrotaskMirrorQueues::isolate_id_to_queue_(
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "platform/list_queue.h"
|
||||
#include "platform/synchronization.h"
|
||||
#include "platform/utils.h"
|
||||
#include "vm/json_stream.h"
|
||||
#include "vm/stack_frame.h"
|
||||
|
||||
namespace dart {
|
||||
@@ -45,9 +46,11 @@ class MicrotaskMirrorQueue {
|
||||
MicrotaskMirrorQueue()
|
||||
: is_disabled_(false), queue_(), next_available_id_(0) {}
|
||||
|
||||
bool is_disabled() const { return is_disabled_; }
|
||||
void OnScheduleAsyncCallback(const StackTrace& st);
|
||||
void OnSchedulePriorityAsyncCallback();
|
||||
void OnAsyncCallbackComplete(int64_t start_time, int64_t end_time);
|
||||
void PrintJSON(JSONStream& js) const;
|
||||
|
||||
private:
|
||||
bool is_disabled_;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "vm/message.h"
|
||||
#include "vm/message_handler.h"
|
||||
#include "vm/message_snapshot.h"
|
||||
#include "vm/microtask_mirror_queues.h"
|
||||
#include "vm/native_arguments.h"
|
||||
#include "vm/native_entry.h"
|
||||
#include "vm/native_symbol.h"
|
||||
@@ -66,6 +67,8 @@ namespace dart {
|
||||
|
||||
DECLARE_FLAG(bool, trace_service);
|
||||
DECLARE_FLAG(bool, trace_service_pause_events);
|
||||
// This flag is defined in "runtime/vm/microtask_mirror_queues.cc".
|
||||
DECLARE_FLAG(bool, profile_microtasks);
|
||||
DECLARE_FLAG(bool, profile_vm);
|
||||
DEFINE_FLAG(charp,
|
||||
vm_name,
|
||||
@@ -3838,6 +3841,32 @@ static void GetPorts(Thread* thread, JSONStream* js) {
|
||||
}
|
||||
}
|
||||
|
||||
static const MethodParameter* const get_queued_microtasks_params[] = {
|
||||
ISOLATE_PARAMETER,
|
||||
nullptr,
|
||||
};
|
||||
|
||||
static void GetQueuedMicrotasks(Thread* thread, JSONStream* js) {
|
||||
if (!FLAG_profile_microtasks) {
|
||||
js->PrintError(kFeatureDisabled,
|
||||
"getQueuedMicrotaks is only available when the VM is "
|
||||
"started with the flag --profile-microtasks.");
|
||||
return;
|
||||
}
|
||||
|
||||
const MicrotaskMirrorQueue& queue =
|
||||
*MicrotaskMirrorQueues::GetQueue(thread->isolate()->main_port());
|
||||
|
||||
if (queue.is_disabled()) {
|
||||
js->PrintError(
|
||||
kCannotGetQueuedMicrotasks,
|
||||
"An exception has gone unhandled in the specified isolate, so "
|
||||
"information about the microtasks queued in it cannot be retrieved.");
|
||||
} else {
|
||||
queue.PrintJSON(*js);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
static const char* const report_enum_names[] = {
|
||||
SourceReport::kCallSitesStr, SourceReport::kCoverageStr,
|
||||
@@ -6271,6 +6300,8 @@ static const ServiceMethodDescriptor service_methods_[] = {
|
||||
lookup_resolved_package_uris_params },
|
||||
{ "lookupPackageUris", LookupPackageUris,
|
||||
lookup_package_uris_params },
|
||||
{ "getQueuedMicrotasks", GetQueuedMicrotasks,
|
||||
get_queued_microtasks_params },
|
||||
{ "getRetainingPath", GetRetainingPath,
|
||||
get_retaining_path_params },
|
||||
{ "getScripts", GetScripts,
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
namespace dart {
|
||||
|
||||
#define SERVICE_PROTOCOL_MAJOR_VERSION 4
|
||||
#define SERVICE_PROTOCOL_MINOR_VERSION 18
|
||||
#define SERVICE_PROTOCOL_MINOR_VERSION 19
|
||||
|
||||
class Array;
|
||||
class EmbedderServiceHandler;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Dart VM Service Protocol 4.18
|
||||
# Dart VM Service Protocol 4.19
|
||||
|
||||
> Please post feedback to the [observatory-discuss group][discuss-list]
|
||||
|
||||
This document describes of _version 4.18_ of the Dart VM Service Protocol. This
|
||||
This document describes of _version 4.19_ 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.
|
||||
@@ -57,6 +57,7 @@ The Service Protocol uses [JSON-RPC 2.0][].
|
||||
- [getPerfettoVMTimeline](#getperfettovmtimeline)
|
||||
- [getPorts](#getports)
|
||||
- [getProcessMemoryUsage](#getprocessmemoryusage)
|
||||
- [getQueuedMicrotasks](#getqueuedmicrotasks)
|
||||
- [getRetainingPath](#getretainingpath)
|
||||
- [getScripts](#getscripts)
|
||||
- [getSourceReport](#getsourcereport)
|
||||
@@ -126,6 +127,7 @@ The Service Protocol uses [JSON-RPC 2.0][].
|
||||
- [LibraryDependency](#librarydependency)
|
||||
- [LogRecord](#logrecord)
|
||||
- [MapAssociation](#mapassociation)
|
||||
- [Microtask](#microtask)
|
||||
- [MemoryUsage](#memoryusage)
|
||||
- [Message](#message)
|
||||
- [NativeFunction](#nativefunction)
|
||||
@@ -135,6 +137,7 @@ The Service Protocol uses [JSON-RPC 2.0][].
|
||||
- [PerfettoCpuSamples](#perfettocpusamples)
|
||||
- [PerfettoTimeline](#perfettotimeline)
|
||||
- [PortList](#portlist)
|
||||
- [QueuedMicrotasks](#queuedmicrotasks)
|
||||
- [ReloadReport](#reloadreport)
|
||||
- [Response](#response)
|
||||
- [RetainingObject](#retainingobject)
|
||||
@@ -264,6 +267,7 @@ code | message | meaning
|
||||
112 | Service disappeared | Failed to fulfill service request, likely service handler is no longer available
|
||||
113 | Expression compilation error | Request to compile expression failed
|
||||
114 | Invalid timeline request | The timeline related request could not be completed due to the current configuration
|
||||
115 | Cannot get queued microtasks | Information about the microtasks queued in the specified isolate cannot be retrieved
|
||||
|
||||
## Events
|
||||
|
||||
@@ -1303,6 +1307,31 @@ Adding or removing buckets is considered a backwards-compatible change
|
||||
for the purposes of versioning. A client must gracefully handle the
|
||||
removal or addition of any bucket.
|
||||
|
||||
### getQueuedMicrotasks
|
||||
|
||||
```
|
||||
QueuedMicrotasks getQueuedMicrotasks(string isolateId)
|
||||
```
|
||||
|
||||
The _getQueuedMicrotasks_ RPC returns a snapshot containing information about
|
||||
the microtasks that were queued in the specified isolate when the snapshot was
|
||||
taken.
|
||||
|
||||
If the VM was not started with the flag `--profile-microtasks`, this RPC will
|
||||
return [RPC error](#rpc-error) 100 "Feature is disabled".
|
||||
|
||||
If an exception has gone unhandled in the specified isolate, this RPC will
|
||||
return [RPC error](#rpc-error) 115 "Cannot get queued microtasks".
|
||||
|
||||
If custom `dart:async` `Zone`s are used to redirect microtasks to be queued
|
||||
elsewhere than the root `dart:async` `Zone`'s microtask queue, information about
|
||||
those redirected microtasks will not be returned by this function.
|
||||
|
||||
If _isolateId_ refers to an isolate that has exited, then the _Collected_
|
||||
[Sentinel](#sentinel) will be returned.
|
||||
|
||||
See [QueuedMicrotasks](#queuedmicrotasks).
|
||||
|
||||
### getStack
|
||||
|
||||
```
|
||||
@@ -4020,6 +4049,24 @@ class Message extends Response {
|
||||
A _Message_ provides information about a pending isolate message and the
|
||||
function that will be invoked to handle it.
|
||||
|
||||
### Microtask
|
||||
|
||||
```
|
||||
class Microtask extends Response {
|
||||
// The numeric ID for this microtask.
|
||||
//
|
||||
// This ID uniquely identifies a microtask within an isolate.
|
||||
int id;
|
||||
|
||||
// A stack trace that was collected when this microtask was enqueued.
|
||||
string stackTrace;
|
||||
}
|
||||
```
|
||||
|
||||
A _Microtask_ represents a Dart microtask.
|
||||
|
||||
See [QueuedMicrotasks](#queuedmicrotasks).
|
||||
|
||||
### NativeFunction
|
||||
|
||||
```
|
||||
@@ -4276,6 +4323,26 @@ class ProcessMemoryItem {
|
||||
}
|
||||
```
|
||||
|
||||
### QueuedMicrotasks
|
||||
|
||||
```
|
||||
class QueuedMicrotasks extends Response {
|
||||
// The time at which this snapshot of the microtask queue was taken,
|
||||
// represented as microseconds since the "Unix epoch".
|
||||
int timestamp;
|
||||
|
||||
// The microtasks that were in the queue when this snapshot was taken. The
|
||||
// microtask at the front of the queue (i.e. the one that will run earliest)
|
||||
// is the one at index 0 of this list.
|
||||
Microtask[] microtasks;
|
||||
}
|
||||
```
|
||||
|
||||
A _QueuedMicrotasks_ object is a snapshot containing information about the
|
||||
microtasks that were queued in a certain isolate at a certain time.
|
||||
|
||||
See [getQueuedMicrotasks](#getqueuedmicrotasks) and [Microtask](#microtask).
|
||||
|
||||
### ReloadReport
|
||||
|
||||
```
|
||||
@@ -4995,5 +5062,6 @@ version | comments
|
||||
4.16 | Added `reloadFailureReason` property to `Event`. Added `createIdZone`, `deleteIdZone`, and `invalidateIdZone` RPCs. Added optional `idZoneId` parameter to `evaluate`, `evaluateInFrame`, `getInboundReferences`, `getInstances`, `getInstancesAsList`, `getObject`, `getRetainingPath`, `getStack`, and `invoke` RPCs.
|
||||
4.17 | Added `Timer` stream, added `TimerSignificantlyOverdue` event kind, and added `details` property to `Event`.
|
||||
4.18 | Added `Microtask` timeline stream.
|
||||
4.19 | Added `getQueuedMicrotasks` RPC, added `Microtask` and `QueuedMicrotasks` types, and added RPC error 115 "Cannot get queued microtasks".
|
||||
|
||||
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
|
||||
|
||||
@@ -58,6 +58,7 @@ const kServiceAlreadyRegistered = 111;
|
||||
const kServiceDisappeared = 112;
|
||||
const kExpressionCompilationError = 113;
|
||||
const kInvalidTimelineRequest = 114;
|
||||
const kCannotGetQueuedMicrotasks = 115;
|
||||
|
||||
// Experimental (used in private rpcs).
|
||||
const kFileSystemAlreadyExists = 1001;
|
||||
|
||||
Reference in New Issue
Block a user