From b449e99118cbfa820943394531055bfb243a7743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Mon, 8 Apr 2024 12:42:29 +0000 Subject: [PATCH] [dart2wasm] Fix async* transformation of nested async* functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With nested `async*` functions, the state of whether we're in an `async*` function should be restored as the previous state after leaving the nested function, instead of as `false`. Fixes #55397. Change-Id: I5f2a964847ae34e98584f3adad6df7857b81e474 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/361600 Commit-Queue: Ömer Ağacan Reviewed-by: Slava Egorov --- pkg/dart2wasm/lib/transformers.dart | 5 +++-- tests/language/async/nested_test.dart | 31 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 tests/language/async/nested_test.dart diff --git a/pkg/dart2wasm/lib/transformers.dart b/pkg/dart2wasm/lib/transformers.dart index 51a3994f6bf..b2b6788f9f8 100644 --- a/pkg/dart2wasm/lib/transformers.dart +++ b/pkg/dart2wasm/lib/transformers.dart @@ -679,13 +679,14 @@ class _WasmTransformer extends Transformer { @override TreeNode visitFunctionNode(FunctionNode functionNode) { + final previousEnclosing = _enclosingIsAsyncStar; if (functionNode.dartAsyncMarker == AsyncMarker.AsyncStar) { _enclosingIsAsyncStar = true; functionNode = _lowerAsyncStar(functionNode) as FunctionNode; - _enclosingIsAsyncStar = false; + _enclosingIsAsyncStar = previousEnclosing; return super.visitFunctionNode(functionNode); } else { - bool previousEnclosing = _enclosingIsAsyncStar; + _enclosingIsAsyncStar = false; TreeNode result = super.visitFunctionNode(functionNode); _enclosingIsAsyncStar = previousEnclosing; return result; diff --git a/tests/language/async/nested_test.dart b/tests/language/async/nested_test.dart new file mode 100644 index 00000000000..d5c398c8fdc --- /dev/null +++ b/tests/language/async/nested_test.dart @@ -0,0 +1,31 @@ +// Copyright (c) 2024, 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:async_helper/async_helper.dart"; +import "package:expect/expect.dart"; + +Stream stream() async* { + yield 'a'; + yield 'b'; +} + +Stream expandedStream() async* { + final expanded = stream().asyncExpand((s) async* { + yield 'before'; + yield s; + yield 'after'; + }); + + yield* expanded; +} + +test() async { + Expect.listEquals(['before', 'a', 'after', 'before', 'b', 'after'], + await expandedStream().toList()); +} + +void main() { + asyncStart(); + test().then((_) => asyncEnd()); +}