| Index: sdk/lib/_internal/pub/lib/src/utils.dart
|
| diff --git a/sdk/lib/_internal/pub/lib/src/utils.dart b/sdk/lib/_internal/pub/lib/src/utils.dart
|
| index c631381c383cb9c855160a362551fa22fd38461a..a3f0f974aa325b6e946f8535fe96b7ee7a681c8a 100644
|
| --- a/sdk/lib/_internal/pub/lib/src/utils.dart
|
| +++ b/sdk/lib/_internal/pub/lib/src/utils.dart
|
| @@ -384,6 +384,31 @@ String fileUriToPath(Uri uri) {
|
| }
|
| }
|
|
|
| +/// Wraps [fn] to guard against several different kinds of stack overflow
|
| +/// exceptions:
|
| +///
|
| +/// * A sufficiently long [Future] chain can cause a stack overflow if there are
|
| +/// no asynchronous operations in it (issue 9583).
|
| +/// * A recursive function that recurses too deeply without an asynchronous
|
| +/// operation can cause a stack overflow.
|
| +/// * Even if the former is guarded against by adding asynchronous operations,
|
| +/// returning a value through the [Future] chain can still cause a stack
|
| +/// overflow.
|
| +Future resetStack(fn()) {
|
| + // Using a [Completer] breaks the [Future] chain for the return value and
|
| + // avoids the third case described above.
|
| + var completer = new Completer();
|
| +
|
| + // Using [new Future] adds an asynchronous operation that works around the
|
| + // first and second cases described above.
|
| + new Future(fn).then((val) {
|
| + runAsync(() => completer.complete(val));
|
| + }).catchError((err) {
|
| + runAsync(() => completer.completeError(err));
|
| + });
|
| + return completer.future;
|
| +}
|
| +
|
| /// An exception class for exceptions that are intended to be seen by the user.
|
| /// These exceptions won't have any debugging information printed when they're
|
| /// thrown.
|
|
|