Version 2.12.0-241.0.dev

Merge commit '04e8aa58ee81bed52a63d4bbb10791a9eb018d7e' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index 31b5e0f..f5498a2 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -9555,26 +9555,6 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(String name)>
-    templateUseOfDeprecatedIdentifier =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""'#name' is deprecated.""",
-        withArguments: _withArgumentsUseOfDeprecatedIdentifier);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeUseOfDeprecatedIdentifier =
-    const Code<Message Function(String name)>("UseOfDeprecatedIdentifier",
-        severity: Severity.ignored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsUseOfDeprecatedIdentifier(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeUseOfDeprecatedIdentifier,
-      message: """'${name}' is deprecated.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
     templateValueForRequiredParameterNotProvidedError =
     const Template<Message Function(String name)>(
         messageTemplate:
diff --git a/pkg/front_end/lib/src/fasta/identifiers.dart b/pkg/front_end/lib/src/fasta/identifiers.dart
index 644cd6a..64d6f92 100644
--- a/pkg/front_end/lib/src/fasta/identifiers.dart
+++ b/pkg/front_end/lib/src/fasta/identifiers.dart
@@ -11,62 +11,31 @@
 import 'problems.dart' show unhandled, unsupported;
 
 class Identifier {
-  final String name;
-  final int charOffset;
+  final Token token;
 
-  Identifier(Token token)
-      : name = token.lexeme,
-        charOffset = token.charOffset;
+  Identifier(this.token);
 
-  Identifier._(this.name, this.charOffset);
+  String get name => token.lexeme;
 
-  factory Identifier.preserveToken(Token token) {
-    return new _TokenIdentifier(token);
-  }
+  int get charOffset => token.charOffset;
 
   Expression get initializer => null;
 
   int get endCharOffset => charOffset + name.length;
 
   QualifiedName withQualifier(Object qualifier) {
-    return new QualifiedName._(qualifier, name, charOffset);
+    return new QualifiedName(qualifier, token);
   }
 
   @override
   String toString() => "identifier($name)";
 }
 
-class _TokenIdentifier implements Identifier {
-  final Token token;
-
-  _TokenIdentifier(this.token);
-
-  @override
-  String get name => token.lexeme;
-
-  @override
-  int get charOffset => token.charOffset;
-
-  @override
-  Expression get initializer => null;
-
-  @override
-  int get endCharOffset => charOffset + name.length;
-
-  @override
-  QualifiedName withQualifier(Object qualifier) {
-    return new _TokenQualifiedName(qualifier, token);
-  }
-
-  @override
-  String toString() => "token-identifier($name)";
-}
-
-class InitializedIdentifier extends _TokenIdentifier {
+class InitializedIdentifier extends Identifier {
   @override
   final Expression initializer;
 
-  InitializedIdentifier(_TokenIdentifier identifier, this.initializer)
+  InitializedIdentifier(Identifier identifier, this.initializer)
       : super(identifier.token);
 
   @override
@@ -83,8 +52,7 @@
 
   QualifiedName(this.qualifier, Token suffix) : super(suffix);
 
-  QualifiedName._(this.qualifier, String name, int charOffset)
-      : super._(name, charOffset);
+  Token get suffix => token;
 
   @override
   QualifiedName withQualifier(Object qualifier) {
@@ -95,23 +63,6 @@
   String toString() => "qualified-name($qualifier, $name)";
 }
 
-class _TokenQualifiedName extends _TokenIdentifier implements QualifiedName {
-  @override
-  final Object qualifier;
-
-  _TokenQualifiedName(this.qualifier, Token suffix)
-      : assert(qualifier is! Identifier || qualifier is _TokenIdentifier),
-        super(suffix);
-
-  @override
-  QualifiedName withQualifier(Object qualifier) {
-    return unsupported("withQualifier", charOffset, null);
-  }
-
-  @override
-  String toString() => "token-qualified-name($qualifier, $name)";
-}
-
 void flattenQualifiedNameOn(
     QualifiedName name, StringBuffer buffer, int charOffset, Uri fileUri) {
   final Object qualifier = name.qualifier;
@@ -142,8 +93,3 @@
     return unhandled("${name.runtimeType}", "flattenName", charOffset, fileUri);
   }
 }
-
-Token deprecated_extractToken(Identifier identifier) {
-  _TokenIdentifier tokenIdentifier = identifier;
-  return tokenIdentifier?.token;
-}
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index c7a0a91..a478938 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -80,12 +80,7 @@
 import '../fasta_codes.dart' show LocatedMessage, Message, noLength, Template;
 
 import '../identifiers.dart'
-    show
-        Identifier,
-        InitializedIdentifier,
-        QualifiedName,
-        deprecated_extractToken,
-        flattenName;
+    show Identifier, InitializedIdentifier, QualifiedName, flattenName;
 
 import '../messages.dart' as messages show getLocationFromUri;
 
@@ -633,9 +628,7 @@
       Object expression = pop();
       if (expression is Identifier) {
         Identifier identifier = expression;
-        expression = new UnresolvedNameGenerator(
-            this,
-            deprecated_extractToken(identifier),
+        expression = new UnresolvedNameGenerator(this, identifier.token,
             new Name(identifier.name, libraryBuilder.nameOrigin));
       }
       if (name?.isNotEmpty ?? false) {
@@ -1997,13 +1990,6 @@
   void handleIdentifier(Token token, IdentifierContext context) {
     debugEvent("handleIdentifier");
     String name = token.lexeme;
-    if (name.startsWith("deprecated") &&
-        // Note that the previous check is redundant, but faster in the common
-        // case (when [name] isn't deprecated).
-        (name == "deprecated" || name.startsWith("deprecated_"))) {
-      addProblem(fasta.templateUseOfDeprecatedIdentifier.withArguments(name),
-          offsetForToken(token), lengthForToken(token));
-    }
     if (context.isScopeReference) {
       assert(!inInitializer ||
           this.scope == enclosingScope ||
@@ -2031,7 +2017,7 @@
     if (token.isSynthetic) {
       push(new ParserRecovery(offsetForToken(token)));
     } else {
-      push(new Identifier.preserveToken(token));
+      push(new Identifier(token));
     }
   }
 
@@ -2503,7 +2489,7 @@
     assert(isConst == (constantContext == ConstantContext.inferred));
     VariableDeclaration variable = new VariableDeclarationImpl(
         identifier.name, functionNestingLevel,
-        forSyntheticToken: deprecated_extractToken(identifier).isSynthetic,
+        forSyntheticToken: identifier.token.isSynthetic,
         initializer: initializer,
         type: buildDartType(currentLocalVariableType),
         isFinal: isFinal,
@@ -3282,7 +3268,7 @@
     if (name is QualifiedName) {
       QualifiedName qualified = name;
       Object prefix = qualified.qualifier;
-      Token suffix = deprecated_extractToken(qualified);
+      Token suffix = qualified.suffix;
       if (prefix is Generator) {
         name = prefix.qualifiedLookup(suffix);
       } else {
@@ -4016,7 +4002,7 @@
               identifier.charOffset, identifier.name.length);
         }
       } else if (qualifier is Generator) {
-        type = qualifier.qualifiedLookup(deprecated_extractToken(identifier));
+        type = qualifier.qualifiedLookup(identifier.token);
         identifier = null;
       } else if (qualifier is ProblemBuilder) {
         type = qualifier;
@@ -4334,8 +4320,7 @@
     ]));
     Arguments arguments = pop();
     Identifier nameLastIdentifier = pop(NullValue.Identifier);
-    Token nameLastToken =
-        deprecated_extractToken(nameLastIdentifier) ?? nameToken;
+    Token nameLastToken = nameLastIdentifier?.token ?? nameToken;
     String name = pop();
     List<UnresolvedType> typeArguments = pop();
 
@@ -4807,7 +4792,7 @@
   void endFunctionName(Token beginToken, Token token) {
     debugEvent("FunctionName");
     Identifier name = pop();
-    Token nameToken = deprecated_extractToken(name);
+    Token nameToken = name.token;
     VariableDeclaration variable = new VariableDeclarationImpl(
         name.name, functionNestingLevel,
         forSyntheticToken: nameToken.isSynthetic,
@@ -6102,7 +6087,7 @@
   @override
   void handleSymbolVoid(Token token) {
     debugEvent("SymbolVoid");
-    push(new Identifier.preserveToken(token));
+    push(new Identifier(token));
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/loader.dart b/pkg/front_end/lib/src/fasta/loader.dart
index cfdb636..0c917db 100644
--- a/pkg/front_end/lib/src/fasta/loader.dart
+++ b/pkg/front_end/lib/src/fasta/loader.dart
@@ -306,7 +306,7 @@
       List<LocatedMessage> context,
       bool problemOnLibrary: false,
       List<Uri> involvedFiles}) {
-    severity = target.fixSeverity(severity, message, fileUri);
+    severity ??= message.code.severity;
     if (severity == Severity.ignored) return null;
     String trace = """
 message: ${message.message}
diff --git a/pkg/front_end/lib/src/fasta/rewrite_severity.dart b/pkg/front_end/lib/src/fasta/rewrite_severity.dart
deleted file mode 100644
index 5fd9ae8..0000000
--- a/pkg/front_end/lib/src/fasta/rewrite_severity.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2018, 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:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-
-import 'messages.dart' as msg;
-
-Severity rewriteSeverity(
-    Severity severity, msg.Code<Object> code, Uri fileUri) {
-  if (severity != Severity.ignored) {
-    return severity;
-  }
-
-  String path = fileUri.path;
-  String fastaPath = "/pkg/front_end/lib/src/fasta/";
-  int index = path.indexOf(fastaPath);
-  if (index == -1) {
-    fastaPath = "/pkg/front_end/tool/_fasta/";
-    index = path.indexOf(fastaPath);
-    if (index == -1) return severity;
-  }
-  if (code == msg.codeUseOfDeprecatedIdentifier) {
-    // TODO(ahe): Remove the exceptions below.
-    // We plan to remove all uses of deprecated identifiers from Fasta. The
-    // strategy is to remove files from the list below one by one. To get
-    // started on cleaning up a given file, simply remove it from the list
-    // below and compile Fasta with itself to get a list of remaining call
-    // sites.
-    switch (path.substring(fastaPath.length + index)) {
-      case "command_line.dart":
-      case "kernel/body_builder.dart":
-        return severity;
-    }
-  }
-  return Severity.error;
-}
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index 264ad8e..2b8a091 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -22,8 +22,6 @@
 
 import 'messages.dart' show FormattedMessage, LocatedMessage, Message;
 
-import 'rewrite_severity.dart' show rewriteSeverity;
-
 import 'target.dart' show Target;
 
 import 'ticker.dart' show Ticker;
@@ -190,11 +188,6 @@
         involvedFiles: involvedFiles);
   }
 
-  Severity fixSeverity(Severity severity, Message message, Uri fileUri) {
-    severity ??= message.code.severity;
-    return rewriteSeverity(severity, message.code, fileUri);
-  }
-
   String get currentSdkVersionString {
     return CompilerContext.current.options.currentSdkVersion;
   }
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 9bb52f9..5c8b909 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -3716,10 +3716,6 @@
   template: "The field that corresponds to the parameter."
   severity: CONTEXT
 
-UseOfDeprecatedIdentifier:
-  template: "'#name' is deprecated."
-  severity: IGNORED
-
 InitializeFromDillNotSelfContained:
   template: |
     Tried to initialize from a previous compilation (#string), but the file was not self-contained. This might be a bug.
diff --git a/pkg/vm_service/test/get_stack_test.dart b/pkg/vm_service/test/get_stack_test.dart
index 5889996..2cd0f93 100644
--- a/pkg/vm_service/test/get_stack_test.dart
+++ b/pkg/vm_service/test/get_stack_test.dart
@@ -52,11 +52,12 @@
   // Before the first await.
   hasStoppedAtBreakpoint,
   stoppedAtLine(LINE_A),
+  // At LINE_A we're still running sync. so no asyncCausalFrames.
   (VmService service, IsolateRef isolateRef) async {
     final result = await service.getStack(isolateRef.id);
 
     expect(result.frames, hasLength(16));
-    expect(result.asyncCausalFrames, hasLength(16));
+    expect(result.asyncCausalFrames, isNull);
     expect(result.awaiterFrames, hasLength(16));
 
     expectFrames(result.frames, [
@@ -73,20 +74,6 @@
       [equals('Regular'), endsWith(' testMain')],
     ]);
 
-    expectFrames(result.asyncCausalFrames, [
-      [equals('Regular'), endsWith(' func10')],
-      [equals('Regular'), endsWith(' func9')],
-      [equals('Regular'), endsWith(' func8')],
-      [equals('Regular'), endsWith(' func7')],
-      [equals('Regular'), endsWith(' func6')],
-      [equals('Regular'), endsWith(' func5')],
-      [equals('Regular'), endsWith(' func4')],
-      [equals('Regular'), endsWith(' func3')],
-      [equals('Regular'), endsWith(' func2')],
-      [equals('Regular'), endsWith(' func1')],
-      [equals('Regular'), endsWith(' testMain')],
-    ]);
-
     expectFrames(result.awaiterFrames, [
       [equals('AsyncActivation'), endsWith(' func10')],
       [equals('AsyncActivation'), endsWith(' func9')],
@@ -101,10 +88,10 @@
       [equals('AsyncActivation'), endsWith(' testMain')],
     ]);
   },
-  // After resuming the continuation - i.e. running async.
   resumeIsolate,
   hasStoppedAtBreakpoint,
   stoppedAtLine(LINE_B),
+  // After resuming the continuation - i.e. running async.
   (VmService service, IsolateRef isolateRef) async {
     final result = await service.getStack(isolateRef.id);
 
diff --git a/runtime/observatory/tests/service/causal_async_stack_presence_test.dart b/runtime/observatory/tests/service/causal_async_stack_presence_test.dart
index 3a90e4a..01331cd 100644
--- a/runtime/observatory/tests/service/causal_async_stack_presence_test.dart
+++ b/runtime/observatory/tests/service/causal_async_stack_presence_test.dart
@@ -11,8 +11,8 @@
 import 'test_helper.dart';
 
 const LINE_C = 19;
-const LINE_A = 24;
-const LINE_B = 30;
+const LINE_A = 25;
+const LINE_B = 31;
 
 foobar() {
   debugger();
@@ -20,6 +20,7 @@
 }
 
 helper() async {
+  await 0; // Yield. The rest will run async.
   debugger();
   print('helper'); // LINE_A.
   foobar();
@@ -36,6 +37,7 @@
   (Isolate isolate) async {
     ServiceMap stack = await isolate.getStack();
     // No causal frames because we are in a completely synchronous stack.
+    // Async function hasn't yielded yet.
     expect(stack['asyncCausalFrames'], isNull);
   },
   resumeIsolate,
@@ -43,7 +45,7 @@
   stoppedAtLine(LINE_A),
   (Isolate isolate) async {
     ServiceMap stack = await isolate.getStack();
-    // Has causal frames (we are inside an async function)
+    // Async function has yielded once, so it's now running async.
     expect(stack['asyncCausalFrames'], isNotNull);
   },
   resumeIsolate,
diff --git a/runtime/observatory/tests/service/causal_async_star_stack_presence_test.dart b/runtime/observatory/tests/service/causal_async_star_stack_presence_test.dart
index 4d3e448..9b605cb 100644
--- a/runtime/observatory/tests/service/causal_async_star_stack_presence_test.dart
+++ b/runtime/observatory/tests/service/causal_async_star_stack_presence_test.dart
@@ -39,7 +39,7 @@
   (Isolate isolate) async {
     ServiceMap stack = await isolate.getStack();
     // No causal frames because we are in a completely synchronous stack.
-    expect(stack['asyncCausalFrames'], isNotNull);
+    expect(stack['asyncCausalFrames'], isNull);
   },
   resumeIsolate,
   hasStoppedAtBreakpoint,
diff --git a/runtime/observatory_2/tests/service_2/causal_async_stack_presence_test.dart b/runtime/observatory_2/tests/service_2/causal_async_stack_presence_test.dart
index f52f4a1..cd9ef6a 100644
--- a/runtime/observatory_2/tests/service_2/causal_async_stack_presence_test.dart
+++ b/runtime/observatory_2/tests/service_2/causal_async_stack_presence_test.dart
@@ -11,8 +11,8 @@
 import 'test_helper.dart';
 
 const LINE_C = 19;
-const LINE_A = 24;
-const LINE_B = 30;
+const LINE_A = 25;
+const LINE_B = 31;
 
 foobar() {
   debugger();
@@ -20,6 +20,7 @@
 }
 
 helper() async {
+  await 0; // Yield. The rest will run async.
   debugger();
   print('helper'); // LINE_A.
   foobar();
diff --git a/runtime/observatory_2/tests/service_2/causal_async_star_stack_presence_test.dart b/runtime/observatory_2/tests/service_2/causal_async_star_stack_presence_test.dart
index 7fb385a..8acf40d 100644
--- a/runtime/observatory_2/tests/service_2/causal_async_star_stack_presence_test.dart
+++ b/runtime/observatory_2/tests/service_2/causal_async_star_stack_presence_test.dart
@@ -39,7 +39,7 @@
   (Isolate isolate) async {
     ServiceMap stack = await isolate.getStack();
     // No causal frames because we are in a completely synchronous stack.
-    expect(stack['asyncCausalFrames'], isNotNull);
+    expect(stack['asyncCausalFrames'], isNull);
   },
   resumeIsolate,
   hasStoppedAtBreakpoint,
diff --git a/runtime/tests/vm/dart/causal_stacks/utils.dart b/runtime/tests/vm/dart/causal_stacks/utils.dart
index 73ffe1d..8b75f98 100644
--- a/runtime/tests/vm/dart/causal_stacks/utils.dart
+++ b/runtime/tests/vm/dart/causal_stacks/utils.dart
@@ -178,12 +178,22 @@
   return Future.sync(throwAsync).whenComplete(() => 'nop');
 }
 
+// ----
+// Scenario: Future.then:
+// ----
+
+Future futureThen() {
+  return Future.value(0).then((value) {
+    throwSync();
+  });
+}
+
 // Helpers:
 
 // We want lines that either start with a frame index or an async gap marker.
 final _lineRE = RegExp(r'^(?:#(?<number>\d+)|<asynchronous suspension>)');
 
-void assertStack(List<String> expects, StackTrace stackTrace,
+Future<void> assertStack(List<String> expects, StackTrace stackTrace,
     [String? debugInfoFilename]) async {
   final original = await Stream.value(stackTrace.toString())
       .transform(const LineSplitter())
@@ -253,7 +263,7 @@
     await f();
     Expect.fail('No exception thrown!');
   } on String catch (e, s) {
-    assertStack(expectedStack, s, debugInfoFilename);
+    return assertStack(expectedStack, s, debugInfoFilename);
   }
 }
 
@@ -267,7 +277,7 @@
     await f().then((e) => Expect.fail('No exception thrown!'));
     Expect.fail('No exception thrown!');
   } on String catch (e, s) {
-    assertStack(expectedStack, s, debugInfoFilename);
+    return assertStack(expectedStack, s, debugInfoFilename);
   }
 }
 
@@ -278,7 +288,7 @@
   await f().catchError((e, s) {
     stackTrace = s;
   });
-  assertStack(expectedStack, stackTrace, debugInfoFilename);
+  return assertStack(expectedStack, stackTrace, debugInfoFilename);
 }
 
 // ----
@@ -327,39 +337,32 @@
             r'^#13     Future._propagateToListeners ',
             r'^#14     Future._completeWithValue ',
             r'^#15     _completeOnAsyncReturn ',
-            r'^#16     doTestAwaitCatchError ',
+            r'^#16     assertStack ',
             r'^#17     _RootZone.runUnary ',
             r'^#18     _FutureListener.handleValue ',
             r'^#19     Future._propagateToListeners.handleValueCallback ',
             r'^#20     Future._propagateToListeners ',
-            r'^#21     Future._completeError ',
-            r'^#22     _completeOnAsyncError ',
-            r'^#23     allYield ',
-            r'^#24     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#25     _RootZone.runBinary ',
-            r'^#26     _FutureListener.handleError ',
-            r'^#27     Future._propagateToListeners.handleError ',
-            r'^#28     Future._propagateToListeners ',
-            r'^#29     Future._completeError ',
-            r'^#30     _completeOnAsyncError ',
-            r'^#31     allYield2 ',
-            r'^#32     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#33     _RootZone.runBinary ',
-            r'^#34     _FutureListener.handleError ',
-            r'^#35     Future._propagateToListeners.handleError ',
-            r'^#36     Future._propagateToListeners ',
-            r'^#37     Future._completeError ',
-            r'^#38     _completeOnAsyncError ',
-            r'^#39     allYield3 ',
-            r'^#40     _RootZone.runUnary ',
-            r'^#41     _FutureListener.handleValue ',
-            r'^#42     Future._propagateToListeners.handleValueCallback ',
-            r'^#43     Future._propagateToListeners ',
-            r'^#44     Future._addListener.<anonymous closure> ',
-            r'^#45     _microtaskLoop ',
-            r'^#46     _startMicrotaskLoop ',
-            r'^#47     _runPendingImmediateCallback ',
-            r'^#48     _RawReceivePortImpl._handleMessage ',
+            r'^#21     Future._complete ',
+            r'^#22     Stream.toList.<anonymous closure> ',
+            r'^#23     _RootZone.runGuarded ',
+            r'^#24     _BufferingStreamSubscription._sendDone.sendDone ',
+            r'^#25     _BufferingStreamSubscription._sendDone ',
+            r'^#26     _BufferingStreamSubscription._close ',
+            r'^#27     _SinkTransformerStreamSubscription._close ',
+            r'^#28     _EventSinkWrapper.close ',
+            r'^#29     _StringAdapterSink.close ',
+            r'^#30     _LineSplitterSink.close ',
+            r'^#31     _SinkTransformerStreamSubscription._handleDone ',
+            r'^#32     _RootZone.runGuarded ',
+            r'^#33     _BufferingStreamSubscription._sendDone.sendDone ',
+            r'^#34     _BufferingStreamSubscription._sendDone ',
+            r'^#35     _DelayedDone.perform ',
+            r'^#36     _StreamImplEvents.handleNext ',
+            r'^#37     _PendingEvents.schedule.<anonymous closure> ',
+            r'^#38     _microtaskLoop ',
+            r'^#39     _startMicrotaskLoop ',
+            r'^#40     _runPendingImmediateCallback ',
+            r'^#41     _RawReceivePortImpl._handleMessage ',
           ],
       debugInfoFilename);
   await doTestAwaitThen(
@@ -375,34 +378,32 @@
             r'^#13     Future._propagateToListeners ',
             r'^#14     Future._completeWithValue ',
             r'^#15     _completeOnAsyncReturn ',
-            r'^#16     doTestAwait ',
-            r'^#17     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#18     _RootZone.runBinary ',
-            r'^#19     _FutureListener.handleError ',
-            r'^#20     Future._propagateToListeners.handleError ',
-            r'^#21     Future._propagateToListeners ',
-            r'^#22     Future._completeError ',
-            r'^#23     _completeOnAsyncError ',
-            r'^#24     noYields ',
-            r'^#25     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#26     _RootZone.runBinary ',
-            r'^#27     _FutureListener.handleError ',
-            r'^#28     Future._propagateToListeners.handleError ',
-            r'^#29     Future._propagateToListeners ',
-            r'^#30     Future._completeError ',
-            r'^#31     _completeOnAsyncError ',
-            r'^#32     noYields2 ',
-            r'^#33     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#34     _RootZone.runBinary ',
-            r'^#35     _FutureListener.handleError ',
-            r'^#36     Future._propagateToListeners.handleError ',
-            r'^#37     Future._propagateToListeners ',
-            r'^#38     Future._completeError ',
-            r'^#39     Future._asyncCompleteError.<anonymous closure> ',
-            r'^#40     _microtaskLoop ',
-            r'^#41     _startMicrotaskLoop ',
-            r'^#42     _runPendingImmediateCallback ',
-            r'^#43     _RawReceivePortImpl._handleMessage ',
+            r'^#16     assertStack ',
+            r'^#17     _RootZone.runUnary ',
+            r'^#18     _FutureListener.handleValue ',
+            r'^#19     Future._propagateToListeners.handleValueCallback ',
+            r'^#20     Future._propagateToListeners ',
+            r'^#21     Future._complete ',
+            r'^#22     Stream.toList.<anonymous closure> ',
+            r'^#23     _RootZone.runGuarded ',
+            r'^#24     _BufferingStreamSubscription._sendDone.sendDone ',
+            r'^#25     _BufferingStreamSubscription._sendDone ',
+            r'^#26     _BufferingStreamSubscription._close ',
+            r'^#27     _SinkTransformerStreamSubscription._close ',
+            r'^#28     _EventSinkWrapper.close ',
+            r'^#29     _StringAdapterSink.close ',
+            r'^#30     _LineSplitterSink.close ',
+            r'^#31     _SinkTransformerStreamSubscription._handleDone ',
+            r'^#32     _RootZone.runGuarded ',
+            r'^#33     _BufferingStreamSubscription._sendDone.sendDone ',
+            r'^#34     _BufferingStreamSubscription._sendDone ',
+            r'^#35     _DelayedDone.perform ',
+            r'^#36     _StreamImplEvents.handleNext ',
+            r'^#37     _PendingEvents.schedule.<anonymous closure> ',
+            r'^#38     _microtaskLoop ',
+            r'^#39     _startMicrotaskLoop ',
+            r'^#40     _runPendingImmediateCallback ',
+            r'^#41     _RawReceivePortImpl._handleMessage ',
           ],
       debugInfoFilename);
   await doTestAwaitCatchError(
@@ -418,34 +419,32 @@
             r'^#13     Future._propagateToListeners ',
             r'^#14     Future._completeWithValue ',
             r'^#15     _completeOnAsyncReturn ',
-            r'^#16     doTestAwaitThen ',
-            r'^#17     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#18     _RootZone.runBinary ',
-            r'^#19     _FutureListener.handleError ',
-            r'^#20     Future._propagateToListeners.handleError ',
-            r'^#21     Future._propagateToListeners ',
-            r'^#22     Future._completeError ',
-            r'^#23     _completeOnAsyncError ',
-            r'^#24     noYields ',
-            r'^#25     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#26     _RootZone.runBinary ',
-            r'^#27     _FutureListener.handleError ',
-            r'^#28     Future._propagateToListeners.handleError ',
-            r'^#29     Future._propagateToListeners ',
-            r'^#30     Future._completeError ',
-            r'^#31     _completeOnAsyncError ',
-            r'^#32     noYields2 ',
-            r'^#33     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#34     _RootZone.runBinary ',
-            r'^#35     _FutureListener.handleError ',
-            r'^#36     Future._propagateToListeners.handleError ',
-            r'^#37     Future._propagateToListeners ',
-            r'^#38     Future._completeError ',
-            r'^#39     Future._asyncCompleteError.<anonymous closure> ',
-            r'^#40     _microtaskLoop ',
-            r'^#41     _startMicrotaskLoop ',
-            r'^#42     _runPendingImmediateCallback ',
-            r'^#43     _RawReceivePortImpl._handleMessage ',
+            r'^#16     assertStack ',
+            r'^#17     _RootZone.runUnary ',
+            r'^#18     _FutureListener.handleValue ',
+            r'^#19     Future._propagateToListeners.handleValueCallback ',
+            r'^#20     Future._propagateToListeners ',
+            r'^#21     Future._complete ',
+            r'^#22     Stream.toList.<anonymous closure> ',
+            r'^#23     _RootZone.runGuarded ',
+            r'^#24     _BufferingStreamSubscription._sendDone.sendDone ',
+            r'^#25     _BufferingStreamSubscription._sendDone ',
+            r'^#26     _BufferingStreamSubscription._close ',
+            r'^#27     _SinkTransformerStreamSubscription._close ',
+            r'^#28     _EventSinkWrapper.close ',
+            r'^#29     _StringAdapterSink.close ',
+            r'^#30     _LineSplitterSink.close ',
+            r'^#31     _SinkTransformerStreamSubscription._handleDone ',
+            r'^#32     _RootZone.runGuarded ',
+            r'^#33     _BufferingStreamSubscription._sendDone.sendDone ',
+            r'^#34     _BufferingStreamSubscription._sendDone ',
+            r'^#35     _DelayedDone.perform ',
+            r'^#36     _StreamImplEvents.handleNext ',
+            r'^#37     _PendingEvents.schedule.<anonymous closure> ',
+            r'^#38     _microtaskLoop ',
+            r'^#39     _startMicrotaskLoop ',
+            r'^#40     _runPendingImmediateCallback ',
+            r'^#41     _RawReceivePortImpl._handleMessage ',
           ],
       debugInfoFilename);
 
@@ -642,329 +641,497 @@
     await doTestAwaitCatchError(
         futureSyncWhenComplete, expected, debugInfoFilename);
   }
+
+  {
+    final expected = const <String>[
+      r'^#0      throwSync \(.*/utils.dart:16(:3)?\)$',
+      r'^#1      futureThen.<anonymous closure> \(.*/utils.dart:187(:5)?\)$',
+      r'^#2      _RootZone.runUnary ',
+      r'^#3      _FutureListener.handleValue ',
+      r'^#4      Future._propagateToListeners.handleValueCallback ',
+      r'^#5      Future._propagateToListeners ',
+      r'^#6      Future._completeWithValue ',
+      r'^#7      Future._asyncCompleteWithValue.<anonymous closure> ',
+      r'^#8      _microtaskLoop ',
+      r'^#9      _startMicrotaskLoop ',
+      r'^#10     _runPendingImmediateCallback ',
+      r'^#11     _RawReceivePortImpl._handleMessage ',
+    ];
+    await doTestAwait(futureThen, expected, debugInfoFilename);
+    await doTestAwaitThen(futureThen, expected, debugInfoFilename);
+    await doTestAwaitCatchError(futureThen, expected, debugInfoFilename);
+  }
 }
 
 // For: --lazy-async-stacks
 Future<void> doTestsLazy([String? debugInfoFilename]) async {
-  final allYieldExpected = const <String>[
-    r'^#0      throwSync \(.*/utils.dart:16(:3)?\)$',
-    r'^#1      allYield3 \(.*/utils.dart:39(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      allYield2 \(.*/utils.dart:34(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#3      allYield \(.*/utils.dart:29(:3)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      allYield,
-      allYieldExpected +
-          const <String>[
-            r'^#4      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#5      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#6      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      allYield,
-      allYieldExpected +
-          const <String>[
-            r'^#4      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(allYield, allYieldExpected, debugInfoFilename);
+  // allYield
+  {
+    final allYieldExpected = const <String>[
+      r'^#0      throwSync \(.*/utils.dart:16(:3)?\)$',
+      r'^#1      allYield3 \(.*/utils.dart:39(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      allYield2 \(.*/utils.dart:34(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#3      allYield \(.*/utils.dart:29(:3)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        allYield,
+        allYieldExpected +
+            const <String>[
+              r'^#4      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#5      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#6      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        allYield,
+        allYieldExpected +
+            const <String>[
+              r'^#4      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#5      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#6      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        allYield,
+        allYieldExpected +
+            const <String>[
+              r'^#4      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#5      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#6      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
 
-  final noYieldsExpected = const <String>[
-    r'^#0      throwSync \(.*/utils.dart:16(:3)?\)$',
-    r'^#1      noYields3 \(.*/utils.dart:54(:3)?\)$',
-    r'^#2      noYields2 \(.*/utils.dart:50(:9)?\)$',
-    r'^#3      noYields \(.*/utils.dart:46(:9)?\)$',
-  ];
-  await doTestAwait(
-      noYields,
-      noYieldsExpected +
-          const <String>[
-            r'^#4      doTestAwait ',
-            r'^#5      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#6      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      noYields,
-      noYieldsExpected +
-          const <String>[
-            r'^#4      doTestAwaitThen ',
-            r'^#5      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#6      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(
-      noYields,
-      noYieldsExpected +
-          const <String>[
-            r'^#4      doTestAwaitCatchError ',
-            r'^#5      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#6      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
+  // noYields
+  {
+    final noYieldsExpected = const <String>[
+      r'^#0      throwSync \(.*/utils.dart:16(:3)?\)$',
+      r'^#1      noYields3 \(.*/utils.dart:54(:3)?\)$',
+      r'^#2      noYields2 \(.*/utils.dart:50(:9)?\)$',
+      r'^#3      noYields \(.*/utils.dart:46(:9)?\)$',
+    ];
+    await doTestAwait(
+        noYields,
+        noYieldsExpected +
+            const <String>[
+              r'^#4      doTestAwait ',
+              r'^#5      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#6      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        noYields,
+        noYieldsExpected +
+            const <String>[
+              r'^#4      doTestAwaitThen ',
+              r'^#5      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#6      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        noYields,
+        noYieldsExpected +
+            const <String>[
+              r'^#4      doTestAwaitCatchError ',
+              r'^#5      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#6      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
 
-  final mixedYieldsExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      mixedYields2 \(.*/utils.dart:66(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      mixedYields \(.*/utils.dart:61(:3)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      mixedYields,
-      mixedYieldsExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      mixedYields,
-      mixedYieldsExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(
-      mixedYields, mixedYieldsExpected, debugInfoFilename);
+  // mixedYields
+  {
+    final mixedYieldsExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      mixedYields2 \(.*/utils.dart:66(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      mixedYields \(.*/utils.dart:61(:3)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        mixedYields,
+        mixedYieldsExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        mixedYields,
+        mixedYieldsExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        mixedYields,
+        mixedYieldsExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
 
-  final syncSuffixExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      syncSuffix2 \(.*/utils.dart:82(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      syncSuffix \(.*/utils.dart:77(:3)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      syncSuffix,
-      syncSuffixExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      syncSuffix,
-      syncSuffixExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(
-      syncSuffix, syncSuffixExpected, debugInfoFilename);
+  // syncSuffix
+  {
+    final syncSuffixExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      syncSuffix2 \(.*/utils.dart:82(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      syncSuffix \(.*/utils.dart:77(:3)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        syncSuffix,
+        syncSuffixExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        syncSuffix,
+        syncSuffixExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        syncSuffix,
+        syncSuffixExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
 
-  final nonAsyncNoStackExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      nonAsyncNoStack1 \(.*/utils.dart:95(:36)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      nonAsyncNoStack \(.*/utils.dart:93(:35)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      nonAsyncNoStack,
-      nonAsyncNoStackExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      nonAsyncNoStack,
-      nonAsyncNoStackExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(
-      nonAsyncNoStack, nonAsyncNoStackExpected, debugInfoFilename);
+  // nonAsyncNoStack
+  {
+    final nonAsyncNoStackExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      nonAsyncNoStack1 \(.*/utils.dart:95(:36)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      nonAsyncNoStack \(.*/utils.dart:93(:35)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        nonAsyncNoStack,
+        nonAsyncNoStackExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        nonAsyncNoStack,
+        nonAsyncNoStackExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        nonAsyncNoStack,
+        nonAsyncNoStackExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
 
-  final asyncStarThrowSyncExpected = const <String>[
-    r'^#0      throwSync \(.+/utils.dart:16(:3)?\)$',
-    r'^#1      asyncStarThrowSync \(.+/utils.dart:112(:11)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      awaitEveryAsyncStarThrowSync \(.+/utils.dart:104(:3)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      awaitEveryAsyncStarThrowSync,
-      asyncStarThrowSyncExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      awaitEveryAsyncStarThrowSync,
-      asyncStarThrowSyncExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(awaitEveryAsyncStarThrowSync,
-      asyncStarThrowSyncExpected, debugInfoFilename);
+  // awaitEveryAsyncStarThrowSync
+  {
+    final asyncStarThrowSyncExpected = const <String>[
+      r'^#0      throwSync \(.+/utils.dart:16(:3)?\)$',
+      r'^#1      asyncStarThrowSync \(.+/utils.dart:112(:11)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      awaitEveryAsyncStarThrowSync \(.+/utils.dart:104(:3)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        awaitEveryAsyncStarThrowSync,
+        asyncStarThrowSyncExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        awaitEveryAsyncStarThrowSync,
+        asyncStarThrowSyncExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        awaitEveryAsyncStarThrowSync,
+        asyncStarThrowSyncExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
 
-  final asyncStarThrowAsyncExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      awaitEveryAsyncStarThrowAsync \(.+/utils.dart:117(:3)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      awaitEveryAsyncStarThrowAsync,
-      asyncStarThrowAsyncExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      awaitEveryAsyncStarThrowAsync,
-      asyncStarThrowAsyncExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(awaitEveryAsyncStarThrowAsync,
-      asyncStarThrowAsyncExpected, debugInfoFilename);
+  // awaitEveryAsyncStarThrowAsync
+  {
+    final asyncStarThrowAsyncExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      awaitEveryAsyncStarThrowAsync \(.+/utils.dart:117(:3)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        awaitEveryAsyncStarThrowAsync,
+        asyncStarThrowAsyncExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        awaitEveryAsyncStarThrowAsync,
+        asyncStarThrowAsyncExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        awaitEveryAsyncStarThrowAsync,
+        asyncStarThrowAsyncExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
 
-  final listenAsyncStartExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      listenAsyncStarThrowAsync.<anonymous closure> \(.+/utils.dart(:0)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename);
-  await doTestAwaitThen(
-      listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename);
-  await doTestAwaitCatchError(
-      listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename);
+  // listenAsyncStarThrowAsync
+  {
+    final listenAsyncStartExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      listenAsyncStarThrowAsync.<anonymous closure> \(.+/utils.dart(:0)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename);
+    await doTestAwaitThen(
+        listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename);
+    await doTestAwaitCatchError(
+        listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename);
+  }
 
-  final customErrorZoneExpected = const <String>[
-    r'#0      throwSync \(.*/utils.dart:16(:3)?\)$',
-    r'#1      allYield3 \(.*/utils.dart:39(:3)?\)$',
-    r'<asynchronous suspension>$',
-    r'#2      allYield2 \(.*/utils.dart:34(:3)?\)$',
-    r'<asynchronous suspension>$',
-    r'#3      allYield \(.*/utils.dart:29(:3)?\)$',
-    r'<asynchronous suspension>$',
-    r'#4      customErrorZone.<anonymous closure> \(.*/utils.dart:144(:5)?\)$',
-    r'<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      customErrorZone, customErrorZoneExpected, debugInfoFilename);
-  await doTestAwaitThen(
-      customErrorZone, customErrorZoneExpected, debugInfoFilename);
-  await doTestAwaitCatchError(
-      customErrorZone, customErrorZoneExpected, debugInfoFilename);
+  // customErrorZone
+  {
+    final customErrorZoneExpected = const <String>[
+      r'#0      throwSync \(.*/utils.dart:16(:3)?\)$',
+      r'#1      allYield3 \(.*/utils.dart:39(:3)?\)$',
+      r'<asynchronous suspension>$',
+      r'#2      allYield2 \(.*/utils.dart:34(:3)?\)$',
+      r'<asynchronous suspension>$',
+      r'#3      allYield \(.*/utils.dart:29(:3)?\)$',
+      r'<asynchronous suspension>$',
+      r'#4      customErrorZone.<anonymous closure> \(.*/utils.dart:144(:5)?\)$',
+      r'<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        customErrorZone, customErrorZoneExpected, debugInfoFilename);
+    await doTestAwaitThen(
+        customErrorZone, customErrorZoneExpected, debugInfoFilename);
+    await doTestAwaitCatchError(
+        customErrorZone, customErrorZoneExpected, debugInfoFilename);
+  }
 
-  final awaitTimeoutExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      Future.timeout.<anonymous closure> \(dart:async/future_impl.dart',
-    r'^<asynchronous suspension>$',
-    r'^#2      awaitTimeout ',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      awaitTimeout,
-      awaitTimeoutExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      awaitTimeout,
-      awaitTimeoutExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(
-      awaitTimeout, awaitTimeoutExpected, debugInfoFilename);
+  // awaitTimeout
+  {
+    final awaitTimeoutExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      Future.timeout.<anonymous closure> \(dart:async/future_impl.dart',
+      r'^<asynchronous suspension>$',
+      r'^#2      awaitTimeout ',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        awaitTimeout,
+        awaitTimeoutExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        awaitTimeout,
+        awaitTimeoutExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        awaitTimeout,
+        awaitTimeoutExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
 
-  final awaitWaitExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      Future.wait.<anonymous closure> \(dart:async/future.dart',
-    r'^<asynchronous suspension>$',
-    r'^#2      awaitWait ',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      awaitWait,
-      awaitWaitExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      awaitWait,
-      awaitWaitExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(awaitWait, awaitWaitExpected, debugInfoFilename);
+  // awaitWait
+  {
+    final awaitWaitExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      Future.wait.<anonymous closure> \(dart:async/future.dart',
+      r'^<asynchronous suspension>$',
+      r'^#2      awaitWait ',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        awaitWait,
+        awaitWaitExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        awaitWait,
+        awaitWaitExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        awaitWait,
+        awaitWaitExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
 
+  // futureSyncWhenComplete
   {
     final expected = const <String>[
       r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
@@ -986,11 +1153,70 @@
         futureSyncWhenComplete,
         expected +
             const <String>[
-              r'^#1      doTestAwaitThen.<anonymous closure> ',
+              r'^#1      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#2      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#3      main ',
               r'^<asynchronous suspension>$',
             ],
         debugInfoFilename);
     await doTestAwaitCatchError(
-        futureSyncWhenComplete, expected, debugInfoFilename);
+        futureSyncWhenComplete,
+        expected +
+            const <String>[
+              r'^#1      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#2      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#3      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
+
+  // futureThen
+  {
+    final expected = const <String>[
+      r'^#0      throwSync \(.*/utils.dart:16(:3)?\)$',
+      r'^#1      futureThen.<anonymous closure> ',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        futureThen,
+        expected +
+            const <String>[
+              r'^#2      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#3      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#4      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        futureThen,
+        expected +
+            const <String>[
+              r'^#2      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#3      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#4      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        futureThen,
+        expected +
+            const <String>[
+              r'^#2      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#3      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#4      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
   }
 }
diff --git a/runtime/tests/vm/dart_2/causal_stacks/utils.dart b/runtime/tests/vm/dart_2/causal_stacks/utils.dart
index 192984f..b7c4e02 100644
--- a/runtime/tests/vm/dart_2/causal_stacks/utils.dart
+++ b/runtime/tests/vm/dart_2/causal_stacks/utils.dart
@@ -178,12 +178,22 @@
   return Future.sync(throwAsync).whenComplete(() => 'nop');
 }
 
+// ----
+// Scenario: Future.then:
+// ----
+
+Future futureThen() {
+  return Future.value(0).then((value) {
+    throwSync();
+  });
+}
+
 // Helpers:
 
 // We want lines that either start with a frame index or an async gap marker.
 final _lineRE = RegExp(r'^(?:#(?<number>\d+)|<asynchronous suspension>)');
 
-void assertStack(List<String> expects, StackTrace stackTrace,
+Future<void> assertStack(List<String> expects, StackTrace stackTrace,
     [String debugInfoFilename]) async {
   final original = await Stream.value(stackTrace.toString())
       .transform(const LineSplitter())
@@ -253,7 +263,7 @@
     await f();
     Expect.fail('No exception thrown!');
   } on String catch (e, s) {
-    assertStack(expectedStack, s, debugInfoFilename);
+    return assertStack(expectedStack, s, debugInfoFilename);
   }
 }
 
@@ -267,7 +277,7 @@
     await f().then((e) => Expect.fail('No exception thrown!'));
     Expect.fail('No exception thrown!');
   } on String catch (e, s) {
-    assertStack(expectedStack, s, debugInfoFilename);
+    return assertStack(expectedStack, s, debugInfoFilename);
   }
 }
 
@@ -278,7 +288,7 @@
   await f().catchError((e, s) {
     stackTrace = s;
   });
-  assertStack(expectedStack, stackTrace, debugInfoFilename);
+  return assertStack(expectedStack, stackTrace, debugInfoFilename);
 }
 
 // ----
@@ -327,39 +337,32 @@
             r'^#13     Future._propagateToListeners ',
             r'^#14     Future._completeWithValue ',
             r'^#15     _completeOnAsyncReturn ',
-            r'^#16     doTestAwaitCatchError ',
+            r'^#16     assertStack ',
             r'^#17     _RootZone.runUnary ',
             r'^#18     _FutureListener.handleValue ',
             r'^#19     Future._propagateToListeners.handleValueCallback ',
             r'^#20     Future._propagateToListeners ',
-            r'^#21     Future._completeError ',
-            r'^#22     _completeOnAsyncError ',
-            r'^#23     allYield ',
-            r'^#24     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#25     _RootZone.runBinary ',
-            r'^#26     _FutureListener.handleError ',
-            r'^#27     Future._propagateToListeners.handleError ',
-            r'^#28     Future._propagateToListeners ',
-            r'^#29     Future._completeError ',
-            r'^#30     _completeOnAsyncError ',
-            r'^#31     allYield2 ',
-            r'^#32     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#33     _RootZone.runBinary ',
-            r'^#34     _FutureListener.handleError ',
-            r'^#35     Future._propagateToListeners.handleError ',
-            r'^#36     Future._propagateToListeners ',
-            r'^#37     Future._completeError ',
-            r'^#38     _completeOnAsyncError ',
-            r'^#39     allYield3 ',
-            r'^#40     _RootZone.runUnary ',
-            r'^#41     _FutureListener.handleValue ',
-            r'^#42     Future._propagateToListeners.handleValueCallback ',
-            r'^#43     Future._propagateToListeners ',
-            r'^#44     Future._addListener.<anonymous closure> ',
-            r'^#45     _microtaskLoop ',
-            r'^#46     _startMicrotaskLoop ',
-            r'^#47     _runPendingImmediateCallback ',
-            r'^#48     _RawReceivePortImpl._handleMessage ',
+            r'^#21     Future._complete ',
+            r'^#22     Stream.toList.<anonymous closure> ',
+            r'^#23     _RootZone.runGuarded ',
+            r'^#24     _BufferingStreamSubscription._sendDone.sendDone ',
+            r'^#25     _BufferingStreamSubscription._sendDone ',
+            r'^#26     _BufferingStreamSubscription._close ',
+            r'^#27     _SinkTransformerStreamSubscription._close ',
+            r'^#28     _EventSinkWrapper.close ',
+            r'^#29     _StringAdapterSink.close ',
+            r'^#30     _LineSplitterSink.close ',
+            r'^#31     _SinkTransformerStreamSubscription._handleDone ',
+            r'^#32     _RootZone.runGuarded ',
+            r'^#33     _BufferingStreamSubscription._sendDone.sendDone ',
+            r'^#34     _BufferingStreamSubscription._sendDone ',
+            r'^#35     _DelayedDone.perform ',
+            r'^#36     _StreamImplEvents.handleNext ',
+            r'^#37     _PendingEvents.schedule.<anonymous closure> ',
+            r'^#38     _microtaskLoop ',
+            r'^#39     _startMicrotaskLoop ',
+            r'^#40     _runPendingImmediateCallback ',
+            r'^#41     _RawReceivePortImpl._handleMessage ',
           ],
       debugInfoFilename);
   await doTestAwaitThen(
@@ -375,34 +378,32 @@
             r'^#13     Future._propagateToListeners ',
             r'^#14     Future._completeWithValue ',
             r'^#15     _completeOnAsyncReturn ',
-            r'^#16     doTestAwait ',
-            r'^#17     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#18     _RootZone.runBinary ',
-            r'^#19     _FutureListener.handleError ',
-            r'^#20     Future._propagateToListeners.handleError ',
-            r'^#21     Future._propagateToListeners ',
-            r'^#22     Future._completeError ',
-            r'^#23     _completeOnAsyncError ',
-            r'^#24     noYields ',
-            r'^#25     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#26     _RootZone.runBinary ',
-            r'^#27     _FutureListener.handleError ',
-            r'^#28     Future._propagateToListeners.handleError ',
-            r'^#29     Future._propagateToListeners ',
-            r'^#30     Future._completeError ',
-            r'^#31     _completeOnAsyncError ',
-            r'^#32     noYields2 ',
-            r'^#33     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#34     _RootZone.runBinary ',
-            r'^#35     _FutureListener.handleError ',
-            r'^#36     Future._propagateToListeners.handleError ',
-            r'^#37     Future._propagateToListeners ',
-            r'^#38     Future._completeError ',
-            r'^#39     Future._asyncCompleteError.<anonymous closure> ',
-            r'^#40     _microtaskLoop ',
-            r'^#41     _startMicrotaskLoop ',
-            r'^#42     _runPendingImmediateCallback ',
-            r'^#43     _RawReceivePortImpl._handleMessage ',
+            r'^#16     assertStack ',
+            r'^#17     _RootZone.runUnary ',
+            r'^#18     _FutureListener.handleValue ',
+            r'^#19     Future._propagateToListeners.handleValueCallback ',
+            r'^#20     Future._propagateToListeners ',
+            r'^#21     Future._complete ',
+            r'^#22     Stream.toList.<anonymous closure> ',
+            r'^#23     _RootZone.runGuarded ',
+            r'^#24     _BufferingStreamSubscription._sendDone.sendDone ',
+            r'^#25     _BufferingStreamSubscription._sendDone ',
+            r'^#26     _BufferingStreamSubscription._close ',
+            r'^#27     _SinkTransformerStreamSubscription._close ',
+            r'^#28     _EventSinkWrapper.close ',
+            r'^#29     _StringAdapterSink.close ',
+            r'^#30     _LineSplitterSink.close ',
+            r'^#31     _SinkTransformerStreamSubscription._handleDone ',
+            r'^#32     _RootZone.runGuarded ',
+            r'^#33     _BufferingStreamSubscription._sendDone.sendDone ',
+            r'^#34     _BufferingStreamSubscription._sendDone ',
+            r'^#35     _DelayedDone.perform ',
+            r'^#36     _StreamImplEvents.handleNext ',
+            r'^#37     _PendingEvents.schedule.<anonymous closure> ',
+            r'^#38     _microtaskLoop ',
+            r'^#39     _startMicrotaskLoop ',
+            r'^#40     _runPendingImmediateCallback ',
+            r'^#41     _RawReceivePortImpl._handleMessage ',
           ],
       debugInfoFilename);
   await doTestAwaitCatchError(
@@ -418,34 +419,32 @@
             r'^#13     Future._propagateToListeners ',
             r'^#14     Future._completeWithValue ',
             r'^#15     _completeOnAsyncReturn ',
-            r'^#16     doTestAwaitThen ',
-            r'^#17     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#18     _RootZone.runBinary ',
-            r'^#19     _FutureListener.handleError ',
-            r'^#20     Future._propagateToListeners.handleError ',
-            r'^#21     Future._propagateToListeners ',
-            r'^#22     Future._completeError ',
-            r'^#23     _completeOnAsyncError ',
-            r'^#24     noYields ',
-            r'^#25     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#26     _RootZone.runBinary ',
-            r'^#27     _FutureListener.handleError ',
-            r'^#28     Future._propagateToListeners.handleError ',
-            r'^#29     Future._propagateToListeners ',
-            r'^#30     Future._completeError ',
-            r'^#31     _completeOnAsyncError ',
-            r'^#32     noYields2 ',
-            r'^#33     _asyncErrorWrapperHelper.errorCallback ',
-            r'^#34     _RootZone.runBinary ',
-            r'^#35     _FutureListener.handleError ',
-            r'^#36     Future._propagateToListeners.handleError ',
-            r'^#37     Future._propagateToListeners ',
-            r'^#38     Future._completeError ',
-            r'^#39     Future._asyncCompleteError.<anonymous closure> ',
-            r'^#40     _microtaskLoop ',
-            r'^#41     _startMicrotaskLoop ',
-            r'^#42     _runPendingImmediateCallback ',
-            r'^#43     _RawReceivePortImpl._handleMessage ',
+            r'^#16     assertStack ',
+            r'^#17     _RootZone.runUnary ',
+            r'^#18     _FutureListener.handleValue ',
+            r'^#19     Future._propagateToListeners.handleValueCallback ',
+            r'^#20     Future._propagateToListeners ',
+            r'^#21     Future._complete ',
+            r'^#22     Stream.toList.<anonymous closure> ',
+            r'^#23     _RootZone.runGuarded ',
+            r'^#24     _BufferingStreamSubscription._sendDone.sendDone ',
+            r'^#25     _BufferingStreamSubscription._sendDone ',
+            r'^#26     _BufferingStreamSubscription._close ',
+            r'^#27     _SinkTransformerStreamSubscription._close ',
+            r'^#28     _EventSinkWrapper.close ',
+            r'^#29     _StringAdapterSink.close ',
+            r'^#30     _LineSplitterSink.close ',
+            r'^#31     _SinkTransformerStreamSubscription._handleDone ',
+            r'^#32     _RootZone.runGuarded ',
+            r'^#33     _BufferingStreamSubscription._sendDone.sendDone ',
+            r'^#34     _BufferingStreamSubscription._sendDone ',
+            r'^#35     _DelayedDone.perform ',
+            r'^#36     _StreamImplEvents.handleNext ',
+            r'^#37     _PendingEvents.schedule.<anonymous closure> ',
+            r'^#38     _microtaskLoop ',
+            r'^#39     _startMicrotaskLoop ',
+            r'^#40     _runPendingImmediateCallback ',
+            r'^#41     _RawReceivePortImpl._handleMessage ',
           ],
       debugInfoFilename);
 
@@ -642,337 +641,505 @@
     await doTestAwaitCatchError(
         futureSyncWhenComplete, expected, debugInfoFilename);
   }
+
+  {
+    final expected = const <String>[
+      r'^#0      throwSync \(.*/utils.dart:16(:3)?\)$',
+      r'^#1      futureThen.<anonymous closure> \(.*/utils.dart:187(:5)?\)$',
+      r'^#2      _RootZone.runUnary ',
+      r'^#3      _FutureListener.handleValue ',
+      r'^#4      Future._propagateToListeners.handleValueCallback ',
+      r'^#5      Future._propagateToListeners ',
+      r'^#6      Future._completeWithValue ',
+      r'^#7      Future._asyncCompleteWithValue.<anonymous closure> ',
+      r'^#8      _microtaskLoop ',
+      r'^#9      _startMicrotaskLoop ',
+      r'^#10     _runPendingImmediateCallback ',
+      r'^#11     _RawReceivePortImpl._handleMessage ',
+    ];
+    await doTestAwait(futureThen, expected, debugInfoFilename);
+    await doTestAwaitThen(futureThen, expected, debugInfoFilename);
+    await doTestAwaitCatchError(futureThen, expected, debugInfoFilename);
+  }
 }
 
 // For: --lazy-async-stacks
 Future<void> doTestsLazy([String debugInfoFilename]) async {
-  final allYieldExpected = const <String>[
-    r'^#0      throwSync \(.*/utils.dart:16(:3)?\)$',
-    r'^#1      allYield3 \(.*/utils.dart:39(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      allYield2 \(.*/utils.dart:34(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#3      allYield \(.*/utils.dart:29(:3)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      allYield,
-      allYieldExpected +
-          const <String>[
-            r'^#4      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#5      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#6      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      allYield,
-      allYieldExpected +
-          const <String>[
-            r'^#4      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(allYield, allYieldExpected, debugInfoFilename);
-
-  final noYieldsExpected = const <String>[
-    r'^#0      throwSync \(.*/utils.dart:16(:3)?\)$',
-    r'^#1      noYields3 \(.*/utils.dart:54(:3)?\)$',
-    r'^#2      noYields2 \(.*/utils.dart:50(:9)?\)$',
-    r'^#3      noYields \(.*/utils.dart:46(:9)?\)$',
-  ];
-  await doTestAwait(
-      noYields,
-      noYieldsExpected +
-          const <String>[
-            r'^#4      doTestAwait ',
-            r'^#5      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#6      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      noYields,
-      noYieldsExpected +
-          const <String>[
-            r'^#4      doTestAwaitThen ',
-            r'^#5      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#6      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(
-      noYields,
-      noYieldsExpected +
-          const <String>[
-            r'^#4      doTestAwaitCatchError ',
-            r'^#5      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#6      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-
-  final mixedYieldsExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      mixedYields2 \(.*/utils.dart:66(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      mixedYields \(.*/utils.dart:61(:3)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      mixedYields,
-      mixedYieldsExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      mixedYields,
-      mixedYieldsExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(
-      mixedYields, mixedYieldsExpected, debugInfoFilename);
-
-  final syncSuffixExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      syncSuffix2 \(.*/utils.dart:82(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      syncSuffix \(.*/utils.dart:77(:3)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      syncSuffix,
-      syncSuffixExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      syncSuffix,
-      syncSuffixExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(
-      syncSuffix, syncSuffixExpected, debugInfoFilename);
-
-  final nonAsyncNoStackExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      nonAsyncNoStack1 \(.*/utils.dart:95(:36)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      nonAsyncNoStack \(.*/utils.dart:93(:35)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      nonAsyncNoStack,
-      nonAsyncNoStackExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      nonAsyncNoStack,
-      nonAsyncNoStackExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(
-      nonAsyncNoStack, nonAsyncNoStackExpected, debugInfoFilename);
-
-  final asyncStarThrowSyncExpected = const <String>[
-    r'^#0      throwSync \(.+/utils.dart:16(:3)?\)$',
-    r'^#1      asyncStarThrowSync \(.+/utils.dart:112(:11)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      awaitEveryAsyncStarThrowSync \(.+/utils.dart:104(:3)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      awaitEveryAsyncStarThrowSync,
-      asyncStarThrowSyncExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      awaitEveryAsyncStarThrowSync,
-      asyncStarThrowSyncExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(awaitEveryAsyncStarThrowSync,
-      asyncStarThrowSyncExpected, debugInfoFilename);
-
-  final asyncStarThrowAsyncExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      awaitEveryAsyncStarThrowAsync \(.+/utils.dart:117(:3)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      awaitEveryAsyncStarThrowAsync,
-      asyncStarThrowAsyncExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      awaitEveryAsyncStarThrowAsync,
-      asyncStarThrowAsyncExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(awaitEveryAsyncStarThrowAsync,
-      asyncStarThrowAsyncExpected, debugInfoFilename);
-
-  final listenAsyncStartExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#2      listenAsyncStarThrowAsync.<anonymous closure> \(.+/utils.dart(:0)?\)$',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename);
-  await doTestAwaitThen(
-      listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename);
-  await doTestAwaitCatchError(
-      listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename);
-
-  final customErrorZoneExpected = const <String>[
-    r'#0      throwSync \(.*/utils.dart:16(:3)?\)$',
-    r'#1      allYield3 \(.*/utils.dart:39(:3)?\)$',
-    r'<asynchronous suspension>$',
-    r'#2      allYield2 \(.*/utils.dart:34(:3)?\)$',
-    r'<asynchronous suspension>$',
-    r'#3      allYield \(.*/utils.dart:29(:3)?\)$',
-    r'<asynchronous suspension>$',
-    r'#4      customErrorZone.<anonymous closure> \(.*/utils.dart:144(:5)?\)$',
-    r'<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      customErrorZone, customErrorZoneExpected, debugInfoFilename);
-  await doTestAwaitThen(
-      customErrorZone, customErrorZoneExpected, debugInfoFilename);
-  await doTestAwaitCatchError(
-      customErrorZone, customErrorZoneExpected, debugInfoFilename);
-
-  final awaitTimeoutExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      Future.timeout.<anonymous closure> \(dart:async/future_impl.dart',
-    r'^<asynchronous suspension>$',
-    r'^#2      awaitTimeout ',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      awaitTimeout,
-      awaitTimeoutExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      awaitTimeout,
-      awaitTimeoutExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(
-      awaitTimeout, awaitTimeoutExpected, debugInfoFilename);
-
-  final awaitWaitExpected = const <String>[
-    r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
-    r'^<asynchronous suspension>$',
-    r'^#1      Future.wait.<anonymous closure> \(dart:async/future.dart',
-    r'^<asynchronous suspension>$',
-    r'^#2      awaitWait ',
-    r'^<asynchronous suspension>$',
-  ];
-  await doTestAwait(
-      awaitWait,
-      awaitWaitExpected +
-          const <String>[
-            r'^#3      doTestAwait ',
-            r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
-            r'^<asynchronous suspension>$',
-            r'^#5      main ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitThen(
-      awaitWait,
-      awaitWaitExpected +
-          const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
-            r'^<asynchronous suspension>$',
-          ],
-      debugInfoFilename);
-  await doTestAwaitCatchError(awaitWait, awaitWaitExpected, debugInfoFilename);
-
+  // allYield
   {
-    final expect = const <String>[
+    final allYieldExpected = const <String>[
+      r'^#0      throwSync \(.*/utils.dart:16(:3)?\)$',
+      r'^#1      allYield3 \(.*/utils.dart:39(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      allYield2 \(.*/utils.dart:34(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#3      allYield \(.*/utils.dart:29(:3)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        allYield,
+        allYieldExpected +
+            const <String>[
+              r'^#4      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#5      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#6      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        allYield,
+        allYieldExpected +
+            const <String>[
+              r'^#4      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#5      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#6      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        allYield,
+        allYieldExpected +
+            const <String>[
+              r'^#4      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#5      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#6      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
+
+  // noYields
+  {
+    final noYieldsExpected = const <String>[
+      r'^#0      throwSync \(.*/utils.dart:16(:3)?\)$',
+      r'^#1      noYields3 \(.*/utils.dart:54(:3)?\)$',
+      r'^#2      noYields2 \(.*/utils.dart:50(:9)?\)$',
+      r'^#3      noYields \(.*/utils.dart:46(:9)?\)$',
+    ];
+    await doTestAwait(
+        noYields,
+        noYieldsExpected +
+            const <String>[
+              r'^#4      doTestAwait ',
+              r'^#5      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#6      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        noYields,
+        noYieldsExpected +
+            const <String>[
+              r'^#4      doTestAwaitThen ',
+              r'^#5      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#6      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        noYields,
+        noYieldsExpected +
+            const <String>[
+              r'^#4      doTestAwaitCatchError ',
+              r'^#5      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#6      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
+
+  // mixedYields
+  {
+    final mixedYieldsExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      mixedYields2 \(.*/utils.dart:66(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      mixedYields \(.*/utils.dart:61(:3)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        mixedYields,
+        mixedYieldsExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        mixedYields,
+        mixedYieldsExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        mixedYields,
+        mixedYieldsExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
+
+  // syncSuffix
+  {
+    final syncSuffixExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      syncSuffix2 \(.*/utils.dart:82(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      syncSuffix \(.*/utils.dart:77(:3)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        syncSuffix,
+        syncSuffixExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        syncSuffix,
+        syncSuffixExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        syncSuffix,
+        syncSuffixExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
+
+  // nonAsyncNoStack
+  {
+    final nonAsyncNoStackExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      nonAsyncNoStack1 \(.*/utils.dart:95(:36)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      nonAsyncNoStack \(.*/utils.dart:93(:35)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        nonAsyncNoStack,
+        nonAsyncNoStackExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        nonAsyncNoStack,
+        nonAsyncNoStackExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        nonAsyncNoStack,
+        nonAsyncNoStackExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
+
+  // awaitEveryAsyncStarThrowSync
+  {
+    final asyncStarThrowSyncExpected = const <String>[
+      r'^#0      throwSync \(.+/utils.dart:16(:3)?\)$',
+      r'^#1      asyncStarThrowSync \(.+/utils.dart:112(:11)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      awaitEveryAsyncStarThrowSync \(.+/utils.dart:104(:3)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        awaitEveryAsyncStarThrowSync,
+        asyncStarThrowSyncExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        awaitEveryAsyncStarThrowSync,
+        asyncStarThrowSyncExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        awaitEveryAsyncStarThrowSync,
+        asyncStarThrowSyncExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
+
+  // awaitEveryAsyncStarThrowAsync
+  {
+    final asyncStarThrowAsyncExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      awaitEveryAsyncStarThrowAsync \(.+/utils.dart:117(:3)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        awaitEveryAsyncStarThrowAsync,
+        asyncStarThrowAsyncExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        awaitEveryAsyncStarThrowAsync,
+        asyncStarThrowAsyncExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        awaitEveryAsyncStarThrowAsync,
+        asyncStarThrowAsyncExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
+
+  // listenAsyncStarThrowAsync
+  {
+    final listenAsyncStartExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#2      listenAsyncStarThrowAsync.<anonymous closure> \(.+/utils.dart(:0)?\)$',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename);
+    await doTestAwaitThen(
+        listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename);
+    await doTestAwaitCatchError(
+        listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename);
+  }
+
+  // customErrorZone
+  {
+    final customErrorZoneExpected = const <String>[
+      r'#0      throwSync \(.*/utils.dart:16(:3)?\)$',
+      r'#1      allYield3 \(.*/utils.dart:39(:3)?\)$',
+      r'<asynchronous suspension>$',
+      r'#2      allYield2 \(.*/utils.dart:34(:3)?\)$',
+      r'<asynchronous suspension>$',
+      r'#3      allYield \(.*/utils.dart:29(:3)?\)$',
+      r'<asynchronous suspension>$',
+      r'#4      customErrorZone.<anonymous closure> \(.*/utils.dart:144(:5)?\)$',
+      r'<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        customErrorZone, customErrorZoneExpected, debugInfoFilename);
+    await doTestAwaitThen(
+        customErrorZone, customErrorZoneExpected, debugInfoFilename);
+    await doTestAwaitCatchError(
+        customErrorZone, customErrorZoneExpected, debugInfoFilename);
+  }
+
+  // awaitTimeout
+  {
+    final awaitTimeoutExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      Future.timeout.<anonymous closure> \(dart:async/future_impl.dart',
+      r'^<asynchronous suspension>$',
+      r'^#2      awaitTimeout ',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        awaitTimeout,
+        awaitTimeoutExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        awaitTimeout,
+        awaitTimeoutExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        awaitTimeout,
+        awaitTimeoutExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
+
+  // awaitWait
+  {
+    final awaitWaitExpected = const <String>[
+      r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
+      r'^<asynchronous suspension>$',
+      r'^#1      Future.wait.<anonymous closure> \(dart:async/future.dart',
+      r'^<asynchronous suspension>$',
+      r'^#2      awaitWait ',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        awaitWait,
+        awaitWaitExpected +
+            const <String>[
+              r'^#3      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        awaitWait,
+        awaitWaitExpected +
+            const <String>[
+              r'^#3      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        awaitWait,
+        awaitWaitExpected +
+            const <String>[
+              r'^#3      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#4      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#5      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
+
+  // futureSyncWhenComplete
+  {
+    final expected = const <String>[
       r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
       r'^<asynchronous suspension>$',
     ];
     await doTestAwait(
         futureSyncWhenComplete,
-        expect +
+        expected +
             const <String>[
               r'^#1      doTestAwait ',
               r'^<asynchronous suspension>$',
@@ -984,13 +1151,72 @@
         debugInfoFilename);
     await doTestAwaitThen(
         futureSyncWhenComplete,
-        expect +
+        expected +
             const <String>[
-              r'^#1      doTestAwaitThen.<anonymous closure> ',
+              r'^#1      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#2      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#3      main ',
               r'^<asynchronous suspension>$',
             ],
         debugInfoFilename);
     await doTestAwaitCatchError(
-        futureSyncWhenComplete, expect, debugInfoFilename);
+        futureSyncWhenComplete,
+        expected +
+            const <String>[
+              r'^#1      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#2      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#3      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+  }
+
+  // futureThen
+  {
+    final expected = const <String>[
+      r'^#0      throwSync \(.*/utils.dart:16(:3)?\)$',
+      r'^#1      futureThen.<anonymous closure> ',
+      r'^<asynchronous suspension>$',
+    ];
+    await doTestAwait(
+        futureThen,
+        expected +
+            const <String>[
+              r'^#2      doTestAwait ',
+              r'^<asynchronous suspension>$',
+              r'^#3      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#4      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitThen(
+        futureThen,
+        expected +
+            const <String>[
+              r'^#2      doTestAwaitThen ',
+              r'^<asynchronous suspension>$',
+              r'^#3      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#4      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
+    await doTestAwaitCatchError(
+        futureThen,
+        expected +
+            const <String>[
+              r'^#2      doTestAwaitCatchError ',
+              r'^<asynchronous suspension>$',
+              r'^#3      doTestsLazy ',
+              r'^<asynchronous suspension>$',
+              r'^#4      main ',
+              r'^<asynchronous suspension>$',
+            ],
+        debugInfoFilename);
   }
 }
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index e221513..134b26b 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1042,7 +1042,20 @@
         field->untag()->end_token_pos_ = d->ReadTokenPosition();
         field->untag()->guarded_cid_ = d->ReadCid();
         field->untag()->is_nullable_ = d->ReadCid();
-        field->untag()->static_type_exactness_state_ = d->Read<int8_t>();
+        const int8_t static_type_exactness_state = d->Read<int8_t>();
+#if defined(TARGET_ARCH_X64)
+        field->untag()->static_type_exactness_state_ =
+            static_type_exactness_state;
+#else
+        // We might produce core snapshots using X64 VM and then consume
+        // them in IA32 or ARM VM. In which case we need to simply ignore
+        // static type exactness state written into snapshot because non-X64
+        // builds don't have this feature enabled.
+        // TODO(dartbug.com/34170) Support other architectures.
+        USE(static_type_exactness_state);
+        field->untag()->static_type_exactness_state_ =
+            StaticTypeExactnessState::NotTracking().Encode();
+#endif  // defined(TARGET_ARCH_X64)
 #if !defined(DART_PRECOMPILED_RUNTIME)
         field->untag()->kernel_offset_ = d->Read<uint32_t>();
 #endif
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 185af0a..6822001 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -196,6 +196,8 @@
   V(_Utf8Decoder, _scan, Utf8DecoderScan, 0xb35ced99)                          \
   V(_Future, timeout, FutureTimeout, 0x6ad7d1ef)                               \
   V(Future, wait, FutureWait, 0x264aacc2)                                      \
+  V(_RootZone, runUnary, RootZoneRunUnary, 0x76e41d34)                         \
+  V(_FutureListener, handleValue, FutureListenerHandleValue, 0x73894d16)       \
 
 // List of intrinsics:
 // (class-name, function-name, intrinsification method, fingerprint).
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 7f6775d..51975f3 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -1848,7 +1848,7 @@
                                      /*skip_frames=*/0, &on_sync_frame,
                                      &has_async);
 
-  // If the entire stack is sync, return no trace.
+  // If the entire stack is sync, return no (async) trace.
   if (!has_async) {
     return nullptr;
   }
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 5a6c5a9..96ad60d 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -528,6 +528,19 @@
   frames_.Unpoison();
 }
 
+StackFrameIterator::StackFrameIterator(const StackFrameIterator& orig)
+    : validate_(orig.validate_),
+      entry_(orig.thread_),
+      exit_(orig.thread_),
+      frames_(orig.thread_),
+      current_frame_(nullptr),
+      thread_(orig.thread_) {
+  frames_.fp_ = orig.frames_.fp_;
+  frames_.sp_ = orig.frames_.sp_;
+  frames_.pc_ = orig.frames_.pc_;
+  frames_.Unpoison();
+}
+
 StackFrame* StackFrameIterator::NextFrame() {
   // When we are at the start of iteration after having created an
   // iterator object, current_frame_ will be NULL as we haven't seen
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index 92f864f..6969642 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -236,6 +236,8 @@
                      Thread* thread,
                      CrossThreadPolicy cross_thread_policy);
 
+  StackFrameIterator(const StackFrameIterator& orig);
+
   // Checks if a next frame exists.
   bool HasNextFrame() const { return frames_.fp_ != 0; }
 
@@ -300,7 +302,6 @@
   Thread* thread_;
 
   friend class ProfilerDartStackWalker;
-  DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
 };
 
 // Iterator for iterating over all dart frames (skips over exit frames,
@@ -339,6 +340,8 @@
                 thread,
                 cross_thread_policy) {}
 
+  DartFrameIterator(const DartFrameIterator& orig) : frames_(orig.frames_) {}
+
   // Get next dart frame.
   StackFrame* NextFrame() {
     StackFrame* frame = frames_.NextFrame();
@@ -350,8 +353,6 @@
 
  private:
   StackFrameIterator frames_;
-
-  DISALLOW_COPY_AND_ASSIGN(DartFrameIterator);
 };
 
 // Iterator for iterating over all inlined dart functions in an optimized
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index ae8849a..a231568 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -10,11 +10,18 @@
 
 namespace dart {
 
-// Keep in sync with
-// sdk/lib/async/stream_controller.dart:_StreamController._STATE_SUBSCRIBED.
+// Keep in sync with:
+// - sdk/lib/async/stream_controller.dart:_StreamController._STATE_SUBSCRIBED.
 const intptr_t k_StreamController__STATE_SUBSCRIBED = 1;
-// sdk/lib/async/future_impl.dart:_FutureListener.stateWhencomplete.
-const intptr_t k_FutureListener_stateWhencomplete = 8;
+// - sdk/lib/async/future_impl.dart:_FutureListener.stateThen.
+const intptr_t k_FutureListener_stateThen = 1;
+// - sdk/lib/async/future_impl.dart:_FutureListener.stateCatchError.
+const intptr_t k_FutureListener_stateCatchError = 2;
+// - sdk/lib/async/future_impl.dart:_FutureListener.stateWhenComplete.
+const intptr_t k_FutureListener_stateWhenComplete = 8;
+
+// Keep in sync with sdk/lib/async/future_impl.dart:_FutureListener.handleValue.
+const intptr_t kNumArgsFutureListenerHandleValue = 1;
 
 // Find current yield index from async closure.
 // Async closures contains a variable, :await_jump_var that holds the index into
@@ -140,21 +147,19 @@
   ASSERT(!future.IsNull());
   ASSERT(future.GetClassId() == future_impl_class.id());
 
-  listener_ = Instance::Cast(future).GetField(future_result_or_listeners_field);
-  if (listener_.GetClassId() != future_listener_class.id()) {
+  // Since this function is recursive, we have to keep a local ref.
+  auto& listener = Object::Handle(
+      Instance::Cast(future).GetField(future_result_or_listeners_field));
+  if (listener.GetClassId() != future_listener_class.id()) {
     return Closure::null();
   }
 
-  // If the _FutureListener is a whenComplete listener, follow the Future being
-  // completed, `result`, instead of the dangling whenComplete `callback`.
-  state_ = Instance::Cast(listener_).GetField(future_listener_state_field);
-  ASSERT(state_.IsSmi());
-  if (Smi::Cast(state_).Value() == k_FutureListener_stateWhencomplete) {
-    future_ = Instance::Cast(listener_).GetField(future_listener_result_field);
-    return GetCallerInFutureImpl(future_);
+  callback_ = GetCallerInFutureListener(listener);
+  if (callback_.IsInstance() && !callback_.IsNull()) {
+    return Closure::Cast(callback_).ptr();
   }
 
-  callback_ = Instance::Cast(listener_).GetField(callback_field);
+  callback_ = Instance::Cast(listener).GetField(callback_field);
   // This happens for e.g.: await f().catchError(..);
   if (callback_.IsNull()) {
     return Closure::null();
@@ -221,22 +226,46 @@
   UNREACHABLE();  // If no onData is found we have a bug.
 }
 
+ClosurePtr CallerClosureFinder::GetCallerInFutureListener(
+    const Object& future_listener) {
+  ASSERT(future_listener.GetClassId() == future_listener_class.id());
+
+  state_ =
+      Instance::Cast(future_listener).GetField(future_listener_state_field);
+
+  auto value = Smi::Cast(state_).Value();
+  // If the _FutureListener is a `then`, `catchError`, or `whenComplete`
+  // listener, follow the Future being completed, `result`, instead of the
+  // dangling whenComplete `callback`.
+  if (value == k_FutureListener_stateThen ||
+      value == k_FutureListener_stateCatchError ||
+      value == k_FutureListener_stateWhenComplete) {
+    future_ =
+        Instance::Cast(future_listener).GetField(future_listener_result_field);
+    return GetCallerInFutureImpl(future_);
+  }
+
+  return Closure::null();
+}
+
 ClosurePtr CallerClosureFinder::FindCaller(const Closure& receiver_closure) {
   receiver_function_ = receiver_closure.function();
   receiver_context_ = receiver_closure.context();
 
   if (receiver_function_.IsAsyncClosure()) {
     return FindCallerInAsyncClosure(receiver_context_);
-  } else if (receiver_function_.IsAsyncGenClosure()) {
+  }
+  if (receiver_function_.IsAsyncGenClosure()) {
     return FindCallerInAsyncGenClosure(receiver_context_);
-  } else if (receiver_function_.IsLocalFunction()) {
+  }
+  if (receiver_function_.IsLocalFunction()) {
     parent_function_ = receiver_function_.parent_function();
     if (parent_function_.recognized_kind() ==
         MethodRecognizer::kFutureTimeout) {
       context_entry_ = receiver_context_.At(Context::kFutureTimeoutFutureIndex);
       return GetCallerInFutureImpl(context_entry_);
-    } else if (parent_function_.recognized_kind() ==
-               MethodRecognizer::kFutureWait) {
+    }
+    if (parent_function_.recognized_kind() == MethodRecognizer::kFutureWait) {
       receiver_context_ = receiver_context_.parent();
       ASSERT(!receiver_context_.IsNull());
       context_entry_ = receiver_context_.At(Context::kFutureWaitFutureIndex);
@@ -300,6 +329,114 @@
   UNREACHABLE();
 }
 
+ClosurePtr StackTraceUtils::ClosureFromFrameFunction(
+    Zone* zone,
+    CallerClosureFinder* caller_closure_finder,
+    const DartFrameIterator& frames,
+    StackFrame* frame,
+    bool* skip_frame,
+    bool* is_async) {
+  auto& closure = Closure::Handle(zone);
+  auto& function = Function::Handle(zone);
+
+  function = frame->LookupDartFunction();
+  if (function.IsNull()) {
+    return Closure::null();
+  }
+
+  if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
+    {
+      NoSafepointScope nsp;
+
+      // Next, look up caller's closure on the stack and walk backwards
+      // through the yields.
+      ObjectPtr* last_caller_obj =
+          reinterpret_cast<ObjectPtr*>(frame->GetCallerSp());
+      closure = FindClosureInFrame(last_caller_obj, function);
+
+      // If this async function hasn't yielded yet, we're still dealing with a
+      // normal stack. Continue to next frame as usual.
+      if (!caller_closure_finder->IsRunningAsync(closure)) {
+        return Closure::null();
+      }
+    }
+
+    *is_async = true;
+
+    // Skip: Already handled this as a sync. frame.
+    return caller_closure_finder->FindCaller(closure);
+  }
+
+  // May have been called from `_FutureListener.handleValue`, which means its
+  // receiver holds the Future chain.
+  if (function.recognized_kind() == MethodRecognizer::kRootZoneRunUnary) {
+    DartFrameIterator future_frames(frames);
+    frame = future_frames.NextFrame();
+    function = frame->LookupDartFunction();
+    if (function.recognized_kind() !=
+        MethodRecognizer::kFutureListenerHandleValue) {
+      return Closure::null();
+    }
+  }
+  if (function.recognized_kind() ==
+      MethodRecognizer::kFutureListenerHandleValue) {
+    *is_async = true;
+    *skip_frame = true;
+
+    // The _FutureListener receiver is at the top of the previous frame, right
+    // before the arguments to the call.
+    Object& receiver =
+        Object::Handle(*(reinterpret_cast<ObjectPtr*>(frame->GetCallerSp()) +
+                         kNumArgsFutureListenerHandleValue));
+
+    return caller_closure_finder->GetCallerInFutureListener(receiver);
+  }
+
+  return Closure::null();
+}
+
+void StackTraceUtils::UnwindAwaiterChain(
+    Zone* zone,
+    const GrowableObjectArray& code_array,
+    const GrowableObjectArray& pc_offset_array,
+    CallerClosureFinder* caller_closure_finder,
+    ClosurePtr leaf_closure) {
+  auto& code = Code::Handle(zone);
+  auto& function = Function::Handle(zone);
+  auto& closure = Closure::Handle(zone, leaf_closure);
+  auto& pc_descs = PcDescriptors::Handle(zone);
+  auto& offset = Smi::Handle(zone);
+
+  // Inject async suspension marker.
+  code_array.Add(StubCode::AsynchronousGapMarker());
+  offset = Smi::New(0);
+  pc_offset_array.Add(offset);
+
+  // Traverse the trail of async futures all the way up.
+  for (; !closure.IsNull();
+       closure = caller_closure_finder->FindCaller(closure)) {
+    function = closure.function();
+    if (function.IsNull()) {
+      continue;
+    }
+    // In hot-reload-test-mode we sometimes have to do this:
+    code = function.EnsureHasCode();
+    RELEASE_ASSERT(!code.IsNull());
+    code_array.Add(code);
+    pc_descs = code.pc_descriptors();
+    offset = Smi::New(FindPcOffset(pc_descs, GetYieldIndex(closure)));
+    // Unlike other sources of PC offsets, the offset may be 0 here if we
+    // reach a non-async closure receiving the yielded value.
+    ASSERT(offset.Value() >= 0);
+    pc_offset_array.Add(offset);
+
+    // Inject async suspension marker.
+    code_array.Add(StubCode::AsynchronousGapMarker());
+    offset = Smi::New(0);
+    pc_offset_array.Add(offset);
+  }
+}
+
 void StackTraceUtils::CollectFramesLazy(
     Thread* thread,
     const GrowableObjectArray& code_array,
@@ -320,13 +457,10 @@
     return;
   }
 
-  auto& function = Function::Handle(zone);
   auto& code = Code::Handle(zone);
   auto& offset = Smi::Handle(zone);
 
-  auto& closure = Closure::Handle(zone);
   CallerClosureFinder caller_closure_finder(zone);
-  auto& pc_descs = PcDescriptors::Handle();
 
   // Start by traversing the sync. part of the stack.
   for (; frame != nullptr; frame = frames.NextFrame()) {
@@ -335,79 +469,36 @@
       continue;
     }
 
-    function = frame->LookupDartFunction();
+    // If we encounter a known part of the async/Future mechanism, unwind the
+    // awaiter chain from the closures.
+    bool skip_frame = false;
+    bool is_async = false;
+    auto closure_ptr = ClosureFromFrameFunction(
+        zone, &caller_closure_finder, frames, frame, &skip_frame, &is_async);
 
-    // Add the current synchronous frame.
-    code = frame->LookupDartCode();
-    ASSERT(function.ptr() == code.function());
-    code_array.Add(code);
-    const intptr_t pc_offset = frame->pc() - code.PayloadStart();
-    ASSERT(pc_offset > 0 && pc_offset <= code.Size());
-    offset = Smi::New(pc_offset);
-    pc_offset_array.Add(offset);
-    if (on_sync_frames != nullptr) {
-      (*on_sync_frames)(frame);
+    // This isn't a special (async) frame we should skip.
+    if (!skip_frame) {
+      // Add the current synchronous frame.
+      code = frame->LookupDartCode();
+      code_array.Add(code);
+      const intptr_t pc_offset = frame->pc() - code.PayloadStart();
+      ASSERT(pc_offset > 0 && pc_offset <= code.Size());
+      offset = Smi::New(pc_offset);
+      pc_offset_array.Add(offset);
+      // Callback for sync frame.
+      if (on_sync_frames != nullptr) {
+        (*on_sync_frames)(frame);
+      }
     }
 
-    // Either continue the loop (sync-async case) or find all await'ers and
-    // return.
-    if (!function.IsNull() &&
-        (function.IsAsyncClosure() || function.IsAsyncGenClosure())) {
+    // This frame is running async.
+    // Note: The closure might still be null in case it's an unawaited future.
+    if (is_async) {
+      UnwindAwaiterChain(zone, code_array, pc_offset_array,
+                         &caller_closure_finder, closure_ptr);
       if (has_async != nullptr) {
         *has_async = true;
       }
-
-      {
-        NoSafepointScope nsp;
-
-        // Next, look up caller's closure on the stack and walk backwards
-        // through the yields.
-        ObjectPtr* last_caller_obj =
-            reinterpret_cast<ObjectPtr*>(frame->GetCallerSp());
-        closure = FindClosureInFrame(last_caller_obj, function);
-
-        // If this async function hasn't yielded yet, we're still dealing with a
-        // normal stack. Continue to next frame as usual.
-        if (!caller_closure_finder.IsRunningAsync(closure)) {
-          continue;
-        }
-      }
-
-      // Inject async suspension marker.
-      code_array.Add(StubCode::AsynchronousGapMarker());
-      offset = Smi::New(0);
-      pc_offset_array.Add(offset);
-
-      // Skip: Already handled this frame's function above.
-      closure = caller_closure_finder.FindCaller(closure);
-
-      // Traverse the trail of async futures all the way up.
-      for (; !closure.IsNull();
-           closure = caller_closure_finder.FindCaller(closure)) {
-        function = closure.function();
-        // In hot-reload-test-mode we sometimes have to do this:
-        if (!function.HasCode()) {
-          function.EnsureHasCode();
-        }
-        if (function.HasCode()) {
-          code = function.CurrentCode();
-          code_array.Add(code);
-          pc_descs = code.pc_descriptors();
-          offset = Smi::New(FindPcOffset(pc_descs, GetYieldIndex(closure)));
-        } else {
-          UNREACHABLE();
-        }
-        // Unlike other sources of PC offsets, the offset may be 0 here if we
-        // reach a non-async closure receiving the yielded value.
-        ASSERT(offset.Value() >= 0);
-        pc_offset_array.Add(offset);
-
-        // Inject async suspension marker.
-        code_array.Add(StubCode::AsynchronousGapMarker());
-        offset = Smi::New(0);
-        pc_offset_array.Add(offset);
-      }
-
       // Ignore the rest of the stack; already unwound all async calls.
       return;
     }
diff --git a/runtime/vm/stack_trace.h b/runtime/vm/stack_trace.h
index 215da83..75ba724 100644
--- a/runtime/vm/stack_trace.h
+++ b/runtime/vm/stack_trace.h
@@ -21,6 +21,8 @@
 
   ClosurePtr GetCallerInFutureImpl(const Object& future_);
 
+  ClosurePtr GetCallerInFutureListener(const Object& future_listener);
+
   ClosurePtr FindCallerInAsyncClosure(const Context& receiver_context);
 
   ClosurePtr FindCallerInAsyncGenClosure(const Context& receiver_context);
@@ -61,6 +63,8 @@
   Field& state_field;
   Field& on_data_field;
   Field& state_data_field;
+
+  DISALLOW_COPY_AND_ASSIGN(CallerClosureFinder);
 };
 
 class StackTraceUtils : public AllStatic {
@@ -69,6 +73,20 @@
   static ClosurePtr FindClosureInFrame(ObjectPtr* last_object_in_caller,
                                        const Function& function);
 
+  static ClosurePtr ClosureFromFrameFunction(
+      Zone* zone,
+      CallerClosureFinder* caller_closure_finder,
+      const DartFrameIterator& frames,
+      StackFrame* frame,
+      bool* skip_frame,
+      bool* is_async);
+
+  static void UnwindAwaiterChain(Zone* zone,
+                                 const GrowableObjectArray& code_array,
+                                 const GrowableObjectArray& pc_offset_array,
+                                 CallerClosureFinder* caller_closure_finder,
+                                 ClosurePtr leaf_closure);
+
   /// Collects all frames on the current stack until an async/async* frame is
   /// hit which has yielded before (i.e. is not in sync-async case).
   ///
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index df8a347..a9f2b80 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -63,18 +63,19 @@
 }
 
 class _FutureListener<S, T> {
+  // Keep in sync with sdk/runtime/vm/stack_trace.cc.
   static const int maskValue = 1;
   static const int maskError = 2;
   static const int maskTestError = 4;
-  static const int maskWhencomplete = 8;
+  static const int maskWhenComplete = 8;
   static const int stateChain = 0;
   static const int stateThen = maskValue;
   static const int stateThenOnerror = maskValue | maskError;
-  static const int stateCatcherror = maskError;
-  static const int stateCatcherrorTest = maskError | maskTestError;
-  static const int stateWhencomplete = maskWhencomplete;
+  static const int stateCatchError = maskError;
+  static const int stateCatchErrorTest = maskError | maskTestError;
+  static const int stateWhenComplete = maskWhenComplete;
   static const int maskType =
-      maskValue | maskError | maskTestError | maskWhencomplete;
+      maskValue | maskError | maskTestError | maskWhenComplete;
   static const int stateIsAwait = 16;
 
   // Listeners on the same future are linked through this link.
@@ -109,18 +110,18 @@
             stateIsAwait;
 
   _FutureListener.catchError(this.result, this.errorCallback, this.callback)
-      : state = (callback == null) ? stateCatcherror : stateCatcherrorTest;
+      : state = (callback == null) ? stateCatchError : stateCatchErrorTest;
 
   _FutureListener.whenComplete(this.result, this.callback)
       : errorCallback = null,
-        state = stateWhencomplete;
+        state = stateWhenComplete;
 
   _Zone get _zone => result._zone;
 
   bool get handlesValue => (state & maskValue != 0);
   bool get handlesError => (state & maskError != 0);
-  bool get hasErrorTest => (state & maskType == stateCatcherrorTest);
-  bool get handlesComplete => (state & maskType == stateWhencomplete);
+  bool get hasErrorTest => (state & maskType == stateCatchErrorTest);
+  bool get handlesComplete => (state & maskType == stateWhenComplete);
   bool get isAwait => (state & stateIsAwait != 0);
 
   FutureOr<T> Function(S) get _onValue {
@@ -148,6 +149,8 @@
     return _onError != null;
   }
 
+  @pragma("vm:recognized", "other")
+  @pragma("vm:never-inline")
   FutureOr<T> handleValue(S sourceResult) {
     return _zone.runUnary<FutureOr<T>, S>(_onValue, sourceResult);
   }
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index 4f0873d..5400814 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -1608,6 +1608,7 @@
     return _rootRun(null, null, this, f);
   }
 
+  @pragma("vm:recognized", "other")
   R runUnary<R, T>(R f(T arg), T arg) {
     if (identical(Zone._current, _rootZone)) return f(arg);
     return _rootRunUnary(null, null, this, f, arg);
diff --git a/tools/VERSION b/tools/VERSION
index 9f61f00..e07d271 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 240
+PRERELEASE 241
 PRERELEASE_PATCH 0
\ No newline at end of file