New implementation of runZoned.

A combination of `runZoned` and `runZonedGuarded` where only the latter allows an `onError` parameter,
and only that has a nullable return type.

Retains the `onError` parameter on `runZoned` for now because it's too breaking to remove it until packages have been migrated off of it.
It will be removed in a follow-up CL.

Change-Id: If0e86c8d14e13fa089c66f4af975aeacb2616cf6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/137302
Reviewed-by: Jake Macdonald <jakemac@google.com>
Reviewed-by: Nate Bosch <nbosch@google.com>
This commit is contained in:
Lasse R.H. Nielsen 2020-03-25 00:24:33 +00:00 committed by Leaf Petersen
parent 289c4d5990
commit 8760283247
44 changed files with 315 additions and 252 deletions

View file

@ -13,6 +13,13 @@
stack trace rather than propagate a `null` value.
Error handling functions need no longer be prepared for `null` stack traces.
* **Breaking change**: [#40681](https://github.com/dart-lang/sdk/issues/40681)
The `runZoned` function is split into two functions: `runZoned` and
`runZonedGuarded`, where the latter has a required `onError` parameter,
and the former has none.
This prepares the functions for Null Safety where the two functions will
differ in the nullability of their return types.
#### `dart:core`
* Adds `StackTrace.empty` constant which is the stack trace used as default
@ -137,6 +144,18 @@ used (see Issue [39627][]).
address in byte format for Internet addresses or raw file path for Unix
domain addresses.
* **Breaking change** [#40681](https://github.com/dart-lang/sdk/issues/40681)
The static method `runZoned` and `runWithHttpOverrides` on `HttpOverrides`
no longer accept `zoneSpecification` and `onError` parameters.
Use the `runZoned` or `runZonedGuarded` functions from `dart:async`
directly if needing to specify those.
* **Breaking change** [#40681](https://github.com/dart-lang/sdk/issues/40681)
The static method `runZoned` and `runWithIOOverrides` on `IOOverrides`
no longer accept `zoneSpecification` and `onError` parameters.
Use the `runZoned` or `runZonedGuarded` functions from `dart:async`
directly if needing to specify those.
#### `dart:mirrors`
* Added `MirrorSystem.neverType`.

View file

@ -312,7 +312,7 @@ class AnalysisServer extends AbstractAnalysisServer {
/// Handle a [request] that was read from the communication channel.
void handleRequest(Request request) {
performance.logRequestTiming(request.clientRequestTime);
runZoned(() {
runZonedGuarded(() {
ServerPerformanceStatistics.serverRequests.makeCurrentWhile(() {
int count = handlers.length;
for (int i = 0; i < count; i++) {
@ -341,7 +341,7 @@ class AnalysisServer extends AbstractAnalysisServer {
}
channel.sendResponse(Response.unknownRequest(request));
});
}, onError: (exception, stackTrace) {
}, (exception, stackTrace) {
AnalysisEngine.instance.instrumentationService.logException(
FatalException('Failed to handle request: ${request.method}',
exception, stackTrace));

View file

@ -144,9 +144,9 @@ class ByteStreamServerChannel implements ServerCommunicationChannel {
/// Send the string [s] to [_output] followed by a newline.
void _outputLine(String s) {
runZoned(() {
runZonedGuarded(() {
_output.writeln(s);
}, onError: (e) {
}, (e, s) {
close();
});
}

View file

@ -217,7 +217,7 @@ class CompletionDomainHandler extends AbstractRequestHandler {
);
}
return runZoned(() {
return runZonedGuarded(() {
String requestName = request.method;
if (requestName == COMPLETION_REQUEST_GET_SUGGESTION_DETAILS) {
@ -233,7 +233,7 @@ class CompletionDomainHandler extends AbstractRequestHandler {
return setSubscriptions(request);
}
return null;
}, onError: (exception, stackTrace) {
}, (exception, stackTrace) {
AnalysisEngine.instance.instrumentationService.logException(
CaughtException.withMessage(
'Failed to handle completion domain request: ${request.method}',

View file

@ -942,7 +942,7 @@ class _RefactoringManager {
?.sendEvent('refactor', params.kind.name.toLowerCase());
}
runZoned(() async {
runZonedGuarded(() async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
await _init(params.kind, file, params.offset, params.length);
@ -990,7 +990,7 @@ class _RefactoringManager {
_checkForReset_afterCreateChange();
result.potentialEdits = nullIfEmpty(refactoring.potentialEditIds);
_sendResultResponse();
}, onError: (exception, stackTrace) {
}, (exception, stackTrace) {
if (exception is _ResetError ||
exception is InconsistentAnalysisException) {
cancel();

View file

@ -128,9 +128,9 @@ class LspByteStreamServerChannel implements LspServerCommunicationChannel {
/// Send [bytes] to [_output].
void _write(List<int> bytes) {
runZoned(
runZonedGuarded(
() => _output.add(bytes),
onError: (e) => close(),
(e, s) => close(),
);
}
}

View file

@ -245,7 +245,7 @@ class LspAnalysisServer extends AbstractAnalysisServer {
/// Handle a [message] that was read from the communication channel.
void handleMessage(Message message) {
performance.logRequestTiming(null);
runZoned(() {
runZonedGuarded(() {
ServerPerformanceStatistics.serverRequests.makeCurrentWhile(() async {
try {
if (message is ResponseMessage) {
@ -284,7 +284,7 @@ class LspAnalysisServer extends AbstractAnalysisServer {
logException(errorMessage, error, stackTrace);
}
});
}, onError: socketError);
}, socketError);
}
/// Logs the error on the client using window/logMessage.

View file

@ -140,10 +140,10 @@ Future listenAsyncStarThrowAsync() async {
Future<void> customErrorZone() async {
final completer = Completer<void>();
runZoned(() async {
runZonedGuarded(() async {
await allYield();
completer.complete(null);
}, onError: (e, s) {
}, (e, s) {
completer.completeError(e, s);
});
return completer.future;
@ -550,7 +550,7 @@ Future<void> doTestsCausal() async {
r'#5 _rootRun ',
r'#6 _CustomZone.run ',
r'#7 _runZoned ',
r'#8 runZoned ',
r'#8 runZonedGuarded ',
r'#9 customErrorZone \(.*/utils.dart:143(:3)?\)$',
];
await doTestAwait(

View file

@ -14,9 +14,9 @@ main(args) async {
{
final caughtErrorCompleter = Completer<String>();
await runZoned(() {
await runZonedGuarded(() {
Isolate.spawn(isolate, x);
}, onError: (e) {
}, (e, s) {
caughtErrorCompleter.complete(e.toString());
});
Expect.equals(

View file

@ -51,27 +51,20 @@ abstract class HttpOverrides {
static R runZoned<R>(R body(),
{HttpClient Function(SecurityContext) createHttpClient,
String Function(Uri uri, Map<String, String> environment)
findProxyFromEnvironment,
ZoneSpecification zoneSpecification,
Function onError}) {
findProxyFromEnvironment}) {
HttpOverrides overrides =
new _HttpOverridesScope(createHttpClient, findProxyFromEnvironment);
return _asyncRunZoned<R>(body,
zoneValues: {_httpOverridesToken: overrides},
zoneSpecification: zoneSpecification,
onError: onError);
zoneValues: {_httpOverridesToken: overrides});
}
/// Runs [body] in a fresh [Zone] using the overrides found in [overrides].
///
/// Note that [overrides] should be an instance of a class that extends
/// [HttpOverrides].
static R runWithHttpOverrides<R>(R body(), HttpOverrides overrides,
{ZoneSpecification zoneSpecification, Function onError}) {
static R runWithHttpOverrides<R>(R body(), HttpOverrides overrides) {
return _asyncRunZoned<R>(body,
zoneValues: {_httpOverridesToken: overrides},
zoneSpecification: zoneSpecification,
onError: onError);
zoneValues: {_httpOverridesToken: overrides});
}
/// Returns a new [HttpClient] using the given [context].

View file

@ -1467,43 +1467,91 @@ const _rootZone = const _RootZone();
* var future2 = future.then((_) { throw "error in first error-zone"; });
* runZoned(() {
* var future3 = future2.catchError((e) { print("Never reached!"); });
* }, onError: (e) { print("unused error handler"); });
* }, onError: (e) { print("catches error of first error-zone."); });
* }, onError: (e, s) { print("unused error handler"); });
* }, onError: (e, s) { print("catches error of first error-zone."); });
*
* Example:
*
* runZoned(() {
* new Future(() { throw "asynchronous error"; });
* }, onError: print); // Will print "asynchronous error".
* }, onError: (e, s) => print(e)); // Will print "asynchronous error".
*
* It is possible to manually pass an error from one error zone to another
* by re-throwing it in the new zone. If [onError] throws, that error will
* occur in the original zone where [runZoned] was called.
*/
R runZoned<R>(R body(),
{Map zoneValues, ZoneSpecification zoneSpecification, Function onError}) {
if (onError == null) {
{Map zoneValues,
ZoneSpecification zoneSpecification,
@Deprecated("Use runZonedGuarded instead") Function onError}) {
ArgumentError.checkNotNull(body, "body");
if (onError != null) {
void Function(Object, StackTrace) typedOnError;
if (onError is void Function(Object, StackTrace)) {
typedOnError = onError;
} else if (onError is void Function(Object)) {
typedOnError = (Object e, StackTrace _) => onError(e);
} else {
throw ArgumentError.value(onError, "onError",
"Should accept one error, or one error and a stack trace");
}
return runZonedGuarded(body, typedOnError,
zoneValues: zoneValues, zoneSpecification: zoneSpecification);
}
return _runZoned<R>(body, zoneValues, zoneSpecification);
}
void Function(Object) unaryOnError;
void Function(Object, StackTrace) binaryOnError;
if (onError is void Function(Object, StackTrace)) {
binaryOnError = onError;
} else if (onError is void Function(Object)) {
unaryOnError = onError;
} else {
throw new ArgumentError("onError callback must take either an Object "
"(the error), or both an Object (the error) and a StackTrace.");
}
/**
* Runs [body] in its own error zone.
*
* Creates a new zone using [Zone.fork] based on [zoneSpecification] and
* [zoneValues], then runs [body] in that zone and returns the result.
*
* The [onError] function is used *both* to handle asynchronous errors
* by overriding [ZoneSpecification.handleUncaughtError] in [zoneSpecification],
* if any, *and* to handle errors thrown synchronously by the call to [body].
*
* If an error occurs synchronously in [body],
* then throwing in the [onError] handler
* makes the call to `runZonedGuarded` throw that error,
* and otherwise the call to `runZonedGuarded` returns `null`.
*
* If the zone specification has a `handleUncaughtError` value or the [onError]
* parameter is provided, the zone becomes an error-zone.
*
* Errors will never cross error-zone boundaries by themselves.
* Errors that try to cross error-zone boundaries are considered uncaught in
* their originating error zone.
*
* var future = new Future.value(499);
* runZoned(() {
* var future2 = future.then((_) { throw "error in first error-zone"; });
* runZoned(() {
* var future3 = future2.catchError((e) { print("Never reached!"); });
* }, onError: (e, s) { print("unused error handler"); });
* }, onError: (e, s) { print("catches error of first error-zone."); });
*
* Example:
*
* runZoned(() {
* new Future(() { throw "asynchronous error"; });
* }, onError: (e, s) => print(e)); // Will print "asynchronous error".
*
* It is possible to manually pass an error from one error zone to another
* by re-throwing it in the new zone. If [onError] throws, that error will
* occur in the original zone where [runZoned] was called.
*/
@Since("2.8")
R runZonedGuarded<R>(R body(), void onError(Object error, StackTrace stack),
{Map zoneValues, ZoneSpecification zoneSpecification}) {
ArgumentError.checkNotNull(body, "body");
ArgumentError.checkNotNull(onError, "onError");
HandleUncaughtErrorHandler errorHandler = (Zone self, ZoneDelegate parent,
Zone zone, error, StackTrace stackTrace) {
try {
if (binaryOnError != null) {
self.parent.runBinary(binaryOnError, error, stackTrace);
} else {
assert(unaryOnError != null);
self.parent.runUnary(unaryOnError, error);
}
self.parent.runBinary(onError, error, stackTrace);
} catch (e, s) {
if (identical(e, error)) {
parent.handleUncaughtError(zone, error, stackTrace);
@ -1521,13 +1569,8 @@ R runZoned<R>(R body(),
}
try {
return _runZoned<R>(body, zoneValues, zoneSpecification);
} catch (e, stackTrace) {
if (binaryOnError != null) {
binaryOnError(e, stackTrace);
} else {
assert(unaryOnError != null);
unaryOnError(e);
}
} catch (error, stackTrace) {
onError(error, stackTrace);
}
return null;
}

View file

@ -92,11 +92,7 @@ abstract class IOOverrides {
// ServerSocket
Future<ServerSocket> Function(dynamic, int,
{int backlog, bool v6Only, bool shared})
serverSocketBind,
// Optional Zone parameters
ZoneSpecification zoneSpecification,
Function onError}) {
serverSocketBind}) {
IOOverrides overrides = new _IOOverridesScope(
// Directory
createDirectory,
@ -131,22 +127,15 @@ abstract class IOOverrides {
// ServerSocket
serverSocketBind,
);
return _asyncRunZoned<R>(body,
zoneValues: {_ioOverridesToken: overrides},
zoneSpecification: zoneSpecification,
onError: onError);
return _asyncRunZoned<R>(body, zoneValues: {_ioOverridesToken: overrides});
}
/// Runs [body] in a fresh [Zone] using the overrides found in [overrides].
///
/// Note that [overrides] should be an instance of a class that extends
/// [IOOverrides].
static R runWithIOOverrides<R>(R body(), IOOverrides overrides,
{ZoneSpecification zoneSpecification, Function onError}) {
return _asyncRunZoned<R>(body,
zoneValues: {_ioOverridesToken: overrides},
zoneSpecification: zoneSpecification,
onError: onError);
static R runWithIOOverrides<R>(R body(), IOOverrides overrides) {
return _asyncRunZoned<R>(body, zoneValues: {_ioOverridesToken: overrides});
}
// Directory

View file

@ -49,27 +49,20 @@ abstract class HttpOverrides {
static R runZoned<R>(R body(),
{HttpClient Function(SecurityContext?)? createHttpClient,
String Function(Uri uri, Map<String, String>? environment)?
findProxyFromEnvironment,
ZoneSpecification? zoneSpecification,
Function? onError}) {
findProxyFromEnvironment}) {
HttpOverrides overrides =
new _HttpOverridesScope(createHttpClient, findProxyFromEnvironment);
return _asyncRunZoned<R>(body,
zoneValues: {_httpOverridesToken: overrides},
zoneSpecification: zoneSpecification,
onError: onError);
zoneValues: {_httpOverridesToken: overrides});
}
/// Runs [body] in a fresh [Zone] using the overrides found in [overrides].
///
/// Note that [overrides] should be an instance of a class that extends
/// [HttpOverrides].
static R runWithHttpOverrides<R>(R body(), HttpOverrides overrides,
{ZoneSpecification? zoneSpecification, Function? onError}) {
static R runWithHttpOverrides<R>(R body(), HttpOverrides overrides) {
return _asyncRunZoned<R>(body,
zoneValues: {_httpOverridesToken: overrides},
zoneSpecification: zoneSpecification,
onError: onError);
zoneValues: {_httpOverridesToken: overrides});
}
/// Returns a new [HttpClient] using the given [context].

View file

@ -1465,7 +1465,7 @@ const _Zone _rootZone = const _RootZone();
* If an error occurs synchronously in [body],
* then throwing in the [onError] handler
* makes the call to `runZone` throw that error,
* and otherwise the call to `runZoned` returns `null`.
* and otherwise the call to `runZoned` attempt to return `null`.
*
* If the zone specification has a `handleUncaughtError` value or the [onError]
* parameter is provided, the zone becomes an error-zone.
@ -1474,19 +1474,19 @@ const _Zone _rootZone = const _RootZone();
* Errors that try to cross error-zone boundaries are considered uncaught in
* their originating error zone.
*
* var future = Future.value(499);
* var future = new Future.value(499);
* runZoned(() {
* var future2 = future.then((_) { throw "error in first error-zone"; });
* runZoned(() {
* var future3 = future2.catchError((e) { print("Never reached!"); });
* }, onError: (e) { print("unused error handler"); });
* }, onError: (e) { print("catches error of first error-zone."); });
* }, onError: (e, s) { print("unused error handler"); });
* }, onError: (e, s) { print("catches error of first error-zone."); });
*
* Example:
*
* runZoned(() {
* new Future(() { throw "asynchronous error"; });
* }, onError: print); // Will print "asynchronous error".
* }, onError: (e, s) => print(e)); // Will print "asynchronous error".
*
* It is possible to manually pass an error from one error zone to another
* by re-throwing it in the new zone. If [onError] throws, that error will
@ -1495,30 +1495,74 @@ const _Zone _rootZone = const _RootZone();
R runZoned<R>(R body(),
{Map<Object?, Object?>? zoneValues,
ZoneSpecification? zoneSpecification,
Function? onError}) {
if (onError == null) {
@Deprecated("Use runZonedGuarded instead") Function? onError}) {
ArgumentError.checkNotNull(body, "body");
if (onError != null) {
// TODO: Remove this when code have been migrated off using [onError].
if (onError is! void Function(Object, StackTrace)) {
if (onError is void Function(Object)) {
var originalOnError = onError;
onError = (Object error, StackTrace stack) => originalOnError(error);
} else {
throw ArgumentError.value(onError, "onError",
"Must be Function(Object) or Function(Object, StackTrace)");
}
}
return runZonedGuarded(body, onError,
zoneSpecification: zoneSpecification, zoneValues: zoneValues) as R;
}
return _runZoned<R>(body, zoneValues, zoneSpecification);
}
void Function(Object)? unaryOnError;
void Function(Object, StackTrace)? binaryOnError;
if (onError is void Function(Object, StackTrace)) {
binaryOnError = onError;
} else if (onError is void Function(Object)) {
unaryOnError = onError;
} else {
throw new ArgumentError("onError callback must take either an Object "
"(the error), or both an Object (the error) and a StackTrace.");
}
/**
* Runs [body] in its own error zone.
*
* Creates a new zone using [Zone.fork] based on [zoneSpecification] and
* [zoneValues], then runs [body] in that zone and returns the result.
*
* The [onError] function is used *both* to handle asynchronous errors
* by overriding [ZoneSpecification.handleUncaughtError] in [zoneSpecification],
* if any, *and* to handle errors thrown synchronously by the call to [body].
*
* If an error occurs synchronously in [body],
* then throwing in the [onError] handler
* makes the call to `runZonedGuarded` throw that error,
* and otherwise the call to `runZonedGuarded` returns `null`.
*
* The zone will always be an error-zone.
*
* Errors will never cross error-zone boundaries by themselves.
* Errors that try to cross error-zone boundaries are considered uncaught in
* their originating error zone.
* ```dart
* var future = Future.value(499);
* runZonedGuarded(() {
* var future2 = future.then((_) { throw "error in first error-zone"; });
* runZonedGuarded(() {
* var future3 = future2.catchError((e) { print("Never reached!"); });
* }, (e, s) { print("unused error handler"); });
* }, (e, s) { print("catches error of first error-zone."); });
* ```
* Example:
* ```dart
* runZonedGuarded(() {
* new Future(() { throw "asynchronous error"; });
* }, (e, s) => print(e)); // Will print "asynchronous error".
* ```
* It is possible to manually pass an error from one error zone to another
* by re-throwing it in the new zone. If [onError] throws, that error will
* occur in the original zone where [runZoned] was called.
*/
@Since("2.8")
R? runZonedGuarded<R>(R body(), void onError(Object error, StackTrace stack),
{Map<Object?, Object?>? zoneValues, ZoneSpecification? zoneSpecification}) {
ArgumentError.checkNotNull(body, "body");
ArgumentError.checkNotNull(onError, "onError");
_Zone parentZone = Zone._current;
HandleUncaughtErrorHandler errorHandler = (Zone self, ZoneDelegate parent,
Zone zone, Object error, StackTrace stackTrace) {
try {
if (binaryOnError != null) {
parentZone.runBinary(binaryOnError, error, stackTrace);
} else {
assert(unaryOnError != null);
parentZone.runUnary(unaryOnError!, error);
}
parentZone.runBinary(onError, error, stackTrace);
} catch (e, s) {
if (identical(e, error)) {
parent.handleUncaughtError(zone, error, stackTrace);
@ -1536,17 +1580,10 @@ R runZoned<R>(R body(),
}
try {
return _runZoned<R>(body, zoneValues, zoneSpecification);
} catch (e, stackTrace) {
if (binaryOnError != null) {
binaryOnError(e, stackTrace);
} else {
assert(unaryOnError != null);
unaryOnError!(e);
} catch (error, stackTrace) {
onError(error, stackTrace);
}
}
// TODO(lrn): Change behavior to throw the actual resulting error,
// perhaps even synchronously.
return null as R;
return null;
}
/// Runs [body] in a new zone based on [zoneValues] and [specification].

View file

@ -90,11 +90,7 @@ abstract class IOOverrides {
// ServerSocket
Future<ServerSocket> Function(dynamic, int,
{int backlog, bool v6Only, bool shared})?
serverSocketBind,
// Optional Zone parameters
ZoneSpecification? zoneSpecification,
Function? onError}) {
serverSocketBind}) {
IOOverrides overrides = new _IOOverridesScope(
// Directory
createDirectory,
@ -129,22 +125,15 @@ abstract class IOOverrides {
// ServerSocket
serverSocketBind,
);
return _asyncRunZoned<R>(body,
zoneValues: {_ioOverridesToken: overrides},
zoneSpecification: zoneSpecification,
onError: onError);
return _asyncRunZoned<R>(body, zoneValues: {_ioOverridesToken: overrides});
}
/// Runs [body] in a fresh [Zone] using the overrides found in [overrides].
///
/// Note that [overrides] should be an instance of a class that extends
/// [IOOverrides].
static R runWithIOOverrides<R>(R body(), IOOverrides overrides,
{ZoneSpecification? zoneSpecification, Function? onError}) {
return _asyncRunZoned<R>(body,
zoneValues: {_ioOverridesToken: overrides},
zoneSpecification: zoneSpecification,
onError: onError);
static R runWithIOOverrides<R>(R body(), IOOverrides overrides) {
return _asyncRunZoned<R>(body, zoneValues: {_ioOverridesToken: overrides});
}
// Directory

View file

@ -11,7 +11,7 @@ Stream catchErrors(dynamic body()) {
}
void onListen() {
runZoned(body, onError: onError);
runZonedGuarded(body, onError);
}
controller = new StreamController(onListen: onListen);
@ -21,7 +21,7 @@ Stream catchErrors(dynamic body()) {
runZonedScheduleMicrotask(body(),
{void onScheduleMicrotask(void callback()), Function? onError}) {
if (onScheduleMicrotask == null) {
return runZoned(body, onError: onError);
return runZonedGuarded(body, onError);
}
HandleUncaughtErrorHandler errorHandler;
if (onError != null) {

View file

@ -868,7 +868,7 @@ void testWaitCleanUpError() {
asyncStart();
asyncStart();
asyncStart();
runZoned(() {
runZonedGuarded(() {
Future.wait([
new Future.delayed(cms, () => 0),
new Future.delayed(cms * 2, () => throw 1),
@ -882,7 +882,7 @@ void testWaitCleanUpError() {
Expect.equals(e, 1);
asyncEnd();
});
}, onError: (e, s) {
}, (e, s) {
int index = e;
Expect.isTrue(index == 0 || index == 2, "$index");
Expect.isFalse(uncaughts[index]);

View file

@ -10,7 +10,7 @@ main() {
// error handler is defined.
Expect.equals(
499,
runZoned(() => 499, onError: (e) {
runZonedGuarded(() => 499, (e, s) {
throw "Unexpected";
}));
}

View file

@ -9,9 +9,9 @@ import 'dart:async';
main() {
asyncStart();
// Ensure that `runZoned`'s onError handles synchronous errors.
runZoned(() {
runZonedGuarded(() {
throw 0;
}, onError: (e) {
}, (e, s) {
Expect.equals(0, e);
asyncEnd();
});

View file

@ -12,9 +12,9 @@ main() {
// in the error handler at that point (when it is a synchronous error) yields
// a synchronous error.
try {
runZoned(() {
runZonedGuarded(() {
throw 0;
}, onError: (e) {
}, (e, s) {
Expect.equals(0, e);
throw e; //#01 : ok
asyncEnd();

View file

@ -13,7 +13,7 @@ main() {
var events = [];
// Test runZoned with periodic Timers.
runZoned(() {
runZonedGuarded(() {
int counter = 0;
new Timer.periodic(const Duration(milliseconds: 50), (timer) {
if (counter == 1) {
@ -24,7 +24,7 @@ main() {
events.add(counter);
throw counter;
});
}, onError: (e, [s]) {
}, (e, [s]) {
events.add("error: $e");
Expect.isNotNull(s); // Regression test for http://dartbug.com/33589
});

View file

@ -12,15 +12,15 @@ main() {
// to the next runZoned when the handler returns false.
bool sawInnerHandler = false;
try {
runZoned(() {
runZonedGuarded(() {
runZoned(() {
throw 0;
}, onError: (e) {
}, onError: (e, s) {
Expect.equals(0, e);
sawInnerHandler = true;
throw e;
});
}, onError: (e) {
}, (e, s) {
Expect.equals(0, e);
Expect.isTrue(sawInnerHandler);
// If we are waiting for an error, don't asyncEnd, but let it time out.

View file

@ -267,7 +267,7 @@ main() {
bool streamIsDone = false;
int errorCount = 0;
runZoned(() {
runZonedGuarded(() {
controller.stream
.transform(new SinkTransformer((sink) =>
new FutureWaitingTransformerSink(sink, closeCompleter.future)))
@ -280,7 +280,7 @@ main() {
Expect.listEquals([], events);
streamIsDone = true;
});
}, onError: (e) {
}, (e, s) {
Expect.isTrue(e is StateError);
errorCount++;
});

View file

@ -114,7 +114,7 @@ main() {
});
test("subscription.asFuture failure in cancel", () {
runZoned(() {
runZonedGuarded(() {
var completer = new Completer();
var controller =
new StreamController(onCancel: () => completer.future, sync: true);
@ -135,7 +135,7 @@ main() {
Expect.isFalse(catchErrorHasRun);
completer.completeError(499);
}));
}, onError: expectAsync((e) {
}, expectAsync2((e, s) {
Expect.equals(499, e);
}));
});

View file

@ -10,8 +10,8 @@ import 'dart:async';
test1() {
var events = [];
var done = new Completer();
runZoned(() {
runZoned(() {
runZonedGuarded(() {
runZonedGuarded(() {
var c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"),
@ -19,8 +19,8 @@ test1() {
c.add(1);
c.addError(2);
c.close();
}, onError: (x) => events.add("rza: error $x"));
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rza: error $e"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {
@ -33,18 +33,18 @@ test1() {
test2() {
var events = [];
var done = new Completer();
runZoned(() {
runZonedGuarded(() {
var c;
runZoned(() {
runZonedGuarded(() {
c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"),
onDone: done.complete);
}, onError: (x) => events.add("rza: error $x"));
}, (e, s) => events.add("rza: error $e"));
c.add(1);
c.addError(2);
c.close();
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {
@ -57,16 +57,16 @@ test2() {
test3() {
var events = [];
var done = new Completer();
runZoned(() {
runZonedGuarded(() {
var c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"), onDone: done.complete);
runZoned(() {
runZonedGuarded(() {
c.add(1);
c.addError(2);
c.close();
}, onError: (x) => events.add("rza: error $x"));
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rza: error $e"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {
@ -79,18 +79,18 @@ test3() {
test4() {
var events = [];
var done = new Completer();
runZoned(() {
runZonedGuarded(() {
var c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"), onDone: done.complete);
runZoned(() {
runZonedGuarded(() {
var c2 = new StreamController();
c.addStream(c2.stream).whenComplete(c.close);
c2.add(1);
c2.addError(2);
c2.close();
}, onError: (x) => events.add("rza: error $x"));
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rza: error $e"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {
@ -104,20 +104,20 @@ test4() {
test5() {
var events = [];
var done = new Completer();
runZoned(() {
runZonedGuarded(() {
var c;
runZoned(() {
runZonedGuarded(() {
c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"),
onDone: done.complete);
}, onError: (x) => events.add("rza: error $x"));
}, (e, s) => events.add("rza: error $e"));
var c2 = new StreamController();
c.addStream(c2.stream).whenComplete(c.close);
c2.add(1);
c2.addError(2);
c2.close();
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {
@ -130,18 +130,18 @@ test6() {
var events = [];
var done = new Completer();
var c;
runZoned(() {
runZonedGuarded(() {
c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"), onDone: done.complete);
}, onError: (x) => events.add("rza: error $x"));
runZoned(() {
}, (e, s) => events.add("rza: error $e"));
runZonedGuarded(() {
var c2 = new StreamController();
c.addStream(c2.stream).whenComplete(c.close);
c2.add(1);
c2.addError(2);
c2.close();
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rzb: error $e, s"));
return [
done.future,
() {
@ -155,16 +155,16 @@ test7() {
var events = [];
var done = new Completer();
var c;
runZoned(() {
runZonedGuarded(() {
c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"), onDone: done.complete);
}, onError: (x) => events.add("rza: error $x"));
runZoned(() {
}, (e, s) => events.add("rza: error $e"));
runZonedGuarded(() {
c.add(1);
c.addError(2);
c.close();
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {

View file

@ -10,7 +10,7 @@ main() {
// error handler is defined.
Expect.equals(
499,
runZoned(() => 499, onError: (e) {
runZonedGuarded(() => 499, (e, s) {
throw "Unexpected";
}));
}

View file

@ -9,9 +9,9 @@ import 'dart:async';
main() {
asyncStart();
// Ensure that `runZoned`'s onError handles synchronous errors.
runZoned(() {
runZonedGuarded(() {
throw 0;
}, onError: (e) {
}, (e, s) {
Expect.equals(0, e);
asyncEnd();
});

View file

@ -12,9 +12,9 @@ main() {
// in the error handler at that point (when it is a synchronous error) yields
// a synchronous error.
try {
runZoned(() {
runZonedGuarded(() {
throw 0;
}, onError: (e) {
}, (e, s) {
Expect.equals(0, e);
throw e; //#01 : ok
asyncEnd();

View file

@ -12,15 +12,15 @@ main() {
// to the next runZoned when the handler returns false.
bool sawInnerHandler = false;
try {
runZoned(() {
runZoned(() {
runZonedGuarded(() {
runZonedGuarded(() {
throw 0;
}, onError: (e) {
}, (e, s) {
Expect.equals(0, e);
sawInnerHandler = true;
throw e;
});
}, onError: (e) {
}, (e, s) {
Expect.equals(0, e);
Expect.isTrue(sawInnerHandler);
// If we are waiting for an error, don't asyncEnd, but let it time out.

View file

@ -267,7 +267,7 @@ main() {
bool streamIsDone = false;
int errorCount = 0;
runZoned(() {
runZonedGuarded(() {
controller.stream
.transform(new SinkTransformer((sink) =>
new FutureWaitingTransformerSink(sink, closeCompleter.future)))
@ -280,7 +280,7 @@ main() {
Expect.listEquals([], events);
streamIsDone = true;
});
}, onError: (e) {
}, (e, s) {
Expect.isTrue(e is StateError);
errorCount++;
});

View file

@ -114,7 +114,7 @@ main() {
});
test("subscription.asFuture failure in cancel", () {
runZoned(() {
runZonedGuarded(() {
var completer = new Completer();
var controller =
new StreamController(onCancel: () => completer.future, sync: true);
@ -135,7 +135,7 @@ main() {
Expect.isFalse(catchErrorHasRun);
completer.completeError(499);
}));
}, onError: expectAsync((e) {
}, expectAsync2((e, s) {
Expect.equals(499, e);
}));
});

View file

@ -10,8 +10,8 @@ import 'dart:async';
test1() {
var events = [];
var done = new Completer();
runZoned(() {
runZoned(() {
runZonedGuarded(() {
runZonedGuarded(() {
var c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"),
@ -19,8 +19,8 @@ test1() {
c.add(1);
c.addError(2);
c.close();
}, onError: (x) => events.add("rza: error $x"));
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rza: error $e"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {
@ -33,18 +33,18 @@ test1() {
test2() {
var events = [];
var done = new Completer();
runZoned(() {
runZonedGuarded(() {
var c;
runZoned(() {
runZonedGuarded(() {
c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"),
onDone: done.complete);
}, onError: (x) => events.add("rza: error $x"));
}, (e, s) => events.add("rza: error $e"));
c.add(1);
c.addError(2);
c.close();
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {
@ -57,16 +57,16 @@ test2() {
test3() {
var events = [];
var done = new Completer();
runZoned(() {
runZonedGuarded(() {
var c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"), onDone: done.complete);
runZoned(() {
runZonedGuarded(() {
c.add(1);
c.addError(2);
c.close();
}, onError: (x) => events.add("rza: error $x"));
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rza: error $e"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {
@ -79,18 +79,18 @@ test3() {
test4() {
var events = [];
var done = new Completer();
runZoned(() {
runZonedGuarded(() {
var c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"), onDone: done.complete);
runZoned(() {
runZonedGuarded(() {
var c2 = new StreamController();
c.addStream(c2.stream).whenComplete(c.close);
c2.add(1);
c2.addError(2);
c2.close();
}, onError: (x) => events.add("rza: error $x"));
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rza: error $e"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {
@ -104,20 +104,20 @@ test4() {
test5() {
var events = [];
var done = new Completer();
runZoned(() {
runZonedGuarded(() {
var c;
runZoned(() {
runZonedGuarded(() {
c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"),
onDone: done.complete);
}, onError: (x) => events.add("rza: error $x"));
}, (e, s) => events.add("rza: error $e"));
var c2 = new StreamController();
c.addStream(c2.stream).whenComplete(c.close);
c2.add(1);
c2.addError(2);
c2.close();
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {
@ -130,18 +130,18 @@ test6() {
var events = [];
var done = new Completer();
var c;
runZoned(() {
runZonedGuarded(() {
c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"), onDone: done.complete);
}, onError: (x) => events.add("rza: error $x"));
runZoned(() {
}, (e, s) => events.add("rza: error $e"));
runZonedGuarded(() {
var c2 = new StreamController();
c.addStream(c2.stream).whenComplete(c.close);
c2.add(1);
c2.addError(2);
c2.close();
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {
@ -155,16 +155,16 @@ test7() {
var events = [];
var done = new Completer();
var c;
runZoned(() {
runZonedGuarded(() {
c = new StreamController();
c.stream.listen((x) => events.add("stream: $x"),
onError: (x) => events.add("stream: error $x"), onDone: done.complete);
}, onError: (x) => events.add("rza: error $x"));
runZoned(() {
}, (e, s) => events.add("rza: error $e"));
runZonedGuarded(() {
c.add(1);
c.addError(2);
c.close();
}, onError: (x) => events.add("rzb: error $x"));
}, (e, s) => events.add("rzb: error $e"));
return [
done.future,
() {

View file

@ -12,11 +12,11 @@ var events = [];
Future testSocketException() {
var completer = new Completer();
runZoned(() {
runZonedGuarded(() {
Socket.connect("4", 1).then((Socket s) {
Expect.fail("Socket should not be able to connect");
});
}, onError: (err) {
}, (err, s) {
if (err is! SocketException) Expect.fail("Not expected error: $err");
completer.complete("socket test, ok.");
events.add("SocketException");
@ -26,9 +26,9 @@ Future testSocketException() {
Future testFileSystemException() {
var completer = new Completer();
runZoned(() {
runZonedGuarded(() {
new File("lol it's not a file\n").openRead().listen(null);
}, onError: (err) {
}, (err, s) {
if (err is! FileSystemException) Expect.fail("Not expected error: $err");
completer.complete("file test, ok.");
events.add("FileSystemException");

View file

@ -452,11 +452,11 @@ testWatchOverflow() async {
}
void watcher(SendPort sendPort) async {
runZoned(() {
runZonedGuarded(() {
var watcher = Directory.systemTemp.watch(recursive: true);
watcher.listen((data) async {});
sendPort.send('start');
}, onError: (error) {
}, (error, stack) {
print(error);
sendPort.send('end');
});

View file

@ -159,7 +159,7 @@ void testHttpServerZone() {
void testHttpServerZoneError() {
asyncStart();
Expect.equals(Zone.root, Zone.current);
runZoned(() {
runZonedGuarded(() {
Expect.notEquals(Zone.root, Zone.current);
HttpServer.bind("127.0.0.1", 0).then((server) {
Expect.notEquals(Zone.root, Zone.current);
@ -178,14 +178,14 @@ void testHttpServerZoneError() {
socket.listen(null);
});
});
}, onError: (e) {
}, (e, s) {
asyncEnd();
});
}
void testHttpServerClientClose() {
HttpServer.bind("127.0.0.1", 0).then((server) {
runZoned(() {
runZonedGuarded(() {
server.listen((request) {
request.response.bufferOutput = false;
request.response.add(new Uint8List(64 * 1024));
@ -195,7 +195,7 @@ void testHttpServerClientClose() {
});
});
});
}, onError: (e, s) {
}, (e, s) {
Expect.fail("Unexpected error: $e(${e.hashCode})\n$s");
});
var client = new HttpClient();

View file

@ -426,7 +426,7 @@ void testSocketZone() {
void testSocketZoneError() {
asyncStart();
Expect.equals(Zone.root, Zone.current);
runZoned(() {
runZonedGuarded(() {
Expect.notEquals(Zone.root, Zone.current);
RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
Expect.notEquals(Zone.root, Zone.current);
@ -451,7 +451,7 @@ void testSocketZoneError() {
socket.close();
});
});
}, onError: (e) {
}, (e, s) {
asyncEnd();
});
}

View file

@ -17,12 +17,12 @@ main() {
initWaitForEvent();
asyncStart();
bool flag = false;
runZoned(() {
runZonedGuarded(() {
Timer.run(() {
asyncEnd();
throw "Exception";
});
}, onError: (e) {
}, (e, s) {
flag = true;
});
Expect.isFalse(flag);

View file

@ -11,12 +11,12 @@ import 'package:expect/expect.dart';
main() {
asyncStart();
Completer<bool> c = new Completer<bool>();
runZoned(() {
runZonedGuarded(() {
Timer.run(() {
asyncEnd();
throw "Error";
});
}, onError: (e) {
}, (e, s) {
Expect.isTrue(e is String);
c.complete(true);
});

View file

@ -12,11 +12,11 @@ var events = [];
Future testSocketException() {
var completer = new Completer();
runZoned(() {
runZonedGuarded(() {
Socket.connect("4", 1).then((Socket s) {
Expect.fail("Socket should not be able to connect");
});
}, onError: (err) {
}, (err, s) {
if (err is! SocketException) Expect.fail("Not expected error: $err");
completer.complete("socket test, ok.");
events.add("SocketException");
@ -26,9 +26,9 @@ Future testSocketException() {
Future testFileSystemException() {
var completer = new Completer();
runZoned(() {
runZonedGuarded(() {
new File("lol it's not a file\n").openRead().listen(null);
}, onError: (err) {
}, (err, s) {
if (err is! FileSystemException) Expect.fail("Not expected error: $err");
completer.complete("file test, ok.");
events.add("FileSystemException");

View file

@ -451,11 +451,11 @@ testWatchOverflow() async {
}
void watcher(SendPort sendPort) async {
runZoned(() {
runZonedGuarded(() {
var watcher = Directory.systemTemp.watch(recursive: true);
watcher.listen((data) async {});
sendPort.send('start');
}, onError: (error) {
}, (error, stack) {
print(error);
sendPort.send('end');
});

View file

@ -159,7 +159,7 @@ void testHttpServerZone() {
void testHttpServerZoneError() {
asyncStart();
Expect.equals(Zone.root, Zone.current);
runZoned(() {
runZonedGuarded(() {
Expect.notEquals(Zone.root, Zone.current);
HttpServer.bind("127.0.0.1", 0).then((server) {
Expect.notEquals(Zone.root, Zone.current);
@ -178,14 +178,14 @@ void testHttpServerZoneError() {
socket.listen(null);
});
});
}, onError: (e) {
}, (e, s) {
asyncEnd();
});
}
void testHttpServerClientClose() {
HttpServer.bind("127.0.0.1", 0).then((server) {
runZoned(() {
runZonedGuarded(() {
server.listen((request) {
request.response.bufferOutput = false;
request.response.add(new Uint8List(64 * 1024));
@ -195,7 +195,7 @@ void testHttpServerClientClose() {
});
});
});
}, onError: (e, s) {
}, (e, s) {
Expect.fail("Unexpected error: $e(${e.hashCode})\n$s");
});
var client = new HttpClient();

View file

@ -429,7 +429,7 @@ void testSocketZone() {
void testSocketZoneError() {
asyncStart();
Expect.equals(Zone.root, Zone.current);
runZoned(() {
runZonedGuarded(() {
Expect.notEquals(Zone.root, Zone.current);
RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
Expect.notEquals(Zone.root, Zone.current);
@ -454,7 +454,7 @@ void testSocketZoneError() {
socket.close();
});
});
}, onError: (e) {
}, (e, s) {
asyncEnd();
});
}

View file

@ -17,12 +17,12 @@ main() {
initWaitForEvent();
asyncStart();
bool flag = false;
runZoned(() {
runZonedGuarded(() {
Timer.run(() {
asyncEnd();
throw "Exception";
});
}, onError: (e) {
}, (e, s) {
flag = true;
});
Expect.isFalse(flag);

View file

@ -11,12 +11,12 @@ import 'package:expect/expect.dart';
main() {
asyncStart();
Completer<bool> c = new Completer<bool>();
runZoned(() {
runZonedGuarded(() {
Timer.run(() {
asyncEnd();
throw "Error";
});
}, onError: (e) {
}, (e, s) {
Expect.isTrue(e is String);
c.complete(true);
});