mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 12:57:42 +00:00
Revert "Make throwing Zone.uncaughtError handlers propagate the error to their parent zone."
This reverts commit 88a351f3d2
.
This broke the Dart SDK -> Flutter Engine roller. Flutter issue at https://github.com/flutter/flutter/issues/80969
Change-Id: Idaf255a730c7b6054e6cd929b6770dbe66860151
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196561
Reviewed-by: Zach Anderson <zra@google.com>
Commit-Queue: Zach Anderson <zra@google.com>
This commit is contained in:
parent
5c36a30de2
commit
f0a8b63402
|
@ -2,12 +2,6 @@
|
|||
|
||||
### Core libraries
|
||||
|
||||
#### `dart:async`
|
||||
|
||||
* The uncaught error handlers of `Zone`s are now run in the parent zone
|
||||
of the zone where they were declared. This prevents a throwing handler
|
||||
from causing an infinite loop by repeatedly triggering itself.
|
||||
|
||||
#### `dart:core`
|
||||
|
||||
* The native `DateTime` class now better handles local time around
|
||||
|
|
|
@ -17,15 +17,6 @@ typedef R ZoneBinaryCallback<R, T1, T2>(T1 arg1, T2 arg2);
|
|||
///
|
||||
/// The [error] and [stackTrace] are the error and stack trace that
|
||||
/// was uncaught in [zone].
|
||||
///
|
||||
/// The function must only access zone-related functionality through
|
||||
/// [self], [parent] or [zone].
|
||||
/// It should not depend on the current zone ([Zone.current]).
|
||||
///
|
||||
/// If the uncaught error handler throws, the error will be passed
|
||||
/// to `parent.handleUncaughtError`. If the thrown object is [error],
|
||||
/// the throw is considered a re-throw and the original [stackTrace]
|
||||
/// is retained. This allows an asynchronous error to leave the error zone.
|
||||
typedef HandleUncaughtErrorHandler = void Function(Zone self,
|
||||
ZoneDelegate parent, Zone zone, Object error, StackTrace stackTrace);
|
||||
|
||||
|
@ -43,10 +34,6 @@ typedef HandleUncaughtErrorHandler = void Function(Zone self,
|
|||
/// to call [f] in the current zone, [zone].
|
||||
/// A custom handler can do things before, after or instead of
|
||||
/// calling [f].
|
||||
///
|
||||
/// The function must only access zone-related functionality through
|
||||
/// [self], [parent] or [zone].
|
||||
/// It should not depend on the current zone ([Zone.current]).
|
||||
typedef RunHandler = R Function<R>(
|
||||
Zone self, ZoneDelegate parent, Zone zone, R Function() f);
|
||||
|
||||
|
@ -64,10 +51,6 @@ typedef RunHandler = R Function<R>(
|
|||
/// to call [f] with argument [arg] in the current zone, [zone].
|
||||
/// A custom handler can do things before, after or instead of
|
||||
/// calling [f].
|
||||
///
|
||||
/// The function must only access zone-related functionality through
|
||||
/// [self], [parent] or [zone].
|
||||
/// It should not depend on the current zone ([Zone.current]).
|
||||
typedef RunUnaryHandler = R Function<R, T>(
|
||||
Zone self, ZoneDelegate parent, Zone zone, R Function(T arg) f, T arg);
|
||||
|
||||
|
@ -85,10 +68,6 @@ typedef RunUnaryHandler = R Function<R, T>(
|
|||
/// to call [f] with arguments [arg1] and [arg2] in the current zone, [zone].
|
||||
/// A custom handler can do things before, after or instead of
|
||||
/// calling [f].
|
||||
///
|
||||
/// The function must only access zone-related functionality through
|
||||
/// [self], [parent] or [zone].
|
||||
/// It should not depend on the current zone ([Zone.current]).
|
||||
typedef RunBinaryHandler = R Function<R, T1, T2>(Zone self, ZoneDelegate parent,
|
||||
Zone zone, R Function(T1 arg1, T2 arg2) f, T1 arg1, T2 arg2);
|
||||
|
||||
|
@ -106,10 +85,6 @@ typedef RunBinaryHandler = R Function<R, T1, T2>(Zone self, ZoneDelegate parent,
|
|||
/// or another function replacing [f],
|
||||
/// typically by wrapping [f] in a function
|
||||
/// which does something extra before and after invoking [f]
|
||||
///
|
||||
/// The function must only access zone-related functionality through
|
||||
/// [self], [parent] or [zone].
|
||||
/// It should not depend on the current zone ([Zone.current]).
|
||||
typedef RegisterCallbackHandler = ZoneCallback<R> Function<R>(
|
||||
Zone self, ZoneDelegate parent, Zone zone, R Function() f);
|
||||
|
||||
|
@ -127,10 +102,6 @@ typedef RegisterCallbackHandler = ZoneCallback<R> Function<R>(
|
|||
/// or another function replacing [f],
|
||||
/// typically by wrapping [f] in a function
|
||||
/// which does something extra before and after invoking [f]
|
||||
///
|
||||
/// The function must only access zone-related functionality through
|
||||
/// [self], [parent] or [zone].
|
||||
/// It should not depend on the current zone ([Zone.current]).
|
||||
typedef RegisterUnaryCallbackHandler = ZoneUnaryCallback<R, T> Function<R, T>(
|
||||
Zone self, ZoneDelegate parent, Zone zone, R Function(T arg) f);
|
||||
|
||||
|
@ -166,12 +137,6 @@ typedef RegisterBinaryCallbackHandler
|
|||
/// to replace the original error and stack trace,
|
||||
/// or an [AsyncError] containing a replacement error and stack trace
|
||||
/// which will be used to replace the originals.
|
||||
///
|
||||
/// The error callback handler must not throw.
|
||||
///
|
||||
/// The function must only access zone-related functionality through
|
||||
/// [self], [parent] or [zone].
|
||||
/// It should not depend on the current zone ([Zone.current]).
|
||||
typedef AsyncError? ErrorCallbackHandler(Zone self, ZoneDelegate parent,
|
||||
Zone zone, Object error, StackTrace? stackTrace);
|
||||
|
||||
|
@ -190,10 +155,6 @@ typedef AsyncError? ErrorCallbackHandler(Zone self, ZoneDelegate parent,
|
|||
/// and then call `parent.scheduleMicrotask(zone, replacement)`.
|
||||
/// or it can implement its own microtask scheduling queue, which typically
|
||||
/// still depends on `parent.scheduleMicrotask` to as a way to get started.
|
||||
///
|
||||
/// The function must only access zone-related functionality through
|
||||
/// [self], [parent] or [zone].
|
||||
/// It should not depend on the current zone ([Zone.current]).
|
||||
typedef void ScheduleMicrotaskHandler(
|
||||
Zone self, ZoneDelegate parent, Zone zone, void f());
|
||||
|
||||
|
@ -216,10 +177,6 @@ typedef void ScheduleMicrotaskHandler(
|
|||
///
|
||||
/// The function should return a [Timer] object which can be used
|
||||
/// to inspect and control the scheduled timer callback.
|
||||
///
|
||||
/// The function must only access zone-related functionality through
|
||||
/// [self], [parent] or [zone].
|
||||
/// It should not depend on the current zone ([Zone.current]).
|
||||
typedef Timer CreateTimerHandler(
|
||||
Zone self, ZoneDelegate parent, Zone zone, Duration duration, void f());
|
||||
|
||||
|
@ -242,10 +199,6 @@ typedef Timer CreateTimerHandler(
|
|||
///
|
||||
/// The function should return a [Timer] object which can be used
|
||||
/// to inspect and control the scheduled timer callbacks.
|
||||
///
|
||||
/// The function must only access zone-related functionality through
|
||||
/// [self], [parent] or [zone].
|
||||
/// It should not depend on the current zone ([Zone.current]).
|
||||
typedef Timer CreatePeriodicTimerHandler(Zone self, ZoneDelegate parent,
|
||||
Zone zone, Duration period, void f(Timer timer));
|
||||
|
||||
|
@ -261,10 +214,6 @@ typedef Timer CreatePeriodicTimerHandler(Zone self, ZoneDelegate parent,
|
|||
///
|
||||
/// The custom handler can intercept print operations and
|
||||
/// redirect them to other targets than the console.
|
||||
///
|
||||
/// The function must only access zone-related functionality through
|
||||
/// [self], [parent] or [zone].
|
||||
/// It should not depend on the current zone ([Zone.current]).
|
||||
typedef void PrintHandler(
|
||||
Zone self, ZoneDelegate parent, Zone zone, String line);
|
||||
|
||||
|
@ -286,10 +235,6 @@ typedef void PrintHandler(
|
|||
/// values before calling `parent.fork(zone, specification, zoneValues)`,
|
||||
/// but it has to call the [parent]'s [ZoneDelegate.fork] in order
|
||||
/// to create a valid [Zone] object.
|
||||
///
|
||||
/// The function must only access zone-related functionality through
|
||||
/// [self], [parent] or [zone].
|
||||
/// It should not depend on the current zone ([Zone.current]).
|
||||
typedef Zone ForkHandler(Zone self, ZoneDelegate parent, Zone zone,
|
||||
ZoneSpecification? specification, Map<Object?, Object?>? zoneValues);
|
||||
|
||||
|
@ -970,7 +915,10 @@ class _ZoneDelegate implements ZoneDelegate {
|
|||
_ZoneDelegate(this._delegationTarget);
|
||||
|
||||
void handleUncaughtError(Zone zone, Object error, StackTrace stackTrace) {
|
||||
_delegationTarget._processUncaughtError(zone, error, stackTrace);
|
||||
var implementation = _delegationTarget._handleUncaughtError;
|
||||
_Zone implZone = implementation.zone;
|
||||
HandleUncaughtErrorHandler handler = implementation.function;
|
||||
return handler(implZone, implZone._parentDelegate, zone, error, stackTrace);
|
||||
}
|
||||
|
||||
R run<R>(Zone zone, R f()) {
|
||||
|
@ -1092,28 +1040,6 @@ abstract class _Zone implements Zone {
|
|||
return identical(this, otherZone) ||
|
||||
identical(errorZone, otherZone.errorZone);
|
||||
}
|
||||
|
||||
void _processUncaughtError(Zone zone, Object error, StackTrace stackTrace) {
|
||||
var implementation = _handleUncaughtError;
|
||||
_Zone implZone = implementation.zone;
|
||||
if (identical(implZone, _rootZone)) {
|
||||
_rootHandleError(error, stackTrace);
|
||||
return;
|
||||
}
|
||||
HandleUncaughtErrorHandler handler = implementation.function;
|
||||
ZoneDelegate parentDelegate = implZone._parentDelegate;
|
||||
_Zone parentZone = implZone.parent!; // Not null for non-root zones.
|
||||
_Zone currentZone = Zone._current;
|
||||
try {
|
||||
Zone._current = parentZone;
|
||||
handler(implZone, parentDelegate, zone, error, stackTrace);
|
||||
Zone._current = currentZone;
|
||||
} catch (e, s) {
|
||||
Zone._current = currentZone;
|
||||
parentZone._processUncaughtError(
|
||||
implZone, e, identical(error, e) ? stackTrace : s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _CustomZone extends _Zone {
|
||||
|
@ -1309,7 +1235,11 @@ class _CustomZone extends _Zone {
|
|||
// Methods that can be customized by the zone specification.
|
||||
|
||||
void handleUncaughtError(Object error, StackTrace stackTrace) {
|
||||
_processUncaughtError(this, error, stackTrace);
|
||||
var implementation = this._handleUncaughtError;
|
||||
ZoneDelegate parentDelegate = implementation.zone._parentDelegate;
|
||||
HandleUncaughtErrorHandler handler = implementation.function;
|
||||
return handler(
|
||||
implementation.zone, parentDelegate, this, error, stackTrace);
|
||||
}
|
||||
|
||||
Zone fork(
|
||||
|
@ -1405,10 +1335,6 @@ class _CustomZone extends _Zone {
|
|||
|
||||
void _rootHandleUncaughtError(Zone? self, ZoneDelegate? parent, Zone zone,
|
||||
Object error, StackTrace stackTrace) {
|
||||
_rootHandleError(error, stackTrace);
|
||||
}
|
||||
|
||||
void _rootHandleError(Object error, StackTrace stackTrace) {
|
||||
_schedulePriorityAsyncCallback(() {
|
||||
_rethrow(error, stackTrace);
|
||||
});
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'dart:async';
|
||||
|
||||
void main() async {
|
||||
asyncStart();
|
||||
await testThrowSame();
|
||||
await testThrowOther();
|
||||
asyncEnd();
|
||||
}
|
||||
|
||||
Future<void> testThrowSame() async {
|
||||
asyncStart();
|
||||
var object1 = Object();
|
||||
var stack1 = StackTrace.current;
|
||||
var outerZone = Zone.current;
|
||||
var firstZone = Zone.current.fork(specification: onError((error, stack) {
|
||||
// Uncaught error handlers run in the parent zone.
|
||||
Expect.identical(outerZone, Zone.current);
|
||||
Expect.identical(object1, error);
|
||||
Expect.identical(stack1, stack); // Get same stack trace.
|
||||
asyncEnd();
|
||||
}));
|
||||
firstZone.run(() async {
|
||||
Expect.identical(firstZone, Zone.current);
|
||||
var secondZone = Zone.current.fork(specification: onError((error, stack) {
|
||||
// Uncaught error handlers run in the parent zone.
|
||||
Expect.identical(firstZone, Zone.current);
|
||||
Expect.identical(object1, error);
|
||||
Expect.identical(stack1, stack);
|
||||
throw error; // Throw same object
|
||||
}));
|
||||
secondZone.run(() async {
|
||||
Expect.identical(secondZone, Zone.current);
|
||||
Future.error(object1, stack1); // Unhandled async error.
|
||||
await Future(() {});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> testThrowOther() async {
|
||||
asyncStart();
|
||||
var object1 = Object();
|
||||
var object2 = Object();
|
||||
var stack1 = StackTrace.current;
|
||||
var outerZone = Zone.current;
|
||||
var firstZone = Zone.current.fork(specification: onError((error, stack) {
|
||||
Expect.identical(outerZone, Zone.current);
|
||||
Expect.identical(object2, error);
|
||||
Expect.notIdentical(stack1, stack); // Get different stack trace.
|
||||
asyncEnd();
|
||||
}));
|
||||
firstZone.run(() async {
|
||||
Expect.identical(firstZone, Zone.current);
|
||||
var secondZone = Zone.current.fork(specification: onError((error, stack) {
|
||||
Expect.identical(firstZone, Zone.current);
|
||||
Expect.identical(object1, error);
|
||||
Expect.identical(stack1, stack);
|
||||
throw object2; // Throw different object
|
||||
}));
|
||||
secondZone.run(() async {
|
||||
Expect.identical(secondZone, Zone.current);
|
||||
Future.error(object1, stack1); // Unhandled async error.
|
||||
await Future(() {});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ZoneSpecification onError(void Function(Object, StackTrace) handler) {
|
||||
return ZoneSpecification(
|
||||
handleUncaughtError: (s, p, z, e, st) => handler(e, st));
|
||||
}
|
|
@ -88,7 +88,7 @@ class DataProvider {
|
|||
listSize -= sentCount - targetCount;
|
||||
sentCount = targetCount;
|
||||
}
|
||||
controller.add(new List<int>(listSize));
|
||||
controller.add(new List(listSize));
|
||||
int ms = listSize * 1000 ~/ bytesPerSecond;
|
||||
Duration duration = new Duration(milliseconds: ms);
|
||||
if (!controller.isPaused) new Timer(duration, send);
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'dart:async';
|
||||
|
||||
void main() async {
|
||||
asyncStart();
|
||||
await testThrowSame();
|
||||
await testThrowOther();
|
||||
asyncEnd();
|
||||
}
|
||||
|
||||
Future<void> testThrowSame() async {
|
||||
asyncStart();
|
||||
var object1 = Object();
|
||||
var stack1 = StackTrace.current;
|
||||
var outerZone = Zone.current;
|
||||
var firstZone = Zone.current.fork(specification: onError((error, stack) {
|
||||
// Uncaught error handlers run in the parent zone.
|
||||
Expect.identical(outerZone, Zone.current);
|
||||
Expect.identical(object1, error);
|
||||
Expect.identical(stack1, stack); // Get same stack trace.
|
||||
asyncEnd();
|
||||
}));
|
||||
firstZone.run(() async {
|
||||
Expect.identical(firstZone, Zone.current);
|
||||
var secondZone = Zone.current.fork(specification: onError((error, stack) {
|
||||
// Uncaught error handlers run in the parent zone.
|
||||
Expect.identical(firstZone, Zone.current);
|
||||
Expect.identical(object1, error);
|
||||
Expect.identical(stack1, stack);
|
||||
throw error; // Throw same object
|
||||
}));
|
||||
secondZone.run(() async {
|
||||
Expect.identical(secondZone, Zone.current);
|
||||
Future.error(object1, stack1); // Unhandled async error.
|
||||
await Future(() {});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> testThrowOther() async {
|
||||
asyncStart();
|
||||
var object1 = Object();
|
||||
var object2 = Object();
|
||||
var stack1 = StackTrace.current;
|
||||
var outerZone = Zone.current;
|
||||
var firstZone = Zone.current.fork(specification: onError((error, stack) {
|
||||
Expect.identical(outerZone, Zone.current);
|
||||
Expect.identical(object2, error);
|
||||
Expect.notIdentical(stack1, stack); // Get different stack trace.
|
||||
asyncEnd();
|
||||
}));
|
||||
firstZone.run(() async {
|
||||
Expect.identical(firstZone, Zone.current);
|
||||
var secondZone = Zone.current.fork(specification: onError((error, stack) {
|
||||
Expect.identical(firstZone, Zone.current);
|
||||
Expect.identical(object1, error);
|
||||
Expect.identical(stack1, stack);
|
||||
throw object2; // Throw different object
|
||||
}));
|
||||
secondZone.run(() async {
|
||||
Expect.identical(secondZone, Zone.current);
|
||||
Future.error(object1, stack1); // Unhandled async error.
|
||||
await Future(() {});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ZoneSpecification onError(void Function(Object, StackTrace) handler) {
|
||||
return ZoneSpecification(
|
||||
handleUncaughtError: (s, p, z, e, st) => handler(e, st));
|
||||
}
|
Loading…
Reference in a new issue