Index: sdk/lib/isolate/isolate.dart |
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart |
index 65f0bcee02574313998ee011a885107e84cb47c7..4a4a104d9c75842db406df2a9678e255ee36afba 100644 |
--- a/sdk/lib/isolate/isolate.dart |
+++ b/sdk/lib/isolate/isolate.dart |
@@ -47,6 +47,7 @@ class Isolate { |
* Capability granting the ability to pause the isolate. |
*/ |
final Capability pauseCapability; |
+ |
/** |
* Capability granting the ability to terminate the isolate. |
*/ |
@@ -298,6 +299,80 @@ class Isolate { |
..[2] = pingType; |
controlPort.send(message); |
} |
+ |
+ /** |
+ * Requests that uncaught errors of the isolate are sent back to [port]. |
+ * |
+ * The errors are sent back as two elements lists. |
+ * The first element is a `String` representation of the error, usually |
+ * created by calling `toString` on the error. |
+ * The second element is a `String` representation of an accompanying |
+ * stack trace, or `null` if no stack trace was provided. |
+ * |
+ * Listening using the same port more than once does nothing. It will only |
+ * get each error once. |
+ */ |
+ void addErrorListener(SendPort port) { |
+ var message = new List(2) |
+ ..[0] = "getErrors" |
+ ..[1] = port; |
+ controlPort.send(message); |
+ } |
+ |
+ /** |
+ * Stop listening for uncaught errors through [port]. |
+ * |
+ * The `port` should be a port that is listening for errors through |
+ * [addErrorListener]. This call requests that the isolate stops sending |
+ * errors on the port. |
+ * |
+ * If the same port has been passed via `addErrorListener` more than once, |
+ * only one call to `removeErrorListener` is needed to stop it from receiving |
+ * errors. |
+ * |
+ * Closing the receive port at the end of the send port will not stop the |
+ * isolate from sending errors, they are just going to be lost. |
+ */ |
+ void removeErrorListener(SendPort port) { |
+ var message = new List(2) |
+ ..[0] = "stopErrors" |
+ ..[1] = port; |
+ controlPort.send(message); |
+ } |
+ |
+ /** |
+ * Returns a broadcast stream of uncaught errors from the isolate. |
+ * |
+ * Each error is provided as an error event on the stream. |
+ * |
+ * The actual error object and stackTraces will not necessarily |
+ * be the same object types as in the actual isolate, but they will |
+ * always have the same [Object.toString] result. |
+ * |
+ * This stream is based on [addErrorListener] and [removeErrorListener]. |
+ */ |
+ Stream get errors { |
+ StreamController controller; |
+ RawReceivePort port; |
+ void handleError(message) { |
+ String errorDescription = message[0]; |
+ String stackDescription = message[1]; |
+ var error = new RemoteError(errorDescription, stackDescription); |
+ controller.addError(error, error.stackTrace); |
+ } |
+ controller = new StreamController.broadcast( |
+ sync: true, |
+ onListen: () { |
+ port = new RawReceivePort(handleError); |
+ this.addErrorListener(port.sendPort); |
+ }, |
+ onCancel: () { |
+ this.removeErrorListener(port.sendPort); |
+ port.close(); |
+ port = null; |
+ }); |
+ return controller.stream; |
+ } |
} |
/** |
@@ -464,3 +539,24 @@ class _IsolateUnhandledException implements Exception { |
'${stackTrace.toString().replaceAll("\n","\n ")}'; |
} |
} |
+ |
+/** |
+ * Description of an error from another isolate. |
+ * |
+ * This error has the same `toString()` and `stackTrace.toString()` behavior |
+ * as the original error, but has no other features of the original error. |
+ */ |
+class RemoteError implements Error { |
+ final String _description; |
+ final StackTrace stackTrace; |
+ RemoteError(String description, String stackDescription) |
+ : _description = description, |
+ stackTrace = new _RemoteStackTrace(stackDescription); |
+ String toString() => _description; |
+} |
+ |
+class _RemoteStackTrace implements StackTrace { |
+ String _trace; |
+ _RemoteStackTrace(this._trace); |
+ String toString() => _trace; |
+} |