| Index: sdk/lib/vmservice/vmservice.dart
|
| diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
|
| index f1253524dc8c38c1b6c3e09b9cef969fce810854..4101023f6c7dc585ad86a3591acaf7bda4cc1b24 100644
|
| --- a/sdk/lib/vmservice/vmservice.dart
|
| +++ b/sdk/lib/vmservice/vmservice.dart
|
| @@ -12,6 +12,7 @@ import 'dart:typed_data';
|
|
|
| part 'asset.dart';
|
| part 'client.dart';
|
| +part 'devfs.dart';
|
| part 'constants.dart';
|
| part 'running_isolate.dart';
|
| part 'running_isolates.dart';
|
| @@ -32,16 +33,24 @@ final Map<int, IsolateEmbedderData> isolateEmbedderData =
|
| new Map<int, IsolateEmbedderData>();
|
|
|
| // These must be kept in sync with the declarations in vm/json_stream.h.
|
| -const kInvalidParams = -32602;
|
| -const kInternalError = -32603;
|
| -const kStreamAlreadySubscribed = 103;
|
| -const kStreamNotSubscribed = 104;
|
| +const kInvalidParams = -32602;
|
| +const kInternalError = -32603;
|
| +const kFeatureDisabled = 100;
|
| +const kStreamAlreadySubscribed = 103;
|
| +const kStreamNotSubscribed = 104;
|
| +const kFileSystemAlreadyExists = 1001;
|
| +const kFileSystemDoesNotExist = 1002;
|
| +const kFileDoesNotExist = 1003;
|
|
|
| var _errorMessages = {
|
| kInvalidParams: 'Invalid params',
|
| kInternalError: 'Internal error',
|
| + kFeatureDisabled: 'Feature is disabled',
|
| kStreamAlreadySubscribed: 'Stream already subscribed',
|
| kStreamNotSubscribed: 'Stream not subscribed',
|
| + kFileSystemAlreadyExists: 'File system already exists',
|
| + kFileSystemDoesNotExist: 'File system does not exist',
|
| + kFileDoesNotExist: 'File does not exist',
|
| };
|
|
|
| String encodeRpcError(Message message, int code, {String details}) {
|
| @@ -61,6 +70,19 @@ String encodeRpcError(Message message, int code, {String details}) {
|
| return JSON.encode(response);
|
| }
|
|
|
| +String encodeMissingParamError(Message message, String param) {
|
| + return encodeRpcError(
|
| + message, kInvalidParams,
|
| + details: "${message.method} expects the '${param}' parameter");
|
| +}
|
| +
|
| +String encodeInvalidParamError(Message message, String param) {
|
| + var value = message.params[param];
|
| + return encodeRpcError(
|
| + message, kInvalidParams,
|
| + details: "${message.method}: invalid '${param}' parameter: ${value}");
|
| +}
|
| +
|
| String encodeResult(Message message, Map result) {
|
| var response = {
|
| 'jsonrpc': '2.0',
|
| @@ -70,6 +92,10 @@ String encodeResult(Message message, Map result) {
|
| return JSON.encode(response);
|
| }
|
|
|
| +String encodeSuccess(Message message) {
|
| + return encodeResult(message, { 'type': 'Success' });
|
| +}
|
| +
|
| const shortDelay = const Duration(milliseconds: 10);
|
|
|
| /// Called when the server should be started.
|
| @@ -81,11 +107,31 @@ typedef Future ServerStopCallback();
|
| /// Called when the service is exiting.
|
| typedef Future CleanupCallback();
|
|
|
| +/// Called to create a temporary directory
|
| +typedef Future<Uri> CreateTempDirCallback(String base);
|
| +
|
| +/// Called to delete a directory
|
| +typedef Future DeleteDirCallback(Uri path);
|
| +
|
| +/// Called to write a file.
|
| +typedef Future WriteFileCallback(Uri path, List<int> bytes);
|
| +
|
| +/// Called to read a file.
|
| +typedef Future<List<int>> ReadFileCallback(Uri path);
|
| +
|
| +/// Called to list all files under some path.
|
| +typedef Future<List<Map<String,String>>> ListFilesCallback(Uri path);
|
| +
|
| /// Hooks that are setup by the embedder.
|
| class VMServiceEmbedderHooks {
|
| static ServerStartCallback serverStart;
|
| static ServerStopCallback serverStop;
|
| static CleanupCallback cleanup;
|
| + static CreateTempDirCallback createTempDir;
|
| + static DeleteDirCallback deleteDir;
|
| + static WriteFileCallback writeFile;
|
| + static ReadFileCallback readFile;
|
| + static ListFilesCallback listFiles;
|
| }
|
|
|
| class VMService extends MessageRouter {
|
| @@ -100,6 +146,8 @@ class VMService extends MessageRouter {
|
| /// A port used to receive events from the VM.
|
| final RawReceivePort eventPort;
|
|
|
| + final _devfs = new DevFS();
|
| +
|
| void _addClient(Client client) {
|
| assert(client.streams.isEmpty);
|
| clients.add(client);
|
| @@ -158,6 +206,7 @@ class VMService extends MessageRouter {
|
| for (var client in clientsList) {
|
| client.disconnect();
|
| }
|
| + _devfs.cleanup();
|
| if (VMServiceEmbedderHooks.cleanup != null) {
|
| await VMServiceEmbedderHooks.cleanup();
|
| }
|
| @@ -228,8 +277,7 @@ class VMService extends MessageRouter {
|
| }
|
| client.streams.add(streamId);
|
|
|
| - var result = { 'type' : 'Success' };
|
| - return encodeResult(message, result);
|
| + return encodeSuccess(message);
|
| }
|
|
|
| Future<String> _streamCancel(Message message) async {
|
| @@ -244,8 +292,7 @@ class VMService extends MessageRouter {
|
| _vmCancelStream(streamId);
|
| }
|
|
|
| - var result = { 'type' : 'Success' };
|
| - return encodeResult(message, result);
|
| + return encodeSuccess(message);
|
| }
|
|
|
| // TODO(johnmccutchan): Turn this into a command line tool that uses the
|
| @@ -320,6 +367,9 @@ class VMService extends MessageRouter {
|
| if (message.method == 'streamCancel') {
|
| return _streamCancel(message);
|
| }
|
| + if (_devfs.shouldHandleMessage(message)) {
|
| + return _devfs.handleMessage(message);
|
| + }
|
| if (message.params['isolateId'] != null) {
|
| return runningIsolates.route(message);
|
| }
|
|
|