| 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());
|
| +}
|
|
|