Index: runtime/lib/developer.dart |
diff --git a/runtime/lib/developer.dart b/runtime/lib/developer.dart |
index 71b1f5ca009e2b59c77398e1342529162d8f6475..6a93d073127bb4da26cec426c30d34ba3453acc4 100644 |
--- a/runtime/lib/developer.dart |
+++ b/runtime/lib/developer.dart |
@@ -2,6 +2,8 @@ |
// 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. |
+import 'dart:isolate'; |
+ |
patch bool debugger({bool when: true, |
String message}) native "Developer_debugger"; |
@@ -55,3 +57,80 @@ patch ServiceExtensionHandler _lookupExtension(String method) |
patch _registerExtension(String method, ServiceExtensionHandler handler) |
native "Developer_registerExtension"; |
+ |
+// This code is only invoked when there is no other Dart code on the stack. |
+_runExtension(ServiceExtensionHandler handler, |
+ String method, |
+ List<String> parameterKeys, |
+ List<String> parameterValues, |
+ SendPort replyPort, |
+ Object id) { |
+ var parameters = {}; |
+ 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); |
+ return; |
+ } |
+ if (response is! Future) { |
+ response = new ServiceExtensionResponse.error( |
+ ServiceExtensionResponse.kExtensionError, |
+ "Extension handler must return a Future"); |
+ _postResponse(replyPort, id, response); |
+ 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); |
+ }).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) { |
+ assert(replyPort != null); |
+ if (id == null) { |
+ // No id -> no response. |
+ replyPort.send(null); |
+ return; |
+ } |
+ assert(id != null); |
+ StringBuffer sb = new StringBuffer(); |
+ sb.write('{"jsonrpc":"2.0",'); |
+ if (response._isError()) { |
+ sb.write('"error":'); |
+ } else { |
+ sb.write('"result":'); |
+ } |
+ sb.write('${response._toString()},'); |
+ if (id is String) { |
+ sb.write('"id":"$id"}'); |
+ } else { |
+ sb.write('"id":$id}'); |
+ } |
+ replyPort.send(sb.toString()); |
+} |