[ Service ] Fix dart:developer service extensions, add getSupportedProtocols

Brings package:vm_service test suite pass rate up to ~93%

Change-Id: I108a24e1acf37eb69c9de25a2f7334eb4c56dbe6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/487600
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Ben Konyi
2026-03-16 11:14:58 -07:00
committed by Commit Queue
parent e3ca6d824b
commit 0e9d801353
8 changed files with 120 additions and 31 deletions
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
@@ -13,6 +14,7 @@ import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
import 'package:logging/logging.dart';
import 'package:stream_channel/stream_channel.dart';
import 'src/dart_runtime_service_vm_rpcs.dart';
import 'src/native_bindings.dart';
import 'src/vm_expression_evaluator.dart';
import 'src/vm_isolate_manager.dart';
@@ -73,6 +75,20 @@ class DartRuntimeServiceVMBackend
@override
late final VmExpressionEvaluator expressionEvaluator;
final _vmServiceRpcs = DartRuntimeServiceVmRpcs();
@override
UnmodifiableListView<ServiceRpcHandler> get rpcs =>
UnmodifiableListView(_vmServiceRpcs.rpcs);
@override
UnmodifiableListView<RpcHandlerWithParameters>
get fallbacks => UnmodifiableListView([
// If the registered Dart RPC handlers can't handle a request, forward it
// it to the native VM service implementation for processing.
sendToRuntime,
]);
@override
Future<void> initialize() async {
_logger.info('Initializing...');
@@ -148,18 +164,6 @@ class DartRuntimeServiceVMBackend
_nativeBindings.streamCancel(streamId: streamId);
}
@override
void registerRpcs(json_rpc.Peer clientPeer) {
// The VM service handles its service requests in service.cc.
}
@override
void registerFallbacks(json_rpc.Peer clientPeer) {
// If the registered Dart RPC handlers can't handle a request, forward it
// it to the native VM service implementation for processing.
clientPeer.registerFallback(sendToRuntime);
}
/// Sends service requests to the Dart VM runtime for processing.
Future<RpcResponse> sendToRuntime(json_rpc.Parameters request) async {
final method = request.method;
@@ -0,0 +1,46 @@
// Copyright (c) 2026, 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:collection';
import 'package:dart_runtime_service/dart_runtime_service.dart';
import 'package:logging/logging.dart';
import 'package:vm_service/vm_service.dart';
import 'native_bindings.dart';
/// Implementations of RPCs specific to the VM service that are not handled
/// in runtime/vm/service.cc.
final class DartRuntimeServiceVmRpcs {
final _logger = Logger('$DartRuntimeServiceVmRpcs');
final _nativeBindings = NativeBindings();
late final rpcs = UnmodifiableListView<ServiceRpcHandler>([
('getSupportedProtocols', getSupportedProtocols),
]);
/// Returns the list of protocols implemented by the service.
///
/// VM service middleware like DDS should intercept this RPC and add their
/// own information to the response.
Future<RpcResponse> getSupportedProtocols() async {
final version = Version.parse(
await _nativeBindings.sendToVM(method: 'getVersion', params: const {}),
);
if (version == null) {
_logger.warning('Unable to retrieve version for getSupportedProtocols.');
RpcException.internalError.throwException();
}
return ProtocolList(
protocols: [
Protocol(
protocolName: 'VM Service',
major: version.major,
minor: version.minor,
),
],
).toJson();
}
}
@@ -133,10 +133,16 @@ class NativeBindings {
const kData = 'data';
final Object? converted;
if (value case [final Uint8List utf8String]) {
if (value case final String string) {
converted = json.decode(string);
} else if (value case [final Uint8List utf8String]) {
converted = jsonUtf8Decoder.decode(utf8String);
} else {
RpcException.internalError.throwException();
RpcException.internalError.throwException(
data: {
'details': 'Unknown response type (${value.runtimeType}: $value)',
},
);
}
if (converted case {kResult: final Map<String, Object?> result}) {
return result;