[dartdevc] Adding support for async operations in block expressions
Moving YieldFinder to shared_compiler
Change-Id: Id4d95447443929376f922005e10f66930630dfaf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97040
Reviewed-by: Jenny Messerly <jmesserly@google.com>
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Commit-Queue: Mark Zhou <markzipan@google.com>
diff --git a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
index 65cfe52..e911dca 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
@@ -4,7 +4,7 @@
// TODO(jmesserly): import from its own package
import '../js_ast/js_ast.dart';
-
+import 'shared_compiler.dart' show YieldFinder;
import 'js_names.dart' show TemporaryId;
/// A synthetic `let*` node, similar to that found in Scheme.
@@ -181,7 +181,7 @@
}
Expression _toInvokedFunction(Block block) {
- var finder = _YieldFinder();
+ var finder = YieldFinder();
block.accept(finder);
if (!finder.hasYield) {
return Call(ArrowFun([], block), []);
@@ -353,34 +353,3 @@
if (!found) super.visitNode(node);
}
}
-
-class _YieldFinder extends BaseVisitor {
- bool hasYield = false;
- bool hasThis = false;
- bool _nestedFunction = false;
-
- @override
- visitThis(This node) {
- hasThis = true;
- }
-
- @override
- visitFunctionExpression(FunctionExpression node) {
- var savedNested = _nestedFunction;
- _nestedFunction = true;
- super.visitFunctionExpression(node);
- _nestedFunction = savedNested;
- }
-
- @override
- visitYield(Yield node) {
- if (!_nestedFunction) hasYield = true;
- super.visitYield(node);
- }
-
- @override
- visitNode(Node node) {
- if (hasYield && hasThis) return; // found both, nothing more to do.
- super.visitNode(node);
- }
-}
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index 66e0628..be9b13f 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -192,3 +192,34 @@
if (!found) super.visitNode(node);
}
}
+
+class YieldFinder extends JS.BaseVisitor {
+ bool hasYield = false;
+ bool hasThis = false;
+ bool _nestedFunction = false;
+
+ @override
+ visitThis(JS.This node) {
+ hasThis = true;
+ }
+
+ @override
+ visitFunctionExpression(JS.FunctionExpression node) {
+ var savedNested = _nestedFunction;
+ _nestedFunction = true;
+ super.visitFunctionExpression(node);
+ _nestedFunction = savedNested;
+ }
+
+ @override
+ visitYield(JS.Yield node) {
+ if (!_nestedFunction) hasYield = true;
+ super.visitYield(node);
+ }
+
+ @override
+ visitNode(JS.Node node) {
+ if (hasYield && hasThis) return; // found both, nothing more to do.
+ super.visitNode(node);
+ }
+}
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 160be8b..a2cba73 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -5061,7 +5061,20 @@
.map(_visitStatement)
.toList()
..add(JS.Return(jsExpr));
- return JS.Call(JS.ArrowFun([], JS.Block(jsStmts)), []);
+ var jsBlock = JS.Block(jsStmts);
+ // BlockExpressions with async operations must be constructed
+ // with a generator instead of a lambda.
+ var finder = YieldFinder();
+ jsBlock.accept(finder);
+ if (finder.hasYield) {
+ var genFn = JS.Fun([], jsBlock, isGenerator: true);
+ var asyncLibrary = emitLibraryName(coreTypes.asyncLibrary);
+ var returnType = _emitType(node.getStaticType(types));
+ var asyncCall =
+ js.call('#.async(#, #)', [asyncLibrary, returnType, genFn]);
+ return JS.Yield(asyncCall);
+ }
+ return JS.Call(JS.ArrowFun([], jsBlock), []);
}
@override