| // 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"; |