Revert "Make throwing Zone.uncaughtError handlers propagate the error to their parent zone."

This reverts commit 88a351f3d2e675e203ce6452bc39f0e06e2a037c.

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>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7bf5a3a..a45fa7a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index fe6dcf0..9301ce3 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -17,15 +17,6 @@
 ///
 /// 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 @@
 /// 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 @@
 /// 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 @@
 /// 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 @@
 /// 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 @@
 /// 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 @@
 /// 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 @@
 /// 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 @@
 ///
 /// 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 @@
 ///
 /// 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 @@
 ///
 /// 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 @@
 /// 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 @@
   _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 @@
     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 @@
   // 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 @@
 
 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);
   });
diff --git a/tests/lib/async/uncaught_error_handler_throws_test.dart b/tests/lib/async/uncaught_error_handler_throws_test.dart
deleted file mode 100644
index f70f098..0000000
--- a/tests/lib/async/uncaught_error_handler_throws_test.dart
+++ /dev/null
@@ -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));
-}
diff --git a/tests/lib_2/async/slow_consumer2_test.dart b/tests/lib_2/async/slow_consumer2_test.dart
index 23a001a..de37668 100644
--- a/tests/lib_2/async/slow_consumer2_test.dart
+++ b/tests/lib_2/async/slow_consumer2_test.dart
@@ -88,7 +88,7 @@
       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);
diff --git a/tests/lib_2/async/uncaught_error_handler_throws_test.dart b/tests/lib_2/async/uncaught_error_handler_throws_test.dart
deleted file mode 100644
index f70f098..0000000
--- a/tests/lib_2/async/uncaught_error_handler_throws_test.dart
+++ /dev/null
@@ -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));
-}