[Test] Fix lazy-async nested stepping consistency, tests.

The debugger async function handling has been moved to allow handling
of stepping_fp_ and async_stepping_fp_.
Previously the presence of an async function would take precedence over
the *stepping_fp while stepping, resulting in nested asyncs to
incorrectly re-trigger the insertion of synthetic breakpoints.

This fix revealed three tests that were still testing for unintentional
inconsistencies between causal and lazy async.
Note that there are still tests that branch on `useCausalAsyncStacks`
though these all test for known differences - namely that lazy async
cannot traverse unawaited future calls.

Cq-Include-Trybots: luci.dart.try:app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-x64-try
Change-Id: I5f74db18086a90828024dbb461759869531d478f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164781
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Clement Skau <cskau@google.com>
diff --git a/runtime/observatory/tests/service/async_next_regession_18877_test.dart b/runtime/observatory/tests/service/async_next_regession_18877_test.dart
index d0843b5..8b56841 100644
--- a/runtime/observatory/tests/service/async_next_regession_18877_test.dart
+++ b/runtime/observatory/tests/service/async_next_regession_18877_test.dart
@@ -38,10 +38,12 @@
   hasStoppedAtBreakpoint,
   stoppedAtLine(LINE_A),
   stepOver, // foo()
+  stoppedAtLine(LINE_A),
   asyncNext,
   hasStoppedAtBreakpoint,
   stoppedAtLine(LINE_B),
   stepOver, // foo()
+  stoppedAtLine(LINE_B),
   asyncNext,
   hasStoppedAtBreakpoint,
   stoppedAtLine(LINE_C),
diff --git a/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions2_test.dart b/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions2_test.dart
index 6f98284..e922a19 100644
--- a/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions2_test.dart
+++ b/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions2_test.dart
@@ -44,20 +44,13 @@
     var stack = await isolate.getStack();
     expect(stack['asyncCausalFrames'], isNotNull);
     var asyncStack = stack['asyncCausalFrames'];
-    if (useCausalAsyncStacks) {
-      expect(asyncStack.length, greaterThanOrEqualTo(4));
-      expect(asyncStack[0].toString(), contains('doThrow'));
-      expect(asyncStack[1].toString(), contains('asyncThrower'));
-      expect(asyncStack[2].kind, equals(M.FrameKind.asyncSuspensionMarker));
-      expect(asyncStack[3].toString(), contains('testeeMain'));
-      expect(await asyncStack[3].location.toUserString(),
-          contains('.dart:$LINE_A'));
-    } else {
-      expect(asyncStack.length, greaterThanOrEqualTo(2));
-      expect(asyncStack[0].toString(), contains('doThrow'));
-      expect(asyncStack[1].toString(), contains('asyncThrower'));
-      // There was no await'er for "doThrow()".
-    }
+    expect(asyncStack.length, greaterThanOrEqualTo(4));
+    expect(asyncStack[0].toString(), contains('doThrow'));
+    expect(asyncStack[1].toString(), contains('asyncThrower'));
+    expect(asyncStack[2].kind, equals(M.FrameKind.asyncSuspensionMarker));
+    expect(asyncStack[3].toString(), contains('testeeMain'));
+    expect(
+        await asyncStack[3].location.toUserString(), contains('.dart:$LINE_A'));
   }
 ];
 
diff --git a/runtime/observatory/tests/service/positive_token_pos_test.dart b/runtime/observatory/tests/service/positive_token_pos_test.dart
index ee8dbad..b9c25a8 100644
--- a/runtime/observatory/tests/service/positive_token_pos_test.dart
+++ b/runtime/observatory/tests/service/positive_token_pos_test.dart
@@ -30,13 +30,8 @@
     // See issue #27128.
     var frame = stack['frames'][0];
     expect(frame.function.qualifiedName, equals('helper.async_op'));
-    if (useCausalAsyncStacks) {
-      expect(await frame.location.getLine(), equals(14));
-      expect(await frame.location.getColumn(), equals(1));
-    } else {
-      expect(await frame.location.getLine(), equals(12));
-      expect(await frame.location.getColumn(), equals(7));
-    }
+    expect(await frame.location.getLine(), equals(14));
+    expect(await frame.location.getColumn(), equals(1));
 
     frame = stack['frames'][1];
     expect(frame.function.name, equals('testMain'));
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 7f385cb..d9f462b 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -4470,37 +4470,6 @@
   ActivationFrame* frame = TopDartFrame();
   ASSERT(frame != NULL);
 
-  // Since lazy async stacks doesn't use the _asyncStackTraceHelper runtime
-  // entry, we need to manually set a synthetic breakpoint for async_op before
-  // we enter it.
-  if (FLAG_lazy_async_stacks) {
-    // async and async* functions always contain synthetic async_ops.
-    if ((frame->function().IsAsyncFunction() ||
-         frame->function().IsAsyncGenerator())) {
-      ASSERT(!frame->GetSavedCurrentContext().IsNull());
-      ASSERT(frame->GetSavedCurrentContext().num_variables() >
-             Context::kAsyncCompleterIndex);
-
-      const Object& jump_var = Object::Handle(
-          frame->GetSavedCurrentContext().At(Context::kAsyncCompleterIndex));
-
-      // Only set breakpoint when entering async_op the first time.
-      // :async_completer_var should be uninitialised at this point:
-      if (jump_var.IsNull()) {
-        const Function& async_op =
-            Function::Handle(frame->function().GetGeneratedClosure());
-        if (!async_op.IsNull()) {
-          SetBreakpointAtAsyncOp(async_op);
-          // After setting the breakpoint we stop stepping and continue the
-          // debugger until the next breakpoint, to step over all the
-          // synthetic code.
-          Continue();
-          return Error::null();
-        }
-      }
-    }
-  }
-
   if (FLAG_async_debugger) {
     if ((async_stepping_fp_ != 0) && (top_frame_awaiter_ != Object::null())) {
       // Check if the user has single stepped out of an async function with
@@ -4539,6 +4508,37 @@
     }
   }
 
+  // Since lazy async stacks doesn't use the _asyncStackTraceHelper runtime
+  // entry, we need to manually set a synthetic breakpoint for async_op before
+  // we enter it.
+  if (FLAG_lazy_async_stacks) {
+    // async and async* functions always contain synthetic async_ops.
+    if ((frame->function().IsAsyncFunction() ||
+         frame->function().IsAsyncGenerator())) {
+      ASSERT(!frame->GetSavedCurrentContext().IsNull());
+      ASSERT(frame->GetSavedCurrentContext().num_variables() >
+             Context::kAsyncCompleterIndex);
+
+      const Object& async_completer = Object::Handle(
+          frame->GetSavedCurrentContext().At(Context::kAsyncCompleterIndex));
+
+      // Only set breakpoint when entering async_op the first time.
+      // :async_completer_var should be uninitialised at this point:
+      if (async_completer.IsNull()) {
+        const Function& async_op =
+            Function::Handle(frame->function().GetGeneratedClosure());
+        if (!async_op.IsNull()) {
+          SetBreakpointAtAsyncOp(async_op);
+          // After setting the breakpoint we stop stepping and continue the
+          // debugger until the next breakpoint, to step over all the
+          // synthetic code.
+          Continue();
+          return Error::null();
+        }
+      }
+    }
+  }
+
   if (!frame->IsDebuggable()) {
     return Error::null();
   }