[ package:vm_service ] Fix VmServerConnection always responding with a string ID

VmServerConnection was converting request IDs into Strings, even if the
ID was an integer. This resulted in request responses always having
string IDs which does not conform to the JSON-RPC spec and breaks

package:json_rpc_2.
Change-Id: Ia42d2fbf5a32b88c57b827f493a1847119e8a08c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/161441
Reviewed-by: Devon Carew <devoncarew@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Ben Konyi 2020-09-01 21:20:49 +00:00 committed by commit-bot@chromium.org
parent fb0729b35d
commit f00e45d9b8
3 changed files with 43 additions and 20 deletions

View file

@ -4,6 +4,7 @@
- Added `isSystemIsolate` property to `IsolateRef` and `Isolate`.
- Added `isSystemIsolateGroup` property to `IsolateGroupRef` and `IsolateGroup`.
- Added `serviceIsolates` and `serviceIsolateGroups` properties to `VM`.
- Fixed issue where `VmServerConnection` would always response with a string ID even if the request ID was not a string.
## 4.2.0
- Update to version `3.37.0` of the spec.

View file

@ -1166,6 +1166,20 @@ abstract class VmServiceInterface {
Future<Success> streamListen(String streamId);
}
class _PendingServiceRequest {
Future<Map<String, Object>> get future => _completer.future;
final _completer = Completer<Map<String, Object>>();
final dynamic originalId;
_PendingServiceRequest(this.originalId);
void complete(Map<String, Object> response) {
response['id'] = originalId;
_completer.complete(response);
}
}
/// A Dart VM Service Protocol connection that delegates requests to a
/// [VmServiceInterface] implementation.
///
@ -1189,8 +1203,7 @@ class VmServerConnection {
final _doneCompleter = Completer<Null>();
/// Pending service extension requests to this client by id.
final _pendingServiceExtensionRequests =
<String, Completer<Map<String, Object>>>{};
final _pendingServiceExtensionRequests = <dynamic, _PendingServiceRequest>{};
VmServerConnection(this._requestStream, this._responseSink,
this._serviceExtensionRegistry, this._serviceImplementation) {
@ -1212,21 +1225,19 @@ class VmServerConnection {
// multiple clients ids.
var newId = '${_nextServiceRequestId++}:$originalId';
request['id'] = newId;
var responseCompleter = Completer<Map<String, Object>>();
_pendingServiceExtensionRequests[newId] = responseCompleter;
var pendingRequest = _PendingServiceRequest(originalId);
_pendingServiceExtensionRequests[newId] = pendingRequest;
_responseSink.add(request);
return responseCompleter.future;
return pendingRequest.future;
}
void _delegateRequest(Map<String, Object> request) async {
try {
var id = request['id'] as String;
var id = request['id'];
// Check if this is actually a response to a pending request.
if (_pendingServiceExtensionRequests.containsKey(id)) {
// Restore the original request ID.
var originalId = id.substring(id.indexOf(':') + 1);
_pendingServiceExtensionRequests[id]
.complete(Map.of(request)..['id'] = originalId);
final pending = _pendingServiceExtensionRequests[id];
pending.complete(Map.of(request));
return;
}
var method = request['method'] as String;

View file

@ -627,6 +627,20 @@ abstract class VmServiceInterface {
// The server class, takes a VmServiceInterface and delegates to it
// automatically.
gen.write('''
class _PendingServiceRequest {
Future<Map<String, Object>> get future => _completer.future;
final _completer = Completer<Map<String, Object>>();
final dynamic originalId;
_PendingServiceRequest(this.originalId);
void complete(Map<String, Object> response) {
response['id'] = originalId;
_completer.complete(response);
}
}
/// A Dart VM Service Protocol connection that delegates requests to a
/// [VmServiceInterface] implementation.
///
@ -649,8 +663,7 @@ abstract class VmServiceInterface {
final _doneCompleter = Completer<Null>();
/// Pending service extension requests to this client by id.
final _pendingServiceExtensionRequests =
<String, Completer<Map<String, Object>>>{};
final _pendingServiceExtensionRequests = <dynamic, _PendingServiceRequest>{};
VmServerConnection(
this._requestStream, this._responseSink, this._serviceExtensionRegistry,
@ -673,21 +686,19 @@ abstract class VmServiceInterface {
// multiple clients ids.
var newId = '\${_nextServiceRequestId++}:\$originalId';
request['id'] = newId;
var responseCompleter = Completer<Map<String, Object>>();
_pendingServiceExtensionRequests[newId] = responseCompleter;
var pendingRequest = _PendingServiceRequest(originalId);
_pendingServiceExtensionRequests[newId] = pendingRequest;
_responseSink.add(request);
return responseCompleter.future;
return pendingRequest.future;
}
void _delegateRequest(Map<String, Object> request) async {
try {
var id = request['id'] as String;
var id = request['id'];
// Check if this is actually a response to a pending request.
if (_pendingServiceExtensionRequests.containsKey(id)) {
// Restore the original request ID.
var originalId = id.substring(id.indexOf(':') + 1);
_pendingServiceExtensionRequests[id].complete(
Map.of(request)..['id'] = originalId);
final pending = _pendingServiceExtensionRequests[id];
pending.complete(Map.of(request));
return;
}
var method = request['method'] as String;