| // Copyright (c) 2015, 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. | |
| /// Note: the VM concatenates all patch files into a single patch file. This | |
| /// file is the first patch in "dart:developer" which contains all the imports | |
| /// used by patches of that library. We plan to change this when we have a | |
| /// shared front end and simply use parts. | |
| import "dart:_internal" show patch; | |
| import "dart:async" show Future, Zone; | |
| import "dart:isolate" show SendPort; | |
| /// These are the additional parts of this patch library: | |
| // part "profiler.dart" | |
| // part "timeline.dart" | |
| @patch | |
| bool debugger({bool when: true, String message}) native "Developer_debugger"; | |
| @patch | |
| Object inspect(Object object) native "Developer_inspect"; | |
| @patch | |
| void log(String message, | |
| {DateTime time, | |
| int sequenceNumber, | |
| int level: 0, | |
| String name: '', | |
| Zone zone, | |
| Object error, | |
| StackTrace stackTrace}) { | |
| if (message is! String) { | |
| throw new ArgumentError.value(message, "message", "Must be a String"); | |
| } | |
| time ??= new DateTime.now(); | |
| if (time is! DateTime) { | |
| throw new ArgumentError.value(time, "time", "Must be a DateTime"); | |
| } | |
| if (sequenceNumber == null) { | |
| sequenceNumber = _nextSequenceNumber++; | |
| } else { | |
| _nextSequenceNumber = sequenceNumber + 1; | |
| } | |
| _log(message, time.millisecondsSinceEpoch, sequenceNumber, level, name, zone, | |
| error, stackTrace); | |
| } | |
| int _nextSequenceNumber = 0; | |
| _log(String message, int timestamp, int sequenceNumber, int level, String name, | |
| Zone zone, Object error, StackTrace stackTrace) native "Developer_log"; | |
| @patch | |
| void _postEvent(String eventKind, String eventData) | |
| native "Developer_postEvent"; | |
| @patch | |
| ServiceExtensionHandler _lookupExtension(String method) | |
| native "Developer_lookupExtension"; | |
| @patch | |
| _registerExtension(String method, ServiceExtensionHandler handler) | |
| native "Developer_registerExtension"; | |
| // This code is only invoked when there is no other Dart code on the stack. | |
| @pragma("vm:entry-point", !const bool.fromEnvironment("dart.vm.product")) | |
| _runExtension( | |
| ServiceExtensionHandler handler, | |
| String method, | |
| List<String> parameterKeys, | |
| List<String> parameterValues, | |
| SendPort replyPort, | |
| Object id, | |
| bool trace_service) { | |
| var parameters = <String, String>{}; | |
| for (var i = 0; i < parameterKeys.length; i++) { | |
| parameters[parameterKeys[i]] = parameterValues[i]; | |
| } | |
| var response; | |
| try { | |
| response = handler(method, parameters); | |
| } catch (e, st) { | |
| var errorDetails = (st == null) ? '$e' : '$e\n$st'; | |
| response = new ServiceExtensionResponse.error( | |
| ServiceExtensionResponse.kExtensionError, errorDetails); | |
| _postResponse(replyPort, id, response, trace_service); | |
| return; | |
| } | |
| if (response is! Future) { | |
| response = new ServiceExtensionResponse.error( | |
| ServiceExtensionResponse.kExtensionError, | |
| "Extension handler must return a Future"); | |
| _postResponse(replyPort, id, response, trace_service); | |
| return; | |
| } | |
| response.catchError((e, st) { | |
| // Catch any errors eagerly and wrap them in a ServiceExtensionResponse. | |
| var errorDetails = (st == null) ? '$e' : '$e\n$st'; | |
| return new ServiceExtensionResponse.error( | |
| ServiceExtensionResponse.kExtensionError, errorDetails); | |
| }).then((response) { | |
| // Post the valid response or the wrapped error after verifying that | |
| // the response is a ServiceExtensionResponse. | |
| if (response is! ServiceExtensionResponse) { | |
| response = new ServiceExtensionResponse.error( | |
| ServiceExtensionResponse.kExtensionError, | |
| "Extension handler must complete to a ServiceExtensionResponse"); | |
| } | |
| _postResponse(replyPort, id, response, trace_service); | |
| }).catchError((e, st) { | |
| // We do not expect any errors to occur in the .then or .catchError blocks | |
| // but, suppress them just in case. | |
| }); | |
| } | |
| // This code is only invoked by _runExtension. | |
| _postResponse(SendPort replyPort, Object id, ServiceExtensionResponse response, | |
| bool trace_service) { | |
| assert(replyPort != null); | |
| if (id == null) { | |
| if (trace_service) { | |
| print("vm-service: posting no response for request"); | |
| } | |
| // No id -> no response. | |
| replyPort.send(null); | |
| return; | |
| } | |
| assert(id != null); | |
| StringBuffer sb = new StringBuffer(); | |
| sb.write('{"jsonrpc":"2.0",'); | |
| if (response.isError()) { | |
| if (trace_service) { | |
| print("vm-service: posting error response for request $id"); | |
| } | |
| sb.write('"error":'); | |
| } else { | |
| if (trace_service) { | |
| print("vm-service: posting response for request $id"); | |
| } | |
| sb.write('"result":'); | |
| } | |
| sb.write('${response._toString()},'); | |
| if (id is String) { | |
| sb.write('"id":"$id"}'); | |
| } else { | |
| sb.write('"id":$id}'); | |
| } | |
| replyPort.send(sb.toString()); | |
| } | |
| @patch | |
| int _getServiceMajorVersion() native "Developer_getServiceMajorVersion"; | |
| @patch | |
| int _getServiceMinorVersion() native "Developer_getServiceMinorVersion"; | |
| @patch | |
| void _getServerInfo(SendPort sendPort) native "Developer_getServerInfo"; | |
| @patch | |
| void _webServerControl(SendPort sendPort, bool enable) | |
| native "Developer_webServerControl"; | |
| @patch | |
| String _getIsolateIDFromSendPort(SendPort sendPort) | |
| native "Developer_getIsolateIDFromSendPort"; |