OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart._vmservice; | 5 library dart._vmservice; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 import 'dart:convert'; | 9 import 'dart:convert'; |
10 import 'dart:developer' show ServiceProtocolInfo; | 10 import 'dart:developer' show ServiceProtocolInfo; |
11 import 'dart:isolate'; | 11 import 'dart:isolate'; |
12 import 'dart:math'; | 12 import 'dart:math'; |
13 import 'dart:typed_data'; | 13 import 'dart:typed_data'; |
14 | 14 |
15 part 'asset.dart'; | 15 part 'asset.dart'; |
16 part 'client.dart'; | 16 part 'client.dart'; |
17 part 'devfs.dart'; | 17 part 'devfs.dart'; |
18 part 'constants.dart'; | 18 part 'constants.dart'; |
19 part 'running_isolate.dart'; | 19 part 'running_isolate.dart'; |
20 part 'running_isolates.dart'; | 20 part 'running_isolates.dart'; |
21 part 'message.dart'; | 21 part 'message.dart'; |
22 part 'message_router.dart'; | 22 part 'message_router.dart'; |
| 23 part 'named_lookup.dart'; |
23 | 24 |
24 final RawReceivePort isolateControlPort = new RawReceivePort(); | 25 final RawReceivePort isolateControlPort = new RawReceivePort(); |
25 final RawReceivePort scriptLoadPort = new RawReceivePort(); | 26 final RawReceivePort scriptLoadPort = new RawReceivePort(); |
26 | 27 |
27 abstract class IsolateEmbedderData { | 28 abstract class IsolateEmbedderData { |
28 void cleanup(); | 29 void cleanup(); |
29 } | 30 } |
30 | 31 |
31 String _makeAuthToken() { | 32 String _makeAuthToken() { |
32 final kTokenByteSize = 8; | 33 final kTokenByteSize = 8; |
(...skipping 11 matching lines...) Expand all Loading... |
44 // TODO(johnmccutchan): Enable the auth token and drop the origin check. | 45 // TODO(johnmccutchan): Enable the auth token and drop the origin check. |
45 final bool useAuthToken = const bool.fromEnvironment('DART_SERVICE_USE_AUTH'); | 46 final bool useAuthToken = const bool.fromEnvironment('DART_SERVICE_USE_AUTH'); |
46 | 47 |
47 // This is for use by the embedder. It is a map from the isolateId to | 48 // This is for use by the embedder. It is a map from the isolateId to |
48 // anything implementing IsolateEmbedderData. When an isolate goes away, | 49 // anything implementing IsolateEmbedderData. When an isolate goes away, |
49 // the cleanup method will be invoked after being removed from the map. | 50 // the cleanup method will be invoked after being removed from the map. |
50 final Map<int, IsolateEmbedderData> isolateEmbedderData = | 51 final Map<int, IsolateEmbedderData> isolateEmbedderData = |
51 new Map<int, IsolateEmbedderData>(); | 52 new Map<int, IsolateEmbedderData>(); |
52 | 53 |
53 // These must be kept in sync with the declarations in vm/json_stream.h. | 54 // These must be kept in sync with the declarations in vm/json_stream.h. |
| 55 const kParseError = -32700; |
| 56 const kInvalidRequest = -32600; |
| 57 const kMethodNotFound = -32601; |
54 const kInvalidParams = -32602; | 58 const kInvalidParams = -32602; |
55 const kInternalError = -32603; | 59 const kInternalError = -32603; |
| 60 |
| 61 const kExtensionError = -32000; |
| 62 |
56 const kFeatureDisabled = 100; | 63 const kFeatureDisabled = 100; |
| 64 const kCannotAddBreakpoint = 102; |
57 const kStreamAlreadySubscribed = 103; | 65 const kStreamAlreadySubscribed = 103; |
58 const kStreamNotSubscribed = 104; | 66 const kStreamNotSubscribed = 104; |
| 67 const kIsolateMustBeRunnable = 105; |
| 68 const kIsolateMustBePaused = 106; |
| 69 const kCannotResume = 107; |
| 70 const kIsolateIsReloading = 108; |
| 71 const kIsolateReloadBarred = 109; |
| 72 const kServiceAlreadyRegistered = 110; |
| 73 const kServiceDisappeared = 111; |
| 74 |
| 75 // Experimental (used in private rpcs). |
59 const kFileSystemAlreadyExists = 1001; | 76 const kFileSystemAlreadyExists = 1001; |
60 const kFileSystemDoesNotExist = 1002; | 77 const kFileSystemDoesNotExist = 1002; |
61 const kFileDoesNotExist = 1003; | 78 const kFileDoesNotExist = 1003; |
62 | 79 |
63 var _errorMessages = { | 80 var _errorMessages = { |
64 kInvalidParams: 'Invalid params', | 81 kInvalidParams: 'Invalid params', |
65 kInternalError: 'Internal error', | 82 kInternalError: 'Internal error', |
66 kFeatureDisabled: 'Feature is disabled', | 83 kFeatureDisabled: 'Feature is disabled', |
67 kStreamAlreadySubscribed: 'Stream already subscribed', | 84 kStreamAlreadySubscribed: 'Stream already subscribed', |
68 kStreamNotSubscribed: 'Stream not subscribed', | 85 kStreamNotSubscribed: 'Stream not subscribed', |
69 kFileSystemAlreadyExists: 'File system already exists', | 86 kFileSystemAlreadyExists: 'File system already exists', |
70 kFileSystemDoesNotExist: 'File system does not exist', | 87 kFileSystemDoesNotExist: 'File system does not exist', |
71 kFileDoesNotExist: 'File does not exist', | 88 kFileDoesNotExist: 'File does not exist', |
| 89 kServiceAlreadyRegistered: 'Service already registered', |
| 90 kServiceDisappeared: 'Service has disappeared', |
72 }; | 91 }; |
73 | 92 |
74 String encodeRpcError(Message message, int code, {String details}) { | 93 String encodeRpcError(Message message, int code, {String details}) { |
75 var response = { | 94 var response = { |
76 'jsonrpc': '2.0', | 95 'jsonrpc': '2.0', |
77 'id': message.serial, | 96 'id': message.serial, |
78 'error': { | 97 'error': { |
79 'code': code, | 98 'code': code, |
80 'message': _errorMessages[code], | 99 'message': _errorMessages[code], |
81 }, | 100 }, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 /// Called to write a stream into a file. | 154 /// Called to write a stream into a file. |
136 typedef Future WriteStreamFileCallback(Uri path, Stream<List<int>> bytes); | 155 typedef Future WriteStreamFileCallback(Uri path, Stream<List<int>> bytes); |
137 | 156 |
138 /// Called to read a file. | 157 /// Called to read a file. |
139 typedef Future<List<int>> ReadFileCallback(Uri path); | 158 typedef Future<List<int>> ReadFileCallback(Uri path); |
140 | 159 |
141 /// Called to list all files under some path. | 160 /// Called to list all files under some path. |
142 typedef Future<List<Map<String, String>>> ListFilesCallback(Uri path); | 161 typedef Future<List<Map<String, String>>> ListFilesCallback(Uri path); |
143 | 162 |
144 /// Called when we need information about the server. | 163 /// Called when we need information about the server. |
| 164 typedef Future<Uri> ServerInformamessage_routertionCallback(); |
| 165 |
| 166 /// Called when we need information about the server. |
145 typedef Future<Uri> ServerInformationCallback(); | 167 typedef Future<Uri> ServerInformationCallback(); |
146 | 168 |
147 /// Called when we want to [enable] or disable the web server. | 169 /// Called when we want to [enable] or disable the web server. |
148 typedef Future<Uri> WebServerControlCallback(bool enable); | 170 typedef Future<Uri> WebServerControlCallback(bool enable); |
149 | 171 |
150 /// Hooks that are setup by the embedder. | 172 /// Hooks that are setup by the embedder. |
151 class VMServiceEmbedderHooks { | 173 class VMServiceEmbedderHooks { |
152 static ServerStartCallback serverStart; | 174 static ServerStartCallback serverStart; |
153 static ServerStopCallback serverStop; | 175 static ServerStopCallback serverStop; |
154 static CleanupCallback cleanup; | 176 static CleanupCallback cleanup; |
155 static CreateTempDirCallback createTempDir; | 177 static CreateTempDirCallback createTempDir; |
156 static DeleteDirCallback deleteDir; | 178 static DeleteDirCallback deleteDir; |
157 static WriteFileCallback writeFile; | 179 static WriteFileCallback writeFile; |
158 static WriteStreamFileCallback writeStreamFile; | 180 static WriteStreamFileCallback writeStreamFile; |
159 static ReadFileCallback readFile; | 181 static ReadFileCallback readFile; |
160 static ListFilesCallback listFiles; | 182 static ListFilesCallback listFiles; |
161 static ServerInformationCallback serverInformation; | 183 static ServerInformationCallback serverInformation; |
162 static WebServerControlCallback webServerControl; | 184 static WebServerControlCallback webServerControl; |
163 } | 185 } |
164 | 186 |
165 class VMService extends MessageRouter { | 187 class VMService extends MessageRouter { |
166 static VMService _instance; | 188 static VMService _instance; |
167 | 189 |
| 190 static const serviceNamespace = 's'; |
| 191 |
168 /// Collection of currently connected clients. | 192 /// Collection of currently connected clients. |
169 final Set<Client> clients = new Set<Client>(); | 193 final NamedLookup<Client> clients = |
| 194 new NamedLookup<Client>(prologue: serviceNamespace); |
| 195 final IdGenerator _serviceRequests = new IdGenerator(prologue: 'sr'); |
170 | 196 |
171 /// Collection of currently running isolates. | 197 /// Collection of currently running isolates. |
172 RunningIsolates runningIsolates = new RunningIsolates(); | 198 RunningIsolates runningIsolates = new RunningIsolates(); |
173 | 199 |
174 /// A port used to receive events from the VM. | 200 /// A port used to receive events from the VM. |
175 final RawReceivePort eventPort; | 201 final RawReceivePort eventPort; |
176 | 202 |
177 final devfs = new DevFS(); | 203 final devfs = new DevFS(); |
178 | 204 |
179 void _addClient(Client client) { | 205 void _addClient(Client client) { |
180 assert(client.streams.isEmpty); | 206 assert(client.streams.isEmpty); |
| 207 assert(client.services.isEmpty); |
181 clients.add(client); | 208 clients.add(client); |
182 } | 209 } |
183 | 210 |
184 void _removeClient(Client client) { | 211 void _removeClient(Client client) { |
| 212 final namespace = clients.keyOf(client); |
185 clients.remove(client); | 213 clients.remove(client); |
186 for (var streamId in client.streams) { | 214 for (var streamId in client.streams) { |
187 if (!_isAnyClientSubscribed(streamId)) { | 215 if (!_isAnyClientSubscribed(streamId)) { |
188 _vmCancelStream(streamId); | 216 _vmCancelStream(streamId); |
189 } | 217 } |
190 } | 218 } |
| 219 for (var service in client.services.keys) { |
| 220 _eventMessageHandler([ |
| 221 '_Service', |
| 222 JSON.encode({ |
| 223 'jsonrpc': '2.0', |
| 224 'method': 'streamNotify', |
| 225 'params': { |
| 226 'streamId': '_Service', |
| 227 'event': { |
| 228 "type": "Event", |
| 229 "kind": "ServiceUnregistered", |
| 230 'timestamp': new DateTime.now().millisecondsSinceEpoch, |
| 231 'service': service, |
| 232 'method': namespace + '.' + service, |
| 233 } |
| 234 } |
| 235 }) |
| 236 ]); |
| 237 } |
| 238 // Complete all requestes as failed |
| 239 for (var handle in client.serviceHandles.values) { |
| 240 handle(null); |
| 241 } |
191 } | 242 } |
192 | 243 |
193 void _eventMessageHandler(List eventMessage) { | 244 void _eventMessageHandler(List eventMessage) { |
194 var streamId = eventMessage[0]; | 245 var streamId = eventMessage[0]; |
195 var event = eventMessage[1]; | 246 var event = eventMessage[1]; |
196 for (var client in clients) { | 247 for (var client in clients) { |
197 if (client.sendEvents && client.streams.contains(streamId)) { | 248 if (client.sendEvents && client.streams.contains(streamId)) { |
198 client.post(event); | 249 client.post(event); |
199 } | 250 } |
200 } | 251 } |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 | 357 |
307 bool _isAnyClientSubscribed(String streamId) { | 358 bool _isAnyClientSubscribed(String streamId) { |
308 for (var client in clients) { | 359 for (var client in clients) { |
309 if (client.streams.contains(streamId)) { | 360 if (client.streams.contains(streamId)) { |
310 return true; | 361 return true; |
311 } | 362 } |
312 } | 363 } |
313 return false; | 364 return false; |
314 } | 365 } |
315 | 366 |
| 367 static const kServiceStream = '_Service'; |
| 368 static const serviceStreams = const [kServiceStream]; |
| 369 |
316 Future<String> _streamListen(Message message) async { | 370 Future<String> _streamListen(Message message) async { |
317 var client = message.client; | 371 var client = message.client; |
318 var streamId = message.params['streamId']; | 372 var streamId = message.params['streamId']; |
319 | 373 |
320 if (client.streams.contains(streamId)) { | 374 if (client.streams.contains(streamId)) { |
321 return encodeRpcError(message, kStreamAlreadySubscribed); | 375 return encodeRpcError(message, kStreamAlreadySubscribed); |
322 } | 376 } |
323 if (!_isAnyClientSubscribed(streamId)) { | 377 if (!_isAnyClientSubscribed(streamId)) { |
324 if (!_vmListenStream(streamId)) { | 378 if (!serviceStreams.contains(streamId) && !_vmListenStream(streamId)) { |
325 return encodeRpcError(message, kInvalidParams, | 379 return encodeRpcError(message, kInvalidParams, |
326 details: "streamListen: invalid 'streamId' parameter: ${streamId}"); | 380 details: "streamListen: invalid 'streamId' parameter: ${streamId}"); |
327 } | 381 } |
328 } | 382 } |
| 383 |
| 384 // Some streams can generate events or side effects after registration |
| 385 switch (streamId) { |
| 386 case kServiceStream: |
| 387 for (Client c in clients) { |
| 388 if (c == client) continue; |
| 389 for (String service in c.services.keys) { |
| 390 _sendServiceRegisteredEvent(c, service, target: client); |
| 391 } |
| 392 } |
| 393 ; |
| 394 break; |
| 395 } |
| 396 |
329 client.streams.add(streamId); | 397 client.streams.add(streamId); |
330 | |
331 return encodeSuccess(message); | 398 return encodeSuccess(message); |
332 } | 399 } |
333 | 400 |
334 Future<String> _streamCancel(Message message) async { | 401 Future<String> _streamCancel(Message message) async { |
335 var client = message.client; | 402 var client = message.client; |
336 var streamId = message.params['streamId']; | 403 var streamId = message.params['streamId']; |
337 | 404 |
338 if (!client.streams.contains(streamId)) { | 405 if (!client.streams.contains(streamId)) { |
339 return encodeRpcError(message, kStreamNotSubscribed); | 406 return encodeRpcError(message, kStreamNotSubscribed); |
340 } | 407 } |
341 client.streams.remove(streamId); | 408 client.streams.remove(streamId); |
342 if (!_isAnyClientSubscribed(streamId)) { | 409 if (!serviceStreams.contains(streamId) && |
| 410 !_isAnyClientSubscribed(streamId)) { |
343 _vmCancelStream(streamId); | 411 _vmCancelStream(streamId); |
344 } | 412 } |
345 | 413 |
346 return encodeSuccess(message); | 414 return encodeSuccess(message); |
347 } | 415 } |
348 | 416 |
| 417 static bool _hasNamespace(String method) => |
| 418 method.contains('.') && |
| 419 _getNamespace(method).startsWith(serviceNamespace); |
| 420 static String _getNamespace(String method) => method.split('.').first; |
| 421 static String _getMethod(String method) => method.split('.').last; |
| 422 |
| 423 Future<String> _registerService(Message message) async { |
| 424 final client = message.client; |
| 425 final service = message.params['service']; |
| 426 final alias = message.params['alias']; |
| 427 |
| 428 if (service is! String || service == '') { |
| 429 return encodeRpcError(message, kInvalidParams, |
| 430 details: "registerService: invalid 'service' parameter: ${service}"); |
| 431 } |
| 432 if (alias is! String || alias == '') { |
| 433 return encodeRpcError(message, kInvalidParams, |
| 434 details: "registerService: invalid 'alias' parameter: ${alias}"); |
| 435 } |
| 436 if (client.services.containsKey(service)) { |
| 437 return encodeRpcError(message, kServiceAlreadyRegistered); |
| 438 } |
| 439 client.services[service] = alias; |
| 440 |
| 441 bool removed; |
| 442 try { |
| 443 // Do not send streaming events to the client which registers the service |
| 444 removed = client.streams.remove(kServiceStream); |
| 445 await _sendServiceRegisteredEvent(client, service); |
| 446 } finally { |
| 447 if (removed) client.streams.add(kServiceStream); |
| 448 } |
| 449 |
| 450 return encodeSuccess(message); |
| 451 } |
| 452 |
| 453 _sendServiceRegisteredEvent(Client client, String service, |
| 454 {Client target}) async { |
| 455 final namespace = clients.keyOf(client); |
| 456 final alias = client.services[service]; |
| 457 final event = JSON.encode({ |
| 458 'jsonrpc': '2.0', |
| 459 'method': 'streamNotify', |
| 460 'params': { |
| 461 'streamId': kServiceStream, |
| 462 'event': { |
| 463 "type": "Event", |
| 464 "kind": "ServiceRegistered", |
| 465 'timestamp': new DateTime.now().millisecondsSinceEpoch, |
| 466 'service': service, |
| 467 'method': namespace + '.' + service, |
| 468 'alias': alias |
| 469 } |
| 470 } |
| 471 }); |
| 472 if (target == null) { |
| 473 _eventMessageHandler([kServiceStream, event]); |
| 474 } else { |
| 475 target.post(event); |
| 476 } |
| 477 } |
| 478 |
| 479 Future<String> _handleService(Message message) async { |
| 480 final namespace = _getNamespace(message.method); |
| 481 final method = _getMethod(message.method); |
| 482 final client = clients[namespace]; |
| 483 if (client != null) { |
| 484 if (client.services.containsKey(method)) { |
| 485 final id = _serviceRequests.newId(); |
| 486 final oldId = message.serial; |
| 487 final completer = new Completer<String>(); |
| 488 client.serviceHandles[id] = (Message m) { |
| 489 if (m != null) { |
| 490 completer.complete(JSON.encode(m.forwardToJson({'id': oldId}))); |
| 491 } else { |
| 492 completer.complete(encodeRpcError(message, kServiceDisappeared)); |
| 493 } |
| 494 }; |
| 495 client.post( |
| 496 JSON.encode(message.forwardToJson({'id': id, 'method': method}))); |
| 497 return completer.future; |
| 498 } |
| 499 } |
| 500 return encodeRpcError(message, kMethodNotFound, |
| 501 details: "Unknown service: ${message.method}"); |
| 502 } |
| 503 |
349 Future<String> _spawnUri(Message message) async { | 504 Future<String> _spawnUri(Message message) async { |
350 var token = message.params['token']; | 505 var token = message.params['token']; |
351 if (token == null) { | 506 if (token == null) { |
352 return encodeMissingParamError(message, 'token'); | 507 return encodeMissingParamError(message, 'token'); |
353 } | 508 } |
354 if (token is! String) { | 509 if (token is! String) { |
355 return encodeInvalidParamError(message, 'token'); | 510 return encodeInvalidParamError(message, 'token'); |
356 } | 511 } |
357 var uri = message.params['uri']; | 512 var uri = message.params['uri']; |
358 if (uri == null) { | 513 if (uri == null) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 var getFlagListResponse = responseAsJson( | 571 var getFlagListResponse = responseAsJson( |
417 await new Message.fromUri(client, getFlagList).sendToVM()); | 572 await new Message.fromUri(client, getFlagList).sendToVM()); |
418 responses[getFlagList.toString()] = getFlagListResponse['result']; | 573 responses[getFlagList.toString()] = getFlagListResponse['result']; |
419 | 574 |
420 // Make requests to each isolate. | 575 // Make requests to each isolate. |
421 for (var isolate in isolates) { | 576 for (var isolate in isolates) { |
422 for (var request in perIsolateRequests) { | 577 for (var request in perIsolateRequests) { |
423 var message = new Message.forIsolate(client, request, isolate); | 578 var message = new Message.forIsolate(client, request, isolate); |
424 // Decode the JSON and and insert it into the map. The map key | 579 // Decode the JSON and and insert it into the map. The map key |
425 // is the request Uri. | 580 // is the request Uri. |
426 var response = responseAsJson(await isolate.route(message)); | 581 var response = responseAsJson(await isolate.routeRequest(message)); |
427 responses[message.toUri().toString()] = response['result']; | 582 responses[message.toUri().toString()] = response['result']; |
428 } | 583 } |
429 // Dump the object id ring requests. | 584 // Dump the object id ring requests. |
430 var message = | 585 var message = |
431 new Message.forIsolate(client, Uri.parse('_dumpIdZone'), isolate); | 586 new Message.forIsolate(client, Uri.parse('_dumpIdZone'), isolate); |
432 var response = responseAsJson(await isolate.route(message)); | 587 var response = responseAsJson(await isolate.routeRequest(message)); |
433 // Insert getObject requests into responses map. | 588 // Insert getObject requests into responses map. |
434 for (var object in response['result']['objects']) { | 589 for (var object in response['result']['objects']) { |
435 final requestUri = | 590 final requestUri = |
436 'getObject&isolateId=${isolate.serviceId}?objectId=${object["id"]}'; | 591 'getObject&isolateId=${isolate.serviceId}?objectId=${object["id"]}'; |
437 responses[requestUri] = object; | 592 responses[requestUri] = object; |
438 } | 593 } |
439 } | 594 } |
440 | 595 |
441 // Encode the entire crash dump. | 596 // Encode the entire crash dump. |
442 return encodeResult(message, responses); | 597 return encodeResult(message, responses); |
443 } | 598 } |
444 | 599 |
445 Future<String> route(Message message) { | 600 Future routeRequest(Message message) async { |
446 if (message.completed) { | 601 try { |
| 602 if (message.completed) { |
| 603 return await message.response; |
| 604 } |
| 605 // TODO(turnidge): Update to json rpc. BEFORE SUBMIT. |
| 606 if (message.method == '_getCrashDump') { |
| 607 return await _getCrashDump(message); |
| 608 } |
| 609 if (message.method == 'streamListen') { |
| 610 return await _streamListen(message); |
| 611 } |
| 612 if (message.method == 'streamCancel') { |
| 613 return await _streamCancel(message); |
| 614 } |
| 615 if (message.method == '_registerService') { |
| 616 return await _registerService(message); |
| 617 } |
| 618 if (message.method == '_spawnUri') { |
| 619 return await _spawnUri(message); |
| 620 } |
| 621 if (devfs.shouldHandleMessage(message)) { |
| 622 return await devfs.handleMessage(message); |
| 623 } |
| 624 if (_hasNamespace(message.method)) { |
| 625 return await _handleService(message); |
| 626 } |
| 627 if (message.params['isolateId'] != null) { |
| 628 return await runningIsolates.routeRequest(message); |
| 629 } |
| 630 return await message.sendToVM(); |
| 631 } catch (e, st) { |
| 632 message.setErrorResponse(kInternalError, 'Unexpected exception:$e\n$st'); |
447 return message.response; | 633 return message.response; |
448 } | 634 } |
449 // TODO(turnidge): Update to json rpc. BEFORE SUBMIT. | 635 } |
450 if (message.method == '_getCrashDump') { | 636 |
451 return _getCrashDump(message); | 637 void routeResponse(message) { |
| 638 final client = message.client; |
| 639 if (client.serviceHandles.containsKey(message.serial)) { |
| 640 client.serviceHandles.remove(message.serial)(message); |
| 641 _serviceRequests.release(message.serial); |
452 } | 642 } |
453 if (message.method == 'streamListen') { | |
454 return _streamListen(message); | |
455 } | |
456 if (message.method == 'streamCancel') { | |
457 return _streamCancel(message); | |
458 } | |
459 if (message.method == '_spawnUri') { | |
460 return _spawnUri(message); | |
461 } | |
462 if (devfs.shouldHandleMessage(message)) { | |
463 return devfs.handleMessage(message); | |
464 } | |
465 if (message.params['isolateId'] != null) { | |
466 return runningIsolates.route(message); | |
467 } | |
468 return message.sendToVM(); | |
469 } | 643 } |
470 } | 644 } |
471 | 645 |
472 RawReceivePort boot() { | 646 RawReceivePort boot() { |
473 // Return the port we expect isolate control messages on. | 647 // Return the port we expect isolate control messages on. |
474 return isolateControlPort; | 648 return isolateControlPort; |
475 } | 649 } |
476 | 650 |
477 void _registerIsolate(int port_id, SendPort sp, String name) { | 651 void _registerIsolate(int port_id, SendPort sp, String name) { |
478 var service = new VMService(); | 652 var service = new VMService(); |
(...skipping 14 matching lines...) Expand all Loading... |
493 bool _vmListenStream(String streamId) native "VMService_ListenStream"; | 667 bool _vmListenStream(String streamId) native "VMService_ListenStream"; |
494 | 668 |
495 /// Cancel a subscription to a service stream. | 669 /// Cancel a subscription to a service stream. |
496 void _vmCancelStream(String streamId) native "VMService_CancelStream"; | 670 void _vmCancelStream(String streamId) native "VMService_CancelStream"; |
497 | 671 |
498 /// Get the bytes to the tar archive. | 672 /// Get the bytes to the tar archive. |
499 Uint8List _requestAssets() native "VMService_RequestAssets"; | 673 Uint8List _requestAssets() native "VMService_RequestAssets"; |
500 | 674 |
501 /// Notify the vm service that an isolate has been spawned via rpc. | 675 /// Notify the vm service that an isolate has been spawned via rpc. |
502 void _spawnUriNotify(obj, String token) native "VMService_spawnUriNotify"; | 676 void _spawnUriNotify(obj, String token) native "VMService_spawnUriNotify"; |
OLD | NEW |