| Index: pkg/compiler/lib/src/ssa/builder.dart
|
| ===================================================================
|
| --- pkg/compiler/lib/src/ssa/builder.dart (revision 43839)
|
| +++ pkg/compiler/lib/src/ssa/builder.dart (working copy)
|
| @@ -25,12 +25,13 @@
|
| JavaScriptBackend backend = builder.backend;
|
|
|
| AsyncRewriter rewriter = null;
|
| +
|
| if (element.asyncMarker == AsyncMarker.ASYNC) {
|
| rewriter = new AsyncRewriter(
|
| backend.compiler,
|
| backend.compiler.currentElement,
|
| - thenHelper:
|
| - backend.emitter.staticFunctionAccess(backend.getThenHelper()),
|
| + asyncHelper:
|
| + backend.emitter.staticFunctionAccess(backend.getAsyncHelper()),
|
| newCompleter: backend.emitter.staticFunctionAccess(
|
| backend.getCompleterConstructor()),
|
| safeVariableName: backend.namer.safeVariableName);
|
| @@ -44,6 +45,8 @@
|
| backend.getSyncStarIterableConstructor()),
|
| yieldStarExpression: backend.emitter.staticFunctionAccess(
|
| backend.getYieldStar()),
|
| + uncaughtErrorExpression: backend.emitter.staticFunctionAccess(
|
| + backend.getSyncStarUncaughtError()),
|
| safeVariableName: backend.namer.safeVariableName);
|
| }
|
| else if (element.asyncMarker == AsyncMarker.ASYNC_STAR) {
|
| @@ -51,7 +54,7 @@
|
| backend.compiler,
|
| backend.compiler.currentElement,
|
| streamHelper: backend.emitter.staticFunctionAccess(
|
| - backend.getStreamHelper()),
|
| + backend.getAsyncStarHelper()),
|
| streamOfController: backend.emitter.staticFunctionAccess(
|
| backend.getStreamOfController()),
|
| newController: backend.emitter.staticFunctionAccess(
|
| @@ -1058,6 +1061,13 @@
|
| // We build the Ssa graph by simulating a stack machine.
|
| List<HInstruction> stack = <HInstruction>[];
|
|
|
| + /// Returns `true` if the current element is an `async` function.
|
| + bool get isBuildingAsyncFunction {
|
| + Element element = sourceElement;
|
| + return (element is FunctionElement &&
|
| + element.asyncMarker == AsyncMarker.ASYNC);
|
| + }
|
| +
|
| SsaBuilder(JavaScriptBackend backend,
|
| CodegenWorkItem work,
|
| this.nativeEmitter,
|
| @@ -5179,6 +5189,28 @@
|
| emitReturn(value, node);
|
| }
|
|
|
| + /// Returns true if the [type] is a valid return type for an asynchronous
|
| + /// function.
|
| + ///
|
| + /// Asynchronous functions return a `Future`, and a valid return is thus
|
| + /// either dynamic, Object, or Future.
|
| + ///
|
| + /// We do not accept the internal Future implementation class.
|
| + bool isValidAsyncReturnType(DartType type) {
|
| + assert (isBuildingAsyncFunction);
|
| + // TODO(sigurdm): In an internal library a function could be declared:
|
| + //
|
| + // _FutureImpl foo async => 1;
|
| + //
|
| + // This should be valid (because the actual value returned from an async
|
| + // function is a `_FutureImpl`), but currently false is returned in this
|
| + // case.
|
| + return type.isDynamic ||
|
| + type.isObject ||
|
| + (type is InterfaceType &&
|
| + type.element == compiler.futureClass);
|
| + }
|
| +
|
| visitReturn(ast.Return node) {
|
| if (identical(node.beginToken.stringValue, 'native')) {
|
| native.handleSsaNative(this, node.expression);
|
| @@ -5190,7 +5222,19 @@
|
| } else {
|
| visit(node.expression);
|
| value = pop();
|
| - value = potentiallyCheckOrTrustType(value, returnType);
|
| + if (isBuildingAsyncFunction) {
|
| + if (compiler.enableTypeAssertions &&
|
| + !isValidAsyncReturnType(returnType)) {
|
| + String message =
|
| + "Async function returned a Future, "
|
| + "was declared to return a $returnType.";
|
| + generateTypeError(node, message);
|
| + pop();
|
| + return;
|
| + }
|
| + } else {
|
| + value = potentiallyCheckOrTrustType(value, returnType);
|
| + }
|
| }
|
|
|
| handleInTryStatement();
|
|
|