diff --git a/pkg/vm_service/test/get_stack_test.dart b/pkg/vm_service/test/get_stack_test.dart index 2cd0f93f458..5889996ef9d 100644 --- a/pkg/vm_service/test/get_stack_test.dart +++ b/pkg/vm_service/test/get_stack_test.dart @@ -52,12 +52,11 @@ final tests = [ // 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, isNull); + expect(result.asyncCausalFrames, hasLength(16)); expect(result.awaiterFrames, hasLength(16)); expectFrames(result.frames, [ @@ -74,6 +73,20 @@ final tests = [ [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')], @@ -88,10 +101,10 @@ final tests = [ [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 01331cdf9d1..3a90e4a62b0 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 'service_test_common.dart'; import 'test_helper.dart'; const LINE_C = 19; -const LINE_A = 25; -const LINE_B = 31; +const LINE_A = 24; +const LINE_B = 30; foobar() { debugger(); @@ -20,7 +20,6 @@ foobar() { } helper() async { - await 0; // Yield. The rest will run async. debugger(); print('helper'); // LINE_A. foobar(); @@ -37,7 +36,6 @@ var tests = [ (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, @@ -45,7 +43,7 @@ var tests = [ stoppedAtLine(LINE_A), (Isolate isolate) async { ServiceMap stack = await isolate.getStack(); - // Async function has yielded once, so it's now running async. + // Has causal frames (we are inside an async function) 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 9b605cb96da..4d3e4486590 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 @@ var tests = [ (Isolate isolate) async { ServiceMap stack = await isolate.getStack(); // No causal frames because we are in a completely synchronous stack. - expect(stack['asyncCausalFrames'], isNull); + expect(stack['asyncCausalFrames'], isNotNull); }, 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 cd9ef6ad386..f52f4a1fbd2 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 'service_test_common.dart'; import 'test_helper.dart'; const LINE_C = 19; -const LINE_A = 25; -const LINE_B = 31; +const LINE_A = 24; +const LINE_B = 30; foobar() { debugger(); @@ -20,7 +20,6 @@ foobar() { } 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 8acf40d5e74..7fb385ae89f 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 @@ var tests = [ (Isolate isolate) async { ServiceMap stack = await isolate.getStack(); // No causal frames because we are in a completely synchronous stack. - expect(stack['asyncCausalFrames'], isNull); + expect(stack['asyncCausalFrames'], isNotNull); }, resumeIsolate, hasStoppedAtBreakpoint, diff --git a/runtime/tests/vm/dart/causal_stacks/utils.dart b/runtime/tests/vm/dart/causal_stacks/utils.dart index 8b75f98bd54..73ffe1d5a60 100644 --- a/runtime/tests/vm/dart/causal_stacks/utils.dart +++ b/runtime/tests/vm/dart/causal_stacks/utils.dart @@ -178,22 +178,12 @@ Future futureSyncWhenComplete() { 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'^(?:#(?\d+)|)'); -Future assertStack(List expects, StackTrace stackTrace, +void assertStack(List expects, StackTrace stackTrace, [String? debugInfoFilename]) async { final original = await Stream.value(stackTrace.toString()) .transform(const LineSplitter()) @@ -263,7 +253,7 @@ Future doTestAwait(Future f(), List expectedStack, await f(); Expect.fail('No exception thrown!'); } on String catch (e, s) { - return assertStack(expectedStack, s, debugInfoFilename); + assertStack(expectedStack, s, debugInfoFilename); } } @@ -277,7 +267,7 @@ Future doTestAwaitThen(Future f(), List expectedStack, await f().then((e) => Expect.fail('No exception thrown!')); Expect.fail('No exception thrown!'); } on String catch (e, s) { - return assertStack(expectedStack, s, debugInfoFilename); + assertStack(expectedStack, s, debugInfoFilename); } } @@ -288,7 +278,7 @@ Future doTestAwaitCatchError(Future f(), List expectedStack, await f().catchError((e, s) { stackTrace = s; }); - return assertStack(expectedStack, stackTrace, debugInfoFilename); + assertStack(expectedStack, stackTrace, debugInfoFilename); } // ---- @@ -337,32 +327,39 @@ Future doTestsNoCausalNoLazy([String? debugInfoFilename]) async { r'^#13 Future._propagateToListeners ', r'^#14 Future._completeWithValue ', r'^#15 _completeOnAsyncReturn ', - r'^#16 assertStack ', + r'^#16 doTestAwaitCatchError ', 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. ', - 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. ', - r'^#38 _microtaskLoop ', - r'^#39 _startMicrotaskLoop ', - r'^#40 _runPendingImmediateCallback ', - r'^#41 _RawReceivePortImpl._handleMessage ', + 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. ', + r'^#45 _microtaskLoop ', + r'^#46 _startMicrotaskLoop ', + r'^#47 _runPendingImmediateCallback ', + r'^#48 _RawReceivePortImpl._handleMessage ', ], debugInfoFilename); await doTestAwaitThen( @@ -378,32 +375,34 @@ Future doTestsNoCausalNoLazy([String? debugInfoFilename]) async { r'^#13 Future._propagateToListeners ', r'^#14 Future._completeWithValue ', r'^#15 _completeOnAsyncReturn ', - 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. ', - 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. ', - r'^#38 _microtaskLoop ', - r'^#39 _startMicrotaskLoop ', - r'^#40 _runPendingImmediateCallback ', - r'^#41 _RawReceivePortImpl._handleMessage ', + 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. ', + r'^#40 _microtaskLoop ', + r'^#41 _startMicrotaskLoop ', + r'^#42 _runPendingImmediateCallback ', + r'^#43 _RawReceivePortImpl._handleMessage ', ], debugInfoFilename); await doTestAwaitCatchError( @@ -419,32 +418,34 @@ Future doTestsNoCausalNoLazy([String? debugInfoFilename]) async { r'^#13 Future._propagateToListeners ', r'^#14 Future._completeWithValue ', r'^#15 _completeOnAsyncReturn ', - 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. ', - 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. ', - r'^#38 _microtaskLoop ', - r'^#39 _startMicrotaskLoop ', - r'^#40 _runPendingImmediateCallback ', - r'^#41 _RawReceivePortImpl._handleMessage ', + 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. ', + r'^#40 _microtaskLoop ', + r'^#41 _startMicrotaskLoop ', + r'^#42 _runPendingImmediateCallback ', + r'^#43 _RawReceivePortImpl._handleMessage ', ], debugInfoFilename); @@ -641,497 +642,329 @@ Future doTestsNoCausalNoLazy([String? debugInfoFilename]) async { await doTestAwaitCatchError( futureSyncWhenComplete, expected, debugInfoFilename); } - - { - final expected = const [ - r'^#0 throwSync \(.*/utils.dart:16(:3)?\)$', - r'^#1 futureThen. \(.*/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. ', - 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 doTestsLazy([String? debugInfoFilename]) async { - // allYield - { - final allYieldExpected = const [ - r'^#0 throwSync \(.*/utils.dart:16(:3)?\)$', - r'^#1 allYield3 \(.*/utils.dart:39(:3)?\)$', - r'^$', - r'^#2 allYield2 \(.*/utils.dart:34(:3)?\)$', - r'^$', - r'^#3 allYield \(.*/utils.dart:29(:3)?\)$', - r'^$', - ]; - await doTestAwait( - allYield, - allYieldExpected + - const [ - r'^#4 doTestAwait ', - r'^$', - r'^#5 doTestsLazy ', - r'^$', - r'^#6 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - allYield, - allYieldExpected + - const [ - r'^#4 doTestAwaitThen ', - r'^$', - r'^#5 doTestsLazy ', - r'^$', - r'^#6 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - allYield, - allYieldExpected + - const [ - r'^#4 doTestAwaitCatchError ', - r'^$', - r'^#5 doTestsLazy ', - r'^$', - r'^#6 main ', - r'^$', - ], - debugInfoFilename); - } + final allYieldExpected = const [ + r'^#0 throwSync \(.*/utils.dart:16(:3)?\)$', + r'^#1 allYield3 \(.*/utils.dart:39(:3)?\)$', + r'^$', + r'^#2 allYield2 \(.*/utils.dart:34(:3)?\)$', + r'^$', + r'^#3 allYield \(.*/utils.dart:29(:3)?\)$', + r'^$', + ]; + await doTestAwait( + allYield, + allYieldExpected + + const [ + r'^#4 doTestAwait ', + r'^$', + r'^#5 doTestsLazy ', + r'^$', + r'^#6 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + allYield, + allYieldExpected + + const [ + r'^#4 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError(allYield, allYieldExpected, debugInfoFilename); - // noYields - { - final noYieldsExpected = const [ - 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 [ - r'^#4 doTestAwait ', - r'^#5 doTestsLazy ', - r'^$', - r'^#6 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - noYields, - noYieldsExpected + - const [ - r'^#4 doTestAwaitThen ', - r'^#5 doTestsLazy ', - r'^$', - r'^#6 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - noYields, - noYieldsExpected + - const [ - r'^#4 doTestAwaitCatchError ', - r'^#5 doTestsLazy ', - r'^$', - r'^#6 main ', - r'^$', - ], - debugInfoFilename); - } + final noYieldsExpected = const [ + 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 [ + r'^#4 doTestAwait ', + r'^#5 doTestsLazy ', + r'^$', + r'^#6 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + noYields, + noYieldsExpected + + const [ + r'^#4 doTestAwaitThen ', + r'^#5 doTestsLazy ', + r'^$', + r'^#6 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError( + noYields, + noYieldsExpected + + const [ + r'^#4 doTestAwaitCatchError ', + r'^#5 doTestsLazy ', + r'^$', + r'^#6 main ', + r'^$', + ], + debugInfoFilename); - // mixedYields - { - final mixedYieldsExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 mixedYields2 \(.*/utils.dart:66(:3)?\)$', - r'^$', - r'^#2 mixedYields \(.*/utils.dart:61(:3)?\)$', - r'^$', - ]; - await doTestAwait( - mixedYields, - mixedYieldsExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - mixedYields, - mixedYieldsExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - mixedYields, - mixedYieldsExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final mixedYieldsExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 mixedYields2 \(.*/utils.dart:66(:3)?\)$', + r'^$', + r'^#2 mixedYields \(.*/utils.dart:61(:3)?\)$', + r'^$', + ]; + await doTestAwait( + mixedYields, + mixedYieldsExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + mixedYields, + mixedYieldsExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError( + mixedYields, mixedYieldsExpected, debugInfoFilename); - // syncSuffix - { - final syncSuffixExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 syncSuffix2 \(.*/utils.dart:82(:3)?\)$', - r'^$', - r'^#2 syncSuffix \(.*/utils.dart:77(:3)?\)$', - r'^$', - ]; - await doTestAwait( - syncSuffix, - syncSuffixExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - syncSuffix, - syncSuffixExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - syncSuffix, - syncSuffixExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final syncSuffixExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 syncSuffix2 \(.*/utils.dart:82(:3)?\)$', + r'^$', + r'^#2 syncSuffix \(.*/utils.dart:77(:3)?\)$', + r'^$', + ]; + await doTestAwait( + syncSuffix, + syncSuffixExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + syncSuffix, + syncSuffixExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError( + syncSuffix, syncSuffixExpected, debugInfoFilename); - // nonAsyncNoStack - { - final nonAsyncNoStackExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 nonAsyncNoStack1 \(.*/utils.dart:95(:36)?\)$', - r'^$', - r'^#2 nonAsyncNoStack \(.*/utils.dart:93(:35)?\)$', - r'^$', - ]; - await doTestAwait( - nonAsyncNoStack, - nonAsyncNoStackExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - nonAsyncNoStack, - nonAsyncNoStackExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - nonAsyncNoStack, - nonAsyncNoStackExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final nonAsyncNoStackExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 nonAsyncNoStack1 \(.*/utils.dart:95(:36)?\)$', + r'^$', + r'^#2 nonAsyncNoStack \(.*/utils.dart:93(:35)?\)$', + r'^$', + ]; + await doTestAwait( + nonAsyncNoStack, + nonAsyncNoStackExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + nonAsyncNoStack, + nonAsyncNoStackExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError( + nonAsyncNoStack, nonAsyncNoStackExpected, debugInfoFilename); - // awaitEveryAsyncStarThrowSync - { - final asyncStarThrowSyncExpected = const [ - r'^#0 throwSync \(.+/utils.dart:16(:3)?\)$', - r'^#1 asyncStarThrowSync \(.+/utils.dart:112(:11)?\)$', - r'^$', - r'^#2 awaitEveryAsyncStarThrowSync \(.+/utils.dart:104(:3)?\)$', - r'^$', - ]; - await doTestAwait( - awaitEveryAsyncStarThrowSync, - asyncStarThrowSyncExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - awaitEveryAsyncStarThrowSync, - asyncStarThrowSyncExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - awaitEveryAsyncStarThrowSync, - asyncStarThrowSyncExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final asyncStarThrowSyncExpected = const [ + r'^#0 throwSync \(.+/utils.dart:16(:3)?\)$', + r'^#1 asyncStarThrowSync \(.+/utils.dart:112(:11)?\)$', + r'^$', + r'^#2 awaitEveryAsyncStarThrowSync \(.+/utils.dart:104(:3)?\)$', + r'^$', + ]; + await doTestAwait( + awaitEveryAsyncStarThrowSync, + asyncStarThrowSyncExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + awaitEveryAsyncStarThrowSync, + asyncStarThrowSyncExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError(awaitEveryAsyncStarThrowSync, + asyncStarThrowSyncExpected, debugInfoFilename); - // awaitEveryAsyncStarThrowAsync - { - final asyncStarThrowAsyncExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$', - r'^$', - r'^#2 awaitEveryAsyncStarThrowAsync \(.+/utils.dart:117(:3)?\)$', - r'^$', - ]; - await doTestAwait( - awaitEveryAsyncStarThrowAsync, - asyncStarThrowAsyncExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - awaitEveryAsyncStarThrowAsync, - asyncStarThrowAsyncExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - awaitEveryAsyncStarThrowAsync, - asyncStarThrowAsyncExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final asyncStarThrowAsyncExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$', + r'^$', + r'^#2 awaitEveryAsyncStarThrowAsync \(.+/utils.dart:117(:3)?\)$', + r'^$', + ]; + await doTestAwait( + awaitEveryAsyncStarThrowAsync, + asyncStarThrowAsyncExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + awaitEveryAsyncStarThrowAsync, + asyncStarThrowAsyncExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError(awaitEveryAsyncStarThrowAsync, + asyncStarThrowAsyncExpected, debugInfoFilename); - // listenAsyncStarThrowAsync - { - final listenAsyncStartExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$', - r'^$', - r'^#2 listenAsyncStarThrowAsync. \(.+/utils.dart(:0)?\)$', - r'^$', - ]; - await doTestAwait( - listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename); - await doTestAwaitThen( - listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename); - await doTestAwaitCatchError( - listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename); - } + final listenAsyncStartExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$', + r'^$', + r'^#2 listenAsyncStarThrowAsync. \(.+/utils.dart(:0)?\)$', + r'^$', + ]; + await doTestAwait( + listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename); + await doTestAwaitThen( + listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename); + await doTestAwaitCatchError( + listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename); - // customErrorZone - { - final customErrorZoneExpected = const [ - r'#0 throwSync \(.*/utils.dart:16(:3)?\)$', - r'#1 allYield3 \(.*/utils.dart:39(:3)?\)$', - r'$', - r'#2 allYield2 \(.*/utils.dart:34(:3)?\)$', - r'$', - r'#3 allYield \(.*/utils.dart:29(:3)?\)$', - r'$', - r'#4 customErrorZone. \(.*/utils.dart:144(:5)?\)$', - r'$', - ]; - await doTestAwait( - customErrorZone, customErrorZoneExpected, debugInfoFilename); - await doTestAwaitThen( - customErrorZone, customErrorZoneExpected, debugInfoFilename); - await doTestAwaitCatchError( - customErrorZone, customErrorZoneExpected, debugInfoFilename); - } + final customErrorZoneExpected = const [ + r'#0 throwSync \(.*/utils.dart:16(:3)?\)$', + r'#1 allYield3 \(.*/utils.dart:39(:3)?\)$', + r'$', + r'#2 allYield2 \(.*/utils.dart:34(:3)?\)$', + r'$', + r'#3 allYield \(.*/utils.dart:29(:3)?\)$', + r'$', + r'#4 customErrorZone. \(.*/utils.dart:144(:5)?\)$', + r'$', + ]; + await doTestAwait( + customErrorZone, customErrorZoneExpected, debugInfoFilename); + await doTestAwaitThen( + customErrorZone, customErrorZoneExpected, debugInfoFilename); + await doTestAwaitCatchError( + customErrorZone, customErrorZoneExpected, debugInfoFilename); - // awaitTimeout - { - final awaitTimeoutExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 Future.timeout. \(dart:async/future_impl.dart', - r'^$', - r'^#2 awaitTimeout ', - r'^$', - ]; - await doTestAwait( - awaitTimeout, - awaitTimeoutExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - awaitTimeout, - awaitTimeoutExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - awaitTimeout, - awaitTimeoutExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final awaitTimeoutExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 Future.timeout. \(dart:async/future_impl.dart', + r'^$', + r'^#2 awaitTimeout ', + r'^$', + ]; + await doTestAwait( + awaitTimeout, + awaitTimeoutExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + awaitTimeout, + awaitTimeoutExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError( + awaitTimeout, awaitTimeoutExpected, debugInfoFilename); - // awaitWait - { - final awaitWaitExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 Future.wait. \(dart:async/future.dart', - r'^$', - r'^#2 awaitWait ', - r'^$', - ]; - await doTestAwait( - awaitWait, - awaitWaitExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - awaitWait, - awaitWaitExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - awaitWait, - awaitWaitExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final awaitWaitExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 Future.wait. \(dart:async/future.dart', + r'^$', + r'^#2 awaitWait ', + r'^$', + ]; + await doTestAwait( + awaitWait, + awaitWaitExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + awaitWait, + awaitWaitExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError(awaitWait, awaitWaitExpected, debugInfoFilename); - // futureSyncWhenComplete { final expected = const [ r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', @@ -1153,70 +986,11 @@ Future doTestsLazy([String? debugInfoFilename]) async { futureSyncWhenComplete, expected + const [ - r'^#1 doTestAwaitThen ', - r'^$', - r'^#2 doTestsLazy ', - r'^$', - r'^#3 main ', + r'^#1 doTestAwaitThen. ', r'^$', ], debugInfoFilename); await doTestAwaitCatchError( - futureSyncWhenComplete, - expected + - const [ - r'^#1 doTestAwaitCatchError ', - r'^$', - r'^#2 doTestsLazy ', - r'^$', - r'^#3 main ', - r'^$', - ], - debugInfoFilename); - } - - // futureThen - { - final expected = const [ - r'^#0 throwSync \(.*/utils.dart:16(:3)?\)$', - r'^#1 futureThen. ', - r'^$', - ]; - await doTestAwait( - futureThen, - expected + - const [ - r'^#2 doTestAwait ', - r'^$', - r'^#3 doTestsLazy ', - r'^$', - r'^#4 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - futureThen, - expected + - const [ - r'^#2 doTestAwaitThen ', - r'^$', - r'^#3 doTestsLazy ', - r'^$', - r'^#4 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - futureThen, - expected + - const [ - r'^#2 doTestAwaitCatchError ', - r'^$', - r'^#3 doTestsLazy ', - r'^$', - r'^#4 main ', - r'^$', - ], - debugInfoFilename); + futureSyncWhenComplete, expected, debugInfoFilename); } } diff --git a/runtime/tests/vm/dart_2/causal_stacks/utils.dart b/runtime/tests/vm/dart_2/causal_stacks/utils.dart index b7c4e022158..192984fe79e 100644 --- a/runtime/tests/vm/dart_2/causal_stacks/utils.dart +++ b/runtime/tests/vm/dart_2/causal_stacks/utils.dart @@ -178,22 +178,12 @@ Future futureSyncWhenComplete() { 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'^(?:#(?\d+)|)'); -Future assertStack(List expects, StackTrace stackTrace, +void assertStack(List expects, StackTrace stackTrace, [String debugInfoFilename]) async { final original = await Stream.value(stackTrace.toString()) .transform(const LineSplitter()) @@ -263,7 +253,7 @@ Future doTestAwait(Future f(), List expectedStack, await f(); Expect.fail('No exception thrown!'); } on String catch (e, s) { - return assertStack(expectedStack, s, debugInfoFilename); + assertStack(expectedStack, s, debugInfoFilename); } } @@ -277,7 +267,7 @@ Future doTestAwaitThen(Future f(), List expectedStack, await f().then((e) => Expect.fail('No exception thrown!')); Expect.fail('No exception thrown!'); } on String catch (e, s) { - return assertStack(expectedStack, s, debugInfoFilename); + assertStack(expectedStack, s, debugInfoFilename); } } @@ -288,7 +278,7 @@ Future doTestAwaitCatchError(Future f(), List expectedStack, await f().catchError((e, s) { stackTrace = s; }); - return assertStack(expectedStack, stackTrace, debugInfoFilename); + assertStack(expectedStack, stackTrace, debugInfoFilename); } // ---- @@ -337,32 +327,39 @@ Future doTestsNoCausalNoLazy([String debugInfoFilename]) async { r'^#13 Future._propagateToListeners ', r'^#14 Future._completeWithValue ', r'^#15 _completeOnAsyncReturn ', - r'^#16 assertStack ', + r'^#16 doTestAwaitCatchError ', 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. ', - 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. ', - r'^#38 _microtaskLoop ', - r'^#39 _startMicrotaskLoop ', - r'^#40 _runPendingImmediateCallback ', - r'^#41 _RawReceivePortImpl._handleMessage ', + 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. ', + r'^#45 _microtaskLoop ', + r'^#46 _startMicrotaskLoop ', + r'^#47 _runPendingImmediateCallback ', + r'^#48 _RawReceivePortImpl._handleMessage ', ], debugInfoFilename); await doTestAwaitThen( @@ -378,32 +375,34 @@ Future doTestsNoCausalNoLazy([String debugInfoFilename]) async { r'^#13 Future._propagateToListeners ', r'^#14 Future._completeWithValue ', r'^#15 _completeOnAsyncReturn ', - 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. ', - 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. ', - r'^#38 _microtaskLoop ', - r'^#39 _startMicrotaskLoop ', - r'^#40 _runPendingImmediateCallback ', - r'^#41 _RawReceivePortImpl._handleMessage ', + 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. ', + r'^#40 _microtaskLoop ', + r'^#41 _startMicrotaskLoop ', + r'^#42 _runPendingImmediateCallback ', + r'^#43 _RawReceivePortImpl._handleMessage ', ], debugInfoFilename); await doTestAwaitCatchError( @@ -419,32 +418,34 @@ Future doTestsNoCausalNoLazy([String debugInfoFilename]) async { r'^#13 Future._propagateToListeners ', r'^#14 Future._completeWithValue ', r'^#15 _completeOnAsyncReturn ', - 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. ', - 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. ', - r'^#38 _microtaskLoop ', - r'^#39 _startMicrotaskLoop ', - r'^#40 _runPendingImmediateCallback ', - r'^#41 _RawReceivePortImpl._handleMessage ', + 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. ', + r'^#40 _microtaskLoop ', + r'^#41 _startMicrotaskLoop ', + r'^#42 _runPendingImmediateCallback ', + r'^#43 _RawReceivePortImpl._handleMessage ', ], debugInfoFilename); @@ -641,505 +642,337 @@ Future doTestsNoCausalNoLazy([String debugInfoFilename]) async { await doTestAwaitCatchError( futureSyncWhenComplete, expected, debugInfoFilename); } - - { - final expected = const [ - r'^#0 throwSync \(.*/utils.dart:16(:3)?\)$', - r'^#1 futureThen. \(.*/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. ', - 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 doTestsLazy([String debugInfoFilename]) async { - // allYield - { - final allYieldExpected = const [ - r'^#0 throwSync \(.*/utils.dart:16(:3)?\)$', - r'^#1 allYield3 \(.*/utils.dart:39(:3)?\)$', - r'^$', - r'^#2 allYield2 \(.*/utils.dart:34(:3)?\)$', - r'^$', - r'^#3 allYield \(.*/utils.dart:29(:3)?\)$', - r'^$', - ]; - await doTestAwait( - allYield, - allYieldExpected + - const [ - r'^#4 doTestAwait ', - r'^$', - r'^#5 doTestsLazy ', - r'^$', - r'^#6 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - allYield, - allYieldExpected + - const [ - r'^#4 doTestAwaitThen ', - r'^$', - r'^#5 doTestsLazy ', - r'^$', - r'^#6 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - allYield, - allYieldExpected + - const [ - r'^#4 doTestAwaitCatchError ', - r'^$', - r'^#5 doTestsLazy ', - r'^$', - r'^#6 main ', - r'^$', - ], - debugInfoFilename); - } + final allYieldExpected = const [ + r'^#0 throwSync \(.*/utils.dart:16(:3)?\)$', + r'^#1 allYield3 \(.*/utils.dart:39(:3)?\)$', + r'^$', + r'^#2 allYield2 \(.*/utils.dart:34(:3)?\)$', + r'^$', + r'^#3 allYield \(.*/utils.dart:29(:3)?\)$', + r'^$', + ]; + await doTestAwait( + allYield, + allYieldExpected + + const [ + r'^#4 doTestAwait ', + r'^$', + r'^#5 doTestsLazy ', + r'^$', + r'^#6 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + allYield, + allYieldExpected + + const [ + r'^#4 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError(allYield, allYieldExpected, debugInfoFilename); - // noYields - { - final noYieldsExpected = const [ - 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 [ - r'^#4 doTestAwait ', - r'^#5 doTestsLazy ', - r'^$', - r'^#6 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - noYields, - noYieldsExpected + - const [ - r'^#4 doTestAwaitThen ', - r'^#5 doTestsLazy ', - r'^$', - r'^#6 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - noYields, - noYieldsExpected + - const [ - r'^#4 doTestAwaitCatchError ', - r'^#5 doTestsLazy ', - r'^$', - r'^#6 main ', - r'^$', - ], - debugInfoFilename); - } + final noYieldsExpected = const [ + 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 [ + r'^#4 doTestAwait ', + r'^#5 doTestsLazy ', + r'^$', + r'^#6 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + noYields, + noYieldsExpected + + const [ + r'^#4 doTestAwaitThen ', + r'^#5 doTestsLazy ', + r'^$', + r'^#6 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError( + noYields, + noYieldsExpected + + const [ + r'^#4 doTestAwaitCatchError ', + r'^#5 doTestsLazy ', + r'^$', + r'^#6 main ', + r'^$', + ], + debugInfoFilename); - // mixedYields - { - final mixedYieldsExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 mixedYields2 \(.*/utils.dart:66(:3)?\)$', - r'^$', - r'^#2 mixedYields \(.*/utils.dart:61(:3)?\)$', - r'^$', - ]; - await doTestAwait( - mixedYields, - mixedYieldsExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - mixedYields, - mixedYieldsExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - mixedYields, - mixedYieldsExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final mixedYieldsExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 mixedYields2 \(.*/utils.dart:66(:3)?\)$', + r'^$', + r'^#2 mixedYields \(.*/utils.dart:61(:3)?\)$', + r'^$', + ]; + await doTestAwait( + mixedYields, + mixedYieldsExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + mixedYields, + mixedYieldsExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError( + mixedYields, mixedYieldsExpected, debugInfoFilename); - // syncSuffix - { - final syncSuffixExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 syncSuffix2 \(.*/utils.dart:82(:3)?\)$', - r'^$', - r'^#2 syncSuffix \(.*/utils.dart:77(:3)?\)$', - r'^$', - ]; - await doTestAwait( - syncSuffix, - syncSuffixExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - syncSuffix, - syncSuffixExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - syncSuffix, - syncSuffixExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final syncSuffixExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 syncSuffix2 \(.*/utils.dart:82(:3)?\)$', + r'^$', + r'^#2 syncSuffix \(.*/utils.dart:77(:3)?\)$', + r'^$', + ]; + await doTestAwait( + syncSuffix, + syncSuffixExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + syncSuffix, + syncSuffixExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError( + syncSuffix, syncSuffixExpected, debugInfoFilename); - // nonAsyncNoStack - { - final nonAsyncNoStackExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 nonAsyncNoStack1 \(.*/utils.dart:95(:36)?\)$', - r'^$', - r'^#2 nonAsyncNoStack \(.*/utils.dart:93(:35)?\)$', - r'^$', - ]; - await doTestAwait( - nonAsyncNoStack, - nonAsyncNoStackExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - nonAsyncNoStack, - nonAsyncNoStackExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - nonAsyncNoStack, - nonAsyncNoStackExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final nonAsyncNoStackExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 nonAsyncNoStack1 \(.*/utils.dart:95(:36)?\)$', + r'^$', + r'^#2 nonAsyncNoStack \(.*/utils.dart:93(:35)?\)$', + r'^$', + ]; + await doTestAwait( + nonAsyncNoStack, + nonAsyncNoStackExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + nonAsyncNoStack, + nonAsyncNoStackExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError( + nonAsyncNoStack, nonAsyncNoStackExpected, debugInfoFilename); - // awaitEveryAsyncStarThrowSync - { - final asyncStarThrowSyncExpected = const [ - r'^#0 throwSync \(.+/utils.dart:16(:3)?\)$', - r'^#1 asyncStarThrowSync \(.+/utils.dart:112(:11)?\)$', - r'^$', - r'^#2 awaitEveryAsyncStarThrowSync \(.+/utils.dart:104(:3)?\)$', - r'^$', - ]; - await doTestAwait( - awaitEveryAsyncStarThrowSync, - asyncStarThrowSyncExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - awaitEveryAsyncStarThrowSync, - asyncStarThrowSyncExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - awaitEveryAsyncStarThrowSync, - asyncStarThrowSyncExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final asyncStarThrowSyncExpected = const [ + r'^#0 throwSync \(.+/utils.dart:16(:3)?\)$', + r'^#1 asyncStarThrowSync \(.+/utils.dart:112(:11)?\)$', + r'^$', + r'^#2 awaitEveryAsyncStarThrowSync \(.+/utils.dart:104(:3)?\)$', + r'^$', + ]; + await doTestAwait( + awaitEveryAsyncStarThrowSync, + asyncStarThrowSyncExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + awaitEveryAsyncStarThrowSync, + asyncStarThrowSyncExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError(awaitEveryAsyncStarThrowSync, + asyncStarThrowSyncExpected, debugInfoFilename); - // awaitEveryAsyncStarThrowAsync - { - final asyncStarThrowAsyncExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$', - r'^$', - r'^#2 awaitEveryAsyncStarThrowAsync \(.+/utils.dart:117(:3)?\)$', - r'^$', - ]; - await doTestAwait( - awaitEveryAsyncStarThrowAsync, - asyncStarThrowAsyncExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - awaitEveryAsyncStarThrowAsync, - asyncStarThrowAsyncExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - awaitEveryAsyncStarThrowAsync, - asyncStarThrowAsyncExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final asyncStarThrowAsyncExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$', + r'^$', + r'^#2 awaitEveryAsyncStarThrowAsync \(.+/utils.dart:117(:3)?\)$', + r'^$', + ]; + await doTestAwait( + awaitEveryAsyncStarThrowAsync, + asyncStarThrowAsyncExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + awaitEveryAsyncStarThrowAsync, + asyncStarThrowAsyncExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError(awaitEveryAsyncStarThrowAsync, + asyncStarThrowAsyncExpected, debugInfoFilename); - // listenAsyncStarThrowAsync - { - final listenAsyncStartExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$', - r'^$', - r'^#2 listenAsyncStarThrowAsync. \(.+/utils.dart(:0)?\)$', - r'^$', - ]; - await doTestAwait( - listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename); - await doTestAwaitThen( - listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename); - await doTestAwaitCatchError( - listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename); - } + final listenAsyncStartExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$', + r'^$', + r'^#2 listenAsyncStarThrowAsync. \(.+/utils.dart(:0)?\)$', + r'^$', + ]; + await doTestAwait( + listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename); + await doTestAwaitThen( + listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename); + await doTestAwaitCatchError( + listenAsyncStarThrowAsync, listenAsyncStartExpected, debugInfoFilename); - // customErrorZone - { - final customErrorZoneExpected = const [ - r'#0 throwSync \(.*/utils.dart:16(:3)?\)$', - r'#1 allYield3 \(.*/utils.dart:39(:3)?\)$', - r'$', - r'#2 allYield2 \(.*/utils.dart:34(:3)?\)$', - r'$', - r'#3 allYield \(.*/utils.dart:29(:3)?\)$', - r'$', - r'#4 customErrorZone. \(.*/utils.dart:144(:5)?\)$', - r'$', - ]; - await doTestAwait( - customErrorZone, customErrorZoneExpected, debugInfoFilename); - await doTestAwaitThen( - customErrorZone, customErrorZoneExpected, debugInfoFilename); - await doTestAwaitCatchError( - customErrorZone, customErrorZoneExpected, debugInfoFilename); - } + final customErrorZoneExpected = const [ + r'#0 throwSync \(.*/utils.dart:16(:3)?\)$', + r'#1 allYield3 \(.*/utils.dart:39(:3)?\)$', + r'$', + r'#2 allYield2 \(.*/utils.dart:34(:3)?\)$', + r'$', + r'#3 allYield \(.*/utils.dart:29(:3)?\)$', + r'$', + r'#4 customErrorZone. \(.*/utils.dart:144(:5)?\)$', + r'$', + ]; + await doTestAwait( + customErrorZone, customErrorZoneExpected, debugInfoFilename); + await doTestAwaitThen( + customErrorZone, customErrorZoneExpected, debugInfoFilename); + await doTestAwaitCatchError( + customErrorZone, customErrorZoneExpected, debugInfoFilename); - // awaitTimeout - { - final awaitTimeoutExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 Future.timeout. \(dart:async/future_impl.dart', - r'^$', - r'^#2 awaitTimeout ', - r'^$', - ]; - await doTestAwait( - awaitTimeout, - awaitTimeoutExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - awaitTimeout, - awaitTimeoutExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - awaitTimeout, - awaitTimeoutExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final awaitTimeoutExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 Future.timeout. \(dart:async/future_impl.dart', + r'^$', + r'^#2 awaitTimeout ', + r'^$', + ]; + await doTestAwait( + awaitTimeout, + awaitTimeoutExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + awaitTimeout, + awaitTimeoutExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError( + awaitTimeout, awaitTimeoutExpected, debugInfoFilename); - // awaitWait - { - final awaitWaitExpected = const [ - r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', - r'^$', - r'^#1 Future.wait. \(dart:async/future.dart', - r'^$', - r'^#2 awaitWait ', - r'^$', - ]; - await doTestAwait( - awaitWait, - awaitWaitExpected + - const [ - r'^#3 doTestAwait ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - awaitWait, - awaitWaitExpected + - const [ - r'^#3 doTestAwaitThen ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - awaitWait, - awaitWaitExpected + - const [ - r'^#3 doTestAwaitCatchError ', - r'^$', - r'^#4 doTestsLazy ', - r'^$', - r'^#5 main ', - r'^$', - ], - debugInfoFilename); - } + final awaitWaitExpected = const [ + r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', + r'^$', + r'^#1 Future.wait. \(dart:async/future.dart', + r'^$', + r'^#2 awaitWait ', + r'^$', + ]; + await doTestAwait( + awaitWait, + awaitWaitExpected + + const [ + r'^#3 doTestAwait ', + r'^$', + r'^#4 doTestsLazy ', + r'^$', + r'^#5 main ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitThen( + awaitWait, + awaitWaitExpected + + const [ + r'^#3 doTestAwaitThen. ', + r'^$', + ], + debugInfoFilename); + await doTestAwaitCatchError(awaitWait, awaitWaitExpected, debugInfoFilename); - // futureSyncWhenComplete { - final expected = const [ + final expect = const [ r'^#0 throwAsync \(.*/utils.dart:21(:3)?\)$', r'^$', ]; await doTestAwait( futureSyncWhenComplete, - expected + + expect + const [ r'^#1 doTestAwait ', r'^$', @@ -1151,72 +984,13 @@ Future doTestsLazy([String debugInfoFilename]) async { debugInfoFilename); await doTestAwaitThen( futureSyncWhenComplete, - expected + + expect + const [ - r'^#1 doTestAwaitThen ', - r'^$', - r'^#2 doTestsLazy ', - r'^$', - r'^#3 main ', + r'^#1 doTestAwaitThen. ', r'^$', ], debugInfoFilename); await doTestAwaitCatchError( - futureSyncWhenComplete, - expected + - const [ - r'^#1 doTestAwaitCatchError ', - r'^$', - r'^#2 doTestsLazy ', - r'^$', - r'^#3 main ', - r'^$', - ], - debugInfoFilename); - } - - // futureThen - { - final expected = const [ - r'^#0 throwSync \(.*/utils.dart:16(:3)?\)$', - r'^#1 futureThen. ', - r'^$', - ]; - await doTestAwait( - futureThen, - expected + - const [ - r'^#2 doTestAwait ', - r'^$', - r'^#3 doTestsLazy ', - r'^$', - r'^#4 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitThen( - futureThen, - expected + - const [ - r'^#2 doTestAwaitThen ', - r'^$', - r'^#3 doTestsLazy ', - r'^$', - r'^#4 main ', - r'^$', - ], - debugInfoFilename); - await doTestAwaitCatchError( - futureThen, - expected + - const [ - r'^#2 doTestAwaitCatchError ', - r'^$', - r'^#3 doTestsLazy ', - r'^$', - r'^#4 main ', - r'^$', - ], - debugInfoFilename); + futureSyncWhenComplete, expect, debugInfoFilename); } } diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h index 682200177f9..185af0ac35c 100644 --- a/runtime/vm/compiler/recognized_methods_list.h +++ b/runtime/vm/compiler/recognized_methods_list.h @@ -196,8 +196,6 @@ namespace dart { 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 8cdee6a8e48..ce152a57285 100644 --- a/runtime/vm/debugger.cc +++ b/runtime/vm/debugger.cc @@ -1848,7 +1848,7 @@ DebuggerStackTrace* Debugger::CollectAsyncLazyStackTrace() { /*skip_frames=*/0, &on_sync_frame, &has_async); - // If the entire stack is sync, return no (async) trace. + // If the entire stack is sync, return no trace. if (!has_async) { return nullptr; } diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc index 74a901e7641..0f3c3ed163d 100644 --- a/runtime/vm/stack_frame.cc +++ b/runtime/vm/stack_frame.cc @@ -528,19 +528,6 @@ StackFrameIterator::StackFrameIterator(uword fp, 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 8f392a9c35c..dff02794c60 100644 --- a/runtime/vm/stack_frame.h +++ b/runtime/vm/stack_frame.h @@ -236,8 +236,6 @@ class StackFrameIterator : public ValueObject { Thread* thread, CrossThreadPolicy cross_thread_policy); - StackFrameIterator(const StackFrameIterator& orig); - // Checks if a next frame exists. bool HasNextFrame() const { return frames_.fp_ != 0; } @@ -302,6 +300,7 @@ class StackFrameIterator : public ValueObject { Thread* thread_; friend class ProfilerDartStackWalker; + DISALLOW_COPY_AND_ASSIGN(StackFrameIterator); }; // Iterator for iterating over all dart frames (skips over exit frames, @@ -340,8 +339,6 @@ class DartFrameIterator : public ValueObject { thread, cross_thread_policy) {} - DartFrameIterator(const DartFrameIterator& orig) : frames_(orig.frames_) {} - // Get next dart frame. StackFrame* NextFrame() { StackFrame* frame = frames_.NextFrame(); @@ -353,6 +350,8 @@ class DartFrameIterator : public ValueObject { 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 0ac6cd3779d..fb01137127a 100644 --- a/runtime/vm/stack_trace.cc +++ b/runtime/vm/stack_trace.cc @@ -10,18 +10,11 @@ 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.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; +// sdk/lib/async/future_impl.dart:_FutureListener.stateWhencomplete. +const intptr_t k_FutureListener_stateWhencomplete = 8; // Find current yield index from async closure. // Async closures contains a variable, :await_jump_var that holds the index into @@ -147,19 +140,21 @@ ClosurePtr CallerClosureFinder::GetCallerInFutureImpl(const Object& future) { ASSERT(!future.IsNull()); ASSERT(future.GetClassId() == future_impl_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()) { + listener_ = Instance::Cast(future).GetField(future_result_or_listeners_field); + if (listener_.GetClassId() != future_listener_class.id()) { return Closure::null(); } - callback_ = GetCallerInFutureListener(listener); - if (callback_.IsInstance() && !callback_.IsNull()) { - return Closure::Cast(callback_).raw(); + // 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_ = 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(); @@ -226,46 +221,22 @@ ClosurePtr CallerClosureFinder::FindCallerInAsyncGenClosure( 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_); - } - if (receiver_function_.IsAsyncGenClosure()) { + } else if (receiver_function_.IsAsyncGenClosure()) { return FindCallerInAsyncGenClosure(receiver_context_); - } - if (receiver_function_.IsLocalFunction()) { + } else 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_); - } - if (parent_function_.recognized_kind() == MethodRecognizer::kFutureWait) { + } else if (parent_function_.recognized_kind() == + MethodRecognizer::kFutureWait) { receiver_context_ = receiver_context_.parent(); ASSERT(!receiver_context_.IsNull()); context_entry_ = receiver_context_.At(Context::kFutureWaitFutureIndex); @@ -329,114 +300,6 @@ ClosurePtr StackTraceUtils::FindClosureInFrame(ObjectPtr* last_object_in_caller, 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(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(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, @@ -457,10 +320,13 @@ void StackTraceUtils::CollectFramesLazy( 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()) { @@ -469,36 +335,79 @@ void StackTraceUtils::CollectFramesLazy( continue; } - // 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); + function = frame->LookupDartFunction(); - // 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); - } + // Add the current synchronous frame. + code = frame->LookupDartCode(); + ASSERT(function.raw() == 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 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); + // Either continue the loop (sync-async case) or find all await'ers and + // return. + if (!function.IsNull() && + (function.IsAsyncClosure() || function.IsAsyncGenClosure())) { 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(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 75ba724303a..215da831798 100644 --- a/runtime/vm/stack_trace.h +++ b/runtime/vm/stack_trace.h @@ -21,8 +21,6 @@ class CallerClosureFinder { ClosurePtr GetCallerInFutureImpl(const Object& future_); - ClosurePtr GetCallerInFutureListener(const Object& future_listener); - ClosurePtr FindCallerInAsyncClosure(const Context& receiver_context); ClosurePtr FindCallerInAsyncGenClosure(const Context& receiver_context); @@ -63,8 +61,6 @@ class CallerClosureFinder { Field& state_field; Field& on_data_field; Field& state_data_field; - - DISALLOW_COPY_AND_ASSIGN(CallerClosureFinder); }; class StackTraceUtils : public AllStatic { @@ -73,20 +69,6 @@ class StackTraceUtils : public AllStatic { 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 103906fc59e..5b3b77b0293 100644 --- a/sdk/lib/async/future_impl.dart +++ b/sdk/lib/async/future_impl.dart @@ -61,19 +61,18 @@ class _SyncCompleter extends _Completer { } class _FutureListener { - // 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. @@ -108,18 +107,18 @@ class _FutureListener { 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 Function(S) get _onValue { @@ -147,8 +146,6 @@ class _FutureListener { return _onError != null; } - @pragma("vm:recognized", "other") - @pragma("vm:never-inline") FutureOr handleValue(S sourceResult) { return _zone.runUnary, S>(_onValue, sourceResult); } diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart index 5daa82c5ad9..f662d53aaa5 100644 --- a/sdk/lib/async/zone.dart +++ b/sdk/lib/async/zone.dart @@ -1442,7 +1442,6 @@ class _RootZone extends _Zone { return _rootRun(null, null, this, f); } - @pragma("vm:recognized", "other") R runUnary(R f(T arg), T arg) { if (identical(Zone._current, _rootZone)) return f(arg); return _rootRunUnary(null, null, this, f, arg);