From d506e92e84a6bb5e48cf3a53da9ab9ebc07a6dbb Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 29 Feb 2016 11:04:56 -0800
Subject: [PATCH 01/23] Early support for generators.

---
 Jakefile.js                                |    2 +
 src/compiler/binder.ts                     |   27 +-
 src/compiler/checker.ts                    |   12 +-
 src/compiler/core.ts                       |   27 +-
 src/compiler/emitter.ts                    |    6 +-
 src/compiler/factory.ts                    |  280 +-
 src/compiler/printer.ts                    |  233 +-
 src/compiler/transformer.ts                |   75 +-
 src/compiler/transformers/es6.ts           |  164 +-
 src/compiler/transformers/generators.ts    | 2957 ++++++++++++++++++++
 src/compiler/transformers/module/module.ts |   18 +-
 src/compiler/transformers/module/system.ts |   39 +-
 src/compiler/transformers/ts.ts            |   19 +-
 src/compiler/types.ts                      |   43 +-
 src/compiler/utilities.ts                  |   10 +
 src/compiler/visitor.ts                    |    7 +-
 16 files changed, 3734 insertions(+), 185 deletions(-)
 create mode 100644 src/compiler/transformers/generators.ts

diff --git a/Jakefile.js b/Jakefile.js
index 26bfe76c04838..5c9e6d5ab598d 100644
--- a/Jakefile.js
+++ b/Jakefile.js
@@ -49,6 +49,7 @@ var compilerSources = [
     "transformers/module/module.ts",
     "transformers/jsx.ts",
     "transformers/es7.ts",
+    "transformers/generators.ts",
     "transformers/es6.ts",
     "transformer.ts",
     "sourcemap.ts",
@@ -82,6 +83,7 @@ var servicesSources = [
     "transformers/module/module.ts",
     "transformers/jsx.ts",
     "transformers/es7.ts",
+    "transformers/generators.ts",
     "transformers/es6.ts",
     "transformer.ts",
     "sourcemap.ts",
diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts
index 4ea2489de8886..cf0230ef9fa2a 100644
--- a/src/compiler/binder.ts
+++ b/src/compiler/binder.ts
@@ -1115,7 +1115,7 @@ namespace ts {
             }
         }
 
-        function checkStrictModeNumericLiteral(node: LiteralExpression) {
+        function checkStrictModeNumericLiteral(node: NumericLiteral) {
             if (inStrictMode && node.isOctalLiteral) {
                 file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode));
             }
@@ -1296,7 +1296,7 @@ namespace ts {
                 case SyntaxKind.DeleteExpression:
                     return checkStrictModeDeleteExpression(<DeleteExpression>node);
                 case SyntaxKind.NumericLiteral:
-                    return checkStrictModeNumericLiteral(<LiteralExpression>node);
+                    return checkStrictModeNumericLiteral(<NumericLiteral>node);
                 case SyntaxKind.PostfixUnaryExpression:
                     return checkStrictModePostfixUnaryExpression(<PostfixUnaryExpression>node);
                 case SyntaxKind.PrefixUnaryExpression:
@@ -1852,11 +1852,14 @@ namespace ts {
             case SyntaxKind.TaggedTemplateExpression:
             case SyntaxKind.ShorthandPropertyAssignment:
             case SyntaxKind.ForOfStatement:
-            case SyntaxKind.YieldExpression:
                 // These nodes are ES6 syntax.
                 transformFlags |= TransformFlags.AssertES6;
                 break;
 
+            case SyntaxKind.YieldExpression:
+                // This node is ES6 syntax.
+                transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsYield;
+                break;
 
             case SyntaxKind.AnyKeyword:
             case SyntaxKind.NumberKeyword:
@@ -2026,10 +2029,13 @@ namespace ts {
                 // A FunctionExpression excludes markers that should not escape the scope of a FunctionExpression.
                 excludeFlags = TransformFlags.FunctionExcludes;
 
+                if ((<FunctionExpression>node).asteriskToken) {
+                    transformFlags |= TransformFlags.ContainsGenerators;
+                }
+
                 // If a FunctionExpression contains an asterisk token, or its subtree has marked the container
                 // as needing to capture the lexical this, then this node is ES6 syntax.
-                if ((<FunctionLikeDeclaration>node).asteriskToken
-                    || subtreeFlags & TransformFlags.ContainsCapturedLexicalThis
+                if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis
                     || subtreeFlags & TransformFlags.ContainsDefaultValueAssignments) {
                     transformFlags |= TransformFlags.AssertES6;
                 }
@@ -2051,11 +2057,14 @@ namespace ts {
                     break;
                 }
 
+                if ((<FunctionDeclaration>node).asteriskToken) {
+                    transformFlags |= TransformFlags.ContainsGenerators;
+                }
+
                 // If a FunctionDeclaration has an asterisk token, is exported, or its
                 // subtree has marked the container as needing to capture the lexical `this`,
                 // then this node is ES6 syntax.
-                if ((<FunctionDeclaration>node).asteriskToken
-                    || node.flags & NodeFlags.Export
+                if (node.flags & NodeFlags.Export
                     || subtreeFlags & TransformFlags.ContainsCapturedLexicalThis
                     || subtreeFlags & TransformFlags.ContainsDefaultValueAssignments) {
                     transformFlags |= TransformFlags.AssertES6;
@@ -2183,6 +2192,10 @@ namespace ts {
                 excludeFlags = TransformFlags.MethodOrAccessorExcludes;
                 transformFlags |= TransformFlags.AssertES6;
 
+                if ((<MethodDeclaration>node).asteriskToken) {
+                    transformFlags |= TransformFlags.ContainsGenerators;
+                }
+
                 // A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded,
                 // generic, or has both a computed property name and a decorator.
                 if ((<MethodDeclaration>node).body === undefined
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 7dfd679e72c26..9878f5e516f00 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -11404,7 +11404,7 @@ namespace ts {
             return type;
         }
 
-        function checkNumericLiteral(node: LiteralExpression): Type {
+        function checkNumericLiteral(node: NumericLiteral): Type {
             // Grammar checking
             checkGrammarNumericLiteral(node);
             return numberType;
@@ -11424,7 +11424,7 @@ namespace ts {
                 case SyntaxKind.FalseKeyword:
                     return booleanType;
                 case SyntaxKind.NumericLiteral:
-                    return checkNumericLiteral(<LiteralExpression>node);
+                    return checkNumericLiteral(<NumericLiteral>node);
                 case SyntaxKind.TemplateExpression:
                     return checkTemplateExpression(<TemplateExpression>node);
                 case SyntaxKind.StringLiteral:
@@ -14328,7 +14328,7 @@ namespace ts {
                             }
                             return undefined;
                         case SyntaxKind.NumericLiteral:
-                            return +(<LiteralExpression>e).text;
+                            return +(<NumericLiteral>e).text;
                         case SyntaxKind.ParenthesizedExpression:
                             return evalConstant((<ParenthesizedExpression>e).expression);
                         case SyntaxKind.Identifier:
@@ -15499,7 +15499,7 @@ namespace ts {
                         if (objectType === unknownType) return undefined;
                         const apparentType = getApparentType(objectType);
                         if (apparentType === unknownType) return undefined;
-                        return getPropertyOfType(apparentType, (<LiteralExpression>node).text);
+                        return getPropertyOfType(apparentType, (<NumericLiteral>node).text);
                     }
                     break;
             }
@@ -16693,7 +16693,7 @@ namespace ts {
                     // Grammar checking for computedPropertName and shorthandPropertyAssignment
                     checkGrammarForInvalidQuestionMark(prop, (<PropertyAssignment>prop).questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
                     if (name.kind === SyntaxKind.NumericLiteral) {
-                        checkGrammarNumericLiteral(<LiteralExpression>name);
+                        checkGrammarNumericLiteral(<NumericLiteral>name);
                     }
                     currentKind = Property;
                 }
@@ -17194,7 +17194,7 @@ namespace ts {
             }
         }
 
-        function checkGrammarNumericLiteral(node: LiteralExpression): boolean {
+        function checkGrammarNumericLiteral(node: NumericLiteral): boolean {
             // Grammar checking
             if (node.isOctalLiteral && languageVersion >= ScriptTarget.ES5) {
                 return grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher);
diff --git a/src/compiler/core.ts b/src/compiler/core.ts
index a464bd8668240..20306deaa2b0d 100644
--- a/src/compiler/core.ts
+++ b/src/compiler/core.ts
@@ -307,13 +307,14 @@ namespace ts {
         return ~low;
     }
 
-    export function reduceLeft<T, U>(array: T[], f: (memo: U, value: T, i: number) => U, initial: U): U;
+    export function reduceLeft<T, U>(array: T[], f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U;
     export function reduceLeft<T>(array: T[], f: (memo: T, value: T, i: number) => T): T;
-    export function reduceLeft<T>(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T): T {
-        if (array) {
-            const count = array.length;
-            if (count > 0) {
-                let pos = 0;
+    export function reduceLeft<T>(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T, start?: number, count?: number): T {
+        if (array && array.length > 0) {
+            const size = array.length;
+            if (size > 0) {
+                let pos = start === undefined || start < 0 ? 0 : start;
+                const end = count === undefined || pos + count > size - 1 ? size - 1 : pos + count;
                 let result: T;
                 if (arguments.length <= 2) {
                     result = array[pos];
@@ -322,7 +323,7 @@ namespace ts {
                 else {
                     result = initial;
                 }
-                while (pos < count) {
+                while (pos <= end) {
                     result = f(result, array[pos], pos);
                     pos++;
                 }
@@ -332,12 +333,14 @@ namespace ts {
         return initial;
     }
 
-    export function reduceRight<T, U>(array: T[], f: (memo: U, value: T, i: number) => U, initial: U): U;
+    export function reduceRight<T, U>(array: T[], f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U;
     export function reduceRight<T>(array: T[], f: (memo: T, value: T, i: number) => T): T;
-    export function reduceRight<T>(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T): T {
+    export function reduceRight<T>(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T, start?: number, count?: number): T {
         if (array) {
-            let pos = array.length - 1;
-            if (pos >= 0) {
+            const size = array.length;
+            if (size > 0) {
+                let pos = start === undefined || start > size - 1 ? size - 1 : start;
+                const end = count === undefined || pos - count < 0 ? 0 : pos - count;
                 let result: T;
                 if (arguments.length <= 2) {
                     result = array[pos];
@@ -346,7 +349,7 @@ namespace ts {
                 else {
                     result = initial;
                 }
-                while (pos >= 0) {
+                while (pos >= end) {
                     result = f(result, array[pos], pos);
                     pos--;
                 }
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index 357fec7f0fd65..23186c7225383 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -1406,7 +1406,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
                     write("\"");
 
                     if (node.kind === SyntaxKind.NumericLiteral) {
-                        write((<LiteralExpression>node).text);
+                        write((<NumericLiteral>node).text);
                     }
                     else {
                         writeTextOfNode(currentText, node);
@@ -3645,7 +3645,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
             }
 
             function createVoidZero(): Expression {
-                const zero = <LiteralExpression>createSynthesizedNode(SyntaxKind.NumericLiteral);
+                const zero = <NumericLiteral>createSynthesizedNode(SyntaxKind.NumericLiteral);
                 zero.text = "0";
                 const result = <VoidExpression>createSynthesizedNode(SyntaxKind.VoidExpression);
                 result.expression = zero;
@@ -3889,7 +3889,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
                 }
 
                 function createNumericLiteral(value: number) {
-                    const node = <LiteralExpression>createSynthesizedNode(SyntaxKind.NumericLiteral);
+                    const node = <NumericLiteral>createSynthesizedNode(SyntaxKind.NumericLiteral);
                     node.text = "" + value;
                     return node;
                 }
diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts
index e63b86a8770d6..b7b922f0c7ce8 100644
--- a/src/compiler/factory.ts
+++ b/src/compiler/factory.ts
@@ -152,8 +152,22 @@ namespace ts {
     /**
      * Creates a shallow, memberwise clone of a node for mutation.
      */
-    export function getMutableNode<T extends Node>(node: T): T {
-        return cloneNode<T>(node, node, node.flags, node.parent, node);
+    export function getMutableClone<T extends Node>(node: T): T {
+        return cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
+    }
+
+    /**
+     * Creates a shallow, memberwise clone with no position information.
+     */
+    export function getSynthesizedClone<T extends Node>(node: T): T {
+        return cloneNode(node, /*location*/ undefined, node.flags, /*parent*/ undefined, /*original*/ node);
+    }
+
+    /**
+     * Creates a shallow, memberwise clone with the specified position information.
+     */
+    export function getRelocatedClone<T extends Node>(node: T, location: TextRange) {
+        return cloneNode(node, location, node.flags, /*parent*/ undefined, /*original*/ node);
     }
 
     export function createNodeArrayNode<T extends Node>(elements: T[]): NodeArrayNode<T> {
@@ -165,12 +179,13 @@ namespace ts {
     // Literals
 
     export function createLiteral(value: string, location?: TextRange): StringLiteral;
-    export function createLiteral(value: number, location?: TextRange): LiteralExpression;
+    export function createLiteral(value: number, location?: TextRange, trailingComment?: string): NumericLiteral;
     export function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression;
-    export function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression {
+    export function createLiteral(value: string | number | boolean, location?: TextRange, trailingComment?: string): PrimaryExpression {
         if (typeof value === "number") {
-            const node = <LiteralExpression>createNode(SyntaxKind.NumericLiteral, location);
+            const node = <NumericLiteral>createNode(SyntaxKind.NumericLiteral, location);
             node.text = value.toString();
+            node.trailingComment = trailingComment;
             return node;
         }
         else if (typeof value === "boolean") {
@@ -185,8 +200,8 @@ namespace ts {
 
     // Identifiers
 
-    export function createIdentifier(text: string): Identifier {
-        const node = <Identifier>createNode(SyntaxKind.Identifier);
+    export function createIdentifier(text: string, location?: TextRange): Identifier {
+        const node = <Identifier>createNode(SyntaxKind.Identifier, location);
         node.text = text;
         return node;
     }
@@ -194,7 +209,7 @@ namespace ts {
     export function createTempVariable(): Identifier {
         const name = <Identifier>createNode(SyntaxKind.Identifier);
         name.text = undefined;
-        name.tempKind = TempVariableKind.Auto;
+        name.tempKind = GeneratedIdentifierKind.Auto;
         getNodeId(name);
         return name;
     }
@@ -202,7 +217,15 @@ namespace ts {
     export function createLoopVariable(): Identifier {
         const name = <Identifier>createNode(SyntaxKind.Identifier);
         name.text = undefined;
-        name.tempKind = TempVariableKind.Loop;
+        name.tempKind = GeneratedIdentifierKind.Loop;
+        getNodeId(name);
+        return name;
+    }
+
+    export function createUniqueName(text: string): Identifier {
+        const name = <Identifier>createNode(SyntaxKind.Identifier);
+        name.text = text;
+        name.tempKind = GeneratedIdentifierKind.Unique;
         getNodeId(name);
         return name;
     }
@@ -292,15 +315,23 @@ namespace ts {
 
     // Expression
 
-    export function createArrayLiteral(elements?: Expression[]) {
-        const node = <ArrayLiteralExpression>createNode(SyntaxKind.ArrayLiteralExpression);
+    export function createArrayLiteral(elements?: Expression[], location?: TextRange, multiLine?: boolean) {
+        const node = <ArrayLiteralExpression>createNode(SyntaxKind.ArrayLiteralExpression, location);
         node.elements = parenthesizeListElements(createNodeArray(elements));
+        if (multiLine) {
+            node.multiLine = true;
+        }
+
         return node;
     }
 
-    export function createObjectLiteral(properties?: ObjectLiteralElement[], location?: TextRange) {
+    export function createObjectLiteral(properties?: ObjectLiteralElement[], location?: TextRange, multiLine?: boolean) {
         const node = <ObjectLiteralExpression>createNode(SyntaxKind.ObjectLiteralExpression, location);
         node.properties = createNodeArray(properties);
+        if (multiLine) {
+            node.multiLine = true;
+        }
+
         return node;
     }
 
@@ -319,16 +350,16 @@ namespace ts {
         return node;
     }
 
-    export function createCall(expression: Expression, argumentsArray: Expression[], location?: TextRange) {
+    export function createCall(expression: string | Expression, argumentsArray: Expression[], location?: TextRange) {
         const node = <CallExpression>createNode(SyntaxKind.CallExpression, location);
-        node.expression = parenthesizeForAccess(expression);
+        node.expression = typeof expression === "string" ? createIdentifier(expression) : parenthesizeForAccess(expression);
         node.arguments = parenthesizeListElements(createNodeArray(argumentsArray));
         return node;
     }
 
     export function createNew(expression: Expression, argumentsArray: Expression[], location?: TextRange) {
         const node = <NewExpression>createNode(SyntaxKind.NewExpression, location);
-        node.expression = parenthesizeForAccess(expression);
+        node.expression = parenthesizeForNew(expression);
         node.arguments = argumentsArray
             ? parenthesizeListElements(createNodeArray(argumentsArray))
             : undefined;
@@ -341,7 +372,7 @@ namespace ts {
         return node;
     }
 
-    export function createFunctionExpression(asteriskToken: Node, name: string | Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange) {
+    export function createFunctionExpression(asteriskToken: Node, name: string | Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, original?: Node) {
         const node = <FunctionExpression>createNode(SyntaxKind.FunctionExpression, location);
         node.modifiers = undefined;
         node.asteriskToken = asteriskToken;
@@ -350,6 +381,10 @@ namespace ts {
         node.parameters = createNodeArray(parameters);
         node.type = undefined;
         node.body = body;
+        if (original) {
+            node.original = original;
+        }
+
         return node;
     }
 
@@ -390,11 +425,15 @@ namespace ts {
         return node;
     }
 
-    export function createBinary(left: Expression, operator: SyntaxKind, right: Expression, location?: TextRange) {
+    export function createBinary(left: Expression, operator: SyntaxKind, right: Expression, location?: TextRange, original?: Node) {
         const node = <BinaryExpression>createNode(SyntaxKind.BinaryExpression, location);
         node.left = parenthesizeBinaryOperand(operator, left, /*isLeftSideOfBinary*/ true);
         node.operatorToken = createSynthesizedNode(operator);
         node.right = parenthesizeBinaryOperand(operator, right, /*isLeftSideOfBinary*/ false);
+        if (original) {
+            node.original = original;
+        }
+
         return node;
     }
 
@@ -440,9 +479,13 @@ namespace ts {
 
     // Element
 
-    export function createBlock(statements: Statement[], location?: TextRange): Block {
+    export function createBlock(statements: Statement[], location?: TextRange, multiLine?: boolean): Block {
         const block = <Block>createNode(SyntaxKind.Block, location);
         block.statements = createNodeArray(statements);
+        if (multiLine) {
+            block.multiLine = true;
+        }
+
         return block;
     }
 
@@ -545,6 +588,42 @@ namespace ts {
         return node;
     }
 
+    export function createWith(expression: Expression, statement: Statement, location?: TextRange): ReturnStatement {
+        const node = <WithStatement>createNode(SyntaxKind.WithStatement, location);
+        node.expression = expression;
+        node.statement = statement;
+        return node;
+    }
+
+    export function createSwitch(expression: Expression, caseBlock: CaseBlock, location?: TextRange): ReturnStatement {
+        const node = <SwitchStatement>createNode(SyntaxKind.SwitchStatement, location);
+        node.expression = expression;
+        node.caseBlock = caseBlock;
+        return node;
+    }
+
+    export function createThrow(expression: Expression, location?: TextRange): ReturnStatement {
+        const node = <ThrowStatement>createNode(SyntaxKind.ThrowStatement, location);
+        node.expression = expression;
+        return node;
+    }
+
+    export function createTryCatchFinally(tryBlock: Block, catchClause: CatchClause, finallyBlock: Block, location?: TextRange) {
+        const node = <TryStatement>createNode(SyntaxKind.TryStatement, location);
+        node.tryBlock = tryBlock;
+        node.catchClause = catchClause;
+        node.finallyBlock = finallyBlock;
+        return node;
+    }
+
+    export function createTryCatch(tryBlock: Block, catchClause: CatchClause, location?: TextRange) {
+        return createTryCatchFinally(tryBlock, catchClause, /*finallyBlock*/ undefined, location);
+    }
+
+    export function createTryFinally(tryBlock: Block, finallyBlock: Block, location?: TextRange) {
+        return createTryCatchFinally(tryBlock, /*catchClause*/ undefined, finallyBlock, location);
+    }
+
     export function createFunctionDeclaration(modifiers: Modifier[], asteriskToken: Node, name: string | Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange) {
         const node = <FunctionDeclaration>createNode(SyntaxKind.FunctionDeclaration, location);
         node.decorators = undefined;
@@ -569,6 +648,12 @@ namespace ts {
         return node;
     }
 
+    export function createCaseBlock(clauses: CaseOrDefaultClause[], location?: TextRange) {
+        const node = <CaseBlock>createNode(SyntaxKind.CaseBlock, location);
+        node.clauses = createNodeArray(clauses);
+        return node;
+    }
+
     export function createExportDefault(expression: Expression) {
         const node = <ExportAssignment>createNode(SyntaxKind.ExportAssignment);
         node.isExportEquals = false;
@@ -632,7 +717,7 @@ namespace ts {
         return <Expression>createBinary(left, SyntaxKind.LessThanToken, right, location);
     }
 
-    export function createAssignment(left: Expression, right: Expression, location?: TextRange) {
+    export function createAssignment(left: Expression, right: Expression, location?: TextRange, original?: Node) {
         return createBinary(left, SyntaxKind.EqualsToken, right, location);
     }
 
@@ -1040,6 +1125,58 @@ namespace ts {
         );
     }
 
+    export interface CallTarget {
+        target: LeftHandSideExpression;
+        thisArg: Expression;
+    }
+
+    export function createCallBinding(expression: Expression): CallTarget {
+        const callee = skipParentheses(expression);
+        let thisArg: Expression;
+        let target: LeftHandSideExpression;
+        switch (callee.kind) {
+            case SyntaxKind.PropertyAccessExpression: {
+                // for `a.b()` target is `(_a = a).b` and thisArg is `_a`
+                thisArg = createTempVariable();
+                target = createPropertyAccess(
+                    createAssignment(
+                        thisArg,
+                        (<PropertyAccessExpression>callee).expression,
+                        /*location*/ (<PropertyAccessExpression>callee).expression
+                    ),
+                    (<PropertyAccessExpression>callee).name,
+                    /*location*/ callee
+                );
+                break;
+            }
+
+            case SyntaxKind.ElementAccessExpression: {
+                // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a`
+                thisArg = createTempVariable();
+                target = createElementAccess(
+                    createAssignment(
+                        thisArg,
+                        (<ElementAccessExpression>callee).expression,
+                        /*location*/ (<ElementAccessExpression>callee).expression
+                    ),
+                    (<ElementAccessExpression>callee).argumentExpression,
+                    /*location*/ callee
+                );
+
+                break;
+            }
+
+            default: {
+                // for `a()` target is `a` and thisArg is `void 0`
+                thisArg = createVoidZero();
+                target = parenthesizeForAccess(expression);
+                break;
+            }
+        }
+
+        return { target, thisArg };
+    }
+
     export function inlineExpressions(expressions: Expression[]) {
         return reduceLeft(expressions, createComma);
     }
@@ -1059,6 +1196,96 @@ namespace ts {
              : cloneNode(memberName, location);
     }
 
+    export function createExpressionForObjectLiteralElement(node: ObjectLiteralExpression, property: ObjectLiteralElement, receiver: Expression): Expression {
+        switch (property.kind) {
+            case SyntaxKind.GetAccessor:
+            case SyntaxKind.SetAccessor:
+                return createExpressionForAccessorDeclaration(node.properties, <AccessorDeclaration>property, receiver, node.multiLine);
+            case SyntaxKind.PropertyAssignment:
+                return createExpressionForPropertyAssignment(<PropertyAssignment>property, receiver);
+            case SyntaxKind.ShorthandPropertyAssignment:
+                return createExpressionForShorthandPropertyAssignment(<ShorthandPropertyAssignment>property, receiver);
+            case SyntaxKind.MethodDeclaration:
+                return createExpressionForMethodDeclaration(<MethodDeclaration>property, receiver);
+        }
+    }
+
+    function createExpressionForAccessorDeclaration(properties: NodeArray<Declaration>, property: AccessorDeclaration, receiver: Expression, multiLine: boolean) {
+        const { firstAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(properties, property);
+        if (property === firstAccessor) {
+            return aggregateTransformFlags(
+                createObjectDefineProperty(
+                    receiver,
+                    createExpressionForPropertyName(property.name, /*location*/ property.name),
+                    {
+                        get: getAccessor && createFunctionExpression(
+                            /*asteriskToken*/ undefined,
+                            /*name*/ undefined,
+                            getAccessor.parameters,
+                            getAccessor.body,
+                            /*location*/ getAccessor,
+                            /*original*/ getAccessor
+                        ),
+                        set: setAccessor && createFunctionExpression(
+                            /*asteriskToken*/ undefined,
+                            /*name*/ undefined,
+                            setAccessor.parameters,
+                            setAccessor.body,
+                            /*location*/ setAccessor,
+                            /*original*/ setAccessor
+                        ),
+                        enumerable: true,
+                        configurable: true
+                    },
+                    multiLine,
+                    /*location*/ firstAccessor
+                )
+            );
+        }
+
+        return undefined;
+    }
+
+    function createExpressionForPropertyAssignment(property: PropertyAssignment, receiver: Expression) {
+        return aggregateTransformFlags(
+            createAssignment(
+                createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name),
+                property.initializer,
+                /*location*/ property,
+                /*original*/ property
+            )
+        );
+    }
+
+    function createExpressionForShorthandPropertyAssignment(property: ShorthandPropertyAssignment, receiver: Expression) {
+        return aggregateTransformFlags(
+            createAssignment(
+                createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name),
+                getSynthesizedClone(property.name),
+                /*location*/ property,
+                /*original*/ property
+            )
+        );
+    }
+
+    function createExpressionForMethodDeclaration(method: MethodDeclaration, receiver: Expression) {
+        return aggregateTransformFlags(
+            createAssignment(
+                createMemberAccessForPropertyName(receiver, method.name, /*location*/ method.name),
+                createFunctionExpression(
+                    method.asteriskToken,
+                    /*name*/ undefined,
+                    method.parameters,
+                    method.body,
+                    /*location*/ method,
+                    /*original*/ method
+                ),
+                /*location*/ method,
+                /*original*/ method
+            )
+        );
+    }
+
     // Utilities
 
     /**
@@ -1178,6 +1405,17 @@ namespace ts {
             || binaryOperator === SyntaxKind.CaretToken;
     }
 
+    export function parenthesizeForNew(expression: Expression): LeftHandSideExpression {
+        const lhs = parenthesizeForAccess(expression);
+        switch (lhs.kind) {
+            case SyntaxKind.CallExpression:
+            case SyntaxKind.NewExpression:
+                return createParen(lhs);
+        }
+
+        return lhs;
+    }
+
     /**
      * Wraps an expression in parentheses if it is needed in order to use the expression for
      * property or element access.
@@ -1335,8 +1573,4 @@ namespace ts {
         nodes.hasTrailingComma = hasTrailingComma;
         return nodes;
     }
-
-    export function getSynthesizedNode<T extends Node>(node: T): T {
-        return nodeIsSynthesized(node) ? node : cloneNode(node, /*location*/ undefined, node.flags, /*parent*/ undefined, /*original*/ node);
-    }
 }
\ No newline at end of file
diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts
index a1d284dd42bba..4fc482be5bffa 100644
--- a/src/compiler/printer.ts
+++ b/src/compiler/printer.ts
@@ -58,6 +58,165 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
     });
 };`;
 
+        const keysHelper = `
+var __keys = (this && this.__keys) || function (o) {
+    var a = [];
+    for (var k in o) a.push(k);
+    return __values(a);
+};`;
+
+        const valuesHelper = `
+var __values = (this && this.__values) || function (o) {
+    if (typeof o.next === "function") {
+        return o;
+    }
+    if (typeof o.length === "number") {
+        var i, done;
+        return {
+            next: function() {
+                return done || (done = i >= o.length)
+                    ? { value: undefined, done: true }
+                    : { value: o[i++], done: false };
+            }
+        };
+    }
+};`;
+
+        const generatorHelper = `
+var __generator = (this && this.__generator) || function (body) {
+    var done, finallyStack, executing, state, yieldStar;
+    function step(opcode, arg) {
+        if (typeof Debug !== "undefined" && "setNonUserCodeExceptions" in Debug) {
+            Debug.setNonUserCodeExceptions = true;
+        }
+
+        if (executing) {
+            throw new TypeError("Generator is already executing.");
+        }
+
+        state = state || { label: 0 };
+        while (true) {
+            executing = false;
+            verb = yielded = undefined;
+            if (!done) {
+                var trys = state.trys;
+                var region = trys && trys[trys.length - 1];
+                if (region) {
+                    var tryLabel = region[0 /*try*/];
+                    var catchLabel = region[1 /*catch*/];
+                    var finallyLabel = region[2 /*finally*/];
+                    var endLabel = region[3 /*endtry*/];
+                }
+                else {
+                    if (opcode === 6 /*catch*/) {
+                        opcode = 1 /*throw*/;
+                    }
+                    if (opcode === 1 /*throw*/ || opcode === 2 /*return*/) {
+                        done = true;
+                    }
+                }
+            }
+            if (done) {
+                finallyStack = void 0;
+                switch (opcode) {
+                    case 0 /*next*/: return { value: void 0, done: true };
+                    case 1 /*throw*/: throw arg;
+                    case 2 /*return*/: return { value: arg, done: true };
+                }
+            }
+            try {
+                if (yieldStar) {
+                    executing = true;
+                    var verb = yieldStar[opcode === 2 ? "return" : opcode === 1 ? "throw" : "next"];
+                    executing = false;
+                    if (verb) {
+                        executing = true;
+                        var yielded = verb.call(yieldStar, arg);
+                        executing = false;
+                        if (!yielded.done) {
+                            return yielded;
+                        }
+
+                        opcode = 0 /*next*/;
+                        arg = yielded.value;
+                    }
+
+                    yieldStar = void 0;
+                    continue;
+                }
+
+                switch (opcode) {
+                    case 0 /*next*/:
+                        state.sent = function() { return arg };
+                        break;
+
+                    case 1 /*throw*/:
+                        state.sent = function() { throw arg };
+                        break;
+
+                    case 4 /*yield*/:
+                        state.label++;
+                        return { value: arg, done: false };
+
+                    case 5 /*yield**/:
+                        state.label++;
+                        yieldStar = arg;
+                        opcode = 0 /*next*/;
+                        arg = void 0;
+                        continue;
+
+                    case 7 /*endfinally*/:
+                        arg = finallyStack.pop();
+                        opcode = finallyStack.pop();
+                        trys.pop();
+                        continue;
+
+                    default:
+                        if (opcode === 3 /*break*/ && (!region || (arg > tryLabel && arg < endLabel))) {
+                            state.label = arg;
+                        }
+                        else if (opcode === 6 /*catch*/ && state.label < catchLabel) {
+                            state.error = arg;
+                            state.label = catchLabel;
+                        }
+                        else if (state.label < finallyLabel) {
+                            finallyStack = finallyStack || [];
+                            finallyStack.push(opcode, arg);
+                            state.label = finallyLabel;
+                        }
+                        else {
+                            if (finallyLabel) {
+                                finallyStack.pop();
+                                finallyStack.pop();
+                            }
+
+                            trys.pop();
+                            continue;
+                        }
+
+                        break;
+                }
+
+                executing = true;
+                var operation = body(state);
+                opcode = operation[0];
+                arg = operation[1];
+            }
+            catch (e) {
+                opcode = 6 /*catch*/;
+                arg = e;
+                yieldStar = void 0;
+            }
+        }
+    }
+    return {
+        next: function (v) { return step(0 /*next*/, v); },
+        "throw": function (v) { return step(1 /*throw*/, v); },
+        "return": function (v) { return step(2 /*return*/, v); },
+    };
+};`;
+
+
         // emit output for the __export helper function
         const exportStarHelper = `
 function __export(m) {
@@ -154,11 +313,12 @@ const _super = (function (geti, seti) {
             let identifierSubstitution: (node: Identifier) => Identifier;
             let onBeforeEmitNode: (node: Node) => void;
             let onAfterEmitNode: (node: Node) => void;
-            let isUniqueName: (name: string) => boolean;
             let temporaryVariables: string[] = [];
             let tempFlags: TempFlags;
+            let generatedNameSet: Map<string>;
             let currentSourceFile: SourceFile;
             let currentText: string;
+            let currentFileIdentifiers: Map<string>;
             let extendsEmitted: boolean;
             let decorateEmitted: boolean;
             let paramEmitted: boolean;
@@ -169,6 +329,8 @@ const _super = (function (geti, seti) {
 
             function doPrint(jsFilePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
                 sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit);
+                generatedNameSet = {};
+
                 isOwnFileEmit = !isBundledEmit;
 
                 // Emit helpers from all the files
@@ -213,7 +375,6 @@ const _super = (function (geti, seti) {
                 identifierSubstitution = undefined;
                 onBeforeEmitNode = undefined;
                 onAfterEmitNode = undefined;
-                isUniqueName = undefined;
                 temporaryVariables = undefined;
                 tempFlags = TempFlags.Auto;
                 currentSourceFile = undefined;
@@ -236,13 +397,13 @@ const _super = (function (geti, seti) {
                 identifierSubstitution = context.identifierSubstitution;
                 onBeforeEmitNode = context.onBeforeEmitNode;
                 onAfterEmitNode = context.onAfterEmitNode;
-                isUniqueName = context.isUniqueName;
                 return printSourceFile;
             }
 
             function printSourceFile(node: SourceFile) {
                 currentSourceFile = node;
                 currentText = node.text;
+                currentFileIdentifiers = node.identifiers;
                 sourceMap.setSourceFile(node);
                 comments.setSourceFile(node);
                 emitWorker(node);
@@ -659,13 +820,16 @@ const _super = (function (geti, seti) {
             //
 
             function emitIdentifier(node: Identifier) {
-                if (node.text === undefined) {
-                    // Emit a temporary variable name for this node.
-                    const nodeId = getOriginalNodeId(node);
-                    const text = temporaryVariables[nodeId] || (temporaryVariables[nodeId] = makeTempVariableName(tempKindToFlags(node.tempKind)));
-                    write(text);
+                switch (node.tempKind) {
+                    case GeneratedIdentifierKind.Auto:
+                        return emitAutoIdentifier(node);
+                    case GeneratedIdentifierKind.Loop:
+                        return emitLoopIdentifier(node);
+                    case GeneratedIdentifierKind.Unique:
+                        return emitUniqueIdentifier(node);
                 }
-                else if (nodeIsSynthesized(node) || !node.parent) {
+
+                if (nodeIsSynthesized(node) || !node.parent) {
                     if (getNodeEmitFlags(node) & NodeEmitFlags.UMDDefine) {
                         writeLines(umdHelper);
                     }
@@ -678,6 +842,24 @@ const _super = (function (geti, seti) {
                 }
             }
 
+            function emitAutoIdentifier(node: Identifier) {
+                const nodeId = getOriginalNodeId(node);
+                const text = temporaryVariables[nodeId] || (temporaryVariables[nodeId] = makeTempVariableName(TempFlags.Auto));
+                write(text);
+            }
+
+            function emitLoopIdentifier(node: Identifier) {
+                const nodeId = getOriginalNodeId(node);
+                const text = temporaryVariables[nodeId] || (temporaryVariables[nodeId] = makeTempVariableName(TempFlags._i));
+                write(text);
+            }
+
+            function emitUniqueIdentifier(node: Identifier) {
+                const nodeId = getOriginalNodeId(node);
+                const text = temporaryVariables[nodeId] || (temporaryVariables[nodeId] = makeUniqueName(node.text));
+                write(text);
+            }
+
             //
             // Names
             //
@@ -2368,12 +2550,18 @@ const _super = (function (geti, seti) {
                     && rangeEndIsOnSameLineAsRangeStart(block, block);
             }
 
-            function tempKindToFlags(kind: TempVariableKind) {
-                return kind === TempVariableKind.Loop
+            function tempKindToFlags(kind: GeneratedIdentifierKind) {
+                return kind === GeneratedIdentifierKind.Loop
                     ? TempFlags._i
                     : TempFlags.Auto;
             }
 
+            function isUniqueName(name: string): boolean {
+                return !resolver.hasGlobalName(name) &&
+                    !hasProperty(currentFileIdentifiers, name) &&
+                    !hasProperty(generatedNameSet, name);
+            }
+
             /**
             * Return the next available name in the pattern _a ... _z, _0, _1, ...
             * TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name.
@@ -2401,6 +2589,29 @@ const _super = (function (geti, seti) {
                     }
                 }
             }
+
+            /**
+             * Generate a name that is unique within the current file and doesn't conflict with any names
+             * in global scope. The name is formed by adding an '_n' suffix to the specified base name,
+             * where n is a positive integer. Note that names generated by makeTempVariableName and
+             * makeUniqueName are guaranteed to never conflict.
+             */
+            function makeUniqueName(baseName: string): string {
+                // Find the first unique 'name_n', where n is a positive number
+                if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) {
+                    baseName += "_";
+                }
+
+                let i = 1;
+                while (true) {
+                    const generatedName = baseName + i;
+                    if (isUniqueName(generatedName)) {
+                        return generatedNameSet[generatedName] = generatedName;
+                    }
+
+                    i++;
+                }
+            }
         }
     }
 
diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts
index 913fd95d55dfc..1a590f3011be8 100644
--- a/src/compiler/transformer.ts
+++ b/src/compiler/transformer.ts
@@ -3,6 +3,7 @@
 /// <reference path="transformers/jsx.ts" />
 /// <reference path="transformers/es7.ts" />
 /// <reference path="transformers/es6.ts" />
+/// <reference path="transformers/generators.ts" />
 /// <reference path="transformers/module/module.ts" />
 /// <reference path="transformers/module/system.ts" />
 /// <reference path="transformers/module/es6.ts" />
@@ -40,6 +41,7 @@ namespace ts {
 
         if (languageVersion < ScriptTarget.ES6) {
             transformers.push(transformES6);
+            transformers.push(transformGenerators);
         }
 
         return transformers;
@@ -55,7 +57,6 @@ namespace ts {
      */
     export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformers: Transformer[]) {
         const nodeToGeneratedName: Identifier[] = [];
-        const generatedNameSet: Map<string> = {};
         const nodeEmitFlags: NodeEmitFlags[] = [];
         const lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
         const lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
@@ -72,10 +73,8 @@ namespace ts {
             getEmitResolver: () => resolver,
             getNodeEmitFlags,
             setNodeEmitFlags,
-            isUniqueName,
             getGeneratedNameForNode,
             nodeHasGeneratedName,
-            makeUniqueName,
             hoistVariableDeclaration,
             hoistFunctionDeclaration,
             startLexicalEnvironment,
@@ -151,28 +150,28 @@ namespace ts {
             return node;
         }
 
-        /**
-         * Generate a name that is unique within the current file and doesn't conflict with any names
-         * in global scope. The name is formed by adding an '_n' suffix to the specified base name,
-         * where n is a positive integer. Note that names generated by makeTempVariableName and
-         * makeUniqueName are guaranteed to never conflict.
-         */
-        function makeUniqueName(baseName: string): Identifier {
-            // Find the first unique 'name_n', where n is a positive number
-            if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) {
-                baseName += "_";
-            }
-
-            let i = 1;
-            while (true) {
-                const generatedName = baseName + i;
-                if (isUniqueName(generatedName)) {
-                    return createIdentifier(generatedNameSet[generatedName] = generatedName);
-                }
-
-                i++;
-            }
-        }
+        // /**
+        //  * Generate a name that is unique within the current file and doesn't conflict with any names
+        //  * in global scope. The name is formed by adding an '_n' suffix to the specified base name,
+        //  * where n is a positive integer. Note that names generated by makeTempVariableName and
+        //  * makeUniqueName are guaranteed to never conflict.
+        //  */
+        // function makeUniqueName(baseName: string): Identifier {
+        //     // Find the first unique 'name_n', where n is a positive number
+        //     if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) {
+        //         baseName += "_";
+        //     }
+
+        //     let i = 1;
+        //     while (true) {
+        //         const generatedName = baseName + i;
+        //         if (isUniqueName(generatedName)) {
+        //             return createIdentifier(generatedNameSet[generatedName] = generatedName);
+        //         }
+
+        //         i++;
+        //     }
+        // }
 
         /**
          * Gets the generated name for a node.
@@ -190,14 +189,14 @@ namespace ts {
             return nodeToGeneratedName[id] !== undefined;
         }
 
-        /**
-         * Tests whether the provided name is unique.
-         */
-        function isUniqueName(name: string): boolean {
-            return !resolver.hasGlobalName(name)
-                && !hasProperty(currentSourceFile.identifiers, name)
-                && !hasProperty(generatedNameSet, name);
-        }
+        // /**
+        //  * Tests whether the provided name is unique.
+        //  */
+        // function isUniqueName(name: string): boolean {
+        //     return !resolver.hasGlobalName(name)
+        //         && !hasProperty(currentSourceFile.identifiers, name)
+        //         && !hasProperty(generatedNameSet, name);
+        // }
 
         /**
          * Tests whether the provided name is unique within a container.
@@ -221,7 +220,7 @@ namespace ts {
         function generateNameForNode(node: Node): Identifier {
             switch (node.kind) {
                 case SyntaxKind.Identifier:
-                    return makeUniqueName((<Identifier>node).text);
+                    return createUniqueName((<Identifier>node).text);
                 case SyntaxKind.ModuleDeclaration:
                 case SyntaxKind.EnumDeclaration:
                     return generateNameForModuleOrEnum(<ModuleDeclaration | EnumDeclaration>node);
@@ -244,7 +243,7 @@ namespace ts {
         function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) {
             const name = node.name;
             // Use module/enum name itself if it is unique, otherwise make a unique variation
-            return isUniqueLocalName(name.text, node) ? name : makeUniqueName(name.text);
+            return isUniqueLocalName(name.text, node) ? name : createUniqueName(name.text);
         }
 
         function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) {
@@ -252,15 +251,15 @@ namespace ts {
             const baseName = expr.kind === SyntaxKind.StringLiteral
                 ? escapeIdentifier(makeIdentifierFromModuleName((<LiteralExpression>expr).text))
                 : "module";
-            return makeUniqueName(baseName);
+            return createUniqueName(baseName);
         }
 
         function generateNameForExportDefault() {
-            return makeUniqueName("default");
+            return createUniqueName("default");
         }
 
         function generateNameForClassExpression() {
-            return makeUniqueName("class");
+            return createUniqueName("class");
         }
 
         /**
diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts
index 36b95812ae746..ad73d3c4180b8 100644
--- a/src/compiler/transformers/es6.ts
+++ b/src/compiler/transformers/es6.ts
@@ -6,7 +6,6 @@ namespace ts {
     export function transformES6(context: TransformationContext) {
         const {
             getGeneratedNameForNode,
-            makeUniqueName,
             startLexicalEnvironment,
             endLexicalEnvironment,
             hoistVariableDeclaration,
@@ -399,14 +398,14 @@ namespace ts {
             addNode(statements,
                 createIf(
                     createStrictEquality(
-                        getSynthesizedNode(name),
+                        getSynthesizedClone(name),
                         createVoidZero()
                     ),
                     setNodeEmitFlags(
                         createBlock([
                             createStatement(
                                 createAssignment(
-                                    getSynthesizedNode(name),
+                                    getSynthesizedClone(name),
                                     visitNode(initializer, visitor, isExpression)
                                 )
                             )
@@ -431,7 +430,7 @@ namespace ts {
                 return;
             }
 
-            const name = getSynthesizedNode(<Identifier>parameter.name);
+            const name = getSynthesizedClone(<Identifier>parameter.name);
             const restIndex = node.parameters.length - 1;
             const temp = createLoopVariable();
 
@@ -611,7 +610,7 @@ namespace ts {
             return setOriginalNode(
                 createFunctionDeclaration(
                     /*modifiers*/ undefined,
-                    node.asteriskToken, // TODO(rbuckton): downlevel support for generators
+                    node.asteriskToken,
                     node.name,
                     visitNodes(node.parameters, visitor, isParameter),
                     transformFunctionBody(node),
@@ -779,6 +778,119 @@ namespace ts {
             return visitEachChild(node, visitor, context);
         }
 
+        // // TODO(rbuckton): Switch to using __values helper for for..of?
+        // function visitForOfStatement2(node: ForOfStatement): OneOrMany<Statement> {
+        //     // [source]
+        //     //  for (let v of expr) {
+        //     //  }
+        //     //
+        //     // [output]
+        //     //  var __values = ...;
+        //     //  try {
+        //     //      for (_a = __values(expr), _b = _a.next(); !_b.done || (_a = void 0); _b = _a.next()) {
+        //     //          var v = _b.value;
+        //     //      }
+        //     //  }
+        //     //  finally {
+        //     //      if (_a && typeof _a.return === "function") _a.return();
+        //     //  }
+        //     //  var _a, b;
+
+        //     const iterator = createTempVariable();
+        //     const iteratorResult = createTempVariable();
+        //     hoistVariableDeclaration(iterator);
+        //     hoistVariableDeclaration(iteratorResult);
+        //     const expression = visitNode(node.expression, visitor, isExpression);
+        //     const initializer = node.initializer;
+        //     const statements: Statement[] = [];
+        //     if (isVariableDeclarationList(initializer)) {
+        //         const variable = getMutableClone(initializer.declarations[0]);
+        //         variable.initializer = createPropertyAccess(iteratorResult, "value");
+        //         statements.push(
+        //             createVariableStatement(
+        //                 /*modifiers*/ undefined,
+        //                 createVariableDeclarationList(
+        //                     isBindingPattern(variable.name)
+        //                         ? flattenVariableDestructuring(variable, /*value*/ undefined, visitor)
+        //                         : [variable]
+        //                 )
+        //             )
+        //         );
+        //     }
+        //     else {
+        //         statements.push(
+        //             createStatement(
+        //                 createAssignment(
+        //                     <Expression>node.initializer,
+        //                     createPropertyAccess(iteratorResult, "value")
+        //                 )
+        //             )
+        //         );
+        //     }
+
+        //     if (isBlock(node.statement)) {
+        //         addNodes(statements, visitNodes((<Block>node.statement).statements, visitor, isStatement));
+        //     }
+        //     else {
+        //         addNodes(statements, visitNodes(createNodeArray([node.statement]), visitor, isStatement));
+        //     }
+
+        //     return createTryFinally(
+        //         createBlock([
+        //             createFor(
+        //                 createComma(
+        //                     createAssignment(
+        //                         iterator,
+        //                         createCall(
+        //                             createIdentifier("__values"),
+        //                             [expression]
+        //                         )
+        //                     ),
+        //                     createAssignment(
+        //                         iteratorResult,
+        //                         createCall(
+        //                             createPropertyAccess(iterator, "next"),
+        //                             []
+        //                         )
+        //                     )
+        //                 ),
+        //                 createLogicalOr(
+        //                     createLogicalNot(createPropertyAccess(iteratorResult, "done")),
+        //                     createAssignment(iterator, createVoidZero())
+        //                 ),
+        //                 createAssignment(
+        //                     iteratorResult,
+        //                     createCall(
+        //                         createPropertyAccess(iterator, "next"),
+        //                         []
+        //                     )
+        //                 ),
+        //                 createBlock(statements)
+        //             )
+        //         ]),
+        //         createBlock([
+        //             createIf(
+        //                 createLogicalAnd(
+        //                     iterator,
+        //                     createStrictEquality(
+        //                         createTypeOf(
+        //                             createPropertyAccess(iterator, "return")
+        //                         ),
+        //                         createLiteral("function")
+        //                     )
+        //                 ),
+        //                 createStatement(
+        //                     createCall(
+        //                         createPropertyAccess(iterator, "return"),
+        //                         [],
+        //                         /*location*/ node.expression
+        //                     )
+        //                 )
+        //             )
+        //         ])
+        //     );
+        // }
+
         function visitForOfStatement(node: ForOfStatement): Statement {
             // TODO: Convert loop body for block scoped bindings.
 
@@ -814,7 +926,7 @@ namespace ts {
             // we don't want to emit a temporary variable for the RHS, just use it directly.
             const counter = createLoopVariable();
             const rhsReference = expression.kind === SyntaxKind.Identifier
-                ? makeUniqueName((<Identifier>expression).text)
+                ? createUniqueName((<Identifier>expression).text)
                 : createTempVariable();
 
             // Initialize LHS
@@ -906,22 +1018,24 @@ namespace ts {
             );
         }
 
-        function visitObjectLiteralExpression(node: ObjectLiteralExpression): LeftHandSideExpression {
+        function visitObjectLiteralExpression(node: ObjectLiteralExpression): Expression {
             // We are here because a ComputedPropertyName was used somewhere in the expression.
             const properties = node.properties;
             const numProperties = properties.length;
 
             // Find the first computed property.
             // Everything until that point can be emitted as part of the initial object literal.
-            let numInitialNonComputedProperties = numProperties;
-            for (let i = 0, n = properties.length; i < n; i++) {
-                if (properties[i].name.kind === SyntaxKind.ComputedPropertyName) {
-                    numInitialNonComputedProperties = i;
+            let numInitialProperties = numProperties;
+            for (let i = 0; i < numProperties; i++) {
+                const property = properties[i];
+                if (property.transformFlags & TransformFlags.ContainsYield
+                    || property.name.kind === SyntaxKind.ComputedPropertyName) {
+                    numInitialProperties = i;
                     break;
                 }
             }
 
-            Debug.assert(numInitialNonComputedProperties !== numProperties);
+            Debug.assert(numInitialProperties !== numProperties);
 
             // For computed properties, we need to create a unique handle to the object
             // literal so we can modify it without risking internal assignments tainting the object.
@@ -933,27 +1047,27 @@ namespace ts {
             addNode(expressions,
                 createAssignment(
                     temp,
-                    setMultiLine(
-                        createObjectLiteral(
-                            visitNodes(properties, visitor, isObjectLiteralElement, 0, numInitialNonComputedProperties)
-                        ),
+                    createObjectLiteral(
+                        visitNodes(properties, visitor, isObjectLiteralElement, 0, numInitialProperties),
+                        /*location*/ undefined,
                         node.multiLine
                     )
                 ),
                 node.multiLine
             );
 
-            addObjectLiteralMembers(expressions, node, temp, numInitialNonComputedProperties);
+            addObjectLiteralMembers(expressions, node, temp, numInitialProperties);
 
             // We need to clone the temporary identifier so that we can write it on a
             // new line
             addNode(expressions, cloneNode(temp), node.multiLine);
-            return createParen(inlineExpressions(expressions));
+            return inlineExpressions(expressions);
         }
 
-        function addObjectLiteralMembers(expressions: Expression[], node: ObjectLiteralExpression, receiver: Identifier, numInitialNonComputedProperties: number) {
+        function addObjectLiteralMembers(expressions: Expression[], node: ObjectLiteralExpression, receiver: Identifier, start: number) {
             const properties = node.properties;
-            for (let i = numInitialNonComputedProperties, len = properties.length; i < len; i++) {
+            const numProperties = properties.length;
+            for (let i = start; i < numProperties; i++) {
                 const property = properties[i];
                 switch (property.kind) {
                     case SyntaxKind.GetAccessor:
@@ -1001,7 +1115,7 @@ namespace ts {
                     receiver,
                     visitNode(property.name, visitor, isPropertyName)
                 ),
-                getSynthesizedNode(property.name),
+                getSynthesizedClone(property.name),
                 /*location*/ property
             );
         }
@@ -1032,7 +1146,7 @@ namespace ts {
         function visitShorthandPropertyAssignment(node: ShorthandPropertyAssignment): ObjectLiteralElement {
             return createPropertyAssignment(
                 node.name,
-                getSynthesizedNode(node.name),
+                getSynthesizedClone(node.name),
                 /*location*/ node
             );
         }
@@ -1188,7 +1302,7 @@ namespace ts {
                         addNode(segments,
                             setMultiLine(
                                 createArrayLiteral(
-                                    visitNodes(elements, visitor, isExpression, start, i)
+                                    visitNodes(elements, visitor, isExpression, start, i - start)
                                 ),
                                 multiLine
                             )
@@ -1204,7 +1318,7 @@ namespace ts {
                 addNode(segments,
                     setMultiLine(
                         createArrayLiteral(
-                            visitNodes(elements, visitor, isExpression, start, length)
+                            visitNodes(elements, visitor, isExpression, start, length - start)
                         ),
                         multiLine
                     )
@@ -1469,7 +1583,7 @@ namespace ts {
         }
 
         function getDeclarationName(node: ClassExpression | ClassDeclaration | FunctionDeclaration) {
-            return node.name ? getSynthesizedNode(node.name) : getGeneratedNameForNode(node);
+            return node.name ? getSynthesizedClone(node.name) : getGeneratedNameForNode(node);
         }
 
         function getClassMemberPrefix(node: ClassExpression | ClassDeclaration, member: ClassElement) {
diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts
new file mode 100644
index 0000000000000..98605fa2f8609
--- /dev/null
+++ b/src/compiler/transformers/generators.ts
@@ -0,0 +1,2957 @@
+/// <reference path="../factory.ts" />
+/// <reference path="../visitor.ts" />
+
+// Transforms generator functions into a compatible ES5 representation with similar runtime
+// semantics. This is accomplished by first transforming the body of each generator
+// function into an intermediate representation that is the compiled into a JavaScript
+// switch statement.
+//
+// Many functions in this transformer will contain comments indicating the expected
+// intermediate representation. For illustrative purposes, the following intermediate
+// language is used to define this intermediate representation:
+//
+//  .nop                            - Performs no operation.
+//  .local NAME, ...                - Define local variable declarations.
+//  .mark LABEL                     - Mark the location of a label.
+//  .br LABEL                       - Jump to a label. If jumping out of a protected
+//                                    region, all .finally blocks are executed.
+//  .brtrue LABEL, (x)              - Jump to a label IIF the expression `x` is truthy.
+//                                    If jumping out of a protected region, all .finally
+//                                    blocks are executed.
+//  .brfalse LABEL, (x)             - Jump to a label IIF the expression `x` is falsey.
+//                                    If jumping out of a protected region, all .finally
+//                                    blocks are executed.
+//  .yield RESUME, (x)              - Yield the value of the optional expression `x`.
+//                                    Resume at the label RESUME.
+//  .yieldstar RESUME, (x)          - Delegate yield to the value of the optional
+//                                    expression `x`. Resume at the label RESUME.
+//  .loop CONTINUE, BREAK           - Marks the beginning of a loop. Any "continue" or
+//                                    "break" abrupt completions jump to the CONTINUE or
+//                                    BREAK labels, respectively.
+//  .endloop                        - Marks the end of a loop.
+//  .with (x)                       - Marks the beginning of a WithStatement block, using
+//                                    the supplied expression.
+//  .endwith                        - Marks the end of a WithStatement.
+//  .switch                         - Marks the beginning of a SwitchStatement.
+//  .endswitch                      - Marks the end of a SwitchStatement.
+//  .labeled NAME                   - Marks the beginning of a LabeledStatement with the
+//                                    supplied name.
+//  .endlabeled                     - Marks the end of a LabeledStatement.
+//  .try TRY, CATCH, FINALLY, END   - Marks the beginning of a protected region, and the
+//                                    labels for each block.
+//  .catch (x)                      - Marks the beginning of a catch block.
+//  .finally                        - Marks the beginning of a finally block.
+//  .endfinally                     - Marks the end of a finally block.
+//  .endtry                         - Marks the end of a protected region.
+//  .throw (x)                      - Throws the value of the expression `x`.
+//  .return (x)                     - Returns the value of the expression `x`.
+//
+// In addition, the illustrative intermediate representation introduces some special
+// variables:
+//
+//  %sent%                          - Either returns the next value sent to the generator,
+//                                    returns the result of a delegated yield, or throws
+//                                    the exception sent to the generator.
+//  %error%                         - Returns the value of the current exception in a
+//                                    catch block.
+//
+// This intermediate representation is then compiled into JavaScript syntax. The resulting
+// compilation output looks something like the following:
+//
+//  function f() {
+//      var /*locals*/;
+//      /*functions*/
+//      return __generator(function (state) {
+//          switch (state.label) {
+//              /*cases per label*/
+//          }
+//      });
+//  }
+//
+// Each of the above instructions corresponds to JavaScript emit similar to the following:
+//
+//  .local NAME                   | var NAME;
+// -------------------------------|----------------------------------------------
+//  .mark LABEL                   | case LABEL:
+// -------------------------------|----------------------------------------------
+//  .br LABEL                     |     return [3 /*break*/, LABEL];
+// -------------------------------|----------------------------------------------
+//  .brtrue LABEL, (x)            |     if (x) return [3 /*break*/, LABEL];
+// -------------------------------|----------------------------------------------
+//  .brfalse LABEL, (x)           |     if (!(x)) return [3, /*break*/, LABEL];
+// -------------------------------|----------------------------------------------
+//  .yield RESUME, (x)            |     return [4 /*yield*/, x];
+//  .mark RESUME                  | case RESUME:
+//      a = %sent%;             |     a = state.sent();
+// -------------------------------|----------------------------------------------
+//  .yieldstar RESUME, (X)        |     return [5 /*yield**/, x];
+//  .mark RESUME                  | case RESUME:
+//      a = %sent%;             |     a = state.sent();
+// -------------------------------|----------------------------------------------
+//  .with (_a)                    |     with (_a) {
+//      a();                      |         a();
+//                                |     }
+//                                |     state.label = LABEL;
+//  .mark LABEL                   | case LABEL:
+//                                |     with (_a) {
+//      b();                      |         b();
+//                                |     }
+//  .endwith                      |
+// -------------------------------|----------------------------------------------
+//                                | case 0:
+//                                |     state.trys = [];
+//                                | ...
+//  .try TRY, CATCH, FINALLY, END |
+//  .mark TRY                     | case TRY:
+//                                |     state.trys.push([TRY, CATCH, FINALLY, END]);
+//  .nop                          |
+//      a();                      |     a();
+//  .br END                       |     return [3 /*break*/, END];
+//  .catch (e)                    |
+//  .mark CATCH                   | case CATCH:
+//                                |     e = state.error;
+//      b();                      |     b();
+//  .br END                       |     return [3 /*break*/, END];
+//  .finally                      |
+//  .mark FINALLY                 | case FINALLY:
+//      c();                      |     c();
+//  .endfinally                   |     return [7 /*endfinally*/];
+//  .endtry                       |
+//  .mark END                     | case END:
+
+/*@internal*/
+namespace ts {
+    type Label = number;
+
+    const enum OpCode {
+        Nop,                    // No operation, used to force a new case in the state machine
+        Statement,              // A regular javascript statement
+        Assign,                 // An assignment
+        Break,                  // A break instruction used to jump to a label
+        BreakWhenTrue,          // A break instruction used to jump to a label if a condition evaluates to true
+        BreakWhenFalse,         // A break instruction used to jump to a label if a condition evaluates to false
+        Yield,                  // A completion instruction for the `yield` keyword
+        YieldStar,              // A completion instruction for the `yield*` keyword
+        Return,                 // A completion instruction for the `return` keyword
+        Throw,                  // A completion instruction for the `throw` keyword
+        Endfinally              // Marks the end of a `finally` block
+    }
+
+    type OperationArguments =
+        [Label] |
+        [Label, Expression] |
+        [Statement] |
+        [Expression] |
+        [Expression, Expression];
+
+    // whether a generated code block is opening or closing at the current operation for a FunctionBuilder
+    const enum BlockAction {
+        Open,
+        Close,
+    }
+
+    // the kind for a generated code block in a FunctionBuilder
+    const enum CodeBlockKind {
+        Exception,
+        With,
+        Switch,
+        Loop,
+        Labeled
+    }
+
+    // the state for a generated code exception block
+    const enum ExceptionBlockState {
+        Try,
+        Catch,
+        Finally,
+        Done
+    }
+
+    // A generated code block
+    interface CodeBlock {
+        kind: CodeBlockKind;
+    }
+
+    // a generated exception block, used for 'try' statements
+    interface ExceptionBlock extends CodeBlock {
+        state: ExceptionBlockState;
+        startLabel: Label;
+        catchVariable?: Identifier;
+        catchLabel?: Label;
+        finallyLabel?: Label;
+        endLabel: Label;
+    }
+
+    // A generated code that tracks the target for 'break' statements in a LabeledStatement.
+    interface LabeledBlock extends CodeBlock {
+        labelText: string;
+        isScript: boolean;
+        breakLabel: Label;
+    }
+
+    // a generated block that tracks the target for 'break' statements in a 'switch' statement
+    interface SwitchBlock extends CodeBlock {
+        isScript: boolean;
+        breakLabel: Label;
+    }
+
+    // a generated block that tracks the targets for 'break' and 'continue' statements, used for iteration statements
+    interface LoopBlock extends CodeBlock {
+        continueLabel: Label;
+        isScript: boolean;
+        breakLabel: Label;
+    }
+
+    // a generated block associated with a 'with' statement
+    interface WithBlock extends CodeBlock {
+        expression: Identifier;
+        startLabel: Label;
+        endLabel: Label;
+    }
+
+    // NOTE: changes to this enum should be reflected in the __generator helper.
+    const enum Instruction {
+        Next = 0,
+        Throw = 1,
+        Return = 2,
+        Break = 3,
+        Yield = 4,
+        YieldStar = 5,
+        Catch = 6,
+        Endfinally = 7,
+    }
+
+    const instructionNames: Map<string> = {
+        [Instruction.Return]: "return",
+        [Instruction.Break]: "break",
+        [Instruction.Yield]: "yield",
+        [Instruction.YieldStar]: "yield*",
+        [Instruction.Endfinally]: "endfinally",
+    };
+
+    export function transformGenerators(context: TransformationContext) {
+        const {
+            getGeneratedNameForNode,
+            startLexicalEnvironment,
+            endLexicalEnvironment,
+            hoistFunctionDeclaration,
+            hoistVariableDeclaration,
+        } = context;
+
+        const resolver = context.getEmitResolver();
+        const previousExpressionSubstitution = context.expressionSubstitution;
+        context.expressionSubstitution = substituteExpression;
+
+        let renamedCatchVariables: Map<boolean>;
+        let renamedCatchVariableDeclarations: Map<Identifier>;
+
+        let inGeneratorFunctionBody: boolean;
+        let inStatementContainingYield: boolean;
+
+        // Indicates whether the builder contains any exception blocks.
+        let hasProtectedRegions: boolean;
+
+        // The following three arrays store information about generated code blocks.
+        // All three arrays are correlated by their index. This approach is used over allocating
+        // objects to store the same information to avoid GC overhead.
+        //
+        let blocks: CodeBlock[]; // Information about the code block
+        let blockOffsets: number[]; // The operation offset at which a code block begins or ends
+        let blockActions: BlockAction[]; // Whether the code block is opened or closed
+        let blockStack: CodeBlock[]; // A stack of currently open code blocks
+
+        // Labels are used to mark locations in the code that can be the target of a Break (jump)
+        // operation. These are translated into case clauses in a switch statement.
+        // The following two arrays are correlated by their index. This approach is used over
+        // allocating objects to store the same information to avoid GC overhead.
+        //
+        let labelOffsets: number[]; // The operation offset at which the label is defined.
+        let labelExpressions: LiteralExpression[][]; // The NumericLiteral nodes bound to each label.
+        let nextLabelId = 1; // The next label id to use.
+
+        // Operations store information about generated code for the function body. This
+        // Includes things like statements, assignments, breaks (jumps), and yields.
+        // The following three arrays are correlated by their index. This approach is used over
+        // allocating objects to store the same information to avoid GC overhead.
+        //
+        let operations: OpCode[]; // The operation to perform.
+        let operationArguments: OperationArguments[]; // The arguments to the operation.
+        let operationLocations: TextRange[]; // The source map location for the operation.
+
+        let state: Identifier; // The name of the state object used by the generator at runtime.
+
+        // The following variables store information used by the `build` function:
+        //
+        let blockIndex = 0; // The index of the current block.
+        let labelNumber = 0; // The current label number.
+        let lastOperationWasAbrupt: boolean; // Indicates whether the last operation was abrupt (break/continue).
+        let lastOperationWasCompletion: boolean; // Indicates whether the last operation was a completion (return/throw).
+        let clauses: CaseClause[]; // The case clauses generated for labels.
+        let statements: Statement[]; // The statements for the current label.
+        let exceptionBlockStack: ExceptionBlock[]; // A stack of containing exception blocks.
+        let currentExceptionBlock: ExceptionBlock; // The current exception block.
+        let withBlockStack: WithBlock[]; // A stack containing `with` blocks.
+
+        return transformSourceFile;
+
+        function transformSourceFile(node: SourceFile) {
+            if (node.transformFlags & TransformFlags.ContainsGenerators) {
+                return visitEachChild(node, visitor, context);
+            }
+
+            return node;
+        }
+
+        /**
+         * Visits a node.
+         *
+         * @param node The node to visit.
+         */
+        function visitor(node: Node): Node {
+            if (containsYield(node)) {
+                return visitJavaScriptContainingYield(node);
+            }
+            else if (inStatementContainingYield) {
+                return visitJavaScriptInStatementContainingYield(node);
+            }
+            else if (inGeneratorFunctionBody) {
+                return visitJavaScriptInGeneratorFunctionBody(node);
+            }
+            else if (node.transformFlags & TransformFlags.ContainsGenerators) {
+                return visitEachChild(node, visitor, context);
+            }
+            else {
+                return node;
+            }
+        }
+
+        /**
+         * Visits a node that contains a YieldExpression.
+         *
+         * @param node The node to visit.
+         */
+        function visitJavaScriptContainingYield(node: Node): Node {
+            switch (node.kind) {
+                case SyntaxKind.BinaryExpression:
+                    return visitBinaryExpression(<BinaryExpression>node);
+                case SyntaxKind.ConditionalExpression:
+                    return visitConditionalExpression(<ConditionalExpression>node);
+                case SyntaxKind.YieldExpression:
+                    return visitYieldExpression(<YieldExpression>node);
+                case SyntaxKind.ArrayLiteralExpression:
+                    return visitArrayLiteralExpression(<ArrayLiteralExpression>node);
+                case SyntaxKind.ObjectLiteralExpression:
+                    return visitObjectLiteralExpression(<ObjectLiteralExpression>node);
+                case SyntaxKind.ElementAccessExpression:
+                    return visitElementAccessExpression(<ElementAccessExpression>node);
+                case SyntaxKind.CallExpression:
+                    return visitCallExpression(<CallExpression>node);
+                case SyntaxKind.NewExpression:
+                    return visitNewExpression(<NewExpression>node);
+                default:
+                    return visitJavaScriptInStatementContainingYield(node);
+            }
+        }
+
+        /**
+         * Visits a node that is contained within a statement that contains yield.
+         *
+         * @param node The node to visit.
+         */
+        function visitJavaScriptInStatementContainingYield(node: Node): Node {
+            switch (node.kind) {
+                case SyntaxKind.DoStatement:
+                    return visitDoStatement(<DoStatement>node);
+                case SyntaxKind.WhileStatement:
+                    return visitWhileStatement(<WhileStatement>node);
+                case SyntaxKind.ForStatement:
+                    return visitForStatement(<ForStatement>node);
+                case SyntaxKind.ForInStatement:
+                    return visitForInStatement(<ForInStatement>node);
+                case SyntaxKind.SwitchStatement:
+                    return visitSwitchStatement(<SwitchStatement>node);
+                case SyntaxKind.LabeledStatement:
+                    return visitLabeledStatement(<LabeledStatement>node);
+                default:
+                    return visitJavaScriptInGeneratorFunctionBody(node);
+            }
+        }
+
+        /**
+         * Visits a node that is contained within a generator function.
+         *
+         * @param node The node to visit.
+         */
+        function visitJavaScriptInGeneratorFunctionBody(node: Node): Node {
+            switch (node.kind) {
+                case SyntaxKind.FunctionDeclaration:
+                    return visitFunctionDeclaration(<FunctionDeclaration>node);
+                case SyntaxKind.FunctionExpression:
+                    return visitFunctionExpression(<FunctionExpression>node);
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                    return visitAccessorDeclaration(<AccessorDeclaration>node);
+                default:
+                    if (node.transformFlags & TransformFlags.ContainsGenerators) {
+                        return visitEachChild(node, visitor, context);
+                    }
+                    else {
+                        return node;
+                    }
+            }
+        }
+
+        /**
+         * Visits a function declaration.
+         *
+         * This will be called when one of the following conditions are met:
+         * - The function declaration is a generator function.
+         * - The function declaration is contained within the body of a generator function.
+         *
+         * @param node The node to visit.
+         */
+        function visitFunctionDeclaration(node: FunctionDeclaration): Statement {
+            if (node.asteriskToken) {
+                node = setOriginalNode(
+                    createFunctionDeclaration(
+                        /*modifiers*/ undefined,
+                        /*asteriskToken*/ undefined,
+                        node.name,
+                        node.parameters,
+                        transformGeneratorFunctionBody(node.body),
+                        /*location*/ node
+                    ),
+                    node
+                );
+            }
+            else {
+                const savedInGeneratorFunctionBody = inGeneratorFunctionBody;
+                const savedInStatementContainingYield = inStatementContainingYield;
+                inGeneratorFunctionBody = false;
+                inStatementContainingYield = false;
+                node = visitEachChild(node, visitor, context);
+                inGeneratorFunctionBody = savedInGeneratorFunctionBody;
+                inStatementContainingYield = savedInStatementContainingYield;
+            }
+
+            if (inGeneratorFunctionBody) {
+                // Function declarations in a generator function body are hoisted
+                // to the top of the lexical scope and elided from the current statement.
+                hoistFunctionDeclaration(node);
+                return undefined;
+            }
+            else {
+                return node;
+            }
+        }
+
+        /**
+         * Visits a function expression.
+         *
+         * This will be called when one of the following conditions are met:
+         * - The function expression is a generator function.
+         * - The function expression is contained within the body of a generator function.
+         *
+         * @param node The node to visit.
+         */
+        function visitFunctionExpression(node: FunctionExpression): Expression {
+            if (node.asteriskToken) {
+                node = setOriginalNode(
+                    createFunctionExpression(
+                        /*asteriskToken*/ undefined,
+                        node.name,
+                        node.parameters,
+                        transformGeneratorFunctionBody(node.body),
+                        /*location*/ node
+                    ),
+                    node
+                );
+            }
+            else {
+                const savedInGeneratorFunctionBody = inGeneratorFunctionBody;
+                const savedInStatementContainingYield = inStatementContainingYield;
+                inGeneratorFunctionBody = false;
+                inStatementContainingYield = false;
+                node = visitEachChild(node, visitor, context);
+                inGeneratorFunctionBody = savedInGeneratorFunctionBody;
+                inStatementContainingYield = savedInStatementContainingYield;
+            }
+
+            return node;
+        }
+
+        /**
+         * Visits a get or set accessor declaration.
+         *
+         * This will be called when one of the following conditions are met:
+         * - The accessor is contained within the body of a generator function.
+         *
+         * @param node The node to visit.
+         */
+        function visitAccessorDeclaration(node: GetAccessorDeclaration) {
+            const savedInGeneratorFunctionBody = inGeneratorFunctionBody;
+            const savedInStatementContainingYield = inStatementContainingYield;
+            inGeneratorFunctionBody = false;
+            inStatementContainingYield = false;
+            node = visitEachChild(node, visitor, context);
+            inGeneratorFunctionBody = savedInGeneratorFunctionBody;
+            inStatementContainingYield = savedInStatementContainingYield;
+            return node;
+        }
+
+        /**
+         * Transforms the body of a generator function declaration.
+         *
+         * @param node The function body to transform.
+         */
+        function transformGeneratorFunctionBody(body: Block) {
+            // Save existing generator state
+            const statements: Statement[] = [];
+            const savedInGeneratorFunctionBody = inGeneratorFunctionBody;
+            const savedInStatementContainingYield = inStatementContainingYield;
+            const savedHasProtectedRegions = hasProtectedRegions;
+            const savedBlocks = blocks;
+            const savedBlockOffsets = blockOffsets;
+            const savedBlockActions = blockActions;
+            const savedLabelOffsets = labelOffsets;
+            const savedLabelExpressions = labelExpressions;
+            const savedNextLabelId = nextLabelId;
+            const savedOperations = operations;
+            const savedOperationArguments = operationArguments;
+            const savedOperationLocations = operationLocations;
+            const savedState = state;
+
+            // Initialize generator state
+            inGeneratorFunctionBody = true;
+            inStatementContainingYield = false;
+            hasProtectedRegions = false;
+            blocks = undefined;
+            blockOffsets = undefined;
+            blockActions = undefined;
+            labelOffsets = undefined;
+            labelExpressions = undefined;
+            nextLabelId = 1;
+            operations = undefined;
+            operationArguments = undefined;
+            operationLocations = undefined;
+            state = undefined;
+
+            // Build the generator
+            startLexicalEnvironment();
+
+            transformAndEmitStatements(body.statements);
+
+            const buildResult = build();
+            addNodes(statements, endLexicalEnvironment());
+            addNode(statements, createReturn(buildResult));
+
+            // Restore previous generator state
+            inGeneratorFunctionBody = savedInGeneratorFunctionBody;
+            inStatementContainingYield = savedInStatementContainingYield;
+            hasProtectedRegions = savedHasProtectedRegions;
+            blocks = savedBlocks;
+            blockOffsets = savedBlockOffsets;
+            blockActions = savedBlockActions;
+            labelOffsets = savedLabelOffsets;
+            labelExpressions = savedLabelExpressions;
+            nextLabelId = savedNextLabelId;
+            operations = savedOperations;
+            operationArguments = savedOperationArguments;
+            operationLocations = savedOperationLocations;
+            state = savedState;
+
+            return createBlock(statements, /*location*/ body, body.multiLine);
+        }
+
+        /**
+         * Visits a variable statement.
+         *
+         * This will be called when one of the following conditions are met:
+         * - The variable statement is contained within the body of a generator function.
+         *
+         * @param node The node to visit.
+         */
+        function visitVariableStatement(node: VariableStatement): Statement {
+            if (containsYield(node)) {
+                transformAndEmitVariableDeclarationList(node.declarationList);
+                return undefined;
+            }
+            else {
+                for (const variable of node.declarationList.declarations) {
+                    hoistVariableDeclaration(<Identifier>variable.name);
+                }
+
+                const variables = getInitializedVariables(node.declarationList);
+                if (variables.length === 0) {
+                    return undefined;
+                }
+
+                return createStatement(
+                    inlineExpressions(
+                        map(variables, transformInitializedVariable)
+                    )
+                );
+            }
+        }
+
+        /**
+         * Visits a binary expression.
+         *
+         * This will be called when one of the following conditions are met:
+         * - The node contains a YieldExpression.
+         *
+         * @param node The node to visit.
+         */
+        function visitBinaryExpression(node: BinaryExpression): Expression {
+            switch (getExpressionAssociativity(node)) {
+                case Associativity.Left:
+                    return visitLeftAssociativeBinaryExpression(node);
+                case Associativity.Right:
+                    return visitRightAssociativeBinaryExpression(node);
+                default:
+                    Debug.fail("Unknown associativity.");
+            }
+        }
+
+        /**
+         * Visits a right-associative binary expression containing `yield`.
+         *
+         * @param node The node to visit.
+         */
+        function visitRightAssociativeBinaryExpression(node: BinaryExpression) {
+            switch (node.left.kind) {
+                case SyntaxKind.PropertyAccessExpression: {
+                    // [source]
+                    //      a.b = yield;
+                    //
+                    // [intermediate]
+                    //  .local _a
+                    //      _a = a;
+                    //  .yield resumeLabel
+                    //  .mark resumeLabel
+                    //      _a.b = %sent%;
+
+                    const clone = getMutableClone(node);
+                    const propertyAccess = <PropertyAccessExpression>node.left;
+                    const propertyAccessClone = getMutableClone(propertyAccess);
+                    propertyAccessClone.expression = cacheExpression(visitNode(propertyAccess.expression, visitor, isLeftHandSideExpression));
+                    clone.left = propertyAccessClone;
+                    clone.right = visitNode(node.right, visitor, isExpression);
+                    return clone;
+                }
+                case SyntaxKind.ElementAccessExpression: {
+                    // [source]
+                    //      a[b] = yield;
+                    //
+                    // [intermediate]
+                    //  .local _a, _b
+                    //      _a = a;
+                    //      _b = b;
+                    //  .yield resumeLabel
+                    //  .mark resumeLabel
+                    //      _a[_b] = %sent%;
+
+                    const clone = getMutableClone(node);
+                    const elementAccess = <ElementAccessExpression>node.left;
+                    const elementAccessClone = getMutableClone(elementAccess);
+                    elementAccessClone.expression = cacheExpression(visitNode(elementAccess.expression, visitor, isLeftHandSideExpression));
+                    elementAccessClone.argumentExpression = cacheExpression(visitNode(elementAccess.argumentExpression, visitor, isExpression));
+                    clone.left = elementAccessClone;
+                    clone.right = visitNode(node.right, visitor, isExpression);
+                    return clone;
+                }
+            }
+            return visitEachChild(node, visitor, context);
+        }
+
+        function visitLeftAssociativeBinaryExpression(node: BinaryExpression) {
+            if (containsYield(node.right)) {
+                if (isLogicalOperator(node.operatorToken.kind)) {
+                    return visitLogicalBinaryExpression(node);
+                }
+                else if (node.operatorToken.kind === SyntaxKind.CommaToken) {
+                    return visitCommaExpression(node);
+                }
+
+                // [source]
+                //      a() + (yield) + c()
+                //
+                // [intermediate]
+                //  .local _a
+                //      _a = a();
+                //  .yield resumeLabel
+                //      _a + %sent% + c()
+
+                const clone = getMutableClone(node);
+                clone.left = cacheExpression(visitNode(node.left, visitor, isExpression));
+                clone.right = visitNode(node.right, visitor, isExpression);
+                return clone;
+            }
+
+            return visitEachChild(node, visitor, context);
+        }
+
+        /**
+         * Visits a logical binary expression containing `yield`.
+         *
+         * @param node A node to visit.
+         */
+        function visitLogicalBinaryExpression(node: BinaryExpression) {
+            // Logical binary expressions (`&&` and `||`) are shortcutting expressions and need
+            // to be transformed as such:
+            //
+            // [source]
+            //      x = a() && yield;
+            //
+            // [intermediate]
+            //  .local _a
+            //      _a = a();
+            //  .brfalse resultLabel, (_a)
+            //  .yield resumeLabel
+            //  .mark resumeLabel
+            //      _a = %sent%;
+            //  .mark resultLabel
+            //      x = _a;
+            //
+            // [source]
+            //      x = a() || yield;
+            //
+            // [intermediate]
+            //  .local _a
+            //      _a = a();
+            //  .brtrue resultLabel, (_a)
+            //  .yield resumeLabel
+            //  .mark resumeLabel
+            //      _a = %sent%;
+            //  .mark resultLabel
+            //      x = _a;
+
+            const resultLabel = defineLabel();
+            const resultLocal = declareLocal();
+
+            emitAssignment(resultLocal, visitNode(node.left, visitor, isExpression), /*location*/ node.left);
+            if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
+                // Logical `&&` shortcuts when the left-hand operand is falsey.
+                emitBreakWhenFalse(resultLabel, resultLocal, /*location*/ node.left);
+            }
+            else {
+                // Logical `||` shortcuts when the left-hand operand is truthy.
+                emitBreakWhenTrue(resultLabel, resultLocal, /*location*/ node.left);
+            }
+
+            emitAssignment(resultLocal, visitNode(node.right, visitor, isExpression), /*location*/ node.right);
+            markLabel(resultLabel);
+            return resultLocal;
+        }
+
+        /**
+         * Visits a comma expression containing `yield`.
+         *
+         * @param node The node to visit.
+         */
+        function visitCommaExpression(node: BinaryExpression) {
+            // [source]
+            //      x = a(), yield, b();
+            //
+            // [intermediate]
+            //      a();
+            //  .yield resumeLabel
+            //  .mark resumeLabel
+            //      x = %sent%, b();
+
+            let pendingExpressions: Expression[] = [];
+            visit(node.left);
+            visit(node.right);
+            return inlineExpressions(pendingExpressions);
+
+            function visit(node: Expression) {
+                if (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.CommaToken) {
+                    visit(node.left);
+                    visit(node.right);
+                }
+                else {
+                    if (containsYield(node) && pendingExpressions.length > 0) {
+                        emitWorker(OpCode.Statement, [createStatement(inlineExpressions(pendingExpressions))]);
+                        pendingExpressions = [];
+                    }
+
+                    pendingExpressions.push(visitNode(node, visitor, isExpression));
+                }
+            }
+        }
+
+        /**
+         * Visits a conditional expression containing `yield`.
+         *
+         * @param node The node to visit.
+         */
+        function visitConditionalExpression(node: ConditionalExpression): Expression {
+            // [source]
+            //      x = a() ? yield : b();
+            //
+            // [intermediate]
+            //  .local _a
+            //  .brfalse whenFalseLabel, (a())
+            //  .yield resumeLabel
+            //  .mark resumeLabel
+            //      _a = %sent%;
+            //  .br resultLabel
+            //  .mark whenFalseLabel
+            //      _a = b();
+            //  .mark resultLabel
+            //      x = _a;
+
+            // We only need to perform a specific transformation if a `yield` expression exists
+            // in either the `whenTrue` or `whenFalse` branches.
+            // A `yield` in the condition will be handled by the normal visitor.
+            if (containsYield(node.whenTrue) || containsYield(node.whenFalse)) {
+                const whenFalseLabel = defineLabel();
+                const resultLabel = defineLabel();
+                const resultLocal = declareLocal();
+                emitBreakWhenFalse(whenFalseLabel, visitNode(node.condition, visitor, isExpression), /*location*/ node.condition);
+                emitAssignment(resultLocal, visitNode(node.whenTrue, visitor, isExpression), /*location*/ node.whenTrue);
+                emitBreak(resultLabel);
+                markLabel(whenFalseLabel);
+                emitAssignment(resultLocal, visitNode(node.whenFalse, visitor, isExpression), /*location*/ node.whenFalse);
+                markLabel(resultLabel);
+                return resultLocal;
+            }
+
+            return visitEachChild(node, visitor, context);
+        }
+
+        /**
+         * Visits a `yield` expression.
+         *
+         * @param node The node to visit.
+         */
+        function visitYieldExpression(node: YieldExpression) {
+            // [source]
+            //      x = yield a();
+            //
+            // [intermediate]
+            //  .yield resumeLabel, (a())
+            //  .mark resumeLabel
+            //      x = %sent%;
+
+            const resumeLabel = defineLabel();
+            if (node.asteriskToken) {
+                emitYieldStar(
+                    createCall(
+                        createIdentifier("__values"),
+                        [visitNode(node.expression, visitor, isExpression)]
+                    ),
+                    /*location*/ node
+                );
+            }
+            else {
+                emitYield(visitNode(node.expression, visitor, isExpression), /*location*/ node);
+            }
+
+            markLabel(resumeLabel);
+            return createGeneratorResume();
+        }
+
+        /**
+         * Visits an ArrayLiteralExpression that contains a YieldExpression.
+         *
+         * @param node The node to visit.
+         */
+        function visitArrayLiteralExpression(node: ArrayLiteralExpression) {
+            return visitElements(node.elements, node.multiLine);
+        }
+
+        /**
+         * Visits an array of expressions containing one or more YieldExpression nodes
+         * and returns an expression for the resulting value.
+         *
+         * @param elements The elements to visit.
+         * @param multiLine Whether array literals created should be emitted on multiple lines.
+         */
+        function visitElements(elements: NodeArray<Expression>, multiLine: boolean) {
+            // [source]
+            //      ar = [1, yield, 2];
+            //
+            // [intermediate]
+            //  .local _a
+            //      _a = [1];
+            //  .yield resumeLabel
+            //  .mark resumeLabel
+            //      ar = _a.concat([%sent%, 2]);
+
+            const numInitialElements = countInitialNodesWithoutYield(elements);
+
+            const temp = declareLocal();
+            emitAssignment(temp,
+                createArrayLiteral(
+                    visitNodes(elements, visitor, isExpression, 0, numInitialElements)
+                )
+            );
+
+            const expressions = reduceLeft(elements, reduceElement, <Expression[]>[], numInitialElements);
+            return createArrayConcat(temp, [createArrayLiteral(expressions)]);
+
+            function reduceElement(expressions: Expression[], element: Expression) {
+                if (containsYield(element) && expressions.length > 0) {
+                    emitAssignment(
+                        temp,
+                        createArrayConcat(
+                            temp,
+                            [createArrayLiteral(expressions)]
+                        )
+                    );
+                    expressions = [];
+                }
+
+                expressions.push(visitNode(element, visitor, isExpression));
+                return expressions;
+            }
+        }
+
+        function visitObjectLiteralExpression(node: ObjectLiteralExpression) {
+            // [source]
+            //      o = {
+            //          a: 1,
+            //          b: yield,
+            //          c: 2
+            //      };
+            //
+            // [intermediate]
+            //  .local _a
+            //      _a = {
+            //          a: 1
+            //      };
+            //  .yield resumeLabel
+            //  .mark resumeLabel
+            //      o = (_a.b = %sent%,
+            //          _a.c = 2,
+            //          _a);
+
+            const properties = node.properties;
+            const numInitialProperties = countInitialNodesWithoutYield(node.properties);
+
+            const temp = declareLocal();
+            emitAssignment(temp,
+                createObjectLiteral(
+                    visitNodes(node.properties, visitor, isObjectLiteralElement, 0, numInitialProperties),
+                    /*location*/ undefined,
+                    node.multiLine
+                )
+            );
+
+            const expressions = reduceLeft(node.properties, reduceProperty, <Expression[]>[], numInitialProperties);
+            addNode(expressions, getMutableClone(temp), node.multiLine);
+            return inlineExpressions(expressions);
+
+            function reduceProperty(expressions: Expression[], property: ObjectLiteralElement) {
+                if (containsYield(property) && expressions.length > 0) {
+                    emitStatement(createStatement(inlineExpressions(expressions)));
+                    expressions = [];
+                }
+
+                const expression = createExpressionForObjectLiteralElement(node, property, temp);
+                addNode(expressions, visitNode(expression, visitor, isExpression), node.multiLine);
+                return expressions;
+            }
+        }
+
+        /**
+         * Visits an ElementAccessExpression that contains a YieldExpression.
+         *
+         * @param node The node to visit.
+         */
+        function visitElementAccessExpression(node: ElementAccessExpression) {
+            if (containsYield(node.argumentExpression)) {
+                // [source]
+                //      a = x[yield];
+                //
+                // [intermediate]
+                //  .local _a
+                //      _a = x;
+                //  .yield resumeLabel
+                //  .mark resumeLabel
+                //      a = _a[%sent%]
+
+                const clone = getMutableClone(node);
+                clone.expression = cacheExpression(visitNode(node.expression, visitor, isLeftHandSideExpression));
+                clone.argumentExpression = visitNode(node.argumentExpression, visitor, isExpression);
+                return clone;
+            }
+
+            return visitEachChild(node, visitor, context);
+        }
+
+        function visitCallExpression(node: CallExpression) {
+            if (forEach(node.arguments, containsYield)) {
+                // [source]
+                //      a.b(1, yield, 2);
+                //
+                // [intermediate]
+                //  .local _a, _b, _c
+                //      _b = (_a = a).b;
+                //      _c = [1];
+                //  .yield resumeLabel
+                //  .mark resumeLabel
+                //      _b.apply(_a, _c.concat([%sent%, 2]));
+
+                const { target, thisArg } = createCallBinding(node.expression);
+                return setOriginalNode(
+                    createFunctionApply(
+                        cacheExpression(visitNode(target, visitor, isLeftHandSideExpression)),
+                        thisArg,
+                        visitElements(node.arguments, /*multiLine*/ false),
+                        /*location*/ node
+                    ),
+                    node
+                );
+            }
+
+            return visitEachChild(node, visitor, context);
+        }
+
+        function visitNewExpression(node: NewExpression) {
+            if (forEach(node.arguments, containsYield)) {
+                // [source]
+                //      new a.b(1, yield, 2);
+                //
+                // [intermediate]
+                //  .local _a, _b, _c
+                //      _b = (_a = a.b).bind;
+                //      _c = [1];
+                //  .yield resumeLabel
+                //  .mark resumeLabel
+                //      new (_b.apply(_a, _c.concat([%sent%, 2])));
+
+                const { target, thisArg } = createCallBinding(createPropertyAccess(node.expression, "bind"));
+                return setOriginalNode(
+                    createNew(
+                        createFunctionApply(
+                            cacheExpression(visitNode(target, visitor, isExpression)),
+                            thisArg,
+                            visitElements(node.arguments, /*multiLine*/ false)
+                        ),
+                        [],
+                        /*location*/ node
+                    ),
+                    node
+                );
+            }
+            return visitEachChild(node, visitor, context);
+        }
+
+        function transformAndEmitStatements(statements: Statement[]) {
+            for (const statement of statements) {
+                transformAndEmitStatement(statement);
+            }
+        }
+
+        function transformAndEmitEmbeddedStatement(node: Statement) {
+            if (isBlock(node)) {
+                transformAndEmitStatements(node.statements);
+            }
+            else {
+                transformAndEmitStatement(node);
+            }
+        }
+
+        function transformAndEmitStatement(node: Statement): void {
+            const savedInStatementContainingYield = inStatementContainingYield;
+            if (!inStatementContainingYield) {
+                inStatementContainingYield = containsYield(node);
+            }
+
+            transformAndEmitStatementWorker(node);
+            inStatementContainingYield = savedInStatementContainingYield;
+        }
+
+        function transformAndEmitStatementWorker(node: Statement): void {
+            switch (node.kind) {
+                case SyntaxKind.Block:
+                    return transformAndEmitBlock(<Block>node);
+                case SyntaxKind.ExpressionStatement:
+                    return transformAndEmitExpressionStatement(<ExpressionStatement>node);
+                case SyntaxKind.IfStatement:
+                    return transformAndEmitIfStatement(<IfStatement>node);
+                case SyntaxKind.DoStatement:
+                    return transformAndEmitDoStatement(<DoStatement>node);
+                case SyntaxKind.WhileStatement:
+                    return transformAndEmitWhileStatement(<WhileStatement>node);
+                case SyntaxKind.ForStatement:
+                    return transformAndEmitForStatement(<ForStatement>node);
+                case SyntaxKind.ForInStatement:
+                    return transformAndEmitForInStatement(<ForInStatement>node);
+                case SyntaxKind.ContinueStatement:
+                    return transformAndEmitContinueStatement(<ContinueStatement>node);
+                case SyntaxKind.BreakStatement:
+                    return transformAndEmitBreakStatement(<BreakStatement>node);
+                case SyntaxKind.ReturnStatement:
+                    return transformAndEmitReturnStatement(<ReturnStatement>node);
+                case SyntaxKind.WithStatement:
+                    return transformAndEmitWithStatement(<WithStatement>node);
+                case SyntaxKind.SwitchStatement:
+                    return transformAndEmitSwitchStatement(<SwitchStatement>node);
+                case SyntaxKind.LabeledStatement:
+                    return transformAndEmitLabeledStatement(<LabeledStatement>node);
+                case SyntaxKind.ThrowStatement:
+                    return transformAndEmitThrowStatement(<ThrowStatement>node);
+                case SyntaxKind.TryStatement:
+                    return transformAndEmitTryStatement(<TryStatement>node);
+                default:
+                    return emitStatement(visitEachChild(node, visitor, context));
+            }
+        }
+
+        function transformAndEmitBlock(node: Block): void {
+            if (containsYield(node)) {
+                transformAndEmitStatements(node.statements);
+            }
+            else {
+                emitStatement(visitNode(node, visitor, isStatement));
+            }
+        }
+
+        function transformAndEmitExpressionStatement(node: ExpressionStatement) {
+            emitStatement(visitNode(node, visitor, isStatement));
+        }
+
+        function transformAndEmitVariableDeclarationList(node: VariableDeclarationList): VariableDeclarationList {
+            for (const variable of node.declarations) {
+                hoistVariableDeclaration(<Identifier>variable.name);
+            }
+
+            const variables = getInitializedVariables(node);
+            const numVariables = variables.length;
+            let variablesWritten = 0;
+            let pendingExpressions: Expression[] = [];
+            while (variablesWritten < numVariables) {
+                for (let i = variablesWritten; i < numVariables; i++) {
+                    const variable = variables[i];
+                    if (containsYield(variable.initializer) && pendingExpressions.length > 0) {
+                        break;
+                    }
+
+                    pendingExpressions.push(transformInitializedVariable(variable));
+                }
+
+                if (pendingExpressions.length) {
+                    emitStatement(createStatement(inlineExpressions(pendingExpressions)));
+                    variablesWritten += pendingExpressions.length;
+                    pendingExpressions = [];
+                }
+            }
+
+            return undefined;
+        }
+
+        function transformInitializedVariable(node: VariableDeclaration) {
+            return createAssignment(
+                <Identifier>getSynthesizedClone(node.name),
+                visitNode(node.initializer, visitor, isExpression)
+            );
+        }
+
+        function transformAndEmitIfStatement(node: IfStatement) {
+            if (containsYield(node)) {
+                // [source]
+                //      if (x)
+                //          /*thenStatement*/
+                //      else
+                //          /*elseStatement*/
+                //
+                // [intermediate]
+                //  .brfalse elseLabel, (x)
+                //      /*thenStatement*/
+                //  .br endLabel
+                //  .mark elseLabel
+                //      /*elseStatement*/
+                //  .mark endLabel
+
+                if (containsYield(node.thenStatement) || containsYield(node.elseStatement)) {
+                    const endLabel = defineLabel();
+                    const elseLabel = node.elseStatement ? defineLabel() : undefined;
+                    emitBreakWhenFalse(node.elseStatement ? elseLabel : endLabel, visitNode(node.expression, visitor, isExpression));
+                    transformAndEmitEmbeddedStatement(node.thenStatement);
+                    if (node.elseStatement) {
+                        emitBreak(endLabel);
+                        markLabel(elseLabel);
+                        transformAndEmitEmbeddedStatement(node.elseStatement);
+                    }
+                    markLabel(endLabel);
+                }
+                else {
+                    emitStatement(visitNode(node, visitor, isStatement));
+                }
+            }
+            else {
+                emitStatement(visitNode(node, visitor, isStatement));
+            }
+        }
+
+        function transformAndEmitDoStatement(node: DoStatement) {
+            if (containsYield(node)) {
+                // [source]
+                //      do {
+                //          /*body*/
+                //      }
+                //      while (i < 10);
+                //
+                // [intermediate]
+                //  .loop conditionLabel, endLabel
+                //  .mark loopLabel
+                //      /*body*/
+                //  .mark conditionLabel
+                //  .brtrue loopLabel, (i < 10)
+                //  .endloop
+                //  .mark endLabel
+
+                const conditionLabel = defineLabel();
+                const loopLabel = defineLabel();
+                beginLoopBlock(/*continueLabel*/ conditionLabel);
+                markLabel(loopLabel);
+                transformAndEmitEmbeddedStatement(node.statement);
+                markLabel(conditionLabel);
+                emitBreakWhenTrue(loopLabel, visitNode(node.expression, visitor, isExpression));
+                endLoopBlock();
+            }
+            else {
+                emitStatement(visitNode(node, visitor, isStatement));
+            }
+        }
+
+        function visitDoStatement(node: DoStatement) {
+            if (inStatementContainingYield) {
+                beginScriptLoopBlock();
+                node = visitEachChild(node, visitor, context);
+                endLoopBlock();
+                return node;
+            }
+            else {
+                return visitEachChild(node, visitor, context);
+            }
+        }
+
+        function transformAndEmitWhileStatement(node: WhileStatement) {
+            if (containsYield(node)) {
+                // [source]
+                //      while (i < 10) {
+                //          /*body*/
+                //      }
+                //
+                // [intermediate]
+                //  .loop loopLabel, endLabel
+                //  .mark loopLabel
+                //  .brfalse endLabel, (i < 10)
+                //      /*body*/
+                //  .br loopLabel
+                //  .endloop
+                //  .mark endLabel
+
+                const loopLabel = defineLabel();
+                const endLabel = beginLoopBlock(loopLabel);
+                markLabel(loopLabel);
+                emitBreakWhenFalse(endLabel, visitNode(node.expression, visitor, isExpression));
+                transformAndEmitEmbeddedStatement(node.statement);
+                emitBreak(loopLabel);
+                endLoopBlock();
+            }
+            else {
+                emitStatement(visitNode(node, visitor, isStatement));
+            }
+        }
+
+        function visitWhileStatement(node: WhileStatement) {
+            if (inStatementContainingYield) {
+                beginScriptLoopBlock();
+                node = visitEachChild(node, visitor, context);
+                endLoopBlock();
+                return node;
+            }
+            else {
+                return visitEachChild(node, visitor, context);
+            }
+        }
+
+        function transformAndEmitForStatement(node: ForStatement) {
+            if (containsYield(node)) {
+                // [source]
+                //      for (var i = 0; i < 10; i++) {
+                //          /*body*/
+                //      }
+                //
+                // [intermediate]
+                //  .local i
+                //      i = 0;
+                //  .loop incrementLabel, endLoopLabel
+                //  .mark conditionLabel
+                //  .brfalse endLoopLabel, (i < 10)
+                //      /*body*/
+                //  .mark incrementLabel
+                //      i++;
+                //  .br conditionLabel
+                //  .endloop
+                //  .mark endLoopLabel
+
+                const conditionLabel = defineLabel();
+                const incrementLabel = defineLabel();
+                const endLabel = beginLoopBlock(incrementLabel);
+                if (node.initializer) {
+                    const initializer = node.initializer;
+                    if (isVariableDeclarationList(initializer)) {
+                        transformAndEmitVariableDeclarationList(initializer);
+                    }
+                    else {
+                        emitStatement(
+                            createStatement(
+                                visitNode(initializer, visitor, isExpression),
+                                /*location*/ initializer
+                            )
+                        );
+                    }
+                }
+
+                markLabel(conditionLabel);
+                if (node.condition) {
+                    emitBreakWhenFalse(endLabel, visitNode(node.condition, visitor, isExpression));
+                }
+
+                transformAndEmitEmbeddedStatement(node.statement);
+
+                markLabel(incrementLabel);
+                if (node.incrementor) {
+                    emitStatement(
+                        createStatement(
+                            visitNode(node.incrementor, visitor, isExpression),
+                            /*location*/ node.incrementor
+                        )
+                    );
+                }
+                emitBreak(conditionLabel);
+                endLoopBlock();
+            }
+            else {
+                emitStatement(visitNode(node, visitor, isStatement));
+            }
+        }
+
+        function visitForStatement(node: ForStatement) {
+            if (inStatementContainingYield) {
+                beginScriptLoopBlock();
+            }
+
+            const initializer = node.initializer;
+            if (isVariableDeclarationList(initializer)) {
+                for (const variable of initializer.declarations) {
+                    hoistVariableDeclaration(<Identifier>variable.name);
+                }
+
+                node = getMutableClone(node);
+
+                const variables = getInitializedVariables(initializer);
+                if (variables.length === 0) {
+                    node.initializer = undefined;
+                }
+                else {
+                    node.initializer = inlineExpressions(
+                        map(variables, transformInitializedVariable)
+                    );
+                }
+
+                node.condition = visitNode(node.condition, visitor, isExpression, /*optional*/ true);
+                node.incrementor = visitNode(node.incrementor, visitor, isExpression, /*optional*/ true);
+                node.statement = visitNode(node.statement, visitor, isStatement);
+            }
+            else {
+                node = visitEachChild(node, visitor, context);
+            }
+
+            if (inStatementContainingYield) {
+                endLoopBlock();
+            }
+
+            return node;
+        }
+
+        function transformAndEmitForInStatement(node: ForInStatement) {
+            // TODO(rbuckton): Source map locations
+            if (containsYield(node)) {
+                // [source]
+                //      for (var p in o) {
+                //          /*body*/
+                //      }
+                //
+                // [intermediate]
+                //  .local _a, _b, p
+                //      _a = __keys(o);
+                //  .loop incrementLabel, endLoopLabel
+                //  .try tryLabel, , finallyLabel, endTryLabel
+                //  .mark tryLabel
+                //  .nop
+                //  .mark incrementLabel
+                //      _b = _a.next();
+                //  .brtrue cleanupLabel, (_b.done)
+                //      p = _b.value;
+                //      /*body*/
+                //  .br incrementLabel
+                //  .mark cleanupLabel
+                //      _b = _a = void 0;
+                //  .br endLoopLabel
+                //  .finally
+                //  .mark finallyLabel
+                //      if (_a && typeof _a.return === "function")
+                //          _a.return();
+                //  .endfinally
+                //  .endtry
+                //  .mark endTryLabel
+                //  .endloop
+                //  .mark endLoopLabel
+
+                const keysIterator = declareLocal(); // _a
+                const iteratorResult = declareLocal(); // _b
+                const initializer = node.initializer;
+
+                let variable: Expression;
+                if (isVariableDeclarationList(initializer)) {
+                    for (const variable of initializer.declarations) {
+                        hoistVariableDeclaration(<Identifier>variable.name);
+                    }
+
+                    variable = <Identifier>getSynthesizedClone(initializer.declarations[0].name);
+                }
+                else {
+                    variable = initializer;
+                    Debug.assert(isLeftHandSideExpression(variable));
+                }
+
+                emitAssignment(keysIterator,
+                    createCall("__keys", [
+                        visitNode(node.expression, visitor, isExpression)
+                    ])
+                );
+
+                const incrementLabel = defineLabel();
+                const cleanupLabel = defineLabel();
+                const endLabel = beginLoopBlock(incrementLabel);
+
+                beginExceptionBlock();
+                markLabel(incrementLabel);
+                emitAssignment(iteratorResult, createCall(createPropertyAccess(iteratorResult, "next"), []));
+                emitBreakWhenTrue(cleanupLabel, createPropertyAccess(iteratorResult, "done"));
+                emitAssignment(variable, createPropertyAccess(iteratorResult, "value"));
+                transformAndEmitEmbeddedStatement(node.statement);
+                emitBreak(incrementLabel);
+                markLabel(cleanupLabel);
+                emitAssignment(keysIterator, createAssignment(iteratorResult, createVoidZero()));
+                emitBreak(endLabel);
+                beginFinallyBlock();
+                emitStatement(
+                    createIf(
+                        createLogicalAnd(
+                            keysIterator,
+                            createStrictEquality(
+                                createTypeOf(
+                                    createPropertyAccess(keysIterator, "return")
+                                ),
+                                createLiteral("function")
+                            )
+                        ),
+                        createStatement(
+                            createCall(createPropertyAccess(keysIterator, "return"), [])
+                        )
+                    )
+                );
+                emitEndfinally();
+                endExceptionBlock();
+                endLoopBlock();
+            }
+            else {
+                emitStatement(visitNode(node, visitor, isStatement));
+            }
+        }
+
+        function visitForInStatement(node: ForInStatement) {
+            // [source]
+            //      for (var x in a) {
+            //          /*body*/
+            //      }
+            //
+            // [intermediate]
+            //  .local x
+            //  .loop
+            //      for (x in a) {
+            //          /*body*/
+            //      }
+            //  .endloop
+
+            if (inStatementContainingYield) {
+                beginScriptLoopBlock();
+            }
+
+            const initializer = node.initializer;
+            if (isVariableDeclarationList(initializer)) {
+                for (const variable of initializer.declarations) {
+                    hoistVariableDeclaration(<Identifier>variable.name);
+                }
+
+                node = getMutableClone(node);
+
+                const variable = initializer.declarations[0];
+                node.initializer = <Identifier>variable.name;
+                node.expression = visitNode(node.expression, visitor, isExpression);
+                node.statement = visitNode(node.statement, visitor, isStatement);
+            }
+            else {
+                node = visitEachChild(node, visitor, context);
+            }
+
+            if (inStatementContainingYield) {
+                endLoopBlock();
+            }
+
+            return node;
+        }
+
+        function transformAndEmitContinueStatement(node: ContinueStatement): void {
+            const label = findContinueTarget(node.label ? node.label.text : undefined);
+            Debug.assert(label > 0, "Expected continue statment to point to a valid Label.");
+            emitBreak(label, /*location*/ node);
+        }
+
+        function visitContinueStatement(node: ContinueStatement): Statement {
+            if (inStatementContainingYield) {
+                const label = findContinueTarget(node.label && node.label.text);
+                if (label > 0) {
+                    return createInlineBreak(label, /*location*/ node);
+                }
+            }
+
+            return visitEachChild(node, visitor, context);
+        }
+
+        function transformAndEmitBreakStatement(node: BreakStatement): void {
+            const label = findBreakTarget(node.label ? node.label.text : undefined);
+            Debug.assert(label > 0, "Expected break statment to point to a valid Label.");
+            emitBreak(label, /*location*/ node);
+        }
+
+        function visitBreakStatement(node: BreakStatement): Statement {
+            if (inStatementContainingYield) {
+                const label = findBreakTarget(node.label && node.label.text);
+                if (label > 0) {
+                    return createInlineBreak(label, /*location*/ node);
+                }
+            }
+
+            return visitEachChild(node, visitor, context);
+        }
+
+
+        function transformAndEmitReturnStatement(node: ReturnStatement): void {
+            emitReturn(
+                visitNode(node.expression, visitor, isExpression, /*optional*/ true),
+                /*location*/ node
+            );
+        }
+
+        function visitReturnStatement(node: ReturnStatement) {
+            return createInlineReturn(
+                visitNode(node.expression, visitor, isExpression, /*optional*/ true),
+                /*location*/ node
+            );
+        }
+
+        function transformAndEmitWithStatement(node: WithStatement) {
+            if (containsYield(node)) {
+                // [source]
+                //      with (x) {
+                //          /*body*/
+                //      }
+                //
+                // [intermediate]
+                //  .with (x)
+                //      /*body*/
+                //  .endwith
+                beginWithBlock(cacheExpression(visitNode(node.expression, visitor, isExpression)));
+                transformAndEmitEmbeddedStatement(node.statement);
+                endWithBlock();
+            }
+            else {
+                emitStatement(visitNode(node, visitor, isStatement));
+            }
+        }
+
+        function transformAndEmitSwitchStatement(node: SwitchStatement) {
+            if (containsYield(node)) {
+                // [source]
+                //      switch (x) {
+                //          case a:
+                //              /*caseStatements*/
+                //          case b:
+                //              /*caseStatements*/
+                //          default:
+                //              /*defaultStatements*/
+                //      }
+                //
+                // [intermediate]
+                //  .local _a
+                //  .switch endLabel
+                //      _a = x;
+                //      switch (_a) {
+                //          case a:
+                //  .br clauseLabels[0]
+                //      }
+                //      switch (_a) {
+                //          case b:
+                //  .br clauseLabels[1]
+                //      }
+                //  .br clauseLabels[2]
+                //  .mark clauseLabels[0]
+                //      /*caseStatements*/
+                //  .mark clauseLabels[1]
+                //      /*caseStatements*/
+                //  .mark clauseLabels[2]
+                //      /*caseStatements*/
+                //  .endswitch
+                //  .mark endLabel
+
+                const caseBlock = node.caseBlock;
+                const numClauses = caseBlock.clauses.length;
+                const endLabel = beginSwitchBlock();
+
+                const expression = cacheExpression(visitNode(node.expression, visitor, isExpression));
+
+                // Create labels for each clause and find the index of the first default clause.
+                const clauseLabels: Label[] = [];
+                let defaultClauseIndex = -1;
+                for (let i = 0; i < numClauses; i++) {
+                    const clause = caseBlock.clauses[i];
+                    clauseLabels.push(defineLabel());
+                    if (clause.kind === SyntaxKind.DefaultClause && defaultClauseIndex === -1) {
+                        defaultClauseIndex = i;
+                    }
+                }
+
+                // Emit switch statements for each run of case clauses either from the first case
+                // clause or the next case clause with a `yield` in its expression, up to the next
+                // case clause with a `yield` in its expression.
+                let clausesWritten = 0;
+                let pendingClauses: CaseClause[] = [];
+                while (clausesWritten < numClauses) {
+                    for (let i = clausesWritten; i < numClauses; i++) {
+                        const clause = caseBlock.clauses[i];
+                        if (clause.kind === SyntaxKind.CaseClause) {
+                            const caseClause = <CaseClause>clause;
+                            if (containsYield(caseClause.expression) && pendingClauses.length > 0) {
+                                break;
+                            }
+
+                            pendingClauses.push(
+                                createCaseClause(
+                                    visitNode(caseClause.expression, visitor, isExpression),
+                                    [
+                                        createInlineBreak(clauseLabels[i], /*location*/ caseClause.expression)
+                                    ]
+                                )
+                            );
+                        }
+                    }
+
+                    if (pendingClauses.length) {
+                        emitStatement(createSwitch(expression, createCaseBlock(pendingClauses)));
+                        clausesWritten += pendingClauses.length;
+                        pendingClauses = [];
+                    }
+                }
+
+                if (defaultClauseIndex >= 0) {
+                    emitBreak(clauseLabels[defaultClauseIndex]);
+                }
+                else {
+                    emitBreak(endLabel);
+                }
+
+                for (let i = 0; i < numClauses; i++) {
+                    markLabel(clauseLabels[i]);
+                    transformAndEmitStatements(caseBlock.clauses[i].statements);
+                }
+
+                endSwitchBlock();
+            }
+            else {
+                emitStatement(visitNode(node, visitor, isStatement));
+            }
+        }
+
+        function visitSwitchStatement(node: SwitchStatement) {
+            if (inStatementContainingYield) {
+                beginScriptSwitchBlock();
+            }
+
+            node = visitEachChild(node, visitor, context);
+
+            if (inStatementContainingYield) {
+                endSwitchBlock();
+            }
+
+            return node;
+        }
+
+        function transformAndEmitLabeledStatement(node: LabeledStatement) {
+            if (containsYield(node)) {
+                // [source]
+                //      x: {
+                //          /*body*/
+                //      }
+                //
+                // [intermediate]
+                //  .labeled "x", endLabel
+                //      /*body*/
+                //  .endlabeled
+                //  .mark endLabel
+                beginLabeledBlock(node.label.text);
+                transformAndEmitEmbeddedStatement(node.statement);
+                endLabeledBlock();
+            }
+            else {
+                emitStatement(visitNode(node, visitor, isStatement));
+            }
+        }
+
+        function visitLabeledStatement(node: LabeledStatement) {
+            if (inStatementContainingYield) {
+                beginScriptLabeledBlock(node.label.text);
+            }
+
+            node = visitEachChild(node, visitor, context);
+
+            if (inStatementContainingYield) {
+                endLabeledBlock();
+            }
+
+            return node;
+        }
+
+        function transformAndEmitThrowStatement(node: ThrowStatement): void {
+            emitThrow(
+                visitNode(node.expression, visitor, isExpression),
+                /*location*/ node
+            );
+        }
+
+        function transformAndEmitTryStatement(node: TryStatement) {
+            if (containsYield(node)) {
+                // [source]
+                //      try {
+                //          /*tryBlock*/
+                //      }
+                //      catch (e) {
+                //          /*catchBlock*/
+                //      }
+                //      finally {
+                //          /*finallyBlock*/
+                //      }
+                //
+                // [intermediate]
+                //  .local _a
+                //  .try tryLabel, catchLabel, finallyLabel, endLabel
+                //  .mark tryLabel
+                //  .nop
+                //      /*tryBlock*/
+                //  .br endLabel
+                //  .catch
+                //  .mark catchLabel
+                //      _a = %error%;
+                //      /*catchBlock*/
+                //  .br endLabel
+                //  .finally
+                //  .mark finallyLabel
+                //      /*finallyBlock*/
+                //  .endfinally
+                //  .endtry
+                //  .mark endLabel
+
+                beginExceptionBlock();
+                transformAndEmitEmbeddedStatement(node.tryBlock);
+                if (node.catchClause) {
+                    if (!renamedCatchVariables) {
+                        renamedCatchVariables = {};
+                    }
+
+                    beginCatchBlock(node.catchClause.variableDeclaration);
+                    transformAndEmitEmbeddedStatement(node.catchClause.block);
+                }
+
+                if (node.finallyBlock) {
+                    beginFinallyBlock();
+                    transformAndEmitEmbeddedStatement(node.finallyBlock);
+                }
+
+                endExceptionBlock();
+            }
+            else {
+                emitStatement(visitEachChild(node, visitor, context));
+            }
+        }
+
+        function containsYield(node: Node) {
+            return node && (node.transformFlags & TransformFlags.ContainsYield) !== 0;
+        }
+
+        function countInitialNodesWithoutYield(nodes: NodeArray<Node>) {
+            const numNodes = nodes.length;
+            for (let i = 0; i < numNodes; i++) {
+                if (containsYield(nodes[i])) {
+                    return i;
+                }
+            }
+
+            return -1;
+        }
+
+        function substituteExpression(node: Expression): Expression {
+            node = previousExpressionSubstitution(node);
+            if (isIdentifier(node)) {
+                return substituteExpressionIdentifier(node);
+            }
+            return node;
+        }
+
+        function substituteExpressionIdentifier(node: Identifier) {
+            if (renamedCatchVariables && hasProperty(renamedCatchVariables, node.text)) {
+                const original = getOriginalNode(node);
+                if (isIdentifier(original) && original.parent) {
+                    const declaration = resolver.getReferencedValueDeclaration(original);
+                    if (declaration) {
+                        const name = getProperty(renamedCatchVariableDeclarations, String(getOriginalNodeId(declaration)));
+                        if (name) {
+                            return getRelocatedClone(name, /*location*/ node);
+                        }
+                    }
+                }
+            }
+
+            return node;
+        }
+
+        function cacheExpression(node: Expression): Identifier {
+            let temp: Identifier;
+            if (isIdentifier(node)) {
+                if (nodeIsSynthesized(node) || isGeneratedIdentifier(node)) {
+                    return node;
+                }
+
+                temp = createUniqueName(node.text);
+            }
+            else {
+                temp = createTempVariable();
+            }
+
+            emitAssignment(temp, node, /*location*/ node);
+            return temp;
+        }
+
+        function declareLocal(name?: string): Identifier {
+            const temp = name
+                ? createUniqueName(name)
+                : createTempVariable();
+            hoistVariableDeclaration(temp);
+            return temp;
+        }
+
+        /**
+         * Defines a label, uses as the target of a Break operation.
+         */
+        function defineLabel(): Label {
+            if (!labelOffsets) {
+                labelOffsets = [];
+            }
+
+            const label = nextLabelId++;
+            labelOffsets[label] = -1;
+            return label;
+        }
+
+        /**
+         * Marks the current operation with the specified label.
+         */
+        function markLabel(label: Label): void {
+            Debug.assert(labelOffsets !== undefined, "No labels were defined.");
+            labelOffsets[label] = operations ? operations.length : 0;
+        }
+
+        /**
+         * Begins a block operation (With, Break/Continue, Try/Catch/Finally)
+         *
+         * @param block Information about the block.
+         */
+        function beginBlock(block: CodeBlock): number {
+            if (!blocks) {
+                blocks = [];
+                blockActions = [];
+                blockOffsets = [];
+                blockStack = [];
+            }
+
+            const index = blockActions.length;
+            blockActions[index] = BlockAction.Open;
+            blockOffsets[index] = operations ? operations.length : 0;
+            blocks[index] = block;
+            blockStack.push(block);
+            return index;
+        }
+
+        /**
+         * Ends the current block operation.
+         */
+        function endBlock(): CodeBlock {
+            const block = peekBlock();
+            Debug.assert(block !== undefined, "beginBlock was never called.");
+
+            const index = blockActions.length;
+            blockActions[index] = BlockAction.Close;
+            blockOffsets[index] = operations ? operations.length : 0;
+            blocks[index] = block;
+            blockStack.pop();
+            return block;
+        }
+
+        /**
+         * Gets the current open block.
+         */
+        function peekBlock() {
+            return lastOrUndefined(blockStack);
+        }
+
+        /**
+         * Gets the kind of the current open block.
+         */
+        function peekBlockKind(): CodeBlockKind {
+            const block = peekBlock();
+            return block && block.kind;
+        }
+
+        /**
+         * Begins a code block for a generated `with` statement.
+         *
+         * @param expression An identifier representing expression for the `with` block.
+         */
+        function beginWithBlock(expression: Identifier): void {
+            const startLabel = defineLabel();
+            const endLabel = defineLabel();
+            markLabel(startLabel);
+            beginBlock(<WithBlock>{
+                kind: CodeBlockKind.With,
+                expression,
+                startLabel,
+                endLabel
+            });
+        }
+
+        /**
+         * Ends a code block for a generated `with` statement.
+         */
+        function endWithBlock(): void {
+            Debug.assert(peekBlockKind() === CodeBlockKind.With);
+            const block = <WithBlock>endBlock();
+            markLabel(block.endLabel);
+        }
+
+        function isWithBlock(block: CodeBlock): block is WithBlock {
+            return block.kind === CodeBlockKind.With;
+        }
+
+        /**
+         * Begins a code block for a generated `try` statement.
+         */
+        function beginExceptionBlock(): Label {
+            const startLabel = defineLabel();
+            const endLabel = defineLabel();
+            markLabel(startLabel);
+            beginBlock(<ExceptionBlock>{
+                kind: CodeBlockKind.Exception,
+                state: ExceptionBlockState.Try,
+                startLabel,
+                endLabel
+            });
+            emitWorker(OpCode.Nop);
+            hasProtectedRegions = true;
+            return endLabel;
+        }
+
+        /**
+         * Enters the `catch` clause of a generated `try` statement.
+         *
+         * @param variable The catch variable.
+         */
+        function beginCatchBlock(variable: VariableDeclaration): void {
+            Debug.assert(peekBlockKind() === CodeBlockKind.Exception);
+
+            const text = (<Identifier>variable.name).text;
+            const name = createUniqueName(text);
+
+            if (!renamedCatchVariables) {
+                renamedCatchVariables = {};
+                renamedCatchVariableDeclarations = {};
+                context.enableExpressionSubstitution(SyntaxKind.Identifier);
+            }
+
+            renamedCatchVariables[text] = true;
+            renamedCatchVariableDeclarations[getOriginalNodeId(variable)] = name;
+
+            const exception = <ExceptionBlock>peekBlock();
+            Debug.assert(exception.state < ExceptionBlockState.Catch);
+
+            const endLabel = exception.endLabel;
+            emitBreak(endLabel);
+
+            const catchLabel = defineLabel();
+            markLabel(catchLabel);
+            exception.state = ExceptionBlockState.Catch;
+            exception.catchVariable = name;
+            exception.catchLabel = catchLabel;
+
+            const state = getState();
+            emitAssignment(name, createPropertyAccess(state, "error"));
+            emitWorker(OpCode.Nop);
+        }
+
+        /**
+         * Enters the `finally` block of a generated `try` statement.
+         */
+        function beginFinallyBlock(): void {
+            Debug.assert(peekBlockKind() === CodeBlockKind.Exception);
+
+            const exception = <ExceptionBlock>peekBlock();
+            Debug.assert(exception.state < ExceptionBlockState.Finally);
+
+            const state = exception.state;
+            const endLabel = exception.endLabel;
+            emitBreak(endLabel);
+
+            const finallyLabel = defineLabel();
+            markLabel(finallyLabel);
+            exception.state = ExceptionBlockState.Finally;
+            exception.finallyLabel = finallyLabel;
+        }
+
+        /**
+         * Ends the code block for a generated `try` statement.
+         */
+        function endExceptionBlock(): void {
+            Debug.assert(peekBlockKind() === CodeBlockKind.Exception);
+            const exception = <ExceptionBlock>endBlock();
+            const state = exception.state;
+            if (state < ExceptionBlockState.Finally) {
+                emitBreak(exception.endLabel);
+            }
+            else {
+                emitEndfinally();
+            }
+
+            markLabel(exception.endLabel);
+            exception.state = ExceptionBlockState.Done;
+        }
+
+        function isExceptionBlock(block: CodeBlock): block is ExceptionBlock {
+            return block.kind === CodeBlockKind.Exception;
+        }
+
+        /**
+         * Begins a code block that supports `break` or `continue` statements that are defined in
+         * the source tree and not from generated code.
+         *
+         * @param labelText Names from containing labeled statements.
+         */
+        function beginScriptLoopBlock(): void {
+            beginBlock(<LoopBlock>{
+                kind: CodeBlockKind.Loop,
+                isScript: true,
+                breakLabel: -1,
+                continueLabel: -1
+            });
+        }
+
+        /**
+         * Begins a code block that supports `break` or `continue` statements that are defined in
+         * generated code. Returns a label used to mark the operation to which to jump when a
+         * `break` statement targets this block.
+         *
+         * @param continueLabel A Label used to mark the operation to which to jump when a
+         *                      `continue` statement targets this block.
+         */
+        function beginLoopBlock(continueLabel: Label): Label {
+            const breakLabel = defineLabel();
+            beginBlock(<LoopBlock>{
+                kind: CodeBlockKind.Loop,
+                isScript: false,
+                breakLabel: breakLabel,
+                continueLabel: continueLabel
+            });
+            return breakLabel;
+        }
+
+        /**
+         * Ends a code block that supports `break` or `continue` statements that are defined in
+         * generated code or in the source tree.
+         */
+        function endLoopBlock(): void {
+            Debug.assert(peekBlockKind() === CodeBlockKind.Loop);
+            const block = <SwitchBlock>endBlock();
+            const breakLabel = block.breakLabel;
+            if (!block.isScript) {
+                markLabel(breakLabel);
+            }
+        }
+
+        /**
+         * Begins a code block that supports `break` statements that are defined in the source
+         * tree and not from generated code.
+         *
+         */
+        function beginScriptSwitchBlock(): void {
+            beginBlock(<SwitchBlock>{
+                kind: CodeBlockKind.Switch,
+                isScript: true,
+                breakLabel: -1
+            });
+        }
+
+
+        /**
+         * Begins a code block that supports `break` statements that are defined in generated code.
+         * Returns a label used to mark the operation to which to jump when a `break` statement
+         * targets this block.
+         */
+        function beginSwitchBlock(): Label {
+            const breakLabel = defineLabel();
+            beginBlock(<SwitchBlock>{
+                kind: CodeBlockKind.Switch,
+                isScript: false,
+                breakLabel: breakLabel
+            });
+            return breakLabel;
+        }
+
+        /**
+         * Ends a code block that supports `break` statements that are defined in generated code.
+         */
+        function endSwitchBlock(): void {
+            Debug.assert(peekBlockKind() === CodeBlockKind.Switch);
+            const block = <SwitchBlock>endBlock();
+            const breakLabel = block.breakLabel;
+            if (!block.isScript) {
+                markLabel(breakLabel);
+            }
+        }
+
+        function beginScriptLabeledBlock(labelText: string) {
+            beginBlock(<LabeledBlock>{
+                kind: CodeBlockKind.Labeled,
+                isScript: true,
+                labelText,
+                breakLabel: -1
+            });
+        }
+
+        function beginLabeledBlock(labelText: string) {
+            const breakLabel = defineLabel();
+            beginBlock(<LabeledBlock>{
+                kind: CodeBlockKind.Labeled,
+                isScript: false,
+                labelText,
+                breakLabel
+            });
+        }
+
+        function endLabeledBlock() {
+            Debug.assert(peekBlockKind() === CodeBlockKind.Labeled);
+            const block = <LabeledBlock>endBlock();
+            if (!block.isScript) {
+                markLabel(block.breakLabel);
+            }
+        }
+
+        /**
+         * Indicates whether the provided block supports `break` statements.
+         *
+         * @param block A code block.
+         */
+        function supportsUnlabeledBreak(block: CodeBlock): block is SwitchBlock | LoopBlock {
+            return block.kind === CodeBlockKind.Switch
+                || block.kind === CodeBlockKind.Loop;
+        }
+
+        /**
+         * Indicates whether the provided block supports `break` statements with labels.
+         *
+         * @param block A code block.
+         */
+        function supportsLabeledBreakOrContinue(block: CodeBlock): block is LabeledBlock {
+            return block.kind === CodeBlockKind.Labeled;
+        }
+
+        /**
+         * Indicates whether the provided block supports `continue` statements.
+         *
+         * @param block A code block.
+         */
+        function supportsUnlabeledContinue(block: CodeBlock): block is LoopBlock {
+            return block.kind === CodeBlockKind.Loop;
+        }
+
+        function hasImmediateContainingLabeledBlock(labelText: string, start: number) {
+            for (let j = start; j >= 0; j--) {
+                const containingBlock = blockStack[j];
+                if (supportsLabeledBreakOrContinue(containingBlock)) {
+                    if (containingBlock.labelText === labelText) {
+                        return true;
+                    }
+                }
+                else {
+                    break;
+                }
+            }
+
+            return false;
+        }
+
+        /**
+         * Finds the label that is the target for a `break` statement.
+         *
+         * @param labelText An optional name of a containing labeled statement.
+         */
+        function findBreakTarget(labelText?: string): Label {
+            Debug.assert(blocks !== undefined);
+            if (labelText) {
+                for (let i = blockStack.length - 1; i >= 0; i--) {
+                    const block = blockStack[i];
+                    if (supportsLabeledBreakOrContinue(block) && block.labelText === labelText) {
+                        return block.breakLabel;
+                    }
+                    else if (supportsUnlabeledBreak(block) && hasImmediateContainingLabeledBlock(labelText, i - 1)) {
+                        return block.breakLabel;
+                    }
+                }
+            }
+            else {
+                for (let i = blockStack.length - 1; i >= 0; i--) {
+                    const block = blockStack[i];
+                    if (supportsUnlabeledBreak(block)) {
+                        return block.breakLabel;
+                    }
+                }
+            }
+
+            return 0;
+        }
+
+        /**
+         * Finds the label that is the target for a `continue` statement.
+         *
+         * @param labelText An optional name of a containing labeled statement.
+         */
+        function findContinueTarget(labelText?: string): Label {
+            Debug.assert(blocks !== undefined);
+            if (labelText) {
+                for (let i = blockStack.length - 1; i >= 0; i--) {
+                    const block = blockStack[i];
+                    if (supportsUnlabeledContinue(block) && hasImmediateContainingLabeledBlock(labelText, i - 1)) {
+                        return block.continueLabel;
+                    }
+                }
+            }
+            else {
+                for (let i = blockStack.length - 1; i >= 0; i--) {
+                    const block = blockStack[i];
+                    if (supportsUnlabeledContinue(block)) {
+                        return block.continueLabel;
+                    }
+                }
+            }
+
+            return 0;
+        }
+
+        /**
+         * Creates an expression that can be used to indicate the value for a label.
+         *
+         * @param label A label.
+         */
+        function createLabel(label: Label): Expression {
+            if (label > 0) {
+                if (labelExpressions === undefined) {
+                    labelExpressions = [];
+                }
+
+                const expression = <LiteralExpression>createSynthesizedNode(SyntaxKind.NumericLiteral);
+                if (labelExpressions[label] === undefined) {
+                    labelExpressions[label] = [expression];
+                }
+                else {
+                    labelExpressions[label].push(expression);
+                }
+
+                return expression;
+            }
+
+            return <OmittedExpression>createNode(SyntaxKind.OmittedExpression);
+        }
+
+        /**
+         * Creates a numeric literal for the provided instruction.
+         */
+        function createInstruction(instruction: Instruction): NumericLiteral {
+            return createLiteral(instruction, /*location*/ undefined, instructionNames[instruction]);
+        }
+
+        /**
+         * Creates a statement that can be used indicate a Break operation to the provided label.
+         *
+         * @param label A label.
+         * @param location An optional source map location for the statement.
+         */
+        function createInlineBreak(label: Label, location?: TextRange): ReturnStatement {
+            Debug.assert(label > 0, `Invalid label: ${label}`);
+            return createReturn(
+                createArrayLiteral([
+                    createInstruction(Instruction.Break),
+                    createLabel(label)
+                ]),
+                location
+            );
+        }
+
+        /**
+         * Creates a statement that can be used indicate a Return operation.
+         *
+         * @param expression The expression for the return statement.
+         * @param location An optional source map location for the statement.
+         */
+        function createInlineReturn(expression?: Expression, location?: TextRange): ReturnStatement {
+            return createReturn(
+                createArrayLiteral(expression
+                    ? [createInstruction(Instruction.Return), expression]
+                    : [createInstruction(Instruction.Return)]
+                ),
+                location
+            );
+        }
+
+        /**
+         * Creates an expression that can be used to resume from a Yield operation.
+         */
+        function createGeneratorResume(location?: TextRange): LeftHandSideExpression {
+            return createCall(createPropertyAccess(getState(), "sent"), [], location);
+        }
+
+        /**
+         * Gets the identifier for the runtime `state` variable.
+         */
+        function getState(): Identifier {
+            if (state === undefined) {
+                state = createUniqueName("state");
+            }
+
+            return state;
+        }
+
+        /**
+         * Emits a NOP (no operation). This is often used to ensure a new operation location exists
+         * when marking labels.
+         */
+        function emitNop(): void {
+            emitWorker(OpCode.Nop);
+        }
+
+        /**
+         * Emits a Statement.
+         *
+         * @param node A statement.
+         */
+        function emitStatement(node: Statement): void {
+            if (node) {
+                emitWorker(OpCode.Statement, [node]);
+            }
+            else {
+                emitWorker(OpCode.Nop);
+            }
+        }
+
+        /**
+         * Emits an Assignment operation.
+         *
+         * @param left The left-hand side of the assignment.
+         * @param right The right-hand side of the assignment.
+         * @param location An optional source map location for the assignment.
+         */
+        function emitAssignment(left: Expression, right: Expression, location?: TextRange): void {
+            emitWorker(OpCode.Assign, [left, right], location);
+        }
+
+        /**
+         * Emits a Break operation to the specified label.
+         *
+         * @param label A label.
+         * @param location An optional source map location for the assignment.
+         */
+        function emitBreak(label: Label, location?: TextRange): void {
+            emitWorker(OpCode.Break, [label], location);
+        }
+
+        /**
+         * Emits a Break operation to the specified label when a condition evaluates to a truthy
+         * value at runtime.
+         *
+         * @param label A label.
+         * @param condition The condition.
+         * @param location An optional source map location for the assignment.
+         */
+        function emitBreakWhenTrue(label: Label, condition: Expression, location?: TextRange): void {
+            emitWorker(OpCode.BreakWhenTrue, [label, condition], location);
+        }
+
+        /**
+         * Emits a Break to the specified label when a condition evaluates to a falsey value at
+         * runtime.
+         *
+         * @param label A label.
+         * @param condition The condition.
+         * @param location An optional source map location for the assignment.
+         */
+        function emitBreakWhenFalse(label: Label, condition: Expression, location?: TextRange): void {
+            emitWorker(OpCode.BreakWhenFalse, [label, condition], location);
+        }
+
+        /**
+         * Emits a Yield operation for the provided expression.
+         *
+         * @param expression An optional value for the yield operation.
+         * @param location An optional source map location for the assignment.
+         */
+        function emitYield(expression?: Expression, location?: TextRange): void {
+            emitWorker(OpCode.Yield, [expression], location);
+        }
+
+        /**
+         * Emits a YieldStar operation for the provided expression.
+         *
+         * @param expression A value for the operation.
+         * @param location An optional source map location for the assignment.
+         */
+        function emitYieldStar(expression: Expression, location?: TextRange): void {
+            emitWorker(OpCode.YieldStar, [expression], location);
+        }
+
+        /**
+         * Emits a Return operation for the provided expression.
+         *
+         * @param expression An optional value for the operation.
+         * @param location An optional source map location for the assignment.
+         */
+        function emitReturn(expression?: Expression, location?: TextRange): void {
+            emitWorker(OpCode.Return, [expression], location);
+        }
+
+        /**
+         * Emits a Throw operation for the provided expression.
+         *
+         * @param expression A value for the operation.
+         * @param location An optional source map location for the assignment.
+         */
+        function emitThrow(expression: Expression, location?: TextRange): void {
+            emitWorker(OpCode.Throw, [expression], location);
+        }
+
+        /**
+         * Emits an Endfinally operation. This is used to handle `finally` block semantics.
+         */
+        function emitEndfinally(): void {
+            emitWorker(OpCode.Endfinally);
+        }
+
+        /**
+         * Emits an operation.
+         *
+         * @param code The OpCode for the operation.
+         * @param args The optional arguments for the operation.
+         */
+        function emitWorker(code: OpCode, args?: OperationArguments, location?: TextRange): void {
+            if (operations === undefined) {
+                operations = [];
+                operationArguments = [];
+                operationLocations = [];
+            }
+
+            if (labelOffsets === undefined) {
+                // mark entry point
+                markLabel(defineLabel());
+            }
+
+            const operationIndex = operations.length;
+            operations[operationIndex] = code;
+            operationArguments[operationIndex] = args;
+            operationLocations[operationIndex] = location;
+        }
+
+        /**
+         * Builds the generator function body.
+         */
+        function build() {
+            blockIndex = 0;
+            labelNumber = 0;
+            lastOperationWasAbrupt = false;
+            lastOperationWasCompletion = false;
+            clauses = undefined;
+            statements = undefined;
+            exceptionBlockStack = undefined;
+            currentExceptionBlock = undefined;
+            withBlockStack = undefined;
+
+            return createCall(
+                createIdentifier("__generator"),
+                [createFunctionExpression(
+                    /*asteriskToken*/ undefined,
+                    /*name*/ undefined,
+                    [createParameter(getState())],
+                    createBlock(
+                        buildStatements()
+                    )
+                )]
+            );
+        }
+
+        /**
+         * Builds the statements for the generator function body.
+         */
+        function buildStatements(): Statement[] {
+            if (hasProtectedRegions) {
+                initializeProtectedRegions();
+            }
+
+            if (operations) {
+                for (let operationIndex = 0; operationIndex < operations.length; operationIndex++) {
+                    writeOperation(operationIndex);
+                }
+
+                flushFinalLabel(operations.length);
+            }
+            else {
+                flushFinalLabel(0);
+            }
+
+
+            if (clauses) {
+                const state = getState();
+                const labelExpression = createPropertyAccess(state, "label");
+                const switchStatement = createSwitch(labelExpression, createCaseBlock(clauses));
+                return [switchStatement];
+            }
+
+            if (statements) {
+                return statements;
+            }
+
+            return [];
+        }
+
+        /**
+         * Initializes protected region information for the generator.
+         *
+         * This assigns an array to `state.trys` that will be used to capture when execution
+         * enters or exits a protected region (i.e. an exception block).
+         */
+        function initializeProtectedRegions(): void {
+            writeAssign(createPropertyAccess(getState(), "trys"), createArrayLiteral(), /*operationLocation*/ undefined);
+            flushLabel();
+        }
+
+        /**
+         * Flush the current label and advance to a new label.
+         */
+        function flushLabel(): void {
+            if (!statements) {
+                return;
+            }
+
+            appendLabel(/*markLabelEnd*/ !lastOperationWasAbrupt);
+
+            lastOperationWasAbrupt = false;
+            lastOperationWasCompletion = false;
+            labelNumber++;
+        }
+
+        /**
+         * Flush the final label of the generator function body.
+         */
+        function flushFinalLabel(operationIndex: number): void {
+            if (!lastOperationWasCompletion) {
+                tryEnterLabel(operationIndex);
+                writeReturn(/*expression*/ undefined, /*operationLocation*/ undefined);
+            }
+
+            if (statements && clauses) {
+                appendLabel(/*markLabelEnd*/ false);
+            }
+        }
+
+        /**
+         * Appends a case clause for the last label and sets the new label.
+         *
+         * @param markLabelEnd Indicates that the transition between labels was a fall-through
+         *                     from a previous case clause and the change in labels should be
+         *                     reflected on the `state` object.
+         */
+        function appendLabel(markLabelEnd: boolean): void {
+            if (!clauses) {
+                clauses = [];
+            }
+
+            if (statements) {
+                if (withBlockStack) {
+                    // The previous label was nested inside one or more `with` blocks, so we
+                    // surround the statements in generated `with` blocks to create the same environment.
+                    for (let i = withBlockStack.length - 1; i >= 0; i--) {
+                        const withBlock = withBlockStack[i];
+                        statements = [createWith(withBlock.expression, createBlock(statements))];
+                    }
+                }
+
+                if (currentExceptionBlock) {
+                    // The previous label was nested inside of an exception block, so we must
+                    // indicate entry into a protected region by pushing the label numbers
+                    // for each block in the protected region.
+                    const { startLabel, catchLabel, finallyLabel, endLabel } = currentExceptionBlock;
+                    statements.unshift(
+                        createStatement(
+                            createCall(
+                                createPropertyAccess(createPropertyAccess(getState(), "trys"), "push"),
+                                [
+                                    createArrayLiteral([
+                                        createLabel(startLabel),
+                                        createLabel(catchLabel),
+                                        createLabel(finallyLabel),
+                                        createLabel(endLabel)
+                                    ])
+                                ]
+                            )
+                        )
+                    );
+
+                    currentExceptionBlock = undefined;
+                }
+
+                if (markLabelEnd) {
+                    // The case clause for the last label falls through to this label, so we
+                    // add an assignment statement to reflect the change in labels.
+                    statements.push(
+                        createStatement(
+                            createAssignment(
+                                createPropertyAccess(getState(), "label"),
+                                createLiteral(labelNumber + 1)
+                            )
+                        )
+                    );
+                }
+            }
+
+            clauses.push(
+                createCaseClause(
+                    createLiteral(labelNumber),
+                    statements || []
+                )
+            );
+
+            statements = undefined;
+        }
+
+        /**
+         * Tries to enter into a new label at the current operation index.
+         */
+        function tryEnterLabel(operationIndex: number): void {
+            if (!labelOffsets) {
+                return;
+            }
+
+            let isLabel: boolean = false;
+            for (let label = 0; label < labelOffsets.length; label++) {
+                if (labelOffsets[label] === operationIndex) {
+                    flushLabel();
+                    if (labelExpressions !== undefined) {
+                        const expressions = labelExpressions[label];
+                        if (expressions !== undefined) {
+                            for (const expression of expressions) {
+                                expression.text = String(labelNumber);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Tries to enter or leave a code block.
+         */
+        function tryEnterOrLeaveBlock(operationIndex: number): void {
+            if (blocks) {
+                for (; blockIndex < blockActions.length && blockOffsets[blockIndex] <= operationIndex; blockIndex++) {
+                    const block = blocks[blockIndex];
+                    const blockAction = blockActions[blockIndex];
+                    if (isExceptionBlock(block)) {
+                        if (blockAction === BlockAction.Open) {
+                            if (!exceptionBlockStack) {
+                                exceptionBlockStack = [];
+                            }
+
+                            if (!statements) {
+                                statements = [];
+                            }
+
+                            exceptionBlockStack.push(currentExceptionBlock);
+                            currentExceptionBlock = block;
+                        }
+                        else if (blockAction === BlockAction.Close) {
+                            currentExceptionBlock = exceptionBlockStack.pop();
+                        }
+                    }
+                    else if (isWithBlock(block)) {
+                        if (blockAction === BlockAction.Open) {
+                            if (!withBlockStack) {
+                                withBlockStack = [];
+                            }
+
+                            withBlockStack.push(block);
+                        }
+                        else if (blockAction === BlockAction.Close) {
+                            withBlockStack.pop();
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Writes an operation as a statement to the current label's statement list.
+         *
+         * @param operation The OpCode of the operation
+         */
+        function writeOperation(operationIndex: number): void {
+            tryEnterLabel(operationIndex);
+            tryEnterOrLeaveBlock(operationIndex);
+
+            // early termination, nothing else to process in this label
+            if (lastOperationWasAbrupt) {
+                return;
+            }
+
+            lastOperationWasAbrupt = false;
+            lastOperationWasCompletion = false;
+
+            const opcode = operations[operationIndex];
+            if (opcode === OpCode.Nop) {
+                return;
+            }
+            else if (opcode === OpCode.Endfinally) {
+                return writeEndfinally();
+            }
+
+            const args = operationArguments[operationIndex];
+            if (opcode === OpCode.Statement) {
+                return writeStatement(<Statement>args[0]);
+            }
+
+            const location = operationLocations[operationIndex];
+            switch (opcode) {
+                case OpCode.Assign:
+                    return writeAssign(<Expression>args[0], <Expression>args[1], location);
+                case OpCode.Break:
+                    return writeBreak(<Label>args[0], location);
+                case OpCode.BreakWhenTrue:
+                    return writeBreakWhenTrue(<Label>args[0], <Expression>args[1], location);
+                case OpCode.BreakWhenFalse:
+                    return writeBreakWhenFalse(<Label>args[0], <Expression>args[1], location);
+                case OpCode.Yield:
+                    return writeYield(<Expression>args[0], location);
+                case OpCode.YieldStar:
+                    return writeYieldStar(<Expression>args[0], location);
+                case OpCode.Return:
+                    return writeReturn(<Expression>args[0], location);
+                case OpCode.Throw:
+                    return writeThrow(<Expression>args[0], location);
+            }
+        }
+
+        /**
+         * Writes a statement to the current label's statement list.
+         *
+         * @param statement A statement to write.
+         */
+        function writeStatement(statement: Statement): void {
+            if (statement) {
+                if (!statements) {
+                    statements = [statement];
+                }
+                else {
+                    statements.push(statement);
+                }
+            }
+        }
+
+        /**
+         * Writes an Assign operation to the current label's statement list.
+         *
+         * @param left The left-hand side of the assignment.
+         * @param right The right-hand side of the assignment.
+         * @param operationLocation The source map location for the operation.
+         */
+        function writeAssign(left: Expression, right: Expression, operationLocation: TextRange): void {
+            writeStatement(createStatement(createAssignment(left, right), operationLocation));
+        }
+
+        /**
+         * Writes a Throw operation to the current label's statement list.
+         *
+         * @param expression The value to throw.
+         * @param operationLocation The source map location for the operation.
+         */
+        function writeThrow(expression: Expression, operationLocation: TextRange): void {
+            lastOperationWasAbrupt = true;
+            lastOperationWasCompletion = true;
+            writeStatement(createThrow(expression, operationLocation));
+        }
+
+        /**
+         * Writes a Return operation to the current label's statement list.
+         *
+         * @param expression The value to return.
+         * @param operationLocation The source map location for the operation.
+         */
+        function writeReturn(expression: Expression, operationLocation: TextRange): void {
+            lastOperationWasAbrupt = true;
+            lastOperationWasCompletion = true;
+            writeStatement(
+                createReturn(
+                    createArrayLiteral(expression
+                        ? [createInstruction(Instruction.Return), expression]
+                        : [createInstruction(Instruction.Return)]
+                    ),
+                    operationLocation
+                )
+            );
+        }
+
+        /**
+         * Writes a Break operation to the current label's statement list.
+         *
+         * @param label The label for the Break.
+         * @param operationLocation The source map location for the operation.
+         */
+        function writeBreak(label: Label, operationLocation: TextRange): void {
+            lastOperationWasAbrupt = true;
+            writeStatement(
+                createReturn(
+                    createArrayLiteral([
+                        createInstruction(Instruction.Break),
+                        createLabel(label)
+                    ]),
+                    operationLocation
+                )
+            );
+        }
+
+        /**
+         * Writes a BreakWhenTrue operation to the current label's statement list.
+         *
+         * @param label The label for the Break.
+         * @param condition The condition for the Break.
+         * @param operationLocation The source map location for the operation.
+         */
+        function writeBreakWhenTrue(label: Label, condition: Expression, operationLocation: TextRange): void {
+            writeStatement(
+                createIf(
+                    condition,
+                    createReturn(
+                        createArrayLiteral([
+                            createInstruction(Instruction.Break),
+                            createLabel(label)
+                        ]),
+                        operationLocation
+                    )
+                )
+            );
+        }
+
+        /**
+         * Writes a BreakWhenFalse operation to the current label's statement list.
+         *
+         * @param label The label for the Break.
+         * @param condition The condition for the Break.
+         * @param operationLocation The source map location for the operation.
+         */
+        function writeBreakWhenFalse(label: Label, condition: Expression, operationLocation: TextRange): void {
+            writeStatement(
+                createIf(
+                    createLogicalNot(condition),
+                    createReturn(
+                        createArrayLiteral([
+                            createInstruction(Instruction.Break),
+                            createLabel(label)
+                        ]),
+                        operationLocation
+                    )
+                )
+            );
+        }
+
+        /**
+         * Writes a Yield operation to the current label's statement list.
+         *
+         * @param expression The expression to yield.
+         * @param operationLocation The source map location for the operation.
+         */
+        function writeYield(expression: Expression, operationLocation: TextRange): void {
+            lastOperationWasAbrupt = true;
+            writeStatement(
+                createReturn(
+                    createArrayLiteral(
+                        expression
+                            ? [createInstruction(Instruction.Yield), expression]
+                            : [createInstruction(Instruction.Yield)]
+                    ),
+                    operationLocation
+                )
+            );
+        }
+
+        /**
+         * Writes a YieldStar instruction to the current label's statement list.
+         *
+         * @param expression The expression to yield.
+         * @param operationLocation The source map location for the operation.
+         */
+        function writeYieldStar(expression: Expression, operationLocation: TextRange): void {
+            lastOperationWasAbrupt = true;
+            writeStatement(
+                createReturn(
+                    createArrayLiteral([
+                        createInstruction(Instruction.YieldStar),
+                        expression
+                    ]),
+                    operationLocation
+                )
+            );
+        }
+
+        /**
+         * Writes an Endfinally instruction to the current label's statement list.
+         */
+        function writeEndfinally(): void {
+            lastOperationWasAbrupt = true;
+            writeStatement(
+                createReturn(
+                    createArrayLiteral([
+                        createInstruction(Instruction.Endfinally)
+                    ])
+                )
+            );
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts
index 68154443ce953..cb5d19e1f3b7c 100644
--- a/src/compiler/transformers/module/module.ts
+++ b/src/compiler/transformers/module/module.ts
@@ -229,7 +229,7 @@ namespace ts {
                             // import * as n from "mod";
                             addNode(variables,
                                 createVariableDeclaration(
-                                    getSynthesizedNode(namespaceDeclaration.name),
+                                    getSynthesizedClone(namespaceDeclaration.name),
                                     createRequireCall(node)
                                 )
                             );
@@ -249,7 +249,7 @@ namespace ts {
                             if (namespaceDeclaration && isDefaultImport(node)) {
                                 addNode(variables,
                                     createVariableDeclaration(
-                                        getSynthesizedNode(namespaceDeclaration.name),
+                                        getSynthesizedClone(namespaceDeclaration.name),
                                         getGeneratedNameForNode(node)
                                     )
                                 );
@@ -272,7 +272,7 @@ namespace ts {
                             /*modifiers*/ undefined,
                             createVariableDeclarationList([
                                 createVariableDeclaration(
-                                    getSynthesizedNode(namespaceDeclaration.name),
+                                    getSynthesizedClone(namespaceDeclaration.name),
                                     getGeneratedNameForNode(node),
                                     /*location*/ node
                                 )
@@ -309,7 +309,7 @@ namespace ts {
                                 /*modifiers*/ undefined,
                                 createVariableDeclarationList([
                                     createVariableDeclaration(
-                                        getSynthesizedNode(node.name),
+                                        getSynthesizedClone(node.name),
                                         createRequireCall(node),
                                         /*location*/ node
                                     )
@@ -519,7 +519,7 @@ namespace ts {
                     );
 
                     if (node.flags & NodeFlags.Default) {
-                        addExportDefault(statements, getSynthesizedNode(node.name), /*location*/ node);
+                        addExportDefault(statements, getSynthesizedClone(node.name), /*location*/ node);
                     }
                 }
                 else {
@@ -559,7 +559,7 @@ namespace ts {
                     );
 
                     if (node.flags & NodeFlags.Default) {
-                        addExportDefault(statements, getSynthesizedNode(node.name), /*location*/ node);
+                        addExportDefault(statements, getSynthesizedClone(node.name), /*location*/ node);
                     }
                 }
                 else {
@@ -598,7 +598,7 @@ namespace ts {
             if (container && container.kind === SyntaxKind.SourceFile) {
                 return createPropertyAccess(
                     createIdentifier("exports"),
-                    getSynthesizedNode(node),
+                    getSynthesizedClone(node),
                     /*location*/ node
                 );
             }
@@ -638,7 +638,7 @@ namespace ts {
             const moduleName = getExternalModuleName(importNode);
             if (moduleName.kind === SyntaxKind.StringLiteral) {
                 return tryRenameExternalModule(<StringLiteral>moduleName)
-                    || getSynthesizedNode(<StringLiteral>moduleName);
+                    || getSynthesizedClone(<StringLiteral>moduleName);
             }
 
             return undefined;
@@ -685,7 +685,7 @@ namespace ts {
                     )
                     : createPropertyAccess(
                         createIdentifier("exports"),
-                        getSynthesizedNode(name)
+                        getSynthesizedClone(name)
                     ),
                 value
             );
diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts
index bf692936800b7..f27b0026be5be 100644
--- a/src/compiler/transformers/module/system.ts
+++ b/src/compiler/transformers/module/system.ts
@@ -11,7 +11,6 @@ namespace ts {
 
         const {
             getGeneratedNameForNode,
-            makeUniqueName,
             startLexicalEnvironment,
             endLexicalEnvironment,
             hoistVariableDeclaration,
@@ -83,8 +82,8 @@ namespace ts {
 
             // Make sure that the name of the 'exports' function does not conflict with
             // existing identifiers.
-            exportFunctionForFile = makeUniqueName("exports");
-            contextObjectForFile = makeUniqueName("context");
+            exportFunctionForFile = createUniqueName("exports");
+            contextObjectForFile = createUniqueName("context");
 
             const dependencyGroups = collectDependencyGroups(externalImports);
 
@@ -299,7 +298,7 @@ namespace ts {
                 }
             }
 
-            const exportedNamesStorageRef = makeUniqueName("exportedNames");
+            const exportedNamesStorageRef = createUniqueName("exportedNames");
             addNode(statements,
                 createVariableStatement(
                     /*modifiers*/ undefined,
@@ -323,7 +322,7 @@ namespace ts {
             const setters: Expression[] = [];
             for (const group of dependencyGroups) {
                 // derive a unique name for parameter from the first named entry in the group
-                const parameterName = makeUniqueName(forEach(group.externalImports, getLocalNameTextForExternalImport) || "");
+                const parameterName = createUniqueName(forEach(group.externalImports, getLocalNameTextForExternalImport) || "");
                 const statements: Statement[] = [];
                 for (const entry of group.externalImports) {
                     const importVariableName = getLocalNameForExternalImport(entry);
@@ -705,7 +704,7 @@ namespace ts {
         function visitForInStatement(node: ForInStatement): ForInStatement {
             const initializer = node.initializer;
             if (isVariableDeclarationList(initializer)) {
-                const updated = getMutableNode(node);
+                const updated = getMutableClone(node);
                 updated.initializer = transformForBinding(initializer);
                 updated.statement = visitNode(node.statement, visitNestedNode, isStatement, /*optional*/ false, liftToBlock);
                 return updated;
@@ -723,7 +722,7 @@ namespace ts {
         function visitForOfStatement(node: ForOfStatement): ForOfStatement {
             const initializer = node.initializer;
             if (isVariableDeclarationList(initializer)) {
-                const updated = getMutableNode(node);
+                const updated = getMutableClone(node);
                 updated.initializer = transformForBinding(initializer);
                 updated.statement = visitNode(node.statement, visitNestedNode, isStatement, /*optional*/ false, liftToBlock);
                 return updated;
@@ -741,7 +740,7 @@ namespace ts {
         function visitDoStatement(node: DoStatement) {
             const statement = visitNode(node.statement, visitNestedNode, isStatement, /*optional*/ false, liftToBlock);
             if (statement !== node.statement) {
-                const updated = getMutableNode(node);
+                const updated = getMutableClone(node);
                 updated.statement = statement;
                 return updated;
             }
@@ -756,7 +755,7 @@ namespace ts {
         function visitWhileStatement(node: WhileStatement) {
             const statement = visitNode(node.statement, visitNestedNode, isStatement, /*optional*/ false, liftToBlock);
             if (statement !== node.statement) {
-                const updated = getMutableNode(node);
+                const updated = getMutableClone(node);
                 updated.statement = statement;
                 return updated;
             }
@@ -771,7 +770,7 @@ namespace ts {
         function visitLabeledStatement(node: LabeledStatement) {
             const statement = visitNode(node.statement, visitNestedNode, isStatement, /*optional*/ false, liftToBlock);
             if (statement !== node.statement) {
-                const updated = getMutableNode(node);
+                const updated = getMutableClone(node);
                 updated.statement = statement;
                 return updated;
             }
@@ -786,7 +785,7 @@ namespace ts {
         function visitWithStatement(node: WithStatement) {
             const statement = visitNode(node.statement, visitNestedNode, isStatement, /*optional*/ false, liftToBlock);
             if (statement !== node.statement) {
-                const updated = getMutableNode(node);
+                const updated = getMutableClone(node);
                 updated.statement = statement;
                 return updated;
             }
@@ -801,7 +800,7 @@ namespace ts {
         function visitSwitchStatement(node: SwitchStatement) {
             const caseBlock = visitNode(node.caseBlock, visitNestedNode, isCaseBlock);
             if (caseBlock !== node.caseBlock) {
-                const updated = getMutableNode(node);
+                const updated = getMutableClone(node);
                 updated.caseBlock = caseBlock;
                 return updated;
             }
@@ -816,7 +815,7 @@ namespace ts {
         function visitCaseBlock(node: CaseBlock) {
             const clauses = visitNodes(node.clauses, visitNestedNode, isCaseOrDefaultClause);
             if (clauses !== node.clauses) {
-                const updated = getMutableNode(node);
+                const updated = getMutableClone(node);
                 updated.clauses = clauses;
                 return updated;
             }
@@ -831,7 +830,7 @@ namespace ts {
         function visitCaseClause(node: CaseClause) {
             const statements = visitNodes(node.statements, visitNestedNode, isStatement);
             if (statements !== node.statements) {
-                const updated = getMutableNode(node);
+                const updated = getMutableClone(node);
                 updated.statements = statements;
                 return updated;
             }
@@ -864,7 +863,7 @@ namespace ts {
         function visitCatchClause(node: CatchClause) {
             const block = visitNode(node.block, visitNestedNode, isBlock);
             if (block !== node.block) {
-                const updated = getMutableNode(node);
+                const updated = getMutableClone(node);
                 updated.block = block;
                 return updated;
             }
@@ -1055,7 +1054,7 @@ namespace ts {
             const moduleName = getExternalModuleName(importNode);
             if (moduleName.kind === SyntaxKind.StringLiteral) {
                 return tryRenameExternalModule(<StringLiteral>moduleName)
-                    || getSynthesizedNode(<StringLiteral>moduleName);
+                    || getSynthesizedClone(<StringLiteral>moduleName);
             }
 
             return undefined;
@@ -1096,11 +1095,11 @@ namespace ts {
          * @param node The declaration statement.
          */
         function getDeclarationName(node: DeclarationStatement) {
-            return node.name ? getSynthesizedNode(node.name) : getGeneratedNameForNode(node);
+            return node.name ? getSynthesizedClone(node.name) : getGeneratedNameForNode(node);
         }
 
         function addExportStarFunction(statements: Statement[], localNames: Identifier) {
-            const exportStarFunction = makeUniqueName("exportStar");
+            const exportStarFunction = createUniqueName("exportStar");
             const m = createIdentifier("m");
             const n = createIdentifier("n");
             const exports = createIdentifier("exports");
@@ -1204,7 +1203,7 @@ namespace ts {
                 return createElementAccess(importAlias, createLiteral(name.text));
             }
             else {
-                return createPropertyAccess(importAlias, getSynthesizedNode(name));
+                return createPropertyAccess(importAlias, getSynthesizedClone(name));
             }
         }
 
@@ -1256,7 +1255,7 @@ namespace ts {
         function hoistBindingElement(node: VariableDeclaration | BindingElement, isExported: boolean) {
             const name = node.name;
             if (isIdentifier(name)) {
-                hoistVariableDeclaration(getSynthesizedNode(name));
+                hoistVariableDeclaration(getSynthesizedClone(name));
                 if (isExported) {
                     recordExportName(name);
                 }
diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts
index b2522d694b161..3171aa97edfde 100644
--- a/src/compiler/transformers/ts.ts
+++ b/src/compiler/transformers/ts.ts
@@ -9,7 +9,6 @@ namespace ts {
     export function transformTypeScript(context: TransformationContext) {
         const {
             getGeneratedNameForNode,
-            makeUniqueName,
             setNodeEmitFlags,
             startLexicalEnvironment,
             endLexicalEnvironment,
@@ -502,7 +501,7 @@ namespace ts {
                 // Record an alias to avoid class double-binding.
                 if (resolver.getNodeCheckFlags(getOriginalNode(node)) & NodeCheckFlags.ClassWithBodyScopedClassBinding) {
                     enableExpressionSubstitutionForDecoratedClasses();
-                    decoratedClassAlias = makeUniqueName(node.name ? node.name.text : "default");
+                    decoratedClassAlias = createUniqueName(node.name ? node.name.text : "default");
                     decoratedClassAliases[getOriginalNodeId(node)] = decoratedClassAlias;
 
                     // We emit the class alias as a `let` declaration here so that it has the same
@@ -697,7 +696,7 @@ namespace ts {
         function transformConstructorParameters(constructor: ConstructorDeclaration, hasExtendsClause: boolean) {
             return constructor
                 ? visitNodes(constructor.parameters, visitor, isParameter)
-                : hasExtendsClause ? [createRestParameter(makeUniqueName("args"))] : [];
+                : hasExtendsClause ? [createRestParameter(createUniqueName("args"))] : [];
         }
 
         /**
@@ -1667,7 +1666,7 @@ namespace ts {
                 return createLiteral(name.text);
             }
             else {
-                return getSynthesizedNode(name);
+                return getSynthesizedClone(name);
             }
         }
 
@@ -1836,7 +1835,7 @@ namespace ts {
             if (isNamespaceExport(node)) {
                 return createNodeArrayNode([
                     func,
-                    createNamespaceExport(getSynthesizedNode(node.name), getSynthesizedNode(node.name))
+                    createNamespaceExport(getSynthesizedClone(node.name), getSynthesizedClone(node.name))
                 ]);
             }
 
@@ -2136,7 +2135,7 @@ namespace ts {
 
             const name = isNamespaceExport(node)
                 ? getNamespaceMemberName(node.name)
-                : getSynthesizedNode(node.name);
+                : getSynthesizedClone(node.name);
 
             currentNamespaceLocalName = getGeneratedNameForNode(node);
             addNode(statements,
@@ -2352,7 +2351,7 @@ namespace ts {
 
             const name = isNamespaceExport(node)
                 ? getNamespaceMemberName(node.name)
-                : getSynthesizedNode(node.name);
+                : getSynthesizedClone(node.name);
 
             let moduleParam: Expression = createLogicalOr(
                 name,
@@ -2463,7 +2462,7 @@ namespace ts {
                 // exports.${name} = ${moduleReference};
                 return setOriginalNode(
                     createNamespaceExport(
-                        getSynthesizedNode(node.name),
+                        getSynthesizedClone(node.name),
                         moduleReference,
                         node
                     ),
@@ -2551,11 +2550,11 @@ namespace ts {
         }
 
         function getNamespaceMemberName(name: Identifier): Expression {
-            return createPropertyAccess(currentNamespaceLocalName, getSynthesizedNode(name));
+            return createPropertyAccess(currentNamespaceLocalName, getSynthesizedClone(name));
         }
 
         function getDeclarationName(node: ClassExpression | ClassDeclaration | FunctionDeclaration | EnumDeclaration) {
-            return node.name ? getSynthesizedNode(node.name) : getGeneratedNameForNode(node);
+            return node.name ? getSynthesizedClone(node.name) : getGeneratedNameForNode(node);
         }
 
         function getClassPrototype(node: ClassExpression | ClassDeclaration) {
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 6a55153f63141..805d91056e121 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -497,16 +497,18 @@ namespace ts {
     // @kind(SyntaxKind.StaticKeyword)
     export interface Modifier extends Node { }
 
-    export const enum TempVariableKind {
+    export const enum GeneratedIdentifierKind {
+        None,   // Not automatically generated
         Auto,   // Automatically generated identifier
         Loop,   // Automatically generated identifier with a preference for '_i'
+        Unique, // Automatically generated identifier based on specified text
     }
 
     // @kind(SyntaxKind.Identifier)
     export interface Identifier extends PrimaryExpression {
         text: string;                                  // Text of identifier (with escapes converted to characters)
-        tempKind?: TempVariableKind;                   // Specifies whether to auto-generate the text for an identifier.
         originalKeywordKind?: SyntaxKind;              // Original syntaxKind which get set so that we can report an error later
+        tempKind?: GeneratedIdentifierKind;            // Specifies whether to auto-generate the text for an identifier.
     }
 
     // @kind(SyntaxKind.QualifiedName)
@@ -944,13 +946,18 @@ namespace ts {
     // The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral,
     // or any literal of a template, this means quotes have been removed and escapes have been converted to actual characters.
     // For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
-    // @kind(SyntaxKind.NumericLiteral)
     // @kind(SyntaxKind.RegularExpressionLiteral)
     // @kind(SyntaxKind.NoSubstitutionTemplateLiteral)
     export interface LiteralExpression extends LiteralLikeNode, PrimaryExpression {
         _literalExpressionBrand: any;
     }
 
+    // @kind(SyntaxKind.NumericLiteral)
+    export interface NumericLiteral extends LiteralExpression {
+        _numericLiteralBrand: any;
+        trailingComment?: string;
+    }
+
     // @kind(SyntaxKind.TemplateHead)
     // @kind(SyntaxKind.TemplateMiddle)
     // @kind(SyntaxKind.TemplateTail)
@@ -2759,18 +2766,20 @@ namespace ts {
         ContainsES7 = 1 << 5,
         ES6 = 1 << 6,
         ContainsES6 = 1 << 7,
+        ContainsGenerators = 1 << 8,
 
         // Markers
         // - Flags used to indicate that a subtree contains a specific transformation.
-        ContainsDecorators = 1 << 8,
-        ContainsPropertyInitializer = 1 << 9,
-        ContainsLexicalThis = 1 << 10,
-        ContainsCapturedLexicalThis = 1 << 11,
-        ContainsDefaultValueAssignments = 1 << 12,
-        ContainsParameterPropertyAssignments = 1 << 13,
-        ContainsSpreadElementExpression = 1 << 14,
-        ContainsComputedPropertyName = 1 << 15,
-        ContainsBlockScopedBinding = 1 << 16,
+        ContainsDecorators = 1 << 9,
+        ContainsPropertyInitializer = 1 << 10,
+        ContainsLexicalThis = 1 << 11,
+        ContainsCapturedLexicalThis = 1 << 12,
+        ContainsDefaultValueAssignments = 1 << 13,
+        ContainsParameterPropertyAssignments = 1 << 14,
+        ContainsSpreadElementExpression = 1 << 15,
+        ContainsComputedPropertyName = 1 << 16,
+        ContainsBlockScopedBinding = 1 << 17,
+        ContainsYield = 1 << 18,
 
         // Assertions
         // - Bitmasks that are used to assert facts about the syntax of a node and its subtree.
@@ -2783,10 +2792,10 @@ namespace ts {
         // - Bitmasks that exclude flags from propagating out of a specific context
         //   into the subtree flags of their container.
         NodeExcludes = TypeScript | Jsx | ES7 | ES6,
-        ArrowFunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding,
-        FunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding,
-        ConstructorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
-        MethodOrAccessorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
+        ArrowFunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield,
+        FunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield,
+        ConstructorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield,
+        MethodOrAccessorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield,
         ClassExcludes = ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsParameterPropertyAssignments,
         ModuleExcludes = ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
         TypeExcludes = ~ContainsTypeScript,
@@ -2825,10 +2834,8 @@ namespace ts {
         setNodeEmitFlags<T extends Node>(node: T, flags: NodeEmitFlags): T;
         hoistFunctionDeclaration(node: FunctionDeclaration): void;
         hoistVariableDeclaration(node: Identifier): void;
-        isUniqueName(name: string): boolean;
         getGeneratedNameForNode(node: Node): Identifier;
         nodeHasGeneratedName(node: Node): boolean;
-        makeUniqueName(baseName: string): Identifier;
 
         /**
          * Hook used by transformers to substitute non-expression identifiers
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 86f1c2a2b73bd..8cb94a8d09983 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -2563,6 +2563,12 @@ namespace ts {
         return 0;
     }
 
+    export function isLogicalOperator(token: SyntaxKind): boolean {
+        return token === SyntaxKind.BarBarToken
+            || token === SyntaxKind.AmpersandAmpersandToken
+            || token === SyntaxKind.ExclamationToken;
+    }
+
     export function isAssignmentOperator(token: SyntaxKind): boolean {
         return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment;
     }
@@ -3003,6 +3009,10 @@ namespace ts {
         return node.kind === SyntaxKind.Identifier;
     }
 
+    export function isGeneratedIdentifier(node: Node): node is Identifier {
+        return isIdentifier(node) && node.tempKind > GeneratedIdentifierKind.None;
+    }
+
     // Keywords
 
     export function isModifier(node: Node): node is Modifier {
diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts
index a5e82c6a04996..03f6c0efb976b 100644
--- a/src/compiler/visitor.ts
+++ b/src/compiler/visitor.ts
@@ -134,7 +134,7 @@ namespace ts {
             { name: "arguments", test: isExpression },
         ],
         [SyntaxKind.NewExpression]: [
-            { name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
+            { name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForNew },
             { name: "typeArguments", test: isTypeNode },
             { name: "arguments", test: isExpression },
         ],
@@ -630,7 +630,7 @@ namespace ts {
 
                     if (updated !== undefined || visited !== value) {
                         if (updated === undefined) {
-                            updated = getMutableNode(node);
+                            updated = getMutableClone(node);
                             updated.flags &= ~NodeFlags.Modifier;
                         }
 
@@ -897,8 +897,9 @@ namespace ts {
     /**
      * Aggregates the TransformFlags for a Node and its subtree.
      */
-    export function aggregateTransformFlags(node: Node): void {
+    export function aggregateTransformFlags<T extends Node>(node: T): T {
         aggregateTransformFlagsForNode(node);
+        return node;
     }
 
     /**

From c267691d8a967edda1cd58b3d340c64412efa3d0 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Wed, 2 Mar 2016 16:45:14 -0800
Subject: [PATCH 02/23] Fixed labels

---
 src/compiler/factory.ts                 |  4 +++
 src/compiler/printer.ts                 | 17 ++++++++++-
 src/compiler/transformers/es6.ts        | 13 +++++++++
 src/compiler/transformers/generators.ts | 39 ++++++++++++++++++++-----
 4 files changed, 65 insertions(+), 8 deletions(-)

diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts
index e12a7730703f5..a39919ce68115 100644
--- a/src/compiler/factory.ts
+++ b/src/compiler/factory.ts
@@ -1498,6 +1498,10 @@ namespace ts {
     }
 
     export function parenthesizeExpressionForList(expression: Expression) {
+        if (expression.kind === SyntaxKind.OmittedExpression) {
+            return expression;
+        }
+
         const expressionPrecedence = getExpressionPrecedence(expression);
         const commaPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, SyntaxKind.CommaToken);
         return expressionPrecedence > commaPrecedence
diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts
index 6d7cb9ab4ba37..7040362fa8f48 100644
--- a/src/compiler/printer.ts
+++ b/src/compiler/printer.ts
@@ -827,6 +827,13 @@ const _super = (function (geti, seti) {
                 else {
                     write(text);
                 }
+
+                if (node.kind === SyntaxKind.NumericLiteral) {
+                    const trailingComment = (<NumericLiteral>node).trailingComment;
+                    if (trailingComment) {
+                        write(` /*${trailingComment}*/`);
+                    }
+                }
             }
 
             //
@@ -1893,7 +1900,7 @@ const _super = (function (geti, seti) {
             }
 
             function emitCaseOrDefaultClauseStatements(parentNode: Node, statements: NodeArray<Statement>) {
-                if (statements.length === 1 && rangeStartPositionsAreOnSameLine(parentNode, statements[0])) {
+                if (statements.length === 1 && shouldEmitCaseOrDefaultClauseStatementOnSameLine(parentNode, statements[0])) {
                     write(" ");
                     emit(statements[0]);
                 }
@@ -1902,6 +1909,14 @@ const _super = (function (geti, seti) {
                 }
             }
 
+            function shouldEmitCaseOrDefaultClauseStatementOnSameLine(parentNode: Node, statement: Statement) {
+                if (statement.startsOnNewLine || nodeIsSynthesized(parentNode)) {
+                    return false;
+                }
+
+                return nodeIsSynthesized(statement) || rangeStartPositionsAreOnSameLine(parentNode, statement);
+            }
+
             function emitHeritageClause(node: HeritageClause) {
                 emitStart(node);
                 write(" ");
diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts
index ee8875465121e..a1e370e23947d 100644
--- a/src/compiler/transformers/es6.ts
+++ b/src/compiler/transformers/es6.ts
@@ -163,6 +163,9 @@ namespace ts {
                 case SyntaxKind.TemplateExpression:
                     return visitTemplateExpression(<TemplateExpression>node);
 
+                case SyntaxKind.YieldExpression:
+                    return visitYieldExpression(<YieldExpression>node);
+
                 case SyntaxKind.SuperKeyword:
                     return visitSuperKeyword(<PrimaryExpression>node);
 
@@ -1496,6 +1499,16 @@ namespace ts {
             );
         }
 
+        /**
+         * Visits a YieldExpression node.
+         *
+         * @param node A YieldExpression node.
+         */
+        function visitYieldExpression(node: YieldExpression): Expression {
+            // `yield` expressions are transformed using the generators transformer.
+            return visitEachChild(node, visitor, context);
+        }
+
         /**
          * Visits an ArrayLiteralExpression that contains a spread element.
          *
diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts
index 8fd9a9e1c63cd..073cf50c90a3c 100644
--- a/src/compiler/transformers/generators.ts
+++ b/src/compiler/transformers/generators.ts
@@ -283,6 +283,7 @@ namespace ts {
         //
         let blockIndex = 0; // The index of the current block.
         let labelNumber = 0; // The current label number.
+        let labelNumbers: number[][];
         let lastOperationWasAbrupt: boolean; // Indicates whether the last operation was abrupt (break/continue).
         let lastOperationWasCompletion: boolean; // Indicates whether the last operation was a completion (return/throw).
         let clauses: CaseClause[]; // The case clauses generated for labels.
@@ -391,7 +392,7 @@ namespace ts {
                 case SyntaxKind.SetAccessor:
                     return visitAccessorDeclaration(<AccessorDeclaration>node);
                 default:
-                    if (node.transformFlags & TransformFlags.ContainsGenerators) {
+                    if (node.transformFlags & TransformFlags.ContainsGenerators || containsYield(node)) {
                         return visitEachChild(node, visitor, context);
                     }
                     else {
@@ -2497,6 +2498,7 @@ namespace ts {
         function build() {
             blockIndex = 0;
             labelNumber = 0;
+            labelNumbers = undefined;
             lastOperationWasAbrupt = false;
             lastOperationWasCompletion = false;
             clauses = undefined;
@@ -2537,7 +2539,6 @@ namespace ts {
                 flushFinalLabel(0);
             }
 
-
             if (clauses) {
                 const state = getState();
                 const labelExpression = createPropertyAccess(state, "label");
@@ -2590,6 +2591,8 @@ namespace ts {
             if (statements && clauses) {
                 appendLabel(/*markLabelEnd*/ false);
             }
+
+            updateLabelExpressions();
         }
 
         /**
@@ -2674,11 +2677,33 @@ namespace ts {
             for (let label = 0; label < labelOffsets.length; label++) {
                 if (labelOffsets[label] === operationIndex) {
                     flushLabel();
-                    if (labelExpressions !== undefined) {
-                        const expressions = labelExpressions[label];
-                        if (expressions !== undefined) {
-                            for (const expression of expressions) {
-                                expression.text = String(labelNumber);
+                    if (labelNumbers === undefined) {
+                        labelNumbers = [];
+                    }
+                    if (labelNumbers[labelNumber] === undefined) {
+                        labelNumbers[labelNumber] = [label]
+                    }
+                    else {
+                        labelNumbers[labelNumber].push(label);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Updates literal expressions for labels with actual label numbers.
+         */
+        function updateLabelExpressions() {
+            if (labelExpressions !== undefined && labelNumbers !== undefined) {
+                for (let labelNumber = 0; labelNumber < labelNumbers.length; labelNumber++) {
+                    const labels = labelNumbers[labelNumber];
+                    if (labels !== undefined) {
+                        for (const label of labels) {
+                            const expressions = labelExpressions[label];
+                            if (expressions !== undefined) {
+                                for (const expression of expressions) {
+                                    expression.text = String(labelNumber);
+                                }
                             }
                         }
                     }

From 4ae83fa8d351e767478f5f94f27c14e56cdf1635 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Tue, 17 May 2016 22:44:19 -0700
Subject: [PATCH 03/23] Fix issues after merge

---
 src/compiler/factory.ts                 | 82 ++++++++++++-------------
 src/compiler/printer.ts                 |  8 ---
 src/compiler/transformers/generators.ts | 34 +++++++---
 3 files changed, 65 insertions(+), 59 deletions(-)

diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts
index 06a7bb66e715e..768ec165d8e71 100644
--- a/src/compiler/factory.ts
+++ b/src/compiler/factory.ts
@@ -112,7 +112,7 @@ namespace ts {
 
     export function createLiteral(textSource: StringLiteral | Identifier, location?: TextRange, emitOptions?: NodeEmitOptions): StringLiteral;
     export function createLiteral(value: string, location?: TextRange, emitOptions?: NodeEmitOptions): StringLiteral;
-    export function createLiteral(value: number, location?: TextRange, emitOptions?: NodeEmitOptions): LiteralExpression;
+    export function createLiteral(value: number, location?: TextRange, emitOptions?: NodeEmitOptions): NumericLiteral;
     export function createLiteral(value: string | number | boolean, location?: TextRange, emitOptions?: NodeEmitOptions): PrimaryExpression;
     export function createLiteral(value: string | number | boolean | StringLiteral | Identifier, location?: TextRange, emitOptions?: NodeEmitOptions): PrimaryExpression {
         if (typeof value === "number") {
@@ -505,7 +505,7 @@ namespace ts {
         return node;
     }
 
-    export function createCaseBlock(clauses: CaseClause[], location?: TextRange): CaseBlock {
+    export function createCaseBlock(clauses: CaseOrDefaultClause[], location?: TextRange): CaseBlock {
         const node = <CaseBlock>createNode(SyntaxKind.CaseBlock, location);
         node.clauses = createNodeArray(clauses);
         return node;
@@ -570,13 +570,6 @@ namespace ts {
         return node;
     }
 
-    export function createSwitch(expression: Expression, caseBlock: CaseBlock, location?: TextRange): ReturnStatement {
-        const node = <SwitchStatement>createNode(SyntaxKind.SwitchStatement, location);
-        node.expression = expression;
-        node.caseBlock = caseBlock;
-        return node;
-    }
-
     export function createThrow(expression: Expression, location?: TextRange): ReturnStatement {
         const node = <ThrowStatement>createNode(SyntaxKind.ThrowStatement, location);
         node.expression = expression;
@@ -626,12 +619,6 @@ namespace ts {
         return node;
     }
 
-    export function createCaseBlock(clauses: CaseOrDefaultClause[], location?: TextRange) {
-        const node = <CaseBlock>createNode(SyntaxKind.CaseBlock, location);
-        node.clauses = createNodeArray(clauses);
-        return node;
-    }
-
     export function createExportDefault(expression: Expression) {
         const node = <ExportAssignment>createNode(SyntaxKind.ExportAssignment);
         node.isExportEquals = false;
@@ -1262,34 +1249,47 @@ namespace ts {
     function createExpressionForAccessorDeclaration(properties: NodeArray<Declaration>, property: AccessorDeclaration, receiver: Expression, multiLine: boolean) {
         const { firstAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(properties, property);
         if (property === firstAccessor) {
-            return aggregateTransformFlags(
-                createObjectDefineProperty(
+            const properties: ObjectLiteralElement[] = [];
+            if (getAccessor) {
+                const getterFunction = createFunctionExpression(
+                    /*asteriskToken*/ undefined,
+                    /*name*/ undefined,
+                    getAccessor.parameters,
+                    getAccessor.body,
+                    /*location*/ getAccessor,
+                    /*original*/ getAccessor
+                );
+                const getter = createPropertyAssignment("get", getterFunction);
+                properties.push(getter);
+            }
+
+            if (setAccessor) {
+                const setterFunction = createFunctionExpression(
+                    /*asteriskToken*/ undefined,
+                    /*name*/ undefined,
+                    setAccessor.parameters,
+                    setAccessor.body,
+                    /*location*/ setAccessor,
+                    /*original*/ setAccessor
+                );
+                const setter = createPropertyAssignment("set", setterFunction);
+                properties.push(setter);
+            }
+
+            properties.push(createPropertyAssignment("enumerable", createLiteral(true)));
+            properties.push(createPropertyAssignment("configurable", createLiteral(true)));
+
+            const expression = createCall(
+                createPropertyAccess(createIdentifier("Object"), "defineProperty"),
+                [
                     receiver,
-                    createExpressionForPropertyName(property.name, /*location*/ property.name),
-                    {
-                        get: getAccessor && createFunctionExpression(
-                            /*asteriskToken*/ undefined,
-                            /*name*/ undefined,
-                            getAccessor.parameters,
-                            getAccessor.body,
-                            /*location*/ getAccessor,
-                            /*original*/ getAccessor
-                        ),
-                        set: setAccessor && createFunctionExpression(
-                            /*asteriskToken*/ undefined,
-                            /*name*/ undefined,
-                            setAccessor.parameters,
-                            setAccessor.body,
-                            /*location*/ setAccessor,
-                            /*original*/ setAccessor
-                        ),
-                        enumerable: true,
-                        configurable: true
-                    },
-                    multiLine,
-                    /*location*/ firstAccessor
-                )
+                    createExpressionForPropertyName(property.name),
+                    createObjectLiteral(properties, /*location*/ undefined, multiLine)
+                ],
+                /*location*/ firstAccessor
             );
+
+            return aggregateTransformFlags(expression);
         }
 
         return undefined;
diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts
index 83895b27ffe92..3a19a5d0f43bb 100644
--- a/src/compiler/printer.ts
+++ b/src/compiler/printer.ts
@@ -2129,14 +2129,6 @@ const _super = (function (geti, seti) {
                 }
             }
 
-            function shouldEmitCaseOrDefaultClauseStatementOnSameLine(parentNode: Node, statement: Statement) {
-                if (statement.startsOnNewLine || nodeIsSynthesized(parentNode)) {
-                    return false;
-                }
-
-                return nodeIsSynthesized(statement) || rangeStartPositionsAreOnSameLine(parentNode, statement);
-            }
-
             function emitHeritageClause(node: HeritageClause) {
                 write(" ");
                 writeTokenText(node.token);
diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts
index 073cf50c90a3c..54d02593caa1d 100644
--- a/src/compiler/transformers/generators.ts
+++ b/src/compiler/transformers/generators.ts
@@ -235,11 +235,13 @@ namespace ts {
             endLexicalEnvironment,
             hoistFunctionDeclaration,
             hoistVariableDeclaration,
+            setSourceMapRange,
+            setCommentRange
         } = context;
 
         const resolver = context.getEmitResolver();
-        const previousExpressionSubstitution = context.expressionSubstitution;
-        context.expressionSubstitution = substituteExpression;
+        const previousOnSubstituteNode = context.onSubstituteNode;
+        context.onSubstituteNode = onSubstituteNode;
 
         let renamedCatchVariables: Map<boolean>;
         let renamedCatchVariableDeclarations: Map<Identifier>;
@@ -994,7 +996,7 @@ namespace ts {
                 //  .mark resumeLabel
                 //      _b.apply(_a, _c.concat([%sent%, 2]));
 
-                const { target, thisArg } = createCallBinding(node.expression);
+                const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration);
                 return setOriginalNode(
                     createFunctionApply(
                         cacheExpression(visitNode(target, visitor, isLeftHandSideExpression)),
@@ -1022,7 +1024,7 @@ namespace ts {
                 //  .mark resumeLabel
                 //      new (_b.apply(_a, _c.concat([%sent%, 2])));
 
-                const { target, thisArg } = createCallBinding(createPropertyAccess(node.expression, "bind"));
+                const { target, thisArg } = createCallBinding(createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration);
                 return setOriginalNode(
                     createNew(
                         createFunctionApply(
@@ -1807,8 +1809,15 @@ namespace ts {
             return -1;
         }
 
+        function onSubstituteNode(node: Node, isExpression: boolean): Node {
+            node = previousOnSubstituteNode(node, isExpression);
+            if (isExpression) {
+                return substituteExpression(<Expression> node);
+            }
+            return node;
+        }
+
         function substituteExpression(node: Expression): Expression {
-            node = previousExpressionSubstitution(node);
             if (isIdentifier(node)) {
                 return substituteExpressionIdentifier(node);
             }
@@ -1823,7 +1832,10 @@ namespace ts {
                     if (declaration) {
                         const name = getProperty(renamedCatchVariableDeclarations, String(getOriginalNodeId(declaration)));
                         if (name) {
-                            return getRelocatedClone(name, /*location*/ node);
+                            const clone = getMutableClone(name);
+                            setSourceMapRange(clone, node);
+                            setCommentRange(clone, node);
+                            return clone;
                         }
                     }
                 }
@@ -1842,7 +1854,7 @@ namespace ts {
                 temp = createUniqueName(node.text);
             }
             else {
-                temp = createTempVariable();
+                temp = createTempVariable(hoistVariableDeclaration);
             }
 
             emitAssignment(temp, node, /*location*/ node);
@@ -1852,7 +1864,7 @@ namespace ts {
         function declareLocal(name?: string): Identifier {
             const temp = name
                 ? createUniqueName(name)
-                : createTempVariable();
+                : createTempVariable(hoistVariableDeclaration);
             hoistVariableDeclaration(temp);
             return temp;
         }
@@ -1991,7 +2003,7 @@ namespace ts {
             if (!renamedCatchVariables) {
                 renamedCatchVariables = {};
                 renamedCatchVariableDeclarations = {};
-                context.enableExpressionSubstitution(SyntaxKind.Identifier);
+                context.enableSubstitution(SyntaxKind.Identifier);
             }
 
             renamedCatchVariables[text] = true;
@@ -2300,7 +2312,9 @@ namespace ts {
          * Creates a numeric literal for the provided instruction.
          */
         function createInstruction(instruction: Instruction): NumericLiteral {
-            return createLiteral(instruction, /*location*/ undefined, instructionNames[instruction]);
+            const literal = createLiteral(instruction);
+            literal.trailingComment = instructionNames[instruction];
+            return literal;
         }
 
         /**

From 0948f73f2aa0c743c61a5009b44d5a7a0485f298 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 13 Jun 2016 12:39:55 -0700
Subject: [PATCH 04/23] Cleanup, only support generators for async functions,
 added emit helper.

---
 src/compiler/binder.ts                  |  19 +-
 src/compiler/emitter.ts                 | 101 ++++++++++
 src/compiler/factory.ts                 |  43 +++--
 src/compiler/transformers/generators.ts | 245 ++++++++++--------------
 src/compiler/types.ts                   |  33 ++--
 src/compiler/visitor.ts                 |  25 +++
 6 files changed, 291 insertions(+), 175 deletions(-)

diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts
index be3a12a5743cb..bbeb5253fff27 100644
--- a/src/compiler/binder.ts
+++ b/src/compiler/binder.ts
@@ -2494,6 +2494,11 @@ namespace ts {
             transformFlags |= TransformFlags.AssertTypeScript;
         }
 
+        // Currently, we only support generators that were originally async function bodies.
+        if (node.asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
+            transformFlags |= TransformFlags.AssertGenerator;
+        }
+
         node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
         return transformFlags & ~TransformFlags.MethodOrAccessorExcludes;
     }
@@ -2556,9 +2561,14 @@ namespace ts {
             // If a FunctionDeclaration has an asterisk token, is exported, or its
             // subtree has marked the container as needing to capture the lexical `this`,
             // then this node is ES6 syntax.
-            if (asteriskToken || (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask)) {
+            if (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask) {
                 transformFlags |= TransformFlags.AssertES6;
             }
+
+            // Currently, we only support generators that were originally async function bodies.
+            if (node.asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
+                transformFlags |= TransformFlags.AssertGenerator;
+            }
         }
 
         node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@@ -2577,10 +2587,15 @@ namespace ts {
 
         // If a FunctionExpression contains an asterisk token, or its subtree has marked the container
         // as needing to capture the lexical this, then this node is ES6 syntax.
-        if (asteriskToken || (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask)) {
+        if (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask) {
             transformFlags |= TransformFlags.AssertES6;
         }
 
+        // Currently, we only support generators that were originally async function bodies.
+        if (node.asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
+            transformFlags |= TransformFlags.AssertGenerator;
+        }
+
         node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
         return transformFlags & ~TransformFlags.FunctionExcludes;
     }
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index 868ede1b0a848..b066540c6b55a 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -71,6 +71,103 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
     });
 };`;
 
+        const generatorHelper = `
+var __generator = (this && this.__generator) || function (body) {
+    var done, finallyStack, executing, yieldStar, trys = [], state = { label: 0, trys: trys };
+    function step(op) {
+        if (executing) throw new TypeError("Generator is already executing.");
+        while (true) {
+            if (done) {
+                switch (op[0]) {
+                    case 0 /*next*/: return { value: void 0, done: true };
+                    case 6 /*catch*/:
+                    case 1 /*throw*/: throw op[1];
+                    case 2 /*return*/: return { value: op[1], done: true };
+                }
+            }
+            try {
+                executing = true;
+                if (yieldStar) {
+                    var verb = yieldStar[op[0] === 2 ? "return" : op[0] === 1 ? "throw" : "next"];
+                    if (verb) {
+                        var yielded = verb.call(yieldStar, op[1]);
+                        if (!yielded.done) return { value: yielded.value, done: false };
+                        op = [0 /*next*/, yielded.value];
+                    }
+
+                    yieldStar = void 0;
+                    continue;
+                }
+
+                switch (op[0]) {
+                    case 0 /*next*/:
+                        state.sent = function() { return op[1]; };
+                        break;
+
+                    case 1 /*throw*/:
+                        state.sent = function() { throw op[1]; };
+                        break;
+
+                    case 4 /*yield*/:
+                        state.label++;
+                        return { value: op[1], done: false };
+
+                    case 5 /*yieldstar*/:
+                        state.label++;
+                        yieldStar = op[1];
+                        op = [0 /*next*/, void 0];
+                        continue;
+
+                    case 7 /*endfinally*/:
+                        op = finallyStack.pop();
+                        trys.pop();
+                        continue;
+
+                    default:
+                        var rgn = trys.length && trys[trys.length - 1];
+                        if (!rgn && (op[0] === 6 /*catch*/ || op[0] === 1 /*throw*/ || op[0] === 2 /*return*/)) {
+                            done = true;
+                            finallyStack = void 0;
+                            continue;
+                        }
+                        else if (op[0] === 3 /*break*/ && (!rgn || (op[1] > rgn[0] && op[1] < rgn[3]))) {
+                            state.label = op[1];
+                        }
+                        else if (op[0] === 6 /*catch*/ && rgn && state.label < rgn[1]) {
+                            state.error = op[1];
+                            state.label = rgn[1];
+                        }
+                        else if (rgn && state.label < rgn[2]) {
+                            (finallyStack || []).push(op);
+                            state.label = rgn[2];
+                        }
+                        else {
+                            if (rgn[2]) finallyStack.pop();
+                            trys.pop();
+                            continue;
+                        }
+                }
+
+                op = body(state);
+            }
+            catch (e) {
+                op = [6 /*catch*/, e];
+                yieldStar = void 0;
+            }
+            finally {
+                executing = false;
+                verb = yielded = void 0;
+            }
+        }
+    }
+    var g = {
+        next: function (v) { return step([0 /*next*/, v]); },
+        "throw": function (v) { return step([1 /*throw*/, v]); },
+        "return": function (v) { return step([2 /*return*/, v]); }
+    };
+    return g;
+};`;
+
         // emit output for the __export helper function
         const exportStarHelper = `
 function __export(m) {
@@ -2141,6 +2238,10 @@ const _super = (function (geti, seti) {
 
                 if (!awaiterEmitted && node.flags & NodeFlags.HasAsyncFunctions) {
                     writeLines(awaiterHelper);
+                    if (languageVersion < ScriptTarget.ES6) {
+                        writeLines(generatorHelper);
+                    }
+
                     awaiterEmitted = true;
                     helpersEmitted = true;
                 }
diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts
index b2c5a54691ace..f95245c4f27d6 100644
--- a/src/compiler/factory.ts
+++ b/src/compiler/factory.ts
@@ -659,6 +659,13 @@ namespace ts {
         return node;
     }
 
+    export function updateFor(node: ForStatement, initializer: ForInitializer, condition: Expression, incrementor: Expression, statement: Statement) {
+        if (node.initializer !== initializer || node.condition !== condition || node.incrementor !== incrementor || node.statement !== statement) {
+            return updateNode(createFor(initializer, condition, incrementor, statement, node), node);
+        }
+        return node;
+    }
+
     export function createLabel(label: string | Identifier, statement: Statement, location?: TextRange) {
         const node = <LabeledStatement>createNode(SyntaxKind.LabeledStatement, location);
         node.label = typeof label === "string" ? createIdentifier(label) : label;
@@ -666,17 +673,17 @@ namespace ts {
         return node;
     }
 
-    export function createDo(expression: Expression, statement: Statement, location?: TextRange) {
+    export function createDo(statement: Statement, expression: Expression, location?: TextRange) {
         const node = <DoStatement>createNode(SyntaxKind.DoStatement, location);
-        node.expression = expression;
         node.statement = statement;
+        node.expression = expression;
         return node;
     }
 
-    export function createWhile(statement: Statement, expression: Expression, location?: TextRange) {
+    export function createWhile(expression: Expression, statement: Statement, location?: TextRange) {
         const node = <WhileStatement>createNode(SyntaxKind.WhileStatement, location);
-        node.statement = statement;
         node.expression = expression;
+        node.statement = statement;
         return node;
     }
 
@@ -688,6 +695,13 @@ namespace ts {
         return node;
     }
 
+    export function updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement) {
+        if (node.initializer !== initializer || node.expression !== expression || node.statement !== statement) {
+            return updateNode(createForIn(initializer, expression, statement, node), node);
+        }
+        return node;
+    }
+
     export function createForOf(initializer: ForInitializer, expression: Expression, statement: Statement, location?: TextRange) {
         const node = <ForOfStatement>createNode(SyntaxKind.ForOfStatement, location);
         node.initializer = initializer;
@@ -1147,6 +1161,18 @@ namespace ts {
     }
 
     export function createAwaiterHelper(hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
+        const generatorFunc = createFunctionExpression(
+            createNode(SyntaxKind.AsteriskToken),
+            /*name*/ undefined,
+            /*typeParameters*/ undefined,
+            /*parameters*/ [],
+            /*type*/ undefined,
+            body
+        );
+
+        // Mark this node as originally an async function
+        generatorFunc.emitFlags |= NodeEmitFlags.AsyncFunctionBody;
+
         return createCall(
             createIdentifier("__awaiter"),
             /*typeArguments*/ undefined,
@@ -1154,14 +1180,7 @@ namespace ts {
                 createThis(),
                 hasLexicalArguments ? createIdentifier("arguments") : createVoidZero(),
                 promiseConstructor ? createExpressionFromEntityName(promiseConstructor) : createVoidZero(),
-                createFunctionExpression(
-                    createNode(SyntaxKind.AsteriskToken),
-                    /*name*/ undefined,
-                    /*typeParameters*/ undefined,
-                    /*parameters*/ [],
-                    /*type*/ undefined,
-                    body
-                )
+                generatorFunc
             ]
         );
     }
diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts
index 792986ed7b79b..9e00b6e6ea5e5 100644
--- a/src/compiler/transformers/generators.ts
+++ b/src/compiler/transformers/generators.ts
@@ -131,7 +131,7 @@ namespace ts {
         BreakWhenTrue,          // A break instruction used to jump to a label if a condition evaluates to true
         BreakWhenFalse,         // A break instruction used to jump to a label if a condition evaluates to false
         Yield,                  // A completion instruction for the `yield` keyword
-        YieldStar,              // A completion instruction for the `yield*` keyword
+        YieldStar,              // A completion instruction for the `yield*` keyword (not implemented, but reserved for future use)
         Return,                 // A completion instruction for the `return` keyword
         Throw,                  // A completion instruction for the `throw` keyword
         Endfinally              // Marks the end of a `finally` block
@@ -249,9 +249,6 @@ namespace ts {
         let inGeneratorFunctionBody: boolean;
         let inStatementContainingYield: boolean;
 
-        // Indicates whether the builder contains any exception blocks.
-        let hasProtectedRegions: boolean;
-
         // The following three arrays store information about generated code blocks.
         // All three arrays are correlated by their index. This approach is used over allocating
         // objects to store the same information to avoid GC overhead.
@@ -297,7 +294,7 @@ namespace ts {
         return transformSourceFile;
 
         function transformSourceFile(node: SourceFile) {
-            if (node.transformFlags & TransformFlags.ContainsGenerators) {
+            if (node.transformFlags & TransformFlags.ContainsGenerator) {
                 return visitEachChild(node, visitor, context);
             }
 
@@ -309,8 +306,9 @@ namespace ts {
          *
          * @param node The node to visit.
          */
-        function visitor(node: Node): Node {
-            if (containsYield(node)) {
+        function visitor(node: Node): VisitResult<Node> {
+            const transformFlags = node.transformFlags;
+            if (transformFlags & TransformFlags.ContainsYield) {
                 return visitJavaScriptContainingYield(node);
             }
             else if (inStatementContainingYield) {
@@ -319,7 +317,10 @@ namespace ts {
             else if (inGeneratorFunctionBody) {
                 return visitJavaScriptInGeneratorFunctionBody(node);
             }
-            else if (node.transformFlags & TransformFlags.ContainsGenerators) {
+            else if (node.transformFlags & TransformFlags.Generator) {
+                return visitGenerator(node);
+            }
+            else if (node.transformFlags & TransformFlags.ContainsGenerator) {
                 return visitEachChild(node, visitor, context);
             }
             else {
@@ -332,7 +333,7 @@ namespace ts {
          *
          * @param node The node to visit.
          */
-        function visitJavaScriptContainingYield(node: Node): Node {
+        function visitJavaScriptContainingYield(node: Node): VisitResult<Node> {
             switch (node.kind) {
                 case SyntaxKind.BinaryExpression:
                     return visitBinaryExpression(<BinaryExpression>node);
@@ -360,7 +361,7 @@ namespace ts {
          *
          * @param node The node to visit.
          */
-        function visitJavaScriptInStatementContainingYield(node: Node): Node {
+        function visitJavaScriptInStatementContainingYield(node: Node): VisitResult<Node> {
             switch (node.kind) {
                 case SyntaxKind.DoStatement:
                     return visitDoStatement(<DoStatement>node);
@@ -384,7 +385,7 @@ namespace ts {
          *
          * @param node The node to visit.
          */
-        function visitJavaScriptInGeneratorFunctionBody(node: Node): Node {
+        function visitJavaScriptInGeneratorFunctionBody(node: Node): VisitResult<Node> {
             switch (node.kind) {
                 case SyntaxKind.FunctionDeclaration:
                     return visitFunctionDeclaration(<FunctionDeclaration>node);
@@ -394,7 +395,7 @@ namespace ts {
                 case SyntaxKind.SetAccessor:
                     return visitAccessorDeclaration(<AccessorDeclaration>node);
                 default:
-                    if (node.transformFlags & TransformFlags.ContainsGenerators || containsYield(node)) {
+                    if (node.transformFlags & (TransformFlags.ContainsGenerator | TransformFlags.ContainsYield)) {
                         return visitEachChild(node, visitor, context);
                     }
                     else {
@@ -403,6 +404,25 @@ namespace ts {
             }
         }
 
+        /**
+         * Visits a generator function.
+         *
+         * @param node The node to visit.
+         */
+        function visitGenerator(node: Node): VisitResult<Node> {
+            switch (node.kind) {
+                case SyntaxKind.FunctionDeclaration:
+                    return visitFunctionDeclaration(<FunctionDeclaration>node);
+
+                case SyntaxKind.FunctionExpression:
+                    return visitFunctionExpression(<FunctionExpression>node);
+
+                default:
+                    Debug.failBadSyntaxKind(node);
+                    return visitEachChild(node, visitor, context);
+            }
+        }
+
         /**
          * Visits a function declaration.
          *
@@ -413,7 +433,8 @@ namespace ts {
          * @param node The node to visit.
          */
         function visitFunctionDeclaration(node: FunctionDeclaration): Statement {
-            if (node.asteriskToken) {
+            // Currently, we only support generators that were originally async functions.
+            if (node.asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
                 node = setOriginalNode(
                     createFunctionDeclaration(
                         /*decorators*/ undefined,
@@ -460,7 +481,8 @@ namespace ts {
          * @param node The node to visit.
          */
         function visitFunctionExpression(node: FunctionExpression): Expression {
-            if (node.asteriskToken) {
+            // Currently, we only support generators that were originally async functions.
+            if (node.asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
                 node = setOriginalNode(
                     createFunctionExpression(
                         /*asteriskToken*/ undefined,
@@ -516,7 +538,6 @@ namespace ts {
             const statements: Statement[] = [];
             const savedInGeneratorFunctionBody = inGeneratorFunctionBody;
             const savedInStatementContainingYield = inStatementContainingYield;
-            const savedHasProtectedRegions = hasProtectedRegions;
             const savedBlocks = blocks;
             const savedBlockOffsets = blockOffsets;
             const savedBlockActions = blockActions;
@@ -531,7 +552,6 @@ namespace ts {
             // Initialize generator state
             inGeneratorFunctionBody = true;
             inStatementContainingYield = false;
-            hasProtectedRegions = false;
             blocks = undefined;
             blockOffsets = undefined;
             blockActions = undefined;
@@ -541,7 +561,7 @@ namespace ts {
             operations = undefined;
             operationArguments = undefined;
             operationLocations = undefined;
-            state = undefined;
+            state = createUniqueName("state");
 
             // Build the generator
             startLexicalEnvironment();
@@ -555,7 +575,6 @@ namespace ts {
             // Restore previous generator state
             inGeneratorFunctionBody = savedInGeneratorFunctionBody;
             inStatementContainingYield = savedInStatementContainingYield;
-            hasProtectedRegions = savedHasProtectedRegions;
             blocks = savedBlocks;
             blockOffsets = savedBlockOffsets;
             blockActions = savedBlockActions;
@@ -579,7 +598,7 @@ namespace ts {
          * @param node The node to visit.
          */
         function visitVariableStatement(node: VariableStatement): Statement {
-            if (containsYield(node)) {
+            if (node.transformFlags & TransformFlags.ContainsYield) {
                 transformAndEmitVariableDeclarationList(node.declarationList);
                 return undefined;
             }
@@ -841,21 +860,9 @@ namespace ts {
             //  .mark resumeLabel
             //      x = %sent%;
 
+            // NOTE: we are explicitly not handling YieldStar at this time.
             const resumeLabel = defineLabel();
-            if (node.asteriskToken) {
-                emitYieldStar(
-                    createCall(
-                        createIdentifier("__values"),
-                        /*typeParameters*/ undefined,
-                        [visitNode(node.expression, visitor, isExpression)]
-                    ),
-                    /*location*/ node
-                );
-            }
-            else {
-                emitYield(visitNode(node.expression, visitor, isExpression), /*location*/ node);
-            }
-
+            emitYield(visitNode(node.expression, visitor, isExpression), /*location*/ node);
             markLabel(resumeLabel);
             return createGeneratorResume();
         }
@@ -1353,21 +1360,15 @@ namespace ts {
                     hoistVariableDeclaration(<Identifier>variable.name);
                 }
 
-                node = getMutableClone(node);
-
                 const variables = getInitializedVariables(initializer);
-                if (variables.length === 0) {
-                    node.initializer = undefined;
-                }
-                else {
-                    node.initializer = inlineExpressions(
-                        map(variables, transformInitializedVariable)
-                    );
-                }
-
-                node.condition = visitNode(node.condition, visitor, isExpression, /*optional*/ true);
-                node.incrementor = visitNode(node.incrementor, visitor, isExpression, /*optional*/ true);
-                node.statement = visitNode(node.statement, visitor, isStatement);
+                node = updateFor(node,
+                    variables.length > 0
+                        ? inlineExpressions(map(variables, transformInitializedVariable))
+                        : undefined,
+                    visitNode(node.condition, visitor, isExpression, /*optional*/ true),
+                    visitNode(node.incrementor, visitor, isExpression, /*optional*/ true),
+                    visitNode(node.statement, visitor, isStatement, /*optional*/ false, liftToBlock)
+                );
             }
             else {
                 node = visitEachChild(node, visitor, context);
@@ -1389,35 +1390,48 @@ namespace ts {
                 //      }
                 //
                 // [intermediate]
-                //  .local _a, _b, p
-                //      _a = __keys(o);
+                //  .local _a, _b, _c
+                //      _a = [];
+                //      for (_b in o) _a.push(_b);
+                //      _c = 0;
                 //  .loop incrementLabel, endLoopLabel
-                //  .try tryLabel, , finallyLabel, endTryLabel
-                //  .mark tryLabel
-                //  .nop
-                //  .mark incrementLabel
-                //      _b = _a.next();
-                //  .brtrue cleanupLabel, (_b.done)
-                //      p = _b.value;
+                //  .mark conditionLabel
+                //  .brfalse endLoopLabel, (_c < _a.length)
+                //      p = _a[_c];
                 //      /*body*/
-                //  .br incrementLabel
-                //  .mark cleanupLabel
-                //      _b = _a = void 0;
-                //  .br endLoopLabel
-                //  .finally
-                //  .mark finallyLabel
-                //      if (_a && typeof _a.return === "function")
-                //          _a.return();
-                //  .endfinally
-                //  .endtry
-                //  .mark endTryLabel
+                //  .mark incrementLabel
+                //      _b++;
+                //  .br conditionLabel
                 //  .endloop
                 //  .mark endLoopLabel
 
-                const keysIterator = declareLocal(); // _a
-                const iteratorResult = declareLocal(); // _b
+                const keysArray = declareLocal(); // _a
+                const key = declareLocal(); // _b
+                const keysIndex = declareLocal(); // _c
                 const initializer = node.initializer;
 
+                emitAssignment(keysArray, createArrayLiteral());
+
+                emitStatement(
+                    createForIn(
+                        key,
+                        visitNode(node.expression, visitor, isExpression),
+                        createStatement(
+                            createCall(
+                                createPropertyAccess(keysArray, "push"),
+                                /*typeArguments*/ undefined,
+                                [key]
+                            )
+                        )
+                    )
+                );
+
+                emitAssignment(keysIndex, createLiteral(0));
+
+                const conditionLabel = defineLabel();
+                const incrementLabel = defineLabel();
+                const endLabel = beginLoopBlock(incrementLabel);
+
                 let variable: Expression;
                 if (isVariableDeclarationList(initializer)) {
                     for (const variable of initializer.declarations) {
@@ -1431,45 +1445,16 @@ namespace ts {
                     Debug.assert(isLeftHandSideExpression(variable));
                 }
 
-                emitAssignment(keysIterator,
-                    createCall(createIdentifier("__keys"), /*typeArguments*/ undefined, [
-                        visitNode(node.expression, visitor, isExpression)
-                    ])
-                );
+                markLabel(conditionLabel);
+                emitBreakWhenFalse(endLabel, createLessThan(keysIndex, createPropertyAccess(keysArray, "length")));
 
-                const incrementLabel = defineLabel();
-                const cleanupLabel = defineLabel();
-                const endLabel = beginLoopBlock(incrementLabel);
+                emitAssignment(variable, createElementAccess(keysArray, keysIndex));
+                transformAndEmitEmbeddedStatement(node.statement);
 
-                beginExceptionBlock();
                 markLabel(incrementLabel);
-                emitAssignment(iteratorResult, createCall(createPropertyAccess(iteratorResult, "next"), /*typeArguments*/ undefined, []));
-                emitBreakWhenTrue(cleanupLabel, createPropertyAccess(iteratorResult, "done"));
-                emitAssignment(variable, createPropertyAccess(iteratorResult, "value"));
-                transformAndEmitEmbeddedStatement(node.statement);
-                emitBreak(incrementLabel);
-                markLabel(cleanupLabel);
-                emitAssignment(keysIterator, createAssignment(iteratorResult, createVoidZero()));
-                emitBreak(endLabel);
-                beginFinallyBlock();
-                emitStatement(
-                    createIf(
-                        createLogicalAnd(
-                            keysIterator,
-                            createStrictEquality(
-                                createTypeOf(
-                                    createPropertyAccess(keysIterator, "return")
-                                ),
-                                createLiteral("function")
-                            )
-                        ),
-                        createStatement(
-                            createCall(createPropertyAccess(keysIterator, "return"), /*typeArguments*/ undefined, [])
-                        )
-                    )
-                );
-                emitEndfinally();
-                endExceptionBlock();
+                emitStatement(createStatement(createPostfixIncrement(keysIndex)));
+
+                emitBreak(conditionLabel);
                 endLoopBlock();
             }
             else {
@@ -1501,12 +1486,11 @@ namespace ts {
                     hoistVariableDeclaration(<Identifier>variable.name);
                 }
 
-                node = getMutableClone(node);
-
-                const variable = initializer.declarations[0];
-                node.initializer = <Identifier>variable.name;
-                node.expression = visitNode(node.expression, visitor, isExpression);
-                node.statement = visitNode(node.statement, visitor, isStatement);
+                node = updateForIn(node,
+                    <Identifier>initializer.declarations[0].name,
+                    visitNode(node.expression, visitor, isExpression),
+                    visitNode(node.statement, visitor, isStatement, /*optional*/ false, liftToBlock)
+                );
             }
             else {
                 node = visitEachChild(node, visitor, context);
@@ -1553,7 +1537,6 @@ namespace ts {
             return visitEachChild(node, visitor, context);
         }
 
-
         function transformAndEmitReturnStatement(node: ReturnStatement): void {
             emitReturn(
                 visitNode(node.expression, visitor, isExpression, /*optional*/ true),
@@ -1992,7 +1975,6 @@ namespace ts {
                 endLabel
             });
             emitWorker(OpCode.Nop);
-            hasProtectedRegions = true;
             return endLabel;
         }
 
@@ -2028,7 +2010,6 @@ namespace ts {
             exception.catchVariable = name;
             exception.catchLabel = catchLabel;
 
-            const state = getState();
             emitAssignment(name, createPropertyAccess(state, "error"));
             emitWorker(OpCode.Nop);
         }
@@ -2134,7 +2115,6 @@ namespace ts {
             });
         }
 
-
         /**
          * Begins a code block that supports `break` statements that are defined in generated code.
          * Returns a label used to mark the operation to which to jump when a `break` statement
@@ -2361,18 +2341,7 @@ namespace ts {
          * Creates an expression that can be used to resume from a Yield operation.
          */
         function createGeneratorResume(location?: TextRange): LeftHandSideExpression {
-            return createCall(createPropertyAccess(getState(), "sent"), /*typeArguments*/ undefined, [], location);
-        }
-
-        /**
-         * Gets the identifier for the runtime `state` variable.
-         */
-        function getState(): Identifier {
-            if (state === undefined) {
-                state = createUniqueName("state");
-            }
-
-            return state;
+            return createCall(createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [], location);
         }
 
         /**
@@ -2535,7 +2504,7 @@ namespace ts {
                     /*asteriskToken*/ undefined,
                     /*name*/ undefined,
                     /*typeParameters*/ undefined,
-                    [createParameter(getState())],
+                    [createParameter(state)],
                     /*type*/ undefined,
                     createBlock(
                         buildStatements()
@@ -2548,10 +2517,6 @@ namespace ts {
          * Builds the statements for the generator function body.
          */
         function buildStatements(): Statement[] {
-            if (hasProtectedRegions) {
-                initializeProtectedRegions();
-            }
-
             if (operations) {
                 for (let operationIndex = 0; operationIndex < operations.length; operationIndex++) {
                     writeOperation(operationIndex);
@@ -2564,7 +2529,6 @@ namespace ts {
             }
 
             if (clauses) {
-                const state = getState();
                 const labelExpression = createPropertyAccess(state, "label");
                 const switchStatement = createSwitch(labelExpression, createCaseBlock(clauses));
                 return [switchStatement];
@@ -2577,17 +2541,6 @@ namespace ts {
             return [];
         }
 
-        /**
-         * Initializes protected region information for the generator.
-         *
-         * This assigns an array to `state.trys` that will be used to capture when execution
-         * enters or exits a protected region (i.e. an exception block).
-         */
-        function initializeProtectedRegions(): void {
-            writeAssign(createPropertyAccess(getState(), "trys"), createArrayLiteral(), /*operationLocation*/ undefined);
-            flushLabel();
-        }
-
         /**
          * Flush the current label and advance to a new label.
          */
@@ -2649,7 +2602,7 @@ namespace ts {
                     statements.unshift(
                         createStatement(
                             createCall(
-                                createPropertyAccess(createPropertyAccess(getState(), "trys"), "push"),
+                                createPropertyAccess(createPropertyAccess(state, "trys"), "push"),
                                 /*typeArguments*/ undefined,
                                 [
                                     createArrayLiteral([
@@ -2672,7 +2625,7 @@ namespace ts {
                     statements.push(
                         createStatement(
                             createAssignment(
-                                createPropertyAccess(getState(), "label"),
+                                createPropertyAccess(state, "label"),
                                 createLiteral(labelNumber + 1)
                             )
                         )
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 34ca73b90fb93..349c637d33667 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -2970,22 +2970,23 @@ namespace ts {
         ES6 = 1 << 6,
         ContainsES6 = 1 << 7,
         DestructuringAssignment = 1 << 8,
-        ContainsGenerators = 1 << 9,
+        Generator = 1 << 9,
+        ContainsGenerator = 1 << 10,
 
         // Markers
         // - Flags used to indicate that a subtree contains a specific transformation.
-        ContainsDecorators = 1 << 10,
-        ContainsPropertyInitializer = 1 << 11,
-        ContainsLexicalThis = 1 << 12,
-        ContainsCapturedLexicalThis = 1 << 13,
-        ContainsLexicalThisInComputedPropertyName = 1 << 14,
-        ContainsDefaultValueAssignments = 1 << 15,
-        ContainsParameterPropertyAssignments = 1 << 16,
-        ContainsSpreadElementExpression = 1 << 17,
-        ContainsComputedPropertyName = 1 << 18,
-        ContainsBlockScopedBinding = 1 << 19,
-        ContainsBindingPattern = 1 << 20,
-        ContainsYield = 1 << 21,
+        ContainsDecorators = 1 << 11,
+        ContainsPropertyInitializer = 1 << 12,
+        ContainsLexicalThis = 1 << 13,
+        ContainsCapturedLexicalThis = 1 << 14,
+        ContainsLexicalThisInComputedPropertyName = 1 << 15,
+        ContainsDefaultValueAssignments = 1 << 16,
+        ContainsParameterPropertyAssignments = 1 << 17,
+        ContainsSpreadElementExpression = 1 << 18,
+        ContainsComputedPropertyName = 1 << 19,
+        ContainsBlockScopedBinding = 1 << 20,
+        ContainsBindingPattern = 1 << 21,
+        ContainsYield = 1 << 22,
 
         HasComputedFlags = 1 << 29, // Transform flags have been computed.
 
@@ -2995,6 +2996,7 @@ namespace ts {
         AssertJsx = Jsx | ContainsJsx,
         AssertES7 = ES7 | ContainsES7,
         AssertES6 = ES6 | ContainsES6,
+        AssertGenerator = Generator | ContainsGenerator,
 
         // Scope Exclusions
         // - Bitmasks that exclude flags from propagating out of a specific context
@@ -3043,13 +3045,14 @@ namespace ts {
         ExportName = 1 << 17,                    // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal).
         LocalName = 1 << 18,                     // Ensure an export prefix is not added for an identifier that points to an exported declaration.
         Indented = 1 << 19,                      // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter).
+        AsyncFunctionBody = 1 << 20,
 
         // SourceMap Specialization.
         // TODO(rbuckton): These should be removed once source maps are aligned with the old
         //                 emitter and new baselines are taken. This exists solely to
         //                 align with the old emitter.
-        SourceMapEmitOpenBraceAsToken = 1 << 20,        // Emits the open brace of a block function body as a source mapped token.
-        SourceMapAdjustRestParameterLoop = 1 << 21,     // Emits adjusted source map positions for a ForStatement generated when transforming a rest parameter for ES5/3.
+        SourceMapEmitOpenBraceAsToken = 1 << 21,        // Emits the open brace of a block function body as a source mapped token.
+        SourceMapAdjustRestParameterLoop = 1 << 22,     // Emits adjusted source map positions for a ForStatement generated when transforming a rest parameter for ES5/3.
     }
 
     /** Additional context provided to `visitEachChild` */
diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts
index 901b6c1719547..bb991760dcb29 100644
--- a/src/compiler/visitor.ts
+++ b/src/compiler/visitor.ts
@@ -698,6 +698,14 @@ namespace ts {
                 visited = visitEachChildOfIf(<IfStatement>node, visitor);
                 break;
 
+            case SyntaxKind.ForStatement:
+                visited = visitEachChildOfFor(<ForStatement>node, visitor);
+                break;
+
+            case SyntaxKind.ForInStatement:
+                visited = visitEachChildOfForIn(<ForInStatement>node, visitor);
+                break;
+
             case SyntaxKind.ReturnStatement:
                 visited = visitEachChildOfReturn(<ReturnStatement>node, visitor);
                 break;
@@ -981,6 +989,23 @@ namespace ts {
         );
     }
 
+    function visitEachChildOfFor(node: ForStatement, visitor: (node: Node) => VisitResult<Node>) {
+        return updateFor(node,
+            visitNode(node.initializer, visitor, isForInitializer, /*optional*/ true),
+            visitNode(node.condition, visitor, isExpression, /*optional*/ true),
+            visitNode(node.incrementor, visitor, isExpression, /*optional*/ true),
+            visitNode(node.statement, visitor, isStatement, /*optional*/ false, liftToBlock)
+        );
+    }
+
+    function visitEachChildOfForIn(node: ForInStatement, visitor: (node: Node) => VisitResult<Node>) {
+        return updateForIn(node,
+            visitNode(node.initializer, visitor, isForInitializer),
+            visitNode(node.expression, visitor, isExpression),
+            visitNode(node.statement, visitor, isStatement, /*optional*/ false, liftToBlock)
+        );
+    }
+
     /**
      * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place.
      *

From 819066611b5f3b2bbe05a4d7b43eb8b846fa3f3b Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Wed, 8 Jun 2016 18:09:36 -0700
Subject: [PATCH 05/23] Adds progress indicators to the runtests-parallel build
 task.

---
 Jakefile.js                    |  48 +----
 scripts/mocha-none-reporter.js |  26 +++
 scripts/mocha-parallel.js      | 367 +++++++++++++++++++++++++++++++++
 3 files changed, 404 insertions(+), 37 deletions(-)
 create mode 100644 scripts/mocha-none-reporter.js
 create mode 100644 scripts/mocha-parallel.js

diff --git a/Jakefile.js b/Jakefile.js
index f4c6fbcf2b87f..4d9cc20937f2a 100644
--- a/Jakefile.js
+++ b/Jakefile.js
@@ -5,6 +5,7 @@ var os = require("os");
 var path = require("path");
 var child_process = require("child_process");
 var Linter = require("tslint");
+var runTestsInParallel = require("./scripts/mocha-parallel").runTestsInParallel;
 
 // Variables
 var compilerDirectory = "src/compiler/";
@@ -719,7 +720,6 @@ function writeTestConfigFile(tests, light, taskConfigsFolder, workerCount, stack
         taskConfigsFolder: taskConfigsFolder,
         stackTraceLimit: stackTraceLimit
     });
-    console.log('Running tests with config: ' + testConfigContents);
     fs.writeFileSync('test.config', testConfigContents);
 }
 
@@ -785,42 +785,16 @@ function runConsoleTests(defaultReporter, runInParallel) {
 
     }
     else {
-        // run task to load all tests and partition them between workers
-        var cmd = "mocha " + " -R min " + colors + run;
-        console.log(cmd);
-        exec(cmd, function() {
-            // read all configuration files and spawn a worker for every config
-            var configFiles = fs.readdirSync(taskConfigsFolder);
-            var counter = configFiles.length;
-            var firstErrorStatus;
-            // schedule work for chunks
-            configFiles.forEach(function (f) {
-                var configPath = path.join(taskConfigsFolder, f);
-                var workerCmd = "mocha" + " -t " + testTimeout + " -R " + reporter + " " + colors + " " + run + " --config='" + configPath + "'";
-                console.log(workerCmd);
-                exec(workerCmd,  finishWorker, finishWorker)
-            });
-
-            function finishWorker(e, errorStatus) {
-                counter--;
-                if (firstErrorStatus === undefined && errorStatus !== undefined) {
-                    firstErrorStatus = errorStatus;
-                }
-                if (counter !== 0) {
-                    complete();
-                }
-                else {
-                    // last worker clean everything and runs linter in case if there were no errors
-                    deleteTemporaryProjectOutput();
-                    jake.rmRf(taskConfigsFolder);
-                    if (firstErrorStatus === undefined) {
-                        runLinter();
-                        complete();
-                    }
-                    else {
-                        failWithStatus(firstErrorStatus);
-                    }
-                }
+        runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) {
+            // last worker clean everything and runs linter in case if there were no errors
+            deleteTemporaryProjectOutput();
+            jake.rmRf(taskConfigsFolder);
+            if (err) {
+                fail(err);
+            }
+            else {
+                runLinter();
+                complete();
             }
         });
     }
diff --git a/scripts/mocha-none-reporter.js b/scripts/mocha-none-reporter.js
new file mode 100644
index 0000000000000..5787b0c042ef5
--- /dev/null
+++ b/scripts/mocha-none-reporter.js
@@ -0,0 +1,26 @@
+/**
+ * Module dependencies.
+ */
+
+var Base = require('mocha').reporters.Base;
+
+/**
+ * Expose `None`.
+ */
+
+exports = module.exports = None;
+
+/**
+ * Initialize a new `None` test reporter.
+ *
+ * @api public
+ * @param {Runner} runner
+ */
+function None(runner) {
+  Base.call(this);
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+None.prototype.__proto__ = Base.prototype;
diff --git a/scripts/mocha-parallel.js b/scripts/mocha-parallel.js
new file mode 100644
index 0000000000000..adba8ebf57c7d
--- /dev/null
+++ b/scripts/mocha-parallel.js
@@ -0,0 +1,367 @@
+var tty = require("tty")
+  , readline = require("readline")
+  , fs = require("fs")
+  , path = require("path")
+  , child_process = require("child_process")
+  , os = require("os")
+  , mocha = require("mocha")
+  , Base = mocha.reporters.Base
+  , color = Base.color
+  , cursor = Base.cursor
+  , ms = require("mocha/lib/ms");
+
+var isatty = tty.isatty(1) && tty.isatty(2);
+var tapRangePattern = /^(\d+)\.\.(\d+)(?:$|\r\n?|\n)/;
+var tapTestPattern = /^(not\sok|ok)\s+(\d+)\s+(?:-\s+)?(.*)$/;
+var tapCommentPattern = /^#(?: (tests|pass|fail) (\d+)$)?/;
+
+exports.runTestsInParallel = runTestsInParallel;
+exports.ProgressBars = ProgressBars;
+
+function runTestsInParallel(taskConfigsFolder, run, options, cb) {
+    if (options === undefined) options = { };
+
+    return discoverTests(run, options, function (error) {
+        if (error) {
+            return cb(error);
+        }
+
+        return runTests(taskConfigsFolder, run, options, cb);
+    });
+}
+
+function discoverTests(run, options, cb) {
+    console.log("Discovering tests...");
+
+    var cmd = "mocha -R " + require.resolve("./mocha-none-reporter.js") + " " + run;
+    var p = child_process.spawn(
+        process.platform === "win32" ? "cmd" : "/bin/sh",
+        process.platform === "win32" ? ["/c", cmd] : ["-c", cmd], {
+            windowsVerbatimArguments: true,
+            env: { NODE_ENV: "development" }
+        });
+
+    p.on("exit", function (status) {
+        if (status) {
+            cb(new Error("Process exited width code " + status));
+        }
+        else {
+            cb();
+        }
+    });
+}
+
+function runTests(taskConfigsFolder, run, options, cb) {
+    var configFiles = fs.readdirSync(taskConfigsFolder);
+    var numPartitions = configFiles.length;
+    if (numPartitions <= 0) {
+        cb();
+        return;
+    }
+
+    console.log("Running tests on " + numPartitions + " threads...");
+
+    var partitions = Array(numPartitions);
+    var progressBars = new ProgressBars();
+    progressBars.enable();
+
+    var counter = numPartitions;
+    configFiles.forEach(runTestsInPartition);
+
+    function runTestsInPartition(file, index) {
+        var partition = {
+            file: path.join(taskConfigsFolder, file),
+            tests: 0,
+            passed: 0,
+            failed: 0,
+            completed: 0,
+            current: undefined,
+            start: undefined,
+            end: undefined,
+            failures: []
+        };
+        partitions[index] = partition;
+
+        // Set up the progress bar.
+        updateProgress(0);
+
+        // Start the background process.
+        var cmd = "mocha -t " + (options.testTimeout || 20000) + " -R tap --no-colors " + run + " --config='" + partition.file + "'";
+        var p = child_process.spawn(
+            process.platform === "win32" ? "cmd" : "/bin/sh",
+            process.platform === "win32" ? ["/c", cmd] : ["-c", cmd], {
+                windowsVerbatimArguments: true,
+                env: { NODE_ENV: "development" }
+            });
+
+        var rl = readline.createInterface({
+            input: p.stdout,
+            terminal: false
+        });
+
+        rl.on("line", onmessage);
+        p.on("exit", onexit)
+
+        function onmessage(line) {
+            if (partition.start === undefined) {
+                partition.start = Date.now();
+            }
+
+            var rangeMatch = tapRangePattern.exec(line);
+            if (rangeMatch) {
+                partition.tests = parseInt(rangeMatch[2]);
+                return;
+            }
+
+            var testMatch = tapTestPattern.exec(line);
+            if (testMatch) {
+                var test = {
+                    result: testMatch[1],
+                    id: parseInt(testMatch[2]),
+                    name: testMatch[3],
+                    output: []
+                };
+
+                partition.current = test;
+                partition.completed++;
+
+                if (test.result === "ok") {
+                    partition.passed++;
+                }
+                else {
+                    partition.failed++;
+                    partition.failures.push(test);
+                }
+
+                var progress = partition.completed / partition.tests;
+                if (progress < 1) {
+                    updateProgress(progress);
+                }
+
+                return;
+            }
+
+            var commentMatch = tapCommentPattern.exec(line);
+            if (commentMatch) {
+                switch (commentMatch[1]) {
+                    case "tests":
+                        partition.current = undefined;
+                        partition.tests = parseInt(commentMatch[2]);
+                        break;
+
+                    case "pass":
+                        partition.passed = parseInt(commentMatch[2]);
+                        break;
+
+                    case "fail":
+                        partition.failed = parseInt(commentMatch[2]);
+                        break;
+                }
+
+                return;
+            }
+
+            if (partition.current) {
+                partition.current.output.push(line);
+            }
+        }
+
+        function onexit() {
+            if (partition.end === undefined) {
+                partition.end = Date.now();
+            }
+
+            partition.duration = partition.end - partition.start;
+            var summaryColor = partition.failed ? "fail" : "green";
+            var summarySymbol = partition.failed ? Base.symbols.err : Base.symbols.ok;
+            var summaryTests = (partition.passed === partition.tests ? partition.passed : partition.passed + "/" + partition.tests) + " passing";
+            var summaryDuration = "(" + ms(partition.duration) + ")";
+            var savedUseColors = Base.useColors;
+            Base.useColors = !options.noColors;
+
+            var summary = color(summaryColor, summarySymbol + " " + summaryTests) + " " + color("light", summaryDuration);
+            Base.useColors = savedUseColors;
+
+            updateProgress(1, summary);
+
+            signal();
+        }
+
+        function updateProgress(percentComplete, title) {
+            var progressColor = "pending";
+            if (partition.failed) {
+                progressColor = "fail";
+            }
+
+            progressBars.update(
+                index,
+                percentComplete,
+                progressColor,
+                title
+            );
+        }
+    }
+
+    function signal() {
+        counter--;
+
+        if (counter <= 0) {
+            var failed = 0;
+            var reporter = new Base(),
+                stats = reporter.stats,
+                failures = reporter.failures;
+
+            var duration = 0;
+            for (var i = 0; i < numPartitions; i++) {
+                var partition = partitions[i];
+                stats.passes += partition.passed;
+                stats.failures += partition.failed;
+                stats.tests += partition.tests;
+                duration += partition.duration;
+                for (var j = 0; j < partition.failures.length; j++) {
+                    var failure = partition.failures[j];
+                    failures.push(makeMochaTest(failure));
+                }
+            }
+
+            stats.duration = duration;
+            progressBars.disable();
+
+            if (options.noColors) {
+                var savedUseColors = Base.useColors;
+                Base.useColors = false;
+                reporter.epilogue();
+                Base.useColors = savedUseColors;
+            }
+            else {
+                reporter.epilogue();
+            }
+
+            if (failed) {
+                return cb(new Error("Test failures reported: " + failed));
+            }
+            else {
+                return cb();
+            }
+        }
+    }
+
+    function makeMochaTest(test) {
+        return {
+            fullTitle: function() {
+                return test.name;
+            },
+            err: {
+                message: test.output[0],
+                stack: test.output.join(os.EOL)
+            }
+        };
+    }
+}
+
+function ProgressBars(options) {
+    if (!options) options = {};
+    var open = options.open || '[';
+    var close = options.close || ']';
+    var complete = options.complete || 'â–¬';
+    var incomplete = options.incomplete || Base.symbols.dot;
+    var maxWidth = Math.floor(Base.window.width * .30) - open.length - close.length - 2;
+    var width = minMax(options.width || maxWidth, 10, maxWidth);
+    this._options = {
+        open: open,
+        complete: complete,
+        incomplete: incomplete,
+        close: close,
+        width: width
+    };
+
+    this._progressBars = [];
+    this._lineCount = 0;
+    this._enabled = false;
+}
+ProgressBars.prototype = {
+    enable: function () {
+        if (!this._enabled) {
+            process.stdout.write(os.EOL);
+            this._enabled = true;
+        }
+    },
+    disable: function () {
+        if (this._enabled) {
+            process.stdout.write(os.EOL);
+            this._enabled = false;
+        }
+    },
+    update: function (index, percentComplete, color, title) {
+        percentComplete = minMax(percentComplete, 0, 1);
+
+        var progressBar = this._progressBars[index] || (this._progressBars[index] = { });
+        var width = this._options.width;
+        var n = Math.floor(width * percentComplete);
+        var i = width - n;
+        if (n === progressBar.lastN && title === progressBar.title && color === progressBar.progressColor) {
+            return;
+        }
+
+        progressBar.lastN = n;
+        progressBar.title = title;
+        progressBar.progressColor = color;
+
+        var progress = "  ";
+        progress += this._color('progress', this._options.open);
+        progress += this._color(color, fill(this._options.complete, n));
+        progress += this._color('progress', fill(this._options.incomplete, i));
+        progress += this._color('progress', this._options.close);
+
+        if (title) {
+            progress += this._color('progress', ' ' + title);
+        }
+
+        if (progressBar.text !== progress) {
+            progressBar.text = progress;
+            this._render(index);
+        }
+    },
+    _render: function (index) {
+        if (!this._enabled || !isatty) {
+            return;
+        }
+
+        cursor.hide();
+        readline.moveCursor(process.stdout, -process.stdout.columns, -this._lineCount);
+        var lineCount = 0;
+        var numProgressBars = this._progressBars.length;
+        for (var i = 0; i < numProgressBars; i++) {
+            if (i === index) {
+                readline.clearLine(process.stdout, 1);
+                process.stdout.write(this._progressBars[i].text + os.EOL);
+            }
+            else {
+                readline.moveCursor(process.stdout, -process.stdout.columns, +1);
+            }
+
+            lineCount++;
+        }
+
+        this._lineCount = lineCount;
+        cursor.show();
+    },
+    _color: function (type, text) {
+        return type && !this._options.noColors ? color(type, text) : text;
+    }
+};
+
+function fill(ch, size) {
+    var s = "";
+    while (s.length < size) {
+        s += ch;
+    }
+
+    return s.length > size ? s.substr(0, size) : s;
+}
+
+function minMax(value, min, max) {
+    if (value < min) return min;
+    if (value > max) return max;
+    return value;
+}
\ No newline at end of file

From 3681e3c4f3094aaa84483934c2b2a8cf57d2b36e Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Wed, 8 Jun 2016 18:18:26 -0700
Subject: [PATCH 06/23] Fixed typo

---
 scripts/mocha-parallel.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/mocha-parallel.js b/scripts/mocha-parallel.js
index adba8ebf57c7d..159dd630cc2cf 100644
--- a/scripts/mocha-parallel.js
+++ b/scripts/mocha-parallel.js
@@ -43,7 +43,7 @@ function discoverTests(run, options, cb) {
 
     p.on("exit", function (status) {
         if (status) {
-            cb(new Error("Process exited width code " + status));
+            cb(new Error("Process exited with code " + status));
         }
         else {
             cb();

From 4afb8c43938ffddc0ebc409b03ea47a5fe90085d Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Thu, 9 Jun 2016 22:07:07 -0700
Subject: [PATCH 07/23] Fixes an issue with runtests-parallel when global mocha
 is not installed.

---
 Jakefile.js               |  9 +++++++++
 scripts/mocha-parallel.js | 23 ++++++++---------------
 2 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/Jakefile.js b/Jakefile.js
index 4d9cc20937f2a..096546c4468c5 100644
--- a/Jakefile.js
+++ b/Jakefile.js
@@ -776,16 +776,25 @@ function runConsoleTests(defaultReporter, runInParallel) {
         tests = tests ? ' -g "' + tests + '"' : '';
         var cmd = "mocha" + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + ' -t ' + testTimeout + ' ' + run;
         console.log(cmd);
+
+        var savedNodeEnv = process.env.NODE_ENV;
+        process.env.NODE_ENV = "development";
         exec(cmd, function () {
+            process.env.NODE_ENV = savedNodeEnv;
             runLinter();
             finish();
         }, function(e, status) {
+            process.env.NODE_ENV = savedNodeEnv;
             finish(status);
         });
 
     }
     else {
+        var savedNodeEnv = process.env.NODE_ENV;
+        process.env.NODE_ENV = "development";
         runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) {
+            process.env.NODE_ENV = savedNodeEnv;
+
             // last worker clean everything and runs linter in case if there were no errors
             deleteTemporaryProjectOutput();
             jake.rmRf(taskConfigsFolder);
diff --git a/scripts/mocha-parallel.js b/scripts/mocha-parallel.js
index 159dd630cc2cf..cc695729cbd43 100644
--- a/scripts/mocha-parallel.js
+++ b/scripts/mocha-parallel.js
@@ -34,13 +34,7 @@ function discoverTests(run, options, cb) {
     console.log("Discovering tests...");
 
     var cmd = "mocha -R " + require.resolve("./mocha-none-reporter.js") + " " + run;
-    var p = child_process.spawn(
-        process.platform === "win32" ? "cmd" : "/bin/sh",
-        process.platform === "win32" ? ["/c", cmd] : ["-c", cmd], {
-            windowsVerbatimArguments: true,
-            env: { NODE_ENV: "development" }
-        });
-
+    var p = spawnProcess(cmd);
     p.on("exit", function (status) {
         if (status) {
             cb(new Error("Process exited with code " + status));
@@ -87,18 +81,11 @@ function runTests(taskConfigsFolder, run, options, cb) {
 
         // Start the background process.
         var cmd = "mocha -t " + (options.testTimeout || 20000) + " -R tap --no-colors " + run + " --config='" + partition.file + "'";
-        var p = child_process.spawn(
-            process.platform === "win32" ? "cmd" : "/bin/sh",
-            process.platform === "win32" ? ["/c", cmd] : ["-c", cmd], {
-                windowsVerbatimArguments: true,
-                env: { NODE_ENV: "development" }
-            });
-
+        var p = spawnProcess(cmd);
         var rl = readline.createInterface({
             input: p.stdout,
             terminal: false
         });
-
         rl.on("line", onmessage);
         p.on("exit", onexit)
 
@@ -259,6 +246,12 @@ function runTests(taskConfigsFolder, run, options, cb) {
     }
 }
 
+function spawnProcess(cmd, options) {
+    var shell = process.platform === "win32" ? "cmd" : "/bin/sh";
+    var prefix = process.platform === "win32" ? "/c" : "-c";
+    return child_process.spawn(shell, [prefix, cmd], { windowsVerbatimArguments: true });
+}
+
 function ProgressBars(options) {
     if (!options) options = {};
     var open = options.open || '[';

From aa4662ed5dfaab63746f93dccf78f099e76b254d Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 13 Jun 2016 12:58:21 -0700
Subject: [PATCH 08/23] Fixes runtests-parallel not reporting failure for
 failed tests.

---
 scripts/mocha-parallel.js | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/scripts/mocha-parallel.js b/scripts/mocha-parallel.js
index cc695729cbd43..bf33f68f20474 100644
--- a/scripts/mocha-parallel.js
+++ b/scripts/mocha-parallel.js
@@ -193,7 +193,6 @@ function runTests(taskConfigsFolder, run, options, cb) {
         counter--;
 
         if (counter <= 0) {
-            var failed = 0;
             var reporter = new Base(),
                 stats = reporter.stats,
                 failures = reporter.failures;
@@ -224,8 +223,8 @@ function runTests(taskConfigsFolder, run, options, cb) {
                 reporter.epilogue();
             }
 
-            if (failed) {
-                return cb(new Error("Test failures reported: " + failed));
+            if (stats.failures) {
+                return cb(new Error("Test failures reported: " + stats.failures));
             }
             else {
                 return cb();

From 27931d5f756ea29390eec38e1d9984804e39bde3 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 13 Jun 2016 13:17:56 -0700
Subject: [PATCH 09/23] Cleanup, fix linter errors, follow hoisted
 declarations.

---
 src/compiler/binder.ts                       | 11 ++--
 src/compiler/transformers/generators.ts      | 59 ++++++++------------
 src/compiler/types.ts                        | 11 ++--
 tests/baselines/reference/exportEqualsAmd.js |  2 +-
 tests/baselines/reference/exportEqualsUmd.js |  2 +-
 5 files changed, 38 insertions(+), 47 deletions(-)

diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts
index bbeb5253fff27..a5a7804b2afbe 100644
--- a/src/compiler/binder.ts
+++ b/src/compiler/binder.ts
@@ -2484,6 +2484,7 @@ namespace ts {
         const modifierFlags = getModifierFlags(node);
         const body = node.body;
         const typeParameters = node.typeParameters;
+        const asteriskToken = node.asteriskToken;
 
         // A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded,
         // generic, or has a decorator.
@@ -2495,7 +2496,7 @@ namespace ts {
         }
 
         // Currently, we only support generators that were originally async function bodies.
-        if (node.asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
+        if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
             transformFlags |= TransformFlags.AssertGenerator;
         }
 
@@ -2546,7 +2547,7 @@ namespace ts {
             transformFlags = TransformFlags.AssertTypeScript;
         }
         else {
-            transformFlags = subtreeFlags;
+            transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclaration;
 
             // If a FunctionDeclaration is exported, then it is either ES6 or TypeScript syntax.
             if (modifierFlags & ModifierFlags.Export) {
@@ -2566,7 +2567,7 @@ namespace ts {
             }
 
             // Currently, we only support generators that were originally async function bodies.
-            if (node.asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
+            if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
                 transformFlags |= TransformFlags.AssertGenerator;
             }
         }
@@ -2592,7 +2593,7 @@ namespace ts {
         }
 
         // Currently, we only support generators that were originally async function bodies.
-        if (node.asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
+        if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
             transformFlags |= TransformFlags.AssertGenerator;
         }
 
@@ -2725,7 +2726,7 @@ namespace ts {
     }
 
     function computeVariableDeclarationList(node: VariableDeclarationList, subtreeFlags: TransformFlags) {
-        let transformFlags = subtreeFlags;
+        let transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclaration;
 
         if (subtreeFlags & TransformFlags.ContainsBindingPattern) {
             transformFlags |= TransformFlags.AssertES6;
diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts
index 9e00b6e6ea5e5..29aa55314d002 100644
--- a/src/compiler/transformers/generators.ts
+++ b/src/compiler/transformers/generators.ts
@@ -137,12 +137,11 @@ namespace ts {
         Endfinally              // Marks the end of a `finally` block
     }
 
-    type OperationArguments =
-        [Label] |
-        [Label, Expression] |
-        [Statement] |
-        [Expression] |
-        [Expression, Expression];
+    type OperationArguments = [Label]
+                            | [Label, Expression]
+                            | [Statement]
+                            | [Expression]
+                            | [Expression, Expression];
 
     // whether a generated code block is opening or closing at the current operation for a FunctionBuilder
     const enum BlockAction {
@@ -394,8 +393,16 @@ namespace ts {
                 case SyntaxKind.GetAccessor:
                 case SyntaxKind.SetAccessor:
                     return visitAccessorDeclaration(<AccessorDeclaration>node);
+                case SyntaxKind.VariableStatement:
+                    return visitVariableStatement(<VariableStatement>node);
+                case SyntaxKind.BreakStatement:
+                    return visitBreakStatement(<BreakStatement>node);
+                case SyntaxKind.ContinueStatement:
+                    return visitContinueStatement(<ContinueStatement>node);
+                case SyntaxKind.ReturnStatement:
+                    return visitReturnStatement(<ReturnStatement>node);
                 default:
-                    if (node.transformFlags & (TransformFlags.ContainsGenerator | TransformFlags.ContainsYield)) {
+                    if (node.transformFlags & (TransformFlags.ContainsGenerator | TransformFlags.ContainsYield | TransformFlags.ContainsHoistedDeclaration)) {
                         return visitEachChild(node, visitor, context);
                     }
                     else {
@@ -943,19 +950,20 @@ namespace ts {
             //          _a);
 
             const properties = node.properties;
-            const numInitialProperties = countInitialNodesWithoutYield(node.properties);
+            const multiLine = node.multiLine;
+            const numInitialProperties = countInitialNodesWithoutYield(properties);
 
             const temp = declareLocal();
             emitAssignment(temp,
                 createObjectLiteral(
-                    visitNodes(node.properties, visitor, isObjectLiteralElement, 0, numInitialProperties),
+                    visitNodes(properties, visitor, isObjectLiteralElement, 0, numInitialProperties),
                     /*location*/ undefined,
-                    node.multiLine
+                    multiLine
                 )
             );
 
-            const expressions = reduceLeft(node.properties, reduceProperty, <Expression[]>[], numInitialProperties);
-            addNode(expressions, getMutableClone(temp), node.multiLine);
+            const expressions = reduceLeft(properties, reduceProperty, <Expression[]>[], numInitialProperties);
+            addNode(expressions, getMutableClone(temp), multiLine);
             return inlineExpressions(expressions);
 
             function reduceProperty(expressions: Expression[], property: ObjectLiteralElement) {
@@ -965,7 +973,7 @@ namespace ts {
                 }
 
                 const expression = createExpressionForObjectLiteralElement(node, property, temp);
-                addNode(expressions, visitNode(expression, visitor, isExpression), node.multiLine);
+                addNode(expressions, visitNode(expression, visitor, isExpression), multiLine);
                 return expressions;
             }
         }
@@ -1867,7 +1875,8 @@ namespace ts {
                 labelOffsets = [];
             }
 
-            const label = nextLabelId++;
+            const label = nextLabelId;
+            nextLabelId++;
             labelOffsets[label] = -1;
             return label;
         }
@@ -2023,7 +2032,6 @@ namespace ts {
             const exception = <ExceptionBlock>peekBlock();
             Debug.assert(exception.state < ExceptionBlockState.Finally);
 
-            const state = exception.state;
             const endLabel = exception.endLabel;
             emitBreak(endLabel);
 
@@ -2344,14 +2352,6 @@ namespace ts {
             return createCall(createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [], location);
         }
 
-        /**
-         * Emits a NOP (no operation). This is often used to ensure a new operation location exists
-         * when marking labels.
-         */
-        function emitNop(): void {
-            emitWorker(OpCode.Nop);
-        }
-
         /**
          * Emits a Statement.
          *
@@ -2421,16 +2421,6 @@ namespace ts {
             emitWorker(OpCode.Yield, [expression], location);
         }
 
-        /**
-         * Emits a YieldStar operation for the provided expression.
-         *
-         * @param expression A value for the operation.
-         * @param location An optional source map location for the assignment.
-         */
-        function emitYieldStar(expression: Expression, location?: TextRange): void {
-            emitWorker(OpCode.YieldStar, [expression], location);
-        }
-
         /**
          * Emits a Return operation for the provided expression.
          *
@@ -2651,7 +2641,6 @@ namespace ts {
                 return;
             }
 
-            let isLabel: boolean = false;
             for (let label = 0; label < labelOffsets.length; label++) {
                 if (labelOffsets[label] === operationIndex) {
                     flushLabel();
@@ -2659,7 +2648,7 @@ namespace ts {
                         labelNumbers = [];
                     }
                     if (labelNumbers[labelNumber] === undefined) {
-                        labelNumbers[labelNumber] = [label]
+                        labelNumbers[labelNumber] = [label];
                     }
                     else {
                         labelNumbers[labelNumber].push(label);
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 349c637d33667..25bbeff92b71a 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -2987,6 +2987,7 @@ namespace ts {
         ContainsBlockScopedBinding = 1 << 20,
         ContainsBindingPattern = 1 << 21,
         ContainsYield = 1 << 22,
+        ContainsHoistedDeclaration = 1 << 23,
 
         HasComputedFlags = 1 << 29, // Transform flags have been computed.
 
@@ -3002,12 +3003,12 @@ namespace ts {
         // - Bitmasks that exclude flags from propagating out of a specific context
         //   into the subtree flags of their container.
         NodeExcludes = TypeScript | Jsx | ES7 | ES6 | DestructuringAssignment | HasComputedFlags,
-        ArrowFunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield,
-        FunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield,
-        ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield,
-        MethodOrAccessorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield,
+        ArrowFunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclaration,
+        FunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclaration,
+        ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclaration,
+        MethodOrAccessorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclaration,
         ClassExcludes = NodeExcludes | ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsParameterPropertyAssignments | ContainsLexicalThisInComputedPropertyName,
-        ModuleExcludes = NodeExcludes | ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
+        ModuleExcludes = NodeExcludes | ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclaration,
         TypeExcludes = ~ContainsTypeScript,
         ObjectLiteralExcludes = NodeExcludes | ContainsDecorators | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName,
         ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsSpreadElementExpression,
diff --git a/tests/baselines/reference/exportEqualsAmd.js b/tests/baselines/reference/exportEqualsAmd.js
index a0f029589d688..385012a6e0f0f 100644
--- a/tests/baselines/reference/exportEqualsAmd.js
+++ b/tests/baselines/reference/exportEqualsAmd.js
@@ -4,6 +4,6 @@ export = { ["hi"]: "there" };
 //// [exportEqualsAmd.js]
 define(["require", "exports"], function (require, exports) {
     "use strict";
-    return (_a = {}, _a["hi"] = "there", _a);
+    return _a = {}, _a["hi"] = "there", _a;
     var _a;
 });
diff --git a/tests/baselines/reference/exportEqualsUmd.js b/tests/baselines/reference/exportEqualsUmd.js
index a9b75978d0627..cd4c99f504d12 100644
--- a/tests/baselines/reference/exportEqualsUmd.js
+++ b/tests/baselines/reference/exportEqualsUmd.js
@@ -11,6 +11,6 @@ export = { ["hi"]: "there" };
     }
 })(["require", "exports"], function (require, exports) {
     "use strict";
-    return (_a = {}, _a["hi"] = "there", _a);
+    return _a = {}, _a["hi"] = "there", _a;
     var _a;
 });

From ea61f2b32bb4c2b49481e8cd50b611fc153d589d Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Tue, 14 Jun 2016 17:59:44 -0700
Subject: [PATCH 10/23] Added tests and fixed related emit issues.

---
 src/compiler/binder.ts                        |  11 +-
 src/compiler/checker.ts                       |   4 -
 src/compiler/diagnosticMessages.json          |   4 -
 src/compiler/emitter.ts                       | 124 ++--
 src/compiler/factory.ts                       |  29 +-
 src/compiler/transformers/generators.ts       | 269 +++++----
 src/compiler/types.ts                         |  21 +-
 .../baselines/reference/es5-asyncFunction.js  |  86 +++
 .../reference/es5-asyncFunction.symbols       |  14 +
 .../reference/es5-asyncFunction.types         |  15 +
 .../es5-asyncFunctionArrayLiterals.js         | 150 +++++
 .../es5-asyncFunctionArrayLiterals.symbols    |  80 +++
 .../es5-asyncFunctionArrayLiterals.types      | 111 ++++
 .../es5-asyncFunctionBinaryExpressions.js     | 561 ++++++++++++++++++
 ...es5-asyncFunctionBinaryExpressions.symbols | 267 +++++++++
 .../es5-asyncFunctionBinaryExpressions.types  | 389 ++++++++++++
 .../es5-asyncFunctionCallExpressions.js       | 383 ++++++++++++
 .../es5-asyncFunctionCallExpressions.symbols  | 204 +++++++
 .../es5-asyncFunctionCallExpressions.types    | 276 +++++++++
 .../es5-asyncFunctionConditionals.js          |  71 +++
 .../es5-asyncFunctionConditionals.symbols     |  38 ++
 .../es5-asyncFunctionConditionals.types       |  48 ++
 .../es5-asyncFunctionDoStatements.js          | 372 ++++++++++++
 .../es5-asyncFunctionDoStatements.symbols     | 152 +++++
 .../es5-asyncFunctionDoStatements.types       | 186 ++++++
 .../es5-asyncFunctionElementAccess.js         |  56 ++
 .../es5-asyncFunctionElementAccess.symbols    |  36 ++
 .../es5-asyncFunctionElementAccess.types      |  46 ++
 .../es5-asyncFunctionForInStatements.js       | 250 ++++++++
 .../es5-asyncFunctionForInStatements.symbols  |  89 +++
 .../es5-asyncFunctionForInStatements.types    | 103 ++++
 .../es5-asyncFunctionForOfStatements.js       | 537 +++++++++++++++++
 .../es5-asyncFunctionForOfStatements.symbols  | 183 ++++++
 .../es5-asyncFunctionForOfStatements.types    | 222 +++++++
 .../es5-asyncFunctionForStatements.js         | 149 +++++
 .../es5-asyncFunctionForStatements.symbols    |  79 +++
 .../es5-asyncFunctionForStatements.types      |  83 +++
 .../reference/es5-asyncFunctionHoisting.js    | 105 ++++
 .../es5-asyncFunctionHoisting.symbols         |  87 +++
 .../reference/es5-asyncFunctionHoisting.types | 101 ++++
 .../es5-asyncFunctionIfStatements.js          |  70 +++
 .../es5-asyncFunctionIfStatements.symbols     |  35 ++
 .../es5-asyncFunctionIfStatements.types       |  38 ++
 .../reference/es5-asyncFunctionNestedLoops.js |  38 ++
 .../es5-asyncFunctionNestedLoops.symbols      |  30 +
 .../es5-asyncFunctionNestedLoops.types        |  33 ++
 .../es5-asyncFunctionNewExpressions.js        | 386 ++++++++++++
 .../es5-asyncFunctionNewExpressions.symbols   | 203 +++++++
 .../es5-asyncFunctionNewExpressions.types     | 275 +++++++++
 .../es5-asyncFunctionObjectLiterals.js        | 177 ++++++
 .../es5-asyncFunctionObjectLiterals.symbols   | 127 ++++
 .../es5-asyncFunctionObjectLiterals.types     | 148 +++++
 .../es5-asyncFunctionPropertyAccess.js        |  52 ++
 .../es5-asyncFunctionPropertyAccess.symbols   |  33 ++
 .../es5-asyncFunctionPropertyAccess.types     |  44 ++
 .../es5-asyncFunctionReturnStatements.js      |  88 +++
 .../es5-asyncFunctionReturnStatements.symbols |  56 ++
 .../es5-asyncFunctionReturnStatements.types   |  59 ++
 .../es5-asyncFunctionSwitchStatements.js      | 289 +++++++++
 .../es5-asyncFunctionSwitchStatements.symbols | 156 +++++
 .../es5-asyncFunctionSwitchStatements.types   | 164 +++++
 .../es5-asyncFunctionTryStatements.js         | 334 +++++++++++
 .../es5-asyncFunctionTryStatements.symbols    | 232 ++++++++
 .../es5-asyncFunctionTryStatements.types      | 241 ++++++++
 .../es5-asyncFunctionWhileStatements.js       | 353 +++++++++++
 .../es5-asyncFunctionWhileStatements.symbols  | 152 +++++
 .../es5-asyncFunctionWhileStatements.types    | 186 ++++++
 ...es5-asyncFunctionWithStatements.errors.txt |  58 ++
 .../es5-asyncFunctionWithStatements.js        | 118 ++++
 tests/cases/compiler/es5-asyncFunction.ts     |  10 +
 .../es5-asyncFunctionArrayLiterals.ts         |  36 ++
 .../es5-asyncFunctionBinaryExpressions.ts     | 125 ++++
 .../es5-asyncFunctionCallExpressions.ts       |  88 +++
 .../compiler/es5-asyncFunctionConditionals.ts |  16 +
 .../compiler/es5-asyncFunctionDoStatements.ts |  80 +++
 .../es5-asyncFunctionElementAccess.ts         |  16 +
 .../es5-asyncFunctionForInStatements.ts       |  40 ++
 .../es5-asyncFunctionForOfStatements.ts       |  80 +++
 .../es5-asyncFunctionForStatements.ts         |  32 +
 .../compiler/es5-asyncFunctionHoisting.ts     |  54 ++
 .../compiler/es5-asyncFunctionIfStatements.ts |  16 +
 .../compiler/es5-asyncFunctionNestedLoops.ts  |  16 +
 .../es5-asyncFunctionNewExpressions.ts        |  88 +++
 .../es5-asyncFunctionObjectLiterals.ts        |  53 ++
 .../es5-asyncFunctionPropertyAccess.ts        |  16 +
 .../es5-asyncFunctionReturnStatements.ts      |  29 +
 .../es5-asyncFunctionSwitchStatements.ts      |  70 +++
 .../es5-asyncFunctionTryStatements.ts         | 125 ++++
 .../es5-asyncFunctionWhileStatements.ts       |  80 +++
 .../es5-asyncFunctionWithStatements.ts        |  34 ++
 90 files changed, 11067 insertions(+), 203 deletions(-)
 create mode 100644 tests/baselines/reference/es5-asyncFunction.js
 create mode 100644 tests/baselines/reference/es5-asyncFunction.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunction.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionArrayLiterals.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionArrayLiterals.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionArrayLiterals.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionBinaryExpressions.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionBinaryExpressions.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionBinaryExpressions.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionCallExpressions.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionCallExpressions.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionCallExpressions.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionConditionals.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionConditionals.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionConditionals.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionDoStatements.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionDoStatements.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionDoStatements.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionElementAccess.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionElementAccess.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionElementAccess.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionForInStatements.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionForInStatements.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionForInStatements.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionForOfStatements.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionForOfStatements.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionForOfStatements.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionForStatements.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionForStatements.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionForStatements.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionHoisting.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionHoisting.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionHoisting.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionIfStatements.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionIfStatements.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionIfStatements.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionNestedLoops.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionNestedLoops.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionNestedLoops.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionNewExpressions.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionNewExpressions.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionNewExpressions.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionObjectLiterals.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionObjectLiterals.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionObjectLiterals.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionPropertyAccess.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionPropertyAccess.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionPropertyAccess.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionReturnStatements.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionReturnStatements.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionReturnStatements.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionSwitchStatements.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionSwitchStatements.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionSwitchStatements.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionTryStatements.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionTryStatements.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionTryStatements.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionWhileStatements.js
 create mode 100644 tests/baselines/reference/es5-asyncFunctionWhileStatements.symbols
 create mode 100644 tests/baselines/reference/es5-asyncFunctionWhileStatements.types
 create mode 100644 tests/baselines/reference/es5-asyncFunctionWithStatements.errors.txt
 create mode 100644 tests/baselines/reference/es5-asyncFunctionWithStatements.js
 create mode 100644 tests/cases/compiler/es5-asyncFunction.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionArrayLiterals.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionBinaryExpressions.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionCallExpressions.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionConditionals.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionDoStatements.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionElementAccess.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionForInStatements.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionForOfStatements.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionForStatements.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionHoisting.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionIfStatements.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionNestedLoops.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionNewExpressions.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionObjectLiterals.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionPropertyAccess.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionReturnStatements.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionSwitchStatements.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionTryStatements.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionWhileStatements.ts
 create mode 100644 tests/cases/compiler/es5-asyncFunctionWithStatements.ts

diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts
index a5a7804b2afbe..ce0ee4678ee35 100644
--- a/src/compiler/binder.ts
+++ b/src/compiler/binder.ts
@@ -2547,7 +2547,7 @@ namespace ts {
             transformFlags = TransformFlags.AssertTypeScript;
         }
         else {
-            transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclaration;
+            transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclarationOrCompletion;
 
             // If a FunctionDeclaration is exported, then it is either ES6 or TypeScript syntax.
             if (modifierFlags & ModifierFlags.Export) {
@@ -2726,7 +2726,7 @@ namespace ts {
     }
 
     function computeVariableDeclarationList(node: VariableDeclarationList, subtreeFlags: TransformFlags) {
-        let transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclaration;
+        let transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclarationOrCompletion;
 
         if (subtreeFlags & TransformFlags.ContainsBindingPattern) {
             transformFlags |= TransformFlags.AssertES6;
@@ -2794,6 +2794,7 @@ namespace ts {
                 // These nodes are ES6 syntax.
                 transformFlags |= TransformFlags.AssertES6;
                 break;
+
             case SyntaxKind.YieldExpression:
                 // This node is ES6 syntax.
                 transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsYield;
@@ -2920,6 +2921,12 @@ namespace ts {
                 }
 
                 break;
+
+            case SyntaxKind.ReturnStatement:
+            case SyntaxKind.ContinueStatement:
+            case SyntaxKind.BreakStatement:
+                transformFlags |= TransformFlags.ContainsHoistedDeclarationOrCompletion;
+                break;
         }
 
         node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 74af285bfcb9f..7c3ea929545fd 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -18069,10 +18069,6 @@ namespace ts {
         }
 
         function checkGrammarAsyncModifier(node: Node, asyncModifier: Node): boolean {
-            if (languageVersion < ScriptTarget.ES6) {
-                return grammarErrorOnNode(asyncModifier, Diagnostics.Async_functions_are_only_available_when_targeting_ECMAScript_6_and_higher);
-            }
-
             switch (node.kind) {
                 case SyntaxKind.MethodDeclaration:
                 case SyntaxKind.FunctionDeclaration:
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index 034bd27b1472a..d22497e4a6396 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -831,10 +831,6 @@
         "category": "Error",
         "code": 1308
     },
-    "Async functions are only available when targeting ECMAScript 6 and higher.": {
-        "category": "Error",
-        "code": 1311
-    },
     "'=' can only be used in an object literal property inside a destructuring assignment.": {
         "category": "Error",
         "code": 1312
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index b066540c6b55a..0ff60a0fe3149 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -73,99 +73,52 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
 
         const generatorHelper = `
 var __generator = (this && this.__generator) || function (body) {
-    var done, finallyStack, executing, yieldStar, trys = [], state = { label: 0, trys: trys };
+    var _ = { label: 0, sent: function() { if (sent[0] === 1 /*throw*/) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent;
     function step(op) {
-        if (executing) throw new TypeError("Generator is already executing.");
+        if (_.flag) throw new TypeError("Generator is already executing.");
         while (true) {
-            if (done) {
-                switch (op[0]) {
-                    case 0 /*next*/: return { value: void 0, done: true };
-                    case 6 /*catch*/:
-                    case 1 /*throw*/: throw op[1];
-                    case 2 /*return*/: return { value: op[1], done: true };
-                }
+            if (_.done) switch (op[0]) {
+                case 0 /*next*/: return { value: void 0, done: true };
+                case 1 /*throw*/: case 6 /*catch*/: throw op[1];
+                case 2 /*return*/: return { value: op[1], done: true };
             }
             try {
-                executing = true;
-                if (yieldStar) {
-                    var verb = yieldStar[op[0] === 2 ? "return" : op[0] === 1 ? "throw" : "next"];
-                    if (verb) {
-                        var yielded = verb.call(yieldStar, op[1]);
-                        if (!yielded.done) return { value: yielded.value, done: false };
-                        op = [0 /*next*/, yielded.value];
-                    }
-
-                    yieldStar = void 0;
-                    continue;
-                }
-
-                switch (op[0]) {
-                    case 0 /*next*/:
-                        state.sent = function() { return op[1]; };
-                        break;
-
-                    case 1 /*throw*/:
-                        state.sent = function() { throw op[1]; };
-                        break;
-
-                    case 4 /*yield*/:
-                        state.label++;
-                        return { value: op[1], done: false };
-
-                    case 5 /*yieldstar*/:
-                        state.label++;
-                        yieldStar = op[1];
-                        op = [0 /*next*/, void 0];
-                        continue;
-
-                    case 7 /*endfinally*/:
-                        op = finallyStack.pop();
-                        trys.pop();
-                        continue;
-
+                switch (_.flag = true, op[0]) {
+                    case 0 /*next*/: case 1 /*throw*/: sent = op; break;
+                    case 4 /*yield*/: return _.label++, { value: op[1], done: false };
+                    case 7 /*endfinally*/: op = _.stack.pop(), _.trys.pop(); continue;
                     default:
-                        var rgn = trys.length && trys[trys.length - 1];
-                        if (!rgn && (op[0] === 6 /*catch*/ || op[0] === 1 /*throw*/ || op[0] === 2 /*return*/)) {
-                            done = true;
-                            finallyStack = void 0;
+                        var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
+                        if (!r && (op[0] === 1 /*throw*/ || op[0] === 6 /*catch*/ || op[0] === 2 /*return*/)) {
+                            _.done = true;
                             continue;
                         }
-                        else if (op[0] === 3 /*break*/ && (!rgn || (op[1] > rgn[0] && op[1] < rgn[3]))) {
-                            state.label = op[1];
+                        if (op[0] === 3 /*break*/ && (!r || (op[1] > r[0] && op[1] < r[3]))) {
+                            _.label = op[1];
                         }
-                        else if (op[0] === 6 /*catch*/ && rgn && state.label < rgn[1]) {
-                            state.error = op[1];
-                            state.label = rgn[1];
+                        else if (op[0] === 6 /*catch*/ && r && _.label < r[1]) {
+                            _.label = r[1], sent = op;
                         }
-                        else if (rgn && state.label < rgn[2]) {
-                            (finallyStack || []).push(op);
-                            state.label = rgn[2];
+                        else if (r && _.label < r[2]) {
+                            _.label = r[2], _.stack.push(op);
                         }
                         else {
-                            if (rgn[2]) finallyStack.pop();
-                            trys.pop();
+                            if (r[2]) _.stack.pop();
+                            _.trys.pop();
                             continue;
                         }
                 }
-
-                op = body(state);
-            }
-            catch (e) {
-                op = [6 /*catch*/, e];
-                yieldStar = void 0;
-            }
-            finally {
-                executing = false;
-                verb = yielded = void 0;
+                op = body(_);
             }
+            catch (e) { op = [6 /*catch*/, e]; }
+            finally { _.flag = false, sent = void 0; }
         }
     }
-    var g = {
+    return {
         next: function (v) { return step([0 /*next*/, v]); },
         "throw": function (v) { return step([1 /*throw*/, v]); },
         "return": function (v) { return step([2 /*return*/, v]); }
     };
-    return g;
 };`;
 
         // emit output for the __export helper function
@@ -782,6 +735,8 @@ const _super = (function (geti, seti) {
             switch (kind) {
                 // Literals
                 case SyntaxKind.NumericLiteral:
+                    return emitNumericLiteral(<NumericLiteral>node);
+
                 case SyntaxKind.StringLiteral:
                 case SyntaxKind.RegularExpressionLiteral:
                 case SyntaxKind.NoSubstitutionTemplateLiteral:
@@ -870,6 +825,13 @@ const _super = (function (geti, seti) {
         //
 
         // SyntaxKind.NumericLiteral
+        function emitNumericLiteral(node: NumericLiteral) {
+            emitLiteral(node);
+            if (node.trailingComment) {
+                write(` /*${node.trailingComment}*/`);
+            }
+        }
+
         // SyntaxKind.StringLiteral
         // SyntaxKind.RegularExpressionLiteral
         // SyntaxKind.NoSubstitutionTemplateLiteral
@@ -1653,15 +1615,21 @@ const _super = (function (geti, seti) {
                         increaseIndent();
                     }
 
-                    const savedTempFlags = tempFlags;
-                    tempFlags = 0;
-                    emitSignatureHead(node);
-                    emitBlockFunctionBody(node, body);
+                    if (node.emitFlags & NodeEmitFlags.ReuseTempVariableScope) {
+                        emitSignatureHead(node);
+                        emitBlockFunctionBody(node, body);
+                    }
+                    else {
+                        const savedTempFlags = tempFlags;
+                        tempFlags = 0;
+                        emitSignatureHead(node);
+                        emitBlockFunctionBody(node, body);
+                        tempFlags = savedTempFlags;
+                    }
+
                     if (indentedFlag) {
                         decreaseIndent();
                     }
-
-                    tempFlags = savedTempFlags;
                 }
                 else {
                     emitSignatureHead(node);
diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts
index f95245c4f27d6..ee1fe3bd2bbe2 100644
--- a/src/compiler/factory.ts
+++ b/src/compiler/factory.ts
@@ -139,7 +139,7 @@ namespace ts {
         return node;
     }
 
-    export function createTempVariable(recordTempVariable: (node: Identifier) => void, location?: TextRange): Identifier {
+    export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, location?: TextRange): Identifier {
         const name = <Identifier>createNode(SyntaxKind.Identifier, location);
         name.text = "";
         name.originalKeywordKind = SyntaxKind.Unknown;
@@ -366,6 +366,13 @@ namespace ts {
         return node;
     }
 
+    export function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) {
+        if (node.expression !== expression || node.argumentExpression !== argumentExpression) {
+            return updateNode(createElementAccess(expression, argumentExpression, node), node);
+        }
+        return node;
+    }
+
     export function createCall(expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[], location?: TextRange, flags?: NodeFlags) {
         const node = <CallExpression>createNode(SyntaxKind.CallExpression, location, flags);
         node.expression = parenthesizeForAccess(expression);
@@ -1378,19 +1385,29 @@ namespace ts {
         thisArg: Expression;
     }
 
-    function shouldBeCapturedInTempVariable(node: Expression): boolean {
-        switch (skipParentheses(node).kind) {
+    function shouldBeCapturedInTempVariable(node: Expression, cacheIdentifiers: boolean): boolean {
+        const target = skipParentheses(node);
+        switch (target.kind) {
             case SyntaxKind.Identifier:
+                return cacheIdentifiers;
             case SyntaxKind.ThisKeyword:
             case SyntaxKind.NumericLiteral:
             case SyntaxKind.StringLiteral:
                 return false;
+            case SyntaxKind.ArrayLiteralExpression:
+                const elements = (<ArrayLiteralExpression>target).elements;
+                if (elements.length === 0) {
+                    return false;
+                }
+                return true;
+            case SyntaxKind.ObjectLiteralExpression:
+                return (<ObjectLiteralExpression>target).properties.length > 0;
             default:
                 return true;
         }
     }
 
-    export function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget): CallBinding {
+    export function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers?: boolean): CallBinding {
         const callee = skipOuterExpressions(expression, OuterExpressionKinds.All);
         let thisArg: Expression;
         let target: LeftHandSideExpression;
@@ -1405,7 +1422,7 @@ namespace ts {
         else {
             switch (callee.kind) {
                 case SyntaxKind.PropertyAccessExpression: {
-                    if (shouldBeCapturedInTempVariable((<PropertyAccessExpression>callee).expression)) {
+                    if (shouldBeCapturedInTempVariable((<PropertyAccessExpression>callee).expression, cacheIdentifiers)) {
                         // for `a.b()` target is `(_a = a).b` and thisArg is `_a`
                         thisArg = createTempVariable(recordTempVariable);
                         target = createPropertyAccess(
@@ -1426,7 +1443,7 @@ namespace ts {
                 }
 
                 case SyntaxKind.ElementAccessExpression: {
-                    if (shouldBeCapturedInTempVariable((<ElementAccessExpression>callee).expression)) {
+                    if (shouldBeCapturedInTempVariable((<ElementAccessExpression>callee).expression, cacheIdentifiers)) {
                         // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a`
                         thisArg = createTempVariable(recordTempVariable);
                         target = createElementAccess(
diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts
index 29aa55314d002..133ed01f09170 100644
--- a/src/compiler/transformers/generators.ts
+++ b/src/compiler/transformers/generators.ts
@@ -235,9 +235,12 @@ namespace ts {
             hoistFunctionDeclaration,
             hoistVariableDeclaration,
             setSourceMapRange,
-            setCommentRange
+            setCommentRange,
+            setNodeEmitFlags
         } = context;
 
+        const compilerOptions = context.getCompilerOptions();
+        const languageVersion = getEmitScriptTarget(compilerOptions);
         const resolver = context.getEmitResolver();
         const previousOnSubstituteNode = context.onSubstituteNode;
         context.onSubstituteNode = onSubstituteNode;
@@ -316,10 +319,10 @@ namespace ts {
             else if (inGeneratorFunctionBody) {
                 return visitJavaScriptInGeneratorFunctionBody(node);
             }
-            else if (node.transformFlags & TransformFlags.Generator) {
+            else if (transformFlags & TransformFlags.Generator) {
                 return visitGenerator(node);
             }
-            else if (node.transformFlags & TransformFlags.ContainsGenerator) {
+            else if (transformFlags & TransformFlags.ContainsGenerator) {
                 return visitEachChild(node, visitor, context);
             }
             else {
@@ -366,10 +369,6 @@ namespace ts {
                     return visitDoStatement(<DoStatement>node);
                 case SyntaxKind.WhileStatement:
                     return visitWhileStatement(<WhileStatement>node);
-                case SyntaxKind.ForStatement:
-                    return visitForStatement(<ForStatement>node);
-                case SyntaxKind.ForInStatement:
-                    return visitForInStatement(<ForInStatement>node);
                 case SyntaxKind.SwitchStatement:
                     return visitSwitchStatement(<SwitchStatement>node);
                 case SyntaxKind.LabeledStatement:
@@ -395,6 +394,10 @@ namespace ts {
                     return visitAccessorDeclaration(<AccessorDeclaration>node);
                 case SyntaxKind.VariableStatement:
                     return visitVariableStatement(<VariableStatement>node);
+                case SyntaxKind.ForStatement:
+                    return visitForStatement(<ForStatement>node);
+                case SyntaxKind.ForInStatement:
+                    return visitForInStatement(<ForInStatement>node);
                 case SyntaxKind.BreakStatement:
                     return visitBreakStatement(<BreakStatement>node);
                 case SyntaxKind.ContinueStatement:
@@ -402,7 +405,7 @@ namespace ts {
                 case SyntaxKind.ReturnStatement:
                     return visitReturnStatement(<ReturnStatement>node);
                 default:
-                    if (node.transformFlags & (TransformFlags.ContainsGenerator | TransformFlags.ContainsYield | TransformFlags.ContainsHoistedDeclaration)) {
+                    if (node.transformFlags & (TransformFlags.ContainsGenerator | TransformFlags.ContainsYield | TransformFlags.ContainsHoistedDeclarationOrCompletion)) {
                         return visitEachChild(node, visitor, context);
                     }
                     else {
@@ -568,7 +571,7 @@ namespace ts {
             operations = undefined;
             operationArguments = undefined;
             operationLocations = undefined;
-            state = createUniqueName("state");
+            state = createTempVariable(/*recordTempVariable*/ undefined);
 
             // Build the generator
             startLexicalEnvironment();
@@ -646,54 +649,98 @@ namespace ts {
             }
         }
 
+        function isCompoundAssignment(kind: SyntaxKind) {
+            return kind >= SyntaxKind.FirstCompoundAssignment
+                && kind <= SyntaxKind.LastCompoundAssignment;
+        }
+
+        function getOperatorForCompoundAssignment(kind: SyntaxKind) {
+            switch (kind) {
+                case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken;
+                case SyntaxKind.MinusEqualsToken: return SyntaxKind.MinusToken;
+                case SyntaxKind.AsteriskEqualsToken: return SyntaxKind.AsteriskToken;
+                case SyntaxKind.AsteriskAsteriskEqualsToken: return SyntaxKind.AsteriskAsteriskToken;
+                case SyntaxKind.SlashEqualsToken: return SyntaxKind.SlashToken;
+                case SyntaxKind.PercentEqualsToken: return SyntaxKind.PercentToken;
+                case SyntaxKind.LessThanLessThanEqualsToken: return SyntaxKind.LessThanLessThanToken;
+                case SyntaxKind.GreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanToken;
+                case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanGreaterThanToken;
+                case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AmpersandToken;
+                case SyntaxKind.BarEqualsToken: return SyntaxKind.BarToken;
+                case SyntaxKind.CaretEqualsToken: return SyntaxKind.CaretToken;
+            }
+        }
+
         /**
          * Visits a right-associative binary expression containing `yield`.
          *
          * @param node The node to visit.
          */
         function visitRightAssociativeBinaryExpression(node: BinaryExpression) {
-            switch (node.left.kind) {
-                case SyntaxKind.PropertyAccessExpression: {
-                    // [source]
-                    //      a.b = yield;
-                    //
-                    // [intermediate]
-                    //  .local _a
-                    //      _a = a;
-                    //  .yield resumeLabel
-                    //  .mark resumeLabel
-                    //      _a.b = %sent%;
-
-                    const clone = getMutableClone(node);
-                    const propertyAccess = <PropertyAccessExpression>node.left;
-                    const propertyAccessClone = getMutableClone(propertyAccess);
-                    propertyAccessClone.expression = cacheExpression(visitNode(propertyAccess.expression, visitor, isLeftHandSideExpression));
-                    clone.left = propertyAccessClone;
-                    clone.right = visitNode(node.right, visitor, isExpression);
-                    return clone;
+            const { left, right } = node;
+            if (containsYield(right)) {
+                let target: Expression;
+                switch (left.kind) {
+                    case SyntaxKind.PropertyAccessExpression:
+                        // [source]
+                        //      a.b = yield;
+                        //
+                        // [intermediate]
+                        //  .local _a
+                        //      _a = a;
+                        //  .yield resumeLabel
+                        //  .mark resumeLabel
+                        //      _a.b = %sent%;
+
+                        target = updatePropertyAccess(
+                            <PropertyAccessExpression>left,
+                            cacheExpression(visitNode((<PropertyAccessExpression>left).expression, visitor, isLeftHandSideExpression)),
+                            (<PropertyAccessExpression>left).name
+                        );
+                        break;
+
+                    case SyntaxKind.ElementAccessExpression:
+                        // [source]
+                        //      a[b] = yield;
+                        //
+                        // [intermediate]
+                        //  .local _a, _b
+                        //      _a = a;
+                        //      _b = b;
+                        //  .yield resumeLabel
+                        //  .mark resumeLabel
+                        //      _a[_b] = %sent%;
+
+                        target = updateElementAccess(<ElementAccessExpression>left,
+                            cacheExpression(visitNode((<ElementAccessExpression>left).expression, visitor, isLeftHandSideExpression)),
+                            cacheExpression(visitNode((<ElementAccessExpression>left).argumentExpression, visitor, isExpression))
+                        );
+                        break;
+
+                    default:
+                        target = visitNode(left, visitor, isExpression);
+                        break;
                 }
-                case SyntaxKind.ElementAccessExpression: {
-                    // [source]
-                    //      a[b] = yield;
-                    //
-                    // [intermediate]
-                    //  .local _a, _b
-                    //      _a = a;
-                    //      _b = b;
-                    //  .yield resumeLabel
-                    //  .mark resumeLabel
-                    //      _a[_b] = %sent%;
-
-                    const clone = getMutableClone(node);
-                    const elementAccess = <ElementAccessExpression>node.left;
-                    const elementAccessClone = getMutableClone(elementAccess);
-                    elementAccessClone.expression = cacheExpression(visitNode(elementAccess.expression, visitor, isLeftHandSideExpression));
-                    elementAccessClone.argumentExpression = cacheExpression(visitNode(elementAccess.argumentExpression, visitor, isExpression));
-                    clone.left = elementAccessClone;
-                    clone.right = visitNode(node.right, visitor, isExpression);
-                    return clone;
+
+                const operator = node.operatorToken.kind;
+                if (isCompoundAssignment(operator)) {
+                    return createBinary(
+                        target,
+                        SyntaxKind.EqualsToken,
+                        createBinary(
+                            cacheExpression(target),
+                            getOperatorForCompoundAssignment(operator),
+                            visitNode(right, visitor, isExpression),
+                            node
+                        ),
+                        node
+                    );
+                }
+                else {
+                    return updateBinary(node, target, visitNode(right, visitor, isExpression));
                 }
             }
+
             return visitEachChild(node, visitor, context);
         }
 
@@ -902,26 +949,34 @@ namespace ts {
             //      ar = _a.concat([%sent%, 2]);
 
             const numInitialElements = countInitialNodesWithoutYield(elements);
-
             const temp = declareLocal();
-            emitAssignment(temp,
-                createArrayLiteral(
-                    visitNodes(elements, visitor, isExpression, 0, numInitialElements)
-                )
-            );
+            let hasAssignedTemp = false;
+            if (numInitialElements > 0) {
+                emitAssignment(temp,
+                    createArrayLiteral(
+                        visitNodes(elements, visitor, isExpression, 0, numInitialElements)
+                    )
+                );
+                hasAssignedTemp = true;
+            }
 
             const expressions = reduceLeft(elements, reduceElement, <Expression[]>[], numInitialElements);
-            return createArrayConcat(temp, [createArrayLiteral(expressions)]);
+            return hasAssignedTemp
+                ? createArrayConcat(temp, [createArrayLiteral(expressions)])
+                : createArrayLiteral(expressions);
 
             function reduceElement(expressions: Expression[], element: Expression) {
                 if (containsYield(element) && expressions.length > 0) {
                     emitAssignment(
                         temp,
-                        createArrayConcat(
-                            temp,
-                            [createArrayLiteral(expressions)]
-                        )
+                        hasAssignedTemp
+                            ? createArrayConcat(
+                                temp,
+                                [createArrayLiteral(expressions)]
+                            )
+                            : createArrayLiteral(expressions)
                     );
+                    hasAssignedTemp = true;
                     expressions = [];
                 }
 
@@ -1017,7 +1072,7 @@ namespace ts {
                 //  .mark resumeLabel
                 //      _b.apply(_a, _c.concat([%sent%, 2]));
 
-                const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration);
+                const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true);
                 return setOriginalNode(
                     createFunctionApply(
                         cacheExpression(visitNode(target, visitor, isLeftHandSideExpression)),
@@ -1121,7 +1176,7 @@ namespace ts {
                 case SyntaxKind.TryStatement:
                     return transformAndEmitTryStatement(<TryStatement>node);
                 default:
-                    return emitStatement(visitEachChild(node, visitor, context));
+                    return emitStatement(visitNode(node, visitor, isStatement, /*optional*/ true));
             }
         }
 
@@ -1398,14 +1453,14 @@ namespace ts {
                 //      }
                 //
                 // [intermediate]
-                //  .local _a, _b, _c
+                //  .local _a, _b, _i
                 //      _a = [];
                 //      for (_b in o) _a.push(_b);
-                //      _c = 0;
+                //      _i = 0;
                 //  .loop incrementLabel, endLoopLabel
                 //  .mark conditionLabel
-                //  .brfalse endLoopLabel, (_c < _a.length)
-                //      p = _a[_c];
+                //  .brfalse endLoopLabel, (_i < _a.length)
+                //      p = _a[_i];
                 //      /*body*/
                 //  .mark incrementLabel
                 //      _b++;
@@ -1415,9 +1470,9 @@ namespace ts {
 
                 const keysArray = declareLocal(); // _a
                 const key = declareLocal(); // _b
-                const keysIndex = declareLocal(); // _c
+                const keysIndex = createLoopVariable(); // _i
                 const initializer = node.initializer;
-
+                hoistVariableDeclaration(keysIndex);
                 emitAssignment(keysArray, createArrayLiteral());
 
                 emitStatement(
@@ -1440,6 +1495,9 @@ namespace ts {
                 const incrementLabel = defineLabel();
                 const endLabel = beginLoopBlock(incrementLabel);
 
+                markLabel(conditionLabel);
+                emitBreakWhenFalse(endLabel, createLessThan(keysIndex, createPropertyAccess(keysArray, "length")));
+
                 let variable: Expression;
                 if (isVariableDeclarationList(initializer)) {
                     for (const variable of initializer.declarations) {
@@ -1449,13 +1507,10 @@ namespace ts {
                     variable = <Identifier>getSynthesizedClone(initializer.declarations[0].name);
                 }
                 else {
-                    variable = initializer;
+                    variable = visitNode(initializer, visitor, isExpression);
                     Debug.assert(isLeftHandSideExpression(variable));
                 }
 
-                markLabel(conditionLabel);
-                emitBreakWhenFalse(endLabel, createLessThan(keysIndex, createPropertyAccess(keysArray, "length")));
-
                 emitAssignment(variable, createElementAccess(keysArray, keysIndex));
                 transformAndEmitEmbeddedStatement(node.statement);
 
@@ -1580,7 +1635,7 @@ namespace ts {
         }
 
         function transformAndEmitSwitchStatement(node: SwitchStatement) {
-            if (containsYield(node)) {
+            if (containsYield(node.caseBlock)) {
                 // [source]
                 //      switch (x) {
                 //          case a:
@@ -1636,6 +1691,7 @@ namespace ts {
                 let clausesWritten = 0;
                 let pendingClauses: CaseClause[] = [];
                 while (clausesWritten < numClauses) {
+                    let defaultClausesSkipped = 0;
                     for (let i = clausesWritten; i < numClauses; i++) {
                         const clause = caseBlock.clauses[i];
                         if (clause.kind === SyntaxKind.CaseClause) {
@@ -1653,6 +1709,9 @@ namespace ts {
                                 )
                             );
                         }
+                        else {
+                            defaultClausesSkipped++;
+                        }
                     }
 
                     if (pendingClauses.length) {
@@ -1660,6 +1719,10 @@ namespace ts {
                         clausesWritten += pendingClauses.length;
                         pendingClauses = [];
                     }
+                    if (defaultClausesSkipped > 0) {
+                        clausesWritten += defaultClausesSkipped;
+                        defaultClausesSkipped = 0;
+                    }
                 }
 
                 if (defaultClauseIndex >= 0) {
@@ -1772,10 +1835,6 @@ namespace ts {
                 beginExceptionBlock();
                 transformAndEmitEmbeddedStatement(node.tryBlock);
                 if (node.catchClause) {
-                    if (!renamedCatchVariables) {
-                        renamedCatchVariables = {};
-                    }
-
                     beginCatchBlock(node.catchClause.variableDeclaration);
                     transformAndEmitEmbeddedStatement(node.catchClause.block);
                 }
@@ -1844,17 +1903,11 @@ namespace ts {
 
         function cacheExpression(node: Expression): Identifier {
             let temp: Identifier;
-            if (isIdentifier(node)) {
-                if (nodeIsSynthesized(node) || isGeneratedIdentifier(node)) {
-                    return node;
-                }
-
-                temp = createUniqueName(node.text);
-            }
-            else {
-                temp = createTempVariable(hoistVariableDeclaration);
+            if (isGeneratedIdentifier(node)) {
+                return node;
             }
 
+            temp = createTempVariable(hoistVariableDeclaration);
             emitAssignment(temp, node, /*location*/ node);
             return temp;
         }
@@ -1862,7 +1915,7 @@ namespace ts {
         function declareLocal(name?: string): Identifier {
             const temp = name
                 ? createUniqueName(name)
-                : createTempVariable(hoistVariableDeclaration);
+                : createTempVariable(/*recordTempVariable*/ undefined);
             hoistVariableDeclaration(temp);
             return temp;
         }
@@ -1983,7 +2036,7 @@ namespace ts {
                 startLabel,
                 endLabel
             });
-            emitWorker(OpCode.Nop);
+            emitNop();
             return endLabel;
         }
 
@@ -1996,7 +2049,7 @@ namespace ts {
             Debug.assert(peekBlockKind() === CodeBlockKind.Exception);
 
             const text = (<Identifier>variable.name).text;
-            const name = createUniqueName(text);
+            const name = declareLocal(text);
 
             if (!renamedCatchVariables) {
                 renamedCatchVariables = {};
@@ -2019,8 +2072,8 @@ namespace ts {
             exception.catchVariable = name;
             exception.catchLabel = catchLabel;
 
-            emitAssignment(name, createPropertyAccess(state, "error"));
-            emitWorker(OpCode.Nop);
+            emitAssignment(name, createCall(createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, []));
+            emitNop();
         }
 
         /**
@@ -2056,6 +2109,7 @@ namespace ts {
             }
 
             markLabel(exception.endLabel);
+            emitNop();
             exception.state = ExceptionBlockState.Done;
         }
 
@@ -2352,6 +2406,13 @@ namespace ts {
             return createCall(createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [], location);
         }
 
+        /**
+         * Emits an empty instruction.
+         */
+        function emitNop() {
+            emitWorker(OpCode.Nop);
+        }
+
         /**
          * Emits a Statement.
          *
@@ -2362,7 +2423,7 @@ namespace ts {
                 emitWorker(OpCode.Statement, [node]);
             }
             else {
-                emitWorker(OpCode.Nop);
+                emitNop();
             }
         }
 
@@ -2487,18 +2548,24 @@ namespace ts {
             currentExceptionBlock = undefined;
             withBlockStack = undefined;
 
+            const buildResult = buildStatements();
             return createCall(
                 createIdentifier("__generator"),
                 /*typeArguments*/ undefined,
-                [createFunctionExpression(
-                    /*asteriskToken*/ undefined,
-                    /*name*/ undefined,
-                    /*typeParameters*/ undefined,
-                    [createParameter(state)],
-                    /*type*/ undefined,
-                    createBlock(
-                        buildStatements()
-                    )
+                [setNodeEmitFlags(
+                    createFunctionExpression(
+                        /*asteriskToken*/ undefined,
+                        /*name*/ undefined,
+                        /*typeParameters*/ undefined,
+                        [createParameter(state)],
+                        /*type*/ undefined,
+                        createBlock(
+                            buildResult,
+                            /*location*/ undefined,
+                            /*multiLine*/ buildResult.length > 0
+                        )
+                    ),
+                    NodeEmitFlags.ReuseTempVariableScope
                 )]
             );
         }
@@ -2521,6 +2588,7 @@ namespace ts {
             if (clauses) {
                 const labelExpression = createPropertyAccess(state, "label");
                 const switchStatement = createSwitch(labelExpression, createCaseBlock(clauses));
+                switchStatement.startsOnNewLine = true;
                 return [switchStatement];
             }
 
@@ -2552,6 +2620,7 @@ namespace ts {
         function flushFinalLabel(operationIndex: number): void {
             if (!lastOperationWasCompletion) {
                 tryEnterLabel(operationIndex);
+                withBlockStack = undefined;
                 writeReturn(/*expression*/ undefined, /*operationLocation*/ undefined);
             }
 
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 25bbeff92b71a..60ebb2d5d6b43 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -359,6 +359,8 @@ namespace ts {
         // Markers
         FirstAssignment = EqualsToken,
         LastAssignment = CaretEqualsToken,
+        FirstCompoundAssignment = PlusEqualsToken,
+        LastCompoundAssignment = CaretEqualsToken,
         FirstReservedWord = BreakKeyword,
         LastReservedWord = WithKeyword,
         FirstKeyword = BreakKeyword,
@@ -2987,7 +2989,7 @@ namespace ts {
         ContainsBlockScopedBinding = 1 << 20,
         ContainsBindingPattern = 1 << 21,
         ContainsYield = 1 << 22,
-        ContainsHoistedDeclaration = 1 << 23,
+        ContainsHoistedDeclarationOrCompletion = 1 << 23,
 
         HasComputedFlags = 1 << 29, // Transform flags have been computed.
 
@@ -3002,13 +3004,13 @@ namespace ts {
         // Scope Exclusions
         // - Bitmasks that exclude flags from propagating out of a specific context
         //   into the subtree flags of their container.
-        NodeExcludes = TypeScript | Jsx | ES7 | ES6 | DestructuringAssignment | HasComputedFlags,
-        ArrowFunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclaration,
-        FunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclaration,
-        ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclaration,
-        MethodOrAccessorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclaration,
+        NodeExcludes = TypeScript | Jsx | ES7 | ES6 | DestructuringAssignment | Generator | HasComputedFlags,
+        ArrowFunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
+        FunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
+        ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
+        MethodOrAccessorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
         ClassExcludes = NodeExcludes | ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsParameterPropertyAssignments | ContainsLexicalThisInComputedPropertyName,
-        ModuleExcludes = NodeExcludes | ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclaration,
+        ModuleExcludes = NodeExcludes | ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion,
         TypeExcludes = ~ContainsTypeScript,
         ObjectLiteralExcludes = NodeExcludes | ContainsDecorators | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName,
         ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsSpreadElementExpression,
@@ -3047,13 +3049,14 @@ namespace ts {
         LocalName = 1 << 18,                     // Ensure an export prefix is not added for an identifier that points to an exported declaration.
         Indented = 1 << 19,                      // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter).
         AsyncFunctionBody = 1 << 20,
+        ReuseTempVariableScope = 1 << 21,        // Reuse the existing temp variable scope during emit.
 
         // SourceMap Specialization.
         // TODO(rbuckton): These should be removed once source maps are aligned with the old
         //                 emitter and new baselines are taken. This exists solely to
         //                 align with the old emitter.
-        SourceMapEmitOpenBraceAsToken = 1 << 21,        // Emits the open brace of a block function body as a source mapped token.
-        SourceMapAdjustRestParameterLoop = 1 << 22,     // Emits adjusted source map positions for a ForStatement generated when transforming a rest parameter for ES5/3.
+        SourceMapEmitOpenBraceAsToken = 1 << 22,        // Emits the open brace of a block function body as a source mapped token.
+        SourceMapAdjustRestParameterLoop = 1 << 23,     // Emits adjusted source map positions for a ForStatement generated when transforming a rest parameter for ES5/3.
     }
 
     /** Additional context provided to `visitEachChild` */
diff --git a/tests/baselines/reference/es5-asyncFunction.js b/tests/baselines/reference/es5-asyncFunction.js
new file mode 100644
index 0000000000000..28197f55bae48
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunction.js
@@ -0,0 +1,86 @@
+//// [es5-asyncFunction.ts]
+declare var x;
+
+async function empty() {
+}
+
+async function singleAwait() {
+    await x;
+}
+
+//// [es5-asyncFunction.js]
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments)).next());
+    });
+};
+var __generator = (this && this.__generator) || function (body) {
+    var _ = { label: 0, sent: function() { if (sent[0] === 1 /*throw*/) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent;
+    function step(op) {
+        if (_.flag) throw new TypeError("Generator is already executing.");
+        while (true) {
+            if (_.done) switch (op[0]) {
+                case 0 /*next*/: return { value: void 0, done: true };
+                case 1 /*throw*/: case 6 /*catch*/: throw op[1];
+                case 2 /*return*/: return { value: op[1], done: true };
+            }
+            try {
+                switch (_.flag = true, op[0]) {
+                    case 0 /*next*/: case 1 /*throw*/: sent = op; break;
+                    case 4 /*yield*/: return _.label++, { value: op[1], done: false };
+                    case 7 /*endfinally*/: op = _.stack.pop(), _.trys.pop(); continue;
+                    default:
+                        var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
+                        if (!r && (op[0] === 1 /*throw*/ || op[0] === 6 /*catch*/ || op[0] === 2 /*return*/)) {
+                            _.done = true;
+                            continue;
+                        }
+                        if (op[0] === 3 /*break*/ && (!r || (op[1] > r[0] && op[1] < r[3]))) {
+                            _.label = op[1];
+                        }
+                        else if (op[0] === 6 /*catch*/ && r && _.label < r[1]) {
+                            _.label = r[1], sent = op;
+                        }
+                        else if (r && _.label < r[2]) {
+                            _.label = r[2], _.stack.push(op);
+                        }
+                        else {
+                            if (r[2]) _.stack.pop();
+                            _.trys.pop();
+                            continue;
+                        }
+                }
+                op = body(_);
+            }
+            catch (e) { op = [6 /*catch*/, e]; }
+            finally { _.flag = false, sent = void 0; }
+        }
+    }
+    return {
+        next: function (v) { return step([0 /*next*/, v]); },
+        "throw": function (v) { return step([1 /*throw*/, v]); },
+        "return": function (v) { return step([2 /*return*/, v]); }
+    };
+};
+function empty() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            return [2 /*return*/];
+        });
+    });
+}
+function singleAwait() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunction.symbols b/tests/baselines/reference/es5-asyncFunction.symbols
new file mode 100644
index 0000000000000..9a79e235090ca
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunction.symbols
@@ -0,0 +1,14 @@
+=== tests/cases/compiler/es5-asyncFunction.ts ===
+declare var x;
+>x : Symbol(x, Decl(es5-asyncFunction.ts, 0, 11))
+
+async function empty() {
+>empty : Symbol(empty, Decl(es5-asyncFunction.ts, 0, 14))
+}
+
+async function singleAwait() {
+>singleAwait : Symbol(singleAwait, Decl(es5-asyncFunction.ts, 3, 1))
+
+    await x;
+>x : Symbol(x, Decl(es5-asyncFunction.ts, 0, 11))
+}
diff --git a/tests/baselines/reference/es5-asyncFunction.types b/tests/baselines/reference/es5-asyncFunction.types
new file mode 100644
index 0000000000000..71700db7c3095
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunction.types
@@ -0,0 +1,15 @@
+=== tests/cases/compiler/es5-asyncFunction.ts ===
+declare var x;
+>x : any
+
+async function empty() {
+>empty : () => Promise<void>
+}
+
+async function singleAwait() {
+>singleAwait : () => Promise<void>
+
+    await x;
+>await x : any
+>x : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionArrayLiterals.js b/tests/baselines/reference/es5-asyncFunctionArrayLiterals.js
new file mode 100644
index 0000000000000..936e530ee2bed
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionArrayLiterals.js
@@ -0,0 +1,150 @@
+//// [es5-asyncFunctionArrayLiterals.ts]
+declare var x, y, z, a;
+
+async function arrayLiteral0() {
+    x = [await y, z];
+}
+
+async function arrayLiteral1() {
+    x = [y, await z];
+}
+
+async function arrayLiteral2() {
+    x = [...(await y), z];
+}
+
+async function arrayLiteral3() {
+    x = [...y, await z];
+}
+
+async function arrayLiteral4() {
+    x = [await y, ...z];
+}
+
+async function arrayLiteral5() {
+    x = [y, ...(await z)];
+}
+
+async function arrayLiteral6() {
+    x = [y, await z, a];
+}
+
+async function arrayLiteral7() {
+    x = [await y, z, await a];
+}
+
+//// [es5-asyncFunctionArrayLiterals.js]
+function arrayLiteral0() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0: return [4 /*yield*/, y];
+                case 1:
+                    x = [_b.sent(), z];
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function arrayLiteral1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = [y];
+                    return [4 /*yield*/, z];
+                case 1:
+                    x = _a.concat([_b.sent()]);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function arrayLiteral2() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, y];
+                case 1:
+                    x = (_a.sent()).concat([z]);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function arrayLiteral3() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c, _d;
+        return __generator(function (_e) {
+            switch (_e.label) {
+                case 0:
+                    _b = (_a = y).concat;
+                    return [4 /*yield*/, z];
+                case 1:
+                    x = _b.apply(_a, [[_e.sent()]]);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function arrayLiteral4() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0: return [4 /*yield*/, y];
+                case 1:
+                    x = [_b.sent()].concat(z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function arrayLiteral5() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    _b = (_a = [y]).concat;
+                    return [4 /*yield*/, z];
+                case 1:
+                    x = _b.apply(_a, [(_d.sent())]);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function arrayLiteral6() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = [y];
+                    return [4 /*yield*/, z];
+                case 1:
+                    x = _a.concat([_b.sent(), a]);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function arrayLiteral7() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0: return [4 /*yield*/, y];
+                case 1:
+                    _a = [_b.sent(), z];
+                    return [4 /*yield*/, a];
+                case 2:
+                    x = _a.concat([_b.sent()]);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionArrayLiterals.symbols b/tests/baselines/reference/es5-asyncFunctionArrayLiterals.symbols
new file mode 100644
index 0000000000000..3bdfb070d1bab
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionArrayLiterals.symbols
@@ -0,0 +1,80 @@
+=== tests/cases/compiler/es5-asyncFunctionArrayLiterals.ts ===
+declare var x, y, z, a;
+>x : Symbol(x, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 20))
+
+async function arrayLiteral0() {
+>arrayLiteral0 : Symbol(arrayLiteral0, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 23))
+
+    x = [await y, z];
+>x : Symbol(x, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 17))
+}
+
+async function arrayLiteral1() {
+>arrayLiteral1 : Symbol(arrayLiteral1, Decl(es5-asyncFunctionArrayLiterals.ts, 4, 1))
+
+    x = [y, await z];
+>x : Symbol(x, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 17))
+}
+
+async function arrayLiteral2() {
+>arrayLiteral2 : Symbol(arrayLiteral2, Decl(es5-asyncFunctionArrayLiterals.ts, 8, 1))
+
+    x = [...(await y), z];
+>x : Symbol(x, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 17))
+}
+
+async function arrayLiteral3() {
+>arrayLiteral3 : Symbol(arrayLiteral3, Decl(es5-asyncFunctionArrayLiterals.ts, 12, 1))
+
+    x = [...y, await z];
+>x : Symbol(x, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 17))
+}
+
+async function arrayLiteral4() {
+>arrayLiteral4 : Symbol(arrayLiteral4, Decl(es5-asyncFunctionArrayLiterals.ts, 16, 1))
+
+    x = [await y, ...z];
+>x : Symbol(x, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 17))
+}
+
+async function arrayLiteral5() {
+>arrayLiteral5 : Symbol(arrayLiteral5, Decl(es5-asyncFunctionArrayLiterals.ts, 20, 1))
+
+    x = [y, ...(await z)];
+>x : Symbol(x, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 17))
+}
+
+async function arrayLiteral6() {
+>arrayLiteral6 : Symbol(arrayLiteral6, Decl(es5-asyncFunctionArrayLiterals.ts, 24, 1))
+
+    x = [y, await z, a];
+>x : Symbol(x, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 20))
+}
+
+async function arrayLiteral7() {
+>arrayLiteral7 : Symbol(arrayLiteral7, Decl(es5-asyncFunctionArrayLiterals.ts, 28, 1))
+
+    x = [await y, z, await a];
+>x : Symbol(x, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionArrayLiterals.ts, 0, 20))
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionArrayLiterals.types b/tests/baselines/reference/es5-asyncFunctionArrayLiterals.types
new file mode 100644
index 0000000000000..80b4e095c9dec
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionArrayLiterals.types
@@ -0,0 +1,111 @@
+=== tests/cases/compiler/es5-asyncFunctionArrayLiterals.ts ===
+declare var x, y, z, a;
+>x : any
+>y : any
+>z : any
+>a : any
+
+async function arrayLiteral0() {
+>arrayLiteral0 : () => Promise<void>
+
+    x = [await y, z];
+>x = [await y, z] : any[]
+>x : any
+>[await y, z] : any[]
+>await y : any
+>y : any
+>z : any
+}
+
+async function arrayLiteral1() {
+>arrayLiteral1 : () => Promise<void>
+
+    x = [y, await z];
+>x = [y, await z] : any[]
+>x : any
+>[y, await z] : any[]
+>y : any
+>await z : any
+>z : any
+}
+
+async function arrayLiteral2() {
+>arrayLiteral2 : () => Promise<void>
+
+    x = [...(await y), z];
+>x = [...(await y), z] : any[]
+>x : any
+>[...(await y), z] : any[]
+>...(await y) : any
+>(await y) : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function arrayLiteral3() {
+>arrayLiteral3 : () => Promise<void>
+
+    x = [...y, await z];
+>x = [...y, await z] : any[]
+>x : any
+>[...y, await z] : any[]
+>...y : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function arrayLiteral4() {
+>arrayLiteral4 : () => Promise<void>
+
+    x = [await y, ...z];
+>x = [await y, ...z] : any[]
+>x : any
+>[await y, ...z] : any[]
+>await y : any
+>y : any
+>...z : any
+>z : any
+}
+
+async function arrayLiteral5() {
+>arrayLiteral5 : () => Promise<void>
+
+    x = [y, ...(await z)];
+>x = [y, ...(await z)] : any[]
+>x : any
+>[y, ...(await z)] : any[]
+>y : any
+>...(await z) : any
+>(await z) : any
+>await z : any
+>z : any
+}
+
+async function arrayLiteral6() {
+>arrayLiteral6 : () => Promise<void>
+
+    x = [y, await z, a];
+>x = [y, await z, a] : any[]
+>x : any
+>[y, await z, a] : any[]
+>y : any
+>await z : any
+>z : any
+>a : any
+}
+
+async function arrayLiteral7() {
+>arrayLiteral7 : () => Promise<void>
+
+    x = [await y, z, await a];
+>x = [await y, z, await a] : any[]
+>x : any
+>[await y, z, await a] : any[]
+>await y : any
+>y : any
+>z : any
+>await a : any
+>a : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.js b/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.js
new file mode 100644
index 0000000000000..936ca033954f8
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.js
@@ -0,0 +1,561 @@
+//// [es5-asyncFunctionBinaryExpressions.ts]
+declare var x, y, z, a, b, c;
+
+async function binaryPlus0() {
+    (await x) + y;
+}
+
+async function binaryPlus1() {
+    x + await y;
+}
+
+async function binaryLogicalAnd0() {
+    (await x) && y;
+}
+
+async function binaryLogicalAnd1() {
+    x && await y;
+}
+
+async function binaryAssignment0() {
+    x = await y;
+}
+
+async function binaryAssignment1() {
+    x.a = await y;
+}
+
+async function binaryAssignment2() {
+    x.a.b = await y;
+}
+
+async function binaryAssignment3() {
+    x[z] = await y;
+}
+
+async function binaryAssignment4() {
+    x[z].b = await y;
+}
+
+async function binaryAssignment5() {
+    x.a[z] = await y;
+}
+
+async function binaryAssignment6() {
+    (await x).a = y;
+}
+
+async function binaryAssignment7() {
+    (await x.a).b = y;
+}
+
+async function binaryAssignment8() {
+    (await x)[z] = y;
+}
+
+async function binaryAssignment9() {
+    x[await z] = y;
+}
+
+async function binaryAssignment10() {
+    x[await z].b = y;
+}
+
+async function binaryAssignment11() {
+    (await x[z]).b = y;
+}
+
+async function binaryAssignment12() {
+    x.a[await z] = y;
+}
+
+async function binaryAssignment13() {
+    (await x.a)[z] = y;
+}
+
+async function binaryCompoundAssignment0() {
+    x += await y;
+}
+
+async function binaryCompoundAssignment1() {
+    x.a += await y;
+}
+
+async function binaryCompoundAssignment2() {
+    x[a] += await y;
+}
+
+async function binaryCompoundAssignment3() {
+    (await x).a += y;
+}
+
+async function binaryCompoundAssignment4() {
+    (await x)[a] += y;
+}
+
+async function binaryCompoundAssignment5() {
+    x[await a] += y;
+}
+
+async function binaryCompoundAssignment6() {
+    (await x).a += await y;
+}
+
+async function binaryCompoundAssignment7() {
+    (await x)[a] += await y;
+}
+
+async function binaryCompoundAssignment8() {
+    x[await a] += await y;
+}
+
+async function binaryExponentiation() {
+    (await x) ** y;
+    x ** await y;
+}
+
+async function binaryComma0() {
+    return (await x), y;
+}
+
+async function binaryComma1(): Promise<any> {
+    return x, await y;
+}
+
+//// [es5-asyncFunctionBinaryExpressions.js]
+function binaryPlus0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    (_a.sent()) + y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryPlus1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a + (_b.sent());
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryLogicalAnd0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    (_a.sent()) && y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryLogicalAnd1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    if (!_a)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a = (_b.sent());
+                    _b.label = 2;
+                case 2:
+                    _a;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, y];
+                case 1:
+                    x = _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.a = _b.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x.a;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.b = _b.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment3() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = x;
+                    _b = z;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a[_b] = _c.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment4() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x[z];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.b = _b.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment5() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = x.a;
+                    _b = z;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a[_b] = _c.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment6() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    (_a.sent()).a = y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment7() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x.a];
+                case 1:
+                    (_a.sent()).b = y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment8() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    (_a.sent())[z] = y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment9() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, z];
+                case 1:
+                    _a[_b.sent()] = y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment10() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, z];
+                case 1:
+                    _a[_b.sent()].b = y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment11() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x[z]];
+                case 1:
+                    (_a.sent()).b = y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment12() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x.a;
+                    return [4 /*yield*/, z];
+                case 1:
+                    _a[_b.sent()] = y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryAssignment13() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x.a];
+                case 1:
+                    (_a.sent())[z] = y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryCompoundAssignment0() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, y];
+                case 1:
+                    x = _a + _b.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryCompoundAssignment1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = x;
+                    _b = _a.a;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.a = _b + _c.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryCompoundAssignment2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    _a = x;
+                    _b = a;
+                    _c = _a[_b];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a[_b] = _c + _d.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryCompoundAssignment3() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    (_a.sent()).a += y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryCompoundAssignment4() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    (_a.sent())[a] += y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryCompoundAssignment5() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, a];
+                case 1:
+                    _a[_b.sent()] += y;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryCompoundAssignment6() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    _a = (_c.sent());
+                    _b = _a.a;
+                    return [4 /*yield*/, y];
+                case 2:
+                    _a.a = _b + _c.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryCompoundAssignment7() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    _a = (_d.sent());
+                    _b = a;
+                    _c = _a[_b];
+                    return [4 /*yield*/, y];
+                case 2:
+                    _a[_b] = _c + _d.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryCompoundAssignment8() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, a];
+                case 1:
+                    _b = _d.sent();
+                    _c = _a[_b];
+                    return [4 /*yield*/, y];
+                case 2:
+                    _a[_b] = _c + _d.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryExponentiation() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c, _d, _e, _f;
+        return __generator(function (_g) {
+            switch (_g.label) {
+                case 0:
+                    _b = (_a = Math).pow;
+                    return [4 /*yield*/, x];
+                case 1:
+                    _b.apply(_a, [(_g.sent()), y]);
+                    _e = (_d = Math).pow;
+                    _f = [x];
+                    return [4 /*yield*/, y];
+                case 2:
+                    _e.apply(_d, _f.concat([_g.sent()]));
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function binaryComma0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1: return [2 /*return*/, ((_a.sent()), y)];
+            }
+        });
+    });
+}
+function binaryComma1() {
+    return __awaiter(this, void 0, Promise, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    x;
+                    return [4 /*yield*/, y];
+                case 1: return [2 /*return*/, _a.sent()];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.symbols b/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.symbols
new file mode 100644
index 0000000000000..6c6a182071707
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.symbols
@@ -0,0 +1,267 @@
+=== tests/cases/compiler/es5-asyncFunctionBinaryExpressions.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 26))
+
+async function binaryPlus0() {
+>binaryPlus0 : Symbol(binaryPlus0, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 29))
+
+    (await x) + y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryPlus1() {
+>binaryPlus1 : Symbol(binaryPlus1, Decl(es5-asyncFunctionBinaryExpressions.ts, 4, 1))
+
+    x + await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryLogicalAnd0() {
+>binaryLogicalAnd0 : Symbol(binaryLogicalAnd0, Decl(es5-asyncFunctionBinaryExpressions.ts, 8, 1))
+
+    (await x) && y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryLogicalAnd1() {
+>binaryLogicalAnd1 : Symbol(binaryLogicalAnd1, Decl(es5-asyncFunctionBinaryExpressions.ts, 12, 1))
+
+    x && await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment0() {
+>binaryAssignment0 : Symbol(binaryAssignment0, Decl(es5-asyncFunctionBinaryExpressions.ts, 16, 1))
+
+    x = await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment1() {
+>binaryAssignment1 : Symbol(binaryAssignment1, Decl(es5-asyncFunctionBinaryExpressions.ts, 20, 1))
+
+    x.a = await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment2() {
+>binaryAssignment2 : Symbol(binaryAssignment2, Decl(es5-asyncFunctionBinaryExpressions.ts, 24, 1))
+
+    x.a.b = await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment3() {
+>binaryAssignment3 : Symbol(binaryAssignment3, Decl(es5-asyncFunctionBinaryExpressions.ts, 28, 1))
+
+    x[z] = await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>z : Symbol(z, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 17))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment4() {
+>binaryAssignment4 : Symbol(binaryAssignment4, Decl(es5-asyncFunctionBinaryExpressions.ts, 32, 1))
+
+    x[z].b = await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>z : Symbol(z, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 17))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment5() {
+>binaryAssignment5 : Symbol(binaryAssignment5, Decl(es5-asyncFunctionBinaryExpressions.ts, 36, 1))
+
+    x.a[z] = await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>z : Symbol(z, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 17))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment6() {
+>binaryAssignment6 : Symbol(binaryAssignment6, Decl(es5-asyncFunctionBinaryExpressions.ts, 40, 1))
+
+    (await x).a = y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment7() {
+>binaryAssignment7 : Symbol(binaryAssignment7, Decl(es5-asyncFunctionBinaryExpressions.ts, 44, 1))
+
+    (await x.a).b = y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment8() {
+>binaryAssignment8 : Symbol(binaryAssignment8, Decl(es5-asyncFunctionBinaryExpressions.ts, 48, 1))
+
+    (await x)[z] = y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>z : Symbol(z, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 17))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment9() {
+>binaryAssignment9 : Symbol(binaryAssignment9, Decl(es5-asyncFunctionBinaryExpressions.ts, 52, 1))
+
+    x[await z] = y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>z : Symbol(z, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 17))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment10() {
+>binaryAssignment10 : Symbol(binaryAssignment10, Decl(es5-asyncFunctionBinaryExpressions.ts, 56, 1))
+
+    x[await z].b = y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>z : Symbol(z, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 17))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment11() {
+>binaryAssignment11 : Symbol(binaryAssignment11, Decl(es5-asyncFunctionBinaryExpressions.ts, 60, 1))
+
+    (await x[z]).b = y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>z : Symbol(z, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 17))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment12() {
+>binaryAssignment12 : Symbol(binaryAssignment12, Decl(es5-asyncFunctionBinaryExpressions.ts, 64, 1))
+
+    x.a[await z] = y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>z : Symbol(z, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 17))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryAssignment13() {
+>binaryAssignment13 : Symbol(binaryAssignment13, Decl(es5-asyncFunctionBinaryExpressions.ts, 68, 1))
+
+    (await x.a)[z] = y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>z : Symbol(z, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 17))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryCompoundAssignment0() {
+>binaryCompoundAssignment0 : Symbol(binaryCompoundAssignment0, Decl(es5-asyncFunctionBinaryExpressions.ts, 72, 1))
+
+    x += await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryCompoundAssignment1() {
+>binaryCompoundAssignment1 : Symbol(binaryCompoundAssignment1, Decl(es5-asyncFunctionBinaryExpressions.ts, 76, 1))
+
+    x.a += await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryCompoundAssignment2() {
+>binaryCompoundAssignment2 : Symbol(binaryCompoundAssignment2, Decl(es5-asyncFunctionBinaryExpressions.ts, 80, 1))
+
+    x[a] += await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryCompoundAssignment3() {
+>binaryCompoundAssignment3 : Symbol(binaryCompoundAssignment3, Decl(es5-asyncFunctionBinaryExpressions.ts, 84, 1))
+
+    (await x).a += y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryCompoundAssignment4() {
+>binaryCompoundAssignment4 : Symbol(binaryCompoundAssignment4, Decl(es5-asyncFunctionBinaryExpressions.ts, 88, 1))
+
+    (await x)[a] += y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryCompoundAssignment5() {
+>binaryCompoundAssignment5 : Symbol(binaryCompoundAssignment5, Decl(es5-asyncFunctionBinaryExpressions.ts, 92, 1))
+
+    x[await a] += y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryCompoundAssignment6() {
+>binaryCompoundAssignment6 : Symbol(binaryCompoundAssignment6, Decl(es5-asyncFunctionBinaryExpressions.ts, 96, 1))
+
+    (await x).a += await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryCompoundAssignment7() {
+>binaryCompoundAssignment7 : Symbol(binaryCompoundAssignment7, Decl(es5-asyncFunctionBinaryExpressions.ts, 100, 1))
+
+    (await x)[a] += await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryCompoundAssignment8() {
+>binaryCompoundAssignment8 : Symbol(binaryCompoundAssignment8, Decl(es5-asyncFunctionBinaryExpressions.ts, 104, 1))
+
+    x[await a] += await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryExponentiation() {
+>binaryExponentiation : Symbol(binaryExponentiation, Decl(es5-asyncFunctionBinaryExpressions.ts, 108, 1))
+
+    (await x) ** y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+
+    x ** await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryComma0() {
+>binaryComma0 : Symbol(binaryComma0, Decl(es5-asyncFunctionBinaryExpressions.ts, 113, 1))
+
+    return (await x), y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
+
+async function binaryComma1(): Promise<any> {
+>binaryComma1 : Symbol(binaryComma1, Decl(es5-asyncFunctionBinaryExpressions.ts, 117, 1))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    return x, await y;
+>x : Symbol(x, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionBinaryExpressions.ts, 0, 14))
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.types b/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.types
new file mode 100644
index 0000000000000..54afaee22c58a
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.types
@@ -0,0 +1,389 @@
+=== tests/cases/compiler/es5-asyncFunctionBinaryExpressions.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function binaryPlus0() {
+>binaryPlus0 : () => Promise<void>
+
+    (await x) + y;
+>(await x) + y : any
+>(await x) : any
+>await x : any
+>x : any
+>y : any
+}
+
+async function binaryPlus1() {
+>binaryPlus1 : () => Promise<void>
+
+    x + await y;
+>x + await y : any
+>x : any
+>await y : any
+>y : any
+}
+
+async function binaryLogicalAnd0() {
+>binaryLogicalAnd0 : () => Promise<void>
+
+    (await x) && y;
+>(await x) && y : any
+>(await x) : any
+>await x : any
+>x : any
+>y : any
+}
+
+async function binaryLogicalAnd1() {
+>binaryLogicalAnd1 : () => Promise<void>
+
+    x && await y;
+>x && await y : any
+>x : any
+>await y : any
+>y : any
+}
+
+async function binaryAssignment0() {
+>binaryAssignment0 : () => Promise<void>
+
+    x = await y;
+>x = await y : any
+>x : any
+>await y : any
+>y : any
+}
+
+async function binaryAssignment1() {
+>binaryAssignment1 : () => Promise<void>
+
+    x.a = await y;
+>x.a = await y : any
+>x.a : any
+>x : any
+>a : any
+>await y : any
+>y : any
+}
+
+async function binaryAssignment2() {
+>binaryAssignment2 : () => Promise<void>
+
+    x.a.b = await y;
+>x.a.b = await y : any
+>x.a.b : any
+>x.a : any
+>x : any
+>a : any
+>b : any
+>await y : any
+>y : any
+}
+
+async function binaryAssignment3() {
+>binaryAssignment3 : () => Promise<void>
+
+    x[z] = await y;
+>x[z] = await y : any
+>x[z] : any
+>x : any
+>z : any
+>await y : any
+>y : any
+}
+
+async function binaryAssignment4() {
+>binaryAssignment4 : () => Promise<void>
+
+    x[z].b = await y;
+>x[z].b = await y : any
+>x[z].b : any
+>x[z] : any
+>x : any
+>z : any
+>b : any
+>await y : any
+>y : any
+}
+
+async function binaryAssignment5() {
+>binaryAssignment5 : () => Promise<void>
+
+    x.a[z] = await y;
+>x.a[z] = await y : any
+>x.a[z] : any
+>x.a : any
+>x : any
+>a : any
+>z : any
+>await y : any
+>y : any
+}
+
+async function binaryAssignment6() {
+>binaryAssignment6 : () => Promise<void>
+
+    (await x).a = y;
+>(await x).a = y : any
+>(await x).a : any
+>(await x) : any
+>await x : any
+>x : any
+>a : any
+>y : any
+}
+
+async function binaryAssignment7() {
+>binaryAssignment7 : () => Promise<void>
+
+    (await x.a).b = y;
+>(await x.a).b = y : any
+>(await x.a).b : any
+>(await x.a) : any
+>await x.a : any
+>x.a : any
+>x : any
+>a : any
+>b : any
+>y : any
+}
+
+async function binaryAssignment8() {
+>binaryAssignment8 : () => Promise<void>
+
+    (await x)[z] = y;
+>(await x)[z] = y : any
+>(await x)[z] : any
+>(await x) : any
+>await x : any
+>x : any
+>z : any
+>y : any
+}
+
+async function binaryAssignment9() {
+>binaryAssignment9 : () => Promise<void>
+
+    x[await z] = y;
+>x[await z] = y : any
+>x[await z] : any
+>x : any
+>await z : any
+>z : any
+>y : any
+}
+
+async function binaryAssignment10() {
+>binaryAssignment10 : () => Promise<void>
+
+    x[await z].b = y;
+>x[await z].b = y : any
+>x[await z].b : any
+>x[await z] : any
+>x : any
+>await z : any
+>z : any
+>b : any
+>y : any
+}
+
+async function binaryAssignment11() {
+>binaryAssignment11 : () => Promise<void>
+
+    (await x[z]).b = y;
+>(await x[z]).b = y : any
+>(await x[z]).b : any
+>(await x[z]) : any
+>await x[z] : any
+>x[z] : any
+>x : any
+>z : any
+>b : any
+>y : any
+}
+
+async function binaryAssignment12() {
+>binaryAssignment12 : () => Promise<void>
+
+    x.a[await z] = y;
+>x.a[await z] = y : any
+>x.a[await z] : any
+>x.a : any
+>x : any
+>a : any
+>await z : any
+>z : any
+>y : any
+}
+
+async function binaryAssignment13() {
+>binaryAssignment13 : () => Promise<void>
+
+    (await x.a)[z] = y;
+>(await x.a)[z] = y : any
+>(await x.a)[z] : any
+>(await x.a) : any
+>await x.a : any
+>x.a : any
+>x : any
+>a : any
+>z : any
+>y : any
+}
+
+async function binaryCompoundAssignment0() {
+>binaryCompoundAssignment0 : () => Promise<void>
+
+    x += await y;
+>x += await y : any
+>x : any
+>await y : any
+>y : any
+}
+
+async function binaryCompoundAssignment1() {
+>binaryCompoundAssignment1 : () => Promise<void>
+
+    x.a += await y;
+>x.a += await y : any
+>x.a : any
+>x : any
+>a : any
+>await y : any
+>y : any
+}
+
+async function binaryCompoundAssignment2() {
+>binaryCompoundAssignment2 : () => Promise<void>
+
+    x[a] += await y;
+>x[a] += await y : any
+>x[a] : any
+>x : any
+>a : any
+>await y : any
+>y : any
+}
+
+async function binaryCompoundAssignment3() {
+>binaryCompoundAssignment3 : () => Promise<void>
+
+    (await x).a += y;
+>(await x).a += y : any
+>(await x).a : any
+>(await x) : any
+>await x : any
+>x : any
+>a : any
+>y : any
+}
+
+async function binaryCompoundAssignment4() {
+>binaryCompoundAssignment4 : () => Promise<void>
+
+    (await x)[a] += y;
+>(await x)[a] += y : any
+>(await x)[a] : any
+>(await x) : any
+>await x : any
+>x : any
+>a : any
+>y : any
+}
+
+async function binaryCompoundAssignment5() {
+>binaryCompoundAssignment5 : () => Promise<void>
+
+    x[await a] += y;
+>x[await a] += y : any
+>x[await a] : any
+>x : any
+>await a : any
+>a : any
+>y : any
+}
+
+async function binaryCompoundAssignment6() {
+>binaryCompoundAssignment6 : () => Promise<void>
+
+    (await x).a += await y;
+>(await x).a += await y : any
+>(await x).a : any
+>(await x) : any
+>await x : any
+>x : any
+>a : any
+>await y : any
+>y : any
+}
+
+async function binaryCompoundAssignment7() {
+>binaryCompoundAssignment7 : () => Promise<void>
+
+    (await x)[a] += await y;
+>(await x)[a] += await y : any
+>(await x)[a] : any
+>(await x) : any
+>await x : any
+>x : any
+>a : any
+>await y : any
+>y : any
+}
+
+async function binaryCompoundAssignment8() {
+>binaryCompoundAssignment8 : () => Promise<void>
+
+    x[await a] += await y;
+>x[await a] += await y : any
+>x[await a] : any
+>x : any
+>await a : any
+>a : any
+>await y : any
+>y : any
+}
+
+async function binaryExponentiation() {
+>binaryExponentiation : () => Promise<void>
+
+    (await x) ** y;
+>(await x) ** y : number
+>(await x) : any
+>await x : any
+>x : any
+>y : any
+
+    x ** await y;
+>x ** await y : number
+>x : any
+>await y : any
+>y : any
+}
+
+async function binaryComma0() {
+>binaryComma0 : () => Promise<any>
+
+    return (await x), y;
+>(await x), y : any
+>(await x) : any
+>await x : any
+>x : any
+>y : any
+}
+
+async function binaryComma1(): Promise<any> {
+>binaryComma1 : () => Promise<any>
+>Promise : Promise<T>
+
+    return x, await y;
+>x, await y : any
+>x : any
+>await y : any
+>y : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionCallExpressions.js b/tests/baselines/reference/es5-asyncFunctionCallExpressions.js
new file mode 100644
index 0000000000000..8f0d17e7c14c5
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionCallExpressions.js
@@ -0,0 +1,383 @@
+//// [es5-asyncFunctionCallExpressions.ts]
+declare var x, y, z, a, b, c;
+
+async function callExpression0() {
+    await x(y, z);
+}
+
+async function callExpression1() {
+    (await x)(y, z);
+}
+
+async function callExpression2() {
+    x(await y, z);
+}
+
+async function callExpression3() {
+    x(y, await z);
+}
+
+async function callExpression4() {
+    await x(...y, z);
+}
+
+async function callExpression5() {
+    (await x)(...y, z);
+}
+
+async function callExpression6() {
+    x(...(await y), z);
+}
+
+async function callExpression7() {
+    x(...y, await z);
+}
+
+async function callExpression8() {
+    x(await y, ...z);
+}
+
+async function callExpression9() {
+    x(y, ...(await z));
+}
+
+async function callExpression10() {
+    await x.a(y, z);
+}
+
+async function callExpression11() {
+    (await x.a)(y, z);
+}
+
+async function callExpression12() {
+    (await x).a(y, z);
+}
+
+async function callExpression13() {
+    x.a(await y, z);
+}
+
+async function callExpression14() {
+    x.a(y, await z);
+}
+
+async function callExpression15() {
+    await x[a](y, z);
+}
+
+async function callExpression16() {
+    (await x[a])(y, z);
+}
+
+async function callExpression17() {
+    (await x)[a](y, z);
+}
+
+async function callExpression18() {
+    x[await a](y, z);
+}
+
+async function callExpression19() {
+    x[a](await y, z);
+}
+
+async function callExpression20() {
+    x[a](y, await z);
+}
+
+
+//// [es5-asyncFunctionCallExpressions.js]
+function callExpression0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x(y, z)];
+                case 1:
+                    _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression1() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    (_a.sent())(y, z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.apply(void 0, [_c.sent(), z]);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression3() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = x;
+                    _b = [y];
+                    return [4 /*yield*/, z];
+                case 1:
+                    _a.apply(void 0, _b.concat([_c.sent()]));
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression4() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x.apply(void 0, y.concat([z]))];
+                case 1:
+                    _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression5() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    (_a.sent()).apply(void 0, y.concat([z]));
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression6() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    _b = (_a = x).apply;
+                    _c = [void 0];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _b.apply(_a, _c.concat([(_d.sent()).concat([z])]));
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression7() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c, _d, _e, _f, _g;
+        return __generator(function (_h) {
+            switch (_h.label) {
+                case 0:
+                    _b = (_a = x).apply;
+                    _c = [void 0];
+                    _e = (_d = y).concat;
+                    return [4 /*yield*/, z];
+                case 1:
+                    _b.apply(_a, _c.concat([_e.apply(_d, [[_h.sent()]])]));
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression8() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c, _d;
+        return __generator(function (_e) {
+            switch (_e.label) {
+                case 0:
+                    _b = (_a = x).apply;
+                    _c = [void 0];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _b.apply(_a, _c.concat([[_e.sent()].concat(z)]));
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression9() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c, _d, _e, _f;
+        return __generator(function (_g) {
+            switch (_g.label) {
+                case 0:
+                    _b = (_a = x).apply;
+                    _c = [void 0];
+                    _e = (_d = [y]).concat;
+                    return [4 /*yield*/, z];
+                case 1:
+                    _b.apply(_a, _c.concat([_e.apply(_d, [(_g.sent())])]));
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression10() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x.a(y, z)];
+                case 1:
+                    _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression11() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x.a];
+                case 1:
+                    (_a.sent())(y, z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression12() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    (_a.sent()).a(y, z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression13() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    _b = (_a = x).a;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _b.apply(_a, [_d.sent(), z]);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression14() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    _b = (_a = x).a;
+                    _c = [y];
+                    return [4 /*yield*/, z];
+                case 1:
+                    _b.apply(_a, _c.concat([_d.sent()]));
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression15() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x[a](y, z)];
+                case 1:
+                    _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression16() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x[a]];
+                case 1:
+                    (_a.sent())(y, z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression17() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    (_a.sent())[a](y, z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression18() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, a];
+                case 1:
+                    _a[_b.sent()](y, z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression19() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    _b = (_a = x)[a];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _b.apply(_a, [_d.sent(), z]);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression20() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    _b = (_a = x)[a];
+                    _c = [y];
+                    return [4 /*yield*/, z];
+                case 1:
+                    _b.apply(_a, _c.concat([_d.sent()]));
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionCallExpressions.symbols b/tests/baselines/reference/es5-asyncFunctionCallExpressions.symbols
new file mode 100644
index 0000000000000..4a73045b5f389
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionCallExpressions.symbols
@@ -0,0 +1,204 @@
+=== tests/cases/compiler/es5-asyncFunctionCallExpressions.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionCallExpressions.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionCallExpressions.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionCallExpressions.ts, 0, 26))
+
+async function callExpression0() {
+>callExpression0 : Symbol(callExpression0, Decl(es5-asyncFunctionCallExpressions.ts, 0, 29))
+
+    await x(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression1() {
+>callExpression1 : Symbol(callExpression1, Decl(es5-asyncFunctionCallExpressions.ts, 4, 1))
+
+    (await x)(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression2() {
+>callExpression2 : Symbol(callExpression2, Decl(es5-asyncFunctionCallExpressions.ts, 8, 1))
+
+    x(await y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression3() {
+>callExpression3 : Symbol(callExpression3, Decl(es5-asyncFunctionCallExpressions.ts, 12, 1))
+
+    x(y, await z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression4() {
+>callExpression4 : Symbol(callExpression4, Decl(es5-asyncFunctionCallExpressions.ts, 16, 1))
+
+    await x(...y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression5() {
+>callExpression5 : Symbol(callExpression5, Decl(es5-asyncFunctionCallExpressions.ts, 20, 1))
+
+    (await x)(...y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression6() {
+>callExpression6 : Symbol(callExpression6, Decl(es5-asyncFunctionCallExpressions.ts, 24, 1))
+
+    x(...(await y), z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression7() {
+>callExpression7 : Symbol(callExpression7, Decl(es5-asyncFunctionCallExpressions.ts, 28, 1))
+
+    x(...y, await z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression8() {
+>callExpression8 : Symbol(callExpression8, Decl(es5-asyncFunctionCallExpressions.ts, 32, 1))
+
+    x(await y, ...z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression9() {
+>callExpression9 : Symbol(callExpression9, Decl(es5-asyncFunctionCallExpressions.ts, 36, 1))
+
+    x(y, ...(await z));
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression10() {
+>callExpression10 : Symbol(callExpression10, Decl(es5-asyncFunctionCallExpressions.ts, 40, 1))
+
+    await x.a(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression11() {
+>callExpression11 : Symbol(callExpression11, Decl(es5-asyncFunctionCallExpressions.ts, 44, 1))
+
+    (await x.a)(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression12() {
+>callExpression12 : Symbol(callExpression12, Decl(es5-asyncFunctionCallExpressions.ts, 48, 1))
+
+    (await x).a(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression13() {
+>callExpression13 : Symbol(callExpression13, Decl(es5-asyncFunctionCallExpressions.ts, 52, 1))
+
+    x.a(await y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression14() {
+>callExpression14 : Symbol(callExpression14, Decl(es5-asyncFunctionCallExpressions.ts, 56, 1))
+
+    x.a(y, await z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression15() {
+>callExpression15 : Symbol(callExpression15, Decl(es5-asyncFunctionCallExpressions.ts, 60, 1))
+
+    await x[a](y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionCallExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression16() {
+>callExpression16 : Symbol(callExpression16, Decl(es5-asyncFunctionCallExpressions.ts, 64, 1))
+
+    (await x[a])(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionCallExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression17() {
+>callExpression17 : Symbol(callExpression17, Decl(es5-asyncFunctionCallExpressions.ts, 68, 1))
+
+    (await x)[a](y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionCallExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression18() {
+>callExpression18 : Symbol(callExpression18, Decl(es5-asyncFunctionCallExpressions.ts, 72, 1))
+
+    x[await a](y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionCallExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression19() {
+>callExpression19 : Symbol(callExpression19, Decl(es5-asyncFunctionCallExpressions.ts, 76, 1))
+
+    x[a](await y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionCallExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
+async function callExpression20() {
+>callExpression20 : Symbol(callExpression20, Decl(es5-asyncFunctionCallExpressions.ts, 80, 1))
+
+    x[a](y, await z);
+>x : Symbol(x, Decl(es5-asyncFunctionCallExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionCallExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionCallExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionCallExpressions.ts, 0, 17))
+}
+
diff --git a/tests/baselines/reference/es5-asyncFunctionCallExpressions.types b/tests/baselines/reference/es5-asyncFunctionCallExpressions.types
new file mode 100644
index 0000000000000..82207b218d279
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionCallExpressions.types
@@ -0,0 +1,276 @@
+=== tests/cases/compiler/es5-asyncFunctionCallExpressions.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function callExpression0() {
+>callExpression0 : () => Promise<void>
+
+    await x(y, z);
+>await x(y, z) : any
+>x(y, z) : any
+>x : any
+>y : any
+>z : any
+}
+
+async function callExpression1() {
+>callExpression1 : () => Promise<void>
+
+    (await x)(y, z);
+>(await x)(y, z) : any
+>(await x) : any
+>await x : any
+>x : any
+>y : any
+>z : any
+}
+
+async function callExpression2() {
+>callExpression2 : () => Promise<void>
+
+    x(await y, z);
+>x(await y, z) : any
+>x : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function callExpression3() {
+>callExpression3 : () => Promise<void>
+
+    x(y, await z);
+>x(y, await z) : any
+>x : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function callExpression4() {
+>callExpression4 : () => Promise<void>
+
+    await x(...y, z);
+>await x(...y, z) : any
+>x(...y, z) : any
+>x : any
+>...y : any
+>y : any
+>z : any
+}
+
+async function callExpression5() {
+>callExpression5 : () => Promise<void>
+
+    (await x)(...y, z);
+>(await x)(...y, z) : any
+>(await x) : any
+>await x : any
+>x : any
+>...y : any
+>y : any
+>z : any
+}
+
+async function callExpression6() {
+>callExpression6 : () => Promise<void>
+
+    x(...(await y), z);
+>x(...(await y), z) : any
+>x : any
+>...(await y) : any
+>(await y) : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function callExpression7() {
+>callExpression7 : () => Promise<void>
+
+    x(...y, await z);
+>x(...y, await z) : any
+>x : any
+>...y : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function callExpression8() {
+>callExpression8 : () => Promise<void>
+
+    x(await y, ...z);
+>x(await y, ...z) : any
+>x : any
+>await y : any
+>y : any
+>...z : any
+>z : any
+}
+
+async function callExpression9() {
+>callExpression9 : () => Promise<void>
+
+    x(y, ...(await z));
+>x(y, ...(await z)) : any
+>x : any
+>y : any
+>...(await z) : any
+>(await z) : any
+>await z : any
+>z : any
+}
+
+async function callExpression10() {
+>callExpression10 : () => Promise<void>
+
+    await x.a(y, z);
+>await x.a(y, z) : any
+>x.a(y, z) : any
+>x.a : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function callExpression11() {
+>callExpression11 : () => Promise<void>
+
+    (await x.a)(y, z);
+>(await x.a)(y, z) : any
+>(await x.a) : any
+>await x.a : any
+>x.a : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function callExpression12() {
+>callExpression12 : () => Promise<void>
+
+    (await x).a(y, z);
+>(await x).a(y, z) : any
+>(await x).a : any
+>(await x) : any
+>await x : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function callExpression13() {
+>callExpression13 : () => Promise<void>
+
+    x.a(await y, z);
+>x.a(await y, z) : any
+>x.a : any
+>x : any
+>a : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function callExpression14() {
+>callExpression14 : () => Promise<void>
+
+    x.a(y, await z);
+>x.a(y, await z) : any
+>x.a : any
+>x : any
+>a : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function callExpression15() {
+>callExpression15 : () => Promise<void>
+
+    await x[a](y, z);
+>await x[a](y, z) : any
+>x[a](y, z) : any
+>x[a] : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function callExpression16() {
+>callExpression16 : () => Promise<void>
+
+    (await x[a])(y, z);
+>(await x[a])(y, z) : any
+>(await x[a]) : any
+>await x[a] : any
+>x[a] : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function callExpression17() {
+>callExpression17 : () => Promise<void>
+
+    (await x)[a](y, z);
+>(await x)[a](y, z) : any
+>(await x)[a] : any
+>(await x) : any
+>await x : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function callExpression18() {
+>callExpression18 : () => Promise<void>
+
+    x[await a](y, z);
+>x[await a](y, z) : any
+>x[await a] : any
+>x : any
+>await a : any
+>a : any
+>y : any
+>z : any
+}
+
+async function callExpression19() {
+>callExpression19 : () => Promise<void>
+
+    x[a](await y, z);
+>x[a](await y, z) : any
+>x[a] : any
+>x : any
+>a : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function callExpression20() {
+>callExpression20 : () => Promise<void>
+
+    x[a](y, await z);
+>x[a](y, await z) : any
+>x[a] : any
+>x : any
+>a : any
+>y : any
+>await z : any
+>z : any
+}
+
diff --git a/tests/baselines/reference/es5-asyncFunctionConditionals.js b/tests/baselines/reference/es5-asyncFunctionConditionals.js
new file mode 100644
index 0000000000000..f559e1f962d82
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionConditionals.js
@@ -0,0 +1,71 @@
+//// [es5-asyncFunctionConditionals.ts]
+declare var x, y, z, a, b, c;
+
+async function conditional0() {
+    a = (await x) ? y : z;
+}
+
+async function conditional1() {
+    a = x ? await y : z;
+}
+
+async function conditional2() {
+    a = x ? y : await z;
+}
+
+//// [es5-asyncFunctionConditionals.js]
+function conditional0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    a = (_a.sent()) ? y : z;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function conditional1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a = _b.sent();
+                    return [3 /*break*/, 3];
+                case 2:
+                    _a = z;
+                    _b.label = 3;
+                case 3:
+                    a = _a;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function conditional2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 1];
+                    _a = y;
+                    return [3 /*break*/, 3];
+                case 1: return [4 /*yield*/, z];
+                case 2:
+                    _a = _b.sent();
+                    _b.label = 3;
+                case 3:
+                    a = _a;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionConditionals.symbols b/tests/baselines/reference/es5-asyncFunctionConditionals.symbols
new file mode 100644
index 0000000000000..8efa16840f25e
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionConditionals.symbols
@@ -0,0 +1,38 @@
+=== tests/cases/compiler/es5-asyncFunctionConditionals.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionConditionals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionConditionals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionConditionals.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionConditionals.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionConditionals.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionConditionals.ts, 0, 26))
+
+async function conditional0() {
+>conditional0 : Symbol(conditional0, Decl(es5-asyncFunctionConditionals.ts, 0, 29))
+
+    a = (await x) ? y : z;
+>a : Symbol(a, Decl(es5-asyncFunctionConditionals.ts, 0, 20))
+>x : Symbol(x, Decl(es5-asyncFunctionConditionals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionConditionals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionConditionals.ts, 0, 17))
+}
+
+async function conditional1() {
+>conditional1 : Symbol(conditional1, Decl(es5-asyncFunctionConditionals.ts, 4, 1))
+
+    a = x ? await y : z;
+>a : Symbol(a, Decl(es5-asyncFunctionConditionals.ts, 0, 20))
+>x : Symbol(x, Decl(es5-asyncFunctionConditionals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionConditionals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionConditionals.ts, 0, 17))
+}
+
+async function conditional2() {
+>conditional2 : Symbol(conditional2, Decl(es5-asyncFunctionConditionals.ts, 8, 1))
+
+    a = x ? y : await z;
+>a : Symbol(a, Decl(es5-asyncFunctionConditionals.ts, 0, 20))
+>x : Symbol(x, Decl(es5-asyncFunctionConditionals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionConditionals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionConditionals.ts, 0, 17))
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionConditionals.types b/tests/baselines/reference/es5-asyncFunctionConditionals.types
new file mode 100644
index 0000000000000..21f13585e891d
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionConditionals.types
@@ -0,0 +1,48 @@
+=== tests/cases/compiler/es5-asyncFunctionConditionals.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function conditional0() {
+>conditional0 : () => Promise<void>
+
+    a = (await x) ? y : z;
+>a = (await x) ? y : z : any
+>a : any
+>(await x) ? y : z : any
+>(await x) : any
+>await x : any
+>x : any
+>y : any
+>z : any
+}
+
+async function conditional1() {
+>conditional1 : () => Promise<void>
+
+    a = x ? await y : z;
+>a = x ? await y : z : any
+>a : any
+>x ? await y : z : any
+>x : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function conditional2() {
+>conditional2 : () => Promise<void>
+
+    a = x ? y : await z;
+>a = x ? y : await z : any
+>a : any
+>x ? y : await z : any
+>x : any
+>y : any
+>await z : any
+>z : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionDoStatements.js b/tests/baselines/reference/es5-asyncFunctionDoStatements.js
new file mode 100644
index 0000000000000..f2052ab378d69
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionDoStatements.js
@@ -0,0 +1,372 @@
+//// [es5-asyncFunctionDoStatements.ts]
+declare var x, y, z, a, b, c;
+
+async function doStatement0() {
+    do { x; } while (y);
+}
+
+async function doStatement1() {
+    do { await x; } while (y);
+}
+
+async function doStatement2() {
+    do { x; } while (await y);
+}
+
+async function doStatement3() {
+    do { continue; } while (y);
+}
+
+async function doStatement4() {
+    do { await x; continue; } while (y);
+}
+
+async function doStatement5() {
+    do { if (1) continue; await x; } while (y);
+}
+
+async function doStatement6() {
+    do { continue; } while (await y);
+}
+
+async function doStatement7() {
+    A: do { continue A; } while (y);
+}
+
+async function doStatement8() {
+    B: do { await x; continue B; } while (y);
+}
+
+async function doStatement9() {
+    C: do { if (1) continue C; await x; } while (y);
+}
+
+async function doStatement10() {
+    D: do { continue D; } while (await y);
+}
+
+async function doStatement11() {
+    do { break; } while (y);
+}
+
+async function doStatement12() {
+    do { await x; break; } while (y);
+}
+
+async function doStatement13() {
+    do { if (1) break; await x; } while (y);
+}
+
+async function doStatement14() {
+    do { break; } while (await y);
+}
+
+async function doStatement15() {
+    E: do { break E; } while (y);
+}
+
+async function doStatement16() {
+    F: do { await x; break F; } while (y);
+}
+
+async function doStatement17() {
+    G: do { if (1) break G; await x; } while (y);
+}
+
+async function doStatement18() {
+    H: do { break H; } while (await y);
+}
+
+//// [es5-asyncFunctionDoStatements.js]
+function doStatement0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            do {
+                x;
+            } while (y);
+            return [2 /*return*/];
+        });
+    });
+}
+function doStatement1() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    _a.label = 2;
+                case 2:
+                    if (y)
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement2() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    x;
+                    _a.label = 1;
+                case 1: return [4 /*yield*/, y];
+                case 2:
+                    if (_a.sent())
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement3() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            do {
+                continue;
+            } while (y);
+            return [2 /*return*/];
+        });
+    });
+}
+function doStatement4() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 2];
+                case 2:
+                    if (y)
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement5() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (1)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    _a.label = 2;
+                case 2:
+                    if (y)
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement6() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [3 /*break*/, 1];
+                case 1: return [4 /*yield*/, y];
+                case 2:
+                    if (_a.sent())
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement7() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            A: do {
+                continue A;
+            } while (y);
+            return [2 /*return*/];
+        });
+    });
+}
+function doStatement8() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 2];
+                case 2:
+                    if (y)
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement9() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (1)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    _a.label = 2;
+                case 2:
+                    if (y)
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement10() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [3 /*break*/, 1];
+                case 1: return [4 /*yield*/, y];
+                case 2:
+                    if (_a.sent())
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement11() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            do {
+                break;
+            } while (y);
+            return [2 /*return*/];
+        });
+    });
+}
+function doStatement12() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 3];
+                case 2:
+                    if (y)
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement13() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (1)
+                        return [3 /*break*/, 3];
+                    return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    _a.label = 2;
+                case 2:
+                    if (y)
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement14() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [3 /*break*/, 3];
+                case 1: return [4 /*yield*/, y];
+                case 2:
+                    if (_a.sent())
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement15() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            E: do {
+                break E;
+            } while (y);
+            return [2 /*return*/];
+        });
+    });
+}
+function doStatement16() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 3];
+                case 2:
+                    if (y)
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement17() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (1)
+                        return [3 /*break*/, 3];
+                    return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    _a.label = 2;
+                case 2:
+                    if (y)
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function doStatement18() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [3 /*break*/, 3];
+                case 1: return [4 /*yield*/, y];
+                case 2:
+                    if (_a.sent())
+                        return [3 /*break*/, 0];
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionDoStatements.symbols b/tests/baselines/reference/es5-asyncFunctionDoStatements.symbols
new file mode 100644
index 0000000000000..4f234828e63b9
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionDoStatements.symbols
@@ -0,0 +1,152 @@
+=== tests/cases/compiler/es5-asyncFunctionDoStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionDoStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionDoStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionDoStatements.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionDoStatements.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionDoStatements.ts, 0, 26))
+
+async function doStatement0() {
+>doStatement0 : Symbol(doStatement0, Decl(es5-asyncFunctionDoStatements.ts, 0, 29))
+
+    do { x; } while (y);
+>x : Symbol(x, Decl(es5-asyncFunctionDoStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement1() {
+>doStatement1 : Symbol(doStatement1, Decl(es5-asyncFunctionDoStatements.ts, 4, 1))
+
+    do { await x; } while (y);
+>x : Symbol(x, Decl(es5-asyncFunctionDoStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement2() {
+>doStatement2 : Symbol(doStatement2, Decl(es5-asyncFunctionDoStatements.ts, 8, 1))
+
+    do { x; } while (await y);
+>x : Symbol(x, Decl(es5-asyncFunctionDoStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement3() {
+>doStatement3 : Symbol(doStatement3, Decl(es5-asyncFunctionDoStatements.ts, 12, 1))
+
+    do { continue; } while (y);
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement4() {
+>doStatement4 : Symbol(doStatement4, Decl(es5-asyncFunctionDoStatements.ts, 16, 1))
+
+    do { await x; continue; } while (y);
+>x : Symbol(x, Decl(es5-asyncFunctionDoStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement5() {
+>doStatement5 : Symbol(doStatement5, Decl(es5-asyncFunctionDoStatements.ts, 20, 1))
+
+    do { if (1) continue; await x; } while (y);
+>x : Symbol(x, Decl(es5-asyncFunctionDoStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement6() {
+>doStatement6 : Symbol(doStatement6, Decl(es5-asyncFunctionDoStatements.ts, 24, 1))
+
+    do { continue; } while (await y);
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement7() {
+>doStatement7 : Symbol(doStatement7, Decl(es5-asyncFunctionDoStatements.ts, 28, 1))
+
+    A: do { continue A; } while (y);
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement8() {
+>doStatement8 : Symbol(doStatement8, Decl(es5-asyncFunctionDoStatements.ts, 32, 1))
+
+    B: do { await x; continue B; } while (y);
+>x : Symbol(x, Decl(es5-asyncFunctionDoStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement9() {
+>doStatement9 : Symbol(doStatement9, Decl(es5-asyncFunctionDoStatements.ts, 36, 1))
+
+    C: do { if (1) continue C; await x; } while (y);
+>x : Symbol(x, Decl(es5-asyncFunctionDoStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement10() {
+>doStatement10 : Symbol(doStatement10, Decl(es5-asyncFunctionDoStatements.ts, 40, 1))
+
+    D: do { continue D; } while (await y);
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement11() {
+>doStatement11 : Symbol(doStatement11, Decl(es5-asyncFunctionDoStatements.ts, 44, 1))
+
+    do { break; } while (y);
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement12() {
+>doStatement12 : Symbol(doStatement12, Decl(es5-asyncFunctionDoStatements.ts, 48, 1))
+
+    do { await x; break; } while (y);
+>x : Symbol(x, Decl(es5-asyncFunctionDoStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement13() {
+>doStatement13 : Symbol(doStatement13, Decl(es5-asyncFunctionDoStatements.ts, 52, 1))
+
+    do { if (1) break; await x; } while (y);
+>x : Symbol(x, Decl(es5-asyncFunctionDoStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement14() {
+>doStatement14 : Symbol(doStatement14, Decl(es5-asyncFunctionDoStatements.ts, 56, 1))
+
+    do { break; } while (await y);
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement15() {
+>doStatement15 : Symbol(doStatement15, Decl(es5-asyncFunctionDoStatements.ts, 60, 1))
+
+    E: do { break E; } while (y);
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement16() {
+>doStatement16 : Symbol(doStatement16, Decl(es5-asyncFunctionDoStatements.ts, 64, 1))
+
+    F: do { await x; break F; } while (y);
+>x : Symbol(x, Decl(es5-asyncFunctionDoStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement17() {
+>doStatement17 : Symbol(doStatement17, Decl(es5-asyncFunctionDoStatements.ts, 68, 1))
+
+    G: do { if (1) break G; await x; } while (y);
+>x : Symbol(x, Decl(es5-asyncFunctionDoStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
+
+async function doStatement18() {
+>doStatement18 : Symbol(doStatement18, Decl(es5-asyncFunctionDoStatements.ts, 72, 1))
+
+    H: do { break H; } while (await y);
+>y : Symbol(y, Decl(es5-asyncFunctionDoStatements.ts, 0, 14))
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionDoStatements.types b/tests/baselines/reference/es5-asyncFunctionDoStatements.types
new file mode 100644
index 0000000000000..cfec3eebcfb0b
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionDoStatements.types
@@ -0,0 +1,186 @@
+=== tests/cases/compiler/es5-asyncFunctionDoStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function doStatement0() {
+>doStatement0 : () => Promise<void>
+
+    do { x; } while (y);
+>x : any
+>y : any
+}
+
+async function doStatement1() {
+>doStatement1 : () => Promise<void>
+
+    do { await x; } while (y);
+>await x : any
+>x : any
+>y : any
+}
+
+async function doStatement2() {
+>doStatement2 : () => Promise<void>
+
+    do { x; } while (await y);
+>x : any
+>await y : any
+>y : any
+}
+
+async function doStatement3() {
+>doStatement3 : () => Promise<void>
+
+    do { continue; } while (y);
+>y : any
+}
+
+async function doStatement4() {
+>doStatement4 : () => Promise<void>
+
+    do { await x; continue; } while (y);
+>await x : any
+>x : any
+>y : any
+}
+
+async function doStatement5() {
+>doStatement5 : () => Promise<void>
+
+    do { if (1) continue; await x; } while (y);
+>1 : number
+>await x : any
+>x : any
+>y : any
+}
+
+async function doStatement6() {
+>doStatement6 : () => Promise<void>
+
+    do { continue; } while (await y);
+>await y : any
+>y : any
+}
+
+async function doStatement7() {
+>doStatement7 : () => Promise<void>
+
+    A: do { continue A; } while (y);
+>A : any
+>A : any
+>y : any
+}
+
+async function doStatement8() {
+>doStatement8 : () => Promise<void>
+
+    B: do { await x; continue B; } while (y);
+>B : any
+>await x : any
+>x : any
+>B : any
+>y : any
+}
+
+async function doStatement9() {
+>doStatement9 : () => Promise<void>
+
+    C: do { if (1) continue C; await x; } while (y);
+>C : any
+>1 : number
+>C : any
+>await x : any
+>x : any
+>y : any
+}
+
+async function doStatement10() {
+>doStatement10 : () => Promise<void>
+
+    D: do { continue D; } while (await y);
+>D : any
+>D : any
+>await y : any
+>y : any
+}
+
+async function doStatement11() {
+>doStatement11 : () => Promise<void>
+
+    do { break; } while (y);
+>y : any
+}
+
+async function doStatement12() {
+>doStatement12 : () => Promise<void>
+
+    do { await x; break; } while (y);
+>await x : any
+>x : any
+>y : any
+}
+
+async function doStatement13() {
+>doStatement13 : () => Promise<void>
+
+    do { if (1) break; await x; } while (y);
+>1 : number
+>await x : any
+>x : any
+>y : any
+}
+
+async function doStatement14() {
+>doStatement14 : () => Promise<void>
+
+    do { break; } while (await y);
+>await y : any
+>y : any
+}
+
+async function doStatement15() {
+>doStatement15 : () => Promise<void>
+
+    E: do { break E; } while (y);
+>E : any
+>E : any
+>y : any
+}
+
+async function doStatement16() {
+>doStatement16 : () => Promise<void>
+
+    F: do { await x; break F; } while (y);
+>F : any
+>await x : any
+>x : any
+>F : any
+>y : any
+}
+
+async function doStatement17() {
+>doStatement17 : () => Promise<void>
+
+    G: do { if (1) break G; await x; } while (y);
+>G : any
+>1 : number
+>G : any
+>await x : any
+>x : any
+>y : any
+}
+
+async function doStatement18() {
+>doStatement18 : () => Promise<void>
+
+    H: do { break H; } while (await y);
+>H : any
+>H : any
+>await y : any
+>y : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionElementAccess.js b/tests/baselines/reference/es5-asyncFunctionElementAccess.js
new file mode 100644
index 0000000000000..4595cc219e9b7
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionElementAccess.js
@@ -0,0 +1,56 @@
+//// [es5-asyncFunctionElementAccess.ts]
+declare var x, y, z, a, b, c;
+
+async function elementAccess0() {
+    z = await x[y];
+}
+
+async function elementAccess1() {
+    z = (await x)[y];
+}
+
+async function elementAccess2() {
+    z = x[await y];
+}
+
+
+//// [es5-asyncFunctionElementAccess.js]
+function elementAccess0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x[y]];
+                case 1:
+                    z = _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function elementAccess1() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    z = (_a.sent())[y];
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function elementAccess2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, y];
+                case 1:
+                    z = _a[_b.sent()];
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionElementAccess.symbols b/tests/baselines/reference/es5-asyncFunctionElementAccess.symbols
new file mode 100644
index 0000000000000..b4c9968e7b9fb
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionElementAccess.symbols
@@ -0,0 +1,36 @@
+=== tests/cases/compiler/es5-asyncFunctionElementAccess.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionElementAccess.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionElementAccess.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionElementAccess.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionElementAccess.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionElementAccess.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionElementAccess.ts, 0, 26))
+
+async function elementAccess0() {
+>elementAccess0 : Symbol(elementAccess0, Decl(es5-asyncFunctionElementAccess.ts, 0, 29))
+
+    z = await x[y];
+>z : Symbol(z, Decl(es5-asyncFunctionElementAccess.ts, 0, 17))
+>x : Symbol(x, Decl(es5-asyncFunctionElementAccess.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionElementAccess.ts, 0, 14))
+}
+
+async function elementAccess1() {
+>elementAccess1 : Symbol(elementAccess1, Decl(es5-asyncFunctionElementAccess.ts, 4, 1))
+
+    z = (await x)[y];
+>z : Symbol(z, Decl(es5-asyncFunctionElementAccess.ts, 0, 17))
+>x : Symbol(x, Decl(es5-asyncFunctionElementAccess.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionElementAccess.ts, 0, 14))
+}
+
+async function elementAccess2() {
+>elementAccess2 : Symbol(elementAccess2, Decl(es5-asyncFunctionElementAccess.ts, 8, 1))
+
+    z = x[await y];
+>z : Symbol(z, Decl(es5-asyncFunctionElementAccess.ts, 0, 17))
+>x : Symbol(x, Decl(es5-asyncFunctionElementAccess.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionElementAccess.ts, 0, 14))
+}
+
diff --git a/tests/baselines/reference/es5-asyncFunctionElementAccess.types b/tests/baselines/reference/es5-asyncFunctionElementAccess.types
new file mode 100644
index 0000000000000..ab5c31ad09abf
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionElementAccess.types
@@ -0,0 +1,46 @@
+=== tests/cases/compiler/es5-asyncFunctionElementAccess.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function elementAccess0() {
+>elementAccess0 : () => Promise<void>
+
+    z = await x[y];
+>z = await x[y] : any
+>z : any
+>await x[y] : any
+>x[y] : any
+>x : any
+>y : any
+}
+
+async function elementAccess1() {
+>elementAccess1 : () => Promise<void>
+
+    z = (await x)[y];
+>z = (await x)[y] : any
+>z : any
+>(await x)[y] : any
+>(await x) : any
+>await x : any
+>x : any
+>y : any
+}
+
+async function elementAccess2() {
+>elementAccess2 : () => Promise<void>
+
+    z = x[await y];
+>z = x[await y] : any
+>z : any
+>x[await y] : any
+>x : any
+>await y : any
+>y : any
+}
+
diff --git a/tests/baselines/reference/es5-asyncFunctionForInStatements.js b/tests/baselines/reference/es5-asyncFunctionForInStatements.js
new file mode 100644
index 0000000000000..4ce6e5e4a1906
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionForInStatements.js
@@ -0,0 +1,250 @@
+//// [es5-asyncFunctionForInStatements.ts]
+declare var x, y, z, a, b, c;
+
+async function forInStatement0() {
+    for (x in y) { z; }
+}
+
+async function forInStatement1() {
+    for (x in await y) { z; }
+}
+
+async function forInStatement2() {
+    for (x in y) { await z; }
+}
+
+async function forInStatement3() {
+    for ((await x).a in y) { z; }
+}
+
+async function forInStatement4() {
+    for (x.a in await y) { z; }
+}
+
+async function forInStatement5() {
+    for (x.a in y) { await z; }
+}
+
+async function forInStatement6() {
+    for (var a in y) { z; }
+}
+
+async function forInStatement7() {
+    for (var b in await y) { z; }
+}
+
+async function forInStatement8() {
+    for (var c in y) { await z; }
+}
+
+//// [es5-asyncFunctionForInStatements.js]
+function forInStatement0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            for (x in y) {
+                z;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function forInStatement1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _i;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = [];
+                    return [4 /*yield*/, y];
+                case 1:
+                    for (_b in _c.sent())
+                        _a.push(_b);
+                    _i = 0;
+                    _c.label = 2;
+                case 2:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    x = _a[_i];
+                    z;
+                    _c.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 2];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forInStatement2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _i;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = [];
+                    for (_b in y)
+                        _a.push(_b);
+                    _i = 0;
+                    _c.label = 1;
+                case 1:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    x = _a[_i];
+                    return [4 /*yield*/, z];
+                case 2:
+                    _c.sent();
+                    _c.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forInStatement3() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _i;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = [];
+                    for (_b in y)
+                        _a.push(_b);
+                    _i = 0;
+                    _c.label = 1;
+                case 1:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    return [4 /*yield*/, x];
+                case 2:
+                    (_c.sent()).a = _a[_i];
+                    z;
+                    _c.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forInStatement4() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _i;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = [];
+                    return [4 /*yield*/, y];
+                case 1:
+                    for (_b in _c.sent())
+                        _a.push(_b);
+                    _i = 0;
+                    _c.label = 2;
+                case 2:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    x.a = _a[_i];
+                    z;
+                    _c.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 2];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forInStatement5() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _i;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = [];
+                    for (_b in y)
+                        _a.push(_b);
+                    _i = 0;
+                    _c.label = 1;
+                case 1:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    x.a = _a[_i];
+                    return [4 /*yield*/, z];
+                case 2:
+                    _c.sent();
+                    _c.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forInStatement6() {
+    return __awaiter(this, void 0, void 0, function () {
+        var a;
+        return __generator(function (_a) {
+            for (a in y) {
+                z;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function forInStatement7() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _i, b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = [];
+                    return [4 /*yield*/, y];
+                case 1:
+                    for (_b in _c.sent())
+                        _a.push(_b);
+                    _i = 0;
+                    _c.label = 2;
+                case 2:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    b = _a[_i];
+                    z;
+                    _c.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 2];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forInStatement8() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _i, c;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = [];
+                    for (_b in y)
+                        _a.push(_b);
+                    _i = 0;
+                    _c.label = 1;
+                case 1:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    c = _a[_i];
+                    return [4 /*yield*/, z];
+                case 2:
+                    _c.sent();
+                    _c.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionForInStatements.symbols b/tests/baselines/reference/es5-asyncFunctionForInStatements.symbols
new file mode 100644
index 0000000000000..623978f0b640d
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionForInStatements.symbols
@@ -0,0 +1,89 @@
+=== tests/cases/compiler/es5-asyncFunctionForInStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionForInStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForInStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForInStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionForInStatements.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionForInStatements.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionForInStatements.ts, 0, 26))
+
+async function forInStatement0() {
+>forInStatement0 : Symbol(forInStatement0, Decl(es5-asyncFunctionForInStatements.ts, 0, 29))
+
+    for (x in y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForInStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForInStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForInStatements.ts, 0, 17))
+}
+
+async function forInStatement1() {
+>forInStatement1 : Symbol(forInStatement1, Decl(es5-asyncFunctionForInStatements.ts, 4, 1))
+
+    for (x in await y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForInStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForInStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForInStatements.ts, 0, 17))
+}
+
+async function forInStatement2() {
+>forInStatement2 : Symbol(forInStatement2, Decl(es5-asyncFunctionForInStatements.ts, 8, 1))
+
+    for (x in y) { await z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForInStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForInStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForInStatements.ts, 0, 17))
+}
+
+async function forInStatement3() {
+>forInStatement3 : Symbol(forInStatement3, Decl(es5-asyncFunctionForInStatements.ts, 12, 1))
+
+    for ((await x).a in y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForInStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForInStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForInStatements.ts, 0, 17))
+}
+
+async function forInStatement4() {
+>forInStatement4 : Symbol(forInStatement4, Decl(es5-asyncFunctionForInStatements.ts, 16, 1))
+
+    for (x.a in await y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForInStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForInStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForInStatements.ts, 0, 17))
+}
+
+async function forInStatement5() {
+>forInStatement5 : Symbol(forInStatement5, Decl(es5-asyncFunctionForInStatements.ts, 20, 1))
+
+    for (x.a in y) { await z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForInStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForInStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForInStatements.ts, 0, 17))
+}
+
+async function forInStatement6() {
+>forInStatement6 : Symbol(forInStatement6, Decl(es5-asyncFunctionForInStatements.ts, 24, 1))
+
+    for (var a in y) { z; }
+>a : Symbol(a, Decl(es5-asyncFunctionForInStatements.ts, 27, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionForInStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForInStatements.ts, 0, 17))
+}
+
+async function forInStatement7() {
+>forInStatement7 : Symbol(forInStatement7, Decl(es5-asyncFunctionForInStatements.ts, 28, 1))
+
+    for (var b in await y) { z; }
+>b : Symbol(b, Decl(es5-asyncFunctionForInStatements.ts, 31, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionForInStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForInStatements.ts, 0, 17))
+}
+
+async function forInStatement8() {
+>forInStatement8 : Symbol(forInStatement8, Decl(es5-asyncFunctionForInStatements.ts, 32, 1))
+
+    for (var c in y) { await z; }
+>c : Symbol(c, Decl(es5-asyncFunctionForInStatements.ts, 35, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionForInStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForInStatements.ts, 0, 17))
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionForInStatements.types b/tests/baselines/reference/es5-asyncFunctionForInStatements.types
new file mode 100644
index 0000000000000..dcdb276cc9055
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionForInStatements.types
@@ -0,0 +1,103 @@
+=== tests/cases/compiler/es5-asyncFunctionForInStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function forInStatement0() {
+>forInStatement0 : () => Promise<void>
+
+    for (x in y) { z; }
+>x : any
+>y : any
+>z : any
+}
+
+async function forInStatement1() {
+>forInStatement1 : () => Promise<void>
+
+    for (x in await y) { z; }
+>x : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function forInStatement2() {
+>forInStatement2 : () => Promise<void>
+
+    for (x in y) { await z; }
+>x : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function forInStatement3() {
+>forInStatement3 : () => Promise<void>
+
+    for ((await x).a in y) { z; }
+>(await x).a : any
+>(await x) : any
+>await x : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function forInStatement4() {
+>forInStatement4 : () => Promise<void>
+
+    for (x.a in await y) { z; }
+>x.a : any
+>x : any
+>a : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function forInStatement5() {
+>forInStatement5 : () => Promise<void>
+
+    for (x.a in y) { await z; }
+>x.a : any
+>x : any
+>a : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function forInStatement6() {
+>forInStatement6 : () => Promise<void>
+
+    for (var a in y) { z; }
+>a : string
+>y : any
+>z : any
+}
+
+async function forInStatement7() {
+>forInStatement7 : () => Promise<void>
+
+    for (var b in await y) { z; }
+>b : string
+>await y : any
+>y : any
+>z : any
+}
+
+async function forInStatement8() {
+>forInStatement8 : () => Promise<void>
+
+    for (var c in y) { await z; }
+>c : string
+>y : any
+>await z : any
+>z : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionForOfStatements.js b/tests/baselines/reference/es5-asyncFunctionForOfStatements.js
new file mode 100644
index 0000000000000..0d5c7753da932
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionForOfStatements.js
@@ -0,0 +1,537 @@
+//// [es5-asyncFunctionForOfStatements.ts]
+declare var x, y, z, a, b, c;
+
+async function forOfStatement0() {
+    for (x of y) { z; }
+}
+
+async function forOfStatement1() {
+    for (x of await y) { z; }
+}
+
+async function forOfStatement2() {
+    for (x of y) { await z; }
+}
+
+async function forOfStatement3() {
+    for ((await x).a of y) { z; }
+}
+
+async function forOfStatement4() {
+    for (x.a of await y) { z; }
+}
+
+async function forOfStatement5() {
+    for (x.a of y) { await z; }
+}
+
+async function forOfStatement6() {
+    for (var b of y) { z; }
+}
+
+async function forOfStatement7() {
+    for (var c of await y) { z; }
+}
+
+async function forOfStatement8() {
+    for (var d of y) { await z; }
+}
+
+async function forOfStatement9() {
+    for ([x] of await y) { z; }
+}
+
+async function forOfStatement10() {
+    for ([x] of y) { await z; }
+}
+
+async function forOfStatement11() {
+    for ([x = await a] of y) { z; }
+}
+
+async function forOfStatement12() {
+    for ([x = a] of await y) { z; }
+}
+
+async function forOfStatement13() {
+    for ([x = a] of y) { await z; }
+}
+
+async function forOfStatement14() {
+    for ({ x } of await y) { z; }
+}
+
+async function forOfStatement15() {
+    for ({ x } of y) { await z; }
+}
+
+async function forOfStatement16() {
+    for ({ x = await a } of y) { z; }
+}
+
+async function forOfStatement17() {
+    for ({ x = a } of await y) { z; }
+}
+
+async function forOfStatement18() {
+    for ({ x = a } of y) { await z; }
+}
+
+//// [es5-asyncFunctionForOfStatements.js]
+function forOfStatement0() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, y_1;
+        return __generator(function (_a) {
+            for (_i = 0, y_1 = y; _i < y_1.length; _i++) {
+                x = y_1[_i];
+                z;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function forOfStatement1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _i = 0;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a = _b.sent();
+                    _b.label = 2;
+                case 2:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    x = _a[_i];
+                    z;
+                    _b.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 2];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, y_2;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _i = 0, y_2 = y;
+                    _a.label = 1;
+                case 1:
+                    if (!(_i < y_2.length))
+                        return [3 /*break*/, 4];
+                    x = y_2[_i];
+                    return [4 /*yield*/, z];
+                case 2:
+                    _a.sent();
+                    _a.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement3() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, y_3;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _i = 0, y_3 = y;
+                    _a.label = 1;
+                case 1:
+                    if (!(_i < y_3.length))
+                        return [3 /*break*/, 4];
+                    return [4 /*yield*/, x];
+                case 2:
+                    (_a.sent()).a = y_3[_i];
+                    z;
+                    _a.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement4() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _i = 0;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a = _b.sent();
+                    _b.label = 2;
+                case 2:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    x.a = _a[_i];
+                    z;
+                    _b.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 2];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement5() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, y_4;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _i = 0, y_4 = y;
+                    _a.label = 1;
+                case 1:
+                    if (!(_i < y_4.length))
+                        return [3 /*break*/, 4];
+                    x.a = y_4[_i];
+                    return [4 /*yield*/, z];
+                case 2:
+                    _a.sent();
+                    _a.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement6() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, y_5, b;
+        return __generator(function (_a) {
+            for (_i = 0, y_5 = y; _i < y_5.length; _i++) {
+                b = y_5[_i];
+                z;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function forOfStatement7() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, _a, c;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _i = 0;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a = _b.sent();
+                    _b.label = 2;
+                case 2:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    c = _a[_i];
+                    z;
+                    _b.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 2];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement8() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, y_6, d;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _i = 0, y_6 = y;
+                    _a.label = 1;
+                case 1:
+                    if (!(_i < y_6.length))
+                        return [3 /*break*/, 4];
+                    d = y_6[_i];
+                    return [4 /*yield*/, z];
+                case 2:
+                    _a.sent();
+                    _a.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement9() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _i = 0;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a = _b.sent();
+                    _b.label = 2;
+                case 2:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    x = _a[_i][0];
+                    z;
+                    _b.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 2];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement10() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, y_7;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _i = 0, y_7 = y;
+                    _a.label = 1;
+                case 1:
+                    if (!(_i < y_7.length))
+                        return [3 /*break*/, 4];
+                    x = y_7[_i][0];
+                    return [4 /*yield*/, z];
+                case 2:
+                    _a.sent();
+                    _a.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement11() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, y_8, _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _i = 0, y_8 = y;
+                    _c.label = 1;
+                case 1:
+                    if (!(_i < y_8.length))
+                        return [3 /*break*/, 6];
+                    _b = y_8[_i][0];
+                    if (!(_b === void 0))
+                        return [3 /*break*/, 3];
+                    return [4 /*yield*/, a];
+                case 2:
+                    _a = _c.sent();
+                    return [3 /*break*/, 4];
+                case 3:
+                    _a = _b;
+                    _c.label = 4;
+                case 4:
+                    x = _a;
+                    z;
+                    _c.label = 5;
+                case 5:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 6: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement12() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _i = 0;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a = _c.sent();
+                    _c.label = 2;
+                case 2:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    _b = _a[_i][0], x = _b === void 0 ? a : _b;
+                    z;
+                    _c.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 2];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement13() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, y_9, _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _i = 0, y_9 = y;
+                    _b.label = 1;
+                case 1:
+                    if (!(_i < y_9.length))
+                        return [3 /*break*/, 4];
+                    _a = y_9[_i][0], x = _a === void 0 ? a : _a;
+                    return [4 /*yield*/, z];
+                case 2:
+                    _b.sent();
+                    _b.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement14() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _i = 0;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a = _b.sent();
+                    _b.label = 2;
+                case 2:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    x = _a[_i].x;
+                    z;
+                    _b.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 2];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement15() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, y_10;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _i = 0, y_10 = y;
+                    _a.label = 1;
+                case 1:
+                    if (!(_i < y_10.length))
+                        return [3 /*break*/, 4];
+                    x = y_10[_i].x;
+                    return [4 /*yield*/, z];
+                case 2:
+                    _a.sent();
+                    _a.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement16() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, y_11, _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _i = 0, y_11 = y;
+                    _c.label = 1;
+                case 1:
+                    if (!(_i < y_11.length))
+                        return [3 /*break*/, 6];
+                    _b = y_11[_i].x;
+                    if (!(_b === void 0))
+                        return [3 /*break*/, 3];
+                    return [4 /*yield*/, a];
+                case 2:
+                    _a = _c.sent();
+                    return [3 /*break*/, 4];
+                case 3:
+                    _a = _b;
+                    _c.label = 4;
+                case 4:
+                    x = _a;
+                    z;
+                    _c.label = 5;
+                case 5:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 6: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement17() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _i = 0;
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a = _c.sent();
+                    _c.label = 2;
+                case 2:
+                    if (!(_i < _a.length))
+                        return [3 /*break*/, 4];
+                    _b = _a[_i].x, x = _b === void 0 ? a : _b;
+                    z;
+                    _c.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 2];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forOfStatement18() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _i, y_12, _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _i = 0, y_12 = y;
+                    _b.label = 1;
+                case 1:
+                    if (!(_i < y_12.length))
+                        return [3 /*break*/, 4];
+                    _a = y_12[_i].x, x = _a === void 0 ? a : _a;
+                    return [4 /*yield*/, z];
+                case 2:
+                    _b.sent();
+                    _b.label = 3;
+                case 3:
+                    _i++;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionForOfStatements.symbols b/tests/baselines/reference/es5-asyncFunctionForOfStatements.symbols
new file mode 100644
index 0000000000000..15742967e09a5
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionForOfStatements.symbols
@@ -0,0 +1,183 @@
+=== tests/cases/compiler/es5-asyncFunctionForOfStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionForOfStatements.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionForOfStatements.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionForOfStatements.ts, 0, 26))
+
+async function forOfStatement0() {
+>forOfStatement0 : Symbol(forOfStatement0, Decl(es5-asyncFunctionForOfStatements.ts, 0, 29))
+
+    for (x of y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement1() {
+>forOfStatement1 : Symbol(forOfStatement1, Decl(es5-asyncFunctionForOfStatements.ts, 4, 1))
+
+    for (x of await y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement2() {
+>forOfStatement2 : Symbol(forOfStatement2, Decl(es5-asyncFunctionForOfStatements.ts, 8, 1))
+
+    for (x of y) { await z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement3() {
+>forOfStatement3 : Symbol(forOfStatement3, Decl(es5-asyncFunctionForOfStatements.ts, 12, 1))
+
+    for ((await x).a of y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement4() {
+>forOfStatement4 : Symbol(forOfStatement4, Decl(es5-asyncFunctionForOfStatements.ts, 16, 1))
+
+    for (x.a of await y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement5() {
+>forOfStatement5 : Symbol(forOfStatement5, Decl(es5-asyncFunctionForOfStatements.ts, 20, 1))
+
+    for (x.a of y) { await z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement6() {
+>forOfStatement6 : Symbol(forOfStatement6, Decl(es5-asyncFunctionForOfStatements.ts, 24, 1))
+
+    for (var b of y) { z; }
+>b : Symbol(b, Decl(es5-asyncFunctionForOfStatements.ts, 27, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement7() {
+>forOfStatement7 : Symbol(forOfStatement7, Decl(es5-asyncFunctionForOfStatements.ts, 28, 1))
+
+    for (var c of await y) { z; }
+>c : Symbol(c, Decl(es5-asyncFunctionForOfStatements.ts, 31, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement8() {
+>forOfStatement8 : Symbol(forOfStatement8, Decl(es5-asyncFunctionForOfStatements.ts, 32, 1))
+
+    for (var d of y) { await z; }
+>d : Symbol(d, Decl(es5-asyncFunctionForOfStatements.ts, 35, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement9() {
+>forOfStatement9 : Symbol(forOfStatement9, Decl(es5-asyncFunctionForOfStatements.ts, 36, 1))
+
+    for ([x] of await y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement10() {
+>forOfStatement10 : Symbol(forOfStatement10, Decl(es5-asyncFunctionForOfStatements.ts, 40, 1))
+
+    for ([x] of y) { await z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement11() {
+>forOfStatement11 : Symbol(forOfStatement11, Decl(es5-asyncFunctionForOfStatements.ts, 44, 1))
+
+    for ([x = await a] of y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionForOfStatements.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement12() {
+>forOfStatement12 : Symbol(forOfStatement12, Decl(es5-asyncFunctionForOfStatements.ts, 48, 1))
+
+    for ([x = a] of await y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionForOfStatements.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement13() {
+>forOfStatement13 : Symbol(forOfStatement13, Decl(es5-asyncFunctionForOfStatements.ts, 52, 1))
+
+    for ([x = a] of y) { await z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionForOfStatements.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement14() {
+>forOfStatement14 : Symbol(forOfStatement14, Decl(es5-asyncFunctionForOfStatements.ts, 56, 1))
+
+    for ({ x } of await y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 59, 10))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement15() {
+>forOfStatement15 : Symbol(forOfStatement15, Decl(es5-asyncFunctionForOfStatements.ts, 60, 1))
+
+    for ({ x } of y) { await z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 63, 10))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement16() {
+>forOfStatement16 : Symbol(forOfStatement16, Decl(es5-asyncFunctionForOfStatements.ts, 64, 1))
+
+    for ({ x = await a } of y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 67, 10))
+>a : Symbol(a, Decl(es5-asyncFunctionForOfStatements.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement17() {
+>forOfStatement17 : Symbol(forOfStatement17, Decl(es5-asyncFunctionForOfStatements.ts, 68, 1))
+
+    for ({ x = a } of await y) { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 71, 10))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
+
+async function forOfStatement18() {
+>forOfStatement18 : Symbol(forOfStatement18, Decl(es5-asyncFunctionForOfStatements.ts, 72, 1))
+
+    for ({ x = a } of y) { await z; }
+>x : Symbol(x, Decl(es5-asyncFunctionForOfStatements.ts, 75, 10))
+>y : Symbol(y, Decl(es5-asyncFunctionForOfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForOfStatements.ts, 0, 17))
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionForOfStatements.types b/tests/baselines/reference/es5-asyncFunctionForOfStatements.types
new file mode 100644
index 0000000000000..24c5e5eb83c9e
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionForOfStatements.types
@@ -0,0 +1,222 @@
+=== tests/cases/compiler/es5-asyncFunctionForOfStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function forOfStatement0() {
+>forOfStatement0 : () => Promise<void>
+
+    for (x of y) { z; }
+>x : any
+>y : any
+>z : any
+}
+
+async function forOfStatement1() {
+>forOfStatement1 : () => Promise<void>
+
+    for (x of await y) { z; }
+>x : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function forOfStatement2() {
+>forOfStatement2 : () => Promise<void>
+
+    for (x of y) { await z; }
+>x : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function forOfStatement3() {
+>forOfStatement3 : () => Promise<void>
+
+    for ((await x).a of y) { z; }
+>(await x).a : any
+>(await x) : any
+>await x : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function forOfStatement4() {
+>forOfStatement4 : () => Promise<void>
+
+    for (x.a of await y) { z; }
+>x.a : any
+>x : any
+>a : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function forOfStatement5() {
+>forOfStatement5 : () => Promise<void>
+
+    for (x.a of y) { await z; }
+>x.a : any
+>x : any
+>a : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function forOfStatement6() {
+>forOfStatement6 : () => Promise<void>
+
+    for (var b of y) { z; }
+>b : any
+>y : any
+>z : any
+}
+
+async function forOfStatement7() {
+>forOfStatement7 : () => Promise<void>
+
+    for (var c of await y) { z; }
+>c : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function forOfStatement8() {
+>forOfStatement8 : () => Promise<void>
+
+    for (var d of y) { await z; }
+>d : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function forOfStatement9() {
+>forOfStatement9 : () => Promise<void>
+
+    for ([x] of await y) { z; }
+>[x] : [any]
+>x : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function forOfStatement10() {
+>forOfStatement10 : () => Promise<void>
+
+    for ([x] of y) { await z; }
+>[x] : [any]
+>x : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function forOfStatement11() {
+>forOfStatement11 : () => Promise<void>
+
+    for ([x = await a] of y) { z; }
+>[x = await a] : [any]
+>x = await a : any
+>x : any
+>await a : any
+>a : any
+>y : any
+>z : any
+}
+
+async function forOfStatement12() {
+>forOfStatement12 : () => Promise<void>
+
+    for ([x = a] of await y) { z; }
+>[x = a] : [any]
+>x = a : any
+>x : any
+>a : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function forOfStatement13() {
+>forOfStatement13 : () => Promise<void>
+
+    for ([x = a] of y) { await z; }
+>[x = a] : [any]
+>x = a : any
+>x : any
+>a : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function forOfStatement14() {
+>forOfStatement14 : () => Promise<void>
+
+    for ({ x } of await y) { z; }
+>{ x } : { x: any; }
+>x : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function forOfStatement15() {
+>forOfStatement15 : () => Promise<void>
+
+    for ({ x } of y) { await z; }
+>{ x } : { x: any; }
+>x : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function forOfStatement16() {
+>forOfStatement16 : () => Promise<void>
+
+    for ({ x = await a } of y) { z; }
+>{ x = await a } : { x?: any; }
+>x : any
+>await a : any
+>a : any
+>y : any
+>z : any
+}
+
+async function forOfStatement17() {
+>forOfStatement17 : () => Promise<void>
+
+    for ({ x = a } of await y) { z; }
+>{ x = a } : { x?: any; }
+>x : any
+>a : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function forOfStatement18() {
+>forOfStatement18 : () => Promise<void>
+
+    for ({ x = a } of y) { await z; }
+>{ x = a } : { x?: any; }
+>x : any
+>a : any
+>y : any
+>await z : any
+>z : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionForStatements.js b/tests/baselines/reference/es5-asyncFunctionForStatements.js
new file mode 100644
index 0000000000000..bea0d5838a406
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionForStatements.js
@@ -0,0 +1,149 @@
+//// [es5-asyncFunctionForStatements.ts]
+declare var x, y, z, a, b, c;
+
+async function forStatement0() {
+    for (x; y; z) { a; }
+}
+
+async function forStatement1() {
+    for (await x; y; z) { a; }
+}
+
+async function forStatement2() {
+    for (x; await y; z) { a; }
+}
+
+async function forStatement3() {
+    for (x; y; await z) { a; }
+}
+
+async function forStatement4() {
+    for (x; y; z) { await a; }
+}
+
+async function forStatement5() {
+    for (var b; y; z) { a; }
+}
+
+async function forStatement6() {
+    for (var c = x; y; z) { a; }
+}
+
+//// [es5-asyncFunctionForStatements.js]
+function forStatement0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            for (x; y; z) {
+                a;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function forStatement1() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    _a.label = 2;
+                case 2:
+                    if (!y)
+                        return [3 /*break*/, 4];
+                    a;
+                    _a.label = 3;
+                case 3:
+                    z;
+                    return [3 /*break*/, 2];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forStatement2() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    x;
+                    _a.label = 1;
+                case 1: return [4 /*yield*/, y];
+                case 2:
+                    if (!_a.sent())
+                        return [3 /*break*/, 4];
+                    a;
+                    _a.label = 3;
+                case 3:
+                    z;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forStatement3() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    x;
+                    _a.label = 1;
+                case 1:
+                    if (!y)
+                        return [3 /*break*/, 4];
+                    a;
+                    _a.label = 2;
+                case 2: return [4 /*yield*/, z];
+                case 3:
+                    _a.sent();
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forStatement4() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    x;
+                    _a.label = 1;
+                case 1:
+                    if (!y)
+                        return [3 /*break*/, 4];
+                    return [4 /*yield*/, a];
+                case 2:
+                    _a.sent();
+                    _a.label = 3;
+                case 3:
+                    z;
+                    return [3 /*break*/, 1];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function forStatement5() {
+    return __awaiter(this, void 0, void 0, function () {
+        var b;
+        return __generator(function (_a) {
+            for (; y; z) {
+                a;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function forStatement6() {
+    return __awaiter(this, void 0, void 0, function () {
+        var c;
+        return __generator(function (_a) {
+            for (c = x; y; z) {
+                a;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionForStatements.symbols b/tests/baselines/reference/es5-asyncFunctionForStatements.symbols
new file mode 100644
index 0000000000000..878c29e484742
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionForStatements.symbols
@@ -0,0 +1,79 @@
+=== tests/cases/compiler/es5-asyncFunctionForStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionForStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionForStatements.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionForStatements.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionForStatements.ts, 0, 26))
+
+async function forStatement0() {
+>forStatement0 : Symbol(forStatement0, Decl(es5-asyncFunctionForStatements.ts, 0, 29))
+
+    for (x; y; z) { a; }
+>x : Symbol(x, Decl(es5-asyncFunctionForStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionForStatements.ts, 0, 20))
+}
+
+async function forStatement1() {
+>forStatement1 : Symbol(forStatement1, Decl(es5-asyncFunctionForStatements.ts, 4, 1))
+
+    for (await x; y; z) { a; }
+>x : Symbol(x, Decl(es5-asyncFunctionForStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionForStatements.ts, 0, 20))
+}
+
+async function forStatement2() {
+>forStatement2 : Symbol(forStatement2, Decl(es5-asyncFunctionForStatements.ts, 8, 1))
+
+    for (x; await y; z) { a; }
+>x : Symbol(x, Decl(es5-asyncFunctionForStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionForStatements.ts, 0, 20))
+}
+
+async function forStatement3() {
+>forStatement3 : Symbol(forStatement3, Decl(es5-asyncFunctionForStatements.ts, 12, 1))
+
+    for (x; y; await z) { a; }
+>x : Symbol(x, Decl(es5-asyncFunctionForStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionForStatements.ts, 0, 20))
+}
+
+async function forStatement4() {
+>forStatement4 : Symbol(forStatement4, Decl(es5-asyncFunctionForStatements.ts, 16, 1))
+
+    for (x; y; z) { await a; }
+>x : Symbol(x, Decl(es5-asyncFunctionForStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionForStatements.ts, 0, 20))
+}
+
+async function forStatement5() {
+>forStatement5 : Symbol(forStatement5, Decl(es5-asyncFunctionForStatements.ts, 20, 1))
+
+    for (var b; y; z) { a; }
+>b : Symbol(b, Decl(es5-asyncFunctionForStatements.ts, 23, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionForStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionForStatements.ts, 0, 20))
+}
+
+async function forStatement6() {
+>forStatement6 : Symbol(forStatement6, Decl(es5-asyncFunctionForStatements.ts, 24, 1))
+
+    for (var c = x; y; z) { a; }
+>c : Symbol(c, Decl(es5-asyncFunctionForStatements.ts, 27, 12))
+>x : Symbol(x, Decl(es5-asyncFunctionForStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionForStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionForStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionForStatements.ts, 0, 20))
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionForStatements.types b/tests/baselines/reference/es5-asyncFunctionForStatements.types
new file mode 100644
index 0000000000000..0b060f5b7080b
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionForStatements.types
@@ -0,0 +1,83 @@
+=== tests/cases/compiler/es5-asyncFunctionForStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function forStatement0() {
+>forStatement0 : () => Promise<void>
+
+    for (x; y; z) { a; }
+>x : any
+>y : any
+>z : any
+>a : any
+}
+
+async function forStatement1() {
+>forStatement1 : () => Promise<void>
+
+    for (await x; y; z) { a; }
+>await x : any
+>x : any
+>y : any
+>z : any
+>a : any
+}
+
+async function forStatement2() {
+>forStatement2 : () => Promise<void>
+
+    for (x; await y; z) { a; }
+>x : any
+>await y : any
+>y : any
+>z : any
+>a : any
+}
+
+async function forStatement3() {
+>forStatement3 : () => Promise<void>
+
+    for (x; y; await z) { a; }
+>x : any
+>y : any
+>await z : any
+>z : any
+>a : any
+}
+
+async function forStatement4() {
+>forStatement4 : () => Promise<void>
+
+    for (x; y; z) { await a; }
+>x : any
+>y : any
+>z : any
+>await a : any
+>a : any
+}
+
+async function forStatement5() {
+>forStatement5 : () => Promise<void>
+
+    for (var b; y; z) { a; }
+>b : any
+>y : any
+>z : any
+>a : any
+}
+
+async function forStatement6() {
+>forStatement6 : () => Promise<void>
+
+    for (var c = x; y; z) { a; }
+>c : any
+>x : any
+>y : any
+>z : any
+>a : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionHoisting.js b/tests/baselines/reference/es5-asyncFunctionHoisting.js
new file mode 100644
index 0000000000000..6dc05e65bf31c
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionHoisting.js
@@ -0,0 +1,105 @@
+//// [es5-asyncFunctionHoisting.ts]
+declare var y;
+
+async function hoisting() {
+    var a0, a1 = 1;
+    function z() {
+        var b0, b1 = 1;
+    }
+
+    if (true) {
+        var c0, c1 = 1;
+    }
+
+    for (var a = 0; y;) {
+
+    }
+
+    for (var b in y) {
+
+    }
+
+    for (var c of y) {
+
+    }
+}
+
+async function hoistingWithAwait() {
+    var a0, a1 = 1;
+
+    function z() {
+        var b0, b1 = 1;
+    }
+
+    await 0;
+
+    if (true) {
+        var c0, c1 = 1;
+    }
+
+    for (var a = 0; y;) {
+
+    }
+
+    for (var b in y) {
+
+    }
+
+    for (var c of y) {
+
+    }
+}
+
+
+
+//// [es5-asyncFunctionHoisting.js]
+function hoisting() {
+    return __awaiter(this, void 0, void 0, function () {
+        function z() {
+            var b0, b1 = 1;
+        }
+        var a0, a1, c0, c1, a, b, _i, y_1, c;
+        return __generator(function (_a) {
+            a1 = 1;
+            if (true) {
+                c1 = 1;
+            }
+            for (a = 0; y;) {
+            }
+            for (b in y) {
+            }
+            for (_i = 0, y_1 = y; _i < y_1.length; _i++) {
+                c = y_1[_i];
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function hoistingWithAwait() {
+    return __awaiter(this, void 0, void 0, function () {
+        function z() {
+            var b0, b1 = 1;
+        }
+        var a0, a1, c0, c1, a, b, _i, y_2, c;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    a1 = 1;
+                    return [4 /*yield*/, 0];
+                case 1:
+                    _a.sent();
+                    if (true) {
+                        c1 = 1;
+                    }
+                    for (a = 0; y;) {
+                    }
+                    for (b in y) {
+                    }
+                    for (_i = 0, y_2 = y; _i < y_2.length; _i++) {
+                        c = y_2[_i];
+                    }
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionHoisting.symbols b/tests/baselines/reference/es5-asyncFunctionHoisting.symbols
new file mode 100644
index 0000000000000..241060286220d
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionHoisting.symbols
@@ -0,0 +1,87 @@
+=== tests/cases/compiler/es5-asyncFunctionHoisting.ts ===
+declare var y;
+>y : Symbol(y, Decl(es5-asyncFunctionHoisting.ts, 0, 11))
+
+async function hoisting() {
+>hoisting : Symbol(hoisting, Decl(es5-asyncFunctionHoisting.ts, 0, 14))
+
+    var a0, a1 = 1;
+>a0 : Symbol(a0, Decl(es5-asyncFunctionHoisting.ts, 3, 7))
+>a1 : Symbol(a1, Decl(es5-asyncFunctionHoisting.ts, 3, 11))
+
+    function z() {
+>z : Symbol(z, Decl(es5-asyncFunctionHoisting.ts, 3, 19))
+
+        var b0, b1 = 1;
+>b0 : Symbol(b0, Decl(es5-asyncFunctionHoisting.ts, 5, 11))
+>b1 : Symbol(b1, Decl(es5-asyncFunctionHoisting.ts, 5, 15))
+    }
+
+    if (true) {
+        var c0, c1 = 1;
+>c0 : Symbol(c0, Decl(es5-asyncFunctionHoisting.ts, 9, 11))
+>c1 : Symbol(c1, Decl(es5-asyncFunctionHoisting.ts, 9, 15))
+    }
+
+    for (var a = 0; y;) {
+>a : Symbol(a, Decl(es5-asyncFunctionHoisting.ts, 12, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionHoisting.ts, 0, 11))
+
+    }
+
+    for (var b in y) {
+>b : Symbol(b, Decl(es5-asyncFunctionHoisting.ts, 16, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionHoisting.ts, 0, 11))
+
+    }
+
+    for (var c of y) {
+>c : Symbol(c, Decl(es5-asyncFunctionHoisting.ts, 20, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionHoisting.ts, 0, 11))
+
+    }
+}
+
+async function hoistingWithAwait() {
+>hoistingWithAwait : Symbol(hoistingWithAwait, Decl(es5-asyncFunctionHoisting.ts, 23, 1))
+
+    var a0, a1 = 1;
+>a0 : Symbol(a0, Decl(es5-asyncFunctionHoisting.ts, 26, 7))
+>a1 : Symbol(a1, Decl(es5-asyncFunctionHoisting.ts, 26, 11))
+
+    function z() {
+>z : Symbol(z, Decl(es5-asyncFunctionHoisting.ts, 26, 19))
+
+        var b0, b1 = 1;
+>b0 : Symbol(b0, Decl(es5-asyncFunctionHoisting.ts, 29, 11))
+>b1 : Symbol(b1, Decl(es5-asyncFunctionHoisting.ts, 29, 15))
+    }
+
+    await 0;
+
+    if (true) {
+        var c0, c1 = 1;
+>c0 : Symbol(c0, Decl(es5-asyncFunctionHoisting.ts, 35, 11))
+>c1 : Symbol(c1, Decl(es5-asyncFunctionHoisting.ts, 35, 15))
+    }
+
+    for (var a = 0; y;) {
+>a : Symbol(a, Decl(es5-asyncFunctionHoisting.ts, 38, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionHoisting.ts, 0, 11))
+
+    }
+
+    for (var b in y) {
+>b : Symbol(b, Decl(es5-asyncFunctionHoisting.ts, 42, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionHoisting.ts, 0, 11))
+
+    }
+
+    for (var c of y) {
+>c : Symbol(c, Decl(es5-asyncFunctionHoisting.ts, 46, 12))
+>y : Symbol(y, Decl(es5-asyncFunctionHoisting.ts, 0, 11))
+
+    }
+}
+
+
diff --git a/tests/baselines/reference/es5-asyncFunctionHoisting.types b/tests/baselines/reference/es5-asyncFunctionHoisting.types
new file mode 100644
index 0000000000000..04b968c571df5
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionHoisting.types
@@ -0,0 +1,101 @@
+=== tests/cases/compiler/es5-asyncFunctionHoisting.ts ===
+declare var y;
+>y : any
+
+async function hoisting() {
+>hoisting : () => Promise<void>
+
+    var a0, a1 = 1;
+>a0 : any
+>a1 : number
+>1 : number
+
+    function z() {
+>z : () => void
+
+        var b0, b1 = 1;
+>b0 : any
+>b1 : number
+>1 : number
+    }
+
+    if (true) {
+>true : boolean
+
+        var c0, c1 = 1;
+>c0 : any
+>c1 : number
+>1 : number
+    }
+
+    for (var a = 0; y;) {
+>a : number
+>0 : number
+>y : any
+
+    }
+
+    for (var b in y) {
+>b : string
+>y : any
+
+    }
+
+    for (var c of y) {
+>c : any
+>y : any
+
+    }
+}
+
+async function hoistingWithAwait() {
+>hoistingWithAwait : () => Promise<void>
+
+    var a0, a1 = 1;
+>a0 : any
+>a1 : number
+>1 : number
+
+    function z() {
+>z : () => void
+
+        var b0, b1 = 1;
+>b0 : any
+>b1 : number
+>1 : number
+    }
+
+    await 0;
+>await 0 : number
+>0 : number
+
+    if (true) {
+>true : boolean
+
+        var c0, c1 = 1;
+>c0 : any
+>c1 : number
+>1 : number
+    }
+
+    for (var a = 0; y;) {
+>a : number
+>0 : number
+>y : any
+
+    }
+
+    for (var b in y) {
+>b : string
+>y : any
+
+    }
+
+    for (var c of y) {
+>c : any
+>y : any
+
+    }
+}
+
+
diff --git a/tests/baselines/reference/es5-asyncFunctionIfStatements.js b/tests/baselines/reference/es5-asyncFunctionIfStatements.js
new file mode 100644
index 0000000000000..9f7c71a7f3f22
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionIfStatements.js
@@ -0,0 +1,70 @@
+//// [es5-asyncFunctionIfStatements.ts]
+declare var x, y, z, a, b, c;
+
+async function ifStatement1() {
+    if (await x) { y; } else { z; }
+}
+
+async function ifStatement2() {
+    if (x) { await y; } else { z; }
+}
+
+async function ifStatement3() {
+    if (x) { y; } else { await z; }
+}
+
+//// [es5-asyncFunctionIfStatements.js]
+function ifStatement1() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    if (_a.sent()) {
+                        y;
+                    }
+                    else {
+                        z;
+                    }
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function ifStatement2() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 3];
+                case 2:
+                    z;
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function ifStatement3() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 1];
+                    y;
+                    return [3 /*break*/, 3];
+                case 1: return [4 /*yield*/, z];
+                case 2:
+                    _a.sent();
+                    _a.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionIfStatements.symbols b/tests/baselines/reference/es5-asyncFunctionIfStatements.symbols
new file mode 100644
index 0000000000000..b8d8387eaec61
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionIfStatements.symbols
@@ -0,0 +1,35 @@
+=== tests/cases/compiler/es5-asyncFunctionIfStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionIfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionIfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionIfStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionIfStatements.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionIfStatements.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionIfStatements.ts, 0, 26))
+
+async function ifStatement1() {
+>ifStatement1 : Symbol(ifStatement1, Decl(es5-asyncFunctionIfStatements.ts, 0, 29))
+
+    if (await x) { y; } else { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionIfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionIfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionIfStatements.ts, 0, 17))
+}
+
+async function ifStatement2() {
+>ifStatement2 : Symbol(ifStatement2, Decl(es5-asyncFunctionIfStatements.ts, 4, 1))
+
+    if (x) { await y; } else { z; }
+>x : Symbol(x, Decl(es5-asyncFunctionIfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionIfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionIfStatements.ts, 0, 17))
+}
+
+async function ifStatement3() {
+>ifStatement3 : Symbol(ifStatement3, Decl(es5-asyncFunctionIfStatements.ts, 8, 1))
+
+    if (x) { y; } else { await z; }
+>x : Symbol(x, Decl(es5-asyncFunctionIfStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionIfStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionIfStatements.ts, 0, 17))
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionIfStatements.types b/tests/baselines/reference/es5-asyncFunctionIfStatements.types
new file mode 100644
index 0000000000000..9cecdcb9f60f6
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionIfStatements.types
@@ -0,0 +1,38 @@
+=== tests/cases/compiler/es5-asyncFunctionIfStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function ifStatement1() {
+>ifStatement1 : () => Promise<void>
+
+    if (await x) { y; } else { z; }
+>await x : any
+>x : any
+>y : any
+>z : any
+}
+
+async function ifStatement2() {
+>ifStatement2 : () => Promise<void>
+
+    if (x) { await y; } else { z; }
+>x : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function ifStatement3() {
+>ifStatement3 : () => Promise<void>
+
+    if (x) { y; } else { await z; }
+>x : any
+>y : any
+>await z : any
+>z : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionNestedLoops.js b/tests/baselines/reference/es5-asyncFunctionNestedLoops.js
new file mode 100644
index 0000000000000..3290965d6cfe8
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionNestedLoops.js
@@ -0,0 +1,38 @@
+//// [es5-asyncFunctionNestedLoops.ts]
+declare var x, y, z, a, b, c;
+
+async function nestedLoops() {
+    A: while (x) {
+        await y;
+        while (z) {
+            continue A;
+        }
+        while (a) {
+            continue;
+        }
+    }
+}
+
+//// [es5-asyncFunctionNestedLoops.js]
+function nestedLoops() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.sent();
+                    while (z) {
+                        return [3 /*break*/, 0];
+                    }
+                    while (a) {
+                        continue;
+                    }
+                    return [3 /*break*/, 0];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionNestedLoops.symbols b/tests/baselines/reference/es5-asyncFunctionNestedLoops.symbols
new file mode 100644
index 0000000000000..45d9cdc781b7f
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionNestedLoops.symbols
@@ -0,0 +1,30 @@
+=== tests/cases/compiler/es5-asyncFunctionNestedLoops.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionNestedLoops.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNestedLoops.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNestedLoops.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionNestedLoops.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionNestedLoops.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionNestedLoops.ts, 0, 26))
+
+async function nestedLoops() {
+>nestedLoops : Symbol(nestedLoops, Decl(es5-asyncFunctionNestedLoops.ts, 0, 29))
+
+    A: while (x) {
+>x : Symbol(x, Decl(es5-asyncFunctionNestedLoops.ts, 0, 11))
+
+        await y;
+>y : Symbol(y, Decl(es5-asyncFunctionNestedLoops.ts, 0, 14))
+
+        while (z) {
+>z : Symbol(z, Decl(es5-asyncFunctionNestedLoops.ts, 0, 17))
+
+            continue A;
+        }
+        while (a) {
+>a : Symbol(a, Decl(es5-asyncFunctionNestedLoops.ts, 0, 20))
+
+            continue;
+        }
+    }
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionNestedLoops.types b/tests/baselines/reference/es5-asyncFunctionNestedLoops.types
new file mode 100644
index 0000000000000..3a2913e65b190
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionNestedLoops.types
@@ -0,0 +1,33 @@
+=== tests/cases/compiler/es5-asyncFunctionNestedLoops.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function nestedLoops() {
+>nestedLoops : () => Promise<void>
+
+    A: while (x) {
+>A : any
+>x : any
+
+        await y;
+>await y : any
+>y : any
+
+        while (z) {
+>z : any
+
+            continue A;
+>A : any
+        }
+        while (a) {
+>a : any
+
+            continue;
+        }
+    }
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionNewExpressions.js b/tests/baselines/reference/es5-asyncFunctionNewExpressions.js
new file mode 100644
index 0000000000000..b7d4514d24ed0
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionNewExpressions.js
@@ -0,0 +1,386 @@
+//// [es5-asyncFunctionNewExpressions.ts]
+declare var x, y, z, a, b, c;
+
+async function newExpression0() {
+    await new x(y, z);
+}
+
+async function newExpression1() {
+    new (await x)(y, z);
+}
+
+async function newExpression2() {
+    new x(await y, z);
+}
+
+async function newExpression3() {
+    new x(y, await z);
+}
+
+async function newExpression4() {
+    await new x(...y, z);
+}
+
+async function newExpression5() {
+    new (await x)(...y, z);
+}
+
+async function newExpression6() {
+    new x(...(await y), z);
+}
+
+async function newExpression7() {
+    new x(...y, await z);
+}
+
+async function newExpression8() {
+    new x(await y, ...z);
+}
+
+async function newExpression9() {
+    new x(y, ...(await z));
+}
+
+async function newExpression10() {
+    await new x.a(y, z);
+}
+
+async function newExpression11() {
+    new (await x.a)(y, z);
+}
+
+async function newExpression12() {
+    new (await x).a(y, z);
+}
+
+async function newExpression13() {
+    new x.a(await y, z);
+}
+
+async function newExpression14() {
+    new x.a(y, await z);
+}
+
+async function newExpression15() {
+    await new x[a](y, z);
+}
+
+async function newExpression16() {
+    new (await x[a])(y, z);
+}
+
+async function newExpression17() {
+    new (await x)[a](y, z);
+}
+
+async function newExpression18() {
+    new x[await a](y, z);
+}
+
+async function newExpression19() {
+    new x[a](await y, z);
+}
+
+async function newExpression20() {
+    new x[a](y, await z);
+}
+
+//// [es5-asyncFunctionNewExpressions.js]
+function newExpression0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, new x(y, z)];
+                case 1:
+                    _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression1() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    new (_a.sent())(y, z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = x.bind;
+                    return [4 /*yield*/, y];
+                case 1:
+                    new (_a.apply(x, [_c.sent(), z]))();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression3() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = x.bind;
+                    _b = [y];
+                    return [4 /*yield*/, z];
+                case 1:
+                    new (_a.apply(x, _b.concat([_c.sent()])))();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression4() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, new (x.bind.apply(x, [void 0].concat(y, [z])))()];
+                case 1:
+                    _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression5() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    new ((_a = (_b.sent())).bind.apply(_a, [void 0].concat(y, [z])))();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression6() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c, _d, _e, _f;
+        return __generator(function (_g) {
+            switch (_g.label) {
+                case 0:
+                    _b = (_a = x.bind).apply;
+                    _c = [x];
+                    _e = (_d = [void 0]).concat;
+                    return [4 /*yield*/, y];
+                case 1:
+                    new (_b.apply(_a, _c.concat([_e.apply(_d, [(_g.sent()), [z]])])))();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression7() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c, _d, _e, _f, _g;
+        return __generator(function (_h) {
+            switch (_h.label) {
+                case 0:
+                    _b = (_a = x.bind).apply;
+                    _c = [x];
+                    _e = (_d = [void 0]).concat;
+                    _f = [y];
+                    return [4 /*yield*/, z];
+                case 1:
+                    new (_b.apply(_a, _c.concat([_e.apply(_d, _f.concat([[_h.sent()]]))])))();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression8() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c, _d;
+        return __generator(function (_e) {
+            switch (_e.label) {
+                case 0:
+                    _b = (_a = x.bind).apply;
+                    _c = [x];
+                    _d = [void 0];
+                    return [4 /*yield*/, y];
+                case 1:
+                    new (_b.apply(_a, _c.concat([_d.concat([_e.sent()]).concat(z)])))();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression9() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c, _d, _e, _f;
+        return __generator(function (_g) {
+            switch (_g.label) {
+                case 0:
+                    _b = (_a = x.bind).apply;
+                    _c = [x];
+                    _e = (_d = [void 0, y]).concat;
+                    return [4 /*yield*/, z];
+                case 1:
+                    new (_b.apply(_a, _c.concat([_e.apply(_d, [(_g.sent())])])))();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression10() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, new x.a(y, z)];
+                case 1:
+                    _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression11() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x.a];
+                case 1:
+                    new (_a.sent())(y, z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression12() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    new (_a.sent()).a(y, z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression13() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    _b = (_a = x.a).bind;
+                    return [4 /*yield*/, y];
+                case 1:
+                    new (_b.apply(_a, [_d.sent(), z]))();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression14() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    _b = (_a = x.a).bind;
+                    _c = [y];
+                    return [4 /*yield*/, z];
+                case 1:
+                    new (_b.apply(_a, _c.concat([_d.sent()])))();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression15() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, new x[a](y, z)];
+                case 1:
+                    _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression16() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x[a]];
+                case 1:
+                    new (_a.sent())(y, z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression17() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    new (_a.sent())[a](y, z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression18() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, a];
+                case 1:
+                    new _a[_b.sent()](y, z);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression19() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    _b = (_a = x[a]).bind;
+                    return [4 /*yield*/, y];
+                case 1:
+                    new (_b.apply(_a, [_d.sent(), z]))();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function newExpression20() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    _b = (_a = x[a]).bind;
+                    _c = [y];
+                    return [4 /*yield*/, z];
+                case 1:
+                    new (_b.apply(_a, _c.concat([_d.sent()])))();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionNewExpressions.symbols b/tests/baselines/reference/es5-asyncFunctionNewExpressions.symbols
new file mode 100644
index 0000000000000..19309bd19fe78
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionNewExpressions.symbols
@@ -0,0 +1,203 @@
+=== tests/cases/compiler/es5-asyncFunctionNewExpressions.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionNewExpressions.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionNewExpressions.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionNewExpressions.ts, 0, 26))
+
+async function newExpression0() {
+>newExpression0 : Symbol(newExpression0, Decl(es5-asyncFunctionNewExpressions.ts, 0, 29))
+
+    await new x(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression1() {
+>newExpression1 : Symbol(newExpression1, Decl(es5-asyncFunctionNewExpressions.ts, 4, 1))
+
+    new (await x)(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression2() {
+>newExpression2 : Symbol(newExpression2, Decl(es5-asyncFunctionNewExpressions.ts, 8, 1))
+
+    new x(await y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression3() {
+>newExpression3 : Symbol(newExpression3, Decl(es5-asyncFunctionNewExpressions.ts, 12, 1))
+
+    new x(y, await z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression4() {
+>newExpression4 : Symbol(newExpression4, Decl(es5-asyncFunctionNewExpressions.ts, 16, 1))
+
+    await new x(...y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression5() {
+>newExpression5 : Symbol(newExpression5, Decl(es5-asyncFunctionNewExpressions.ts, 20, 1))
+
+    new (await x)(...y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression6() {
+>newExpression6 : Symbol(newExpression6, Decl(es5-asyncFunctionNewExpressions.ts, 24, 1))
+
+    new x(...(await y), z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression7() {
+>newExpression7 : Symbol(newExpression7, Decl(es5-asyncFunctionNewExpressions.ts, 28, 1))
+
+    new x(...y, await z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression8() {
+>newExpression8 : Symbol(newExpression8, Decl(es5-asyncFunctionNewExpressions.ts, 32, 1))
+
+    new x(await y, ...z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression9() {
+>newExpression9 : Symbol(newExpression9, Decl(es5-asyncFunctionNewExpressions.ts, 36, 1))
+
+    new x(y, ...(await z));
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression10() {
+>newExpression10 : Symbol(newExpression10, Decl(es5-asyncFunctionNewExpressions.ts, 40, 1))
+
+    await new x.a(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression11() {
+>newExpression11 : Symbol(newExpression11, Decl(es5-asyncFunctionNewExpressions.ts, 44, 1))
+
+    new (await x.a)(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression12() {
+>newExpression12 : Symbol(newExpression12, Decl(es5-asyncFunctionNewExpressions.ts, 48, 1))
+
+    new (await x).a(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression13() {
+>newExpression13 : Symbol(newExpression13, Decl(es5-asyncFunctionNewExpressions.ts, 52, 1))
+
+    new x.a(await y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression14() {
+>newExpression14 : Symbol(newExpression14, Decl(es5-asyncFunctionNewExpressions.ts, 56, 1))
+
+    new x.a(y, await z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression15() {
+>newExpression15 : Symbol(newExpression15, Decl(es5-asyncFunctionNewExpressions.ts, 60, 1))
+
+    await new x[a](y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionNewExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression16() {
+>newExpression16 : Symbol(newExpression16, Decl(es5-asyncFunctionNewExpressions.ts, 64, 1))
+
+    new (await x[a])(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionNewExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression17() {
+>newExpression17 : Symbol(newExpression17, Decl(es5-asyncFunctionNewExpressions.ts, 68, 1))
+
+    new (await x)[a](y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionNewExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression18() {
+>newExpression18 : Symbol(newExpression18, Decl(es5-asyncFunctionNewExpressions.ts, 72, 1))
+
+    new x[await a](y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionNewExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression19() {
+>newExpression19 : Symbol(newExpression19, Decl(es5-asyncFunctionNewExpressions.ts, 76, 1))
+
+    new x[a](await y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionNewExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
+
+async function newExpression20() {
+>newExpression20 : Symbol(newExpression20, Decl(es5-asyncFunctionNewExpressions.ts, 80, 1))
+
+    new x[a](y, await z);
+>x : Symbol(x, Decl(es5-asyncFunctionNewExpressions.ts, 0, 11))
+>a : Symbol(a, Decl(es5-asyncFunctionNewExpressions.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionNewExpressions.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionNewExpressions.ts, 0, 17))
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionNewExpressions.types b/tests/baselines/reference/es5-asyncFunctionNewExpressions.types
new file mode 100644
index 0000000000000..c6390430380a4
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionNewExpressions.types
@@ -0,0 +1,275 @@
+=== tests/cases/compiler/es5-asyncFunctionNewExpressions.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function newExpression0() {
+>newExpression0 : () => Promise<void>
+
+    await new x(y, z);
+>await new x(y, z) : any
+>new x(y, z) : any
+>x : any
+>y : any
+>z : any
+}
+
+async function newExpression1() {
+>newExpression1 : () => Promise<void>
+
+    new (await x)(y, z);
+>new (await x)(y, z) : any
+>(await x) : any
+>await x : any
+>x : any
+>y : any
+>z : any
+}
+
+async function newExpression2() {
+>newExpression2 : () => Promise<void>
+
+    new x(await y, z);
+>new x(await y, z) : any
+>x : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function newExpression3() {
+>newExpression3 : () => Promise<void>
+
+    new x(y, await z);
+>new x(y, await z) : any
+>x : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function newExpression4() {
+>newExpression4 : () => Promise<void>
+
+    await new x(...y, z);
+>await new x(...y, z) : any
+>new x(...y, z) : any
+>x : any
+>...y : any
+>y : any
+>z : any
+}
+
+async function newExpression5() {
+>newExpression5 : () => Promise<void>
+
+    new (await x)(...y, z);
+>new (await x)(...y, z) : any
+>(await x) : any
+>await x : any
+>x : any
+>...y : any
+>y : any
+>z : any
+}
+
+async function newExpression6() {
+>newExpression6 : () => Promise<void>
+
+    new x(...(await y), z);
+>new x(...(await y), z) : any
+>x : any
+>...(await y) : any
+>(await y) : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function newExpression7() {
+>newExpression7 : () => Promise<void>
+
+    new x(...y, await z);
+>new x(...y, await z) : any
+>x : any
+>...y : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function newExpression8() {
+>newExpression8 : () => Promise<void>
+
+    new x(await y, ...z);
+>new x(await y, ...z) : any
+>x : any
+>await y : any
+>y : any
+>...z : any
+>z : any
+}
+
+async function newExpression9() {
+>newExpression9 : () => Promise<void>
+
+    new x(y, ...(await z));
+>new x(y, ...(await z)) : any
+>x : any
+>y : any
+>...(await z) : any
+>(await z) : any
+>await z : any
+>z : any
+}
+
+async function newExpression10() {
+>newExpression10 : () => Promise<void>
+
+    await new x.a(y, z);
+>await new x.a(y, z) : any
+>new x.a(y, z) : any
+>x.a : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function newExpression11() {
+>newExpression11 : () => Promise<void>
+
+    new (await x.a)(y, z);
+>new (await x.a)(y, z) : any
+>(await x.a) : any
+>await x.a : any
+>x.a : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function newExpression12() {
+>newExpression12 : () => Promise<void>
+
+    new (await x).a(y, z);
+>new (await x).a(y, z) : any
+>(await x).a : any
+>(await x) : any
+>await x : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function newExpression13() {
+>newExpression13 : () => Promise<void>
+
+    new x.a(await y, z);
+>new x.a(await y, z) : any
+>x.a : any
+>x : any
+>a : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function newExpression14() {
+>newExpression14 : () => Promise<void>
+
+    new x.a(y, await z);
+>new x.a(y, await z) : any
+>x.a : any
+>x : any
+>a : any
+>y : any
+>await z : any
+>z : any
+}
+
+async function newExpression15() {
+>newExpression15 : () => Promise<void>
+
+    await new x[a](y, z);
+>await new x[a](y, z) : any
+>new x[a](y, z) : any
+>x[a] : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function newExpression16() {
+>newExpression16 : () => Promise<void>
+
+    new (await x[a])(y, z);
+>new (await x[a])(y, z) : any
+>(await x[a]) : any
+>await x[a] : any
+>x[a] : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function newExpression17() {
+>newExpression17 : () => Promise<void>
+
+    new (await x)[a](y, z);
+>new (await x)[a](y, z) : any
+>(await x)[a] : any
+>(await x) : any
+>await x : any
+>x : any
+>a : any
+>y : any
+>z : any
+}
+
+async function newExpression18() {
+>newExpression18 : () => Promise<void>
+
+    new x[await a](y, z);
+>new x[await a](y, z) : any
+>x[await a] : any
+>x : any
+>await a : any
+>a : any
+>y : any
+>z : any
+}
+
+async function newExpression19() {
+>newExpression19 : () => Promise<void>
+
+    new x[a](await y, z);
+>new x[a](await y, z) : any
+>x[a] : any
+>x : any
+>a : any
+>await y : any
+>y : any
+>z : any
+}
+
+async function newExpression20() {
+>newExpression20 : () => Promise<void>
+
+    new x[a](y, await z);
+>new x[a](y, await z) : any
+>x[a] : any
+>x : any
+>a : any
+>y : any
+>await z : any
+>z : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionObjectLiterals.js b/tests/baselines/reference/es5-asyncFunctionObjectLiterals.js
new file mode 100644
index 0000000000000..1c5d1fcd23b8c
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionObjectLiterals.js
@@ -0,0 +1,177 @@
+//// [es5-asyncFunctionObjectLiterals.ts]
+declare var x, y, z, a, b, c;
+
+async function objectLiteral0() {
+    x = {
+        a: await y,
+        b: z
+    };
+}
+
+async function objectLiteral1() {
+    x = {
+        a: y,
+        b: await z
+    };
+}
+
+async function objectLiteral2() {
+    x = {
+        [await a]: y,
+        b: z
+    };
+}
+
+async function objectLiteral3() {
+    x = {
+        [a]: await y,
+        b: z
+    };
+}
+
+async function objectLiteral4() {
+    x = {
+        a: await y,
+        [b]: z
+    };
+}
+
+async function objectLiteral5() {
+    x = {
+        a: y,
+        [await b]: z
+    };
+}
+
+async function objectLiteral6() {
+    x = {
+        a: y,
+        [b]: await z
+    };
+}
+
+//// [es5-asyncFunctionObjectLiterals.js]
+function objectLiteral0() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = {};
+                    return [4 /*yield*/, y];
+                case 1:
+                    x = (_a.a = _b.sent(),
+                        _a.b = z,
+                        _a);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function objectLiteral1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = {
+                        a: y
+                    };
+                    return [4 /*yield*/, z];
+                case 1:
+                    x = (_a.b = _b.sent(),
+                        _a);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function objectLiteral2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = {};
+                    return [4 /*yield*/, a];
+                case 1:
+                    x = (_a[_b.sent()] = y,
+                        _a.b = z,
+                        _a);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function objectLiteral3() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _b = {};
+                    _a = a;
+                    return [4 /*yield*/, y];
+                case 1:
+                    x = (_b[_a] = _c.sent(),
+                        _b.b = z,
+                        _b);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function objectLiteral4() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = {};
+                    return [4 /*yield*/, y];
+                case 1:
+                    x = (_a.a = _b.sent(),
+                        _a[b] = z,
+                        _a);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function objectLiteral5() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = {
+                            a: y
+                        };
+                    return [4 /*yield*/, b];
+                case 1:
+                    x = (_a[_b.sent()] = z,
+                        _a);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function objectLiteral6() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _b = {
+                            a: y
+                        };
+                    _a = b;
+                    return [4 /*yield*/, z];
+                case 1:
+                    x = (_b[_a] = _c.sent(),
+                        _b);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionObjectLiterals.symbols b/tests/baselines/reference/es5-asyncFunctionObjectLiterals.symbols
new file mode 100644
index 0000000000000..dd84a5c11f4da
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionObjectLiterals.symbols
@@ -0,0 +1,127 @@
+=== tests/cases/compiler/es5-asyncFunctionObjectLiterals.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 26))
+
+async function objectLiteral0() {
+>objectLiteral0 : Symbol(objectLiteral0, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 29))
+
+    x = {
+>x : Symbol(x, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 11))
+
+        a: await y,
+>a : Symbol(a, Decl(es5-asyncFunctionObjectLiterals.ts, 3, 9))
+>y : Symbol(y, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 14))
+
+        b: z
+>b : Symbol(b, Decl(es5-asyncFunctionObjectLiterals.ts, 4, 19))
+>z : Symbol(z, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 17))
+
+    };
+}
+
+async function objectLiteral1() {
+>objectLiteral1 : Symbol(objectLiteral1, Decl(es5-asyncFunctionObjectLiterals.ts, 7, 1))
+
+    x = {
+>x : Symbol(x, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 11))
+
+        a: y,
+>a : Symbol(a, Decl(es5-asyncFunctionObjectLiterals.ts, 10, 9))
+>y : Symbol(y, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 14))
+
+        b: await z
+>b : Symbol(b, Decl(es5-asyncFunctionObjectLiterals.ts, 11, 13))
+>z : Symbol(z, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 17))
+
+    };
+}
+
+async function objectLiteral2() {
+>objectLiteral2 : Symbol(objectLiteral2, Decl(es5-asyncFunctionObjectLiterals.ts, 14, 1))
+
+    x = {
+>x : Symbol(x, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 11))
+
+        [await a]: y,
+>a : Symbol(a, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 14))
+
+        b: z
+>b : Symbol(b, Decl(es5-asyncFunctionObjectLiterals.ts, 18, 21))
+>z : Symbol(z, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 17))
+
+    };
+}
+
+async function objectLiteral3() {
+>objectLiteral3 : Symbol(objectLiteral3, Decl(es5-asyncFunctionObjectLiterals.ts, 21, 1))
+
+    x = {
+>x : Symbol(x, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 11))
+
+        [a]: await y,
+>a : Symbol(a, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 20))
+>y : Symbol(y, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 14))
+
+        b: z
+>b : Symbol(b, Decl(es5-asyncFunctionObjectLiterals.ts, 25, 21))
+>z : Symbol(z, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 17))
+
+    };
+}
+
+async function objectLiteral4() {
+>objectLiteral4 : Symbol(objectLiteral4, Decl(es5-asyncFunctionObjectLiterals.ts, 28, 1))
+
+    x = {
+>x : Symbol(x, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 11))
+
+        a: await y,
+>a : Symbol(a, Decl(es5-asyncFunctionObjectLiterals.ts, 31, 9))
+>y : Symbol(y, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 14))
+
+        [b]: z
+>b : Symbol(b, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 23))
+>z : Symbol(z, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 17))
+
+    };
+}
+
+async function objectLiteral5() {
+>objectLiteral5 : Symbol(objectLiteral5, Decl(es5-asyncFunctionObjectLiterals.ts, 35, 1))
+
+    x = {
+>x : Symbol(x, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 11))
+
+        a: y,
+>a : Symbol(a, Decl(es5-asyncFunctionObjectLiterals.ts, 38, 9))
+>y : Symbol(y, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 14))
+
+        [await b]: z
+>b : Symbol(b, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 23))
+>z : Symbol(z, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 17))
+
+    };
+}
+
+async function objectLiteral6() {
+>objectLiteral6 : Symbol(objectLiteral6, Decl(es5-asyncFunctionObjectLiterals.ts, 42, 1))
+
+    x = {
+>x : Symbol(x, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 11))
+
+        a: y,
+>a : Symbol(a, Decl(es5-asyncFunctionObjectLiterals.ts, 45, 9))
+>y : Symbol(y, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 14))
+
+        [b]: await z
+>b : Symbol(b, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 23))
+>z : Symbol(z, Decl(es5-asyncFunctionObjectLiterals.ts, 0, 17))
+
+    };
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionObjectLiterals.types b/tests/baselines/reference/es5-asyncFunctionObjectLiterals.types
new file mode 100644
index 0000000000000..d37dd8a6cebd0
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionObjectLiterals.types
@@ -0,0 +1,148 @@
+=== tests/cases/compiler/es5-asyncFunctionObjectLiterals.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function objectLiteral0() {
+>objectLiteral0 : () => Promise<void>
+
+    x = {
+>x = {        a: await y,        b: z    } : { a: any; b: any; }
+>x : any
+>{        a: await y,        b: z    } : { a: any; b: any; }
+
+        a: await y,
+>a : any
+>await y : any
+>y : any
+
+        b: z
+>b : any
+>z : any
+
+    };
+}
+
+async function objectLiteral1() {
+>objectLiteral1 : () => Promise<void>
+
+    x = {
+>x = {        a: y,        b: await z    } : { a: any; b: any; }
+>x : any
+>{        a: y,        b: await z    } : { a: any; b: any; }
+
+        a: y,
+>a : any
+>y : any
+
+        b: await z
+>b : any
+>await z : any
+>z : any
+
+    };
+}
+
+async function objectLiteral2() {
+>objectLiteral2 : () => Promise<void>
+
+    x = {
+>x = {        [await a]: y,        b: z    } : { [x: number]: any; b: any; }
+>x : any
+>{        [await a]: y,        b: z    } : { [x: number]: any; b: any; }
+
+        [await a]: y,
+>await a : any
+>a : any
+>y : any
+
+        b: z
+>b : any
+>z : any
+
+    };
+}
+
+async function objectLiteral3() {
+>objectLiteral3 : () => Promise<void>
+
+    x = {
+>x = {        [a]: await y,        b: z    } : { [x: number]: any; b: any; }
+>x : any
+>{        [a]: await y,        b: z    } : { [x: number]: any; b: any; }
+
+        [a]: await y,
+>a : any
+>await y : any
+>y : any
+
+        b: z
+>b : any
+>z : any
+
+    };
+}
+
+async function objectLiteral4() {
+>objectLiteral4 : () => Promise<void>
+
+    x = {
+>x = {        a: await y,        [b]: z    } : { [x: number]: any; a: any; }
+>x : any
+>{        a: await y,        [b]: z    } : { [x: number]: any; a: any; }
+
+        a: await y,
+>a : any
+>await y : any
+>y : any
+
+        [b]: z
+>b : any
+>z : any
+
+    };
+}
+
+async function objectLiteral5() {
+>objectLiteral5 : () => Promise<void>
+
+    x = {
+>x = {        a: y,        [await b]: z    } : { [x: number]: any; a: any; }
+>x : any
+>{        a: y,        [await b]: z    } : { [x: number]: any; a: any; }
+
+        a: y,
+>a : any
+>y : any
+
+        [await b]: z
+>await b : any
+>b : any
+>z : any
+
+    };
+}
+
+async function objectLiteral6() {
+>objectLiteral6 : () => Promise<void>
+
+    x = {
+>x = {        a: y,        [b]: await z    } : { [x: number]: any; a: any; }
+>x : any
+>{        a: y,        [b]: await z    } : { [x: number]: any; a: any; }
+
+        a: y,
+>a : any
+>y : any
+
+        [b]: await z
+>b : any
+>await z : any
+>z : any
+
+    };
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionPropertyAccess.js b/tests/baselines/reference/es5-asyncFunctionPropertyAccess.js
new file mode 100644
index 0000000000000..47110ff11bcb4
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionPropertyAccess.js
@@ -0,0 +1,52 @@
+//// [es5-asyncFunctionPropertyAccess.ts]
+declare var x, y, z, a, b, c;
+
+async function propertyAccess0() {
+    y = await x.a;
+}
+
+async function propertyAccess1() {
+    y = (await x).a;
+}
+
+async function callExpression0() {
+    await x(y, z);
+}
+
+//// [es5-asyncFunctionPropertyAccess.js]
+function propertyAccess0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x.a];
+                case 1:
+                    y = _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function propertyAccess1() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    y = (_a.sent()).a;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function callExpression0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x(y, z)];
+                case 1:
+                    _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionPropertyAccess.symbols b/tests/baselines/reference/es5-asyncFunctionPropertyAccess.symbols
new file mode 100644
index 0000000000000..22f7bcc95464b
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionPropertyAccess.symbols
@@ -0,0 +1,33 @@
+=== tests/cases/compiler/es5-asyncFunctionPropertyAccess.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 26))
+
+async function propertyAccess0() {
+>propertyAccess0 : Symbol(propertyAccess0, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 29))
+
+    y = await x.a;
+>y : Symbol(y, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 14))
+>x : Symbol(x, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 11))
+}
+
+async function propertyAccess1() {
+>propertyAccess1 : Symbol(propertyAccess1, Decl(es5-asyncFunctionPropertyAccess.ts, 4, 1))
+
+    y = (await x).a;
+>y : Symbol(y, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 14))
+>x : Symbol(x, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 11))
+}
+
+async function callExpression0() {
+>callExpression0 : Symbol(callExpression0, Decl(es5-asyncFunctionPropertyAccess.ts, 8, 1))
+
+    await x(y, z);
+>x : Symbol(x, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionPropertyAccess.ts, 0, 17))
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionPropertyAccess.types b/tests/baselines/reference/es5-asyncFunctionPropertyAccess.types
new file mode 100644
index 0000000000000..a6f7980e8ba07
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionPropertyAccess.types
@@ -0,0 +1,44 @@
+=== tests/cases/compiler/es5-asyncFunctionPropertyAccess.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function propertyAccess0() {
+>propertyAccess0 : () => Promise<void>
+
+    y = await x.a;
+>y = await x.a : any
+>y : any
+>await x.a : any
+>x.a : any
+>x : any
+>a : any
+}
+
+async function propertyAccess1() {
+>propertyAccess1 : () => Promise<void>
+
+    y = (await x).a;
+>y = (await x).a : any
+>y : any
+>(await x).a : any
+>(await x) : any
+>await x : any
+>x : any
+>a : any
+}
+
+async function callExpression0() {
+>callExpression0 : () => Promise<void>
+
+    await x(y, z);
+>await x(y, z) : any
+>x(y, z) : any
+>x : any
+>y : any
+>z : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionReturnStatements.js b/tests/baselines/reference/es5-asyncFunctionReturnStatements.js
new file mode 100644
index 0000000000000..df279f3680d73
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionReturnStatements.js
@@ -0,0 +1,88 @@
+//// [es5-asyncFunctionReturnStatements.ts]
+declare var x, y, z, a, b, c;
+
+async function returnStatement0(): Promise<any> {
+    return;
+}
+
+async function returnStatement1(): Promise<any> {
+    return x;
+}
+
+async function returnStatement2(): Promise<any> {
+    return await x;
+}
+
+async function returnStatement3(): Promise<any> {
+    { return; }
+}
+
+async function returnStatement4(): Promise<any> {
+    await x;
+    { return; }
+}
+
+async function returnStatement5(): Promise<any>{
+    { return await x; }
+}
+
+//// [es5-asyncFunctionReturnStatements.js]
+function returnStatement0() {
+    return __awaiter(this, void 0, Promise, function () {
+        return __generator(function (_a) {
+            return [2 /*return*/];
+        });
+    });
+}
+function returnStatement1() {
+    return __awaiter(this, void 0, Promise, function () {
+        return __generator(function (_a) {
+            return [2 /*return*/, x];
+        });
+    });
+}
+function returnStatement2() {
+    return __awaiter(this, void 0, Promise, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1: return [2 /*return*/, _a.sent()];
+            }
+        });
+    });
+}
+function returnStatement3() {
+    return __awaiter(this, void 0, Promise, function () {
+        return __generator(function (_a) {
+            {
+                return [2 /*return*/];
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function returnStatement4() {
+    return __awaiter(this, void 0, Promise, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    {
+                        return [2 /*return*/];
+                    }
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function returnStatement5() {
+    return __awaiter(this, void 0, Promise, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1: return [2 /*return*/, _a.sent()];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionReturnStatements.symbols b/tests/baselines/reference/es5-asyncFunctionReturnStatements.symbols
new file mode 100644
index 0000000000000..651af244e70d4
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionReturnStatements.symbols
@@ -0,0 +1,56 @@
+=== tests/cases/compiler/es5-asyncFunctionReturnStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionReturnStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionReturnStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionReturnStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionReturnStatements.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionReturnStatements.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionReturnStatements.ts, 0, 26))
+
+async function returnStatement0(): Promise<any> {
+>returnStatement0 : Symbol(returnStatement0, Decl(es5-asyncFunctionReturnStatements.ts, 0, 29))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    return;
+}
+
+async function returnStatement1(): Promise<any> {
+>returnStatement1 : Symbol(returnStatement1, Decl(es5-asyncFunctionReturnStatements.ts, 4, 1))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    return x;
+>x : Symbol(x, Decl(es5-asyncFunctionReturnStatements.ts, 0, 11))
+}
+
+async function returnStatement2(): Promise<any> {
+>returnStatement2 : Symbol(returnStatement2, Decl(es5-asyncFunctionReturnStatements.ts, 8, 1))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    return await x;
+>x : Symbol(x, Decl(es5-asyncFunctionReturnStatements.ts, 0, 11))
+}
+
+async function returnStatement3(): Promise<any> {
+>returnStatement3 : Symbol(returnStatement3, Decl(es5-asyncFunctionReturnStatements.ts, 12, 1))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    { return; }
+}
+
+async function returnStatement4(): Promise<any> {
+>returnStatement4 : Symbol(returnStatement4, Decl(es5-asyncFunctionReturnStatements.ts, 16, 1))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    await x;
+>x : Symbol(x, Decl(es5-asyncFunctionReturnStatements.ts, 0, 11))
+
+    { return; }
+}
+
+async function returnStatement5(): Promise<any>{
+>returnStatement5 : Symbol(returnStatement5, Decl(es5-asyncFunctionReturnStatements.ts, 21, 1))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    { return await x; }
+>x : Symbol(x, Decl(es5-asyncFunctionReturnStatements.ts, 0, 11))
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionReturnStatements.types b/tests/baselines/reference/es5-asyncFunctionReturnStatements.types
new file mode 100644
index 0000000000000..486bc5c55664f
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionReturnStatements.types
@@ -0,0 +1,59 @@
+=== tests/cases/compiler/es5-asyncFunctionReturnStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function returnStatement0(): Promise<any> {
+>returnStatement0 : () => Promise<any>
+>Promise : Promise<T>
+
+    return;
+}
+
+async function returnStatement1(): Promise<any> {
+>returnStatement1 : () => Promise<any>
+>Promise : Promise<T>
+
+    return x;
+>x : any
+}
+
+async function returnStatement2(): Promise<any> {
+>returnStatement2 : () => Promise<any>
+>Promise : Promise<T>
+
+    return await x;
+>await x : any
+>x : any
+}
+
+async function returnStatement3(): Promise<any> {
+>returnStatement3 : () => Promise<any>
+>Promise : Promise<T>
+
+    { return; }
+}
+
+async function returnStatement4(): Promise<any> {
+>returnStatement4 : () => Promise<any>
+>Promise : Promise<T>
+
+    await x;
+>await x : any
+>x : any
+
+    { return; }
+}
+
+async function returnStatement5(): Promise<any>{
+>returnStatement5 : () => Promise<any>
+>Promise : Promise<T>
+
+    { return await x; }
+>await x : any
+>x : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionSwitchStatements.js b/tests/baselines/reference/es5-asyncFunctionSwitchStatements.js
new file mode 100644
index 0000000000000..7c6da63dfe4f7
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionSwitchStatements.js
@@ -0,0 +1,289 @@
+//// [es5-asyncFunctionSwitchStatements.ts]
+declare var x, y, z, a, b, c;
+
+async function switchStatement0() {
+    switch (x) {
+        case y: a; break;
+        default: b; break;
+    }
+}
+
+async function switchStatement1() {
+    switch (await x) {
+        case y: a; break;
+        default: b; break;
+    }
+}
+
+async function switchStatement2() {
+    switch (x) {
+        case await y: a; break;
+        default: b; break;
+    }
+}
+
+async function switchStatement3() {
+    switch (x) {
+        case y: await a; break;
+        default: b; break;
+    }
+}
+
+async function switchStatement4() {
+    switch (x) {
+        case y: a; break;
+        default: await b; break;
+    }
+}
+
+async function switchStatement5() {
+    switch (x) {
+        case y: a; break;
+        case await z: b; break;
+    }
+}
+
+async function switchStatement6() {
+    switch (x) {
+        default: c; break;
+        case await y: a; break;
+        case z: b; break;
+    }
+}
+
+async function switchStatement7() {
+    switch (x) {
+        default: c; break;
+        case y: a; break;
+        case await z: b; break;
+    }
+}
+
+async function switchStatement8() {
+    switch (x) {
+        default: c;
+        case y: a; break;
+        case await z: b; break;
+    }
+}
+
+//// [es5-asyncFunctionSwitchStatements.js]
+function switchStatement0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (x) {
+                case y:
+                    a;
+                    break;
+                default:
+                    b;
+                    break;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function switchStatement1() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    switch (_a.sent()) {
+                        case y:
+                            a;
+                            break;
+                        default:
+                            b;
+                            break;
+                    }
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
+function switchStatement2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, y];
+                case 1:
+                    switch (_a) {
+                        case _b.sent(): return [3 /*break*/, 2];
+                    }
+                    return [3 /*break*/, 3];
+                case 2:
+                    a;
+                    return [3 /*break*/, 4];
+                case 3:
+                    b;
+                    return [3 /*break*/, 4];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function switchStatement3() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    switch (_a) {
+                        case y: return [3 /*break*/, 1];
+                    }
+                    return [3 /*break*/, 3];
+                case 1: return [4 /*yield*/, a];
+                case 2:
+                    _b.sent();
+                    return [3 /*break*/, 4];
+                case 3:
+                    b;
+                    return [3 /*break*/, 4];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function switchStatement4() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    switch (_a) {
+                        case y: return [3 /*break*/, 1];
+                    }
+                    return [3 /*break*/, 2];
+                case 1:
+                    a;
+                    return [3 /*break*/, 4];
+                case 2: return [4 /*yield*/, b];
+                case 3:
+                    _b.sent();
+                    return [3 /*break*/, 4];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function switchStatement5() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    switch (_a) {
+                        case y: return [3 /*break*/, 2];
+                    }
+                    return [4 /*yield*/, z];
+                case 1:
+                    switch (_a) {
+                        case _b.sent(): return [3 /*break*/, 3];
+                    }
+                    return [3 /*break*/, 4];
+                case 2:
+                    a;
+                    return [3 /*break*/, 4];
+                case 3:
+                    b;
+                    return [3 /*break*/, 4];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function switchStatement6() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    return [4 /*yield*/, y];
+                case 1:
+                    switch (_a) {
+                        case _b.sent(): return [3 /*break*/, 3];
+                        case z: return [3 /*break*/, 4];
+                    }
+                    return [3 /*break*/, 2];
+                case 2:
+                    c;
+                    return [3 /*break*/, 5];
+                case 3:
+                    a;
+                    return [3 /*break*/, 5];
+                case 4:
+                    b;
+                    return [3 /*break*/, 5];
+                case 5: return [2 /*return*/];
+            }
+        });
+    });
+}
+function switchStatement7() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    switch (_a) {
+                        case y: return [3 /*break*/, 3];
+                    }
+                    return [4 /*yield*/, z];
+                case 1:
+                    switch (_a) {
+                        case _b.sent(): return [3 /*break*/, 4];
+                    }
+                    return [3 /*break*/, 2];
+                case 2:
+                    c;
+                    return [3 /*break*/, 5];
+                case 3:
+                    a;
+                    return [3 /*break*/, 5];
+                case 4:
+                    b;
+                    return [3 /*break*/, 5];
+                case 5: return [2 /*return*/];
+            }
+        });
+    });
+}
+function switchStatement8() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    switch (_a) {
+                        case y: return [3 /*break*/, 3];
+                    }
+                    return [4 /*yield*/, z];
+                case 1:
+                    switch (_a) {
+                        case _b.sent(): return [3 /*break*/, 4];
+                    }
+                    return [3 /*break*/, 2];
+                case 2:
+                    c;
+                    _b.label = 3;
+                case 3:
+                    a;
+                    return [3 /*break*/, 5];
+                case 4:
+                    b;
+                    return [3 /*break*/, 5];
+                case 5: return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionSwitchStatements.symbols b/tests/baselines/reference/es5-asyncFunctionSwitchStatements.symbols
new file mode 100644
index 0000000000000..668339af57683
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionSwitchStatements.symbols
@@ -0,0 +1,156 @@
+=== tests/cases/compiler/es5-asyncFunctionSwitchStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 26))
+
+async function switchStatement0() {
+>switchStatement0 : Symbol(switchStatement0, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 29))
+
+    switch (x) {
+>x : Symbol(x, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 11))
+
+        case y: a; break;
+>y : Symbol(y, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 14))
+>a : Symbol(a, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 20))
+
+        default: b; break;
+>b : Symbol(b, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 23))
+    }
+}
+
+async function switchStatement1() {
+>switchStatement1 : Symbol(switchStatement1, Decl(es5-asyncFunctionSwitchStatements.ts, 7, 1))
+
+    switch (await x) {
+>x : Symbol(x, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 11))
+
+        case y: a; break;
+>y : Symbol(y, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 14))
+>a : Symbol(a, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 20))
+
+        default: b; break;
+>b : Symbol(b, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 23))
+    }
+}
+
+async function switchStatement2() {
+>switchStatement2 : Symbol(switchStatement2, Decl(es5-asyncFunctionSwitchStatements.ts, 14, 1))
+
+    switch (x) {
+>x : Symbol(x, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 11))
+
+        case await y: a; break;
+>y : Symbol(y, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 14))
+>a : Symbol(a, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 20))
+
+        default: b; break;
+>b : Symbol(b, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 23))
+    }
+}
+
+async function switchStatement3() {
+>switchStatement3 : Symbol(switchStatement3, Decl(es5-asyncFunctionSwitchStatements.ts, 21, 1))
+
+    switch (x) {
+>x : Symbol(x, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 11))
+
+        case y: await a; break;
+>y : Symbol(y, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 14))
+>a : Symbol(a, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 20))
+
+        default: b; break;
+>b : Symbol(b, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 23))
+    }
+}
+
+async function switchStatement4() {
+>switchStatement4 : Symbol(switchStatement4, Decl(es5-asyncFunctionSwitchStatements.ts, 28, 1))
+
+    switch (x) {
+>x : Symbol(x, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 11))
+
+        case y: a; break;
+>y : Symbol(y, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 14))
+>a : Symbol(a, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 20))
+
+        default: await b; break;
+>b : Symbol(b, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 23))
+    }
+}
+
+async function switchStatement5() {
+>switchStatement5 : Symbol(switchStatement5, Decl(es5-asyncFunctionSwitchStatements.ts, 35, 1))
+
+    switch (x) {
+>x : Symbol(x, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 11))
+
+        case y: a; break;
+>y : Symbol(y, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 14))
+>a : Symbol(a, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 20))
+
+        case await z: b; break;
+>z : Symbol(z, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 17))
+>b : Symbol(b, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 23))
+    }
+}
+
+async function switchStatement6() {
+>switchStatement6 : Symbol(switchStatement6, Decl(es5-asyncFunctionSwitchStatements.ts, 42, 1))
+
+    switch (x) {
+>x : Symbol(x, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 11))
+
+        default: c; break;
+>c : Symbol(c, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 26))
+
+        case await y: a; break;
+>y : Symbol(y, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 14))
+>a : Symbol(a, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 20))
+
+        case z: b; break;
+>z : Symbol(z, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 17))
+>b : Symbol(b, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 23))
+    }
+}
+
+async function switchStatement7() {
+>switchStatement7 : Symbol(switchStatement7, Decl(es5-asyncFunctionSwitchStatements.ts, 50, 1))
+
+    switch (x) {
+>x : Symbol(x, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 11))
+
+        default: c; break;
+>c : Symbol(c, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 26))
+
+        case y: a; break;
+>y : Symbol(y, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 14))
+>a : Symbol(a, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 20))
+
+        case await z: b; break;
+>z : Symbol(z, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 17))
+>b : Symbol(b, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 23))
+    }
+}
+
+async function switchStatement8() {
+>switchStatement8 : Symbol(switchStatement8, Decl(es5-asyncFunctionSwitchStatements.ts, 58, 1))
+
+    switch (x) {
+>x : Symbol(x, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 11))
+
+        default: c;
+>c : Symbol(c, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 26))
+
+        case y: a; break;
+>y : Symbol(y, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 14))
+>a : Symbol(a, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 20))
+
+        case await z: b; break;
+>z : Symbol(z, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 17))
+>b : Symbol(b, Decl(es5-asyncFunctionSwitchStatements.ts, 0, 23))
+    }
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionSwitchStatements.types b/tests/baselines/reference/es5-asyncFunctionSwitchStatements.types
new file mode 100644
index 0000000000000..694e7cdc89de3
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionSwitchStatements.types
@@ -0,0 +1,164 @@
+=== tests/cases/compiler/es5-asyncFunctionSwitchStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function switchStatement0() {
+>switchStatement0 : () => Promise<void>
+
+    switch (x) {
+>x : any
+
+        case y: a; break;
+>y : any
+>a : any
+
+        default: b; break;
+>b : any
+    }
+}
+
+async function switchStatement1() {
+>switchStatement1 : () => Promise<void>
+
+    switch (await x) {
+>await x : any
+>x : any
+
+        case y: a; break;
+>y : any
+>a : any
+
+        default: b; break;
+>b : any
+    }
+}
+
+async function switchStatement2() {
+>switchStatement2 : () => Promise<void>
+
+    switch (x) {
+>x : any
+
+        case await y: a; break;
+>await y : any
+>y : any
+>a : any
+
+        default: b; break;
+>b : any
+    }
+}
+
+async function switchStatement3() {
+>switchStatement3 : () => Promise<void>
+
+    switch (x) {
+>x : any
+
+        case y: await a; break;
+>y : any
+>await a : any
+>a : any
+
+        default: b; break;
+>b : any
+    }
+}
+
+async function switchStatement4() {
+>switchStatement4 : () => Promise<void>
+
+    switch (x) {
+>x : any
+
+        case y: a; break;
+>y : any
+>a : any
+
+        default: await b; break;
+>await b : any
+>b : any
+    }
+}
+
+async function switchStatement5() {
+>switchStatement5 : () => Promise<void>
+
+    switch (x) {
+>x : any
+
+        case y: a; break;
+>y : any
+>a : any
+
+        case await z: b; break;
+>await z : any
+>z : any
+>b : any
+    }
+}
+
+async function switchStatement6() {
+>switchStatement6 : () => Promise<void>
+
+    switch (x) {
+>x : any
+
+        default: c; break;
+>c : any
+
+        case await y: a; break;
+>await y : any
+>y : any
+>a : any
+
+        case z: b; break;
+>z : any
+>b : any
+    }
+}
+
+async function switchStatement7() {
+>switchStatement7 : () => Promise<void>
+
+    switch (x) {
+>x : any
+
+        default: c; break;
+>c : any
+
+        case y: a; break;
+>y : any
+>a : any
+
+        case await z: b; break;
+>await z : any
+>z : any
+>b : any
+    }
+}
+
+async function switchStatement8() {
+>switchStatement8 : () => Promise<void>
+
+    switch (x) {
+>x : any
+
+        default: c;
+>c : any
+
+        case y: a; break;
+>y : any
+>a : any
+
+        case await z: b; break;
+>await z : any
+>z : any
+>b : any
+    }
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionTryStatements.js b/tests/baselines/reference/es5-asyncFunctionTryStatements.js
new file mode 100644
index 0000000000000..54371c5842fc6
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionTryStatements.js
@@ -0,0 +1,334 @@
+//// [es5-asyncFunctionTryStatements.ts]
+declare var x, y, z, a, b, c;
+
+async function tryCatch0() {
+    var x, y;
+    try {
+        x;
+    }
+    catch (e) {
+        y;
+    }
+}
+
+async function tryCatch1() {
+    var x, y;
+    try {
+        await x;
+    }
+    catch (e) {
+        y;
+    }
+}
+
+async function tryCatch2() {
+    var x, y;
+    try {
+        x;
+    }
+    catch (e) {
+        await y;
+    }
+}
+
+async function tryCatch3(): Promise<Function> {
+    var x, y;
+    try {
+        await x;
+    }
+    catch (e) {
+        return () => e;
+    }
+}
+async function tryFinally0() {
+    var x, y;
+    try {
+        x;
+    }
+    finally {
+        y;
+    }
+}
+
+async function tryFinally1() {
+    var x, y;
+    try {
+        await x;
+    }
+    finally {
+        y;
+    }
+}
+
+async function tryFinally2() {
+    var x, y;
+    try {
+        x;
+    }
+    finally {
+        await y;
+    }
+}
+
+async function tryCatchFinally0() {
+    var x, y, z;
+    try {
+        x;
+    }
+    catch (e) {
+        y;
+    }
+    finally {
+        z;
+    }
+}
+
+async function tryCatchFinally1() {
+    var x, y, z;
+    try {
+        await x;
+    }
+    catch (e) {
+        y;
+    }
+    finally {
+        z;
+    }
+}
+
+async function tryCatchFinally2() {
+    var x, y, z;
+    try {
+        x;
+    }
+    catch (e) {
+        await y;
+    }
+    finally {
+        z;
+    }
+}
+
+async function tryCatchFinally3() {
+    var x, y, z;
+    try {
+        x;
+    }
+    catch (e) {
+        y;
+    }
+    finally {
+        await z;
+    }
+}
+
+//// [es5-asyncFunctionTryStatements.js]
+function tryCatch0() {
+    return __awaiter(this, void 0, void 0, function () {
+        var x, y;
+        return __generator(function (_a) {
+            try {
+                x;
+            }
+            catch (e) {
+                y;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function tryCatch1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var x, y, e_1;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _a.trys.push([0, 2, , 3]);
+                    return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 3];
+                case 2:
+                    e_1 = _a.sent();
+                    y;
+                    return [3 /*break*/, 3];
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function tryCatch2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var x, y, e_2;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _a.trys.push([0, 1, , 3]);
+                    x;
+                    return [3 /*break*/, 3];
+                case 1:
+                    e_2 = _a.sent();
+                    return [4 /*yield*/, y];
+                case 2:
+                    _a.sent();
+                    return [3 /*break*/, 3];
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function tryCatch3() {
+    return __awaiter(this, void 0, Promise, function () {
+        var x, y, e_3;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _a.trys.push([0, 2, , 3]);
+                    return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 3];
+                case 2:
+                    e_3 = _a.sent();
+                    return [2 /*return*/, function () { return e_3; }];
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function tryFinally0() {
+    return __awaiter(this, void 0, void 0, function () {
+        var x, y;
+        return __generator(function (_a) {
+            try {
+                x;
+            }
+            finally {
+                y;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function tryFinally1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var x, y;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _a.trys.push([0, , 2, 3]);
+                    return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 3];
+                case 2:
+                    y;
+                    return [7 /*endfinally*/];
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function tryFinally2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var x, y;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _a.trys.push([0, , 1, 3]);
+                    x;
+                    return [3 /*break*/, 3];
+                case 1: return [4 /*yield*/, y];
+                case 2:
+                    _a.sent();
+                    return [7 /*endfinally*/];
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function tryCatchFinally0() {
+    return __awaiter(this, void 0, void 0, function () {
+        var x, y, z;
+        return __generator(function (_a) {
+            try {
+                x;
+            }
+            catch (e) {
+                y;
+            }
+            finally {
+                z;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function tryCatchFinally1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var x, y, z, e_4;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _a.trys.push([0, 2, 3, 4]);
+                    return [4 /*yield*/, x];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 4];
+                case 2:
+                    e_4 = _a.sent();
+                    y;
+                    return [3 /*break*/, 4];
+                case 3:
+                    z;
+                    return [7 /*endfinally*/];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function tryCatchFinally2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var x, y, z, e_5;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _a.trys.push([0, 1, 3, 4]);
+                    x;
+                    return [3 /*break*/, 4];
+                case 1:
+                    e_5 = _a.sent();
+                    return [4 /*yield*/, y];
+                case 2:
+                    _a.sent();
+                    return [3 /*break*/, 4];
+                case 3:
+                    z;
+                    return [7 /*endfinally*/];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
+function tryCatchFinally3() {
+    return __awaiter(this, void 0, void 0, function () {
+        var x, y, z, e_6;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _a.trys.push([0, 1, 2, 4]);
+                    x;
+                    return [3 /*break*/, 4];
+                case 1:
+                    e_6 = _a.sent();
+                    y;
+                    return [3 /*break*/, 4];
+                case 2: return [4 /*yield*/, z];
+                case 3:
+                    _a.sent();
+                    return [7 /*endfinally*/];
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionTryStatements.symbols b/tests/baselines/reference/es5-asyncFunctionTryStatements.symbols
new file mode 100644
index 0000000000000..ecf8fbc505b91
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionTryStatements.symbols
@@ -0,0 +1,232 @@
+=== tests/cases/compiler/es5-asyncFunctionTryStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionTryStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionTryStatements.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionTryStatements.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionTryStatements.ts, 0, 26))
+
+async function tryCatch0() {
+>tryCatch0 : Symbol(tryCatch0, Decl(es5-asyncFunctionTryStatements.ts, 0, 29))
+
+    var x, y;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 3, 7))
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 3, 10))
+
+    try {
+        x;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 3, 7))
+    }
+    catch (e) {
+>e : Symbol(e, Decl(es5-asyncFunctionTryStatements.ts, 7, 11))
+
+        y;
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 3, 10))
+    }
+}
+
+async function tryCatch1() {
+>tryCatch1 : Symbol(tryCatch1, Decl(es5-asyncFunctionTryStatements.ts, 10, 1))
+
+    var x, y;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 13, 7))
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 13, 10))
+
+    try {
+        await x;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 13, 7))
+    }
+    catch (e) {
+>e : Symbol(e, Decl(es5-asyncFunctionTryStatements.ts, 17, 11))
+
+        y;
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 13, 10))
+    }
+}
+
+async function tryCatch2() {
+>tryCatch2 : Symbol(tryCatch2, Decl(es5-asyncFunctionTryStatements.ts, 20, 1))
+
+    var x, y;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 23, 7))
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 23, 10))
+
+    try {
+        x;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 23, 7))
+    }
+    catch (e) {
+>e : Symbol(e, Decl(es5-asyncFunctionTryStatements.ts, 27, 11))
+
+        await y;
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 23, 10))
+    }
+}
+
+async function tryCatch3(): Promise<Function> {
+>tryCatch3 : Symbol(tryCatch3, Decl(es5-asyncFunctionTryStatements.ts, 30, 1))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
+
+    var x, y;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 33, 7))
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 33, 10))
+
+    try {
+        await x;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 33, 7))
+    }
+    catch (e) {
+>e : Symbol(e, Decl(es5-asyncFunctionTryStatements.ts, 37, 11))
+
+        return () => e;
+>e : Symbol(e, Decl(es5-asyncFunctionTryStatements.ts, 37, 11))
+    }
+}
+async function tryFinally0() {
+>tryFinally0 : Symbol(tryFinally0, Decl(es5-asyncFunctionTryStatements.ts, 40, 1))
+
+    var x, y;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 42, 7))
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 42, 10))
+
+    try {
+        x;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 42, 7))
+    }
+    finally {
+        y;
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 42, 10))
+    }
+}
+
+async function tryFinally1() {
+>tryFinally1 : Symbol(tryFinally1, Decl(es5-asyncFunctionTryStatements.ts, 49, 1))
+
+    var x, y;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 52, 7))
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 52, 10))
+
+    try {
+        await x;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 52, 7))
+    }
+    finally {
+        y;
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 52, 10))
+    }
+}
+
+async function tryFinally2() {
+>tryFinally2 : Symbol(tryFinally2, Decl(es5-asyncFunctionTryStatements.ts, 59, 1))
+
+    var x, y;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 62, 7))
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 62, 10))
+
+    try {
+        x;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 62, 7))
+    }
+    finally {
+        await y;
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 62, 10))
+    }
+}
+
+async function tryCatchFinally0() {
+>tryCatchFinally0 : Symbol(tryCatchFinally0, Decl(es5-asyncFunctionTryStatements.ts, 69, 1))
+
+    var x, y, z;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 72, 7))
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 72, 10))
+>z : Symbol(z, Decl(es5-asyncFunctionTryStatements.ts, 72, 13))
+
+    try {
+        x;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 72, 7))
+    }
+    catch (e) {
+>e : Symbol(e, Decl(es5-asyncFunctionTryStatements.ts, 76, 11))
+
+        y;
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 72, 10))
+    }
+    finally {
+        z;
+>z : Symbol(z, Decl(es5-asyncFunctionTryStatements.ts, 72, 13))
+    }
+}
+
+async function tryCatchFinally1() {
+>tryCatchFinally1 : Symbol(tryCatchFinally1, Decl(es5-asyncFunctionTryStatements.ts, 82, 1))
+
+    var x, y, z;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 85, 7))
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 85, 10))
+>z : Symbol(z, Decl(es5-asyncFunctionTryStatements.ts, 85, 13))
+
+    try {
+        await x;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 85, 7))
+    }
+    catch (e) {
+>e : Symbol(e, Decl(es5-asyncFunctionTryStatements.ts, 89, 11))
+
+        y;
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 85, 10))
+    }
+    finally {
+        z;
+>z : Symbol(z, Decl(es5-asyncFunctionTryStatements.ts, 85, 13))
+    }
+}
+
+async function tryCatchFinally2() {
+>tryCatchFinally2 : Symbol(tryCatchFinally2, Decl(es5-asyncFunctionTryStatements.ts, 95, 1))
+
+    var x, y, z;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 98, 7))
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 98, 10))
+>z : Symbol(z, Decl(es5-asyncFunctionTryStatements.ts, 98, 13))
+
+    try {
+        x;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 98, 7))
+    }
+    catch (e) {
+>e : Symbol(e, Decl(es5-asyncFunctionTryStatements.ts, 102, 11))
+
+        await y;
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 98, 10))
+    }
+    finally {
+        z;
+>z : Symbol(z, Decl(es5-asyncFunctionTryStatements.ts, 98, 13))
+    }
+}
+
+async function tryCatchFinally3() {
+>tryCatchFinally3 : Symbol(tryCatchFinally3, Decl(es5-asyncFunctionTryStatements.ts, 108, 1))
+
+    var x, y, z;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 111, 7))
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 111, 10))
+>z : Symbol(z, Decl(es5-asyncFunctionTryStatements.ts, 111, 13))
+
+    try {
+        x;
+>x : Symbol(x, Decl(es5-asyncFunctionTryStatements.ts, 111, 7))
+    }
+    catch (e) {
+>e : Symbol(e, Decl(es5-asyncFunctionTryStatements.ts, 115, 11))
+
+        y;
+>y : Symbol(y, Decl(es5-asyncFunctionTryStatements.ts, 111, 10))
+    }
+    finally {
+        await z;
+>z : Symbol(z, Decl(es5-asyncFunctionTryStatements.ts, 111, 13))
+    }
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionTryStatements.types b/tests/baselines/reference/es5-asyncFunctionTryStatements.types
new file mode 100644
index 0000000000000..ab1cd84561624
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionTryStatements.types
@@ -0,0 +1,241 @@
+=== tests/cases/compiler/es5-asyncFunctionTryStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function tryCatch0() {
+>tryCatch0 : () => Promise<void>
+
+    var x, y;
+>x : any
+>y : any
+
+    try {
+        x;
+>x : any
+    }
+    catch (e) {
+>e : any
+
+        y;
+>y : any
+    }
+}
+
+async function tryCatch1() {
+>tryCatch1 : () => Promise<void>
+
+    var x, y;
+>x : any
+>y : any
+
+    try {
+        await x;
+>await x : any
+>x : any
+    }
+    catch (e) {
+>e : any
+
+        y;
+>y : any
+    }
+}
+
+async function tryCatch2() {
+>tryCatch2 : () => Promise<void>
+
+    var x, y;
+>x : any
+>y : any
+
+    try {
+        x;
+>x : any
+    }
+    catch (e) {
+>e : any
+
+        await y;
+>await y : any
+>y : any
+    }
+}
+
+async function tryCatch3(): Promise<Function> {
+>tryCatch3 : () => Promise<Function>
+>Promise : Promise<T>
+>Function : Function
+
+    var x, y;
+>x : any
+>y : any
+
+    try {
+        await x;
+>await x : any
+>x : any
+    }
+    catch (e) {
+>e : any
+
+        return () => e;
+>() => e : () => any
+>e : any
+    }
+}
+async function tryFinally0() {
+>tryFinally0 : () => Promise<void>
+
+    var x, y;
+>x : any
+>y : any
+
+    try {
+        x;
+>x : any
+    }
+    finally {
+        y;
+>y : any
+    }
+}
+
+async function tryFinally1() {
+>tryFinally1 : () => Promise<void>
+
+    var x, y;
+>x : any
+>y : any
+
+    try {
+        await x;
+>await x : any
+>x : any
+    }
+    finally {
+        y;
+>y : any
+    }
+}
+
+async function tryFinally2() {
+>tryFinally2 : () => Promise<void>
+
+    var x, y;
+>x : any
+>y : any
+
+    try {
+        x;
+>x : any
+    }
+    finally {
+        await y;
+>await y : any
+>y : any
+    }
+}
+
+async function tryCatchFinally0() {
+>tryCatchFinally0 : () => Promise<void>
+
+    var x, y, z;
+>x : any
+>y : any
+>z : any
+
+    try {
+        x;
+>x : any
+    }
+    catch (e) {
+>e : any
+
+        y;
+>y : any
+    }
+    finally {
+        z;
+>z : any
+    }
+}
+
+async function tryCatchFinally1() {
+>tryCatchFinally1 : () => Promise<void>
+
+    var x, y, z;
+>x : any
+>y : any
+>z : any
+
+    try {
+        await x;
+>await x : any
+>x : any
+    }
+    catch (e) {
+>e : any
+
+        y;
+>y : any
+    }
+    finally {
+        z;
+>z : any
+    }
+}
+
+async function tryCatchFinally2() {
+>tryCatchFinally2 : () => Promise<void>
+
+    var x, y, z;
+>x : any
+>y : any
+>z : any
+
+    try {
+        x;
+>x : any
+    }
+    catch (e) {
+>e : any
+
+        await y;
+>await y : any
+>y : any
+    }
+    finally {
+        z;
+>z : any
+    }
+}
+
+async function tryCatchFinally3() {
+>tryCatchFinally3 : () => Promise<void>
+
+    var x, y, z;
+>x : any
+>y : any
+>z : any
+
+    try {
+        x;
+>x : any
+    }
+    catch (e) {
+>e : any
+
+        y;
+>y : any
+    }
+    finally {
+        await z;
+>await z : any
+>z : any
+    }
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionWhileStatements.js b/tests/baselines/reference/es5-asyncFunctionWhileStatements.js
new file mode 100644
index 0000000000000..53ca2a2da37c7
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionWhileStatements.js
@@ -0,0 +1,353 @@
+//// [es5-asyncFunctionWhileStatements.ts]
+declare var x, y, z, a, b, c;
+
+async function whileStatement0() {
+    while (x) { y; }
+}
+
+async function whileStatement1() {
+    while (await x) { y; }
+}
+
+async function whileStatement2() {
+    while (x) { await y; }
+}
+
+async function whileStatement3() {
+    while (x) { continue; }
+}
+
+async function whileStatement4() {
+    while (await x) { continue; }
+}
+
+async function whileStatement5() {
+    while (x) { await y; continue; }
+}
+
+async function whileStatement6() {
+    while (x) { if (1) continue; await y; }
+}
+
+async function whileStatement7() {
+    A: while (x) { continue A; }
+}
+
+async function whileStatement8() {
+    B: while (await x) { continue B; }
+}
+
+async function whileStatement9() {
+    C: while (x) { await y; continue C; }
+}
+
+async function whileStatement10() {
+    D: while (x) { if (1) continue D; await y; }
+}
+
+async function whileStatement11() {
+    while (x) { break; }
+}
+
+async function whileStatement12() {
+    while (await x) { break; }
+}
+
+async function whileStatement13() {
+    while (x) { await y; break; }
+}
+
+async function whileStatement14() {
+    while (x) { if (1) break; await y; }
+}
+
+async function whileStatement15() {
+    E: while (x) { break E; }
+}
+
+async function whileStatement16() {
+    F: while (await x) { break F; }
+}
+
+async function whileStatement17() {
+    G: while (x) { await y; break G; }
+}
+
+async function whileStatement18() {
+    H: while (x) { if (1) break H; await y; }
+}
+
+//// [es5-asyncFunctionWhileStatements.js]
+function whileStatement0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            while (x) {
+                y;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function whileStatement1() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    if (!_a.sent())
+                        return [3 /*break*/, 2];
+                    y;
+                    return [3 /*break*/, 0];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement2() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 0];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement3() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            while (x) {
+                continue;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function whileStatement4() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    if (!_a.sent())
+                        return [3 /*break*/, 2];
+                    return [3 /*break*/, 0];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement5() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 0];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement6() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 2];
+                    if (1)
+                        return [3 /*break*/, 0];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 0];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement7() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            A: while (x) {
+                continue A;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function whileStatement8() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    if (!_a.sent())
+                        return [3 /*break*/, 2];
+                    return [3 /*break*/, 0];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement9() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 0];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement10() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 2];
+                    if (1)
+                        return [3 /*break*/, 0];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 0];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement11() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            while (x) {
+                break;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function whileStatement12() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    if (!_a.sent())
+                        return [3 /*break*/, 2];
+                    return [3 /*break*/, 2];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement13() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 2];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement14() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 2];
+                    if (1)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 0];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement15() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            E: while (x) {
+                break E;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function whileStatement16() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    if (!_a.sent())
+                        return [3 /*break*/, 2];
+                    return [3 /*break*/, 2];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement17() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 2];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
+function whileStatement18() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    if (!x)
+                        return [3 /*break*/, 2];
+                    if (1)
+                        return [3 /*break*/, 2];
+                    return [4 /*yield*/, y];
+                case 1:
+                    _a.sent();
+                    return [3 /*break*/, 0];
+                case 2: return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionWhileStatements.symbols b/tests/baselines/reference/es5-asyncFunctionWhileStatements.symbols
new file mode 100644
index 0000000000000..31c38da469338
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionWhileStatements.symbols
@@ -0,0 +1,152 @@
+=== tests/cases/compiler/es5-asyncFunctionWhileStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionWhileStatements.ts, 0, 14))
+>z : Symbol(z, Decl(es5-asyncFunctionWhileStatements.ts, 0, 17))
+>a : Symbol(a, Decl(es5-asyncFunctionWhileStatements.ts, 0, 20))
+>b : Symbol(b, Decl(es5-asyncFunctionWhileStatements.ts, 0, 23))
+>c : Symbol(c, Decl(es5-asyncFunctionWhileStatements.ts, 0, 26))
+
+async function whileStatement0() {
+>whileStatement0 : Symbol(whileStatement0, Decl(es5-asyncFunctionWhileStatements.ts, 0, 29))
+
+    while (x) { y; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionWhileStatements.ts, 0, 14))
+}
+
+async function whileStatement1() {
+>whileStatement1 : Symbol(whileStatement1, Decl(es5-asyncFunctionWhileStatements.ts, 4, 1))
+
+    while (await x) { y; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionWhileStatements.ts, 0, 14))
+}
+
+async function whileStatement2() {
+>whileStatement2 : Symbol(whileStatement2, Decl(es5-asyncFunctionWhileStatements.ts, 8, 1))
+
+    while (x) { await y; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionWhileStatements.ts, 0, 14))
+}
+
+async function whileStatement3() {
+>whileStatement3 : Symbol(whileStatement3, Decl(es5-asyncFunctionWhileStatements.ts, 12, 1))
+
+    while (x) { continue; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+}
+
+async function whileStatement4() {
+>whileStatement4 : Symbol(whileStatement4, Decl(es5-asyncFunctionWhileStatements.ts, 16, 1))
+
+    while (await x) { continue; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+}
+
+async function whileStatement5() {
+>whileStatement5 : Symbol(whileStatement5, Decl(es5-asyncFunctionWhileStatements.ts, 20, 1))
+
+    while (x) { await y; continue; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionWhileStatements.ts, 0, 14))
+}
+
+async function whileStatement6() {
+>whileStatement6 : Symbol(whileStatement6, Decl(es5-asyncFunctionWhileStatements.ts, 24, 1))
+
+    while (x) { if (1) continue; await y; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionWhileStatements.ts, 0, 14))
+}
+
+async function whileStatement7() {
+>whileStatement7 : Symbol(whileStatement7, Decl(es5-asyncFunctionWhileStatements.ts, 28, 1))
+
+    A: while (x) { continue A; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+}
+
+async function whileStatement8() {
+>whileStatement8 : Symbol(whileStatement8, Decl(es5-asyncFunctionWhileStatements.ts, 32, 1))
+
+    B: while (await x) { continue B; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+}
+
+async function whileStatement9() {
+>whileStatement9 : Symbol(whileStatement9, Decl(es5-asyncFunctionWhileStatements.ts, 36, 1))
+
+    C: while (x) { await y; continue C; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionWhileStatements.ts, 0, 14))
+}
+
+async function whileStatement10() {
+>whileStatement10 : Symbol(whileStatement10, Decl(es5-asyncFunctionWhileStatements.ts, 40, 1))
+
+    D: while (x) { if (1) continue D; await y; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionWhileStatements.ts, 0, 14))
+}
+
+async function whileStatement11() {
+>whileStatement11 : Symbol(whileStatement11, Decl(es5-asyncFunctionWhileStatements.ts, 44, 1))
+
+    while (x) { break; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+}
+
+async function whileStatement12() {
+>whileStatement12 : Symbol(whileStatement12, Decl(es5-asyncFunctionWhileStatements.ts, 48, 1))
+
+    while (await x) { break; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+}
+
+async function whileStatement13() {
+>whileStatement13 : Symbol(whileStatement13, Decl(es5-asyncFunctionWhileStatements.ts, 52, 1))
+
+    while (x) { await y; break; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionWhileStatements.ts, 0, 14))
+}
+
+async function whileStatement14() {
+>whileStatement14 : Symbol(whileStatement14, Decl(es5-asyncFunctionWhileStatements.ts, 56, 1))
+
+    while (x) { if (1) break; await y; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionWhileStatements.ts, 0, 14))
+}
+
+async function whileStatement15() {
+>whileStatement15 : Symbol(whileStatement15, Decl(es5-asyncFunctionWhileStatements.ts, 60, 1))
+
+    E: while (x) { break E; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+}
+
+async function whileStatement16() {
+>whileStatement16 : Symbol(whileStatement16, Decl(es5-asyncFunctionWhileStatements.ts, 64, 1))
+
+    F: while (await x) { break F; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+}
+
+async function whileStatement17() {
+>whileStatement17 : Symbol(whileStatement17, Decl(es5-asyncFunctionWhileStatements.ts, 68, 1))
+
+    G: while (x) { await y; break G; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionWhileStatements.ts, 0, 14))
+}
+
+async function whileStatement18() {
+>whileStatement18 : Symbol(whileStatement18, Decl(es5-asyncFunctionWhileStatements.ts, 72, 1))
+
+    H: while (x) { if (1) break H; await y; }
+>x : Symbol(x, Decl(es5-asyncFunctionWhileStatements.ts, 0, 11))
+>y : Symbol(y, Decl(es5-asyncFunctionWhileStatements.ts, 0, 14))
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionWhileStatements.types b/tests/baselines/reference/es5-asyncFunctionWhileStatements.types
new file mode 100644
index 0000000000000..2410befa043f9
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionWhileStatements.types
@@ -0,0 +1,186 @@
+=== tests/cases/compiler/es5-asyncFunctionWhileStatements.ts ===
+declare var x, y, z, a, b, c;
+>x : any
+>y : any
+>z : any
+>a : any
+>b : any
+>c : any
+
+async function whileStatement0() {
+>whileStatement0 : () => Promise<void>
+
+    while (x) { y; }
+>x : any
+>y : any
+}
+
+async function whileStatement1() {
+>whileStatement1 : () => Promise<void>
+
+    while (await x) { y; }
+>await x : any
+>x : any
+>y : any
+}
+
+async function whileStatement2() {
+>whileStatement2 : () => Promise<void>
+
+    while (x) { await y; }
+>x : any
+>await y : any
+>y : any
+}
+
+async function whileStatement3() {
+>whileStatement3 : () => Promise<void>
+
+    while (x) { continue; }
+>x : any
+}
+
+async function whileStatement4() {
+>whileStatement4 : () => Promise<void>
+
+    while (await x) { continue; }
+>await x : any
+>x : any
+}
+
+async function whileStatement5() {
+>whileStatement5 : () => Promise<void>
+
+    while (x) { await y; continue; }
+>x : any
+>await y : any
+>y : any
+}
+
+async function whileStatement6() {
+>whileStatement6 : () => Promise<void>
+
+    while (x) { if (1) continue; await y; }
+>x : any
+>1 : number
+>await y : any
+>y : any
+}
+
+async function whileStatement7() {
+>whileStatement7 : () => Promise<void>
+
+    A: while (x) { continue A; }
+>A : any
+>x : any
+>A : any
+}
+
+async function whileStatement8() {
+>whileStatement8 : () => Promise<void>
+
+    B: while (await x) { continue B; }
+>B : any
+>await x : any
+>x : any
+>B : any
+}
+
+async function whileStatement9() {
+>whileStatement9 : () => Promise<void>
+
+    C: while (x) { await y; continue C; }
+>C : any
+>x : any
+>await y : any
+>y : any
+>C : any
+}
+
+async function whileStatement10() {
+>whileStatement10 : () => Promise<void>
+
+    D: while (x) { if (1) continue D; await y; }
+>D : any
+>x : any
+>1 : number
+>D : any
+>await y : any
+>y : any
+}
+
+async function whileStatement11() {
+>whileStatement11 : () => Promise<void>
+
+    while (x) { break; }
+>x : any
+}
+
+async function whileStatement12() {
+>whileStatement12 : () => Promise<void>
+
+    while (await x) { break; }
+>await x : any
+>x : any
+}
+
+async function whileStatement13() {
+>whileStatement13 : () => Promise<void>
+
+    while (x) { await y; break; }
+>x : any
+>await y : any
+>y : any
+}
+
+async function whileStatement14() {
+>whileStatement14 : () => Promise<void>
+
+    while (x) { if (1) break; await y; }
+>x : any
+>1 : number
+>await y : any
+>y : any
+}
+
+async function whileStatement15() {
+>whileStatement15 : () => Promise<void>
+
+    E: while (x) { break E; }
+>E : any
+>x : any
+>E : any
+}
+
+async function whileStatement16() {
+>whileStatement16 : () => Promise<void>
+
+    F: while (await x) { break F; }
+>F : any
+>await x : any
+>x : any
+>F : any
+}
+
+async function whileStatement17() {
+>whileStatement17 : () => Promise<void>
+
+    G: while (x) { await y; break G; }
+>G : any
+>x : any
+>await y : any
+>y : any
+>G : any
+}
+
+async function whileStatement18() {
+>whileStatement18 : () => Promise<void>
+
+    H: while (x) { if (1) break H; await y; }
+>H : any
+>x : any
+>1 : number
+>H : any
+>await y : any
+>y : any
+}
diff --git a/tests/baselines/reference/es5-asyncFunctionWithStatements.errors.txt b/tests/baselines/reference/es5-asyncFunctionWithStatements.errors.txt
new file mode 100644
index 0000000000000..560612bc81ebf
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionWithStatements.errors.txt
@@ -0,0 +1,58 @@
+tests/cases/compiler/es5-asyncFunctionWithStatements.ts(4,5): error TS1300: 'with' statements are not allowed in an async function block.
+tests/cases/compiler/es5-asyncFunctionWithStatements.ts(4,11): error TS2410: All symbols within a 'with' block will be resolved to 'any'.
+tests/cases/compiler/es5-asyncFunctionWithStatements.ts(10,5): error TS1300: 'with' statements are not allowed in an async function block.
+tests/cases/compiler/es5-asyncFunctionWithStatements.ts(10,11): error TS2410: All symbols within a 'with' block will be resolved to 'any'.
+tests/cases/compiler/es5-asyncFunctionWithStatements.ts(16,5): error TS1300: 'with' statements are not allowed in an async function block.
+tests/cases/compiler/es5-asyncFunctionWithStatements.ts(16,11): error TS2410: All symbols within a 'with' block will be resolved to 'any'.
+tests/cases/compiler/es5-asyncFunctionWithStatements.ts(24,5): error TS1300: 'with' statements are not allowed in an async function block.
+tests/cases/compiler/es5-asyncFunctionWithStatements.ts(24,11): error TS2410: All symbols within a 'with' block will be resolved to 'any'.
+
+
+==== tests/cases/compiler/es5-asyncFunctionWithStatements.ts (8 errors) ====
+    declare var x, y, z, a, b, c;
+    
+    async function withStatement0() {
+        with (x) {
+        ~~~~
+!!! error TS1300: 'with' statements are not allowed in an async function block.
+              ~
+!!! error TS2410: All symbols within a 'with' block will be resolved to 'any'.
+            y;
+        }
+    }
+    
+    async function withStatement1() {
+        with (await x) {
+        ~~~~
+!!! error TS1300: 'with' statements are not allowed in an async function block.
+              ~~~~~~~
+!!! error TS2410: All symbols within a 'with' block will be resolved to 'any'.
+            y;
+        }
+    }
+    
+    async function withStatement2() {
+        with (x) {
+        ~~~~
+!!! error TS1300: 'with' statements are not allowed in an async function block.
+              ~
+!!! error TS2410: All symbols within a 'with' block will be resolved to 'any'.
+            a;
+            await y;
+            b;
+        }
+    }
+    
+    async function withStatement3() {
+        with (x) {
+        ~~~~
+!!! error TS1300: 'with' statements are not allowed in an async function block.
+              ~
+!!! error TS2410: All symbols within a 'with' block will be resolved to 'any'.
+            with (z) {
+                a;
+                await y;
+                b;
+            }
+        }
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/es5-asyncFunctionWithStatements.js b/tests/baselines/reference/es5-asyncFunctionWithStatements.js
new file mode 100644
index 0000000000000..20bedc25da9f0
--- /dev/null
+++ b/tests/baselines/reference/es5-asyncFunctionWithStatements.js
@@ -0,0 +1,118 @@
+//// [es5-asyncFunctionWithStatements.ts]
+declare var x, y, z, a, b, c;
+
+async function withStatement0() {
+    with (x) {
+        y;
+    }
+}
+
+async function withStatement1() {
+    with (await x) {
+        y;
+    }
+}
+
+async function withStatement2() {
+    with (x) {
+        a;
+        await y;
+        b;
+    }
+}
+
+async function withStatement3() {
+    with (x) {
+        with (z) {
+            a;
+            await y;
+            b;
+        }
+    }
+}
+
+//// [es5-asyncFunctionWithStatements.js]
+function withStatement0() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            with (x) {
+                y;
+            }
+            return [2 /*return*/];
+        });
+    });
+}
+function withStatement1() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0: return [4 /*yield*/, x];
+                case 1:
+                    _a = _b.sent();
+                    _b.label = 2;
+                case 2:
+                    with (_a) {
+                        y;
+                    }
+                    _b.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function withStatement2() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = x;
+                    _b.label = 1;
+                case 1: with (_a) {
+                    a;
+                    return [4 /*yield*/, y];
+                }
+                case 2:
+                    with (_a) {
+                        _b.sent();
+                        b;
+                    }
+                    _b.label = 3;
+                case 3: return [2 /*return*/];
+            }
+        });
+    });
+}
+function withStatement3() {
+    return __awaiter(this, void 0, void 0, function () {
+        var _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = x;
+                    _c.label = 1;
+                case 1:
+                    with (_a) {
+                        _b = z;
+                    }
+                    _c.label = 2;
+                case 2: with (_a) {
+                    with (_b) {
+                        a;
+                        return [4 /*yield*/, y];
+                    }
+                }
+                case 3:
+                    with (_a) {
+                        with (_b) {
+                            _c.sent();
+                            b;
+                        }
+                    }
+                    _c.label = 4;
+                case 4: return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/cases/compiler/es5-asyncFunction.ts b/tests/cases/compiler/es5-asyncFunction.ts
new file mode 100644
index 0000000000000..2ee2ccb3f91d9
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunction.ts
@@ -0,0 +1,10 @@
+// @lib: es5,es2015.promise
+// @target: ES5
+declare var x;
+
+async function empty() {
+}
+
+async function singleAwait() {
+    await x;
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionArrayLiterals.ts b/tests/cases/compiler/es5-asyncFunctionArrayLiterals.ts
new file mode 100644
index 0000000000000..69240010c2759
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionArrayLiterals.ts
@@ -0,0 +1,36 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a;
+
+async function arrayLiteral0() {
+    x = [await y, z];
+}
+
+async function arrayLiteral1() {
+    x = [y, await z];
+}
+
+async function arrayLiteral2() {
+    x = [...(await y), z];
+}
+
+async function arrayLiteral3() {
+    x = [...y, await z];
+}
+
+async function arrayLiteral4() {
+    x = [await y, ...z];
+}
+
+async function arrayLiteral5() {
+    x = [y, ...(await z)];
+}
+
+async function arrayLiteral6() {
+    x = [y, await z, a];
+}
+
+async function arrayLiteral7() {
+    x = [await y, z, await a];
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionBinaryExpressions.ts b/tests/cases/compiler/es5-asyncFunctionBinaryExpressions.ts
new file mode 100644
index 0000000000000..cb633640466b0
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionBinaryExpressions.ts
@@ -0,0 +1,125 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function binaryPlus0() {
+    (await x) + y;
+}
+
+async function binaryPlus1() {
+    x + await y;
+}
+
+async function binaryLogicalAnd0() {
+    (await x) && y;
+}
+
+async function binaryLogicalAnd1() {
+    x && await y;
+}
+
+async function binaryAssignment0() {
+    x = await y;
+}
+
+async function binaryAssignment1() {
+    x.a = await y;
+}
+
+async function binaryAssignment2() {
+    x.a.b = await y;
+}
+
+async function binaryAssignment3() {
+    x[z] = await y;
+}
+
+async function binaryAssignment4() {
+    x[z].b = await y;
+}
+
+async function binaryAssignment5() {
+    x.a[z] = await y;
+}
+
+async function binaryAssignment6() {
+    (await x).a = y;
+}
+
+async function binaryAssignment7() {
+    (await x.a).b = y;
+}
+
+async function binaryAssignment8() {
+    (await x)[z] = y;
+}
+
+async function binaryAssignment9() {
+    x[await z] = y;
+}
+
+async function binaryAssignment10() {
+    x[await z].b = y;
+}
+
+async function binaryAssignment11() {
+    (await x[z]).b = y;
+}
+
+async function binaryAssignment12() {
+    x.a[await z] = y;
+}
+
+async function binaryAssignment13() {
+    (await x.a)[z] = y;
+}
+
+async function binaryCompoundAssignment0() {
+    x += await y;
+}
+
+async function binaryCompoundAssignment1() {
+    x.a += await y;
+}
+
+async function binaryCompoundAssignment2() {
+    x[a] += await y;
+}
+
+async function binaryCompoundAssignment3() {
+    (await x).a += y;
+}
+
+async function binaryCompoundAssignment4() {
+    (await x)[a] += y;
+}
+
+async function binaryCompoundAssignment5() {
+    x[await a] += y;
+}
+
+async function binaryCompoundAssignment6() {
+    (await x).a += await y;
+}
+
+async function binaryCompoundAssignment7() {
+    (await x)[a] += await y;
+}
+
+async function binaryCompoundAssignment8() {
+    x[await a] += await y;
+}
+
+async function binaryExponentiation() {
+    (await x) ** y;
+    x ** await y;
+}
+
+async function binaryComma0() {
+    return (await x), y;
+}
+
+async function binaryComma1(): Promise<any> {
+    return x, await y;
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionCallExpressions.ts b/tests/cases/compiler/es5-asyncFunctionCallExpressions.ts
new file mode 100644
index 0000000000000..7b748b95bdf9f
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionCallExpressions.ts
@@ -0,0 +1,88 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function callExpression0() {
+    await x(y, z);
+}
+
+async function callExpression1() {
+    (await x)(y, z);
+}
+
+async function callExpression2() {
+    x(await y, z);
+}
+
+async function callExpression3() {
+    x(y, await z);
+}
+
+async function callExpression4() {
+    await x(...y, z);
+}
+
+async function callExpression5() {
+    (await x)(...y, z);
+}
+
+async function callExpression6() {
+    x(...(await y), z);
+}
+
+async function callExpression7() {
+    x(...y, await z);
+}
+
+async function callExpression8() {
+    x(await y, ...z);
+}
+
+async function callExpression9() {
+    x(y, ...(await z));
+}
+
+async function callExpression10() {
+    await x.a(y, z);
+}
+
+async function callExpression11() {
+    (await x.a)(y, z);
+}
+
+async function callExpression12() {
+    (await x).a(y, z);
+}
+
+async function callExpression13() {
+    x.a(await y, z);
+}
+
+async function callExpression14() {
+    x.a(y, await z);
+}
+
+async function callExpression15() {
+    await x[a](y, z);
+}
+
+async function callExpression16() {
+    (await x[a])(y, z);
+}
+
+async function callExpression17() {
+    (await x)[a](y, z);
+}
+
+async function callExpression18() {
+    x[await a](y, z);
+}
+
+async function callExpression19() {
+    x[a](await y, z);
+}
+
+async function callExpression20() {
+    x[a](y, await z);
+}
diff --git a/tests/cases/compiler/es5-asyncFunctionConditionals.ts b/tests/cases/compiler/es5-asyncFunctionConditionals.ts
new file mode 100644
index 0000000000000..fbc577b983347
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionConditionals.ts
@@ -0,0 +1,16 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function conditional0() {
+    a = (await x) ? y : z;
+}
+
+async function conditional1() {
+    a = x ? await y : z;
+}
+
+async function conditional2() {
+    a = x ? y : await z;
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionDoStatements.ts b/tests/cases/compiler/es5-asyncFunctionDoStatements.ts
new file mode 100644
index 0000000000000..6501e27769fb1
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionDoStatements.ts
@@ -0,0 +1,80 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function doStatement0() {
+    do { x; } while (y);
+}
+
+async function doStatement1() {
+    do { await x; } while (y);
+}
+
+async function doStatement2() {
+    do { x; } while (await y);
+}
+
+async function doStatement3() {
+    do { continue; } while (y);
+}
+
+async function doStatement4() {
+    do { await x; continue; } while (y);
+}
+
+async function doStatement5() {
+    do { if (1) continue; await x; } while (y);
+}
+
+async function doStatement6() {
+    do { continue; } while (await y);
+}
+
+async function doStatement7() {
+    A: do { continue A; } while (y);
+}
+
+async function doStatement8() {
+    B: do { await x; continue B; } while (y);
+}
+
+async function doStatement9() {
+    C: do { if (1) continue C; await x; } while (y);
+}
+
+async function doStatement10() {
+    D: do { continue D; } while (await y);
+}
+
+async function doStatement11() {
+    do { break; } while (y);
+}
+
+async function doStatement12() {
+    do { await x; break; } while (y);
+}
+
+async function doStatement13() {
+    do { if (1) break; await x; } while (y);
+}
+
+async function doStatement14() {
+    do { break; } while (await y);
+}
+
+async function doStatement15() {
+    E: do { break E; } while (y);
+}
+
+async function doStatement16() {
+    F: do { await x; break F; } while (y);
+}
+
+async function doStatement17() {
+    G: do { if (1) break G; await x; } while (y);
+}
+
+async function doStatement18() {
+    H: do { break H; } while (await y);
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionElementAccess.ts b/tests/cases/compiler/es5-asyncFunctionElementAccess.ts
new file mode 100644
index 0000000000000..01372b43f5eb3
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionElementAccess.ts
@@ -0,0 +1,16 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function elementAccess0() {
+    z = await x[y];
+}
+
+async function elementAccess1() {
+    z = (await x)[y];
+}
+
+async function elementAccess2() {
+    z = x[await y];
+}
diff --git a/tests/cases/compiler/es5-asyncFunctionForInStatements.ts b/tests/cases/compiler/es5-asyncFunctionForInStatements.ts
new file mode 100644
index 0000000000000..b1593041080d1
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionForInStatements.ts
@@ -0,0 +1,40 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function forInStatement0() {
+    for (x in y) { z; }
+}
+
+async function forInStatement1() {
+    for (x in await y) { z; }
+}
+
+async function forInStatement2() {
+    for (x in y) { await z; }
+}
+
+async function forInStatement3() {
+    for ((await x).a in y) { z; }
+}
+
+async function forInStatement4() {
+    for (x.a in await y) { z; }
+}
+
+async function forInStatement5() {
+    for (x.a in y) { await z; }
+}
+
+async function forInStatement6() {
+    for (var a in y) { z; }
+}
+
+async function forInStatement7() {
+    for (var b in await y) { z; }
+}
+
+async function forInStatement8() {
+    for (var c in y) { await z; }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionForOfStatements.ts b/tests/cases/compiler/es5-asyncFunctionForOfStatements.ts
new file mode 100644
index 0000000000000..d741c55e31e98
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionForOfStatements.ts
@@ -0,0 +1,80 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function forOfStatement0() {
+    for (x of y) { z; }
+}
+
+async function forOfStatement1() {
+    for (x of await y) { z; }
+}
+
+async function forOfStatement2() {
+    for (x of y) { await z; }
+}
+
+async function forOfStatement3() {
+    for ((await x).a of y) { z; }
+}
+
+async function forOfStatement4() {
+    for (x.a of await y) { z; }
+}
+
+async function forOfStatement5() {
+    for (x.a of y) { await z; }
+}
+
+async function forOfStatement6() {
+    for (var b of y) { z; }
+}
+
+async function forOfStatement7() {
+    for (var c of await y) { z; }
+}
+
+async function forOfStatement8() {
+    for (var d of y) { await z; }
+}
+
+async function forOfStatement9() {
+    for ([x] of await y) { z; }
+}
+
+async function forOfStatement10() {
+    for ([x] of y) { await z; }
+}
+
+async function forOfStatement11() {
+    for ([x = await a] of y) { z; }
+}
+
+async function forOfStatement12() {
+    for ([x = a] of await y) { z; }
+}
+
+async function forOfStatement13() {
+    for ([x = a] of y) { await z; }
+}
+
+async function forOfStatement14() {
+    for ({ x } of await y) { z; }
+}
+
+async function forOfStatement15() {
+    for ({ x } of y) { await z; }
+}
+
+async function forOfStatement16() {
+    for ({ x = await a } of y) { z; }
+}
+
+async function forOfStatement17() {
+    for ({ x = a } of await y) { z; }
+}
+
+async function forOfStatement18() {
+    for ({ x = a } of y) { await z; }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionForStatements.ts b/tests/cases/compiler/es5-asyncFunctionForStatements.ts
new file mode 100644
index 0000000000000..4fddf395588f2
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionForStatements.ts
@@ -0,0 +1,32 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function forStatement0() {
+    for (x; y; z) { a; }
+}
+
+async function forStatement1() {
+    for (await x; y; z) { a; }
+}
+
+async function forStatement2() {
+    for (x; await y; z) { a; }
+}
+
+async function forStatement3() {
+    for (x; y; await z) { a; }
+}
+
+async function forStatement4() {
+    for (x; y; z) { await a; }
+}
+
+async function forStatement5() {
+    for (var b; y; z) { a; }
+}
+
+async function forStatement6() {
+    for (var c = x; y; z) { a; }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionHoisting.ts b/tests/cases/compiler/es5-asyncFunctionHoisting.ts
new file mode 100644
index 0000000000000..7c05372ada9d3
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionHoisting.ts
@@ -0,0 +1,54 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var y;
+
+async function hoisting() {
+    var a0, a1 = 1;
+    function z() {
+        var b0, b1 = 1;
+    }
+
+    if (true) {
+        var c0, c1 = 1;
+    }
+
+    for (var a = 0; y;) {
+
+    }
+
+    for (var b in y) {
+
+    }
+
+    for (var c of y) {
+
+    }
+}
+
+async function hoistingWithAwait() {
+    var a0, a1 = 1;
+
+    function z() {
+        var b0, b1 = 1;
+    }
+
+    await 0;
+
+    if (true) {
+        var c0, c1 = 1;
+    }
+
+    for (var a = 0; y;) {
+
+    }
+
+    for (var b in y) {
+
+    }
+
+    for (var c of y) {
+
+    }
+}
+
diff --git a/tests/cases/compiler/es5-asyncFunctionIfStatements.ts b/tests/cases/compiler/es5-asyncFunctionIfStatements.ts
new file mode 100644
index 0000000000000..65bda05ee7954
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionIfStatements.ts
@@ -0,0 +1,16 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function ifStatement1() {
+    if (await x) { y; } else { z; }
+}
+
+async function ifStatement2() {
+    if (x) { await y; } else { z; }
+}
+
+async function ifStatement3() {
+    if (x) { y; } else { await z; }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionNestedLoops.ts b/tests/cases/compiler/es5-asyncFunctionNestedLoops.ts
new file mode 100644
index 0000000000000..dd6f3126bcf10
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionNestedLoops.ts
@@ -0,0 +1,16 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function nestedLoops() {
+    A: while (x) {
+        await y;
+        while (z) {
+            continue A;
+        }
+        while (a) {
+            continue;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionNewExpressions.ts b/tests/cases/compiler/es5-asyncFunctionNewExpressions.ts
new file mode 100644
index 0000000000000..d7f0da9f433e8
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionNewExpressions.ts
@@ -0,0 +1,88 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function newExpression0() {
+    await new x(y, z);
+}
+
+async function newExpression1() {
+    new (await x)(y, z);
+}
+
+async function newExpression2() {
+    new x(await y, z);
+}
+
+async function newExpression3() {
+    new x(y, await z);
+}
+
+async function newExpression4() {
+    await new x(...y, z);
+}
+
+async function newExpression5() {
+    new (await x)(...y, z);
+}
+
+async function newExpression6() {
+    new x(...(await y), z);
+}
+
+async function newExpression7() {
+    new x(...y, await z);
+}
+
+async function newExpression8() {
+    new x(await y, ...z);
+}
+
+async function newExpression9() {
+    new x(y, ...(await z));
+}
+
+async function newExpression10() {
+    await new x.a(y, z);
+}
+
+async function newExpression11() {
+    new (await x.a)(y, z);
+}
+
+async function newExpression12() {
+    new (await x).a(y, z);
+}
+
+async function newExpression13() {
+    new x.a(await y, z);
+}
+
+async function newExpression14() {
+    new x.a(y, await z);
+}
+
+async function newExpression15() {
+    await new x[a](y, z);
+}
+
+async function newExpression16() {
+    new (await x[a])(y, z);
+}
+
+async function newExpression17() {
+    new (await x)[a](y, z);
+}
+
+async function newExpression18() {
+    new x[await a](y, z);
+}
+
+async function newExpression19() {
+    new x[a](await y, z);
+}
+
+async function newExpression20() {
+    new x[a](y, await z);
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionObjectLiterals.ts b/tests/cases/compiler/es5-asyncFunctionObjectLiterals.ts
new file mode 100644
index 0000000000000..42d03f90494c7
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionObjectLiterals.ts
@@ -0,0 +1,53 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function objectLiteral0() {
+    x = {
+        a: await y,
+        b: z
+    };
+}
+
+async function objectLiteral1() {
+    x = {
+        a: y,
+        b: await z
+    };
+}
+
+async function objectLiteral2() {
+    x = {
+        [await a]: y,
+        b: z
+    };
+}
+
+async function objectLiteral3() {
+    x = {
+        [a]: await y,
+        b: z
+    };
+}
+
+async function objectLiteral4() {
+    x = {
+        a: await y,
+        [b]: z
+    };
+}
+
+async function objectLiteral5() {
+    x = {
+        a: y,
+        [await b]: z
+    };
+}
+
+async function objectLiteral6() {
+    x = {
+        a: y,
+        [b]: await z
+    };
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionPropertyAccess.ts b/tests/cases/compiler/es5-asyncFunctionPropertyAccess.ts
new file mode 100644
index 0000000000000..3541c1b354b36
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionPropertyAccess.ts
@@ -0,0 +1,16 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function propertyAccess0() {
+    y = await x.a;
+}
+
+async function propertyAccess1() {
+    y = (await x).a;
+}
+
+async function callExpression0() {
+    await x(y, z);
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionReturnStatements.ts b/tests/cases/compiler/es5-asyncFunctionReturnStatements.ts
new file mode 100644
index 0000000000000..944c61b568c6e
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionReturnStatements.ts
@@ -0,0 +1,29 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function returnStatement0(): Promise<any> {
+    return;
+}
+
+async function returnStatement1(): Promise<any> {
+    return x;
+}
+
+async function returnStatement2(): Promise<any> {
+    return await x;
+}
+
+async function returnStatement3(): Promise<any> {
+    { return; }
+}
+
+async function returnStatement4(): Promise<any> {
+    await x;
+    { return; }
+}
+
+async function returnStatement5(): Promise<any>{
+    { return await x; }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionSwitchStatements.ts b/tests/cases/compiler/es5-asyncFunctionSwitchStatements.ts
new file mode 100644
index 0000000000000..b321c7115ce28
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionSwitchStatements.ts
@@ -0,0 +1,70 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function switchStatement0() {
+    switch (x) {
+        case y: a; break;
+        default: b; break;
+    }
+}
+
+async function switchStatement1() {
+    switch (await x) {
+        case y: a; break;
+        default: b; break;
+    }
+}
+
+async function switchStatement2() {
+    switch (x) {
+        case await y: a; break;
+        default: b; break;
+    }
+}
+
+async function switchStatement3() {
+    switch (x) {
+        case y: await a; break;
+        default: b; break;
+    }
+}
+
+async function switchStatement4() {
+    switch (x) {
+        case y: a; break;
+        default: await b; break;
+    }
+}
+
+async function switchStatement5() {
+    switch (x) {
+        case y: a; break;
+        case await z: b; break;
+    }
+}
+
+async function switchStatement6() {
+    switch (x) {
+        default: c; break;
+        case await y: a; break;
+        case z: b; break;
+    }
+}
+
+async function switchStatement7() {
+    switch (x) {
+        default: c; break;
+        case y: a; break;
+        case await z: b; break;
+    }
+}
+
+async function switchStatement8() {
+    switch (x) {
+        default: c;
+        case y: a; break;
+        case await z: b; break;
+    }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionTryStatements.ts b/tests/cases/compiler/es5-asyncFunctionTryStatements.ts
new file mode 100644
index 0000000000000..11459295f47cd
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionTryStatements.ts
@@ -0,0 +1,125 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function tryCatch0() {
+    var x, y;
+    try {
+        x;
+    }
+    catch (e) {
+        y;
+    }
+}
+
+async function tryCatch1() {
+    var x, y;
+    try {
+        await x;
+    }
+    catch (e) {
+        y;
+    }
+}
+
+async function tryCatch2() {
+    var x, y;
+    try {
+        x;
+    }
+    catch (e) {
+        await y;
+    }
+}
+
+async function tryCatch3(): Promise<Function> {
+    var x, y;
+    try {
+        await x;
+    }
+    catch (e) {
+        return () => e;
+    }
+}
+async function tryFinally0() {
+    var x, y;
+    try {
+        x;
+    }
+    finally {
+        y;
+    }
+}
+
+async function tryFinally1() {
+    var x, y;
+    try {
+        await x;
+    }
+    finally {
+        y;
+    }
+}
+
+async function tryFinally2() {
+    var x, y;
+    try {
+        x;
+    }
+    finally {
+        await y;
+    }
+}
+
+async function tryCatchFinally0() {
+    var x, y, z;
+    try {
+        x;
+    }
+    catch (e) {
+        y;
+    }
+    finally {
+        z;
+    }
+}
+
+async function tryCatchFinally1() {
+    var x, y, z;
+    try {
+        await x;
+    }
+    catch (e) {
+        y;
+    }
+    finally {
+        z;
+    }
+}
+
+async function tryCatchFinally2() {
+    var x, y, z;
+    try {
+        x;
+    }
+    catch (e) {
+        await y;
+    }
+    finally {
+        z;
+    }
+}
+
+async function tryCatchFinally3() {
+    var x, y, z;
+    try {
+        x;
+    }
+    catch (e) {
+        y;
+    }
+    finally {
+        await z;
+    }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionWhileStatements.ts b/tests/cases/compiler/es5-asyncFunctionWhileStatements.ts
new file mode 100644
index 0000000000000..d31ab21ab7bf7
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionWhileStatements.ts
@@ -0,0 +1,80 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function whileStatement0() {
+    while (x) { y; }
+}
+
+async function whileStatement1() {
+    while (await x) { y; }
+}
+
+async function whileStatement2() {
+    while (x) { await y; }
+}
+
+async function whileStatement3() {
+    while (x) { continue; }
+}
+
+async function whileStatement4() {
+    while (await x) { continue; }
+}
+
+async function whileStatement5() {
+    while (x) { await y; continue; }
+}
+
+async function whileStatement6() {
+    while (x) { if (1) continue; await y; }
+}
+
+async function whileStatement7() {
+    A: while (x) { continue A; }
+}
+
+async function whileStatement8() {
+    B: while (await x) { continue B; }
+}
+
+async function whileStatement9() {
+    C: while (x) { await y; continue C; }
+}
+
+async function whileStatement10() {
+    D: while (x) { if (1) continue D; await y; }
+}
+
+async function whileStatement11() {
+    while (x) { break; }
+}
+
+async function whileStatement12() {
+    while (await x) { break; }
+}
+
+async function whileStatement13() {
+    while (x) { await y; break; }
+}
+
+async function whileStatement14() {
+    while (x) { if (1) break; await y; }
+}
+
+async function whileStatement15() {
+    E: while (x) { break E; }
+}
+
+async function whileStatement16() {
+    F: while (await x) { break F; }
+}
+
+async function whileStatement17() {
+    G: while (x) { await y; break G; }
+}
+
+async function whileStatement18() {
+    H: while (x) { if (1) break H; await y; }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-asyncFunctionWithStatements.ts b/tests/cases/compiler/es5-asyncFunctionWithStatements.ts
new file mode 100644
index 0000000000000..c82901ac9fd1e
--- /dev/null
+++ b/tests/cases/compiler/es5-asyncFunctionWithStatements.ts
@@ -0,0 +1,34 @@
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+// @target: ES5
+declare var x, y, z, a, b, c;
+
+async function withStatement0() {
+    with (x) {
+        y;
+    }
+}
+
+async function withStatement1() {
+    with (await x) {
+        y;
+    }
+}
+
+async function withStatement2() {
+    with (x) {
+        a;
+        await y;
+        b;
+    }
+}
+
+async function withStatement3() {
+    with (x) {
+        with (z) {
+            a;
+            await y;
+            b;
+        }
+    }
+}
\ No newline at end of file

From 278a350add2fe2d82f831b335d01f670b57a1408 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Wed, 15 Jun 2016 13:49:32 -0700
Subject: [PATCH 11/23] Add support for external helpers module, cleanup, and
 accept new baselines.

---
 src/compiler/checker.ts                       |  3 +
 src/compiler/emitter.ts                       | 55 +++++-------
 src/compiler/transformers/generators.ts       | 13 ++-
 .../disallowAsyncModifierInES5.errors.txt     | 27 ------
 .../reference/disallowAsyncModifierInES5.js   | 23 -----
 .../baselines/reference/es5-asyncFunction.js  | 55 +++++-------
 .../es5-importHelpersAsyncFunctions.js        | 83 +++++++++++++++++++
 .../es5-importHelpersAsyncFunctions.symbols   | 58 +++++++++++++
 .../es5-importHelpersAsyncFunctions.types     | 58 +++++++++++++
 .../compiler/disallowAsyncModifierInES5.ts    |  5 --
 .../es5-importHelpersAsyncFunctions.ts        | 21 +++++
 11 files changed, 273 insertions(+), 128 deletions(-)
 delete mode 100644 tests/baselines/reference/disallowAsyncModifierInES5.errors.txt
 delete mode 100644 tests/baselines/reference/disallowAsyncModifierInES5.js
 create mode 100644 tests/baselines/reference/es5-importHelpersAsyncFunctions.js
 create mode 100644 tests/baselines/reference/es5-importHelpersAsyncFunctions.symbols
 create mode 100644 tests/baselines/reference/es5-importHelpersAsyncFunctions.types
 delete mode 100644 tests/cases/compiler/disallowAsyncModifierInES5.ts
 create mode 100644 tests/cases/compiler/es5-importHelpersAsyncFunctions.ts

diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 9ec88e0be3ed5..19ddbcdac04cf 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -17892,6 +17892,9 @@ namespace ts {
                     }
                     if (requestedExternalEmitHelpers & NodeFlags.HasAsyncFunctions) {
                         verifyHelperSymbol(exports, "__awaiter", SymbolFlags.Value);
+                        if (languageVersion < ScriptTarget.ES6) {
+                            verifyHelperSymbol(exports, "__generator", SymbolFlags.Value);
+                        }
                     }
                 }
             }
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index 99b0535da47d8..09c785a24e36b 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -73,51 +73,40 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
 
         const generatorHelper = `
 var __generator = (this && this.__generator) || function (body) {
-    var _ = { label: 0, sent: function() { if (sent[0] === 1 /*throw*/) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent;
+    var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
     function step(op) {
-        if (_.flag) throw new TypeError("Generator is already executing.");
-        while (true) {
+        if (f) throw new TypeError("Generator is already executing.");
+        while (1) {
             if (_.done) switch (op[0]) {
-                case 0 /*next*/: return { value: void 0, done: true };
-                case 1 /*throw*/: case 6 /*catch*/: throw op[1];
-                case 2 /*return*/: return { value: op[1], done: true };
+                case 0: return { value: void 0, done: true };
+                case 1: case 6: throw op[1];
+                case 2: return { value: op[1], done: true };
             }
             try {
-                switch (_.flag = true, op[0]) {
-                    case 0 /*next*/: case 1 /*throw*/: sent = op; break;
-                    case 4 /*yield*/: return _.label++, { value: op[1], done: false };
-                    case 7 /*endfinally*/: op = _.stack.pop(), _.trys.pop(); continue;
+                switch (f = 1, op[0]) {
+                    case 0: case 1: sent = op; break;
+                    case 4: return _.label++, { value: op[1], done: false };
+                    case 7: op = _.stack.pop(), _.trys.pop(); continue;
                     default:
                         var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
-                        if (!r && (op[0] === 1 /*throw*/ || op[0] === 6 /*catch*/ || op[0] === 2 /*return*/)) {
-                            _.done = true;
-                            continue;
-                        }
-                        if (op[0] === 3 /*break*/ && (!r || (op[1] > r[0] && op[1] < r[3]))) {
-                            _.label = op[1];
-                        }
-                        else if (op[0] === 6 /*catch*/ && r && _.label < r[1]) {
-                            _.label = r[1], sent = op;
-                        }
-                        else if (r && _.label < r[2]) {
-                            _.label = r[2], _.stack.push(op);
-                        }
-                        else {
-                            if (r[2]) _.stack.pop();
-                            _.trys.pop();
-                            continue;
-                        }
+                        if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; }
+                        if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; }
+                        if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; }
+                        if (r && _.label < r[2]) { _.label = r[2], _.stack.push(op); break; }
+                        if (r[2]) { _.stack.pop(); }
+                        _.trys.pop();
+                        continue;
                 }
                 op = body(_);
             }
-            catch (e) { op = [6 /*catch*/, e]; }
-            finally { _.flag = false, sent = void 0; }
+            catch (e) { op = [6, e]; }
+            finally { f = 0, sent = void 0; }
         }
     }
     return {
-        next: function (v) { return step([0 /*next*/, v]); },
-        "throw": function (v) { return step([1 /*throw*/, v]); },
-        "return": function (v) { return step([2 /*return*/, v]); }
+        next: function (v) { return step([0, v]); },
+        "throw": function (v) { return step([1, v]); },
+        "return": function (v) { return step([2, v]); }
     };
 };`;
 
diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts
index 133ed01f09170..e11804bd467ca 100644
--- a/src/compiler/transformers/generators.ts
+++ b/src/compiler/transformers/generators.ts
@@ -137,11 +137,7 @@ namespace ts {
         Endfinally              // Marks the end of a `finally` block
     }
 
-    type OperationArguments = [Label]
-                            | [Label, Expression]
-                            | [Statement]
-                            | [Expression]
-                            | [Expression, Expression];
+    type OperationArguments = [Label] | [Label, Expression] | [Statement] | [Expression] | [Expression, Expression];
 
     // whether a generated code block is opening or closing at the current operation for a FunctionBuilder
     const enum BlockAction {
@@ -245,6 +241,7 @@ namespace ts {
         const previousOnSubstituteNode = context.onSubstituteNode;
         context.onSubstituteNode = onSubstituteNode;
 
+        let currentSourceFile: SourceFile;
         let renamedCatchVariables: Map<boolean>;
         let renamedCatchVariableDeclarations: Map<Identifier>;
 
@@ -297,7 +294,9 @@ namespace ts {
 
         function transformSourceFile(node: SourceFile) {
             if (node.transformFlags & TransformFlags.ContainsGenerator) {
-                return visitEachChild(node, visitor, context);
+                currentSourceFile = node;
+                node = visitEachChild(node, visitor, context);
+                currentSourceFile = undefined;
             }
 
             return node;
@@ -2550,7 +2549,7 @@ namespace ts {
 
             const buildResult = buildStatements();
             return createCall(
-                createIdentifier("__generator"),
+                createHelperName(currentSourceFile.externalHelpersModuleName, "__generator"),
                 /*typeArguments*/ undefined,
                 [setNodeEmitFlags(
                     createFunctionExpression(
diff --git a/tests/baselines/reference/disallowAsyncModifierInES5.errors.txt b/tests/baselines/reference/disallowAsyncModifierInES5.errors.txt
deleted file mode 100644
index eb3cc8218d18e..0000000000000
--- a/tests/baselines/reference/disallowAsyncModifierInES5.errors.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-error TS2318: Cannot find global type 'Promise'.
-tests/cases/compiler/disallowAsyncModifierInES5.ts(2,1): error TS1311: Async functions are only available when targeting ECMAScript 2015 or higher.
-tests/cases/compiler/disallowAsyncModifierInES5.ts(2,16): error TS1057: An async function or method must have a valid awaitable return type.
-tests/cases/compiler/disallowAsyncModifierInES5.ts(3,11): error TS1057: An async function or method must have a valid awaitable return type.
-tests/cases/compiler/disallowAsyncModifierInES5.ts(3,11): error TS1311: Async functions are only available when targeting ECMAScript 2015 or higher.
-tests/cases/compiler/disallowAsyncModifierInES5.ts(4,11): error TS1311: Async functions are only available when targeting ECMAScript 2015 or higher.
-tests/cases/compiler/disallowAsyncModifierInES5.ts(4,11): error TS1057: An async function or method must have a valid awaitable return type.
-
-
-!!! error TS2318: Cannot find global type 'Promise'.
-==== tests/cases/compiler/disallowAsyncModifierInES5.ts (6 errors) ====
-    
-    async function foo() { return 42; } // ERROR: Async functions are only available in ES6+
-    ~~~~~
-!!! error TS1311: Async functions are only available when targeting ECMAScript 2015 or higher.
-                   ~~~
-!!! error TS1057: An async function or method must have a valid awaitable return type.
-    let bar = async function () { return 42; } // OK, but should be an error
-              ~~~~~
-!!! error TS1057: An async function or method must have a valid awaitable return type.
-              ~~~~~
-!!! error TS1311: Async functions are only available when targeting ECMAScript 2015 or higher.
-    let baz = async () => 42; // OK, but should be an error
-              ~~~~~
-!!! error TS1311: Async functions are only available when targeting ECMAScript 2015 or higher.
-              ~~~~~~~~~~~~~~
-!!! error TS1057: An async function or method must have a valid awaitable return type.
\ No newline at end of file
diff --git a/tests/baselines/reference/disallowAsyncModifierInES5.js b/tests/baselines/reference/disallowAsyncModifierInES5.js
deleted file mode 100644
index e0997f1311068..0000000000000
--- a/tests/baselines/reference/disallowAsyncModifierInES5.js
+++ /dev/null
@@ -1,23 +0,0 @@
-//// [disallowAsyncModifierInES5.ts]
-
-async function foo() { return 42; } // ERROR: Async functions are only available in ES6+
-let bar = async function () { return 42; } // OK, but should be an error
-let baz = async () => 42; // OK, but should be an error
-
-//// [disallowAsyncModifierInES5.js]
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
-    return new (P || (P = Promise))(function (resolve, reject) {
-        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
-        function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
-        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
-        step((generator = generator.apply(thisArg, _arguments)).next());
-    });
-};
-var _this = this;
-function foo() {
-    return __awaiter(this, void 0, void 0, function* () { return 42; });
-} // ERROR: Async functions are only available in ES6+
-var bar = function () {
-    return __awaiter(this, void 0, void 0, function* () { return 42; });
-}; // OK, but should be an error
-var baz = function () { return __awaiter(_this, void 0, void 0, function* () { return 42; }); }; // OK, but should be an error
diff --git a/tests/baselines/reference/es5-asyncFunction.js b/tests/baselines/reference/es5-asyncFunction.js
index 28197f55bae48..57c9a7c05f67f 100644
--- a/tests/baselines/reference/es5-asyncFunction.js
+++ b/tests/baselines/reference/es5-asyncFunction.js
@@ -18,51 +18,40 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
     });
 };
 var __generator = (this && this.__generator) || function (body) {
-    var _ = { label: 0, sent: function() { if (sent[0] === 1 /*throw*/) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent;
+    var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
     function step(op) {
-        if (_.flag) throw new TypeError("Generator is already executing.");
-        while (true) {
+        if (f) throw new TypeError("Generator is already executing.");
+        while (1) {
             if (_.done) switch (op[0]) {
-                case 0 /*next*/: return { value: void 0, done: true };
-                case 1 /*throw*/: case 6 /*catch*/: throw op[1];
-                case 2 /*return*/: return { value: op[1], done: true };
+                case 0: return { value: void 0, done: true };
+                case 1: case 6: throw op[1];
+                case 2: return { value: op[1], done: true };
             }
             try {
-                switch (_.flag = true, op[0]) {
-                    case 0 /*next*/: case 1 /*throw*/: sent = op; break;
-                    case 4 /*yield*/: return _.label++, { value: op[1], done: false };
-                    case 7 /*endfinally*/: op = _.stack.pop(), _.trys.pop(); continue;
+                switch (f = 1, op[0]) {
+                    case 0: case 1: sent = op; break;
+                    case 4: return _.label++, { value: op[1], done: false };
+                    case 7: op = _.stack.pop(), _.trys.pop(); continue;
                     default:
                         var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
-                        if (!r && (op[0] === 1 /*throw*/ || op[0] === 6 /*catch*/ || op[0] === 2 /*return*/)) {
-                            _.done = true;
-                            continue;
-                        }
-                        if (op[0] === 3 /*break*/ && (!r || (op[1] > r[0] && op[1] < r[3]))) {
-                            _.label = op[1];
-                        }
-                        else if (op[0] === 6 /*catch*/ && r && _.label < r[1]) {
-                            _.label = r[1], sent = op;
-                        }
-                        else if (r && _.label < r[2]) {
-                            _.label = r[2], _.stack.push(op);
-                        }
-                        else {
-                            if (r[2]) _.stack.pop();
-                            _.trys.pop();
-                            continue;
-                        }
+                        if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; }
+                        if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; }
+                        if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; }
+                        if (r && _.label < r[2]) { _.label = r[2], _.stack.push(op); break; }
+                        if (r[2]) { _.stack.pop(); }
+                        _.trys.pop();
+                        continue;
                 }
                 op = body(_);
             }
-            catch (e) { op = [6 /*catch*/, e]; }
-            finally { _.flag = false, sent = void 0; }
+            catch (e) { op = [6, e]; }
+            finally { f = 0, sent = void 0; }
         }
     }
     return {
-        next: function (v) { return step([0 /*next*/, v]); },
-        "throw": function (v) { return step([1 /*throw*/, v]); },
-        "return": function (v) { return step([2 /*return*/, v]); }
+        next: function (v) { return step([0, v]); },
+        "throw": function (v) { return step([1, v]); },
+        "return": function (v) { return step([2, v]); }
     };
 };
 function empty() {
diff --git a/tests/baselines/reference/es5-importHelpersAsyncFunctions.js b/tests/baselines/reference/es5-importHelpersAsyncFunctions.js
new file mode 100644
index 0000000000000..b90e2248c2c53
--- /dev/null
+++ b/tests/baselines/reference/es5-importHelpersAsyncFunctions.js
@@ -0,0 +1,83 @@
+//// [tests/cases/compiler/es5-importHelpersAsyncFunctions.ts] ////
+
+//// [external.ts]
+export async function foo() {
+}
+
+//// [script.ts]
+async function foo() {
+}
+
+//// [tslib.d.ts]
+export declare function __extends(d: Function, b: Function): void;
+export declare function __assign(t: any, ...sources: any[]): any;
+export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
+export declare function __param(paramIndex: number, decorator: Function): Function;
+export declare function __metadata(metadataKey: any, metadataValue: any): Function;
+export declare function __awaiter(thisArg: any, _arguments: any, P: Function, generator: Function): any;
+export declare function __generator(body: Function): any;
+
+//// [external.js]
+"use strict";
+var tslib_1 = require("tslib");
+function foo() {
+    return tslib_1.__awaiter(this, void 0, void 0, function () {
+        return tslib_1.__generator(function (_a) {
+            return [2 /*return*/];
+        });
+    });
+}
+exports.foo = foo;
+//// [script.js]
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments)).next());
+    });
+};
+var __generator = (this && this.__generator) || function (body) {
+    var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
+    function step(op) {
+        if (f) throw new TypeError("Generator is already executing.");
+        while (1) {
+            if (_.done) switch (op[0]) {
+                case 0: return { value: void 0, done: true };
+                case 1: case 6: throw op[1];
+                case 2: return { value: op[1], done: true };
+            }
+            try {
+                switch (f = 1, op[0]) {
+                    case 0: case 1: sent = op; break;
+                    case 4: return _.label++, { value: op[1], done: false };
+                    case 7: op = _.stack.pop(), _.trys.pop(); continue;
+                    default:
+                        var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
+                        if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; }
+                        if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; }
+                        if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; }
+                        if (r && _.label < r[2]) { _.label = r[2], _.stack.push(op); break; }
+                        if (r[2]) { _.stack.pop(); }
+                        _.trys.pop();
+                        continue;
+                }
+                op = body(_);
+            }
+            catch (e) { op = [6, e]; }
+            finally { f = 0, sent = void 0; }
+        }
+    }
+    return {
+        next: function (v) { return step([0, v]); },
+        "throw": function (v) { return step([1, v]); },
+        "return": function (v) { return step([2, v]); }
+    };
+};
+function foo() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(function (_a) {
+            return [2 /*return*/];
+        });
+    });
+}
diff --git a/tests/baselines/reference/es5-importHelpersAsyncFunctions.symbols b/tests/baselines/reference/es5-importHelpersAsyncFunctions.symbols
new file mode 100644
index 0000000000000..89660cea722ad
--- /dev/null
+++ b/tests/baselines/reference/es5-importHelpersAsyncFunctions.symbols
@@ -0,0 +1,58 @@
+=== tests/cases/compiler/external.ts ===
+export async function foo() {
+>foo : Symbol(foo, Decl(external.ts, 0, 0))
+}
+
+=== tests/cases/compiler/script.ts ===
+async function foo() {
+>foo : Symbol(foo, Decl(script.ts, 0, 0))
+}
+
+=== tests/cases/compiler/tslib.d.ts ===
+export declare function __extends(d: Function, b: Function): void;
+>__extends : Symbol(__extends, Decl(tslib.d.ts, --, --))
+>d : Symbol(d, Decl(tslib.d.ts, --, --))
+>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
+>b : Symbol(b, Decl(tslib.d.ts, --, --))
+>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
+
+export declare function __assign(t: any, ...sources: any[]): any;
+>__assign : Symbol(__assign, Decl(tslib.d.ts, --, --))
+>t : Symbol(t, Decl(tslib.d.ts, --, --))
+>sources : Symbol(sources, Decl(tslib.d.ts, --, --))
+
+export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
+>__decorate : Symbol(__decorate, Decl(tslib.d.ts, --, --))
+>decorators : Symbol(decorators, Decl(tslib.d.ts, --, --))
+>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
+>target : Symbol(target, Decl(tslib.d.ts, --, --))
+>key : Symbol(key, Decl(tslib.d.ts, --, --))
+>desc : Symbol(desc, Decl(tslib.d.ts, --, --))
+
+export declare function __param(paramIndex: number, decorator: Function): Function;
+>__param : Symbol(__param, Decl(tslib.d.ts, --, --))
+>paramIndex : Symbol(paramIndex, Decl(tslib.d.ts, --, --))
+>decorator : Symbol(decorator, Decl(tslib.d.ts, --, --))
+>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
+>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
+
+export declare function __metadata(metadataKey: any, metadataValue: any): Function;
+>__metadata : Symbol(__metadata, Decl(tslib.d.ts, --, --))
+>metadataKey : Symbol(metadataKey, Decl(tslib.d.ts, --, --))
+>metadataValue : Symbol(metadataValue, Decl(tslib.d.ts, --, --))
+>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
+
+export declare function __awaiter(thisArg: any, _arguments: any, P: Function, generator: Function): any;
+>__awaiter : Symbol(__awaiter, Decl(tslib.d.ts, --, --))
+>thisArg : Symbol(thisArg, Decl(tslib.d.ts, --, --))
+>_arguments : Symbol(_arguments, Decl(tslib.d.ts, --, --))
+>P : Symbol(P, Decl(tslib.d.ts, --, --))
+>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
+>generator : Symbol(generator, Decl(tslib.d.ts, --, --))
+>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
+
+export declare function __generator(body: Function): any;
+>__generator : Symbol(__generator, Decl(tslib.d.ts, --, --))
+>body : Symbol(body, Decl(tslib.d.ts, --, --))
+>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
+
diff --git a/tests/baselines/reference/es5-importHelpersAsyncFunctions.types b/tests/baselines/reference/es5-importHelpersAsyncFunctions.types
new file mode 100644
index 0000000000000..9ceeee92bc84e
--- /dev/null
+++ b/tests/baselines/reference/es5-importHelpersAsyncFunctions.types
@@ -0,0 +1,58 @@
+=== tests/cases/compiler/external.ts ===
+export async function foo() {
+>foo : () => Promise<void>
+}
+
+=== tests/cases/compiler/script.ts ===
+async function foo() {
+>foo : () => Promise<void>
+}
+
+=== tests/cases/compiler/tslib.d.ts ===
+export declare function __extends(d: Function, b: Function): void;
+>__extends : (d: Function, b: Function) => void
+>d : Function
+>Function : Function
+>b : Function
+>Function : Function
+
+export declare function __assign(t: any, ...sources: any[]): any;
+>__assign : (t: any, ...sources: any[]) => any
+>t : any
+>sources : any[]
+
+export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
+>__decorate : (decorators: Function[], target: any, key?: string | symbol, desc?: any) => any
+>decorators : Function[]
+>Function : Function
+>target : any
+>key : string | symbol
+>desc : any
+
+export declare function __param(paramIndex: number, decorator: Function): Function;
+>__param : (paramIndex: number, decorator: Function) => Function
+>paramIndex : number
+>decorator : Function
+>Function : Function
+>Function : Function
+
+export declare function __metadata(metadataKey: any, metadataValue: any): Function;
+>__metadata : (metadataKey: any, metadataValue: any) => Function
+>metadataKey : any
+>metadataValue : any
+>Function : Function
+
+export declare function __awaiter(thisArg: any, _arguments: any, P: Function, generator: Function): any;
+>__awaiter : (thisArg: any, _arguments: any, P: Function, generator: Function) => any
+>thisArg : any
+>_arguments : any
+>P : Function
+>Function : Function
+>generator : Function
+>Function : Function
+
+export declare function __generator(body: Function): any;
+>__generator : (body: Function) => any
+>body : Function
+>Function : Function
+
diff --git a/tests/cases/compiler/disallowAsyncModifierInES5.ts b/tests/cases/compiler/disallowAsyncModifierInES5.ts
deleted file mode 100644
index 5417e678dcea8..0000000000000
--- a/tests/cases/compiler/disallowAsyncModifierInES5.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-// @target: es5
-
-async function foo() { return 42; } // ERROR: Async functions are only available in ES6+
-let bar = async function () { return 42; } // OK, but should be an error
-let baz = async () => 42; // OK, but should be an error
\ No newline at end of file
diff --git a/tests/cases/compiler/es5-importHelpersAsyncFunctions.ts b/tests/cases/compiler/es5-importHelpersAsyncFunctions.ts
new file mode 100644
index 0000000000000..87acc67a59b31
--- /dev/null
+++ b/tests/cases/compiler/es5-importHelpersAsyncFunctions.ts
@@ -0,0 +1,21 @@
+// @lib: es5,es2015.promise
+// @importHelpers: true
+// @target: es5
+// @module: commonjs
+// @moduleResolution: classic
+// @filename: external.ts
+export async function foo() {
+}
+
+// @filename: script.ts
+async function foo() {
+}
+
+// @filename: tslib.d.ts
+export declare function __extends(d: Function, b: Function): void;
+export declare function __assign(t: any, ...sources: any[]): any;
+export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
+export declare function __param(paramIndex: number, decorator: Function): Function;
+export declare function __metadata(metadataKey: any, metadataValue: any): Function;
+export declare function __awaiter(thisArg: any, _arguments: any, P: Function, generator: Function): any;
+export declare function __generator(body: Function): any;
\ No newline at end of file

From c11b5600b279b61315d060ebb80272d5ef949e72 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 27 Jun 2016 13:12:11 -0700
Subject: [PATCH 12/23] es6 test conformance cleanup

---
 .../arrowFunctionWithParameterNameAsync.js    |  6 -----
 ...rrowFunctionWithParameterNameAsync.symbols |  7 ------
 ...arrowFunctionWithParameterNameAsync_es6.js |  6 +++++
 ...FunctionWithParameterNameAsync_es6.symbols |  7 ++++++
 ...wFunctionWithParameterNameAsync_es6.types} |  2 +-
 .../asyncArrowFunction10_es6.errors.txt       | 16 ++----------
 .../reference/asyncArrowFunction10_es6.js     |  6 ++---
 ...syncMultiFile.js => asyncMultiFile_es6.js} |  2 +-
 ...ile.symbols => asyncMultiFile_es6.symbols} |  0
 ...ltiFile.types => asyncMultiFile_es6.types} |  0
 .../reference/awaitBinaryExpression1_es6.js   | 10 +++++---
 .../awaitBinaryExpression1_es6.symbols        | 17 ++++++++++---
 .../awaitBinaryExpression1_es6.types          | 16 +++++++++---
 .../reference/awaitBinaryExpression2_es6.js   | 10 +++++---
 .../awaitBinaryExpression2_es6.symbols        | 17 ++++++++++---
 .../awaitBinaryExpression2_es6.types          | 16 +++++++++---
 .../reference/awaitBinaryExpression3_es6.js   | 10 +++++---
 .../awaitBinaryExpression3_es6.symbols        | 17 ++++++++++---
 .../awaitBinaryExpression3_es6.types          | 16 +++++++++---
 .../reference/awaitBinaryExpression4_es6.js   | 10 +++++---
 .../awaitBinaryExpression4_es6.symbols        | 19 ++++++++++----
 .../awaitBinaryExpression4_es6.types          | 16 +++++++++---
 .../reference/awaitBinaryExpression5_es6.js   | 10 +++++---
 .../awaitBinaryExpression5_es6.symbols        | 25 +++++++++++++------
 .../awaitBinaryExpression5_es6.types          | 16 +++++++++---
 .../reference/awaitCallExpression1_es6.js     | 10 +++++---
 .../awaitCallExpression1_es6.symbols          | 17 ++++++++++---
 .../reference/awaitCallExpression1_es6.types  | 16 +++++++++---
 .../reference/awaitCallExpression2_es6.js     | 10 +++++---
 .../awaitCallExpression2_es6.symbols          | 17 ++++++++++---
 .../reference/awaitCallExpression2_es6.types  | 16 +++++++++---
 .../reference/awaitCallExpression3_es6.js     | 10 +++++---
 .../awaitCallExpression3_es6.symbols          | 17 ++++++++++---
 .../reference/awaitCallExpression3_es6.types  | 16 +++++++++---
 .../reference/awaitCallExpression4_es6.js     | 10 +++++---
 .../awaitCallExpression4_es6.symbols          | 17 ++++++++++---
 .../reference/awaitCallExpression4_es6.types  | 16 +++++++++---
 .../reference/awaitCallExpression5_es6.js     | 10 +++++---
 .../awaitCallExpression5_es6.symbols          | 17 ++++++++++---
 .../reference/awaitCallExpression5_es6.types  | 16 +++++++++---
 .../reference/awaitCallExpression6_es6.js     | 10 +++++---
 .../awaitCallExpression6_es6.symbols          | 17 ++++++++++---
 .../reference/awaitCallExpression6_es6.types  | 16 +++++++++---
 .../reference/awaitCallExpression7_es6.js     | 10 +++++---
 .../awaitCallExpression7_es6.symbols          | 17 ++++++++++---
 .../reference/awaitCallExpression7_es6.types  | 16 +++++++++---
 .../reference/awaitCallExpression8_es6.js     | 10 +++++---
 .../awaitCallExpression8_es6.symbols          | 17 ++++++++++---
 .../reference/awaitCallExpression8_es6.types  | 16 +++++++++---
 .../reference/awaitClassExpression_es6.js     | 16 ++++++++++++
 .../awaitClassExpression_es6.symbols          | 18 +++++++++++++
 .../reference/awaitClassExpression_es6.types  | 20 +++++++++++++++
 tests/baselines/reference/awaitUnion_es6.js   |  2 +-
 .../reference/awaitUnion_es6.symbols          |  2 +-
 .../baselines/reference/awaitUnion_es6.types  |  2 +-
 ...rrowFunctionWithParameterNameAsync_es6.ts} |  0
 .../asyncArrowFunction10_es6.ts               |  2 +-
 ...syncMultiFile.ts => asyncMultiFile_es6.ts} |  0
 .../awaitBinaryExpression1_es6.ts             |  6 +++--
 .../awaitBinaryExpression2_es6.ts             |  6 +++--
 .../awaitBinaryExpression3_es6.ts             |  6 +++--
 .../awaitBinaryExpression4_es6.ts             |  6 +++--
 .../awaitBinaryExpression5_es6.ts             |  6 +++--
 .../awaitCallExpression1_es6.ts               |  6 +++--
 .../awaitCallExpression2_es6.ts               |  6 +++--
 .../awaitCallExpression3_es6.ts               |  6 +++--
 .../awaitCallExpression4_es6.ts               |  6 +++--
 .../awaitCallExpression5_es6.ts               |  6 +++--
 .../awaitCallExpression6_es6.ts               |  6 +++--
 .../awaitCallExpression7_es6.ts               |  6 +++--
 .../awaitCallExpression8_es6.ts               |  6 +++--
 .../async/es6/awaitClassExpression_es6.ts     |  9 +++++++
 .../conformance/async/es6/awaitUnion_es6.ts   |  2 +-
 73 files changed, 548 insertions(+), 224 deletions(-)
 delete mode 100644 tests/baselines/reference/arrowFunctionWithParameterNameAsync.js
 delete mode 100644 tests/baselines/reference/arrowFunctionWithParameterNameAsync.symbols
 create mode 100644 tests/baselines/reference/arrowFunctionWithParameterNameAsync_es6.js
 create mode 100644 tests/baselines/reference/arrowFunctionWithParameterNameAsync_es6.symbols
 rename tests/baselines/reference/{arrowFunctionWithParameterNameAsync.types => arrowFunctionWithParameterNameAsync_es6.types} (79%)
 rename tests/baselines/reference/{asyncMultiFile.js => asyncMultiFile_es6.js} (89%)
 rename tests/baselines/reference/{asyncMultiFile.symbols => asyncMultiFile_es6.symbols} (100%)
 rename tests/baselines/reference/{asyncMultiFile.types => asyncMultiFile_es6.types} (100%)
 create mode 100644 tests/baselines/reference/awaitClassExpression_es6.js
 create mode 100644 tests/baselines/reference/awaitClassExpression_es6.symbols
 create mode 100644 tests/baselines/reference/awaitClassExpression_es6.types
 rename tests/cases/conformance/async/es6/asyncArrowFunction/{arrowFunctionWithParameterNameAsync.ts => arrowFunctionWithParameterNameAsync_es6.ts} (100%)
 rename tests/cases/conformance/async/es6/{asyncMultiFile.ts => asyncMultiFile_es6.ts} (100%)
 create mode 100644 tests/cases/conformance/async/es6/awaitClassExpression_es6.ts

diff --git a/tests/baselines/reference/arrowFunctionWithParameterNameAsync.js b/tests/baselines/reference/arrowFunctionWithParameterNameAsync.js
deleted file mode 100644
index 0baea798c03c2..0000000000000
--- a/tests/baselines/reference/arrowFunctionWithParameterNameAsync.js
+++ /dev/null
@@ -1,6 +0,0 @@
-//// [arrowFunctionWithParameterNameAsync.ts]
-
-const x = async => async;
-
-//// [arrowFunctionWithParameterNameAsync.js]
-var x = function (async) { return async; };
diff --git a/tests/baselines/reference/arrowFunctionWithParameterNameAsync.symbols b/tests/baselines/reference/arrowFunctionWithParameterNameAsync.symbols
deleted file mode 100644
index 26f36f48df7a4..0000000000000
--- a/tests/baselines/reference/arrowFunctionWithParameterNameAsync.symbols
+++ /dev/null
@@ -1,7 +0,0 @@
-=== tests/cases/conformance/async/es6/asyncArrowFunction/arrowFunctionWithParameterNameAsync.ts ===
-
-const x = async => async;
->x : Symbol(x, Decl(arrowFunctionWithParameterNameAsync.ts, 1, 5))
->async : Symbol(async, Decl(arrowFunctionWithParameterNameAsync.ts, 1, 9))
->async : Symbol(async, Decl(arrowFunctionWithParameterNameAsync.ts, 1, 9))
-
diff --git a/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es6.js b/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es6.js
new file mode 100644
index 0000000000000..8527fefc50db9
--- /dev/null
+++ b/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es6.js
@@ -0,0 +1,6 @@
+//// [arrowFunctionWithParameterNameAsync_es6.ts]
+
+const x = async => async;
+
+//// [arrowFunctionWithParameterNameAsync_es6.js]
+var x = function (async) { return async; };
diff --git a/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es6.symbols b/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es6.symbols
new file mode 100644
index 0000000000000..73e5f31aeb3d0
--- /dev/null
+++ b/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es6.symbols
@@ -0,0 +1,7 @@
+=== tests/cases/conformance/async/es6/asyncArrowFunction/arrowFunctionWithParameterNameAsync_es6.ts ===
+
+const x = async => async;
+>x : Symbol(x, Decl(arrowFunctionWithParameterNameAsync_es6.ts, 1, 5))
+>async : Symbol(async, Decl(arrowFunctionWithParameterNameAsync_es6.ts, 1, 9))
+>async : Symbol(async, Decl(arrowFunctionWithParameterNameAsync_es6.ts, 1, 9))
+
diff --git a/tests/baselines/reference/arrowFunctionWithParameterNameAsync.types b/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es6.types
similarity index 79%
rename from tests/baselines/reference/arrowFunctionWithParameterNameAsync.types
rename to tests/baselines/reference/arrowFunctionWithParameterNameAsync_es6.types
index 4bdc60935eafd..b6a19fe30edca 100644
--- a/tests/baselines/reference/arrowFunctionWithParameterNameAsync.types
+++ b/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es6.types
@@ -1,4 +1,4 @@
-=== tests/cases/conformance/async/es6/asyncArrowFunction/arrowFunctionWithParameterNameAsync.ts ===
+=== tests/cases/conformance/async/es6/asyncArrowFunction/arrowFunctionWithParameterNameAsync_es6.ts ===
 
 const x = async => async;
 >x : (async: any) => any
diff --git a/tests/baselines/reference/asyncArrowFunction10_es6.errors.txt b/tests/baselines/reference/asyncArrowFunction10_es6.errors.txt
index 08e59e69b9f15..b5ea2a9d926c4 100644
--- a/tests/baselines/reference/asyncArrowFunction10_es6.errors.txt
+++ b/tests/baselines/reference/asyncArrowFunction10_es6.errors.txt
@@ -1,21 +1,9 @@
-tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction10_es6.ts(2,11): error TS2304: Cannot find name 'async'.
-tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction10_es6.ts(2,17): error TS1005: ',' expected.
-tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction10_es6.ts(2,20): error TS1005: '=' expected.
-tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction10_es6.ts(2,24): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
 tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction10_es6.ts(4,11): error TS2304: Cannot find name 'await'.
 
 
-==== tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction10_es6.ts (5 errors) ====
+==== tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction10_es6.ts (1 errors) ====
     
-    var foo = async foo(): Promise<void> => {
-              ~~~~~
-!!! error TS2304: Cannot find name 'async'.
-                    ~~~
-!!! error TS1005: ',' expected.
-                       ~
-!!! error TS1005: '=' expected.
-                           ~~~~~~~~~~~~~
-!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
+    var foo = async (): Promise<void> => {
        // Legal to use 'await' in a type context.
        var v: await;
               ~~~~~
diff --git a/tests/baselines/reference/asyncArrowFunction10_es6.js b/tests/baselines/reference/asyncArrowFunction10_es6.js
index 23b2c3af80edd..301e41544bbc9 100644
--- a/tests/baselines/reference/asyncArrowFunction10_es6.js
+++ b/tests/baselines/reference/asyncArrowFunction10_es6.js
@@ -1,13 +1,13 @@
 //// [asyncArrowFunction10_es6.ts]
 
-var foo = async foo(): Promise<void> => {
+var foo = async (): Promise<void> => {
    // Legal to use 'await' in a type context.
    var v: await;
 }
 
 
 //// [asyncArrowFunction10_es6.js]
-var foo = async, foo = () => {
+var foo = () => __awaiter(this, void 0, void 0, function* () {
     // Legal to use 'await' in a type context.
     var v;
-};
+});
diff --git a/tests/baselines/reference/asyncMultiFile.js b/tests/baselines/reference/asyncMultiFile_es6.js
similarity index 89%
rename from tests/baselines/reference/asyncMultiFile.js
rename to tests/baselines/reference/asyncMultiFile_es6.js
index cbf3445ecc992..08d63521fb5b7 100644
--- a/tests/baselines/reference/asyncMultiFile.js
+++ b/tests/baselines/reference/asyncMultiFile_es6.js
@@ -1,4 +1,4 @@
-//// [tests/cases/conformance/async/es6/asyncMultiFile.ts] ////
+//// [tests/cases/conformance/async/es6/asyncMultiFile_es6.ts] ////
 
 //// [a.ts]
 async function f() {}
diff --git a/tests/baselines/reference/asyncMultiFile.symbols b/tests/baselines/reference/asyncMultiFile_es6.symbols
similarity index 100%
rename from tests/baselines/reference/asyncMultiFile.symbols
rename to tests/baselines/reference/asyncMultiFile_es6.symbols
diff --git a/tests/baselines/reference/asyncMultiFile.types b/tests/baselines/reference/asyncMultiFile_es6.types
similarity index 100%
rename from tests/baselines/reference/asyncMultiFile.types
rename to tests/baselines/reference/asyncMultiFile_es6.types
diff --git a/tests/baselines/reference/awaitBinaryExpression1_es6.js b/tests/baselines/reference/awaitBinaryExpression1_es6.js
index a19e94353d595..83979a5b19b5b 100644
--- a/tests/baselines/reference/awaitBinaryExpression1_es6.js
+++ b/tests/baselines/reference/awaitBinaryExpression1_es6.js
@@ -1,17 +1,19 @@
 //// [awaitBinaryExpression1_es6.ts]
 declare var a: boolean;
 declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = await p || a;
-    "after";
+    after();
 }
 
 //// [awaitBinaryExpression1_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var b = (yield p) || a;
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression1_es6.symbols b/tests/baselines/reference/awaitBinaryExpression1_es6.symbols
index aee3dbefe966c..0f05f6521cb2f 100644
--- a/tests/baselines/reference/awaitBinaryExpression1_es6.symbols
+++ b/tests/baselines/reference/awaitBinaryExpression1_es6.symbols
@@ -6,15 +6,24 @@ declare var p: Promise<boolean>;
 >p : Symbol(p, Decl(awaitBinaryExpression1_es6.ts, 1, 11))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitBinaryExpression1_es6.ts, 1, 32))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitBinaryExpression1_es6.ts, 2, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitBinaryExpression1_es6.ts, 1, 32))
+>func : Symbol(func, Decl(awaitBinaryExpression1_es6.ts, 3, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitBinaryExpression1_es6.ts, 1, 32))
+
     var b = await p || a;
->b : Symbol(b, Decl(awaitBinaryExpression1_es6.ts, 4, 7))
+>b : Symbol(b, Decl(awaitBinaryExpression1_es6.ts, 6, 7))
 >p : Symbol(p, Decl(awaitBinaryExpression1_es6.ts, 1, 11))
 >a : Symbol(a, Decl(awaitBinaryExpression1_es6.ts, 0, 11))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitBinaryExpression1_es6.ts, 2, 32))
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression1_es6.types b/tests/baselines/reference/awaitBinaryExpression1_es6.types
index 4718f5f8fe9a2..6078e2b6dff76 100644
--- a/tests/baselines/reference/awaitBinaryExpression1_es6.types
+++ b/tests/baselines/reference/awaitBinaryExpression1_es6.types
@@ -6,12 +6,19 @@ declare var p: Promise<boolean>;
 >p : Promise<boolean>
 >Promise : Promise<T>
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var b = await p || a;
 >b : boolean
@@ -20,6 +27,7 @@ async function func(): Promise<void> {
 >p : Promise<boolean>
 >a : boolean
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression2_es6.js b/tests/baselines/reference/awaitBinaryExpression2_es6.js
index 7fb1a70446b26..a40a948576de7 100644
--- a/tests/baselines/reference/awaitBinaryExpression2_es6.js
+++ b/tests/baselines/reference/awaitBinaryExpression2_es6.js
@@ -1,17 +1,19 @@
 //// [awaitBinaryExpression2_es6.ts]
 declare var a: boolean;
 declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = await p && a;
-    "after";
+    after();
 }
 
 //// [awaitBinaryExpression2_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var b = (yield p) && a;
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression2_es6.symbols b/tests/baselines/reference/awaitBinaryExpression2_es6.symbols
index a4ed0ec14bd5a..518e6eec528a0 100644
--- a/tests/baselines/reference/awaitBinaryExpression2_es6.symbols
+++ b/tests/baselines/reference/awaitBinaryExpression2_es6.symbols
@@ -6,15 +6,24 @@ declare var p: Promise<boolean>;
 >p : Symbol(p, Decl(awaitBinaryExpression2_es6.ts, 1, 11))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitBinaryExpression2_es6.ts, 1, 32))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitBinaryExpression2_es6.ts, 2, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitBinaryExpression2_es6.ts, 1, 32))
+>func : Symbol(func, Decl(awaitBinaryExpression2_es6.ts, 3, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitBinaryExpression2_es6.ts, 1, 32))
+
     var b = await p && a;
->b : Symbol(b, Decl(awaitBinaryExpression2_es6.ts, 4, 7))
+>b : Symbol(b, Decl(awaitBinaryExpression2_es6.ts, 6, 7))
 >p : Symbol(p, Decl(awaitBinaryExpression2_es6.ts, 1, 11))
 >a : Symbol(a, Decl(awaitBinaryExpression2_es6.ts, 0, 11))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitBinaryExpression2_es6.ts, 2, 32))
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression2_es6.types b/tests/baselines/reference/awaitBinaryExpression2_es6.types
index 6154377a6f1df..5f092675e8595 100644
--- a/tests/baselines/reference/awaitBinaryExpression2_es6.types
+++ b/tests/baselines/reference/awaitBinaryExpression2_es6.types
@@ -6,12 +6,19 @@ declare var p: Promise<boolean>;
 >p : Promise<boolean>
 >Promise : Promise<T>
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var b = await p && a;
 >b : boolean
@@ -20,6 +27,7 @@ async function func(): Promise<void> {
 >p : Promise<boolean>
 >a : boolean
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression3_es6.js b/tests/baselines/reference/awaitBinaryExpression3_es6.js
index f845ce1242148..56092a490b3ea 100644
--- a/tests/baselines/reference/awaitBinaryExpression3_es6.js
+++ b/tests/baselines/reference/awaitBinaryExpression3_es6.js
@@ -1,17 +1,19 @@
 //// [awaitBinaryExpression3_es6.ts]
 declare var a: number;
 declare var p: Promise<number>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = await p + a;
-    "after";
+    after();
 }
 
 //// [awaitBinaryExpression3_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var b = (yield p) + a;
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression3_es6.symbols b/tests/baselines/reference/awaitBinaryExpression3_es6.symbols
index 4b3beb9d9a5ce..0d653c1ff7b42 100644
--- a/tests/baselines/reference/awaitBinaryExpression3_es6.symbols
+++ b/tests/baselines/reference/awaitBinaryExpression3_es6.symbols
@@ -6,15 +6,24 @@ declare var p: Promise<number>;
 >p : Symbol(p, Decl(awaitBinaryExpression3_es6.ts, 1, 11))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitBinaryExpression3_es6.ts, 1, 31))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitBinaryExpression3_es6.ts, 2, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitBinaryExpression3_es6.ts, 1, 31))
+>func : Symbol(func, Decl(awaitBinaryExpression3_es6.ts, 3, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitBinaryExpression3_es6.ts, 1, 31))
+
     var b = await p + a;
->b : Symbol(b, Decl(awaitBinaryExpression3_es6.ts, 4, 7))
+>b : Symbol(b, Decl(awaitBinaryExpression3_es6.ts, 6, 7))
 >p : Symbol(p, Decl(awaitBinaryExpression3_es6.ts, 1, 11))
 >a : Symbol(a, Decl(awaitBinaryExpression3_es6.ts, 0, 11))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitBinaryExpression3_es6.ts, 2, 32))
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression3_es6.types b/tests/baselines/reference/awaitBinaryExpression3_es6.types
index 2d5b087d6e38a..98bff3b94394f 100644
--- a/tests/baselines/reference/awaitBinaryExpression3_es6.types
+++ b/tests/baselines/reference/awaitBinaryExpression3_es6.types
@@ -6,12 +6,19 @@ declare var p: Promise<number>;
 >p : Promise<number>
 >Promise : Promise<T>
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var b = await p + a;
 >b : number
@@ -20,6 +27,7 @@ async function func(): Promise<void> {
 >p : Promise<number>
 >a : number
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression4_es6.js b/tests/baselines/reference/awaitBinaryExpression4_es6.js
index b6e14c8248761..99d568c0227c7 100644
--- a/tests/baselines/reference/awaitBinaryExpression4_es6.js
+++ b/tests/baselines/reference/awaitBinaryExpression4_es6.js
@@ -1,17 +1,19 @@
 //// [awaitBinaryExpression4_es6.ts]
 declare var a: boolean;
 declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = await p, a;
-    "after";
+    after();
 }
 
 //// [awaitBinaryExpression4_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var b = yield p, a;
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression4_es6.symbols b/tests/baselines/reference/awaitBinaryExpression4_es6.symbols
index 1c52cbb48eff0..c7a1b17eaa82b 100644
--- a/tests/baselines/reference/awaitBinaryExpression4_es6.symbols
+++ b/tests/baselines/reference/awaitBinaryExpression4_es6.symbols
@@ -6,15 +6,24 @@ declare var p: Promise<boolean>;
 >p : Symbol(p, Decl(awaitBinaryExpression4_es6.ts, 1, 11))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitBinaryExpression4_es6.ts, 1, 32))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitBinaryExpression4_es6.ts, 2, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitBinaryExpression4_es6.ts, 1, 32))
+>func : Symbol(func, Decl(awaitBinaryExpression4_es6.ts, 3, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitBinaryExpression4_es6.ts, 1, 32))
+
     var b = await p, a;
->b : Symbol(b, Decl(awaitBinaryExpression4_es6.ts, 4, 7))
+>b : Symbol(b, Decl(awaitBinaryExpression4_es6.ts, 6, 7))
 >p : Symbol(p, Decl(awaitBinaryExpression4_es6.ts, 1, 11))
->a : Symbol(a, Decl(awaitBinaryExpression4_es6.ts, 4, 20))
+>a : Symbol(a, Decl(awaitBinaryExpression4_es6.ts, 6, 20))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitBinaryExpression4_es6.ts, 2, 32))
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression4_es6.types b/tests/baselines/reference/awaitBinaryExpression4_es6.types
index 80135203a8237..672d862416826 100644
--- a/tests/baselines/reference/awaitBinaryExpression4_es6.types
+++ b/tests/baselines/reference/awaitBinaryExpression4_es6.types
@@ -6,12 +6,19 @@ declare var p: Promise<boolean>;
 >p : Promise<boolean>
 >Promise : Promise<T>
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var b = await p, a;
 >b : boolean
@@ -19,6 +26,7 @@ async function func(): Promise<void> {
 >p : Promise<boolean>
 >a : any
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression5_es6.js b/tests/baselines/reference/awaitBinaryExpression5_es6.js
index 65a5bbfee777f..1b5d7677b5229 100644
--- a/tests/baselines/reference/awaitBinaryExpression5_es6.js
+++ b/tests/baselines/reference/awaitBinaryExpression5_es6.js
@@ -1,19 +1,21 @@
 //// [awaitBinaryExpression5_es6.ts]
 declare var a: boolean;
 declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var o: { a: boolean; };
     o.a = await p;
-    "after";
+    after();
 }
 
 //// [awaitBinaryExpression5_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var o;
         o.a = yield p;
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression5_es6.symbols b/tests/baselines/reference/awaitBinaryExpression5_es6.symbols
index 28f96aa55f5af..57a7958a13cff 100644
--- a/tests/baselines/reference/awaitBinaryExpression5_es6.symbols
+++ b/tests/baselines/reference/awaitBinaryExpression5_es6.symbols
@@ -6,20 +6,29 @@ declare var p: Promise<boolean>;
 >p : Symbol(p, Decl(awaitBinaryExpression5_es6.ts, 1, 11))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitBinaryExpression5_es6.ts, 1, 32))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitBinaryExpression5_es6.ts, 2, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitBinaryExpression5_es6.ts, 1, 32))
+>func : Symbol(func, Decl(awaitBinaryExpression5_es6.ts, 3, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitBinaryExpression5_es6.ts, 1, 32))
+
     var o: { a: boolean; };
->o : Symbol(o, Decl(awaitBinaryExpression5_es6.ts, 4, 7))
->a : Symbol(a, Decl(awaitBinaryExpression5_es6.ts, 4, 12))
+>o : Symbol(o, Decl(awaitBinaryExpression5_es6.ts, 6, 7))
+>a : Symbol(a, Decl(awaitBinaryExpression5_es6.ts, 6, 12))
 
     o.a = await p;
->o.a : Symbol(a, Decl(awaitBinaryExpression5_es6.ts, 4, 12))
->o : Symbol(o, Decl(awaitBinaryExpression5_es6.ts, 4, 7))
->a : Symbol(a, Decl(awaitBinaryExpression5_es6.ts, 4, 12))
+>o.a : Symbol(a, Decl(awaitBinaryExpression5_es6.ts, 6, 12))
+>o : Symbol(o, Decl(awaitBinaryExpression5_es6.ts, 6, 7))
+>a : Symbol(a, Decl(awaitBinaryExpression5_es6.ts, 6, 12))
 >p : Symbol(p, Decl(awaitBinaryExpression5_es6.ts, 1, 11))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitBinaryExpression5_es6.ts, 2, 32))
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression5_es6.types b/tests/baselines/reference/awaitBinaryExpression5_es6.types
index 8b76b6f8b883b..649d160a847f0 100644
--- a/tests/baselines/reference/awaitBinaryExpression5_es6.types
+++ b/tests/baselines/reference/awaitBinaryExpression5_es6.types
@@ -6,12 +6,19 @@ declare var p: Promise<boolean>;
 >p : Promise<boolean>
 >Promise : Promise<T>
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var o: { a: boolean; };
 >o : { a: boolean; }
@@ -25,6 +32,7 @@ async function func(): Promise<void> {
 >await p : boolean
 >p : Promise<boolean>
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitCallExpression1_es6.js b/tests/baselines/reference/awaitCallExpression1_es6.js
index aeeb598e3bf18..19ac51a6dad2d 100644
--- a/tests/baselines/reference/awaitCallExpression1_es6.js
+++ b/tests/baselines/reference/awaitCallExpression1_es6.js
@@ -5,17 +5,19 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = fn(a, a, a);
-    "after";
+    after();
 }
 
 //// [awaitCallExpression1_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var b = fn(a, a, a);
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitCallExpression1_es6.symbols b/tests/baselines/reference/awaitCallExpression1_es6.symbols
index c4a91817a46c0..1b1deb0f5795f 100644
--- a/tests/baselines/reference/awaitCallExpression1_es6.symbols
+++ b/tests/baselines/reference/awaitCallExpression1_es6.symbols
@@ -34,17 +34,26 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : Symbol(arg1, Decl(awaitCallExpression1_es6.ts, 5, 43))
 >arg2 : Symbol(arg2, Decl(awaitCallExpression1_es6.ts, 5, 58))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression1_es6.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression1_es6.ts, 6, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitCallExpression1_es6.ts, 5, 84))
+>func : Symbol(func, Decl(awaitCallExpression1_es6.ts, 7, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitCallExpression1_es6.ts, 5, 84))
+
     var b = fn(a, a, a);
->b : Symbol(b, Decl(awaitCallExpression1_es6.ts, 8, 7))
+>b : Symbol(b, Decl(awaitCallExpression1_es6.ts, 10, 7))
 >fn : Symbol(fn, Decl(awaitCallExpression1_es6.ts, 1, 32))
 >a : Symbol(a, Decl(awaitCallExpression1_es6.ts, 0, 11))
 >a : Symbol(a, Decl(awaitCallExpression1_es6.ts, 0, 11))
 >a : Symbol(a, Decl(awaitCallExpression1_es6.ts, 0, 11))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitCallExpression1_es6.ts, 6, 32))
 }
diff --git a/tests/baselines/reference/awaitCallExpression1_es6.types b/tests/baselines/reference/awaitCallExpression1_es6.types
index 334175b7edbcd..3807379a2f29f 100644
--- a/tests/baselines/reference/awaitCallExpression1_es6.types
+++ b/tests/baselines/reference/awaitCallExpression1_es6.types
@@ -34,12 +34,19 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : boolean
 >arg2 : boolean
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var b = fn(a, a, a);
 >b : void
@@ -49,6 +56,7 @@ async function func(): Promise<void> {
 >a : boolean
 >a : boolean
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitCallExpression2_es6.js b/tests/baselines/reference/awaitCallExpression2_es6.js
index b41735275a842..d8a45fa1bf89a 100644
--- a/tests/baselines/reference/awaitCallExpression2_es6.js
+++ b/tests/baselines/reference/awaitCallExpression2_es6.js
@@ -5,17 +5,19 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = fn(await p, a, a);
-    "after";
+    after();
 }
 
 //// [awaitCallExpression2_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var b = fn(yield p, a, a);
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitCallExpression2_es6.symbols b/tests/baselines/reference/awaitCallExpression2_es6.symbols
index 3931e28045d19..d7f3cc0d4bd0a 100644
--- a/tests/baselines/reference/awaitCallExpression2_es6.symbols
+++ b/tests/baselines/reference/awaitCallExpression2_es6.symbols
@@ -34,17 +34,26 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : Symbol(arg1, Decl(awaitCallExpression2_es6.ts, 5, 43))
 >arg2 : Symbol(arg2, Decl(awaitCallExpression2_es6.ts, 5, 58))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression2_es6.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression2_es6.ts, 6, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitCallExpression2_es6.ts, 5, 84))
+>func : Symbol(func, Decl(awaitCallExpression2_es6.ts, 7, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitCallExpression2_es6.ts, 5, 84))
+
     var b = fn(await p, a, a);
->b : Symbol(b, Decl(awaitCallExpression2_es6.ts, 8, 7))
+>b : Symbol(b, Decl(awaitCallExpression2_es6.ts, 10, 7))
 >fn : Symbol(fn, Decl(awaitCallExpression2_es6.ts, 1, 32))
 >p : Symbol(p, Decl(awaitCallExpression2_es6.ts, 1, 11))
 >a : Symbol(a, Decl(awaitCallExpression2_es6.ts, 0, 11))
 >a : Symbol(a, Decl(awaitCallExpression2_es6.ts, 0, 11))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitCallExpression2_es6.ts, 6, 32))
 }
diff --git a/tests/baselines/reference/awaitCallExpression2_es6.types b/tests/baselines/reference/awaitCallExpression2_es6.types
index 1617f4a14ff26..8758fea7f957d 100644
--- a/tests/baselines/reference/awaitCallExpression2_es6.types
+++ b/tests/baselines/reference/awaitCallExpression2_es6.types
@@ -34,12 +34,19 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : boolean
 >arg2 : boolean
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var b = fn(await p, a, a);
 >b : void
@@ -50,6 +57,7 @@ async function func(): Promise<void> {
 >a : boolean
 >a : boolean
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitCallExpression3_es6.js b/tests/baselines/reference/awaitCallExpression3_es6.js
index 74dee3e7e427c..cf19e28b8679e 100644
--- a/tests/baselines/reference/awaitCallExpression3_es6.js
+++ b/tests/baselines/reference/awaitCallExpression3_es6.js
@@ -5,17 +5,19 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = fn(a, await p, a);
-    "after";
+    after();
 }
 
 //// [awaitCallExpression3_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var b = fn(a, yield p, a);
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitCallExpression3_es6.symbols b/tests/baselines/reference/awaitCallExpression3_es6.symbols
index 2002748c9ba2c..14b6f35bc30de 100644
--- a/tests/baselines/reference/awaitCallExpression3_es6.symbols
+++ b/tests/baselines/reference/awaitCallExpression3_es6.symbols
@@ -34,17 +34,26 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : Symbol(arg1, Decl(awaitCallExpression3_es6.ts, 5, 43))
 >arg2 : Symbol(arg2, Decl(awaitCallExpression3_es6.ts, 5, 58))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression3_es6.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression3_es6.ts, 6, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitCallExpression3_es6.ts, 5, 84))
+>func : Symbol(func, Decl(awaitCallExpression3_es6.ts, 7, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitCallExpression3_es6.ts, 5, 84))
+
     var b = fn(a, await p, a);
->b : Symbol(b, Decl(awaitCallExpression3_es6.ts, 8, 7))
+>b : Symbol(b, Decl(awaitCallExpression3_es6.ts, 10, 7))
 >fn : Symbol(fn, Decl(awaitCallExpression3_es6.ts, 1, 32))
 >a : Symbol(a, Decl(awaitCallExpression3_es6.ts, 0, 11))
 >p : Symbol(p, Decl(awaitCallExpression3_es6.ts, 1, 11))
 >a : Symbol(a, Decl(awaitCallExpression3_es6.ts, 0, 11))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitCallExpression3_es6.ts, 6, 32))
 }
diff --git a/tests/baselines/reference/awaitCallExpression3_es6.types b/tests/baselines/reference/awaitCallExpression3_es6.types
index 6304a803f644a..490fd861a6142 100644
--- a/tests/baselines/reference/awaitCallExpression3_es6.types
+++ b/tests/baselines/reference/awaitCallExpression3_es6.types
@@ -34,12 +34,19 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : boolean
 >arg2 : boolean
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var b = fn(a, await p, a);
 >b : void
@@ -50,6 +57,7 @@ async function func(): Promise<void> {
 >p : Promise<boolean>
 >a : boolean
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitCallExpression4_es6.js b/tests/baselines/reference/awaitCallExpression4_es6.js
index 682a1776ac53c..832f0cf20e30d 100644
--- a/tests/baselines/reference/awaitCallExpression4_es6.js
+++ b/tests/baselines/reference/awaitCallExpression4_es6.js
@@ -5,17 +5,19 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = (await pfn)(a, a, a);
-    "after";
+    after();
 }
 
 //// [awaitCallExpression4_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var b = (yield pfn)(a, a, a);
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitCallExpression4_es6.symbols b/tests/baselines/reference/awaitCallExpression4_es6.symbols
index d31cf100ad456..d7e90fc4a53e5 100644
--- a/tests/baselines/reference/awaitCallExpression4_es6.symbols
+++ b/tests/baselines/reference/awaitCallExpression4_es6.symbols
@@ -34,17 +34,26 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : Symbol(arg1, Decl(awaitCallExpression4_es6.ts, 5, 43))
 >arg2 : Symbol(arg2, Decl(awaitCallExpression4_es6.ts, 5, 58))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression4_es6.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression4_es6.ts, 6, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitCallExpression4_es6.ts, 5, 84))
+>func : Symbol(func, Decl(awaitCallExpression4_es6.ts, 7, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitCallExpression4_es6.ts, 5, 84))
+
     var b = (await pfn)(a, a, a);
->b : Symbol(b, Decl(awaitCallExpression4_es6.ts, 8, 7))
+>b : Symbol(b, Decl(awaitCallExpression4_es6.ts, 10, 7))
 >pfn : Symbol(pfn, Decl(awaitCallExpression4_es6.ts, 4, 11))
 >a : Symbol(a, Decl(awaitCallExpression4_es6.ts, 0, 11))
 >a : Symbol(a, Decl(awaitCallExpression4_es6.ts, 0, 11))
 >a : Symbol(a, Decl(awaitCallExpression4_es6.ts, 0, 11))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitCallExpression4_es6.ts, 6, 32))
 }
diff --git a/tests/baselines/reference/awaitCallExpression4_es6.types b/tests/baselines/reference/awaitCallExpression4_es6.types
index ff5d8f4012b3d..d8a514a67e6cb 100644
--- a/tests/baselines/reference/awaitCallExpression4_es6.types
+++ b/tests/baselines/reference/awaitCallExpression4_es6.types
@@ -34,12 +34,19 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : boolean
 >arg2 : boolean
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var b = (await pfn)(a, a, a);
 >b : void
@@ -51,6 +58,7 @@ async function func(): Promise<void> {
 >a : boolean
 >a : boolean
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitCallExpression5_es6.js b/tests/baselines/reference/awaitCallExpression5_es6.js
index 30889b350115f..05b06e7fc2f0f 100644
--- a/tests/baselines/reference/awaitCallExpression5_es6.js
+++ b/tests/baselines/reference/awaitCallExpression5_es6.js
@@ -5,17 +5,19 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = o.fn(a, a, a);
-    "after";
+    after();
 }
 
 //// [awaitCallExpression5_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var b = o.fn(a, a, a);
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitCallExpression5_es6.symbols b/tests/baselines/reference/awaitCallExpression5_es6.symbols
index d14a966b0b1e2..ba8f987818827 100644
--- a/tests/baselines/reference/awaitCallExpression5_es6.symbols
+++ b/tests/baselines/reference/awaitCallExpression5_es6.symbols
@@ -34,13 +34,21 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : Symbol(arg1, Decl(awaitCallExpression5_es6.ts, 5, 43))
 >arg2 : Symbol(arg2, Decl(awaitCallExpression5_es6.ts, 5, 58))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression5_es6.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression5_es6.ts, 6, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitCallExpression5_es6.ts, 5, 84))
+>func : Symbol(func, Decl(awaitCallExpression5_es6.ts, 7, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitCallExpression5_es6.ts, 5, 84))
+
     var b = o.fn(a, a, a);
->b : Symbol(b, Decl(awaitCallExpression5_es6.ts, 8, 7))
+>b : Symbol(b, Decl(awaitCallExpression5_es6.ts, 10, 7))
 >o.fn : Symbol(fn, Decl(awaitCallExpression5_es6.ts, 3, 16))
 >o : Symbol(o, Decl(awaitCallExpression5_es6.ts, 3, 11))
 >fn : Symbol(fn, Decl(awaitCallExpression5_es6.ts, 3, 16))
@@ -48,5 +56,6 @@ async function func(): Promise<void> {
 >a : Symbol(a, Decl(awaitCallExpression5_es6.ts, 0, 11))
 >a : Symbol(a, Decl(awaitCallExpression5_es6.ts, 0, 11))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitCallExpression5_es6.ts, 6, 32))
 }
diff --git a/tests/baselines/reference/awaitCallExpression5_es6.types b/tests/baselines/reference/awaitCallExpression5_es6.types
index 5074c007743c3..3e9f1c6387e03 100644
--- a/tests/baselines/reference/awaitCallExpression5_es6.types
+++ b/tests/baselines/reference/awaitCallExpression5_es6.types
@@ -34,12 +34,19 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : boolean
 >arg2 : boolean
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var b = o.fn(a, a, a);
 >b : void
@@ -51,6 +58,7 @@ async function func(): Promise<void> {
 >a : boolean
 >a : boolean
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitCallExpression6_es6.js b/tests/baselines/reference/awaitCallExpression6_es6.js
index 55d86119d6495..ba488d5334791 100644
--- a/tests/baselines/reference/awaitCallExpression6_es6.js
+++ b/tests/baselines/reference/awaitCallExpression6_es6.js
@@ -5,17 +5,19 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = o.fn(await p, a, a);
-    "after";
+    after();
 }
 
 //// [awaitCallExpression6_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var b = o.fn(yield p, a, a);
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitCallExpression6_es6.symbols b/tests/baselines/reference/awaitCallExpression6_es6.symbols
index afd07fd018574..938c49d1d4111 100644
--- a/tests/baselines/reference/awaitCallExpression6_es6.symbols
+++ b/tests/baselines/reference/awaitCallExpression6_es6.symbols
@@ -34,13 +34,21 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : Symbol(arg1, Decl(awaitCallExpression6_es6.ts, 5, 43))
 >arg2 : Symbol(arg2, Decl(awaitCallExpression6_es6.ts, 5, 58))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression6_es6.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression6_es6.ts, 6, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitCallExpression6_es6.ts, 5, 84))
+>func : Symbol(func, Decl(awaitCallExpression6_es6.ts, 7, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitCallExpression6_es6.ts, 5, 84))
+
     var b = o.fn(await p, a, a);
->b : Symbol(b, Decl(awaitCallExpression6_es6.ts, 8, 7))
+>b : Symbol(b, Decl(awaitCallExpression6_es6.ts, 10, 7))
 >o.fn : Symbol(fn, Decl(awaitCallExpression6_es6.ts, 3, 16))
 >o : Symbol(o, Decl(awaitCallExpression6_es6.ts, 3, 11))
 >fn : Symbol(fn, Decl(awaitCallExpression6_es6.ts, 3, 16))
@@ -48,5 +56,6 @@ async function func(): Promise<void> {
 >a : Symbol(a, Decl(awaitCallExpression6_es6.ts, 0, 11))
 >a : Symbol(a, Decl(awaitCallExpression6_es6.ts, 0, 11))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitCallExpression6_es6.ts, 6, 32))
 }
diff --git a/tests/baselines/reference/awaitCallExpression6_es6.types b/tests/baselines/reference/awaitCallExpression6_es6.types
index 3266733fab00e..6c5f0f9063e4b 100644
--- a/tests/baselines/reference/awaitCallExpression6_es6.types
+++ b/tests/baselines/reference/awaitCallExpression6_es6.types
@@ -34,12 +34,19 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : boolean
 >arg2 : boolean
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var b = o.fn(await p, a, a);
 >b : void
@@ -52,6 +59,7 @@ async function func(): Promise<void> {
 >a : boolean
 >a : boolean
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitCallExpression7_es6.js b/tests/baselines/reference/awaitCallExpression7_es6.js
index df805266ff3a2..2eb830986d966 100644
--- a/tests/baselines/reference/awaitCallExpression7_es6.js
+++ b/tests/baselines/reference/awaitCallExpression7_es6.js
@@ -5,17 +5,19 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = o.fn(a, await p, a);
-    "after";
+    after();
 }
 
 //// [awaitCallExpression7_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var b = o.fn(a, yield p, a);
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitCallExpression7_es6.symbols b/tests/baselines/reference/awaitCallExpression7_es6.symbols
index bb503d4b3a175..f366417b23f9d 100644
--- a/tests/baselines/reference/awaitCallExpression7_es6.symbols
+++ b/tests/baselines/reference/awaitCallExpression7_es6.symbols
@@ -34,13 +34,21 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : Symbol(arg1, Decl(awaitCallExpression7_es6.ts, 5, 43))
 >arg2 : Symbol(arg2, Decl(awaitCallExpression7_es6.ts, 5, 58))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression7_es6.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression7_es6.ts, 6, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitCallExpression7_es6.ts, 5, 84))
+>func : Symbol(func, Decl(awaitCallExpression7_es6.ts, 7, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitCallExpression7_es6.ts, 5, 84))
+
     var b = o.fn(a, await p, a);
->b : Symbol(b, Decl(awaitCallExpression7_es6.ts, 8, 7))
+>b : Symbol(b, Decl(awaitCallExpression7_es6.ts, 10, 7))
 >o.fn : Symbol(fn, Decl(awaitCallExpression7_es6.ts, 3, 16))
 >o : Symbol(o, Decl(awaitCallExpression7_es6.ts, 3, 11))
 >fn : Symbol(fn, Decl(awaitCallExpression7_es6.ts, 3, 16))
@@ -48,5 +56,6 @@ async function func(): Promise<void> {
 >p : Symbol(p, Decl(awaitCallExpression7_es6.ts, 1, 11))
 >a : Symbol(a, Decl(awaitCallExpression7_es6.ts, 0, 11))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitCallExpression7_es6.ts, 6, 32))
 }
diff --git a/tests/baselines/reference/awaitCallExpression7_es6.types b/tests/baselines/reference/awaitCallExpression7_es6.types
index b1b382f732503..e36b3773091f7 100644
--- a/tests/baselines/reference/awaitCallExpression7_es6.types
+++ b/tests/baselines/reference/awaitCallExpression7_es6.types
@@ -34,12 +34,19 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : boolean
 >arg2 : boolean
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var b = o.fn(a, await p, a);
 >b : void
@@ -52,6 +59,7 @@ async function func(): Promise<void> {
 >p : Promise<boolean>
 >a : boolean
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitCallExpression8_es6.js b/tests/baselines/reference/awaitCallExpression8_es6.js
index 8d7bb4b83ce96..ecf36a319369c 100644
--- a/tests/baselines/reference/awaitCallExpression8_es6.js
+++ b/tests/baselines/reference/awaitCallExpression8_es6.js
@@ -5,17 +5,19 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = (await po).fn(a, a, a);
-    "after";
+    after();
 }
 
 //// [awaitCallExpression8_es6.js]
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
-        "before";
+        before();
         var b = (yield po).fn(a, a, a);
-        "after";
+        after();
     });
 }
diff --git a/tests/baselines/reference/awaitCallExpression8_es6.symbols b/tests/baselines/reference/awaitCallExpression8_es6.symbols
index 9f4df1046f47c..89441ea3e37da 100644
--- a/tests/baselines/reference/awaitCallExpression8_es6.symbols
+++ b/tests/baselines/reference/awaitCallExpression8_es6.symbols
@@ -34,13 +34,21 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : Symbol(arg1, Decl(awaitCallExpression8_es6.ts, 5, 43))
 >arg2 : Symbol(arg2, Decl(awaitCallExpression8_es6.ts, 5, 58))
 
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression8_es6.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression8_es6.ts, 6, 32))
+
 async function func(): Promise<void> {
->func : Symbol(func, Decl(awaitCallExpression8_es6.ts, 5, 84))
+>func : Symbol(func, Decl(awaitCallExpression8_es6.ts, 7, 31))
 >Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
 
-    "before";
+    before();
+>before : Symbol(before, Decl(awaitCallExpression8_es6.ts, 5, 84))
+
     var b = (await po).fn(a, a, a);
->b : Symbol(b, Decl(awaitCallExpression8_es6.ts, 8, 7))
+>b : Symbol(b, Decl(awaitCallExpression8_es6.ts, 10, 7))
 >(await po).fn : Symbol(fn, Decl(awaitCallExpression8_es6.ts, 5, 25))
 >po : Symbol(po, Decl(awaitCallExpression8_es6.ts, 5, 11))
 >fn : Symbol(fn, Decl(awaitCallExpression8_es6.ts, 5, 25))
@@ -48,5 +56,6 @@ async function func(): Promise<void> {
 >a : Symbol(a, Decl(awaitCallExpression8_es6.ts, 0, 11))
 >a : Symbol(a, Decl(awaitCallExpression8_es6.ts, 0, 11))
 
-    "after";
+    after();
+>after : Symbol(after, Decl(awaitCallExpression8_es6.ts, 6, 32))
 }
diff --git a/tests/baselines/reference/awaitCallExpression8_es6.types b/tests/baselines/reference/awaitCallExpression8_es6.types
index 76719c09c85b5..8258ba830b25f 100644
--- a/tests/baselines/reference/awaitCallExpression8_es6.types
+++ b/tests/baselines/reference/awaitCallExpression8_es6.types
@@ -34,12 +34,19 @@ declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 >arg1 : boolean
 >arg2 : boolean
 
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
 async function func(): Promise<void> {
 >func : () => Promise<void>
 >Promise : Promise<T>
 
-    "before";
->"before" : string
+    before();
+>before() : void
+>before : () => void
 
     var b = (await po).fn(a, a, a);
 >b : void
@@ -53,6 +60,7 @@ async function func(): Promise<void> {
 >a : boolean
 >a : boolean
 
-    "after";
->"after" : string
+    after();
+>after() : void
+>after : () => void
 }
diff --git a/tests/baselines/reference/awaitClassExpression_es6.js b/tests/baselines/reference/awaitClassExpression_es6.js
new file mode 100644
index 0000000000000..26740b9de6daf
--- /dev/null
+++ b/tests/baselines/reference/awaitClassExpression_es6.js
@@ -0,0 +1,16 @@
+//// [awaitClassExpression_es6.ts]
+declare class C { }
+declare var p: Promise<typeof C>;
+
+async function func(): Promise<void> {
+    class D extends (await p) {
+    }
+}
+
+//// [awaitClassExpression_es6.js]
+function func() {
+    return __awaiter(this, void 0, void 0, function* () {
+        class D extends (yield p) {
+        }
+    });
+}
diff --git a/tests/baselines/reference/awaitClassExpression_es6.symbols b/tests/baselines/reference/awaitClassExpression_es6.symbols
new file mode 100644
index 0000000000000..6d1e9f1a10316
--- /dev/null
+++ b/tests/baselines/reference/awaitClassExpression_es6.symbols
@@ -0,0 +1,18 @@
+=== tests/cases/conformance/async/es6/awaitClassExpression_es6.ts ===
+declare class C { }
+>C : Symbol(C, Decl(awaitClassExpression_es6.ts, 0, 0))
+
+declare var p: Promise<typeof C>;
+>p : Symbol(p, Decl(awaitClassExpression_es6.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
+>C : Symbol(C, Decl(awaitClassExpression_es6.ts, 0, 0))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitClassExpression_es6.ts, 1, 33))
+>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
+
+    class D extends (await p) {
+>D : Symbol(D, Decl(awaitClassExpression_es6.ts, 3, 38))
+>p : Symbol(p, Decl(awaitClassExpression_es6.ts, 1, 11))
+    }
+}
diff --git a/tests/baselines/reference/awaitClassExpression_es6.types b/tests/baselines/reference/awaitClassExpression_es6.types
new file mode 100644
index 0000000000000..4a7780217201e
--- /dev/null
+++ b/tests/baselines/reference/awaitClassExpression_es6.types
@@ -0,0 +1,20 @@
+=== tests/cases/conformance/async/es6/awaitClassExpression_es6.ts ===
+declare class C { }
+>C : C
+
+declare var p: Promise<typeof C>;
+>p : Promise<typeof C>
+>Promise : Promise<T>
+>C : typeof C
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    class D extends (await p) {
+>D : D
+>(await p) : C
+>await p : typeof C
+>p : Promise<typeof C>
+    }
+}
diff --git a/tests/baselines/reference/awaitUnion_es6.js b/tests/baselines/reference/awaitUnion_es6.js
index 9603454b969aa..628e488cb4fac 100644
--- a/tests/baselines/reference/awaitUnion_es6.js
+++ b/tests/baselines/reference/awaitUnion_es6.js
@@ -9,7 +9,7 @@ async function f() {
 	let await_b = await b;
 	let await_c = await c;
 	let await_d = await d;
-	let await_e = await e; 
+	let await_e = await e;
 }
 
 //// [awaitUnion_es6.js]
diff --git a/tests/baselines/reference/awaitUnion_es6.symbols b/tests/baselines/reference/awaitUnion_es6.symbols
index 98a229c41482c..c301f3c5b8dd7 100644
--- a/tests/baselines/reference/awaitUnion_es6.symbols
+++ b/tests/baselines/reference/awaitUnion_es6.symbols
@@ -38,7 +38,7 @@ async function f() {
 >await_d : Symbol(await_d, Decl(awaitUnion_es6.ts, 9, 4))
 >d : Symbol(d, Decl(awaitUnion_es6.ts, 3, 11))
 
-	let await_e = await e; 
+	let await_e = await e;
 >await_e : Symbol(await_e, Decl(awaitUnion_es6.ts, 10, 4))
 >e : Symbol(e, Decl(awaitUnion_es6.ts, 4, 11))
 }
diff --git a/tests/baselines/reference/awaitUnion_es6.types b/tests/baselines/reference/awaitUnion_es6.types
index 97d4bd2fc579b..63260772f5392 100644
--- a/tests/baselines/reference/awaitUnion_es6.types
+++ b/tests/baselines/reference/awaitUnion_es6.types
@@ -42,7 +42,7 @@ async function f() {
 >await d : number | string
 >d : number | PromiseLike<string>
 
-	let await_e = await e; 
+	let await_e = await e;
 >await_e : number | string
 >await e : number | string
 >e : number | PromiseLike<number | string>
diff --git a/tests/cases/conformance/async/es6/asyncArrowFunction/arrowFunctionWithParameterNameAsync.ts b/tests/cases/conformance/async/es6/asyncArrowFunction/arrowFunctionWithParameterNameAsync_es6.ts
similarity index 100%
rename from tests/cases/conformance/async/es6/asyncArrowFunction/arrowFunctionWithParameterNameAsync.ts
rename to tests/cases/conformance/async/es6/asyncArrowFunction/arrowFunctionWithParameterNameAsync_es6.ts
diff --git a/tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction10_es6.ts b/tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction10_es6.ts
index 0959ed6c561e8..1d7f6e3079e24 100644
--- a/tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction10_es6.ts
+++ b/tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction10_es6.ts
@@ -1,7 +1,7 @@
 // @target: ES6
 // @noEmitHelpers: true
 
-var foo = async foo(): Promise<void> => {
+var foo = async (): Promise<void> => {
    // Legal to use 'await' in a type context.
    var v: await;
 }
diff --git a/tests/cases/conformance/async/es6/asyncMultiFile.ts b/tests/cases/conformance/async/es6/asyncMultiFile_es6.ts
similarity index 100%
rename from tests/cases/conformance/async/es6/asyncMultiFile.ts
rename to tests/cases/conformance/async/es6/asyncMultiFile_es6.ts
diff --git a/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression1_es6.ts b/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression1_es6.ts
index 46060f309b241..da7c0d09142eb 100644
--- a/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression1_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression1_es6.ts
@@ -2,8 +2,10 @@
 // @noEmitHelpers: true
 declare var a: boolean;
 declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = await p || a;
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression2_es6.ts b/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression2_es6.ts
index 362f1ecc4463f..a81f50c51ef45 100644
--- a/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression2_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression2_es6.ts
@@ -2,8 +2,10 @@
 // @noEmitHelpers: true
 declare var a: boolean;
 declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = await p && a;
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression3_es6.ts b/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression3_es6.ts
index d3b02033252e1..3ba0fa7ef0756 100644
--- a/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression3_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression3_es6.ts
@@ -2,8 +2,10 @@
 // @noEmitHelpers: true
 declare var a: number;
 declare var p: Promise<number>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = await p + a;
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression4_es6.ts b/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression4_es6.ts
index eba3be31acfbc..2ed73473323e8 100644
--- a/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression4_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression4_es6.ts
@@ -2,8 +2,10 @@
 // @noEmitHelpers: true
 declare var a: boolean;
 declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = await p, a;
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression5_es6.ts b/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression5_es6.ts
index 71b173f9e73a7..91fbc3cd17b79 100644
--- a/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression5_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression5_es6.ts
@@ -2,9 +2,11 @@
 // @noEmitHelpers: true
 declare var a: boolean;
 declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var o: { a: boolean; };
     o.a = await p;
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression1_es6.ts b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression1_es6.ts
index d0442f0968dc4..6a73dcca4531b 100644
--- a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression1_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression1_es6.ts
@@ -6,8 +6,10 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = fn(a, a, a);
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression2_es6.ts b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression2_es6.ts
index 6de07ef12ffee..dd4c8a2d4d926 100644
--- a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression2_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression2_es6.ts
@@ -6,8 +6,10 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = fn(await p, a, a);
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression3_es6.ts b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression3_es6.ts
index 2cc0b7b12d071..01d29cd51636d 100644
--- a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression3_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression3_es6.ts
@@ -6,8 +6,10 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = fn(a, await p, a);
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression4_es6.ts b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression4_es6.ts
index 8e349fbc5c329..1a57debb6b1ef 100644
--- a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression4_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression4_es6.ts
@@ -6,8 +6,10 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = (await pfn)(a, a, a);
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression5_es6.ts b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression5_es6.ts
index bbe81ac94b110..2a24fe28df407 100644
--- a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression5_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression5_es6.ts
@@ -6,8 +6,10 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = o.fn(a, a, a);
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression6_es6.ts b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression6_es6.ts
index 09e88f5acbcdd..e2d0877a39bfb 100644
--- a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression6_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression6_es6.ts
@@ -6,8 +6,10 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = o.fn(await p, a, a);
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression7_es6.ts b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression7_es6.ts
index fe0182da4aa1b..f309874232d30 100644
--- a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression7_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression7_es6.ts
@@ -6,8 +6,10 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = o.fn(a, await p, a);
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression8_es6.ts b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression8_es6.ts
index e3280eb7c10ff..ccd82ffef2f7a 100644
--- a/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression8_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitCallExpression/awaitCallExpression8_es6.ts
@@ -6,8 +6,10 @@ declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
 declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
 declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
 declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
 async function func(): Promise<void> {
-    "before";
+    before();
     var b = (await po).fn(a, a, a);
-    "after";
+    after();
 }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitClassExpression_es6.ts b/tests/cases/conformance/async/es6/awaitClassExpression_es6.ts
new file mode 100644
index 0000000000000..f503985ba9402
--- /dev/null
+++ b/tests/cases/conformance/async/es6/awaitClassExpression_es6.ts
@@ -0,0 +1,9 @@
+// @target: ES6
+// @noEmitHelpers: true
+declare class C { }
+declare var p: Promise<typeof C>;
+
+async function func(): Promise<void> {
+    class D extends (await p) {
+    }
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitUnion_es6.ts b/tests/cases/conformance/async/es6/awaitUnion_es6.ts
index a132ae01dfde2..1618ea28a86e3 100644
--- a/tests/cases/conformance/async/es6/awaitUnion_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitUnion_es6.ts
@@ -10,5 +10,5 @@ async function f() {
 	let await_b = await b;
 	let await_c = await c;
 	let await_d = await d;
-	let await_e = await e; 
+	let await_e = await e;
 }
\ No newline at end of file

From a858db6ac8dabeeb86fc45df74a1528cf59ba7bb Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 27 Jun 2016 13:14:57 -0700
Subject: [PATCH 13/23] Remove extraneous comments.

---
 src/compiler/transformers/es6.ts | 113 -------------------------------
 1 file changed, 113 deletions(-)

diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts
index 49fd5106ba408..110d744021230 100644
--- a/src/compiler/transformers/es6.ts
+++ b/src/compiler/transformers/es6.ts
@@ -1686,119 +1686,6 @@ namespace ts {
             return convertIterationStatementBodyIfNecessary(node);
         }
 
-        // // TODO(rbuckton): Switch to using __values helper for for..of?
-        // function visitForOfStatement2(node: ForOfStatement): OneOrMany<Statement> {
-        //     // [source]
-        //     //  for (let v of expr) {
-        //     //  }
-        //     //
-        //     // [output]
-        //     //  var __values = ...;
-        //     //  try {
-        //     //      for (_a = __values(expr), _b = _a.next(); !_b.done || (_a = void 0); _b = _a.next()) {
-        //     //          var v = _b.value;
-        //     //      }
-        //     //  }
-        //     //  finally {
-        //     //      if (_a && typeof _a.return === "function") _a.return();
-        //     //  }
-        //     //  var _a, b;
-
-        //     const iterator = createTempVariable();
-        //     const iteratorResult = createTempVariable();
-        //     hoistVariableDeclaration(iterator);
-        //     hoistVariableDeclaration(iteratorResult);
-        //     const expression = visitNode(node.expression, visitor, isExpression);
-        //     const initializer = node.initializer;
-        //     const statements: Statement[] = [];
-        //     if (isVariableDeclarationList(initializer)) {
-        //         const variable = getMutableClone(initializer.declarations[0]);
-        //         variable.initializer = createPropertyAccess(iteratorResult, "value");
-        //         statements.push(
-        //             createVariableStatement(
-        //                 /*modifiers*/ undefined,
-        //                 createVariableDeclarationList(
-        //                     isBindingPattern(variable.name)
-        //                         ? flattenVariableDestructuring(variable, /*value*/ undefined, visitor)
-        //                         : [variable]
-        //                 )
-        //             )
-        //         );
-        //     }
-        //     else {
-        //         statements.push(
-        //             createStatement(
-        //                 createAssignment(
-        //                     <Expression>node.initializer,
-        //                     createPropertyAccess(iteratorResult, "value")
-        //                 )
-        //             )
-        //         );
-        //     }
-
-        //     if (isBlock(node.statement)) {
-        //         addNodes(statements, visitNodes((<Block>node.statement).statements, visitor, isStatement));
-        //     }
-        //     else {
-        //         addNodes(statements, visitNodes(createNodeArray([node.statement]), visitor, isStatement));
-        //     }
-
-        //     return createTryFinally(
-        //         createBlock([
-        //             createFor(
-        //                 createComma(
-        //                     createAssignment(
-        //                         iterator,
-        //                         createCall(
-        //                             createIdentifier("__values"),
-        //                             [expression]
-        //                         )
-        //                     ),
-        //                     createAssignment(
-        //                         iteratorResult,
-        //                         createCall(
-        //                             createPropertyAccess(iterator, "next"),
-        //                             []
-        //                         )
-        //                     )
-        //                 ),
-        //                 createLogicalOr(
-        //                     createLogicalNot(createPropertyAccess(iteratorResult, "done")),
-        //                     createAssignment(iterator, createVoidZero())
-        //                 ),
-        //                 createAssignment(
-        //                     iteratorResult,
-        //                     createCall(
-        //                         createPropertyAccess(iterator, "next"),
-        //                         []
-        //                     )
-        //                 ),
-        //                 createBlock(statements)
-        //             )
-        //         ]),
-        //         createBlock([
-        //             createIf(
-        //                 createLogicalAnd(
-        //                     iterator,
-        //                     createStrictEquality(
-        //                         createTypeOf(
-        //                             createPropertyAccess(iterator, "return")
-        //                         ),
-        //                         createLiteral("function")
-        //                     )
-        //                 ),
-        //                 createStatement(
-        //                     createCall(
-        //                         createPropertyAccess(iterator, "return"),
-        //                         [],
-        //                         /*location*/ node.expression
-        //                     )
-        //                 )
-        //             )
-        //         ])
-        //     );
-        // }
-
         /**
          * Visits a ForOfStatement and converts it into a compatible ForStatement.
          *

From 4a16f65c0074913b08ce147eb620a9ffee4411ce Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 27 Jun 2016 13:19:24 -0700
Subject: [PATCH 14/23] Removed extranous original parameter.

---
 src/compiler/factory.ts | 50 +++++++++++++++++++++++------------------
 1 file changed, 28 insertions(+), 22 deletions(-)

diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts
index e20ce42eb0416..40c63cb7ac95e 100644
--- a/src/compiler/factory.ts
+++ b/src/compiler/factory.ts
@@ -923,7 +923,7 @@ namespace ts {
         return <Expression>createBinary(left, SyntaxKind.LessThanToken, right, location);
     }
 
-    export function createAssignment(left: Expression, right: Expression, location?: TextRange, original?: Node) {
+    export function createAssignment(left: Expression, right: Expression, location?: TextRange) {
         return createBinary(left, SyntaxKind.EqualsToken, right, location);
     }
 
@@ -1586,10 +1586,12 @@ namespace ts {
 
     function createExpressionForPropertyAssignment(property: PropertyAssignment, receiver: Expression) {
         return aggregateTransformFlags(
-            createAssignment(
-                createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name),
-                property.initializer,
-                /*location*/ property,
+            setOriginalNode(
+                createAssignment(
+                    createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name),
+                    property.initializer,
+                    /*location*/ property
+                ),
                 /*original*/ property
             )
         );
@@ -1597,10 +1599,12 @@ namespace ts {
 
     function createExpressionForShorthandPropertyAssignment(property: ShorthandPropertyAssignment, receiver: Expression) {
         return aggregateTransformFlags(
-            createAssignment(
-                createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name),
-                getSynthesizedClone(property.name),
-                /*location*/ property,
+            setOriginalNode(
+                createAssignment(
+                    createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name),
+                    getSynthesizedClone(property.name),
+                    /*location*/ property
+                ),
                 /*original*/ property
             )
         );
@@ -1608,21 +1612,23 @@ namespace ts {
 
     function createExpressionForMethodDeclaration(method: MethodDeclaration, receiver: Expression) {
         return aggregateTransformFlags(
-            createAssignment(
-                createMemberAccessForPropertyName(receiver, method.name, /*location*/ method.name),
-                setOriginalNode(
-                    createFunctionExpression(
-                        method.asteriskToken,
-                        /*name*/ undefined,
-                        /*typeParameters*/ undefined,
-                        method.parameters,
-                        /*type*/ undefined,
-                        method.body,
-                        /*location*/ method
+            setOriginalNode(
+                createAssignment(
+                    createMemberAccessForPropertyName(receiver, method.name, /*location*/ method.name),
+                    setOriginalNode(
+                        createFunctionExpression(
+                            method.asteriskToken,
+                            /*name*/ undefined,
+                            /*typeParameters*/ undefined,
+                            method.parameters,
+                            /*type*/ undefined,
+                            method.body,
+                            /*location*/ method
+                        ),
+                        /*original*/ method
                     ),
-                    /*original*/ method
+                    /*location*/ method
                 ),
-                /*location*/ method,
                 /*original*/ method
             )
         );

From 393ee28fb01abee2c7ad07e5c8a028d6aebb6b35 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 27 Jun 2016 13:48:47 -0700
Subject: [PATCH 15/23] Move 'use strict' directive out of generator for async
 function.

---
 src/compiler/transformers/generators.ts       | 11 ++++++----
 src/compiler/transformers/ts.ts               | 10 +++++----
 .../baselines/reference/asyncUseStrict_es6.js | 15 +++++++++++++
 .../reference/asyncUseStrict_es6.symbols      | 18 +++++++++++++++
 .../reference/asyncUseStrict_es6.types        | 22 +++++++++++++++++++
 .../async/es6/asyncUseStrict_es6.ts           |  8 +++++++
 6 files changed, 76 insertions(+), 8 deletions(-)
 create mode 100644 tests/baselines/reference/asyncUseStrict_es6.js
 create mode 100644 tests/baselines/reference/asyncUseStrict_es6.symbols
 create mode 100644 tests/baselines/reference/asyncUseStrict_es6.types
 create mode 100644 tests/cases/conformance/async/es6/asyncUseStrict_es6.ts

diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts
index e11804bd467ca..234f39550a7b0 100644
--- a/src/compiler/transformers/generators.ts
+++ b/src/compiler/transformers/generators.ts
@@ -572,10 +572,12 @@ namespace ts {
             operationLocations = undefined;
             state = createTempVariable(/*recordTempVariable*/ undefined);
 
+            const statementOffset = addPrologueDirectives(statements, body.statements);
+
             // Build the generator
             startLexicalEnvironment();
 
-            transformAndEmitStatements(body.statements);
+            transformAndEmitStatements(body.statements, statementOffset);
 
             const buildResult = build();
             addNodes(statements, endLexicalEnvironment());
@@ -1117,9 +1119,10 @@ namespace ts {
             return visitEachChild(node, visitor, context);
         }
 
-        function transformAndEmitStatements(statements: Statement[]) {
-            for (const statement of statements) {
-                transformAndEmitStatement(statement);
+        function transformAndEmitStatements(statements: Statement[], start = 0) {
+            const numStatements = statements.length;
+            for (let i = start; i < numStatements; i++) {
+                transformAndEmitStatement(statements[i]);
             }
         }
 
diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts
index 788791bfe74c7..f2157e5a5c0e9 100644
--- a/src/compiler/transformers/ts.ts
+++ b/src/compiler/transformers/ts.ts
@@ -2181,11 +2181,13 @@ namespace ts {
             return transformFunctionBodyWorker(node.body);
         }
 
-        function transformFunctionBodyWorker(body: Block) {
+        function transformFunctionBodyWorker(body: Block, start = 0) {
             const savedCurrentScope = currentScope;
             currentScope = body;
             startLexicalEnvironment();
-            const visited = visitEachChild(body, visitor, context);
+
+            const statements = visitNodes(body.statements, visitor, isStatement, start);
+            const visited = updateBlock(body, statements);
             const declarations = endLexicalEnvironment();
             currentScope = savedCurrentScope;
             return mergeFunctionBodyLexicalEnvironment(visited, declarations);
@@ -2233,14 +2235,14 @@ namespace ts {
 
             if (!isArrowFunction) {
                 const statements: Statement[] = [];
-
+                const statementOffset = addPrologueDirectives(statements, (<Block>node.body).statements);
                 statements.push(
                     createReturn(
                         createAwaiterHelper(
                             currentSourceFileExternalHelpersModuleName,
                             hasLexicalArguments,
                             promiseConstructor,
-                            transformFunctionBodyWorker(<Block>node.body)
+                            transformFunctionBodyWorker(<Block>node.body, statementOffset)
                         )
                     )
                 );
diff --git a/tests/baselines/reference/asyncUseStrict_es6.js b/tests/baselines/reference/asyncUseStrict_es6.js
new file mode 100644
index 0000000000000..5475a71102ace
--- /dev/null
+++ b/tests/baselines/reference/asyncUseStrict_es6.js
@@ -0,0 +1,15 @@
+//// [asyncUseStrict_es6.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+async function func(): Promise<void> {
+    "use strict";
+    var b = await p || a;
+}
+
+//// [asyncUseStrict_es6.js]
+function func() {
+    "use strict";
+    return __awaiter(this, void 0, void 0, function* () {
+        var b = (yield p) || a;
+    });
+}
diff --git a/tests/baselines/reference/asyncUseStrict_es6.symbols b/tests/baselines/reference/asyncUseStrict_es6.symbols
new file mode 100644
index 0000000000000..f94c16664e7f0
--- /dev/null
+++ b/tests/baselines/reference/asyncUseStrict_es6.symbols
@@ -0,0 +1,18 @@
+=== tests/cases/conformance/async/es6/asyncUseStrict_es6.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(asyncUseStrict_es6.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(asyncUseStrict_es6.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(asyncUseStrict_es6.ts, 1, 32))
+>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
+
+    "use strict";
+    var b = await p || a;
+>b : Symbol(b, Decl(asyncUseStrict_es6.ts, 4, 7))
+>p : Symbol(p, Decl(asyncUseStrict_es6.ts, 1, 11))
+>a : Symbol(a, Decl(asyncUseStrict_es6.ts, 0, 11))
+}
diff --git a/tests/baselines/reference/asyncUseStrict_es6.types b/tests/baselines/reference/asyncUseStrict_es6.types
new file mode 100644
index 0000000000000..7e6fd8720817e
--- /dev/null
+++ b/tests/baselines/reference/asyncUseStrict_es6.types
@@ -0,0 +1,22 @@
+=== tests/cases/conformance/async/es6/asyncUseStrict_es6.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    "use strict";
+>"use strict" : string
+
+    var b = await p || a;
+>b : boolean
+>await p || a : boolean
+>await p : boolean
+>p : Promise<boolean>
+>a : boolean
+}
diff --git a/tests/cases/conformance/async/es6/asyncUseStrict_es6.ts b/tests/cases/conformance/async/es6/asyncUseStrict_es6.ts
new file mode 100644
index 0000000000000..b3948daf384f5
--- /dev/null
+++ b/tests/cases/conformance/async/es6/asyncUseStrict_es6.ts
@@ -0,0 +1,8 @@
+// @target: ES6
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+async function func(): Promise<void> {
+    "use strict";
+    var b = await p || a;
+}
\ No newline at end of file

From 5b2e11c5d0630380a8599b8778615bcd03678519 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 27 Jun 2016 14:08:36 -0700
Subject: [PATCH 16/23] Added es5 conformance tests for await in binary.

---
 .../reference/awaitBinaryExpression1_es5.js   | 28 ++++++++++++++
 .../awaitBinaryExpression1_es5.symbols        | 29 ++++++++++++++
 .../awaitBinaryExpression1_es5.types          | 33 ++++++++++++++++
 .../reference/awaitBinaryExpression2_es5.js   | 28 ++++++++++++++
 .../awaitBinaryExpression2_es5.symbols        | 29 ++++++++++++++
 .../awaitBinaryExpression2_es5.types          | 33 ++++++++++++++++
 .../reference/awaitBinaryExpression3_es5.js   | 28 ++++++++++++++
 .../awaitBinaryExpression3_es5.symbols        | 29 ++++++++++++++
 .../awaitBinaryExpression3_es5.types          | 33 ++++++++++++++++
 .../reference/awaitBinaryExpression4_es5.js   | 28 ++++++++++++++
 .../awaitBinaryExpression4_es5.symbols        | 29 ++++++++++++++
 .../awaitBinaryExpression4_es5.types          | 34 +++++++++++++++++
 .../reference/awaitBinaryExpression4_es6.js   |  4 +-
 .../awaitBinaryExpression4_es6.symbols        |  4 +-
 .../awaitBinaryExpression4_es6.types          |  6 ++-
 .../reference/awaitBinaryExpression5_es5.js   | 30 +++++++++++++++
 .../awaitBinaryExpression5_es5.symbols        | 34 +++++++++++++++++
 .../awaitBinaryExpression5_es5.types          | 38 +++++++++++++++++++
 .../awaitBinaryExpression1_es5.ts             | 12 ++++++
 .../awaitBinaryExpression2_es5.ts             | 12 ++++++
 .../awaitBinaryExpression3_es5.ts             | 12 ++++++
 .../awaitBinaryExpression4_es5.ts             | 12 ++++++
 .../awaitBinaryExpression5_es5.ts             | 13 +++++++
 .../awaitBinaryExpression4_es6.ts             |  2 +-
 24 files changed, 533 insertions(+), 7 deletions(-)
 create mode 100644 tests/baselines/reference/awaitBinaryExpression1_es5.js
 create mode 100644 tests/baselines/reference/awaitBinaryExpression1_es5.symbols
 create mode 100644 tests/baselines/reference/awaitBinaryExpression1_es5.types
 create mode 100644 tests/baselines/reference/awaitBinaryExpression2_es5.js
 create mode 100644 tests/baselines/reference/awaitBinaryExpression2_es5.symbols
 create mode 100644 tests/baselines/reference/awaitBinaryExpression2_es5.types
 create mode 100644 tests/baselines/reference/awaitBinaryExpression3_es5.js
 create mode 100644 tests/baselines/reference/awaitBinaryExpression3_es5.symbols
 create mode 100644 tests/baselines/reference/awaitBinaryExpression3_es5.types
 create mode 100644 tests/baselines/reference/awaitBinaryExpression4_es5.js
 create mode 100644 tests/baselines/reference/awaitBinaryExpression4_es5.symbols
 create mode 100644 tests/baselines/reference/awaitBinaryExpression4_es5.types
 create mode 100644 tests/baselines/reference/awaitBinaryExpression5_es5.js
 create mode 100644 tests/baselines/reference/awaitBinaryExpression5_es5.symbols
 create mode 100644 tests/baselines/reference/awaitBinaryExpression5_es5.types
 create mode 100644 tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression1_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression2_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression3_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression4_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression5_es5.ts

diff --git a/tests/baselines/reference/awaitBinaryExpression1_es5.js b/tests/baselines/reference/awaitBinaryExpression1_es5.js
new file mode 100644
index 0000000000000..c0202d41dad78
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression1_es5.js
@@ -0,0 +1,28 @@
+//// [awaitBinaryExpression1_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = await p || a;
+    after();
+}
+
+//// [awaitBinaryExpression1_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var b;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    before();
+                    return [4 /*yield*/, p];
+                case 1:
+                    b = (_a.sent()) || a;
+                    after();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression1_es5.symbols b/tests/baselines/reference/awaitBinaryExpression1_es5.symbols
new file mode 100644
index 0000000000000..84d3b17b126cb
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression1_es5.symbols
@@ -0,0 +1,29 @@
+=== tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression1_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(awaitBinaryExpression1_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(awaitBinaryExpression1_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitBinaryExpression1_es5.ts, 1, 32))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitBinaryExpression1_es5.ts, 2, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitBinaryExpression1_es5.ts, 3, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitBinaryExpression1_es5.ts, 1, 32))
+
+    var b = await p || a;
+>b : Symbol(b, Decl(awaitBinaryExpression1_es5.ts, 6, 7))
+>p : Symbol(p, Decl(awaitBinaryExpression1_es5.ts, 1, 11))
+>a : Symbol(a, Decl(awaitBinaryExpression1_es5.ts, 0, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitBinaryExpression1_es5.ts, 2, 32))
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression1_es5.types b/tests/baselines/reference/awaitBinaryExpression1_es5.types
new file mode 100644
index 0000000000000..f704eb632b4f2
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression1_es5.types
@@ -0,0 +1,33 @@
+=== tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression1_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var b = await p || a;
+>b : boolean
+>await p || a : boolean
+>await p : boolean
+>p : Promise<boolean>
+>a : boolean
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression2_es5.js b/tests/baselines/reference/awaitBinaryExpression2_es5.js
new file mode 100644
index 0000000000000..8484a9a3268de
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression2_es5.js
@@ -0,0 +1,28 @@
+//// [awaitBinaryExpression2_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = await p && a;
+    after();
+}
+
+//// [awaitBinaryExpression2_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var b;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    before();
+                    return [4 /*yield*/, p];
+                case 1:
+                    b = (_a.sent()) && a;
+                    after();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression2_es5.symbols b/tests/baselines/reference/awaitBinaryExpression2_es5.symbols
new file mode 100644
index 0000000000000..e44238d4172a7
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression2_es5.symbols
@@ -0,0 +1,29 @@
+=== tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression2_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(awaitBinaryExpression2_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(awaitBinaryExpression2_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitBinaryExpression2_es5.ts, 1, 32))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitBinaryExpression2_es5.ts, 2, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitBinaryExpression2_es5.ts, 3, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitBinaryExpression2_es5.ts, 1, 32))
+
+    var b = await p && a;
+>b : Symbol(b, Decl(awaitBinaryExpression2_es5.ts, 6, 7))
+>p : Symbol(p, Decl(awaitBinaryExpression2_es5.ts, 1, 11))
+>a : Symbol(a, Decl(awaitBinaryExpression2_es5.ts, 0, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitBinaryExpression2_es5.ts, 2, 32))
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression2_es5.types b/tests/baselines/reference/awaitBinaryExpression2_es5.types
new file mode 100644
index 0000000000000..d3f1f861a453a
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression2_es5.types
@@ -0,0 +1,33 @@
+=== tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression2_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var b = await p && a;
+>b : boolean
+>await p && a : boolean
+>await p : boolean
+>p : Promise<boolean>
+>a : boolean
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression3_es5.js b/tests/baselines/reference/awaitBinaryExpression3_es5.js
new file mode 100644
index 0000000000000..3403749814a19
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression3_es5.js
@@ -0,0 +1,28 @@
+//// [awaitBinaryExpression3_es5.ts]
+declare var a: number;
+declare var p: Promise<number>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = await p + a;
+    after();
+}
+
+//// [awaitBinaryExpression3_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var b;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    before();
+                    return [4 /*yield*/, p];
+                case 1:
+                    b = (_a.sent()) + a;
+                    after();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression3_es5.symbols b/tests/baselines/reference/awaitBinaryExpression3_es5.symbols
new file mode 100644
index 0000000000000..d9480fdf5248a
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression3_es5.symbols
@@ -0,0 +1,29 @@
+=== tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression3_es5.ts ===
+declare var a: number;
+>a : Symbol(a, Decl(awaitBinaryExpression3_es5.ts, 0, 11))
+
+declare var p: Promise<number>;
+>p : Symbol(p, Decl(awaitBinaryExpression3_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitBinaryExpression3_es5.ts, 1, 31))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitBinaryExpression3_es5.ts, 2, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitBinaryExpression3_es5.ts, 3, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitBinaryExpression3_es5.ts, 1, 31))
+
+    var b = await p + a;
+>b : Symbol(b, Decl(awaitBinaryExpression3_es5.ts, 6, 7))
+>p : Symbol(p, Decl(awaitBinaryExpression3_es5.ts, 1, 11))
+>a : Symbol(a, Decl(awaitBinaryExpression3_es5.ts, 0, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitBinaryExpression3_es5.ts, 2, 32))
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression3_es5.types b/tests/baselines/reference/awaitBinaryExpression3_es5.types
new file mode 100644
index 0000000000000..debc71a6475dd
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression3_es5.types
@@ -0,0 +1,33 @@
+=== tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression3_es5.ts ===
+declare var a: number;
+>a : number
+
+declare var p: Promise<number>;
+>p : Promise<number>
+>Promise : Promise<T>
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var b = await p + a;
+>b : number
+>await p + a : number
+>await p : number
+>p : Promise<number>
+>a : number
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression4_es5.js b/tests/baselines/reference/awaitBinaryExpression4_es5.js
new file mode 100644
index 0000000000000..6a67eefac3355
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression4_es5.js
@@ -0,0 +1,28 @@
+//// [awaitBinaryExpression4_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = (await p, a);
+    after();
+}
+
+//// [awaitBinaryExpression4_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var b;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    before();
+                    return [4 /*yield*/, p];
+                case 1:
+                    b = (_a.sent(), a);
+                    after();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression4_es5.symbols b/tests/baselines/reference/awaitBinaryExpression4_es5.symbols
new file mode 100644
index 0000000000000..ab2cbeadfc5cf
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression4_es5.symbols
@@ -0,0 +1,29 @@
+=== tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression4_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(awaitBinaryExpression4_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(awaitBinaryExpression4_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitBinaryExpression4_es5.ts, 1, 32))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitBinaryExpression4_es5.ts, 2, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitBinaryExpression4_es5.ts, 3, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitBinaryExpression4_es5.ts, 1, 32))
+
+    var b = (await p, a);
+>b : Symbol(b, Decl(awaitBinaryExpression4_es5.ts, 6, 7))
+>p : Symbol(p, Decl(awaitBinaryExpression4_es5.ts, 1, 11))
+>a : Symbol(a, Decl(awaitBinaryExpression4_es5.ts, 0, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitBinaryExpression4_es5.ts, 2, 32))
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression4_es5.types b/tests/baselines/reference/awaitBinaryExpression4_es5.types
new file mode 100644
index 0000000000000..f535741fa456b
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression4_es5.types
@@ -0,0 +1,34 @@
+=== tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression4_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var b = (await p, a);
+>b : boolean
+>(await p, a) : boolean
+>await p, a : boolean
+>await p : boolean
+>p : Promise<boolean>
+>a : boolean
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression4_es6.js b/tests/baselines/reference/awaitBinaryExpression4_es6.js
index 99d568c0227c7..1e909282d43b7 100644
--- a/tests/baselines/reference/awaitBinaryExpression4_es6.js
+++ b/tests/baselines/reference/awaitBinaryExpression4_es6.js
@@ -5,7 +5,7 @@ declare function before(): void;
 declare function after(): void;
 async function func(): Promise<void> {
     before();
-    var b = await p, a;
+    var b = (await p, a);
     after();
 }
 
@@ -13,7 +13,7 @@ async function func(): Promise<void> {
 function func() {
     return __awaiter(this, void 0, void 0, function* () {
         before();
-        var b = yield p, a;
+        var b = (yield p, a);
         after();
     });
 }
diff --git a/tests/baselines/reference/awaitBinaryExpression4_es6.symbols b/tests/baselines/reference/awaitBinaryExpression4_es6.symbols
index c7a1b17eaa82b..18a593225584c 100644
--- a/tests/baselines/reference/awaitBinaryExpression4_es6.symbols
+++ b/tests/baselines/reference/awaitBinaryExpression4_es6.symbols
@@ -19,10 +19,10 @@ async function func(): Promise<void> {
     before();
 >before : Symbol(before, Decl(awaitBinaryExpression4_es6.ts, 1, 32))
 
-    var b = await p, a;
+    var b = (await p, a);
 >b : Symbol(b, Decl(awaitBinaryExpression4_es6.ts, 6, 7))
 >p : Symbol(p, Decl(awaitBinaryExpression4_es6.ts, 1, 11))
->a : Symbol(a, Decl(awaitBinaryExpression4_es6.ts, 6, 20))
+>a : Symbol(a, Decl(awaitBinaryExpression4_es6.ts, 0, 11))
 
     after();
 >after : Symbol(after, Decl(awaitBinaryExpression4_es6.ts, 2, 32))
diff --git a/tests/baselines/reference/awaitBinaryExpression4_es6.types b/tests/baselines/reference/awaitBinaryExpression4_es6.types
index 672d862416826..ea1d968346d23 100644
--- a/tests/baselines/reference/awaitBinaryExpression4_es6.types
+++ b/tests/baselines/reference/awaitBinaryExpression4_es6.types
@@ -20,11 +20,13 @@ async function func(): Promise<void> {
 >before() : void
 >before : () => void
 
-    var b = await p, a;
+    var b = (await p, a);
 >b : boolean
+>(await p, a) : boolean
+>await p, a : boolean
 >await p : boolean
 >p : Promise<boolean>
->a : any
+>a : boolean
 
     after();
 >after() : void
diff --git a/tests/baselines/reference/awaitBinaryExpression5_es5.js b/tests/baselines/reference/awaitBinaryExpression5_es5.js
new file mode 100644
index 0000000000000..5064e72bd5ee2
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression5_es5.js
@@ -0,0 +1,30 @@
+//// [awaitBinaryExpression5_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var o: { a: boolean; };
+    o.a = await p;
+    after();
+}
+
+//// [awaitBinaryExpression5_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var o, _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    before();
+                    _a = o;
+                    return [4 /*yield*/, p];
+                case 1:
+                    _a.a = _b.sent();
+                    after();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression5_es5.symbols b/tests/baselines/reference/awaitBinaryExpression5_es5.symbols
new file mode 100644
index 0000000000000..ad258355d3872
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression5_es5.symbols
@@ -0,0 +1,34 @@
+=== tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression5_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(awaitBinaryExpression5_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(awaitBinaryExpression5_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitBinaryExpression5_es5.ts, 1, 32))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitBinaryExpression5_es5.ts, 2, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitBinaryExpression5_es5.ts, 3, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitBinaryExpression5_es5.ts, 1, 32))
+
+    var o: { a: boolean; };
+>o : Symbol(o, Decl(awaitBinaryExpression5_es5.ts, 6, 7))
+>a : Symbol(a, Decl(awaitBinaryExpression5_es5.ts, 6, 12))
+
+    o.a = await p;
+>o.a : Symbol(a, Decl(awaitBinaryExpression5_es5.ts, 6, 12))
+>o : Symbol(o, Decl(awaitBinaryExpression5_es5.ts, 6, 7))
+>a : Symbol(a, Decl(awaitBinaryExpression5_es5.ts, 6, 12))
+>p : Symbol(p, Decl(awaitBinaryExpression5_es5.ts, 1, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitBinaryExpression5_es5.ts, 2, 32))
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression5_es5.types b/tests/baselines/reference/awaitBinaryExpression5_es5.types
new file mode 100644
index 0000000000000..6d1ebb42c84c2
--- /dev/null
+++ b/tests/baselines/reference/awaitBinaryExpression5_es5.types
@@ -0,0 +1,38 @@
+=== tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression5_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var o: { a: boolean; };
+>o : { a: boolean; }
+>a : boolean
+
+    o.a = await p;
+>o.a = await p : boolean
+>o.a : boolean
+>o : { a: boolean; }
+>a : boolean
+>await p : boolean
+>p : Promise<boolean>
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression1_es5.ts b/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression1_es5.ts
new file mode 100644
index 0000000000000..3ef62d83bf81e
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression1_es5.ts
@@ -0,0 +1,12 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = await p || a;
+    after();
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression2_es5.ts b/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression2_es5.ts
new file mode 100644
index 0000000000000..07d9bfd221453
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression2_es5.ts
@@ -0,0 +1,12 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = await p && a;
+    after();
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression3_es5.ts b/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression3_es5.ts
new file mode 100644
index 0000000000000..1acb6930b4980
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression3_es5.ts
@@ -0,0 +1,12 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: number;
+declare var p: Promise<number>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = await p + a;
+    after();
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression4_es5.ts b/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression4_es5.ts
new file mode 100644
index 0000000000000..44c1f64315632
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression4_es5.ts
@@ -0,0 +1,12 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = (await p, a);
+    after();
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression5_es5.ts b/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression5_es5.ts
new file mode 100644
index 0000000000000..9e29c5d6cef0e
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitBinaryExpression/awaitBinaryExpression5_es5.ts
@@ -0,0 +1,13 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var o: { a: boolean; };
+    o.a = await p;
+    after();
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression4_es6.ts b/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression4_es6.ts
index 2ed73473323e8..c5c007a1483c4 100644
--- a/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression4_es6.ts
+++ b/tests/cases/conformance/async/es6/awaitBinaryExpression/awaitBinaryExpression4_es6.ts
@@ -6,6 +6,6 @@ declare function before(): void;
 declare function after(): void;
 async function func(): Promise<void> {
     before();
-    var b = await p, a;
+    var b = (await p, a);
     after();
 }
\ No newline at end of file

From 48a9562e4197b0cab900abb6c240bc00adb1c744 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 27 Jun 2016 15:26:33 -0700
Subject: [PATCH 17/23] Added es5 conformance tests for async function
 declarations. Add ability to treat some statements as if they were prologue
 directives.

---
 src/compiler/factory.ts                       |  28 ++--
 src/compiler/transformers/es6.ts              |  57 ++++---
 src/compiler/transformers/generators.ts       |  68 ++++----
 src/compiler/transformers/module/module.ts    |   4 +-
 src/compiler/transformers/module/system.ts    |   2 +-
 src/compiler/transformers/ts.ts               |   6 +-
 src/compiler/types.ts                         |   1 +
 .../asyncFunctionDeclaration10_es5.errors.txt |  26 +++
 .../asyncFunctionDeclaration10_es5.js         |   7 +
 .../asyncFunctionDeclaration11_es5.js         |  12 ++
 .../asyncFunctionDeclaration11_es5.symbols    |   5 +
 .../asyncFunctionDeclaration11_es5.types      |   5 +
 .../asyncFunctionDeclaration12_es5.errors.txt |  16 ++
 .../asyncFunctionDeclaration12_es5.js         |   5 +
 .../asyncFunctionDeclaration13_es5.errors.txt |  11 ++
 .../asyncFunctionDeclaration13_es5.js         |  16 ++
 .../asyncFunctionDeclaration14_es5.js         |  13 ++
 .../asyncFunctionDeclaration14_es5.symbols    |   7 +
 .../asyncFunctionDeclaration14_es5.types      |   7 +
 .../asyncFunctionDeclaration15_es5.errors.txt |  59 +++++++
 .../asyncFunctionDeclaration15_es5.js         | 152 ++++++++++++++++++
 .../asyncFunctionDeclaration1_es5.js          |  12 ++
 .../asyncFunctionDeclaration1_es5.symbols     |   5 +
 .../asyncFunctionDeclaration1_es5.types       |   5 +
 .../asyncFunctionDeclaration2_es5.js          |   7 +
 .../asyncFunctionDeclaration2_es5.symbols     |   5 +
 .../asyncFunctionDeclaration2_es5.types       |   5 +
 .../asyncFunctionDeclaration3_es5.errors.txt  |   8 +
 .../asyncFunctionDeclaration3_es5.js          |   8 +
 .../asyncFunctionDeclaration4_es5.js          |   7 +
 .../asyncFunctionDeclaration4_es5.symbols     |   4 +
 .../asyncFunctionDeclaration4_es5.types       |   4 +
 .../asyncFunctionDeclaration5_es5.errors.txt  |  20 +++
 .../asyncFunctionDeclaration5_es5.js          |   7 +
 .../asyncFunctionDeclaration6_es5.errors.txt  |  11 ++
 .../asyncFunctionDeclaration6_es5.js          |  13 ++
 .../asyncFunctionDeclaration7_es5.errors.txt  |  14 ++
 .../asyncFunctionDeclaration7_es5.js          |  24 +++
 .../asyncFunctionDeclaration8_es5.errors.txt  |  10 ++
 .../asyncFunctionDeclaration8_es5.js          |   6 +
 .../asyncFunctionDeclaration9_es5.errors.txt  |   9 ++
 .../asyncFunctionDeclaration9_es5.js          |  21 +++
 .../asyncFunctionDeclaration10_es5.ts         |   5 +
 .../asyncFunctionDeclaration11_es5.ts         |   5 +
 .../asyncFunctionDeclaration12_es5.ts         |   4 +
 .../asyncFunctionDeclaration13_es5.ts         |   7 +
 .../asyncFunctionDeclaration14_es5.ts         |   6 +
 .../asyncFunctionDeclaration15_es5.ts         |  26 +++
 .../asyncFunctionDeclaration1_es5.ts          |   5 +
 .../asyncFunctionDeclaration2_es5.ts          |   5 +
 .../asyncFunctionDeclaration3_es5.ts          |   5 +
 .../asyncFunctionDeclaration4_es5.ts          |   5 +
 .../asyncFunctionDeclaration5_es5.ts          |   5 +
 .../asyncFunctionDeclaration6_es5.ts          |   5 +
 .../asyncFunctionDeclaration7_es5.ts          |   8 +
 .../asyncFunctionDeclaration8_es5.ts          |   4 +
 .../asyncFunctionDeclaration9_es5.ts          |   6 +
 57 files changed, 739 insertions(+), 74 deletions(-)
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration10_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration10_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration11_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration11_es5.symbols
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration11_es5.types
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration12_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration12_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration13_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration13_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration14_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration14_es5.symbols
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration14_es5.types
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration15_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration1_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration1_es5.symbols
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration1_es5.types
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration2_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration2_es5.symbols
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration2_es5.types
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration3_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration3_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration4_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration4_es5.symbols
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration4_es5.types
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration5_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration5_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration6_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration6_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration7_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration7_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration8_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration8_es5.js
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration9_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncFunctionDeclaration9_es5.js
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration11_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration12_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration13_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration14_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration2_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration3_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration4_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration6_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration7_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration8_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration9_es5.ts

diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts
index 40c63cb7ac95e..d6571dfdb757a 100644
--- a/src/compiler/factory.ts
+++ b/src/compiler/factory.ts
@@ -1649,28 +1649,36 @@ namespace ts {
      * @param target: result statements array
      * @param source: origin statements array
      * @param ensureUseStrict: boolean determining whether the function need to add prologue-directives
+     * @param visitor: Optional callback used to visit any custom prologue directives.
      */
-    export function addPrologueDirectives(target: Statement[], source: Statement[], ensureUseStrict?: boolean): number {
+    export function addPrologueDirectives(target: Statement[], source: Statement[], ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult<Node>): number {
         Debug.assert(target.length === 0, "PrologueDirectives should be at the first statement in the target statements array");
         let foundUseStrict = false;
-        for (let i = 0; i < source.length; i++) {
-            if (isPrologueDirective(source[i])) {
-                if (isUseStrictPrologue(source[i] as ExpressionStatement)) {
+        let statementOffset = 0;
+        const numStatements = source.length;
+        while (statementOffset < numStatements) {
+            const statement = source[statementOffset];
+            if (isPrologueDirective(statement)) {
+                if (isUseStrictPrologue(statement as ExpressionStatement)) {
                     foundUseStrict = true;
                 }
-
-                target.push(source[i]);
+                target.push(statement);
             }
             else {
                 if (ensureUseStrict && !foundUseStrict) {
                     target.push(startOnNewLine(createStatement(createLiteral("use strict"))));
+                    foundUseStrict = true;
+                }
+                if (statement.emitFlags & NodeEmitFlags.CustomPrologue) {
+                    target.push(visitor ? visitNode(statement, visitor, isStatement) : statement);
+                }
+                else {
+                    break;
                 }
-
-                return i;
             }
+            statementOffset++;
         }
-
-        return source.length;
+        return statementOffset;
     }
 
     /**
diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts
index 110d744021230..7deaa38d1489c 100644
--- a/src/compiler/transformers/es6.ts
+++ b/src/compiler/transformers/es6.ts
@@ -930,21 +930,27 @@ namespace ts {
             // of an initializer, we must emit that expression to preserve side effects.
             if (name.elements.length > 0) {
                 statements.push(
-                    createVariableStatement(
-                        /*modifiers*/ undefined,
-                        createVariableDeclarationList(
-                            flattenParameterDestructuring(context, parameter, temp, visitor)
-                        )
+                    setNodeEmitFlags(
+                        createVariableStatement(
+                            /*modifiers*/ undefined,
+                            createVariableDeclarationList(
+                                flattenParameterDestructuring(context, parameter, temp, visitor)
+                            )
+                        ),
+                        NodeEmitFlags.CustomPrologue
                     )
                 );
             }
             else if (initializer) {
                 statements.push(
-                    createStatement(
-                        createAssignment(
-                            temp,
-                            visitNode(initializer, visitor, isExpression)
-                        )
+                    setNodeEmitFlags(
+                        createStatement(
+                            createAssignment(
+                                temp,
+                                visitNode(initializer, visitor, isExpression)
+                            )
+                        ),
+                        NodeEmitFlags.CustomPrologue
                     )
                 );
             }
@@ -981,7 +987,7 @@ namespace ts {
                 /*location*/ parameter
             );
             statement.startsOnNewLine = true;
-            setNodeEmitFlags(statement, NodeEmitFlags.NoTokenSourceMaps | NodeEmitFlags.NoTrailingSourceMap);
+            setNodeEmitFlags(statement, NodeEmitFlags.NoTokenSourceMaps | NodeEmitFlags.NoTrailingSourceMap | NodeEmitFlags.CustomPrologue);
             statements.push(statement);
         }
 
@@ -1023,16 +1029,19 @@ namespace ts {
 
             // var param = [];
             statements.push(
-                createVariableStatement(
-                    /*modifiers*/ undefined,
-                    createVariableDeclarationList([
-                        createVariableDeclaration(
-                            declarationName,
-                            /*type*/ undefined,
-                            createArrayLiteral([])
-                        )
-                    ]),
-                    /*location*/ parameter
+                setNodeEmitFlags(
+                    createVariableStatement(
+                        /*modifiers*/ undefined,
+                        createVariableDeclarationList([
+                            createVariableDeclaration(
+                                declarationName,
+                                /*type*/ undefined,
+                                createArrayLiteral([])
+                            )
+                        ]),
+                        /*location*/ parameter
+                    ),
+                    NodeEmitFlags.CustomPrologue
                 )
             );
 
@@ -1065,7 +1074,7 @@ namespace ts {
                 ])
             );
 
-            setNodeEmitFlags(forStatement, NodeEmitFlags.SourceMapAdjustRestParameterLoop);
+            setNodeEmitFlags(forStatement, NodeEmitFlags.SourceMapAdjustRestParameterLoop | NodeEmitFlags.CustomPrologue);
             startOnNewLine(forStatement);
             statements.push(forStatement);
         }
@@ -1090,7 +1099,7 @@ namespace ts {
                     ])
                 );
 
-                setNodeEmitFlags(captureThisStatement, NodeEmitFlags.NoComments);
+                setNodeEmitFlags(captureThisStatement, NodeEmitFlags.NoComments | NodeEmitFlags.CustomPrologue);
                 setSourceMapRange(captureThisStatement, node);
                 statements.push(captureThisStatement);
             }
@@ -1347,7 +1356,7 @@ namespace ts {
             if (isBlock(body)) {
                 // ensureUseStrict is false because no new prologue-directive should be added.
                 // addPrologueDirectives will simply put already-existing directives at the beginning of the target statement-array
-                statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false);
+                statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor);
             }
 
             addCaptureThisForNodeIfNeeded(statements, node);
diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts
index 234f39550a7b0..adb62f117ef87 100644
--- a/src/compiler/transformers/generators.ts
+++ b/src/compiler/transformers/generators.ts
@@ -309,10 +309,7 @@ namespace ts {
          */
         function visitor(node: Node): VisitResult<Node> {
             const transformFlags = node.transformFlags;
-            if (transformFlags & TransformFlags.ContainsYield) {
-                return visitJavaScriptContainingYield(node);
-            }
-            else if (inStatementContainingYield) {
+            if (inStatementContainingYield) {
                 return visitJavaScriptInStatementContainingYield(node);
             }
             else if (inGeneratorFunctionBody) {
@@ -329,34 +326,6 @@ namespace ts {
             }
         }
 
-        /**
-         * Visits a node that contains a YieldExpression.
-         *
-         * @param node The node to visit.
-         */
-        function visitJavaScriptContainingYield(node: Node): VisitResult<Node> {
-            switch (node.kind) {
-                case SyntaxKind.BinaryExpression:
-                    return visitBinaryExpression(<BinaryExpression>node);
-                case SyntaxKind.ConditionalExpression:
-                    return visitConditionalExpression(<ConditionalExpression>node);
-                case SyntaxKind.YieldExpression:
-                    return visitYieldExpression(<YieldExpression>node);
-                case SyntaxKind.ArrayLiteralExpression:
-                    return visitArrayLiteralExpression(<ArrayLiteralExpression>node);
-                case SyntaxKind.ObjectLiteralExpression:
-                    return visitObjectLiteralExpression(<ObjectLiteralExpression>node);
-                case SyntaxKind.ElementAccessExpression:
-                    return visitElementAccessExpression(<ElementAccessExpression>node);
-                case SyntaxKind.CallExpression:
-                    return visitCallExpression(<CallExpression>node);
-                case SyntaxKind.NewExpression:
-                    return visitNewExpression(<NewExpression>node);
-                default:
-                    return visitJavaScriptInStatementContainingYield(node);
-            }
-        }
-
         /**
          * Visits a node that is contained within a statement that contains yield.
          *
@@ -404,7 +373,10 @@ namespace ts {
                 case SyntaxKind.ReturnStatement:
                     return visitReturnStatement(<ReturnStatement>node);
                 default:
-                    if (node.transformFlags & (TransformFlags.ContainsGenerator | TransformFlags.ContainsYield | TransformFlags.ContainsHoistedDeclarationOrCompletion)) {
+                    if (node.transformFlags & TransformFlags.ContainsYield) {
+                        return visitJavaScriptContainingYield(node);
+                    }
+                    else if (node.transformFlags & (TransformFlags.ContainsGenerator | TransformFlags.ContainsHoistedDeclarationOrCompletion)) {
                         return visitEachChild(node, visitor, context);
                     }
                     else {
@@ -413,6 +385,34 @@ namespace ts {
             }
         }
 
+        /**
+         * Visits a node that contains a YieldExpression.
+         *
+         * @param node The node to visit.
+         */
+        function visitJavaScriptContainingYield(node: Node): VisitResult<Node> {
+            switch (node.kind) {
+                case SyntaxKind.BinaryExpression:
+                    return visitBinaryExpression(<BinaryExpression>node);
+                case SyntaxKind.ConditionalExpression:
+                    return visitConditionalExpression(<ConditionalExpression>node);
+                case SyntaxKind.YieldExpression:
+                    return visitYieldExpression(<YieldExpression>node);
+                case SyntaxKind.ArrayLiteralExpression:
+                    return visitArrayLiteralExpression(<ArrayLiteralExpression>node);
+                case SyntaxKind.ObjectLiteralExpression:
+                    return visitObjectLiteralExpression(<ObjectLiteralExpression>node);
+                case SyntaxKind.ElementAccessExpression:
+                    return visitElementAccessExpression(<ElementAccessExpression>node);
+                case SyntaxKind.CallExpression:
+                    return visitCallExpression(<CallExpression>node);
+                case SyntaxKind.NewExpression:
+                    return visitNewExpression(<NewExpression>node);
+                default:
+                    return visitEachChild(node, visitor, context);
+            }
+        }
+
         /**
          * Visits a generator function.
          *
@@ -572,7 +572,7 @@ namespace ts {
             operationLocations = undefined;
             state = createTempVariable(/*recordTempVariable*/ undefined);
 
-            const statementOffset = addPrologueDirectives(statements, body.statements);
+            const statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor);
 
             // Build the generator
             startLexicalEnvironment();
diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts
index 7eb86a1143b6d..ce699630ba718 100644
--- a/src/compiler/transformers/module/module.ts
+++ b/src/compiler/transformers/module/module.ts
@@ -84,7 +84,7 @@ namespace ts {
             startLexicalEnvironment();
 
             const statements: Statement[] = [];
-            const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict);
+            const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, visitor);
             addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
             addRange(statements, endLexicalEnvironment());
             addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false);
@@ -203,7 +203,7 @@ namespace ts {
             startLexicalEnvironment();
 
             const statements: Statement[] = [];
-            const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict);
+            const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, visitor);
 
             // Visit each statement of the module body.
             addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts
index 1f601ae4b5530..8f956c19adcb0 100644
--- a/src/compiler/transformers/module/system.ts
+++ b/src/compiler/transformers/module/system.ts
@@ -194,7 +194,7 @@ namespace ts {
             startLexicalEnvironment();
 
             // Add any prologue directives.
-            const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict);
+            const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, visitSourceElement);
 
             // var __moduleName = context_1 && context_1.id;
             addNode(statements,
diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts
index f2157e5a5c0e9..57de884da33ec 100644
--- a/src/compiler/transformers/ts.ts
+++ b/src/compiler/transformers/ts.ts
@@ -431,7 +431,7 @@ namespace ts {
                 && (isExternalModule(node) || compilerOptions.isolatedModules)) {
                 startLexicalEnvironment();
                 const statements: Statement[] = [];
-                const statementOffset = addPrologueDirectives(statements, node.statements);
+                const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ false, visitor);
                 const externalHelpersModuleName = createUniqueName(externalHelpersModuleNameText);
                 const externalHelpersModuleImport = createImportDeclaration(
                     createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
@@ -933,7 +933,7 @@ namespace ts {
             if (ctor.body) {
                 const statements = ctor.body.statements;
                 // add prologue directives to the list (if any)
-                const index = addPrologueDirectives(result, statements);
+                const index = addPrologueDirectives(result, statements, /*ensureUseStrict*/ false, visitor);
                 if (index === statements.length) {
                     // list contains nothing but prologue directives (or empty) - exit
                     return index;
@@ -2235,7 +2235,7 @@ namespace ts {
 
             if (!isArrowFunction) {
                 const statements: Statement[] = [];
-                const statementOffset = addPrologueDirectives(statements, (<Block>node.body).statements);
+                const statementOffset = addPrologueDirectives(statements, (<Block>node.body).statements, /*ensureUseStrict*/ false, visitor);
                 statements.push(
                     createReturn(
                         createAwaiterHelper(
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index e827265dd29e0..71e4a202b4097 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -3064,6 +3064,7 @@ namespace ts {
         Indented = 1 << 19,                      // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter).
         AsyncFunctionBody = 1 << 20,
         ReuseTempVariableScope = 1 << 21,        // Reuse the existing temp variable scope during emit.
+        CustomPrologue = 1 << 22,                // Treat the statement as if it were a prologue directive (NOTE: Prologue directives are *not* transformed).
 
         // SourceMap Specialization.
         // TODO(rbuckton): These should be removed once source maps are aligned with the old
diff --git a/tests/baselines/reference/asyncFunctionDeclaration10_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration10_es5.errors.txt
new file mode 100644
index 0000000000000..dc814e9c88709
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration10_es5.errors.txt
@@ -0,0 +1,26 @@
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,20): error TS2371: A parameter initializer is only allowed in a function or constructor implementation.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,30): error TS1109: Expression expected.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,33): error TS1138: Parameter declaration expected.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,33): error TS2304: Cannot find name 'await'.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,38): error TS1005: ';' expected.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,39): error TS1128: Declaration or statement expected.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,53): error TS1109: Expression expected.
+
+
+==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts (7 errors) ====
+    async function foo(a = await => await): Promise<void> {
+                       ~~~~~~~~~
+!!! error TS2371: A parameter initializer is only allowed in a function or constructor implementation.
+                                 ~~
+!!! error TS1109: Expression expected.
+                                    ~~~~~
+!!! error TS1138: Parameter declaration expected.
+                                    ~~~~~
+!!! error TS2304: Cannot find name 'await'.
+                                         ~
+!!! error TS1005: ';' expected.
+                                          ~
+!!! error TS1128: Declaration or statement expected.
+                                                        ~
+!!! error TS1109: Expression expected.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncFunctionDeclaration10_es5.js b/tests/baselines/reference/asyncFunctionDeclaration10_es5.js
new file mode 100644
index 0000000000000..05ff9daa9dabd
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration10_es5.js
@@ -0,0 +1,7 @@
+//// [asyncFunctionDeclaration10_es5.ts]
+async function foo(a = await => await): Promise<void> {
+}
+
+//// [asyncFunctionDeclaration10_es5.js]
+await;
+Promise < void  > {};
diff --git a/tests/baselines/reference/asyncFunctionDeclaration11_es5.js b/tests/baselines/reference/asyncFunctionDeclaration11_es5.js
new file mode 100644
index 0000000000000..166f4c9c5ca36
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration11_es5.js
@@ -0,0 +1,12 @@
+//// [asyncFunctionDeclaration11_es5.ts]
+async function await(): Promise<void> {
+}
+
+//// [asyncFunctionDeclaration11_es5.js]
+function await() {
+    return __awaiter(this, void 0, Promise, function () {
+        return __generator(function (_a) {
+            return [2 /*return*/];
+        });
+    });
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration11_es5.symbols b/tests/baselines/reference/asyncFunctionDeclaration11_es5.symbols
new file mode 100644
index 0000000000000..fc20251d5671e
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration11_es5.symbols
@@ -0,0 +1,5 @@
+=== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration11_es5.ts ===
+async function await(): Promise<void> {
+>await : Symbol(await, Decl(asyncFunctionDeclaration11_es5.ts, 0, 0))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration11_es5.types b/tests/baselines/reference/asyncFunctionDeclaration11_es5.types
new file mode 100644
index 0000000000000..fdda0b0a084fc
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration11_es5.types
@@ -0,0 +1,5 @@
+=== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration11_es5.ts ===
+async function await(): Promise<void> {
+>await : () => Promise<void>
+>Promise : Promise<T>
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration12_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration12_es5.errors.txt
new file mode 100644
index 0000000000000..6468ec6971610
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration12_es5.errors.txt
@@ -0,0 +1,16 @@
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration12_es5.ts(1,24): error TS1005: '(' expected.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration12_es5.ts(1,29): error TS1005: '=' expected.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration12_es5.ts(1,33): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration12_es5.ts(1,47): error TS1005: '=>' expected.
+
+
+==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration12_es5.ts (4 errors) ====
+    var v = async function await(): Promise<void> { }
+                           ~~~~~
+!!! error TS1005: '(' expected.
+                                ~
+!!! error TS1005: '=' expected.
+                                    ~~~~~~~~~~~~~
+!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
+                                                  ~
+!!! error TS1005: '=>' expected.
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncFunctionDeclaration12_es5.js b/tests/baselines/reference/asyncFunctionDeclaration12_es5.js
new file mode 100644
index 0000000000000..4123175b22ced
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration12_es5.js
@@ -0,0 +1,5 @@
+//// [asyncFunctionDeclaration12_es5.ts]
+var v = async function await(): Promise<void> { }
+
+//// [asyncFunctionDeclaration12_es5.js]
+var v = , await = function () { };
diff --git a/tests/baselines/reference/asyncFunctionDeclaration13_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration13_es5.errors.txt
new file mode 100644
index 0000000000000..ce83aabc4bed8
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration13_es5.errors.txt
@@ -0,0 +1,11 @@
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration13_es5.ts(3,11): error TS2304: Cannot find name 'await'.
+
+
+==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration13_es5.ts (1 errors) ====
+    async function foo(): Promise<void> {
+       // Legal to use 'await' in a type context.
+       var v: await;
+              ~~~~~
+!!! error TS2304: Cannot find name 'await'.
+    }
+    
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncFunctionDeclaration13_es5.js b/tests/baselines/reference/asyncFunctionDeclaration13_es5.js
new file mode 100644
index 0000000000000..2ab2f5c7b7b1f
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration13_es5.js
@@ -0,0 +1,16 @@
+//// [asyncFunctionDeclaration13_es5.ts]
+async function foo(): Promise<void> {
+   // Legal to use 'await' in a type context.
+   var v: await;
+}
+
+
+//// [asyncFunctionDeclaration13_es5.js]
+function foo() {
+    return __awaiter(this, void 0, Promise, function () {
+        var v;
+        return __generator(function (_a) {
+            return [2 /*return*/];
+        });
+    });
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration14_es5.js b/tests/baselines/reference/asyncFunctionDeclaration14_es5.js
new file mode 100644
index 0000000000000..d0e747e0f8430
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration14_es5.js
@@ -0,0 +1,13 @@
+//// [asyncFunctionDeclaration14_es5.ts]
+async function foo(): Promise<void> {
+  return;
+}
+
+//// [asyncFunctionDeclaration14_es5.js]
+function foo() {
+    return __awaiter(this, void 0, Promise, function () {
+        return __generator(function (_a) {
+            return [2 /*return*/];
+        });
+    });
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration14_es5.symbols b/tests/baselines/reference/asyncFunctionDeclaration14_es5.symbols
new file mode 100644
index 0000000000000..1126618cfe73f
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration14_es5.symbols
@@ -0,0 +1,7 @@
+=== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration14_es5.ts ===
+async function foo(): Promise<void> {
+>foo : Symbol(foo, Decl(asyncFunctionDeclaration14_es5.ts, 0, 0))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+  return;
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration14_es5.types b/tests/baselines/reference/asyncFunctionDeclaration14_es5.types
new file mode 100644
index 0000000000000..5c2575c9cc905
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration14_es5.types
@@ -0,0 +1,7 @@
+=== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration14_es5.ts ===
+async function foo(): Promise<void> {
+>foo : () => Promise<void>
+>Promise : Promise<T>
+
+  return;
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt
new file mode 100644
index 0000000000000..752feb261b3c4
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt
@@ -0,0 +1,59 @@
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(6,16): error TS1055: Type '{}' is not a valid async function return type.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(7,16): error TS1055: Type 'any' is not a valid async function return type.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(8,16): error TS1055: Type 'number' is not a valid async function return type.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(9,16): error TS1055: Type 'PromiseLike' is not a valid async function return type.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,16): error TS1055: Type 'typeof Thenable' is not a valid async function return type.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,16): error TS1055: Type 'typeof Thenable' is not a valid async function return type.
+  Type 'Thenable' is not assignable to type 'PromiseLike<any>'.
+    Types of property 'then' are incompatible.
+      Type '() => void' is not assignable to type '{ <TResult>(onfulfilled?: (value: any) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>; <TResult>(onfulfilled?: (value: any) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): PromiseLike<TResult>; }'.
+        Type 'void' is not assignable to type 'PromiseLike<any>'.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(17,16): error TS1059: Return expression in async function does not have a valid callable 'then' member.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(23,25): error TS1058: Operand for 'await' does not have a valid callable 'then' member.
+
+
+==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts (8 errors) ====
+    declare class Thenable { then(): void; }
+    declare let a: any;
+    declare let obj: { then: string; };
+    declare let thenable: Thenable;
+    async function fn1() { } // valid: Promise<void>
+    async function fn2(): { } { } // error
+                   ~~~
+!!! error TS1055: Type '{}' is not a valid async function return type.
+    async function fn3(): any { } // error
+                   ~~~
+!!! error TS1055: Type 'any' is not a valid async function return type.
+    async function fn4(): number { } // error
+                   ~~~
+!!! error TS1055: Type 'number' is not a valid async function return type.
+    async function fn5(): PromiseLike<void> { } // error
+                   ~~~
+!!! error TS1055: Type 'PromiseLike' is not a valid async function return type.
+    async function fn6(): Thenable { } // error
+                   ~~~
+!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type.
+                   ~~~
+!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type.
+!!! error TS1055:   Type 'Thenable' is not assignable to type 'PromiseLike<any>'.
+!!! error TS1055:     Types of property 'then' are incompatible.
+!!! error TS1055:       Type '() => void' is not assignable to type '{ <TResult>(onfulfilled?: (value: any) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>; <TResult>(onfulfilled?: (value: any) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): PromiseLike<TResult>; }'.
+!!! error TS1055:         Type 'void' is not assignable to type 'PromiseLike<any>'.
+    async function fn7() { return; } // valid: Promise<void>
+    async function fn8() { return 1; } // valid: Promise<number>
+    async function fn9() { return null; } // valid: Promise<any>
+    async function fn10() { return undefined; } // valid: Promise<any>
+    async function fn11() { return a; } // valid: Promise<any>
+    async function fn12() { return obj; } // valid: Promise<{ then: string; }>
+    async function fn13() { return thenable; } // error
+                   ~~~~
+!!! error TS1059: Return expression in async function does not have a valid callable 'then' member.
+    async function fn14() { await 1; } // valid: Promise<void>
+    async function fn15() { await null; } // valid: Promise<void>
+    async function fn16() { await undefined; } // valid: Promise<void>
+    async function fn17() { await a; } // valid: Promise<void>
+    async function fn18() { await obj; } // valid: Promise<void>
+    async function fn19() { await thenable; } // error
+                            ~~~~~~~~~~~~~~
+!!! error TS1058: Operand for 'await' does not have a valid callable 'then' member.
+    
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncFunctionDeclaration15_es5.js b/tests/baselines/reference/asyncFunctionDeclaration15_es5.js
new file mode 100644
index 0000000000000..47e1fe45c80df
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration15_es5.js
@@ -0,0 +1,152 @@
+//// [asyncFunctionDeclaration15_es5.ts]
+declare class Thenable { then(): void; }
+declare let a: any;
+declare let obj: { then: string; };
+declare let thenable: Thenable;
+async function fn1() { } // valid: Promise<void>
+async function fn2(): { } { } // error
+async function fn3(): any { } // error
+async function fn4(): number { } // error
+async function fn5(): PromiseLike<void> { } // error
+async function fn6(): Thenable { } // error
+async function fn7() { return; } // valid: Promise<void>
+async function fn8() { return 1; } // valid: Promise<number>
+async function fn9() { return null; } // valid: Promise<any>
+async function fn10() { return undefined; } // valid: Promise<any>
+async function fn11() { return a; } // valid: Promise<any>
+async function fn12() { return obj; } // valid: Promise<{ then: string; }>
+async function fn13() { return thenable; } // error
+async function fn14() { await 1; } // valid: Promise<void>
+async function fn15() { await null; } // valid: Promise<void>
+async function fn16() { await undefined; } // valid: Promise<void>
+async function fn17() { await a; } // valid: Promise<void>
+async function fn18() { await obj; } // valid: Promise<void>
+async function fn19() { await thenable; } // error
+
+
+//// [asyncFunctionDeclaration15_es5.js]
+function fn1() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        return [2 /*return*/];
+    }); });
+} // valid: Promise<void>
+function fn2() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        return [2 /*return*/];
+    }); });
+} // error
+function fn3() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        return [2 /*return*/];
+    }); });
+} // error
+function fn4() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        return [2 /*return*/];
+    }); });
+} // error
+function fn5() {
+    return __awaiter(this, void 0, PromiseLike, function () { return __generator(function (_a) {
+        return [2 /*return*/];
+    }); });
+} // error
+function fn6() {
+    return __awaiter(this, void 0, Thenable, function () { return __generator(function (_a) {
+        return [2 /*return*/];
+    }); });
+} // error
+function fn7() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        return [2 /*return*/];
+    }); });
+} // valid: Promise<void>
+function fn8() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        return [2 /*return*/, 1];
+    }); });
+} // valid: Promise<number>
+function fn9() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        return [2 /*return*/, null];
+    }); });
+} // valid: Promise<any>
+function fn10() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        return [2 /*return*/, undefined];
+    }); });
+} // valid: Promise<any>
+function fn11() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        return [2 /*return*/, a];
+    }); });
+} // valid: Promise<any>
+function fn12() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        return [2 /*return*/, obj];
+    }); });
+} // valid: Promise<{ then: string; }>
+function fn13() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        return [2 /*return*/, thenable];
+    }); });
+} // error
+function fn14() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        switch (_a.label) {
+            case 0: return [4 /*yield*/, 1];
+            case 1:
+                _a.sent();
+                return [2 /*return*/];
+        }
+    }); });
+} // valid: Promise<void>
+function fn15() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        switch (_a.label) {
+            case 0: return [4 /*yield*/, null];
+            case 1:
+                _a.sent();
+                return [2 /*return*/];
+        }
+    }); });
+} // valid: Promise<void>
+function fn16() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        switch (_a.label) {
+            case 0: return [4 /*yield*/, undefined];
+            case 1:
+                _a.sent();
+                return [2 /*return*/];
+        }
+    }); });
+} // valid: Promise<void>
+function fn17() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        switch (_a.label) {
+            case 0: return [4 /*yield*/, a];
+            case 1:
+                _a.sent();
+                return [2 /*return*/];
+        }
+    }); });
+} // valid: Promise<void>
+function fn18() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        switch (_a.label) {
+            case 0: return [4 /*yield*/, obj];
+            case 1:
+                _a.sent();
+                return [2 /*return*/];
+        }
+    }); });
+} // valid: Promise<void>
+function fn19() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+        switch (_a.label) {
+            case 0: return [4 /*yield*/, thenable];
+            case 1:
+                _a.sent();
+                return [2 /*return*/];
+        }
+    }); });
+} // error
diff --git a/tests/baselines/reference/asyncFunctionDeclaration1_es5.js b/tests/baselines/reference/asyncFunctionDeclaration1_es5.js
new file mode 100644
index 0000000000000..3f020ec6ece36
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration1_es5.js
@@ -0,0 +1,12 @@
+//// [asyncFunctionDeclaration1_es5.ts]
+async function foo(): Promise<void> {
+}
+
+//// [asyncFunctionDeclaration1_es5.js]
+function foo() {
+    return __awaiter(this, void 0, Promise, function () {
+        return __generator(function (_a) {
+            return [2 /*return*/];
+        });
+    });
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration1_es5.symbols b/tests/baselines/reference/asyncFunctionDeclaration1_es5.symbols
new file mode 100644
index 0000000000000..ba7616ac293d9
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration1_es5.symbols
@@ -0,0 +1,5 @@
+=== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1_es5.ts ===
+async function foo(): Promise<void> {
+>foo : Symbol(foo, Decl(asyncFunctionDeclaration1_es5.ts, 0, 0))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration1_es5.types b/tests/baselines/reference/asyncFunctionDeclaration1_es5.types
new file mode 100644
index 0000000000000..b1336715bfbc3
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration1_es5.types
@@ -0,0 +1,5 @@
+=== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1_es5.ts ===
+async function foo(): Promise<void> {
+>foo : () => Promise<void>
+>Promise : Promise<T>
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration2_es5.js b/tests/baselines/reference/asyncFunctionDeclaration2_es5.js
new file mode 100644
index 0000000000000..427fb2b1bf939
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration2_es5.js
@@ -0,0 +1,7 @@
+//// [asyncFunctionDeclaration2_es5.ts]
+function f(await) {
+}
+
+//// [asyncFunctionDeclaration2_es5.js]
+function f(await) {
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration2_es5.symbols b/tests/baselines/reference/asyncFunctionDeclaration2_es5.symbols
new file mode 100644
index 0000000000000..78f4da3c25e71
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration2_es5.symbols
@@ -0,0 +1,5 @@
+=== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration2_es5.ts ===
+function f(await) {
+>f : Symbol(f, Decl(asyncFunctionDeclaration2_es5.ts, 0, 0))
+>await : Symbol(await, Decl(asyncFunctionDeclaration2_es5.ts, 0, 11))
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration2_es5.types b/tests/baselines/reference/asyncFunctionDeclaration2_es5.types
new file mode 100644
index 0000000000000..7add17dd5d646
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration2_es5.types
@@ -0,0 +1,5 @@
+=== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration2_es5.ts ===
+function f(await) {
+>f : (await: any) => void
+>await : any
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration3_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration3_es5.errors.txt
new file mode 100644
index 0000000000000..1192e396a6496
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration3_es5.errors.txt
@@ -0,0 +1,8 @@
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration3_es5.ts(1,20): error TS2372: Parameter 'await' cannot be referenced in its initializer.
+
+
+==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration3_es5.ts (1 errors) ====
+    function f(await = await) {
+                       ~~~~~
+!!! error TS2372: Parameter 'await' cannot be referenced in its initializer.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncFunctionDeclaration3_es5.js b/tests/baselines/reference/asyncFunctionDeclaration3_es5.js
new file mode 100644
index 0000000000000..0bcc99b6bc7b2
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration3_es5.js
@@ -0,0 +1,8 @@
+//// [asyncFunctionDeclaration3_es5.ts]
+function f(await = await) {
+}
+
+//// [asyncFunctionDeclaration3_es5.js]
+function f(await) {
+    if (await === void 0) { await = await; }
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration4_es5.js b/tests/baselines/reference/asyncFunctionDeclaration4_es5.js
new file mode 100644
index 0000000000000..8b6f58b84abdb
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration4_es5.js
@@ -0,0 +1,7 @@
+//// [asyncFunctionDeclaration4_es5.ts]
+function await() {
+}
+
+//// [asyncFunctionDeclaration4_es5.js]
+function await() {
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration4_es5.symbols b/tests/baselines/reference/asyncFunctionDeclaration4_es5.symbols
new file mode 100644
index 0000000000000..0690c33309566
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration4_es5.symbols
@@ -0,0 +1,4 @@
+=== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration4_es5.ts ===
+function await() {
+>await : Symbol(await, Decl(asyncFunctionDeclaration4_es5.ts, 0, 0))
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration4_es5.types b/tests/baselines/reference/asyncFunctionDeclaration4_es5.types
new file mode 100644
index 0000000000000..8dac22820321c
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration4_es5.types
@@ -0,0 +1,4 @@
+=== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration4_es5.ts ===
+function await() {
+>await : () => void
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration5_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration5_es5.errors.txt
new file mode 100644
index 0000000000000..3060c2c836b1e
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration5_es5.errors.txt
@@ -0,0 +1,20 @@
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts(1,20): error TS1138: Parameter declaration expected.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts(1,20): error TS2304: Cannot find name 'await'.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts(1,25): error TS1005: ';' expected.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts(1,26): error TS1128: Declaration or statement expected.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts(1,40): error TS1109: Expression expected.
+
+
+==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts (5 errors) ====
+    async function foo(await): Promise<void> {
+                       ~~~~~
+!!! error TS1138: Parameter declaration expected.
+                       ~~~~~
+!!! error TS2304: Cannot find name 'await'.
+                            ~
+!!! error TS1005: ';' expected.
+                             ~
+!!! error TS1128: Declaration or statement expected.
+                                           ~
+!!! error TS1109: Expression expected.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncFunctionDeclaration5_es5.js b/tests/baselines/reference/asyncFunctionDeclaration5_es5.js
new file mode 100644
index 0000000000000..22c18ff6ad412
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration5_es5.js
@@ -0,0 +1,7 @@
+//// [asyncFunctionDeclaration5_es5.ts]
+async function foo(await): Promise<void> {
+}
+
+//// [asyncFunctionDeclaration5_es5.js]
+await;
+Promise < void  > {};
diff --git a/tests/baselines/reference/asyncFunctionDeclaration6_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration6_es5.errors.txt
new file mode 100644
index 0000000000000..d8cf82fbc28e3
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration6_es5.errors.txt
@@ -0,0 +1,11 @@
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration6_es5.ts(1,24): error TS2524: 'await' expressions cannot be used in a parameter initializer.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration6_es5.ts(1,29): error TS1109: Expression expected.
+
+
+==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration6_es5.ts (2 errors) ====
+    async function foo(a = await): Promise<void> {
+                           ~~~~~
+!!! error TS2524: 'await' expressions cannot be used in a parameter initializer.
+                                ~
+!!! error TS1109: Expression expected.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncFunctionDeclaration6_es5.js b/tests/baselines/reference/asyncFunctionDeclaration6_es5.js
new file mode 100644
index 0000000000000..2ee26f29e62e0
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration6_es5.js
@@ -0,0 +1,13 @@
+//// [asyncFunctionDeclaration6_es5.ts]
+async function foo(a = await): Promise<void> {
+}
+
+//// [asyncFunctionDeclaration6_es5.js]
+function foo(a) {
+    if (a === void 0) { a = yield ; }
+    return __awaiter(this, void 0, Promise, function () {
+        return __generator(function (_a) {
+            return [2 /*return*/];
+        });
+    });
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration7_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration7_es5.errors.txt
new file mode 100644
index 0000000000000..48984724e4c16
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration7_es5.errors.txt
@@ -0,0 +1,14 @@
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration7_es5.ts(3,26): error TS2524: 'await' expressions cannot be used in a parameter initializer.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration7_es5.ts(3,31): error TS1109: Expression expected.
+
+
+==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration7_es5.ts (2 errors) ====
+    async function bar(): Promise<void> {
+      // 'await' here is an identifier, and not a yield expression.
+      async function foo(a = await): Promise<void> {
+                             ~~~~~
+!!! error TS2524: 'await' expressions cannot be used in a parameter initializer.
+                                  ~
+!!! error TS1109: Expression expected.
+      }
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncFunctionDeclaration7_es5.js b/tests/baselines/reference/asyncFunctionDeclaration7_es5.js
new file mode 100644
index 0000000000000..7bcf3be59ad69
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration7_es5.js
@@ -0,0 +1,24 @@
+//// [asyncFunctionDeclaration7_es5.ts]
+async function bar(): Promise<void> {
+  // 'await' here is an identifier, and not a yield expression.
+  async function foo(a = await): Promise<void> {
+  }
+}
+
+//// [asyncFunctionDeclaration7_es5.js]
+function bar() {
+    return __awaiter(this, void 0, Promise, function () {
+        // 'await' here is an identifier, and not a yield expression.
+        function foo(a) {
+            if (a === void 0) { a = yield ; }
+            return __awaiter(this, void 0, Promise, function () {
+                return __generator(function (_a) {
+                    return [2 /*return*/];
+                });
+            });
+        }
+        return __generator(function (_a) {
+            return [2 /*return*/];
+        });
+    });
+}
diff --git a/tests/baselines/reference/asyncFunctionDeclaration8_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration8_es5.errors.txt
new file mode 100644
index 0000000000000..7f2a4cc650b6c
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration8_es5.errors.txt
@@ -0,0 +1,10 @@
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration8_es5.ts(1,12): error TS2304: Cannot find name 'await'.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration8_es5.ts(1,20): error TS2304: Cannot find name 'foo'.
+
+
+==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration8_es5.ts (2 errors) ====
+    var v = { [await]: foo }
+               ~~~~~
+!!! error TS2304: Cannot find name 'await'.
+                       ~~~
+!!! error TS2304: Cannot find name 'foo'.
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncFunctionDeclaration8_es5.js b/tests/baselines/reference/asyncFunctionDeclaration8_es5.js
new file mode 100644
index 0000000000000..3e518481178b9
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration8_es5.js
@@ -0,0 +1,6 @@
+//// [asyncFunctionDeclaration8_es5.ts]
+var v = { [await]: foo }
+
+//// [asyncFunctionDeclaration8_es5.js]
+var v = (_a = {}, _a[await] = foo, _a);
+var _a;
diff --git a/tests/baselines/reference/asyncFunctionDeclaration9_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration9_es5.errors.txt
new file mode 100644
index 0000000000000..8eed8dade45bc
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration9_es5.errors.txt
@@ -0,0 +1,9 @@
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration9_es5.ts(2,19): error TS1109: Expression expected.
+
+
+==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration9_es5.ts (1 errors) ====
+    async function foo(): Promise<void> {
+      var v = { [await]: foo }
+                      ~
+!!! error TS1109: Expression expected.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncFunctionDeclaration9_es5.js b/tests/baselines/reference/asyncFunctionDeclaration9_es5.js
new file mode 100644
index 0000000000000..2da28f95cff00
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclaration9_es5.js
@@ -0,0 +1,21 @@
+//// [asyncFunctionDeclaration9_es5.ts]
+async function foo(): Promise<void> {
+  var v = { [await]: foo }
+}
+
+//// [asyncFunctionDeclaration9_es5.js]
+function foo() {
+    return __awaiter(this, void 0, Promise, function () {
+        var v, _a;
+        return __generator(function (_b) {
+            switch (_b.label) {
+                case 0:
+                    _a = {};
+                    return [4 /*yield*/, ];
+                case 1:
+                    v = (_a[_b.sent()] = foo, _a);
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts
new file mode 100644
index 0000000000000..f1cb80162bd40
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async function foo(a = await => await): Promise<void> {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration11_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration11_es5.ts
new file mode 100644
index 0000000000000..8edf36f9a2f56
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration11_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async function await(): Promise<void> {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration12_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration12_es5.ts
new file mode 100644
index 0000000000000..4601fba6ea257
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration12_es5.ts
@@ -0,0 +1,4 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+var v = async function await(): Promise<void> { }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration13_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration13_es5.ts
new file mode 100644
index 0000000000000..2b70bc4c6415c
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration13_es5.ts
@@ -0,0 +1,7 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async function foo(): Promise<void> {
+   // Legal to use 'await' in a type context.
+   var v: await;
+}
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration14_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration14_es5.ts
new file mode 100644
index 0000000000000..eedfd438b7c23
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration14_es5.ts
@@ -0,0 +1,6 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async function foo(): Promise<void> {
+  return;
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts
new file mode 100644
index 0000000000000..373677bf58f7a
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts
@@ -0,0 +1,26 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare class Thenable { then(): void; }
+declare let a: any;
+declare let obj: { then: string; };
+declare let thenable: Thenable;
+async function fn1() { } // valid: Promise<void>
+async function fn2(): { } { } // error
+async function fn3(): any { } // error
+async function fn4(): number { } // error
+async function fn5(): PromiseLike<void> { } // error
+async function fn6(): Thenable { } // error
+async function fn7() { return; } // valid: Promise<void>
+async function fn8() { return 1; } // valid: Promise<number>
+async function fn9() { return null; } // valid: Promise<any>
+async function fn10() { return undefined; } // valid: Promise<any>
+async function fn11() { return a; } // valid: Promise<any>
+async function fn12() { return obj; } // valid: Promise<{ then: string; }>
+async function fn13() { return thenable; } // error
+async function fn14() { await 1; } // valid: Promise<void>
+async function fn15() { await null; } // valid: Promise<void>
+async function fn16() { await undefined; } // valid: Promise<void>
+async function fn17() { await a; } // valid: Promise<void>
+async function fn18() { await obj; } // valid: Promise<void>
+async function fn19() { await thenable; } // error
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1_es5.ts
new file mode 100644
index 0000000000000..1448b33599244
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async function foo(): Promise<void> {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration2_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration2_es5.ts
new file mode 100644
index 0000000000000..b1e337938e00b
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration2_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+function f(await) {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration3_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration3_es5.ts
new file mode 100644
index 0000000000000..810d7bc7e0568
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration3_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+function f(await = await) {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration4_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration4_es5.ts
new file mode 100644
index 0000000000000..40bd69d592fe2
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration4_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+function await() {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts
new file mode 100644
index 0000000000000..3c71741da143a
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async function foo(await): Promise<void> {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration6_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration6_es5.ts
new file mode 100644
index 0000000000000..34ff3b3c4c59d
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration6_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async function foo(a = await): Promise<void> {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration7_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration7_es5.ts
new file mode 100644
index 0000000000000..53d7bc5edb532
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration7_es5.ts
@@ -0,0 +1,8 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async function bar(): Promise<void> {
+  // 'await' here is an identifier, and not a yield expression.
+  async function foo(a = await): Promise<void> {
+  }
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration8_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration8_es5.ts
new file mode 100644
index 0000000000000..27db170b08039
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration8_es5.ts
@@ -0,0 +1,4 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+var v = { [await]: foo }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration9_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration9_es5.ts
new file mode 100644
index 0000000000000..7a1130f8abfbe
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration9_es5.ts
@@ -0,0 +1,6 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async function foo(): Promise<void> {
+  var v = { [await]: foo }
+}
\ No newline at end of file

From 0c647c3d1442f41269abbed9bd48c7bfcd698730 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 27 Jun 2016 15:34:15 -0700
Subject: [PATCH 18/23] Added es5 conformance tests for awaiting a call

---
 .../reference/awaitCallExpression1_es5.js     | 27 ++++++++
 .../awaitCallExpression1_es5.symbols          | 59 +++++++++++++++++
 .../reference/awaitCallExpression1_es5.types  | 62 +++++++++++++++++
 .../reference/awaitCallExpression2_es5.js     | 33 ++++++++++
 .../awaitCallExpression2_es5.symbols          | 59 +++++++++++++++++
 .../reference/awaitCallExpression2_es5.types  | 63 ++++++++++++++++++
 .../reference/awaitCallExpression3_es5.js     | 34 ++++++++++
 .../awaitCallExpression3_es5.symbols          | 59 +++++++++++++++++
 .../reference/awaitCallExpression3_es5.types  | 63 ++++++++++++++++++
 .../reference/awaitCallExpression4_es5.js     | 32 +++++++++
 .../awaitCallExpression4_es5.symbols          | 59 +++++++++++++++++
 .../reference/awaitCallExpression4_es5.types  | 64 ++++++++++++++++++
 .../reference/awaitCallExpression5_es5.js     | 27 ++++++++
 .../awaitCallExpression5_es5.symbols          | 61 +++++++++++++++++
 .../reference/awaitCallExpression5_es5.types  | 64 ++++++++++++++++++
 .../reference/awaitCallExpression6_es5.js     | 33 ++++++++++
 .../awaitCallExpression6_es5.symbols          | 61 +++++++++++++++++
 .../reference/awaitCallExpression6_es5.types  | 65 ++++++++++++++++++
 .../reference/awaitCallExpression7_es5.js     | 34 ++++++++++
 .../awaitCallExpression7_es5.symbols          | 61 +++++++++++++++++
 .../reference/awaitCallExpression7_es5.types  | 65 ++++++++++++++++++
 .../reference/awaitCallExpression8_es5.js     | 32 +++++++++
 .../awaitCallExpression8_es5.symbols          | 61 +++++++++++++++++
 .../reference/awaitCallExpression8_es5.types  | 66 +++++++++++++++++++
 .../awaitCallExpression1_es5.ts               | 16 +++++
 .../awaitCallExpression2_es5.ts               | 16 +++++
 .../awaitCallExpression3_es5.ts               | 16 +++++
 .../awaitCallExpression4_es5.ts               | 16 +++++
 .../awaitCallExpression5_es5.ts               | 16 +++++
 .../awaitCallExpression6_es5.ts               | 16 +++++
 .../awaitCallExpression7_es5.ts               | 16 +++++
 .../awaitCallExpression8_es5.ts               | 16 +++++
 32 files changed, 1372 insertions(+)
 create mode 100644 tests/baselines/reference/awaitCallExpression1_es5.js
 create mode 100644 tests/baselines/reference/awaitCallExpression1_es5.symbols
 create mode 100644 tests/baselines/reference/awaitCallExpression1_es5.types
 create mode 100644 tests/baselines/reference/awaitCallExpression2_es5.js
 create mode 100644 tests/baselines/reference/awaitCallExpression2_es5.symbols
 create mode 100644 tests/baselines/reference/awaitCallExpression2_es5.types
 create mode 100644 tests/baselines/reference/awaitCallExpression3_es5.js
 create mode 100644 tests/baselines/reference/awaitCallExpression3_es5.symbols
 create mode 100644 tests/baselines/reference/awaitCallExpression3_es5.types
 create mode 100644 tests/baselines/reference/awaitCallExpression4_es5.js
 create mode 100644 tests/baselines/reference/awaitCallExpression4_es5.symbols
 create mode 100644 tests/baselines/reference/awaitCallExpression4_es5.types
 create mode 100644 tests/baselines/reference/awaitCallExpression5_es5.js
 create mode 100644 tests/baselines/reference/awaitCallExpression5_es5.symbols
 create mode 100644 tests/baselines/reference/awaitCallExpression5_es5.types
 create mode 100644 tests/baselines/reference/awaitCallExpression6_es5.js
 create mode 100644 tests/baselines/reference/awaitCallExpression6_es5.symbols
 create mode 100644 tests/baselines/reference/awaitCallExpression6_es5.types
 create mode 100644 tests/baselines/reference/awaitCallExpression7_es5.js
 create mode 100644 tests/baselines/reference/awaitCallExpression7_es5.symbols
 create mode 100644 tests/baselines/reference/awaitCallExpression7_es5.types
 create mode 100644 tests/baselines/reference/awaitCallExpression8_es5.js
 create mode 100644 tests/baselines/reference/awaitCallExpression8_es5.symbols
 create mode 100644 tests/baselines/reference/awaitCallExpression8_es5.types
 create mode 100644 tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression1_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression2_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression3_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression4_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression5_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression6_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression7_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression8_es5.ts

diff --git a/tests/baselines/reference/awaitCallExpression1_es5.js b/tests/baselines/reference/awaitCallExpression1_es5.js
new file mode 100644
index 0000000000000..d1f1a5ea7b1da
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression1_es5.js
@@ -0,0 +1,27 @@
+//// [awaitCallExpression1_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = fn(a, a, a);
+    after();
+}
+
+//// [awaitCallExpression1_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var b;
+        return __generator(function (_a) {
+            before();
+            b = fn(a, a, a);
+            after();
+            return [2 /*return*/];
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitCallExpression1_es5.symbols b/tests/baselines/reference/awaitCallExpression1_es5.symbols
new file mode 100644
index 0000000000000..b172db760e37d
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression1_es5.symbols
@@ -0,0 +1,59 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression1_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(awaitCallExpression1_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(awaitCallExpression1_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : Symbol(fn, Decl(awaitCallExpression1_es5.ts, 1, 32))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression1_es5.ts, 2, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression1_es5.ts, 2, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression1_es5.ts, 2, 49))
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : Symbol(o, Decl(awaitCallExpression1_es5.ts, 3, 11))
+>fn : Symbol(fn, Decl(awaitCallExpression1_es5.ts, 3, 16))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression1_es5.ts, 3, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression1_es5.ts, 3, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression1_es5.ts, 3, 49))
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Symbol(pfn, Decl(awaitCallExpression1_es5.ts, 4, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression1_es5.ts, 4, 28))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression1_es5.ts, 4, 42))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression1_es5.ts, 4, 57))
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Symbol(po, Decl(awaitCallExpression1_es5.ts, 5, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>fn : Symbol(fn, Decl(awaitCallExpression1_es5.ts, 5, 25))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression1_es5.ts, 5, 29))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression1_es5.ts, 5, 43))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression1_es5.ts, 5, 58))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression1_es5.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression1_es5.ts, 6, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitCallExpression1_es5.ts, 7, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitCallExpression1_es5.ts, 5, 84))
+
+    var b = fn(a, a, a);
+>b : Symbol(b, Decl(awaitCallExpression1_es5.ts, 10, 7))
+>fn : Symbol(fn, Decl(awaitCallExpression1_es5.ts, 1, 32))
+>a : Symbol(a, Decl(awaitCallExpression1_es5.ts, 0, 11))
+>a : Symbol(a, Decl(awaitCallExpression1_es5.ts, 0, 11))
+>a : Symbol(a, Decl(awaitCallExpression1_es5.ts, 0, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitCallExpression1_es5.ts, 6, 32))
+}
diff --git a/tests/baselines/reference/awaitCallExpression1_es5.types b/tests/baselines/reference/awaitCallExpression1_es5.types
new file mode 100644
index 0000000000000..8e712443cabb0
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression1_es5.types
@@ -0,0 +1,62 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression1_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Promise<(arg0: boolean, arg1: boolean, arg2: boolean) => void>
+>Promise : Promise<T>
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>
+>Promise : Promise<T>
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var b = fn(a, a, a);
+>b : void
+>fn(a, a, a) : void
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>a : boolean
+>a : boolean
+>a : boolean
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/baselines/reference/awaitCallExpression2_es5.js b/tests/baselines/reference/awaitCallExpression2_es5.js
new file mode 100644
index 0000000000000..399dead0084ec
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression2_es5.js
@@ -0,0 +1,33 @@
+//// [awaitCallExpression2_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = fn(await p, a, a);
+    after();
+}
+
+//// [awaitCallExpression2_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var b, _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    before();
+                    _a = fn;
+                    return [4 /*yield*/, p];
+                case 1:
+                    b = _a.apply(void 0, [_c.sent(), a, a]);
+                    after();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitCallExpression2_es5.symbols b/tests/baselines/reference/awaitCallExpression2_es5.symbols
new file mode 100644
index 0000000000000..95e1f65003099
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression2_es5.symbols
@@ -0,0 +1,59 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression2_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(awaitCallExpression2_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(awaitCallExpression2_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : Symbol(fn, Decl(awaitCallExpression2_es5.ts, 1, 32))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression2_es5.ts, 2, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression2_es5.ts, 2, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression2_es5.ts, 2, 49))
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : Symbol(o, Decl(awaitCallExpression2_es5.ts, 3, 11))
+>fn : Symbol(fn, Decl(awaitCallExpression2_es5.ts, 3, 16))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression2_es5.ts, 3, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression2_es5.ts, 3, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression2_es5.ts, 3, 49))
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Symbol(pfn, Decl(awaitCallExpression2_es5.ts, 4, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression2_es5.ts, 4, 28))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression2_es5.ts, 4, 42))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression2_es5.ts, 4, 57))
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Symbol(po, Decl(awaitCallExpression2_es5.ts, 5, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>fn : Symbol(fn, Decl(awaitCallExpression2_es5.ts, 5, 25))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression2_es5.ts, 5, 29))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression2_es5.ts, 5, 43))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression2_es5.ts, 5, 58))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression2_es5.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression2_es5.ts, 6, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitCallExpression2_es5.ts, 7, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitCallExpression2_es5.ts, 5, 84))
+
+    var b = fn(await p, a, a);
+>b : Symbol(b, Decl(awaitCallExpression2_es5.ts, 10, 7))
+>fn : Symbol(fn, Decl(awaitCallExpression2_es5.ts, 1, 32))
+>p : Symbol(p, Decl(awaitCallExpression2_es5.ts, 1, 11))
+>a : Symbol(a, Decl(awaitCallExpression2_es5.ts, 0, 11))
+>a : Symbol(a, Decl(awaitCallExpression2_es5.ts, 0, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitCallExpression2_es5.ts, 6, 32))
+}
diff --git a/tests/baselines/reference/awaitCallExpression2_es5.types b/tests/baselines/reference/awaitCallExpression2_es5.types
new file mode 100644
index 0000000000000..5fd85ce39212a
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression2_es5.types
@@ -0,0 +1,63 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression2_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Promise<(arg0: boolean, arg1: boolean, arg2: boolean) => void>
+>Promise : Promise<T>
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>
+>Promise : Promise<T>
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var b = fn(await p, a, a);
+>b : void
+>fn(await p, a, a) : void
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>await p : boolean
+>p : Promise<boolean>
+>a : boolean
+>a : boolean
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/baselines/reference/awaitCallExpression3_es5.js b/tests/baselines/reference/awaitCallExpression3_es5.js
new file mode 100644
index 0000000000000..5b14075a3731b
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression3_es5.js
@@ -0,0 +1,34 @@
+//// [awaitCallExpression3_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = fn(a, await p, a);
+    after();
+}
+
+//// [awaitCallExpression3_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var b, _a, _b;
+        return __generator(function (_c) {
+            switch (_c.label) {
+                case 0:
+                    before();
+                    _a = fn;
+                    _b = [a];
+                    return [4 /*yield*/, p];
+                case 1:
+                    b = _a.apply(void 0, _b.concat([_c.sent(), a]));
+                    after();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitCallExpression3_es5.symbols b/tests/baselines/reference/awaitCallExpression3_es5.symbols
new file mode 100644
index 0000000000000..2c18507340adc
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression3_es5.symbols
@@ -0,0 +1,59 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression3_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(awaitCallExpression3_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(awaitCallExpression3_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : Symbol(fn, Decl(awaitCallExpression3_es5.ts, 1, 32))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression3_es5.ts, 2, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression3_es5.ts, 2, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression3_es5.ts, 2, 49))
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : Symbol(o, Decl(awaitCallExpression3_es5.ts, 3, 11))
+>fn : Symbol(fn, Decl(awaitCallExpression3_es5.ts, 3, 16))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression3_es5.ts, 3, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression3_es5.ts, 3, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression3_es5.ts, 3, 49))
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Symbol(pfn, Decl(awaitCallExpression3_es5.ts, 4, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression3_es5.ts, 4, 28))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression3_es5.ts, 4, 42))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression3_es5.ts, 4, 57))
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Symbol(po, Decl(awaitCallExpression3_es5.ts, 5, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>fn : Symbol(fn, Decl(awaitCallExpression3_es5.ts, 5, 25))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression3_es5.ts, 5, 29))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression3_es5.ts, 5, 43))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression3_es5.ts, 5, 58))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression3_es5.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression3_es5.ts, 6, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitCallExpression3_es5.ts, 7, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitCallExpression3_es5.ts, 5, 84))
+
+    var b = fn(a, await p, a);
+>b : Symbol(b, Decl(awaitCallExpression3_es5.ts, 10, 7))
+>fn : Symbol(fn, Decl(awaitCallExpression3_es5.ts, 1, 32))
+>a : Symbol(a, Decl(awaitCallExpression3_es5.ts, 0, 11))
+>p : Symbol(p, Decl(awaitCallExpression3_es5.ts, 1, 11))
+>a : Symbol(a, Decl(awaitCallExpression3_es5.ts, 0, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitCallExpression3_es5.ts, 6, 32))
+}
diff --git a/tests/baselines/reference/awaitCallExpression3_es5.types b/tests/baselines/reference/awaitCallExpression3_es5.types
new file mode 100644
index 0000000000000..d2d851c1daefc
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression3_es5.types
@@ -0,0 +1,63 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression3_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Promise<(arg0: boolean, arg1: boolean, arg2: boolean) => void>
+>Promise : Promise<T>
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>
+>Promise : Promise<T>
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var b = fn(a, await p, a);
+>b : void
+>fn(a, await p, a) : void
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>a : boolean
+>await p : boolean
+>p : Promise<boolean>
+>a : boolean
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/baselines/reference/awaitCallExpression4_es5.js b/tests/baselines/reference/awaitCallExpression4_es5.js
new file mode 100644
index 0000000000000..8202598b82831
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression4_es5.js
@@ -0,0 +1,32 @@
+//// [awaitCallExpression4_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = (await pfn)(a, a, a);
+    after();
+}
+
+//// [awaitCallExpression4_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var b;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    before();
+                    return [4 /*yield*/, pfn];
+                case 1:
+                    b = (_a.sent())(a, a, a);
+                    after();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitCallExpression4_es5.symbols b/tests/baselines/reference/awaitCallExpression4_es5.symbols
new file mode 100644
index 0000000000000..46a5b942956a8
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression4_es5.symbols
@@ -0,0 +1,59 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression4_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(awaitCallExpression4_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(awaitCallExpression4_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : Symbol(fn, Decl(awaitCallExpression4_es5.ts, 1, 32))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression4_es5.ts, 2, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression4_es5.ts, 2, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression4_es5.ts, 2, 49))
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : Symbol(o, Decl(awaitCallExpression4_es5.ts, 3, 11))
+>fn : Symbol(fn, Decl(awaitCallExpression4_es5.ts, 3, 16))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression4_es5.ts, 3, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression4_es5.ts, 3, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression4_es5.ts, 3, 49))
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Symbol(pfn, Decl(awaitCallExpression4_es5.ts, 4, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression4_es5.ts, 4, 28))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression4_es5.ts, 4, 42))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression4_es5.ts, 4, 57))
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Symbol(po, Decl(awaitCallExpression4_es5.ts, 5, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>fn : Symbol(fn, Decl(awaitCallExpression4_es5.ts, 5, 25))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression4_es5.ts, 5, 29))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression4_es5.ts, 5, 43))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression4_es5.ts, 5, 58))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression4_es5.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression4_es5.ts, 6, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitCallExpression4_es5.ts, 7, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitCallExpression4_es5.ts, 5, 84))
+
+    var b = (await pfn)(a, a, a);
+>b : Symbol(b, Decl(awaitCallExpression4_es5.ts, 10, 7))
+>pfn : Symbol(pfn, Decl(awaitCallExpression4_es5.ts, 4, 11))
+>a : Symbol(a, Decl(awaitCallExpression4_es5.ts, 0, 11))
+>a : Symbol(a, Decl(awaitCallExpression4_es5.ts, 0, 11))
+>a : Symbol(a, Decl(awaitCallExpression4_es5.ts, 0, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitCallExpression4_es5.ts, 6, 32))
+}
diff --git a/tests/baselines/reference/awaitCallExpression4_es5.types b/tests/baselines/reference/awaitCallExpression4_es5.types
new file mode 100644
index 0000000000000..0b510c4699850
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression4_es5.types
@@ -0,0 +1,64 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression4_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Promise<(arg0: boolean, arg1: boolean, arg2: boolean) => void>
+>Promise : Promise<T>
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>
+>Promise : Promise<T>
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var b = (await pfn)(a, a, a);
+>b : void
+>(await pfn)(a, a, a) : void
+>(await pfn) : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>await pfn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>pfn : Promise<(arg0: boolean, arg1: boolean, arg2: boolean) => void>
+>a : boolean
+>a : boolean
+>a : boolean
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/baselines/reference/awaitCallExpression5_es5.js b/tests/baselines/reference/awaitCallExpression5_es5.js
new file mode 100644
index 0000000000000..387dabc1df3e3
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression5_es5.js
@@ -0,0 +1,27 @@
+//// [awaitCallExpression5_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = o.fn(a, a, a);
+    after();
+}
+
+//// [awaitCallExpression5_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var b;
+        return __generator(function (_a) {
+            before();
+            b = o.fn(a, a, a);
+            after();
+            return [2 /*return*/];
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitCallExpression5_es5.symbols b/tests/baselines/reference/awaitCallExpression5_es5.symbols
new file mode 100644
index 0000000000000..9f34c3e9fe81d
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression5_es5.symbols
@@ -0,0 +1,61 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression5_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(awaitCallExpression5_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(awaitCallExpression5_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : Symbol(fn, Decl(awaitCallExpression5_es5.ts, 1, 32))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression5_es5.ts, 2, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression5_es5.ts, 2, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression5_es5.ts, 2, 49))
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : Symbol(o, Decl(awaitCallExpression5_es5.ts, 3, 11))
+>fn : Symbol(fn, Decl(awaitCallExpression5_es5.ts, 3, 16))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression5_es5.ts, 3, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression5_es5.ts, 3, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression5_es5.ts, 3, 49))
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Symbol(pfn, Decl(awaitCallExpression5_es5.ts, 4, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression5_es5.ts, 4, 28))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression5_es5.ts, 4, 42))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression5_es5.ts, 4, 57))
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Symbol(po, Decl(awaitCallExpression5_es5.ts, 5, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>fn : Symbol(fn, Decl(awaitCallExpression5_es5.ts, 5, 25))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression5_es5.ts, 5, 29))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression5_es5.ts, 5, 43))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression5_es5.ts, 5, 58))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression5_es5.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression5_es5.ts, 6, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitCallExpression5_es5.ts, 7, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitCallExpression5_es5.ts, 5, 84))
+
+    var b = o.fn(a, a, a);
+>b : Symbol(b, Decl(awaitCallExpression5_es5.ts, 10, 7))
+>o.fn : Symbol(fn, Decl(awaitCallExpression5_es5.ts, 3, 16))
+>o : Symbol(o, Decl(awaitCallExpression5_es5.ts, 3, 11))
+>fn : Symbol(fn, Decl(awaitCallExpression5_es5.ts, 3, 16))
+>a : Symbol(a, Decl(awaitCallExpression5_es5.ts, 0, 11))
+>a : Symbol(a, Decl(awaitCallExpression5_es5.ts, 0, 11))
+>a : Symbol(a, Decl(awaitCallExpression5_es5.ts, 0, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitCallExpression5_es5.ts, 6, 32))
+}
diff --git a/tests/baselines/reference/awaitCallExpression5_es5.types b/tests/baselines/reference/awaitCallExpression5_es5.types
new file mode 100644
index 0000000000000..b4b6d947275cf
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression5_es5.types
@@ -0,0 +1,64 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression5_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Promise<(arg0: boolean, arg1: boolean, arg2: boolean) => void>
+>Promise : Promise<T>
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>
+>Promise : Promise<T>
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var b = o.fn(a, a, a);
+>b : void
+>o.fn(a, a, a) : void
+>o.fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>o : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>a : boolean
+>a : boolean
+>a : boolean
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/baselines/reference/awaitCallExpression6_es5.js b/tests/baselines/reference/awaitCallExpression6_es5.js
new file mode 100644
index 0000000000000..3c2910135e794
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression6_es5.js
@@ -0,0 +1,33 @@
+//// [awaitCallExpression6_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = o.fn(await p, a, a);
+    after();
+}
+
+//// [awaitCallExpression6_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var b, _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    before();
+                    _b = (_a = o).fn;
+                    return [4 /*yield*/, p];
+                case 1:
+                    b = _b.apply(_a, [_d.sent(), a, a]);
+                    after();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitCallExpression6_es5.symbols b/tests/baselines/reference/awaitCallExpression6_es5.symbols
new file mode 100644
index 0000000000000..fc3ae4cbdbb5c
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression6_es5.symbols
@@ -0,0 +1,61 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression6_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(awaitCallExpression6_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(awaitCallExpression6_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : Symbol(fn, Decl(awaitCallExpression6_es5.ts, 1, 32))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression6_es5.ts, 2, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression6_es5.ts, 2, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression6_es5.ts, 2, 49))
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : Symbol(o, Decl(awaitCallExpression6_es5.ts, 3, 11))
+>fn : Symbol(fn, Decl(awaitCallExpression6_es5.ts, 3, 16))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression6_es5.ts, 3, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression6_es5.ts, 3, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression6_es5.ts, 3, 49))
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Symbol(pfn, Decl(awaitCallExpression6_es5.ts, 4, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression6_es5.ts, 4, 28))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression6_es5.ts, 4, 42))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression6_es5.ts, 4, 57))
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Symbol(po, Decl(awaitCallExpression6_es5.ts, 5, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>fn : Symbol(fn, Decl(awaitCallExpression6_es5.ts, 5, 25))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression6_es5.ts, 5, 29))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression6_es5.ts, 5, 43))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression6_es5.ts, 5, 58))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression6_es5.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression6_es5.ts, 6, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitCallExpression6_es5.ts, 7, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitCallExpression6_es5.ts, 5, 84))
+
+    var b = o.fn(await p, a, a);
+>b : Symbol(b, Decl(awaitCallExpression6_es5.ts, 10, 7))
+>o.fn : Symbol(fn, Decl(awaitCallExpression6_es5.ts, 3, 16))
+>o : Symbol(o, Decl(awaitCallExpression6_es5.ts, 3, 11))
+>fn : Symbol(fn, Decl(awaitCallExpression6_es5.ts, 3, 16))
+>p : Symbol(p, Decl(awaitCallExpression6_es5.ts, 1, 11))
+>a : Symbol(a, Decl(awaitCallExpression6_es5.ts, 0, 11))
+>a : Symbol(a, Decl(awaitCallExpression6_es5.ts, 0, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitCallExpression6_es5.ts, 6, 32))
+}
diff --git a/tests/baselines/reference/awaitCallExpression6_es5.types b/tests/baselines/reference/awaitCallExpression6_es5.types
new file mode 100644
index 0000000000000..e34839f3c1584
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression6_es5.types
@@ -0,0 +1,65 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression6_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Promise<(arg0: boolean, arg1: boolean, arg2: boolean) => void>
+>Promise : Promise<T>
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>
+>Promise : Promise<T>
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var b = o.fn(await p, a, a);
+>b : void
+>o.fn(await p, a, a) : void
+>o.fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>o : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>await p : boolean
+>p : Promise<boolean>
+>a : boolean
+>a : boolean
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/baselines/reference/awaitCallExpression7_es5.js b/tests/baselines/reference/awaitCallExpression7_es5.js
new file mode 100644
index 0000000000000..0f3056e48fa7e
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression7_es5.js
@@ -0,0 +1,34 @@
+//// [awaitCallExpression7_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = o.fn(a, await p, a);
+    after();
+}
+
+//// [awaitCallExpression7_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var b, _a, _b, _c;
+        return __generator(function (_d) {
+            switch (_d.label) {
+                case 0:
+                    before();
+                    _b = (_a = o).fn;
+                    _c = [a];
+                    return [4 /*yield*/, p];
+                case 1:
+                    b = _b.apply(_a, _c.concat([_d.sent(), a]));
+                    after();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitCallExpression7_es5.symbols b/tests/baselines/reference/awaitCallExpression7_es5.symbols
new file mode 100644
index 0000000000000..96a7252ef04d0
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression7_es5.symbols
@@ -0,0 +1,61 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression7_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(awaitCallExpression7_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(awaitCallExpression7_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : Symbol(fn, Decl(awaitCallExpression7_es5.ts, 1, 32))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression7_es5.ts, 2, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression7_es5.ts, 2, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression7_es5.ts, 2, 49))
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : Symbol(o, Decl(awaitCallExpression7_es5.ts, 3, 11))
+>fn : Symbol(fn, Decl(awaitCallExpression7_es5.ts, 3, 16))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression7_es5.ts, 3, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression7_es5.ts, 3, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression7_es5.ts, 3, 49))
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Symbol(pfn, Decl(awaitCallExpression7_es5.ts, 4, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression7_es5.ts, 4, 28))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression7_es5.ts, 4, 42))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression7_es5.ts, 4, 57))
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Symbol(po, Decl(awaitCallExpression7_es5.ts, 5, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>fn : Symbol(fn, Decl(awaitCallExpression7_es5.ts, 5, 25))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression7_es5.ts, 5, 29))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression7_es5.ts, 5, 43))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression7_es5.ts, 5, 58))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression7_es5.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression7_es5.ts, 6, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitCallExpression7_es5.ts, 7, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitCallExpression7_es5.ts, 5, 84))
+
+    var b = o.fn(a, await p, a);
+>b : Symbol(b, Decl(awaitCallExpression7_es5.ts, 10, 7))
+>o.fn : Symbol(fn, Decl(awaitCallExpression7_es5.ts, 3, 16))
+>o : Symbol(o, Decl(awaitCallExpression7_es5.ts, 3, 11))
+>fn : Symbol(fn, Decl(awaitCallExpression7_es5.ts, 3, 16))
+>a : Symbol(a, Decl(awaitCallExpression7_es5.ts, 0, 11))
+>p : Symbol(p, Decl(awaitCallExpression7_es5.ts, 1, 11))
+>a : Symbol(a, Decl(awaitCallExpression7_es5.ts, 0, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitCallExpression7_es5.ts, 6, 32))
+}
diff --git a/tests/baselines/reference/awaitCallExpression7_es5.types b/tests/baselines/reference/awaitCallExpression7_es5.types
new file mode 100644
index 0000000000000..9d220c6c8b8b2
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression7_es5.types
@@ -0,0 +1,65 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression7_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Promise<(arg0: boolean, arg1: boolean, arg2: boolean) => void>
+>Promise : Promise<T>
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>
+>Promise : Promise<T>
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var b = o.fn(a, await p, a);
+>b : void
+>o.fn(a, await p, a) : void
+>o.fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>o : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>a : boolean
+>await p : boolean
+>p : Promise<boolean>
+>a : boolean
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/baselines/reference/awaitCallExpression8_es5.js b/tests/baselines/reference/awaitCallExpression8_es5.js
new file mode 100644
index 0000000000000..bcb7a7f8d7b87
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression8_es5.js
@@ -0,0 +1,32 @@
+//// [awaitCallExpression8_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = (await po).fn(a, a, a);
+    after();
+}
+
+//// [awaitCallExpression8_es5.js]
+function func() {
+    return __awaiter(this, void 0, Promise, function () {
+        var b;
+        return __generator(function (_a) {
+            switch (_a.label) {
+                case 0:
+                    before();
+                    return [4 /*yield*/, po];
+                case 1:
+                    b = (_a.sent()).fn(a, a, a);
+                    after();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitCallExpression8_es5.symbols b/tests/baselines/reference/awaitCallExpression8_es5.symbols
new file mode 100644
index 0000000000000..50b564481b960
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression8_es5.symbols
@@ -0,0 +1,61 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression8_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(awaitCallExpression8_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(awaitCallExpression8_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : Symbol(fn, Decl(awaitCallExpression8_es5.ts, 1, 32))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression8_es5.ts, 2, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression8_es5.ts, 2, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression8_es5.ts, 2, 49))
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : Symbol(o, Decl(awaitCallExpression8_es5.ts, 3, 11))
+>fn : Symbol(fn, Decl(awaitCallExpression8_es5.ts, 3, 16))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression8_es5.ts, 3, 20))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression8_es5.ts, 3, 34))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression8_es5.ts, 3, 49))
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Symbol(pfn, Decl(awaitCallExpression8_es5.ts, 4, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression8_es5.ts, 4, 28))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression8_es5.ts, 4, 42))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression8_es5.ts, 4, 57))
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Symbol(po, Decl(awaitCallExpression8_es5.ts, 5, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>fn : Symbol(fn, Decl(awaitCallExpression8_es5.ts, 5, 25))
+>arg0 : Symbol(arg0, Decl(awaitCallExpression8_es5.ts, 5, 29))
+>arg1 : Symbol(arg1, Decl(awaitCallExpression8_es5.ts, 5, 43))
+>arg2 : Symbol(arg2, Decl(awaitCallExpression8_es5.ts, 5, 58))
+
+declare function before(): void;
+>before : Symbol(before, Decl(awaitCallExpression8_es5.ts, 5, 84))
+
+declare function after(): void;
+>after : Symbol(after, Decl(awaitCallExpression8_es5.ts, 6, 32))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitCallExpression8_es5.ts, 7, 31))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    before();
+>before : Symbol(before, Decl(awaitCallExpression8_es5.ts, 5, 84))
+
+    var b = (await po).fn(a, a, a);
+>b : Symbol(b, Decl(awaitCallExpression8_es5.ts, 10, 7))
+>(await po).fn : Symbol(fn, Decl(awaitCallExpression8_es5.ts, 5, 25))
+>po : Symbol(po, Decl(awaitCallExpression8_es5.ts, 5, 11))
+>fn : Symbol(fn, Decl(awaitCallExpression8_es5.ts, 5, 25))
+>a : Symbol(a, Decl(awaitCallExpression8_es5.ts, 0, 11))
+>a : Symbol(a, Decl(awaitCallExpression8_es5.ts, 0, 11))
+>a : Symbol(a, Decl(awaitCallExpression8_es5.ts, 0, 11))
+
+    after();
+>after : Symbol(after, Decl(awaitCallExpression8_es5.ts, 6, 32))
+}
diff --git a/tests/baselines/reference/awaitCallExpression8_es5.types b/tests/baselines/reference/awaitCallExpression8_es5.types
new file mode 100644
index 0000000000000..1b2fa16d1fc3b
--- /dev/null
+++ b/tests/baselines/reference/awaitCallExpression8_es5.types
@@ -0,0 +1,66 @@
+=== tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression8_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+>o : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>pfn : Promise<(arg0: boolean, arg1: boolean, arg2: boolean) => void>
+>Promise : Promise<T>
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+>po : Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>
+>Promise : Promise<T>
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>arg0 : boolean
+>arg1 : boolean
+>arg2 : boolean
+
+declare function before(): void;
+>before : () => void
+
+declare function after(): void;
+>after : () => void
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    before();
+>before() : void
+>before : () => void
+
+    var b = (await po).fn(a, a, a);
+>b : void
+>(await po).fn(a, a, a) : void
+>(await po).fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>(await po) : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>await po : { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }
+>po : Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>
+>fn : (arg0: boolean, arg1: boolean, arg2: boolean) => void
+>a : boolean
+>a : boolean
+>a : boolean
+
+    after();
+>after() : void
+>after : () => void
+}
diff --git a/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression1_es5.ts b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression1_es5.ts
new file mode 100644
index 0000000000000..8f133327c021f
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression1_es5.ts
@@ -0,0 +1,16 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = fn(a, a, a);
+    after();
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression2_es5.ts b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression2_es5.ts
new file mode 100644
index 0000000000000..b6949b97fcf4c
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression2_es5.ts
@@ -0,0 +1,16 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = fn(await p, a, a);
+    after();
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression3_es5.ts b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression3_es5.ts
new file mode 100644
index 0000000000000..10eef215cccab
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression3_es5.ts
@@ -0,0 +1,16 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = fn(a, await p, a);
+    after();
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression4_es5.ts b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression4_es5.ts
new file mode 100644
index 0000000000000..9e2159e57304c
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression4_es5.ts
@@ -0,0 +1,16 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = (await pfn)(a, a, a);
+    after();
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression5_es5.ts b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression5_es5.ts
new file mode 100644
index 0000000000000..19415c30de544
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression5_es5.ts
@@ -0,0 +1,16 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = o.fn(a, a, a);
+    after();
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression6_es5.ts b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression6_es5.ts
new file mode 100644
index 0000000000000..23804c47a3243
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression6_es5.ts
@@ -0,0 +1,16 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = o.fn(await p, a, a);
+    after();
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression7_es5.ts b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression7_es5.ts
new file mode 100644
index 0000000000000..5227f480c8e80
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression7_es5.ts
@@ -0,0 +1,16 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = o.fn(a, await p, a);
+    after();
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression8_es5.ts b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression8_es5.ts
new file mode 100644
index 0000000000000..ab47d34aac063
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitCallExpression/awaitCallExpression8_es5.ts
@@ -0,0 +1,16 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+declare function fn(arg0: boolean, arg1: boolean, arg2: boolean): void;
+declare var o: { fn(arg0: boolean, arg1: boolean, arg2: boolean): void; };
+declare var pfn: Promise<{ (arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare var po: Promise<{ fn(arg0: boolean, arg1: boolean, arg2: boolean): void; }>;
+declare function before(): void;
+declare function after(): void;
+async function func(): Promise<void> {
+    before();
+    var b = (await po).fn(a, a, a);
+    after();
+}
\ No newline at end of file

From 203dab44122fea4bb2efb558a41ec098e4368bed Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 27 Jun 2016 17:12:24 -0700
Subject: [PATCH 19/23] Added additional es5 conformance tests, better emit for
 functions returning global promise, pass this to __generator

---
 src/compiler/checker.ts                       |  23 +-
 src/compiler/emitter.ts                       |   4 +-
 src/compiler/transformers/generators.ts       |  33 +--
 src/compiler/transformers/ts.ts               |  20 +-
 src/compiler/types.ts                         |   3 +-
 .../reference/asyncAliasReturnType_es5.js     |  14 ++
 .../asyncAliasReturnType_es5.symbols          |  11 +
 .../reference/asyncAliasReturnType_es5.types  |  11 +
 .../asyncAwaitIsolatedModules_es5.errors.txt  |  45 ++++
 .../asyncAwaitIsolatedModules_es5.js          | 201 ++++++++++++++++++
 tests/baselines/reference/asyncAwait_es5.js   | 200 +++++++++++++++++
 .../reference/asyncAwait_es5.symbols          | 118 ++++++++++
 .../baselines/reference/asyncAwait_es5.types  | 129 +++++++++++
 .../reference/asyncClass_es5.errors.txt       |   8 +
 tests/baselines/reference/asyncClass_es5.js   |  10 +
 .../reference/asyncConstructor_es5.errors.txt |  10 +
 .../reference/asyncConstructor_es5.js         |  12 ++
 .../reference/asyncDeclare_es5.errors.txt     |   7 +
 tests/baselines/reference/asyncDeclare_es5.js |   4 +
 .../reference/asyncEnum_es5.errors.txt        |   9 +
 tests/baselines/reference/asyncEnum_es5.js    |  10 +
 .../asyncFunctionDeclaration11_es5.js         |   4 +-
 .../asyncFunctionDeclaration13_es5.js         |   4 +-
 .../asyncFunctionDeclaration14_es5.js         |   4 +-
 .../asyncFunctionDeclaration15_es5.errors.txt |  24 +--
 .../asyncFunctionDeclaration15_es5.js         |  38 ++--
 .../asyncFunctionDeclaration1_es5.js          |   4 +-
 .../asyncFunctionDeclaration6_es5.js          |   4 +-
 .../asyncFunctionDeclaration7_es5.js          |   8 +-
 .../asyncFunctionDeclaration9_es5.js          |   4 +-
 .../reference/asyncGetter_es5.errors.txt      |  13 ++
 tests/baselines/reference/asyncGetter_es5.js  |  18 ++
 .../reference/asyncImportedPromise_es5.js     |  84 ++++++++
 .../asyncImportedPromise_es5.symbols          |  20 ++
 .../reference/asyncImportedPromise_es5.types  |  20 ++
 .../reference/asyncInterface_es5.errors.txt   |   8 +
 .../baselines/reference/asyncInterface_es5.js |   5 +
 .../reference/asyncMethodWithSuper_es5.js     | 106 +++++++++
 .../asyncMethodWithSuper_es5.symbols          | 102 +++++++++
 .../reference/asyncMethodWithSuper_es5.types  | 123 +++++++++++
 .../reference/asyncModule_es5.errors.txt      |   8 +
 tests/baselines/reference/asyncModule_es5.js  |   5 +
 .../baselines/reference/asyncMultiFile_es5.js |  60 ++++++
 .../reference/asyncMultiFile_es5.symbols      |   8 +
 .../reference/asyncMultiFile_es5.types        |   8 +
 .../reference/asyncQualifiedReturnType_es5.js |  28 +++
 .../asyncQualifiedReturnType_es5.symbols      |  17 ++
 .../asyncQualifiedReturnType_es5.types        |  17 ++
 .../reference/asyncSetter_es5.errors.txt      |  10 +
 tests/baselines/reference/asyncSetter_es5.js  |  18 ++
 .../baselines/reference/asyncUseStrict_es5.js |  23 ++
 .../reference/asyncUseStrict_es5.symbols      |  18 ++
 .../reference/asyncUseStrict_es5.types        |  22 ++
 .../reference/awaitBinaryExpression1_es5.js   |   4 +-
 .../reference/awaitBinaryExpression2_es5.js   |   4 +-
 .../reference/awaitBinaryExpression3_es5.js   |   4 +-
 .../reference/awaitBinaryExpression4_es5.js   |   4 +-
 .../reference/awaitBinaryExpression5_es5.js   |   4 +-
 .../reference/awaitCallExpression1_es5.js     |   4 +-
 .../reference/awaitCallExpression2_es5.js     |   4 +-
 .../reference/awaitCallExpression3_es5.js     |   4 +-
 .../reference/awaitCallExpression4_es5.js     |   4 +-
 .../reference/awaitCallExpression5_es5.js     |   4 +-
 .../reference/awaitCallExpression6_es5.js     |   4 +-
 .../reference/awaitCallExpression7_es5.js     |   4 +-
 .../reference/awaitCallExpression8_es5.js     |   4 +-
 .../reference/awaitClassExpression_es5.js     |  31 +++
 .../awaitClassExpression_es5.symbols          |  18 ++
 .../reference/awaitClassExpression_es5.types  |  20 ++
 tests/baselines/reference/awaitUnion_es5.js   |  40 ++++
 .../reference/awaitUnion_es5.symbols          |  44 ++++
 .../baselines/reference/awaitUnion_es5.types  |  49 +++++
 .../baselines/reference/es5-asyncFunction.js  |   8 +-
 .../es5-asyncFunctionArrayLiterals.js         |  16 +-
 .../es5-asyncFunctionBinaryExpressions.js     |  62 +++---
 .../es5-asyncFunctionCallExpressions.js       |  42 ++--
 .../es5-asyncFunctionConditionals.js          |   6 +-
 .../es5-asyncFunctionDoStatements.js          |  38 ++--
 .../es5-asyncFunctionElementAccess.js         |   6 +-
 .../es5-asyncFunctionForInStatements.js       |  18 +-
 .../es5-asyncFunctionForOfStatements.js       |  38 ++--
 .../es5-asyncFunctionForStatements.js         |  14 +-
 .../reference/es5-asyncFunctionHoisting.js    |   4 +-
 .../es5-asyncFunctionIfStatements.js          |   6 +-
 .../reference/es5-asyncFunctionNestedLoops.js |   2 +-
 .../es5-asyncFunctionNewExpressions.js        |  42 ++--
 .../es5-asyncFunctionObjectLiterals.js        |  14 +-
 .../es5-asyncFunctionPropertyAccess.js        |   6 +-
 .../es5-asyncFunctionReturnStatements.js      |  24 +--
 .../es5-asyncFunctionSwitchStatements.js      |  18 +-
 .../es5-asyncFunctionTryStatements.js         |  24 +--
 .../es5-asyncFunctionWhileStatements.js       |  38 ++--
 .../es5-asyncFunctionWithStatements.js        |   8 +-
 .../es5-importHelpersAsyncFunctions.js        |   8 +-
 .../async/es5/asyncAliasReturnType_es5.ts     |   7 +
 .../es5/asyncAwaitIsolatedModules_es5.ts      |  42 ++++
 .../conformance/async/es5/asyncAwait_es5.ts   |  41 ++++
 .../conformance/async/es5/asyncClass_es5.ts   |   5 +
 .../async/es5/asyncConstructor_es5.ts         |   7 +
 .../conformance/async/es5/asyncDeclare_es5.ts |   4 +
 .../conformance/async/es5/asyncEnum_es5.ts    |   6 +
 .../conformance/async/es5/asyncGetter_es5.ts  |   7 +
 .../async/es5/asyncImportedPromise_es5.ts     |  11 +
 .../async/es5/asyncInterface_es5.ts           |   5 +
 .../async/es5/asyncMethodWithSuper_es5.ts     |  53 +++++
 .../conformance/async/es5/asyncModule_es5.ts  |   5 +
 .../async/es5/asyncMultiFile_es5.ts           |   6 +
 .../async/es5/asyncQualifiedReturnType_es5.ts |  10 +
 .../conformance/async/es5/asyncSetter_es5.ts  |   7 +
 .../async/es5/asyncUseStrict_es5.ts           |   9 +
 .../async/es5/awaitClassExpression_es5.ts     |  10 +
 .../conformance/async/es5/awaitUnion_es5.ts   |  15 ++
 112 files changed, 2341 insertions(+), 322 deletions(-)
 create mode 100644 tests/baselines/reference/asyncAliasReturnType_es5.js
 create mode 100644 tests/baselines/reference/asyncAliasReturnType_es5.symbols
 create mode 100644 tests/baselines/reference/asyncAliasReturnType_es5.types
 create mode 100644 tests/baselines/reference/asyncAwaitIsolatedModules_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncAwaitIsolatedModules_es5.js
 create mode 100644 tests/baselines/reference/asyncAwait_es5.js
 create mode 100644 tests/baselines/reference/asyncAwait_es5.symbols
 create mode 100644 tests/baselines/reference/asyncAwait_es5.types
 create mode 100644 tests/baselines/reference/asyncClass_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncClass_es5.js
 create mode 100644 tests/baselines/reference/asyncConstructor_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncConstructor_es5.js
 create mode 100644 tests/baselines/reference/asyncDeclare_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncDeclare_es5.js
 create mode 100644 tests/baselines/reference/asyncEnum_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncEnum_es5.js
 create mode 100644 tests/baselines/reference/asyncGetter_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncGetter_es5.js
 create mode 100644 tests/baselines/reference/asyncImportedPromise_es5.js
 create mode 100644 tests/baselines/reference/asyncImportedPromise_es5.symbols
 create mode 100644 tests/baselines/reference/asyncImportedPromise_es5.types
 create mode 100644 tests/baselines/reference/asyncInterface_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncInterface_es5.js
 create mode 100644 tests/baselines/reference/asyncMethodWithSuper_es5.js
 create mode 100644 tests/baselines/reference/asyncMethodWithSuper_es5.symbols
 create mode 100644 tests/baselines/reference/asyncMethodWithSuper_es5.types
 create mode 100644 tests/baselines/reference/asyncModule_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncModule_es5.js
 create mode 100644 tests/baselines/reference/asyncMultiFile_es5.js
 create mode 100644 tests/baselines/reference/asyncMultiFile_es5.symbols
 create mode 100644 tests/baselines/reference/asyncMultiFile_es5.types
 create mode 100644 tests/baselines/reference/asyncQualifiedReturnType_es5.js
 create mode 100644 tests/baselines/reference/asyncQualifiedReturnType_es5.symbols
 create mode 100644 tests/baselines/reference/asyncQualifiedReturnType_es5.types
 create mode 100644 tests/baselines/reference/asyncSetter_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncSetter_es5.js
 create mode 100644 tests/baselines/reference/asyncUseStrict_es5.js
 create mode 100644 tests/baselines/reference/asyncUseStrict_es5.symbols
 create mode 100644 tests/baselines/reference/asyncUseStrict_es5.types
 create mode 100644 tests/baselines/reference/awaitClassExpression_es5.js
 create mode 100644 tests/baselines/reference/awaitClassExpression_es5.symbols
 create mode 100644 tests/baselines/reference/awaitClassExpression_es5.types
 create mode 100644 tests/baselines/reference/awaitUnion_es5.js
 create mode 100644 tests/baselines/reference/awaitUnion_es5.symbols
 create mode 100644 tests/baselines/reference/awaitUnion_es5.types
 create mode 100644 tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncAwaitIsolatedModules_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncAwait_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncClass_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncConstructor_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncDeclare_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncEnum_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncGetter_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncImportedPromise_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncInterface_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncMethodWithSuper_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncModule_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncMultiFile_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncQualifiedReturnType_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncSetter_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncUseStrict_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitClassExpression_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/awaitUnion_es5.ts

diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 19ddbcdac04cf..56ec54781e782 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -148,6 +148,7 @@ namespace ts {
         let getGlobalESSymbolConstructorSymbol: () => Symbol;
 
         let getGlobalPromiseConstructorSymbol: () => Symbol;
+        let tryGetGlobalPromiseConstructorSymbol: () => Symbol;
 
         let globalObjectType: ObjectType;
         let globalFunctionType: ObjectType;
@@ -13922,7 +13923,7 @@ namespace ts {
          * @param returnType The return type of a FunctionLikeDeclaration
          * @param location The node on which to report the error.
          */
-        function checkCorrectPromiseType(returnType: Type, location: Node) {
+        function checkCorrectPromiseType(returnType: Type, location: Node, diagnostic: DiagnosticMessage, typeName?: string) {
             if (returnType === unknownType) {
                 // The return type already had some other error, so we ignore and return
                 // the unknown type.
@@ -13941,7 +13942,7 @@ namespace ts {
 
             // The promise type was not a valid type reference to the global promise type, so we
             // report an error and return the unknown type.
-            error(location, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
+            error(location, diagnostic, typeName);
             return unknownType;
         }
 
@@ -13961,7 +13962,7 @@ namespace ts {
         function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type {
             if (languageVersion >= ScriptTarget.ES6) {
                 const returnType = getTypeFromTypeNode(node.type);
-                return checkCorrectPromiseType(returnType, node.type);
+                return checkCorrectPromiseType(returnType, node.type, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
             }
 
             const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
@@ -14007,11 +14008,11 @@ namespace ts {
 
             const promiseConstructor = getNodeLinks(node.type).resolvedSymbol;
             if (!promiseConstructor || !symbolIsValue(promiseConstructor)) {
+                // try to fall back to global promise type.
                 const typeName = promiseConstructor
                     ? symbolToString(promiseConstructor)
                     : typeToString(promiseType);
-                error(node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName);
-                return unknownType;
+                return checkCorrectPromiseType(promiseType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName);
             }
 
             // If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced.
@@ -14019,7 +14020,7 @@ namespace ts {
 
             // Validate the promise constructor type.
             const promiseConstructorType = getTypeOfSymbol(promiseConstructor);
-            if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
+            if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
                 return unknownType;
             }
 
@@ -17520,6 +17521,11 @@ namespace ts {
         function getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind {
             // Resolve the symbol as a value to ensure the type can be reached at runtime during emit.
             const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location);
+            const globalPromiseSymbol = tryGetGlobalPromiseConstructorSymbol();
+            if (globalPromiseSymbol && valueSymbol === globalPromiseSymbol) {
+                return TypeReferenceSerializationKind.Promise;
+            }
+
             const constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined;
             if (constructorType && isConstructorType(constructorType)) {
                 return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue;
@@ -17538,8 +17544,8 @@ namespace ts {
             else if (type.flags & TypeFlags.Any) {
                 return TypeReferenceSerializationKind.ObjectType;
             }
-            else if (isTypeOfKind(type, TypeFlags.Void)) {
-                return TypeReferenceSerializationKind.VoidType;
+            else if (isTypeOfKind(type, TypeFlags.Void | TypeFlags.Nullable | TypeFlags.Never)) {
+                return TypeReferenceSerializationKind.VoidNullableOrNeverType;
             }
             else if (isTypeOfKind(type, TypeFlags.Boolean)) {
                 return TypeReferenceSerializationKind.BooleanType;
@@ -17837,6 +17843,7 @@ namespace ts {
             getGlobalPromiseLikeType = memoize(() => getGlobalType("PromiseLike", /*arity*/ 1));
             getInstantiatedGlobalPromiseLikeType = memoize(createInstantiatedPromiseLikeType);
             getGlobalPromiseConstructorSymbol = memoize(() => getGlobalValueSymbol("Promise"));
+            tryGetGlobalPromiseConstructorSymbol = memoize(() => getGlobalSymbol("Promise", SymbolFlags.Value, /*diagnostic*/ undefined) && getGlobalPromiseConstructorSymbol());
             getGlobalPromiseConstructorLikeType = memoize(() => getGlobalType("PromiseConstructorLike"));
             getGlobalThenableType = memoize(createThenableType);
 
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index 09c785a24e36b..ab01fd3dbfcfd 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -72,7 +72,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
 };`;
 
         const generatorHelper = `
-var __generator = (this && this.__generator) || function (body) {
+var __generator = (this && this.__generator) || function (thisArg, body) {
     var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
     function step(op) {
         if (f) throw new TypeError("Generator is already executing.");
@@ -97,7 +97,7 @@ var __generator = (this && this.__generator) || function (body) {
                         _.trys.pop();
                         continue;
                 }
-                op = body(_);
+                op = body.call(thisArg, _);
             }
             catch (e) { op = [6, e]; }
             finally { f = 0, sent = void 0; }
diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts
index adb62f117ef87..f96aacdce454e 100644
--- a/src/compiler/transformers/generators.ts
+++ b/src/compiler/transformers/generators.ts
@@ -2554,21 +2554,24 @@ namespace ts {
             return createCall(
                 createHelperName(currentSourceFile.externalHelpersModuleName, "__generator"),
                 /*typeArguments*/ undefined,
-                [setNodeEmitFlags(
-                    createFunctionExpression(
-                        /*asteriskToken*/ undefined,
-                        /*name*/ undefined,
-                        /*typeParameters*/ undefined,
-                        [createParameter(state)],
-                        /*type*/ undefined,
-                        createBlock(
-                            buildResult,
-                            /*location*/ undefined,
-                            /*multiLine*/ buildResult.length > 0
-                        )
-                    ),
-                    NodeEmitFlags.ReuseTempVariableScope
-                )]
+                [
+                    createThis(),
+                    setNodeEmitFlags(
+                        createFunctionExpression(
+                            /*asteriskToken*/ undefined,
+                            /*name*/ undefined,
+                            /*typeParameters*/ undefined,
+                            [createParameter(state)],
+                            /*type*/ undefined,
+                            createBlock(
+                                buildResult,
+                                /*location*/ undefined,
+                                /*multiLine*/ buildResult.length > 0
+                            )
+                        ),
+                        NodeEmitFlags.ReuseTempVariableScope
+                    )
+                ]
             );
         }
 
diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts
index 57de884da33ec..2e2ed1be4b923 100644
--- a/src/compiler/transformers/ts.ts
+++ b/src/compiler/transformers/ts.ts
@@ -1774,7 +1774,7 @@ namespace ts {
                 case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue:
                     return serializeEntityNameAsExpression(node.typeName, /*useFallback*/ false);
 
-                case TypeReferenceSerializationKind.VoidType:
+                case TypeReferenceSerializationKind.VoidNullableOrNeverType:
                     return createVoidZero();
 
                 case TypeReferenceSerializationKind.BooleanType:
@@ -1797,6 +1797,9 @@ namespace ts {
                 case TypeReferenceSerializationKind.TypeWithCallSignature:
                     return createIdentifier("Function");
 
+                case TypeReferenceSerializationKind.Promise:
+                    return createIdentifier("Promise");
+
                 case TypeReferenceSerializationKind.ObjectType:
                 default:
                     return createIdentifier("Object");
@@ -2221,8 +2224,21 @@ namespace ts {
             }
         }
 
+        function getPromiseConstructor(type: TypeNode) {
+            const typeName = getEntityNameFromTypeNode(type);
+            if (typeName && isEntityName(typeName)) {
+                const serializationKind = resolver.getTypeReferenceSerializationKind(typeName);
+                if (serializationKind === TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue
+                    || serializationKind === TypeReferenceSerializationKind.Unknown) {
+                    return typeName;
+                }
+            }
+
+            return undefined;
+        }
+
         function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody | FunctionBody {
-            const promiseConstructor = languageVersion < ScriptTarget.ES6 ? getEntityNameFromTypeNode(node.type) : undefined;
+            const promiseConstructor = languageVersion < ScriptTarget.ES6 ? getPromiseConstructor(node.type) : undefined;
             const isArrowFunction = node.kind === SyntaxKind.ArrowFunction;
             const hasLexicalArguments = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureArguments) !== 0;
 
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 71e4a202b4097..a8be1a5263470 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -2043,12 +2043,13 @@ namespace ts {
                                             // function that can be reached at runtime (e.g. a `class`
                                             // declaration or a `var` declaration for the static side
                                             // of a type, such as the global `Promise` type in lib.d.ts).
-        VoidType,                           // The TypeReferenceNode resolves to a Void-like type.
+        VoidNullableOrNeverType,            // The TypeReferenceNode resolves to a Void-like, Nullable, or Never type.
         NumberLikeType,                     // The TypeReferenceNode resolves to a Number-like type.
         StringLikeType,                     // The TypeReferenceNode resolves to a String-like type.
         BooleanType,                        // The TypeReferenceNode resolves to a Boolean-like type.
         ArrayLikeType,                      // The TypeReferenceNode resolves to an Array-like type.
         ESSymbolType,                       // The TypeReferenceNode resolves to the ESSymbol type.
+        Promise,                            // The TypeReferenceNode resolved to the global Promise constructor symbol.
         TypeWithCallSignature,              // The TypeReferenceNode resolves to a Function type or a type
                                             // with call signatures.
         ObjectType,                         // The TypeReferenceNode resolves to any other type.
diff --git a/tests/baselines/reference/asyncAliasReturnType_es5.js b/tests/baselines/reference/asyncAliasReturnType_es5.js
new file mode 100644
index 0000000000000..7684b413405f4
--- /dev/null
+++ b/tests/baselines/reference/asyncAliasReturnType_es5.js
@@ -0,0 +1,14 @@
+//// [asyncAliasReturnType_es5.ts]
+type PromiseAlias<T> = Promise<T>;
+
+async function f(): PromiseAlias<void> {
+}
+
+//// [asyncAliasReturnType_es5.js]
+function f() {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
+            return [2 /*return*/];
+        });
+    });
+}
diff --git a/tests/baselines/reference/asyncAliasReturnType_es5.symbols b/tests/baselines/reference/asyncAliasReturnType_es5.symbols
new file mode 100644
index 0000000000000..b61fbf6e275bc
--- /dev/null
+++ b/tests/baselines/reference/asyncAliasReturnType_es5.symbols
@@ -0,0 +1,11 @@
+=== tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts ===
+type PromiseAlias<T> = Promise<T>;
+>PromiseAlias : Symbol(PromiseAlias, Decl(asyncAliasReturnType_es5.ts, 0, 0))
+>T : Symbol(T, Decl(asyncAliasReturnType_es5.ts, 0, 18))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>T : Symbol(T, Decl(asyncAliasReturnType_es5.ts, 0, 18))
+
+async function f(): PromiseAlias<void> {
+>f : Symbol(f, Decl(asyncAliasReturnType_es5.ts, 0, 34))
+>PromiseAlias : Symbol(PromiseAlias, Decl(asyncAliasReturnType_es5.ts, 0, 0))
+}
diff --git a/tests/baselines/reference/asyncAliasReturnType_es5.types b/tests/baselines/reference/asyncAliasReturnType_es5.types
new file mode 100644
index 0000000000000..2b8b576a4d3f5
--- /dev/null
+++ b/tests/baselines/reference/asyncAliasReturnType_es5.types
@@ -0,0 +1,11 @@
+=== tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts ===
+type PromiseAlias<T> = Promise<T>;
+>PromiseAlias : Promise<T>
+>T : T
+>Promise : Promise<T>
+>T : T
+
+async function f(): PromiseAlias<void> {
+>f : () => Promise<void>
+>PromiseAlias : Promise<T>
+}
diff --git a/tests/baselines/reference/asyncAwaitIsolatedModules_es5.errors.txt b/tests/baselines/reference/asyncAwaitIsolatedModules_es5.errors.txt
new file mode 100644
index 0000000000000..7d46517ca159f
--- /dev/null
+++ b/tests/baselines/reference/asyncAwaitIsolatedModules_es5.errors.txt
@@ -0,0 +1,45 @@
+tests/cases/conformance/async/es5/asyncAwaitIsolatedModules_es5.ts(1,27): error TS2307: Cannot find module 'missing'.
+
+
+==== tests/cases/conformance/async/es5/asyncAwaitIsolatedModules_es5.ts (1 errors) ====
+    import { MyPromise } from "missing";
+                              ~~~~~~~~~
+!!! error TS2307: Cannot find module 'missing'.
+    
+    declare var p: Promise<number>;
+    declare var mp: MyPromise<number>;
+    
+    async function f0() { }
+    async function f1(): Promise<void> { }
+    async function f3(): MyPromise<void> { }
+    
+    let f4 = async function() { }
+    let f5 = async function(): Promise<void> { }
+    let f6 = async function(): MyPromise<void> { }
+    
+    let f7 = async () => { };
+    let f8 = async (): Promise<void> => { };
+    let f9 = async (): MyPromise<void> => { };
+    let f10 = async () => p;
+    let f11 = async () => mp;
+    let f12 = async (): Promise<number> => mp;
+    let f13 = async (): MyPromise<number> => p;
+    
+    let o = {
+    	async m1() { },
+    	async m2(): Promise<void> { },
+    	async m3(): MyPromise<void> { }
+    };
+    
+    class C {
+    	async m1() { }
+    	async m2(): Promise<void> { }
+    	async m3(): MyPromise<void> { }
+    	static async m4() { }
+    	static async m5(): Promise<void> { }
+    	static async m6(): MyPromise<void> { }
+    }
+    
+    module M {
+    	export async function f1() { }
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncAwaitIsolatedModules_es5.js b/tests/baselines/reference/asyncAwaitIsolatedModules_es5.js
new file mode 100644
index 0000000000000..95416f3aaa278
--- /dev/null
+++ b/tests/baselines/reference/asyncAwaitIsolatedModules_es5.js
@@ -0,0 +1,201 @@
+//// [asyncAwaitIsolatedModules_es5.ts]
+import { MyPromise } from "missing";
+
+declare var p: Promise<number>;
+declare var mp: MyPromise<number>;
+
+async function f0() { }
+async function f1(): Promise<void> { }
+async function f3(): MyPromise<void> { }
+
+let f4 = async function() { }
+let f5 = async function(): Promise<void> { }
+let f6 = async function(): MyPromise<void> { }
+
+let f7 = async () => { };
+let f8 = async (): Promise<void> => { };
+let f9 = async (): MyPromise<void> => { };
+let f10 = async () => p;
+let f11 = async () => mp;
+let f12 = async (): Promise<number> => mp;
+let f13 = async (): MyPromise<number> => p;
+
+let o = {
+	async m1() { },
+	async m2(): Promise<void> { },
+	async m3(): MyPromise<void> { }
+};
+
+class C {
+	async m1() { }
+	async m2(): Promise<void> { }
+	async m3(): MyPromise<void> { }
+	static async m4() { }
+	static async m5(): Promise<void> { }
+	static async m6(): MyPromise<void> { }
+}
+
+module M {
+	export async function f1() { }
+}
+
+//// [asyncAwaitIsolatedModules_es5.js]
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments)).next());
+    });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+    var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
+    function step(op) {
+        if (f) throw new TypeError("Generator is already executing.");
+        while (1) {
+            if (_.done) switch (op[0]) {
+                case 0: return { value: void 0, done: true };
+                case 1: case 6: throw op[1];
+                case 2: return { value: op[1], done: true };
+            }
+            try {
+                switch (f = 1, op[0]) {
+                    case 0: case 1: sent = op; break;
+                    case 4: return _.label++, { value: op[1], done: false };
+                    case 7: op = _.stack.pop(), _.trys.pop(); continue;
+                    default:
+                        var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
+                        if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; }
+                        if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; }
+                        if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; }
+                        if (r && _.label < r[2]) { _.label = r[2], _.stack.push(op); break; }
+                        if (r[2]) { _.stack.pop(); }
+                        _.trys.pop();
+                        continue;
+                }
+                op = body.call(thisArg, _);
+            }
+            catch (e) { op = [6, e]; }
+            finally { f = 0, sent = void 0; }
+        }
+    }
+    return {
+        next: function (v) { return step([0, v]); },
+        "throw": function (v) { return step([1, v]); },
+        "return": function (v) { return step([2, v]); }
+    };
+};
+var _this = this;
+function f0() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+}
+function f1() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+}
+function f3() {
+    return __awaiter(this, void 0, missing_1.MyPromise, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+}
+var f4 = function () {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+};
+var f5 = function () {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+};
+var f6 = function () {
+    return __awaiter(this, void 0, missing_1.MyPromise, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+};
+var f7 = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+    return [2 /*return*/];
+}); }); };
+var f8 = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+    return [2 /*return*/];
+}); }); };
+var f9 = function () { return __awaiter(_this, void 0, missing_1.MyPromise, function () { return __generator(this, function (_a) {
+    return [2 /*return*/];
+}); }); };
+var f10 = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+    return [2 /*return*/, p];
+}); }); };
+var f11 = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+    return [2 /*return*/, mp];
+}); }); };
+var f12 = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+    return [2 /*return*/, mp];
+}); }); };
+var f13 = function () { return __awaiter(_this, void 0, missing_1.MyPromise, function () { return __generator(this, function (_a) {
+    return [2 /*return*/, p];
+}); }); };
+var o = {
+    m1: function () {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    },
+    m2: function () {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    },
+    m3: function () {
+        return __awaiter(this, void 0, missing_1.MyPromise, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    }
+};
+var C = (function () {
+    function C() {
+    }
+    C.prototype.m1 = function () {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    C.prototype.m2 = function () {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    C.prototype.m3 = function () {
+        return __awaiter(this, void 0, missing_1.MyPromise, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    C.m4 = function () {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    C.m5 = function () {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    C.m6 = function () {
+        return __awaiter(this, void 0, missing_1.MyPromise, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    return C;
+}());
+var M;
+(function (M) {
+    function f1() {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    }
+    M.f1 = f1;
+})(M || (M = {}));
diff --git a/tests/baselines/reference/asyncAwait_es5.js b/tests/baselines/reference/asyncAwait_es5.js
new file mode 100644
index 0000000000000..e148de70ad271
--- /dev/null
+++ b/tests/baselines/reference/asyncAwait_es5.js
@@ -0,0 +1,200 @@
+//// [asyncAwait_es5.ts]
+type MyPromise<T> = Promise<T>;
+declare var MyPromise: typeof Promise;
+declare var p: Promise<number>;
+declare var mp: MyPromise<number>;
+
+async function f0() { }
+async function f1(): Promise<void> { }
+async function f3(): MyPromise<void> { }
+
+let f4 = async function() { }
+let f5 = async function(): Promise<void> { }
+let f6 = async function(): MyPromise<void> { }
+
+let f7 = async () => { };
+let f8 = async (): Promise<void> => { };
+let f9 = async (): MyPromise<void> => { };
+let f10 = async () => p;
+let f11 = async () => mp;
+let f12 = async (): Promise<number> => mp;
+let f13 = async (): MyPromise<number> => p;
+
+let o = {
+	async m1() { },
+	async m2(): Promise<void> { },
+	async m3(): MyPromise<void> { }
+};
+
+class C {
+	async m1() { }
+	async m2(): Promise<void> { }
+	async m3(): MyPromise<void> { }
+	static async m4() { }
+	static async m5(): Promise<void> { }
+	static async m6(): MyPromise<void> { }
+}
+
+module M {
+	export async function f1() { }
+}
+
+//// [asyncAwait_es5.js]
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments)).next());
+    });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+    var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
+    function step(op) {
+        if (f) throw new TypeError("Generator is already executing.");
+        while (1) {
+            if (_.done) switch (op[0]) {
+                case 0: return { value: void 0, done: true };
+                case 1: case 6: throw op[1];
+                case 2: return { value: op[1], done: true };
+            }
+            try {
+                switch (f = 1, op[0]) {
+                    case 0: case 1: sent = op; break;
+                    case 4: return _.label++, { value: op[1], done: false };
+                    case 7: op = _.stack.pop(), _.trys.pop(); continue;
+                    default:
+                        var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
+                        if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; }
+                        if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; }
+                        if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; }
+                        if (r && _.label < r[2]) { _.label = r[2], _.stack.push(op); break; }
+                        if (r[2]) { _.stack.pop(); }
+                        _.trys.pop();
+                        continue;
+                }
+                op = body.call(thisArg, _);
+            }
+            catch (e) { op = [6, e]; }
+            finally { f = 0, sent = void 0; }
+        }
+    }
+    return {
+        next: function (v) { return step([0, v]); },
+        "throw": function (v) { return step([1, v]); },
+        "return": function (v) { return step([2, v]); }
+    };
+};
+var _this = this;
+function f0() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+}
+function f1() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+}
+function f3() {
+    return __awaiter(this, void 0, MyPromise, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+}
+var f4 = function () {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+};
+var f5 = function () {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+};
+var f6 = function () {
+    return __awaiter(this, void 0, MyPromise, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+};
+var f7 = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+    return [2 /*return*/];
+}); }); };
+var f8 = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+    return [2 /*return*/];
+}); }); };
+var f9 = function () { return __awaiter(_this, void 0, MyPromise, function () { return __generator(this, function (_a) {
+    return [2 /*return*/];
+}); }); };
+var f10 = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+    return [2 /*return*/, p];
+}); }); };
+var f11 = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+    return [2 /*return*/, mp];
+}); }); };
+var f12 = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+    return [2 /*return*/, mp];
+}); }); };
+var f13 = function () { return __awaiter(_this, void 0, MyPromise, function () { return __generator(this, function (_a) {
+    return [2 /*return*/, p];
+}); }); };
+var o = {
+    m1: function () {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    },
+    m2: function () {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    },
+    m3: function () {
+        return __awaiter(this, void 0, MyPromise, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    }
+};
+var C = (function () {
+    function C() {
+    }
+    C.prototype.m1 = function () {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    C.prototype.m2 = function () {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    C.prototype.m3 = function () {
+        return __awaiter(this, void 0, MyPromise, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    C.m4 = function () {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    C.m5 = function () {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    C.m6 = function () {
+        return __awaiter(this, void 0, MyPromise, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    return C;
+}());
+var M;
+(function (M) {
+    function f1() {
+        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    }
+    M.f1 = f1;
+})(M || (M = {}));
diff --git a/tests/baselines/reference/asyncAwait_es5.symbols b/tests/baselines/reference/asyncAwait_es5.symbols
new file mode 100644
index 0000000000000..2f80a025ade2a
--- /dev/null
+++ b/tests/baselines/reference/asyncAwait_es5.symbols
@@ -0,0 +1,118 @@
+=== tests/cases/conformance/async/es5/asyncAwait_es5.ts ===
+type MyPromise<T> = Promise<T>;
+>MyPromise : Symbol(MyPromise, Decl(asyncAwait_es5.ts, 0, 0), Decl(asyncAwait_es5.ts, 1, 11))
+>T : Symbol(T, Decl(asyncAwait_es5.ts, 0, 15))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>T : Symbol(T, Decl(asyncAwait_es5.ts, 0, 15))
+
+declare var MyPromise: typeof Promise;
+>MyPromise : Symbol(MyPromise, Decl(asyncAwait_es5.ts, 0, 0), Decl(asyncAwait_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare var p: Promise<number>;
+>p : Symbol(p, Decl(asyncAwait_es5.ts, 2, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+declare var mp: MyPromise<number>;
+>mp : Symbol(mp, Decl(asyncAwait_es5.ts, 3, 11))
+>MyPromise : Symbol(MyPromise, Decl(asyncAwait_es5.ts, 0, 0), Decl(asyncAwait_es5.ts, 1, 11))
+
+async function f0() { }
+>f0 : Symbol(f0, Decl(asyncAwait_es5.ts, 3, 34))
+
+async function f1(): Promise<void> { }
+>f1 : Symbol(f1, Decl(asyncAwait_es5.ts, 5, 23))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+async function f3(): MyPromise<void> { }
+>f3 : Symbol(f3, Decl(asyncAwait_es5.ts, 6, 38))
+>MyPromise : Symbol(MyPromise, Decl(asyncAwait_es5.ts, 0, 0), Decl(asyncAwait_es5.ts, 1, 11))
+
+let f4 = async function() { }
+>f4 : Symbol(f4, Decl(asyncAwait_es5.ts, 9, 3))
+
+let f5 = async function(): Promise<void> { }
+>f5 : Symbol(f5, Decl(asyncAwait_es5.ts, 10, 3))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+let f6 = async function(): MyPromise<void> { }
+>f6 : Symbol(f6, Decl(asyncAwait_es5.ts, 11, 3))
+>MyPromise : Symbol(MyPromise, Decl(asyncAwait_es5.ts, 0, 0), Decl(asyncAwait_es5.ts, 1, 11))
+
+let f7 = async () => { };
+>f7 : Symbol(f7, Decl(asyncAwait_es5.ts, 13, 3))
+
+let f8 = async (): Promise<void> => { };
+>f8 : Symbol(f8, Decl(asyncAwait_es5.ts, 14, 3))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+let f9 = async (): MyPromise<void> => { };
+>f9 : Symbol(f9, Decl(asyncAwait_es5.ts, 15, 3))
+>MyPromise : Symbol(MyPromise, Decl(asyncAwait_es5.ts, 0, 0), Decl(asyncAwait_es5.ts, 1, 11))
+
+let f10 = async () => p;
+>f10 : Symbol(f10, Decl(asyncAwait_es5.ts, 16, 3))
+>p : Symbol(p, Decl(asyncAwait_es5.ts, 2, 11))
+
+let f11 = async () => mp;
+>f11 : Symbol(f11, Decl(asyncAwait_es5.ts, 17, 3))
+>mp : Symbol(mp, Decl(asyncAwait_es5.ts, 3, 11))
+
+let f12 = async (): Promise<number> => mp;
+>f12 : Symbol(f12, Decl(asyncAwait_es5.ts, 18, 3))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>mp : Symbol(mp, Decl(asyncAwait_es5.ts, 3, 11))
+
+let f13 = async (): MyPromise<number> => p;
+>f13 : Symbol(f13, Decl(asyncAwait_es5.ts, 19, 3))
+>MyPromise : Symbol(MyPromise, Decl(asyncAwait_es5.ts, 0, 0), Decl(asyncAwait_es5.ts, 1, 11))
+>p : Symbol(p, Decl(asyncAwait_es5.ts, 2, 11))
+
+let o = {
+>o : Symbol(o, Decl(asyncAwait_es5.ts, 21, 3))
+
+	async m1() { },
+>m1 : Symbol(m1, Decl(asyncAwait_es5.ts, 21, 9))
+
+	async m2(): Promise<void> { },
+>m2 : Symbol(m2, Decl(asyncAwait_es5.ts, 22, 16))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+	async m3(): MyPromise<void> { }
+>m3 : Symbol(m3, Decl(asyncAwait_es5.ts, 23, 31))
+>MyPromise : Symbol(MyPromise, Decl(asyncAwait_es5.ts, 0, 0), Decl(asyncAwait_es5.ts, 1, 11))
+
+};
+
+class C {
+>C : Symbol(C, Decl(asyncAwait_es5.ts, 25, 2))
+
+	async m1() { }
+>m1 : Symbol(C.m1, Decl(asyncAwait_es5.ts, 27, 9))
+
+	async m2(): Promise<void> { }
+>m2 : Symbol(C.m2, Decl(asyncAwait_es5.ts, 28, 15))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+	async m3(): MyPromise<void> { }
+>m3 : Symbol(C.m3, Decl(asyncAwait_es5.ts, 29, 30))
+>MyPromise : Symbol(MyPromise, Decl(asyncAwait_es5.ts, 0, 0), Decl(asyncAwait_es5.ts, 1, 11))
+
+	static async m4() { }
+>m4 : Symbol(C.m4, Decl(asyncAwait_es5.ts, 30, 32))
+
+	static async m5(): Promise<void> { }
+>m5 : Symbol(C.m5, Decl(asyncAwait_es5.ts, 31, 22))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+	static async m6(): MyPromise<void> { }
+>m6 : Symbol(C.m6, Decl(asyncAwait_es5.ts, 32, 37))
+>MyPromise : Symbol(MyPromise, Decl(asyncAwait_es5.ts, 0, 0), Decl(asyncAwait_es5.ts, 1, 11))
+}
+
+module M {
+>M : Symbol(M, Decl(asyncAwait_es5.ts, 34, 1))
+
+	export async function f1() { }
+>f1 : Symbol(f1, Decl(asyncAwait_es5.ts, 36, 10))
+}
diff --git a/tests/baselines/reference/asyncAwait_es5.types b/tests/baselines/reference/asyncAwait_es5.types
new file mode 100644
index 0000000000000..4162aa84b765c
--- /dev/null
+++ b/tests/baselines/reference/asyncAwait_es5.types
@@ -0,0 +1,129 @@
+=== tests/cases/conformance/async/es5/asyncAwait_es5.ts ===
+type MyPromise<T> = Promise<T>;
+>MyPromise : Promise<T>
+>T : T
+>Promise : Promise<T>
+>T : T
+
+declare var MyPromise: typeof Promise;
+>MyPromise : PromiseConstructor
+>Promise : PromiseConstructor
+
+declare var p: Promise<number>;
+>p : Promise<number>
+>Promise : Promise<T>
+
+declare var mp: MyPromise<number>;
+>mp : Promise<number>
+>MyPromise : Promise<T>
+
+async function f0() { }
+>f0 : () => Promise<void>
+
+async function f1(): Promise<void> { }
+>f1 : () => Promise<void>
+>Promise : Promise<T>
+
+async function f3(): MyPromise<void> { }
+>f3 : () => Promise<void>
+>MyPromise : Promise<T>
+
+let f4 = async function() { }
+>f4 : () => Promise<void>
+>async function() { } : () => Promise<void>
+
+let f5 = async function(): Promise<void> { }
+>f5 : () => Promise<void>
+>async function(): Promise<void> { } : () => Promise<void>
+>Promise : Promise<T>
+
+let f6 = async function(): MyPromise<void> { }
+>f6 : () => Promise<void>
+>async function(): MyPromise<void> { } : () => Promise<void>
+>MyPromise : Promise<T>
+
+let f7 = async () => { };
+>f7 : () => Promise<void>
+>async () => { } : () => Promise<void>
+
+let f8 = async (): Promise<void> => { };
+>f8 : () => Promise<void>
+>async (): Promise<void> => { } : () => Promise<void>
+>Promise : Promise<T>
+
+let f9 = async (): MyPromise<void> => { };
+>f9 : () => Promise<void>
+>async (): MyPromise<void> => { } : () => Promise<void>
+>MyPromise : Promise<T>
+
+let f10 = async () => p;
+>f10 : () => Promise<number>
+>async () => p : () => Promise<number>
+>p : Promise<number>
+
+let f11 = async () => mp;
+>f11 : () => Promise<number>
+>async () => mp : () => Promise<number>
+>mp : Promise<number>
+
+let f12 = async (): Promise<number> => mp;
+>f12 : () => Promise<number>
+>async (): Promise<number> => mp : () => Promise<number>
+>Promise : Promise<T>
+>mp : Promise<number>
+
+let f13 = async (): MyPromise<number> => p;
+>f13 : () => Promise<number>
+>async (): MyPromise<number> => p : () => Promise<number>
+>MyPromise : Promise<T>
+>p : Promise<number>
+
+let o = {
+>o : { m1(): Promise<void>; m2(): Promise<void>; m3(): Promise<void>; }
+>{	async m1() { },	async m2(): Promise<void> { },	async m3(): MyPromise<void> { }} : { m1(): Promise<void>; m2(): Promise<void>; m3(): Promise<void>; }
+
+	async m1() { },
+>m1 : () => Promise<void>
+
+	async m2(): Promise<void> { },
+>m2 : () => Promise<void>
+>Promise : Promise<T>
+
+	async m3(): MyPromise<void> { }
+>m3 : () => Promise<void>
+>MyPromise : Promise<T>
+
+};
+
+class C {
+>C : C
+
+	async m1() { }
+>m1 : () => Promise<void>
+
+	async m2(): Promise<void> { }
+>m2 : () => Promise<void>
+>Promise : Promise<T>
+
+	async m3(): MyPromise<void> { }
+>m3 : () => Promise<void>
+>MyPromise : Promise<T>
+
+	static async m4() { }
+>m4 : () => Promise<void>
+
+	static async m5(): Promise<void> { }
+>m5 : () => Promise<void>
+>Promise : Promise<T>
+
+	static async m6(): MyPromise<void> { }
+>m6 : () => Promise<void>
+>MyPromise : Promise<T>
+}
+
+module M {
+>M : typeof M
+
+	export async function f1() { }
+>f1 : () => Promise<void>
+}
diff --git a/tests/baselines/reference/asyncClass_es5.errors.txt b/tests/baselines/reference/asyncClass_es5.errors.txt
new file mode 100644
index 0000000000000..e8f4efd4f07eb
--- /dev/null
+++ b/tests/baselines/reference/asyncClass_es5.errors.txt
@@ -0,0 +1,8 @@
+tests/cases/conformance/async/es5/asyncClass_es5.ts(1,1): error TS1042: 'async' modifier cannot be used here.
+
+
+==== tests/cases/conformance/async/es5/asyncClass_es5.ts (1 errors) ====
+    async class C {
+    ~~~~~
+!!! error TS1042: 'async' modifier cannot be used here.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncClass_es5.js b/tests/baselines/reference/asyncClass_es5.js
new file mode 100644
index 0000000000000..a552349118aee
--- /dev/null
+++ b/tests/baselines/reference/asyncClass_es5.js
@@ -0,0 +1,10 @@
+//// [asyncClass_es5.ts]
+async class C {
+}
+
+//// [asyncClass_es5.js]
+var C = (function () {
+    function C() {
+    }
+    return C;
+}());
diff --git a/tests/baselines/reference/asyncConstructor_es5.errors.txt b/tests/baselines/reference/asyncConstructor_es5.errors.txt
new file mode 100644
index 0000000000000..c24bf87ae67ff
--- /dev/null
+++ b/tests/baselines/reference/asyncConstructor_es5.errors.txt
@@ -0,0 +1,10 @@
+tests/cases/conformance/async/es5/asyncConstructor_es5.ts(2,3): error TS1089: 'async' modifier cannot appear on a constructor declaration.
+
+
+==== tests/cases/conformance/async/es5/asyncConstructor_es5.ts (1 errors) ====
+    class C {
+      async constructor() {
+      ~~~~~
+!!! error TS1089: 'async' modifier cannot appear on a constructor declaration.
+      }
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncConstructor_es5.js b/tests/baselines/reference/asyncConstructor_es5.js
new file mode 100644
index 0000000000000..95470ccf9b0dc
--- /dev/null
+++ b/tests/baselines/reference/asyncConstructor_es5.js
@@ -0,0 +1,12 @@
+//// [asyncConstructor_es5.ts]
+class C {
+  async constructor() {
+  }
+}
+
+//// [asyncConstructor_es5.js]
+var C = (function () {
+    function C() {
+    }
+    return C;
+}());
diff --git a/tests/baselines/reference/asyncDeclare_es5.errors.txt b/tests/baselines/reference/asyncDeclare_es5.errors.txt
new file mode 100644
index 0000000000000..bfa467acca219
--- /dev/null
+++ b/tests/baselines/reference/asyncDeclare_es5.errors.txt
@@ -0,0 +1,7 @@
+tests/cases/conformance/async/es5/asyncDeclare_es5.ts(1,9): error TS1040: 'async' modifier cannot be used in an ambient context.
+
+
+==== tests/cases/conformance/async/es5/asyncDeclare_es5.ts (1 errors) ====
+    declare async function foo(): Promise<void>;
+            ~~~~~
+!!! error TS1040: 'async' modifier cannot be used in an ambient context.
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncDeclare_es5.js b/tests/baselines/reference/asyncDeclare_es5.js
new file mode 100644
index 0000000000000..80ee6017ad596
--- /dev/null
+++ b/tests/baselines/reference/asyncDeclare_es5.js
@@ -0,0 +1,4 @@
+//// [asyncDeclare_es5.ts]
+declare async function foo(): Promise<void>;
+
+//// [asyncDeclare_es5.js]
diff --git a/tests/baselines/reference/asyncEnum_es5.errors.txt b/tests/baselines/reference/asyncEnum_es5.errors.txt
new file mode 100644
index 0000000000000..6029ae9c9d0a1
--- /dev/null
+++ b/tests/baselines/reference/asyncEnum_es5.errors.txt
@@ -0,0 +1,9 @@
+tests/cases/conformance/async/es5/asyncEnum_es5.ts(1,1): error TS1042: 'async' modifier cannot be used here.
+
+
+==== tests/cases/conformance/async/es5/asyncEnum_es5.ts (1 errors) ====
+    async enum E {
+    ~~~~~
+!!! error TS1042: 'async' modifier cannot be used here.
+      Value
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncEnum_es5.js b/tests/baselines/reference/asyncEnum_es5.js
new file mode 100644
index 0000000000000..d65b4bdb510af
--- /dev/null
+++ b/tests/baselines/reference/asyncEnum_es5.js
@@ -0,0 +1,10 @@
+//// [asyncEnum_es5.ts]
+async enum E {
+  Value
+}
+
+//// [asyncEnum_es5.js]
+var E;
+(function (E) {
+    E[E["Value"] = 0] = "Value";
+})(E || (E = {}));
diff --git a/tests/baselines/reference/asyncFunctionDeclaration11_es5.js b/tests/baselines/reference/asyncFunctionDeclaration11_es5.js
index 166f4c9c5ca36..27d16ebb0c1f3 100644
--- a/tests/baselines/reference/asyncFunctionDeclaration11_es5.js
+++ b/tests/baselines/reference/asyncFunctionDeclaration11_es5.js
@@ -4,8 +4,8 @@ async function await(): Promise<void> {
 
 //// [asyncFunctionDeclaration11_es5.js]
 function await() {
-    return __awaiter(this, void 0, Promise, function () {
-        return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
             return [2 /*return*/];
         });
     });
diff --git a/tests/baselines/reference/asyncFunctionDeclaration13_es5.js b/tests/baselines/reference/asyncFunctionDeclaration13_es5.js
index 2ab2f5c7b7b1f..e097192fbbf65 100644
--- a/tests/baselines/reference/asyncFunctionDeclaration13_es5.js
+++ b/tests/baselines/reference/asyncFunctionDeclaration13_es5.js
@@ -7,9 +7,9 @@ async function foo(): Promise<void> {
 
 //// [asyncFunctionDeclaration13_es5.js]
 function foo() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var v;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             return [2 /*return*/];
         });
     });
diff --git a/tests/baselines/reference/asyncFunctionDeclaration14_es5.js b/tests/baselines/reference/asyncFunctionDeclaration14_es5.js
index d0e747e0f8430..5ef6ce610843c 100644
--- a/tests/baselines/reference/asyncFunctionDeclaration14_es5.js
+++ b/tests/baselines/reference/asyncFunctionDeclaration14_es5.js
@@ -5,8 +5,8 @@ async function foo(): Promise<void> {
 
 //// [asyncFunctionDeclaration14_es5.js]
 function foo() {
-    return __awaiter(this, void 0, Promise, function () {
-        return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
             return [2 /*return*/];
         });
     });
diff --git a/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt
index 752feb261b3c4..62c64f2cd5401 100644
--- a/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt
+++ b/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt
@@ -1,9 +1,9 @@
-tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(6,16): error TS1055: Type '{}' is not a valid async function return type.
-tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(7,16): error TS1055: Type 'any' is not a valid async function return type.
-tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(8,16): error TS1055: Type 'number' is not a valid async function return type.
-tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(9,16): error TS1055: Type 'PromiseLike' is not a valid async function return type.
-tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,16): error TS1055: Type 'typeof Thenable' is not a valid async function return type.
-tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,16): error TS1055: Type 'typeof Thenable' is not a valid async function return type.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(6,23): error TS1055: Type '{}' is not a valid async function return type.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(7,23): error TS1055: Type 'any' is not a valid async function return type.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(8,23): error TS1055: Type 'number' is not a valid async function return type.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(9,23): error TS1055: Type 'PromiseLike' is not a valid async function return type.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type.
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type.
   Type 'Thenable' is not assignable to type 'PromiseLike<any>'.
     Types of property 'then' are incompatible.
       Type '() => void' is not assignable to type '{ <TResult>(onfulfilled?: (value: any) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>; <TResult>(onfulfilled?: (value: any) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): PromiseLike<TResult>; }'.
@@ -19,21 +19,21 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1
     declare let thenable: Thenable;
     async function fn1() { } // valid: Promise<void>
     async function fn2(): { } { } // error
-                   ~~~
+                          ~~~
 !!! error TS1055: Type '{}' is not a valid async function return type.
     async function fn3(): any { } // error
-                   ~~~
+                          ~~~
 !!! error TS1055: Type 'any' is not a valid async function return type.
     async function fn4(): number { } // error
-                   ~~~
+                          ~~~~~~
 !!! error TS1055: Type 'number' is not a valid async function return type.
     async function fn5(): PromiseLike<void> { } // error
-                   ~~~
+                          ~~~~~~~~~~~~~~~~~
 !!! error TS1055: Type 'PromiseLike' is not a valid async function return type.
     async function fn6(): Thenable { } // error
-                   ~~~
+                          ~~~~~~~~
 !!! error TS1055: Type 'typeof Thenable' is not a valid async function return type.
-                   ~~~
+                          ~~~~~~~~
 !!! error TS1055: Type 'typeof Thenable' is not a valid async function return type.
 !!! error TS1055:   Type 'Thenable' is not assignable to type 'PromiseLike<any>'.
 !!! error TS1055:     Types of property 'then' are incompatible.
diff --git a/tests/baselines/reference/asyncFunctionDeclaration15_es5.js b/tests/baselines/reference/asyncFunctionDeclaration15_es5.js
index 47e1fe45c80df..5ca93d3eca85e 100644
--- a/tests/baselines/reference/asyncFunctionDeclaration15_es5.js
+++ b/tests/baselines/reference/asyncFunctionDeclaration15_es5.js
@@ -26,72 +26,72 @@ async function fn19() { await thenable; } // error
 
 //// [asyncFunctionDeclaration15_es5.js]
 function fn1() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         return [2 /*return*/];
     }); });
 } // valid: Promise<void>
 function fn2() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         return [2 /*return*/];
     }); });
 } // error
 function fn3() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         return [2 /*return*/];
     }); });
 } // error
 function fn4() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         return [2 /*return*/];
     }); });
 } // error
 function fn5() {
-    return __awaiter(this, void 0, PromiseLike, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         return [2 /*return*/];
     }); });
 } // error
 function fn6() {
-    return __awaiter(this, void 0, Thenable, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, Thenable, function () { return __generator(this, function (_a) {
         return [2 /*return*/];
     }); });
 } // error
 function fn7() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         return [2 /*return*/];
     }); });
 } // valid: Promise<void>
 function fn8() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         return [2 /*return*/, 1];
     }); });
 } // valid: Promise<number>
 function fn9() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         return [2 /*return*/, null];
     }); });
 } // valid: Promise<any>
 function fn10() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         return [2 /*return*/, undefined];
     }); });
 } // valid: Promise<any>
 function fn11() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         return [2 /*return*/, a];
     }); });
 } // valid: Promise<any>
 function fn12() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         return [2 /*return*/, obj];
     }); });
 } // valid: Promise<{ then: string; }>
 function fn13() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         return [2 /*return*/, thenable];
     }); });
 } // error
 function fn14() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         switch (_a.label) {
             case 0: return [4 /*yield*/, 1];
             case 1:
@@ -101,7 +101,7 @@ function fn14() {
     }); });
 } // valid: Promise<void>
 function fn15() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         switch (_a.label) {
             case 0: return [4 /*yield*/, null];
             case 1:
@@ -111,7 +111,7 @@ function fn15() {
     }); });
 } // valid: Promise<void>
 function fn16() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         switch (_a.label) {
             case 0: return [4 /*yield*/, undefined];
             case 1:
@@ -121,7 +121,7 @@ function fn16() {
     }); });
 } // valid: Promise<void>
 function fn17() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         switch (_a.label) {
             case 0: return [4 /*yield*/, a];
             case 1:
@@ -131,7 +131,7 @@ function fn17() {
     }); });
 } // valid: Promise<void>
 function fn18() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         switch (_a.label) {
             case 0: return [4 /*yield*/, obj];
             case 1:
@@ -141,7 +141,7 @@ function fn18() {
     }); });
 } // valid: Promise<void>
 function fn19() {
-    return __awaiter(this, void 0, void 0, function () { return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
         switch (_a.label) {
             case 0: return [4 /*yield*/, thenable];
             case 1:
diff --git a/tests/baselines/reference/asyncFunctionDeclaration1_es5.js b/tests/baselines/reference/asyncFunctionDeclaration1_es5.js
index 3f020ec6ece36..913a0b3c4e21f 100644
--- a/tests/baselines/reference/asyncFunctionDeclaration1_es5.js
+++ b/tests/baselines/reference/asyncFunctionDeclaration1_es5.js
@@ -4,8 +4,8 @@ async function foo(): Promise<void> {
 
 //// [asyncFunctionDeclaration1_es5.js]
 function foo() {
-    return __awaiter(this, void 0, Promise, function () {
-        return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
             return [2 /*return*/];
         });
     });
diff --git a/tests/baselines/reference/asyncFunctionDeclaration6_es5.js b/tests/baselines/reference/asyncFunctionDeclaration6_es5.js
index 2ee26f29e62e0..282036f97def1 100644
--- a/tests/baselines/reference/asyncFunctionDeclaration6_es5.js
+++ b/tests/baselines/reference/asyncFunctionDeclaration6_es5.js
@@ -5,8 +5,8 @@ async function foo(a = await): Promise<void> {
 //// [asyncFunctionDeclaration6_es5.js]
 function foo(a) {
     if (a === void 0) { a = yield ; }
-    return __awaiter(this, void 0, Promise, function () {
-        return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
             return [2 /*return*/];
         });
     });
diff --git a/tests/baselines/reference/asyncFunctionDeclaration7_es5.js b/tests/baselines/reference/asyncFunctionDeclaration7_es5.js
index 7bcf3be59ad69..60dd0d6e3bf32 100644
--- a/tests/baselines/reference/asyncFunctionDeclaration7_es5.js
+++ b/tests/baselines/reference/asyncFunctionDeclaration7_es5.js
@@ -7,17 +7,17 @@ async function bar(): Promise<void> {
 
 //// [asyncFunctionDeclaration7_es5.js]
 function bar() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         // 'await' here is an identifier, and not a yield expression.
         function foo(a) {
             if (a === void 0) { a = yield ; }
-            return __awaiter(this, void 0, Promise, function () {
-                return __generator(function (_a) {
+            return __awaiter(this, void 0, void 0, function () {
+                return __generator(this, function (_a) {
                     return [2 /*return*/];
                 });
             });
         }
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             return [2 /*return*/];
         });
     });
diff --git a/tests/baselines/reference/asyncFunctionDeclaration9_es5.js b/tests/baselines/reference/asyncFunctionDeclaration9_es5.js
index 2da28f95cff00..e35ec29595bb2 100644
--- a/tests/baselines/reference/asyncFunctionDeclaration9_es5.js
+++ b/tests/baselines/reference/asyncFunctionDeclaration9_es5.js
@@ -5,9 +5,9 @@ async function foo(): Promise<void> {
 
 //// [asyncFunctionDeclaration9_es5.js]
 function foo() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var v, _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = {};
diff --git a/tests/baselines/reference/asyncGetter_es5.errors.txt b/tests/baselines/reference/asyncGetter_es5.errors.txt
new file mode 100644
index 0000000000000..fd3fba40a60ec
--- /dev/null
+++ b/tests/baselines/reference/asyncGetter_es5.errors.txt
@@ -0,0 +1,13 @@
+tests/cases/conformance/async/es5/asyncGetter_es5.ts(2,3): error TS1042: 'async' modifier cannot be used here.
+tests/cases/conformance/async/es5/asyncGetter_es5.ts(2,13): error TS2378: A 'get' accessor must return a value.
+
+
+==== tests/cases/conformance/async/es5/asyncGetter_es5.ts (2 errors) ====
+    class C {
+      async get foo() {
+      ~~~~~
+!!! error TS1042: 'async' modifier cannot be used here.
+                ~~~
+!!! error TS2378: A 'get' accessor must return a value.
+      }
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncGetter_es5.js b/tests/baselines/reference/asyncGetter_es5.js
new file mode 100644
index 0000000000000..a9c7f6355d313
--- /dev/null
+++ b/tests/baselines/reference/asyncGetter_es5.js
@@ -0,0 +1,18 @@
+//// [asyncGetter_es5.ts]
+class C {
+  async get foo() {
+  }
+}
+
+//// [asyncGetter_es5.js]
+var C = (function () {
+    function C() {
+    }
+    Object.defineProperty(C.prototype, "foo", {
+        get: function () {
+        },
+        enumerable: true,
+        configurable: true
+    });
+    return C;
+}());
diff --git a/tests/baselines/reference/asyncImportedPromise_es5.js b/tests/baselines/reference/asyncImportedPromise_es5.js
new file mode 100644
index 0000000000000..54d1b0fdac824
--- /dev/null
+++ b/tests/baselines/reference/asyncImportedPromise_es5.js
@@ -0,0 +1,84 @@
+//// [tests/cases/conformance/async/es5/asyncImportedPromise_es5.ts] ////
+
+//// [task.ts]
+export class Task<T> extends Promise<T> { }
+
+//// [test.ts]
+import { Task } from "./task";
+class Test {
+    async example<T>(): Task<T> { return; }
+}
+
+//// [task.js]
+"use strict";
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var Task = (function (_super) {
+    __extends(Task, _super);
+    function Task() {
+        _super.apply(this, arguments);
+    }
+    return Task;
+}(Promise));
+exports.Task = Task;
+//// [test.js]
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments)).next());
+    });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+    var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
+    function step(op) {
+        if (f) throw new TypeError("Generator is already executing.");
+        while (1) {
+            if (_.done) switch (op[0]) {
+                case 0: return { value: void 0, done: true };
+                case 1: case 6: throw op[1];
+                case 2: return { value: op[1], done: true };
+            }
+            try {
+                switch (f = 1, op[0]) {
+                    case 0: case 1: sent = op; break;
+                    case 4: return _.label++, { value: op[1], done: false };
+                    case 7: op = _.stack.pop(), _.trys.pop(); continue;
+                    default:
+                        var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
+                        if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; }
+                        if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; }
+                        if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; }
+                        if (r && _.label < r[2]) { _.label = r[2], _.stack.push(op); break; }
+                        if (r[2]) { _.stack.pop(); }
+                        _.trys.pop();
+                        continue;
+                }
+                op = body.call(thisArg, _);
+            }
+            catch (e) { op = [6, e]; }
+            finally { f = 0, sent = void 0; }
+        }
+    }
+    return {
+        next: function (v) { return step([0, v]); },
+        "throw": function (v) { return step([1, v]); },
+        "return": function (v) { return step([2, v]); }
+    };
+};
+var task_1 = require("./task");
+var Test = (function () {
+    function Test() {
+    }
+    Test.prototype.example = function () {
+        return __awaiter(this, void 0, task_1.Task, function () { return __generator(this, function (_a) {
+            return [2 /*return*/];
+        }); });
+    };
+    return Test;
+}());
diff --git a/tests/baselines/reference/asyncImportedPromise_es5.symbols b/tests/baselines/reference/asyncImportedPromise_es5.symbols
new file mode 100644
index 0000000000000..b889299bd7ebd
--- /dev/null
+++ b/tests/baselines/reference/asyncImportedPromise_es5.symbols
@@ -0,0 +1,20 @@
+=== tests/cases/conformance/async/es5/task.ts ===
+export class Task<T> extends Promise<T> { }
+>Task : Symbol(Task, Decl(task.ts, 0, 0))
+>T : Symbol(T, Decl(task.ts, 0, 18))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>T : Symbol(T, Decl(task.ts, 0, 18))
+
+=== tests/cases/conformance/async/es5/test.ts ===
+import { Task } from "./task";
+>Task : Symbol(Task, Decl(test.ts, 0, 8))
+
+class Test {
+>Test : Symbol(Test, Decl(test.ts, 0, 30))
+
+    async example<T>(): Task<T> { return; }
+>example : Symbol(Test.example, Decl(test.ts, 1, 12))
+>T : Symbol(T, Decl(test.ts, 2, 18))
+>Task : Symbol(Task, Decl(test.ts, 0, 8))
+>T : Symbol(T, Decl(test.ts, 2, 18))
+}
diff --git a/tests/baselines/reference/asyncImportedPromise_es5.types b/tests/baselines/reference/asyncImportedPromise_es5.types
new file mode 100644
index 0000000000000..54a6e52fa171b
--- /dev/null
+++ b/tests/baselines/reference/asyncImportedPromise_es5.types
@@ -0,0 +1,20 @@
+=== tests/cases/conformance/async/es5/task.ts ===
+export class Task<T> extends Promise<T> { }
+>Task : Task<T>
+>T : T
+>Promise : Promise<T>
+>T : T
+
+=== tests/cases/conformance/async/es5/test.ts ===
+import { Task } from "./task";
+>Task : typeof Task
+
+class Test {
+>Test : Test
+
+    async example<T>(): Task<T> { return; }
+>example : <T>() => Task<T>
+>T : T
+>Task : Task<T>
+>T : T
+}
diff --git a/tests/baselines/reference/asyncInterface_es5.errors.txt b/tests/baselines/reference/asyncInterface_es5.errors.txt
new file mode 100644
index 0000000000000..30d2c554da718
--- /dev/null
+++ b/tests/baselines/reference/asyncInterface_es5.errors.txt
@@ -0,0 +1,8 @@
+tests/cases/conformance/async/es5/asyncInterface_es5.ts(1,1): error TS1042: 'async' modifier cannot be used here.
+
+
+==== tests/cases/conformance/async/es5/asyncInterface_es5.ts (1 errors) ====
+    async interface I {
+    ~~~~~
+!!! error TS1042: 'async' modifier cannot be used here.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncInterface_es5.js b/tests/baselines/reference/asyncInterface_es5.js
new file mode 100644
index 0000000000000..280dade386942
--- /dev/null
+++ b/tests/baselines/reference/asyncInterface_es5.js
@@ -0,0 +1,5 @@
+//// [asyncInterface_es5.ts]
+async interface I {
+}
+
+//// [asyncInterface_es5.js]
diff --git a/tests/baselines/reference/asyncMethodWithSuper_es5.js b/tests/baselines/reference/asyncMethodWithSuper_es5.js
new file mode 100644
index 0000000000000..87debbdc55c2e
--- /dev/null
+++ b/tests/baselines/reference/asyncMethodWithSuper_es5.js
@@ -0,0 +1,106 @@
+//// [asyncMethodWithSuper_es5.ts]
+class A {
+    x() {
+    }
+}
+
+class B extends A {
+    // async method with only call/get on 'super' does not require a binding
+    async simple() {
+        // call with property access
+        super.x();
+
+        // call with element access
+        super["x"]();
+
+        // property access (read)
+        const a = super.x;
+
+        // element access (read)
+        const b = super["x"];
+    }
+
+    // async method with assignment/destructuring on 'super' requires a binding
+    async advanced() {
+        const f = () => {};
+
+        // call with property access
+        super.x();
+
+        // call with element access
+        super["x"]();
+
+        // property access (read)
+        const a = super.x;
+
+        // element access (read)
+        const b = super["x"];
+
+        // property access (assign)
+        super.x = f;
+
+        // element access (assign)
+        super["x"] = f;
+
+        // destructuring assign with property access
+        ({ f: super.x } = { f });
+
+        // destructuring assign with element access
+        ({ f: super["x"] } = { f });
+    }
+}
+
+//// [asyncMethodWithSuper_es5.js]
+var A = (function () {
+    function A() {
+    }
+    A.prototype.x = function () {
+    };
+    return A;
+}());
+var B = (function (_super) {
+    __extends(B, _super);
+    function B() {
+        _super.apply(this, arguments);
+    }
+    // async method with only call/get on 'super' does not require a binding
+    B.prototype.simple = function () {
+        return __awaiter(this, void 0, void 0, function () {
+            var a, b;
+            return __generator(this, function (_a) {
+                // call with property access
+                _super.x.call(this);
+                // call with element access
+                _super["x"].call(this);
+                a = _super.x;
+                b = _super["x"];
+                return [2 /*return*/];
+            });
+        });
+    };
+    // async method with assignment/destructuring on 'super' requires a binding
+    B.prototype.advanced = function () {
+        return __awaiter(this, void 0, void 0, function () {
+            var f, a, b, _a, _b;
+            return __generator(this, function (_c) {
+                f = function () { };
+                // call with property access
+                _super.x.call(this);
+                // call with element access
+                _super["x"].call(this);
+                a = _super.x;
+                b = _super["x"];
+                // property access (assign)
+                _super.x = f;
+                // element access (assign)
+                _super["x"] = f;
+                // destructuring assign with property access
+                (_a = { f: f }, super.x = _a.f, _a);
+                // destructuring assign with element access
+                (_b = { f: f }, super["x"] = _b.f, _b);
+                return [2 /*return*/];
+            });
+        });
+    };
+    return B;
+}(A));
diff --git a/tests/baselines/reference/asyncMethodWithSuper_es5.symbols b/tests/baselines/reference/asyncMethodWithSuper_es5.symbols
new file mode 100644
index 0000000000000..e05f00a8e97c2
--- /dev/null
+++ b/tests/baselines/reference/asyncMethodWithSuper_es5.symbols
@@ -0,0 +1,102 @@
+=== tests/cases/conformance/async/es5/asyncMethodWithSuper_es5.ts ===
+class A {
+>A : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+
+    x() {
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+    }
+}
+
+class B extends A {
+>B : Symbol(B, Decl(asyncMethodWithSuper_es5.ts, 3, 1))
+>A : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+
+    // async method with only call/get on 'super' does not require a binding
+    async simple() {
+>simple : Symbol(B.simple, Decl(asyncMethodWithSuper_es5.ts, 5, 19))
+
+        // call with property access
+        super.x();
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+
+        // call with element access
+        super["x"]();
+>super : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+
+        // property access (read)
+        const a = super.x;
+>a : Symbol(a, Decl(asyncMethodWithSuper_es5.ts, 15, 13))
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+
+        // element access (read)
+        const b = super["x"];
+>b : Symbol(b, Decl(asyncMethodWithSuper_es5.ts, 18, 13))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+    }
+
+    // async method with assignment/destructuring on 'super' requires a binding
+    async advanced() {
+>advanced : Symbol(B.advanced, Decl(asyncMethodWithSuper_es5.ts, 19, 5))
+
+        const f = () => {};
+>f : Symbol(f, Decl(asyncMethodWithSuper_es5.ts, 23, 13))
+
+        // call with property access
+        super.x();
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+
+        // call with element access
+        super["x"]();
+>super : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+
+        // property access (read)
+        const a = super.x;
+>a : Symbol(a, Decl(asyncMethodWithSuper_es5.ts, 32, 13))
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+
+        // element access (read)
+        const b = super["x"];
+>b : Symbol(b, Decl(asyncMethodWithSuper_es5.ts, 35, 13))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+
+        // property access (assign)
+        super.x = f;
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+>f : Symbol(f, Decl(asyncMethodWithSuper_es5.ts, 23, 13))
+
+        // element access (assign)
+        super["x"] = f;
+>super : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+>f : Symbol(f, Decl(asyncMethodWithSuper_es5.ts, 23, 13))
+
+        // destructuring assign with property access
+        ({ f: super.x } = { f });
+>f : Symbol(f, Decl(asyncMethodWithSuper_es5.ts, 44, 10))
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+>f : Symbol(f, Decl(asyncMethodWithSuper_es5.ts, 44, 27))
+
+        // destructuring assign with element access
+        ({ f: super["x"] } = { f });
+>f : Symbol(f, Decl(asyncMethodWithSuper_es5.ts, 47, 10))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es5.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es5.ts, 0, 9))
+>f : Symbol(f, Decl(asyncMethodWithSuper_es5.ts, 47, 30))
+    }
+}
diff --git a/tests/baselines/reference/asyncMethodWithSuper_es5.types b/tests/baselines/reference/asyncMethodWithSuper_es5.types
new file mode 100644
index 0000000000000..4d14528409cf6
--- /dev/null
+++ b/tests/baselines/reference/asyncMethodWithSuper_es5.types
@@ -0,0 +1,123 @@
+=== tests/cases/conformance/async/es5/asyncMethodWithSuper_es5.ts ===
+class A {
+>A : A
+
+    x() {
+>x : () => void
+    }
+}
+
+class B extends A {
+>B : B
+>A : A
+
+    // async method with only call/get on 'super' does not require a binding
+    async simple() {
+>simple : () => Promise<void>
+
+        // call with property access
+        super.x();
+>super.x() : void
+>super.x : () => void
+>super : A
+>x : () => void
+
+        // call with element access
+        super["x"]();
+>super["x"]() : void
+>super["x"] : () => void
+>super : A
+>"x" : string
+
+        // property access (read)
+        const a = super.x;
+>a : () => void
+>super.x : () => void
+>super : A
+>x : () => void
+
+        // element access (read)
+        const b = super["x"];
+>b : () => void
+>super["x"] : () => void
+>super : A
+>"x" : string
+    }
+
+    // async method with assignment/destructuring on 'super' requires a binding
+    async advanced() {
+>advanced : () => Promise<void>
+
+        const f = () => {};
+>f : () => void
+>() => {} : () => void
+
+        // call with property access
+        super.x();
+>super.x() : void
+>super.x : () => void
+>super : A
+>x : () => void
+
+        // call with element access
+        super["x"]();
+>super["x"]() : void
+>super["x"] : () => void
+>super : A
+>"x" : string
+
+        // property access (read)
+        const a = super.x;
+>a : () => void
+>super.x : () => void
+>super : A
+>x : () => void
+
+        // element access (read)
+        const b = super["x"];
+>b : () => void
+>super["x"] : () => void
+>super : A
+>"x" : string
+
+        // property access (assign)
+        super.x = f;
+>super.x = f : () => void
+>super.x : () => void
+>super : A
+>x : () => void
+>f : () => void
+
+        // element access (assign)
+        super["x"] = f;
+>super["x"] = f : () => void
+>super["x"] : () => void
+>super : A
+>"x" : string
+>f : () => void
+
+        // destructuring assign with property access
+        ({ f: super.x } = { f });
+>({ f: super.x } = { f }) : { f: () => void; }
+>{ f: super.x } = { f } : { f: () => void; }
+>{ f: super.x } : { f: () => void; }
+>f : () => void
+>super.x : () => void
+>super : A
+>x : () => void
+>{ f } : { f: () => void; }
+>f : () => void
+
+        // destructuring assign with element access
+        ({ f: super["x"] } = { f });
+>({ f: super["x"] } = { f }) : { f: () => void; }
+>{ f: super["x"] } = { f } : { f: () => void; }
+>{ f: super["x"] } : { f: () => void; }
+>f : () => void
+>super["x"] : () => void
+>super : A
+>"x" : string
+>{ f } : { f: () => void; }
+>f : () => void
+    }
+}
diff --git a/tests/baselines/reference/asyncModule_es5.errors.txt b/tests/baselines/reference/asyncModule_es5.errors.txt
new file mode 100644
index 0000000000000..f3f1b58828867
--- /dev/null
+++ b/tests/baselines/reference/asyncModule_es5.errors.txt
@@ -0,0 +1,8 @@
+tests/cases/conformance/async/es5/asyncModule_es5.ts(1,1): error TS1042: 'async' modifier cannot be used here.
+
+
+==== tests/cases/conformance/async/es5/asyncModule_es5.ts (1 errors) ====
+    async module M {
+    ~~~~~
+!!! error TS1042: 'async' modifier cannot be used here.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncModule_es5.js b/tests/baselines/reference/asyncModule_es5.js
new file mode 100644
index 0000000000000..a36356463309e
--- /dev/null
+++ b/tests/baselines/reference/asyncModule_es5.js
@@ -0,0 +1,5 @@
+//// [asyncModule_es5.ts]
+async module M {
+}
+
+//// [asyncModule_es5.js]
diff --git a/tests/baselines/reference/asyncMultiFile_es5.js b/tests/baselines/reference/asyncMultiFile_es5.js
new file mode 100644
index 0000000000000..197127c5f1024
--- /dev/null
+++ b/tests/baselines/reference/asyncMultiFile_es5.js
@@ -0,0 +1,60 @@
+//// [tests/cases/conformance/async/es5/asyncMultiFile_es5.ts] ////
+
+//// [a.ts]
+async function f() {}
+//// [b.ts]
+function g() { }
+
+//// [a.js]
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments)).next());
+    });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+    var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
+    function step(op) {
+        if (f) throw new TypeError("Generator is already executing.");
+        while (1) {
+            if (_.done) switch (op[0]) {
+                case 0: return { value: void 0, done: true };
+                case 1: case 6: throw op[1];
+                case 2: return { value: op[1], done: true };
+            }
+            try {
+                switch (f = 1, op[0]) {
+                    case 0: case 1: sent = op; break;
+                    case 4: return _.label++, { value: op[1], done: false };
+                    case 7: op = _.stack.pop(), _.trys.pop(); continue;
+                    default:
+                        var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
+                        if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; }
+                        if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; }
+                        if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; }
+                        if (r && _.label < r[2]) { _.label = r[2], _.stack.push(op); break; }
+                        if (r[2]) { _.stack.pop(); }
+                        _.trys.pop();
+                        continue;
+                }
+                op = body.call(thisArg, _);
+            }
+            catch (e) { op = [6, e]; }
+            finally { f = 0, sent = void 0; }
+        }
+    }
+    return {
+        next: function (v) { return step([0, v]); },
+        "throw": function (v) { return step([1, v]); },
+        "return": function (v) { return step([2, v]); }
+    };
+};
+function f() {
+    return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
+        return [2 /*return*/];
+    }); });
+}
+//// [b.js]
+function g() { }
diff --git a/tests/baselines/reference/asyncMultiFile_es5.symbols b/tests/baselines/reference/asyncMultiFile_es5.symbols
new file mode 100644
index 0000000000000..e8e5bf2850e84
--- /dev/null
+++ b/tests/baselines/reference/asyncMultiFile_es5.symbols
@@ -0,0 +1,8 @@
+=== tests/cases/conformance/async/es5/a.ts ===
+async function f() {}
+>f : Symbol(f, Decl(a.ts, 0, 0))
+
+=== tests/cases/conformance/async/es5/b.ts ===
+function g() { }
+>g : Symbol(g, Decl(b.ts, 0, 0))
+
diff --git a/tests/baselines/reference/asyncMultiFile_es5.types b/tests/baselines/reference/asyncMultiFile_es5.types
new file mode 100644
index 0000000000000..52ca4f49e813b
--- /dev/null
+++ b/tests/baselines/reference/asyncMultiFile_es5.types
@@ -0,0 +1,8 @@
+=== tests/cases/conformance/async/es5/a.ts ===
+async function f() {}
+>f : () => Promise<void>
+
+=== tests/cases/conformance/async/es5/b.ts ===
+function g() { }
+>g : () => void
+
diff --git a/tests/baselines/reference/asyncQualifiedReturnType_es5.js b/tests/baselines/reference/asyncQualifiedReturnType_es5.js
new file mode 100644
index 0000000000000..19de38325e2cc
--- /dev/null
+++ b/tests/baselines/reference/asyncQualifiedReturnType_es5.js
@@ -0,0 +1,28 @@
+//// [asyncQualifiedReturnType_es5.ts]
+namespace X {
+    export class MyPromise<T> extends Promise<T> {
+    }
+}
+
+async function f(): X.MyPromise<void> {
+}
+
+//// [asyncQualifiedReturnType_es5.js]
+var X;
+(function (X) {
+    var MyPromise = (function (_super) {
+        __extends(MyPromise, _super);
+        function MyPromise() {
+            _super.apply(this, arguments);
+        }
+        return MyPromise;
+    }(Promise));
+    X.MyPromise = MyPromise;
+})(X || (X = {}));
+function f() {
+    return __awaiter(this, void 0, X.MyPromise, function () {
+        return __generator(this, function (_a) {
+            return [2 /*return*/];
+        });
+    });
+}
diff --git a/tests/baselines/reference/asyncQualifiedReturnType_es5.symbols b/tests/baselines/reference/asyncQualifiedReturnType_es5.symbols
new file mode 100644
index 0000000000000..1fcc5d4e60904
--- /dev/null
+++ b/tests/baselines/reference/asyncQualifiedReturnType_es5.symbols
@@ -0,0 +1,17 @@
+=== tests/cases/conformance/async/es5/asyncQualifiedReturnType_es5.ts ===
+namespace X {
+>X : Symbol(X, Decl(asyncQualifiedReturnType_es5.ts, 0, 0))
+
+    export class MyPromise<T> extends Promise<T> {
+>MyPromise : Symbol(MyPromise, Decl(asyncQualifiedReturnType_es5.ts, 0, 13))
+>T : Symbol(T, Decl(asyncQualifiedReturnType_es5.ts, 1, 27))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>T : Symbol(T, Decl(asyncQualifiedReturnType_es5.ts, 1, 27))
+    }
+}
+
+async function f(): X.MyPromise<void> {
+>f : Symbol(f, Decl(asyncQualifiedReturnType_es5.ts, 3, 1))
+>X : Symbol(X, Decl(asyncQualifiedReturnType_es5.ts, 0, 0))
+>MyPromise : Symbol(X.MyPromise, Decl(asyncQualifiedReturnType_es5.ts, 0, 13))
+}
diff --git a/tests/baselines/reference/asyncQualifiedReturnType_es5.types b/tests/baselines/reference/asyncQualifiedReturnType_es5.types
new file mode 100644
index 0000000000000..2fccf45f2a4ff
--- /dev/null
+++ b/tests/baselines/reference/asyncQualifiedReturnType_es5.types
@@ -0,0 +1,17 @@
+=== tests/cases/conformance/async/es5/asyncQualifiedReturnType_es5.ts ===
+namespace X {
+>X : typeof X
+
+    export class MyPromise<T> extends Promise<T> {
+>MyPromise : MyPromise<T>
+>T : T
+>Promise : Promise<T>
+>T : T
+    }
+}
+
+async function f(): X.MyPromise<void> {
+>f : () => X.MyPromise<void>
+>X : any
+>MyPromise : X.MyPromise<T>
+}
diff --git a/tests/baselines/reference/asyncSetter_es5.errors.txt b/tests/baselines/reference/asyncSetter_es5.errors.txt
new file mode 100644
index 0000000000000..59557ec9313fc
--- /dev/null
+++ b/tests/baselines/reference/asyncSetter_es5.errors.txt
@@ -0,0 +1,10 @@
+tests/cases/conformance/async/es5/asyncSetter_es5.ts(2,3): error TS1042: 'async' modifier cannot be used here.
+
+
+==== tests/cases/conformance/async/es5/asyncSetter_es5.ts (1 errors) ====
+    class C {
+      async set foo(value) {
+      ~~~~~
+!!! error TS1042: 'async' modifier cannot be used here.
+      }
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncSetter_es5.js b/tests/baselines/reference/asyncSetter_es5.js
new file mode 100644
index 0000000000000..a260ae67bd1b4
--- /dev/null
+++ b/tests/baselines/reference/asyncSetter_es5.js
@@ -0,0 +1,18 @@
+//// [asyncSetter_es5.ts]
+class C {
+  async set foo(value) {
+  }
+}
+
+//// [asyncSetter_es5.js]
+var C = (function () {
+    function C() {
+    }
+    Object.defineProperty(C.prototype, "foo", {
+        set: function (value) {
+        },
+        enumerable: true,
+        configurable: true
+    });
+    return C;
+}());
diff --git a/tests/baselines/reference/asyncUseStrict_es5.js b/tests/baselines/reference/asyncUseStrict_es5.js
new file mode 100644
index 0000000000000..0a1b61b96d8aa
--- /dev/null
+++ b/tests/baselines/reference/asyncUseStrict_es5.js
@@ -0,0 +1,23 @@
+//// [asyncUseStrict_es5.ts]
+declare var a: boolean;
+declare var p: Promise<boolean>;
+async function func(): Promise<void> {
+    "use strict";
+    var b = await p || a;
+}
+
+//// [asyncUseStrict_es5.js]
+function func() {
+    "use strict";
+    return __awaiter(this, void 0, void 0, function () {
+        var b;
+        return __generator(this, function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, p];
+                case 1:
+                    b = (_a.sent()) || a;
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/asyncUseStrict_es5.symbols b/tests/baselines/reference/asyncUseStrict_es5.symbols
new file mode 100644
index 0000000000000..a70f3ca546ab5
--- /dev/null
+++ b/tests/baselines/reference/asyncUseStrict_es5.symbols
@@ -0,0 +1,18 @@
+=== tests/cases/conformance/async/es5/asyncUseStrict_es5.ts ===
+declare var a: boolean;
+>a : Symbol(a, Decl(asyncUseStrict_es5.ts, 0, 11))
+
+declare var p: Promise<boolean>;
+>p : Symbol(p, Decl(asyncUseStrict_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(asyncUseStrict_es5.ts, 1, 32))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    "use strict";
+    var b = await p || a;
+>b : Symbol(b, Decl(asyncUseStrict_es5.ts, 4, 7))
+>p : Symbol(p, Decl(asyncUseStrict_es5.ts, 1, 11))
+>a : Symbol(a, Decl(asyncUseStrict_es5.ts, 0, 11))
+}
diff --git a/tests/baselines/reference/asyncUseStrict_es5.types b/tests/baselines/reference/asyncUseStrict_es5.types
new file mode 100644
index 0000000000000..c7eafb3433c5e
--- /dev/null
+++ b/tests/baselines/reference/asyncUseStrict_es5.types
@@ -0,0 +1,22 @@
+=== tests/cases/conformance/async/es5/asyncUseStrict_es5.ts ===
+declare var a: boolean;
+>a : boolean
+
+declare var p: Promise<boolean>;
+>p : Promise<boolean>
+>Promise : Promise<T>
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    "use strict";
+>"use strict" : string
+
+    var b = await p || a;
+>b : boolean
+>await p || a : boolean
+>await p : boolean
+>p : Promise<boolean>
+>a : boolean
+}
diff --git a/tests/baselines/reference/awaitBinaryExpression1_es5.js b/tests/baselines/reference/awaitBinaryExpression1_es5.js
index c0202d41dad78..41b090d2c4636 100644
--- a/tests/baselines/reference/awaitBinaryExpression1_es5.js
+++ b/tests/baselines/reference/awaitBinaryExpression1_es5.js
@@ -11,9 +11,9 @@ async function func(): Promise<void> {
 
 //// [awaitBinaryExpression1_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var b;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     before();
diff --git a/tests/baselines/reference/awaitBinaryExpression2_es5.js b/tests/baselines/reference/awaitBinaryExpression2_es5.js
index 8484a9a3268de..dd84d069c27f8 100644
--- a/tests/baselines/reference/awaitBinaryExpression2_es5.js
+++ b/tests/baselines/reference/awaitBinaryExpression2_es5.js
@@ -11,9 +11,9 @@ async function func(): Promise<void> {
 
 //// [awaitBinaryExpression2_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var b;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     before();
diff --git a/tests/baselines/reference/awaitBinaryExpression3_es5.js b/tests/baselines/reference/awaitBinaryExpression3_es5.js
index 3403749814a19..0c301dec2c8ca 100644
--- a/tests/baselines/reference/awaitBinaryExpression3_es5.js
+++ b/tests/baselines/reference/awaitBinaryExpression3_es5.js
@@ -11,9 +11,9 @@ async function func(): Promise<void> {
 
 //// [awaitBinaryExpression3_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var b;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     before();
diff --git a/tests/baselines/reference/awaitBinaryExpression4_es5.js b/tests/baselines/reference/awaitBinaryExpression4_es5.js
index 6a67eefac3355..26c0e5de5f1fa 100644
--- a/tests/baselines/reference/awaitBinaryExpression4_es5.js
+++ b/tests/baselines/reference/awaitBinaryExpression4_es5.js
@@ -11,9 +11,9 @@ async function func(): Promise<void> {
 
 //// [awaitBinaryExpression4_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var b;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     before();
diff --git a/tests/baselines/reference/awaitBinaryExpression5_es5.js b/tests/baselines/reference/awaitBinaryExpression5_es5.js
index 5064e72bd5ee2..4e07e40a174f4 100644
--- a/tests/baselines/reference/awaitBinaryExpression5_es5.js
+++ b/tests/baselines/reference/awaitBinaryExpression5_es5.js
@@ -12,9 +12,9 @@ async function func(): Promise<void> {
 
 //// [awaitBinaryExpression5_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var o, _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     before();
diff --git a/tests/baselines/reference/awaitCallExpression1_es5.js b/tests/baselines/reference/awaitCallExpression1_es5.js
index d1f1a5ea7b1da..dfc0e2cbd8494 100644
--- a/tests/baselines/reference/awaitCallExpression1_es5.js
+++ b/tests/baselines/reference/awaitCallExpression1_es5.js
@@ -15,9 +15,9 @@ async function func(): Promise<void> {
 
 //// [awaitCallExpression1_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var b;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             before();
             b = fn(a, a, a);
             after();
diff --git a/tests/baselines/reference/awaitCallExpression2_es5.js b/tests/baselines/reference/awaitCallExpression2_es5.js
index 399dead0084ec..6b0d6e4b648f7 100644
--- a/tests/baselines/reference/awaitCallExpression2_es5.js
+++ b/tests/baselines/reference/awaitCallExpression2_es5.js
@@ -15,9 +15,9 @@ async function func(): Promise<void> {
 
 //// [awaitCallExpression2_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var b, _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     before();
diff --git a/tests/baselines/reference/awaitCallExpression3_es5.js b/tests/baselines/reference/awaitCallExpression3_es5.js
index 5b14075a3731b..685616b23dd1b 100644
--- a/tests/baselines/reference/awaitCallExpression3_es5.js
+++ b/tests/baselines/reference/awaitCallExpression3_es5.js
@@ -15,9 +15,9 @@ async function func(): Promise<void> {
 
 //// [awaitCallExpression3_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var b, _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     before();
diff --git a/tests/baselines/reference/awaitCallExpression4_es5.js b/tests/baselines/reference/awaitCallExpression4_es5.js
index 8202598b82831..88c3cea35bd0d 100644
--- a/tests/baselines/reference/awaitCallExpression4_es5.js
+++ b/tests/baselines/reference/awaitCallExpression4_es5.js
@@ -15,9 +15,9 @@ async function func(): Promise<void> {
 
 //// [awaitCallExpression4_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var b;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     before();
diff --git a/tests/baselines/reference/awaitCallExpression5_es5.js b/tests/baselines/reference/awaitCallExpression5_es5.js
index 387dabc1df3e3..72c0e200c8d1f 100644
--- a/tests/baselines/reference/awaitCallExpression5_es5.js
+++ b/tests/baselines/reference/awaitCallExpression5_es5.js
@@ -15,9 +15,9 @@ async function func(): Promise<void> {
 
 //// [awaitCallExpression5_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var b;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             before();
             b = o.fn(a, a, a);
             after();
diff --git a/tests/baselines/reference/awaitCallExpression6_es5.js b/tests/baselines/reference/awaitCallExpression6_es5.js
index 3c2910135e794..acc4261eacbb2 100644
--- a/tests/baselines/reference/awaitCallExpression6_es5.js
+++ b/tests/baselines/reference/awaitCallExpression6_es5.js
@@ -15,9 +15,9 @@ async function func(): Promise<void> {
 
 //// [awaitCallExpression6_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var b, _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     before();
diff --git a/tests/baselines/reference/awaitCallExpression7_es5.js b/tests/baselines/reference/awaitCallExpression7_es5.js
index 0f3056e48fa7e..dd69abc051417 100644
--- a/tests/baselines/reference/awaitCallExpression7_es5.js
+++ b/tests/baselines/reference/awaitCallExpression7_es5.js
@@ -15,9 +15,9 @@ async function func(): Promise<void> {
 
 //// [awaitCallExpression7_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var b, _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     before();
diff --git a/tests/baselines/reference/awaitCallExpression8_es5.js b/tests/baselines/reference/awaitCallExpression8_es5.js
index bcb7a7f8d7b87..6d7d5dceba96d 100644
--- a/tests/baselines/reference/awaitCallExpression8_es5.js
+++ b/tests/baselines/reference/awaitCallExpression8_es5.js
@@ -15,9 +15,9 @@ async function func(): Promise<void> {
 
 //// [awaitCallExpression8_es5.js]
 function func() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var b;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     before();
diff --git a/tests/baselines/reference/awaitClassExpression_es5.js b/tests/baselines/reference/awaitClassExpression_es5.js
new file mode 100644
index 0000000000000..9123f5f2ea86a
--- /dev/null
+++ b/tests/baselines/reference/awaitClassExpression_es5.js
@@ -0,0 +1,31 @@
+//// [awaitClassExpression_es5.ts]
+declare class C { }
+declare var p: Promise<typeof C>;
+
+async function func(): Promise<void> {
+    class D extends (await p) {
+    }
+}
+
+//// [awaitClassExpression_es5.js]
+function func() {
+    return __awaiter(this, void 0, void 0, function () {
+        var D, _a, _b;
+        return __generator(this, function (_c) {
+            switch (_c.label) {
+                case 0:
+                    _a = function (_super) {
+                        __extends(D, _super);
+                        function D() {
+                            _super.apply(this, arguments);
+                        }
+                        return D;
+                    };
+                    return [4 /*yield*/, p];
+                case 1:
+                    D = (_a.apply(void 0, [(_c.sent())]));
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitClassExpression_es5.symbols b/tests/baselines/reference/awaitClassExpression_es5.symbols
new file mode 100644
index 0000000000000..1f550576c0983
--- /dev/null
+++ b/tests/baselines/reference/awaitClassExpression_es5.symbols
@@ -0,0 +1,18 @@
+=== tests/cases/conformance/async/es5/awaitClassExpression_es5.ts ===
+declare class C { }
+>C : Symbol(C, Decl(awaitClassExpression_es5.ts, 0, 0))
+
+declare var p: Promise<typeof C>;
+>p : Symbol(p, Decl(awaitClassExpression_es5.ts, 1, 11))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+>C : Symbol(C, Decl(awaitClassExpression_es5.ts, 0, 0))
+
+async function func(): Promise<void> {
+>func : Symbol(func, Decl(awaitClassExpression_es5.ts, 1, 33))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+    class D extends (await p) {
+>D : Symbol(D, Decl(awaitClassExpression_es5.ts, 3, 38))
+>p : Symbol(p, Decl(awaitClassExpression_es5.ts, 1, 11))
+    }
+}
diff --git a/tests/baselines/reference/awaitClassExpression_es5.types b/tests/baselines/reference/awaitClassExpression_es5.types
new file mode 100644
index 0000000000000..e1f4bf8f82eb2
--- /dev/null
+++ b/tests/baselines/reference/awaitClassExpression_es5.types
@@ -0,0 +1,20 @@
+=== tests/cases/conformance/async/es5/awaitClassExpression_es5.ts ===
+declare class C { }
+>C : C
+
+declare var p: Promise<typeof C>;
+>p : Promise<typeof C>
+>Promise : Promise<T>
+>C : typeof C
+
+async function func(): Promise<void> {
+>func : () => Promise<void>
+>Promise : Promise<T>
+
+    class D extends (await p) {
+>D : D
+>(await p) : C
+>await p : typeof C
+>p : Promise<typeof C>
+    }
+}
diff --git a/tests/baselines/reference/awaitUnion_es5.js b/tests/baselines/reference/awaitUnion_es5.js
new file mode 100644
index 0000000000000..e4ebaa4f62ec4
--- /dev/null
+++ b/tests/baselines/reference/awaitUnion_es5.js
@@ -0,0 +1,40 @@
+//// [awaitUnion_es5.ts]
+declare let a: number | string;
+declare let b: PromiseLike<number> | PromiseLike<string>;
+declare let c: PromiseLike<number | string>;
+declare let d: number | PromiseLike<string>;
+declare let e: number | PromiseLike<number | string>;
+async function f() {
+	let await_a = await a;
+	let await_b = await b;
+	let await_c = await c;
+	let await_d = await d;
+	let await_e = await e;
+}
+
+//// [awaitUnion_es5.js]
+function f() {
+    return __awaiter(this, void 0, void 0, function () {
+        var await_a, await_b, await_c, await_d, await_e;
+        return __generator(this, function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, a];
+                case 1:
+                    await_a = _a.sent();
+                    return [4 /*yield*/, b];
+                case 2:
+                    await_b = _a.sent();
+                    return [4 /*yield*/, c];
+                case 3:
+                    await_c = _a.sent();
+                    return [4 /*yield*/, d];
+                case 4:
+                    await_d = _a.sent();
+                    return [4 /*yield*/, e];
+                case 5:
+                    await_e = _a.sent();
+                    return [2 /*return*/];
+            }
+        });
+    });
+}
diff --git a/tests/baselines/reference/awaitUnion_es5.symbols b/tests/baselines/reference/awaitUnion_es5.symbols
new file mode 100644
index 0000000000000..b8fb6dbed38f7
--- /dev/null
+++ b/tests/baselines/reference/awaitUnion_es5.symbols
@@ -0,0 +1,44 @@
+=== tests/cases/conformance/async/es5/awaitUnion_es5.ts ===
+declare let a: number | string;
+>a : Symbol(a, Decl(awaitUnion_es5.ts, 0, 11))
+
+declare let b: PromiseLike<number> | PromiseLike<string>;
+>b : Symbol(b, Decl(awaitUnion_es5.ts, 1, 11))
+>PromiseLike : Symbol(PromiseLike, Decl(lib.es5.d.ts, --, --))
+>PromiseLike : Symbol(PromiseLike, Decl(lib.es5.d.ts, --, --))
+
+declare let c: PromiseLike<number | string>;
+>c : Symbol(c, Decl(awaitUnion_es5.ts, 2, 11))
+>PromiseLike : Symbol(PromiseLike, Decl(lib.es5.d.ts, --, --))
+
+declare let d: number | PromiseLike<string>;
+>d : Symbol(d, Decl(awaitUnion_es5.ts, 3, 11))
+>PromiseLike : Symbol(PromiseLike, Decl(lib.es5.d.ts, --, --))
+
+declare let e: number | PromiseLike<number | string>;
+>e : Symbol(e, Decl(awaitUnion_es5.ts, 4, 11))
+>PromiseLike : Symbol(PromiseLike, Decl(lib.es5.d.ts, --, --))
+
+async function f() {
+>f : Symbol(f, Decl(awaitUnion_es5.ts, 4, 53))
+
+	let await_a = await a;
+>await_a : Symbol(await_a, Decl(awaitUnion_es5.ts, 6, 4))
+>a : Symbol(a, Decl(awaitUnion_es5.ts, 0, 11))
+
+	let await_b = await b;
+>await_b : Symbol(await_b, Decl(awaitUnion_es5.ts, 7, 4))
+>b : Symbol(b, Decl(awaitUnion_es5.ts, 1, 11))
+
+	let await_c = await c;
+>await_c : Symbol(await_c, Decl(awaitUnion_es5.ts, 8, 4))
+>c : Symbol(c, Decl(awaitUnion_es5.ts, 2, 11))
+
+	let await_d = await d;
+>await_d : Symbol(await_d, Decl(awaitUnion_es5.ts, 9, 4))
+>d : Symbol(d, Decl(awaitUnion_es5.ts, 3, 11))
+
+	let await_e = await e;
+>await_e : Symbol(await_e, Decl(awaitUnion_es5.ts, 10, 4))
+>e : Symbol(e, Decl(awaitUnion_es5.ts, 4, 11))
+}
diff --git a/tests/baselines/reference/awaitUnion_es5.types b/tests/baselines/reference/awaitUnion_es5.types
new file mode 100644
index 0000000000000..fa68780e72d2e
--- /dev/null
+++ b/tests/baselines/reference/awaitUnion_es5.types
@@ -0,0 +1,49 @@
+=== tests/cases/conformance/async/es5/awaitUnion_es5.ts ===
+declare let a: number | string;
+>a : number | string
+
+declare let b: PromiseLike<number> | PromiseLike<string>;
+>b : PromiseLike<number> | PromiseLike<string>
+>PromiseLike : PromiseLike<T>
+>PromiseLike : PromiseLike<T>
+
+declare let c: PromiseLike<number | string>;
+>c : PromiseLike<number | string>
+>PromiseLike : PromiseLike<T>
+
+declare let d: number | PromiseLike<string>;
+>d : number | PromiseLike<string>
+>PromiseLike : PromiseLike<T>
+
+declare let e: number | PromiseLike<number | string>;
+>e : number | PromiseLike<number | string>
+>PromiseLike : PromiseLike<T>
+
+async function f() {
+>f : () => Promise<void>
+
+	let await_a = await a;
+>await_a : number | string
+>await a : number | string
+>a : number | string
+
+	let await_b = await b;
+>await_b : number | string
+>await b : number | string
+>b : PromiseLike<number> | PromiseLike<string>
+
+	let await_c = await c;
+>await_c : number | string
+>await c : number | string
+>c : PromiseLike<number | string>
+
+	let await_d = await d;
+>await_d : number | string
+>await d : number | string
+>d : number | PromiseLike<string>
+
+	let await_e = await e;
+>await_e : number | string
+>await e : number | string
+>e : number | PromiseLike<number | string>
+}
diff --git a/tests/baselines/reference/es5-asyncFunction.js b/tests/baselines/reference/es5-asyncFunction.js
index 57c9a7c05f67f..9cb6f1d367443 100644
--- a/tests/baselines/reference/es5-asyncFunction.js
+++ b/tests/baselines/reference/es5-asyncFunction.js
@@ -17,7 +17,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
         step((generator = generator.apply(thisArg, _arguments)).next());
     });
 };
-var __generator = (this && this.__generator) || function (body) {
+var __generator = (this && this.__generator) || function (thisArg, body) {
     var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
     function step(op) {
         if (f) throw new TypeError("Generator is already executing.");
@@ -42,7 +42,7 @@ var __generator = (this && this.__generator) || function (body) {
                         _.trys.pop();
                         continue;
                 }
-                op = body(_);
+                op = body.call(thisArg, _);
             }
             catch (e) { op = [6, e]; }
             finally { f = 0, sent = void 0; }
@@ -56,14 +56,14 @@ var __generator = (this && this.__generator) || function (body) {
 };
 function empty() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             return [2 /*return*/];
         });
     });
 }
 function singleAwait() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
diff --git a/tests/baselines/reference/es5-asyncFunctionArrayLiterals.js b/tests/baselines/reference/es5-asyncFunctionArrayLiterals.js
index 936e530ee2bed..c8a4733aa94f6 100644
--- a/tests/baselines/reference/es5-asyncFunctionArrayLiterals.js
+++ b/tests/baselines/reference/es5-asyncFunctionArrayLiterals.js
@@ -37,7 +37,7 @@ async function arrayLiteral7() {
 function arrayLiteral0() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0: return [4 /*yield*/, y];
                 case 1:
@@ -50,7 +50,7 @@ function arrayLiteral0() {
 function arrayLiteral1() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = [y];
@@ -64,7 +64,7 @@ function arrayLiteral1() {
 }
 function arrayLiteral2() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, y];
                 case 1:
@@ -77,7 +77,7 @@ function arrayLiteral2() {
 function arrayLiteral3() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c, _d;
-        return __generator(function (_e) {
+        return __generator(this, function (_e) {
             switch (_e.label) {
                 case 0:
                     _b = (_a = y).concat;
@@ -92,7 +92,7 @@ function arrayLiteral3() {
 function arrayLiteral4() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0: return [4 /*yield*/, y];
                 case 1:
@@ -105,7 +105,7 @@ function arrayLiteral4() {
 function arrayLiteral5() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     _b = (_a = [y]).concat;
@@ -120,7 +120,7 @@ function arrayLiteral5() {
 function arrayLiteral6() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = [y];
@@ -135,7 +135,7 @@ function arrayLiteral6() {
 function arrayLiteral7() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0: return [4 /*yield*/, y];
                 case 1:
diff --git a/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.js b/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.js
index 936ca033954f8..a7aff63025603 100644
--- a/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.js
+++ b/tests/baselines/reference/es5-asyncFunctionBinaryExpressions.js
@@ -125,7 +125,7 @@ async function binaryComma1(): Promise<any> {
 //// [es5-asyncFunctionBinaryExpressions.js]
 function binaryPlus0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -138,7 +138,7 @@ function binaryPlus0() {
 function binaryPlus1() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -152,7 +152,7 @@ function binaryPlus1() {
 }
 function binaryLogicalAnd0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -165,7 +165,7 @@ function binaryLogicalAnd0() {
 function binaryLogicalAnd1() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -184,7 +184,7 @@ function binaryLogicalAnd1() {
 }
 function binaryAssignment0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, y];
                 case 1:
@@ -197,7 +197,7 @@ function binaryAssignment0() {
 function binaryAssignment1() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -212,7 +212,7 @@ function binaryAssignment1() {
 function binaryAssignment2() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x.a;
@@ -227,7 +227,7 @@ function binaryAssignment2() {
 function binaryAssignment3() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = x;
@@ -243,7 +243,7 @@ function binaryAssignment3() {
 function binaryAssignment4() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x[z];
@@ -258,7 +258,7 @@ function binaryAssignment4() {
 function binaryAssignment5() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = x.a;
@@ -273,7 +273,7 @@ function binaryAssignment5() {
 }
 function binaryAssignment6() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -285,7 +285,7 @@ function binaryAssignment6() {
 }
 function binaryAssignment7() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x.a];
                 case 1:
@@ -297,7 +297,7 @@ function binaryAssignment7() {
 }
 function binaryAssignment8() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -310,7 +310,7 @@ function binaryAssignment8() {
 function binaryAssignment9() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -325,7 +325,7 @@ function binaryAssignment9() {
 function binaryAssignment10() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -339,7 +339,7 @@ function binaryAssignment10() {
 }
 function binaryAssignment11() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x[z]];
                 case 1:
@@ -352,7 +352,7 @@ function binaryAssignment11() {
 function binaryAssignment12() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x.a;
@@ -366,7 +366,7 @@ function binaryAssignment12() {
 }
 function binaryAssignment13() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x.a];
                 case 1:
@@ -379,7 +379,7 @@ function binaryAssignment13() {
 function binaryCompoundAssignment0() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -394,7 +394,7 @@ function binaryCompoundAssignment0() {
 function binaryCompoundAssignment1() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = x;
@@ -410,7 +410,7 @@ function binaryCompoundAssignment1() {
 function binaryCompoundAssignment2() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     _a = x;
@@ -426,7 +426,7 @@ function binaryCompoundAssignment2() {
 }
 function binaryCompoundAssignment3() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -438,7 +438,7 @@ function binaryCompoundAssignment3() {
 }
 function binaryCompoundAssignment4() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -451,7 +451,7 @@ function binaryCompoundAssignment4() {
 function binaryCompoundAssignment5() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -466,7 +466,7 @@ function binaryCompoundAssignment5() {
 function binaryCompoundAssignment6() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -483,7 +483,7 @@ function binaryCompoundAssignment6() {
 function binaryCompoundAssignment7() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -501,7 +501,7 @@ function binaryCompoundAssignment7() {
 function binaryCompoundAssignment8() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     _a = x;
@@ -520,7 +520,7 @@ function binaryCompoundAssignment8() {
 function binaryExponentiation() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c, _d, _e, _f;
-        return __generator(function (_g) {
+        return __generator(this, function (_g) {
             switch (_g.label) {
                 case 0:
                     _b = (_a = Math).pow;
@@ -539,7 +539,7 @@ function binaryExponentiation() {
 }
 function binaryComma0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1: return [2 /*return*/, ((_a.sent()), y)];
@@ -548,8 +548,8 @@ function binaryComma0() {
     });
 }
 function binaryComma1() {
-    return __awaiter(this, void 0, Promise, function () {
-        return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     x;
diff --git a/tests/baselines/reference/es5-asyncFunctionCallExpressions.js b/tests/baselines/reference/es5-asyncFunctionCallExpressions.js
index 8f0d17e7c14c5..93c4dcfd3cbc9 100644
--- a/tests/baselines/reference/es5-asyncFunctionCallExpressions.js
+++ b/tests/baselines/reference/es5-asyncFunctionCallExpressions.js
@@ -89,7 +89,7 @@ async function callExpression20() {
 //// [es5-asyncFunctionCallExpressions.js]
 function callExpression0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x(y, z)];
                 case 1:
@@ -101,7 +101,7 @@ function callExpression0() {
 }
 function callExpression1() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -114,7 +114,7 @@ function callExpression1() {
 function callExpression2() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = x;
@@ -129,7 +129,7 @@ function callExpression2() {
 function callExpression3() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = x;
@@ -144,7 +144,7 @@ function callExpression3() {
 }
 function callExpression4() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x.apply(void 0, y.concat([z]))];
                 case 1:
@@ -156,7 +156,7 @@ function callExpression4() {
 }
 function callExpression5() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -169,7 +169,7 @@ function callExpression5() {
 function callExpression6() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     _b = (_a = x).apply;
@@ -185,7 +185,7 @@ function callExpression6() {
 function callExpression7() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c, _d, _e, _f, _g;
-        return __generator(function (_h) {
+        return __generator(this, function (_h) {
             switch (_h.label) {
                 case 0:
                     _b = (_a = x).apply;
@@ -202,7 +202,7 @@ function callExpression7() {
 function callExpression8() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c, _d;
-        return __generator(function (_e) {
+        return __generator(this, function (_e) {
             switch (_e.label) {
                 case 0:
                     _b = (_a = x).apply;
@@ -218,7 +218,7 @@ function callExpression8() {
 function callExpression9() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c, _d, _e, _f;
-        return __generator(function (_g) {
+        return __generator(this, function (_g) {
             switch (_g.label) {
                 case 0:
                     _b = (_a = x).apply;
@@ -234,7 +234,7 @@ function callExpression9() {
 }
 function callExpression10() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x.a(y, z)];
                 case 1:
@@ -246,7 +246,7 @@ function callExpression10() {
 }
 function callExpression11() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x.a];
                 case 1:
@@ -258,7 +258,7 @@ function callExpression11() {
 }
 function callExpression12() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -271,7 +271,7 @@ function callExpression12() {
 function callExpression13() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     _b = (_a = x).a;
@@ -286,7 +286,7 @@ function callExpression13() {
 function callExpression14() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     _b = (_a = x).a;
@@ -301,7 +301,7 @@ function callExpression14() {
 }
 function callExpression15() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x[a](y, z)];
                 case 1:
@@ -313,7 +313,7 @@ function callExpression15() {
 }
 function callExpression16() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x[a]];
                 case 1:
@@ -325,7 +325,7 @@ function callExpression16() {
 }
 function callExpression17() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -338,7 +338,7 @@ function callExpression17() {
 function callExpression18() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -353,7 +353,7 @@ function callExpression18() {
 function callExpression19() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     _b = (_a = x)[a];
@@ -368,7 +368,7 @@ function callExpression19() {
 function callExpression20() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     _b = (_a = x)[a];
diff --git a/tests/baselines/reference/es5-asyncFunctionConditionals.js b/tests/baselines/reference/es5-asyncFunctionConditionals.js
index f559e1f962d82..b42b0c07b0ac5 100644
--- a/tests/baselines/reference/es5-asyncFunctionConditionals.js
+++ b/tests/baselines/reference/es5-asyncFunctionConditionals.js
@@ -16,7 +16,7 @@ async function conditional2() {
 //// [es5-asyncFunctionConditionals.js]
 function conditional0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -29,7 +29,7 @@ function conditional0() {
 function conditional1() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     if (!x)
@@ -51,7 +51,7 @@ function conditional1() {
 function conditional2() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     if (!x)
diff --git a/tests/baselines/reference/es5-asyncFunctionDoStatements.js b/tests/baselines/reference/es5-asyncFunctionDoStatements.js
index f2052ab378d69..7151446dddf39 100644
--- a/tests/baselines/reference/es5-asyncFunctionDoStatements.js
+++ b/tests/baselines/reference/es5-asyncFunctionDoStatements.js
@@ -80,7 +80,7 @@ async function doStatement18() {
 //// [es5-asyncFunctionDoStatements.js]
 function doStatement0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             do {
                 x;
             } while (y);
@@ -90,7 +90,7 @@ function doStatement0() {
 }
 function doStatement1() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -107,7 +107,7 @@ function doStatement1() {
 }
 function doStatement2() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     x;
@@ -124,7 +124,7 @@ function doStatement2() {
 }
 function doStatement3() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             do {
                 continue;
             } while (y);
@@ -134,7 +134,7 @@ function doStatement3() {
 }
 function doStatement4() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -151,7 +151,7 @@ function doStatement4() {
 }
 function doStatement5() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (1)
@@ -171,7 +171,7 @@ function doStatement5() {
 }
 function doStatement6() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [3 /*break*/, 1];
                 case 1: return [4 /*yield*/, y];
@@ -186,7 +186,7 @@ function doStatement6() {
 }
 function doStatement7() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             A: do {
                 continue A;
             } while (y);
@@ -196,7 +196,7 @@ function doStatement7() {
 }
 function doStatement8() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -213,7 +213,7 @@ function doStatement8() {
 }
 function doStatement9() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (1)
@@ -233,7 +233,7 @@ function doStatement9() {
 }
 function doStatement10() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [3 /*break*/, 1];
                 case 1: return [4 /*yield*/, y];
@@ -248,7 +248,7 @@ function doStatement10() {
 }
 function doStatement11() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             do {
                 break;
             } while (y);
@@ -258,7 +258,7 @@ function doStatement11() {
 }
 function doStatement12() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -275,7 +275,7 @@ function doStatement12() {
 }
 function doStatement13() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (1)
@@ -295,7 +295,7 @@ function doStatement13() {
 }
 function doStatement14() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [3 /*break*/, 3];
                 case 1: return [4 /*yield*/, y];
@@ -310,7 +310,7 @@ function doStatement14() {
 }
 function doStatement15() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             E: do {
                 break E;
             } while (y);
@@ -320,7 +320,7 @@ function doStatement15() {
 }
 function doStatement16() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -337,7 +337,7 @@ function doStatement16() {
 }
 function doStatement17() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (1)
@@ -357,7 +357,7 @@ function doStatement17() {
 }
 function doStatement18() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [3 /*break*/, 3];
                 case 1: return [4 /*yield*/, y];
diff --git a/tests/baselines/reference/es5-asyncFunctionElementAccess.js b/tests/baselines/reference/es5-asyncFunctionElementAccess.js
index 4595cc219e9b7..56c9b54644b9c 100644
--- a/tests/baselines/reference/es5-asyncFunctionElementAccess.js
+++ b/tests/baselines/reference/es5-asyncFunctionElementAccess.js
@@ -17,7 +17,7 @@ async function elementAccess2() {
 //// [es5-asyncFunctionElementAccess.js]
 function elementAccess0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x[y]];
                 case 1:
@@ -29,7 +29,7 @@ function elementAccess0() {
 }
 function elementAccess1() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -42,7 +42,7 @@ function elementAccess1() {
 function elementAccess2() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
diff --git a/tests/baselines/reference/es5-asyncFunctionForInStatements.js b/tests/baselines/reference/es5-asyncFunctionForInStatements.js
index 4ce6e5e4a1906..30946fca56da0 100644
--- a/tests/baselines/reference/es5-asyncFunctionForInStatements.js
+++ b/tests/baselines/reference/es5-asyncFunctionForInStatements.js
@@ -40,7 +40,7 @@ async function forInStatement8() {
 //// [es5-asyncFunctionForInStatements.js]
 function forInStatement0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             for (x in y) {
                 z;
             }
@@ -51,7 +51,7 @@ function forInStatement0() {
 function forInStatement1() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _i;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = [];
@@ -78,7 +78,7 @@ function forInStatement1() {
 function forInStatement2() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _i;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = [];
@@ -105,7 +105,7 @@ function forInStatement2() {
 function forInStatement3() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _i;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = [];
@@ -132,7 +132,7 @@ function forInStatement3() {
 function forInStatement4() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _i;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = [];
@@ -159,7 +159,7 @@ function forInStatement4() {
 function forInStatement5() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _i;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = [];
@@ -186,7 +186,7 @@ function forInStatement5() {
 function forInStatement6() {
     return __awaiter(this, void 0, void 0, function () {
         var a;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             for (a in y) {
                 z;
             }
@@ -197,7 +197,7 @@ function forInStatement6() {
 function forInStatement7() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _i, b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = [];
@@ -224,7 +224,7 @@ function forInStatement7() {
 function forInStatement8() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _i, c;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = [];
diff --git a/tests/baselines/reference/es5-asyncFunctionForOfStatements.js b/tests/baselines/reference/es5-asyncFunctionForOfStatements.js
index 0d5c7753da932..e12f1e18d4415 100644
--- a/tests/baselines/reference/es5-asyncFunctionForOfStatements.js
+++ b/tests/baselines/reference/es5-asyncFunctionForOfStatements.js
@@ -81,7 +81,7 @@ async function forOfStatement18() {
 function forOfStatement0() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, y_1;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             for (_i = 0, y_1 = y; _i < y_1.length; _i++) {
                 x = y_1[_i];
                 z;
@@ -93,7 +93,7 @@ function forOfStatement0() {
 function forOfStatement1() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _i = 0;
@@ -118,7 +118,7 @@ function forOfStatement1() {
 function forOfStatement2() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, y_2;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _i = 0, y_2 = y;
@@ -142,7 +142,7 @@ function forOfStatement2() {
 function forOfStatement3() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, y_3;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _i = 0, y_3 = y;
@@ -166,7 +166,7 @@ function forOfStatement3() {
 function forOfStatement4() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _i = 0;
@@ -191,7 +191,7 @@ function forOfStatement4() {
 function forOfStatement5() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, y_4;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _i = 0, y_4 = y;
@@ -215,7 +215,7 @@ function forOfStatement5() {
 function forOfStatement6() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, y_5, b;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             for (_i = 0, y_5 = y; _i < y_5.length; _i++) {
                 b = y_5[_i];
                 z;
@@ -227,7 +227,7 @@ function forOfStatement6() {
 function forOfStatement7() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, _a, c;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _i = 0;
@@ -252,7 +252,7 @@ function forOfStatement7() {
 function forOfStatement8() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, y_6, d;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _i = 0, y_6 = y;
@@ -276,7 +276,7 @@ function forOfStatement8() {
 function forOfStatement9() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _i = 0;
@@ -301,7 +301,7 @@ function forOfStatement9() {
 function forOfStatement10() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, y_7;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _i = 0, y_7 = y;
@@ -325,7 +325,7 @@ function forOfStatement10() {
 function forOfStatement11() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, y_8, _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _i = 0, y_8 = y;
@@ -358,7 +358,7 @@ function forOfStatement11() {
 function forOfStatement12() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _i = 0;
@@ -383,7 +383,7 @@ function forOfStatement12() {
 function forOfStatement13() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, y_9, _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _i = 0, y_9 = y;
@@ -407,7 +407,7 @@ function forOfStatement13() {
 function forOfStatement14() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _i = 0;
@@ -432,7 +432,7 @@ function forOfStatement14() {
 function forOfStatement15() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, y_10;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _i = 0, y_10 = y;
@@ -456,7 +456,7 @@ function forOfStatement15() {
 function forOfStatement16() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, y_11, _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _i = 0, y_11 = y;
@@ -489,7 +489,7 @@ function forOfStatement16() {
 function forOfStatement17() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _i = 0;
@@ -514,7 +514,7 @@ function forOfStatement17() {
 function forOfStatement18() {
     return __awaiter(this, void 0, void 0, function () {
         var _i, y_12, _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _i = 0, y_12 = y;
diff --git a/tests/baselines/reference/es5-asyncFunctionForStatements.js b/tests/baselines/reference/es5-asyncFunctionForStatements.js
index bea0d5838a406..e02d20c7864aa 100644
--- a/tests/baselines/reference/es5-asyncFunctionForStatements.js
+++ b/tests/baselines/reference/es5-asyncFunctionForStatements.js
@@ -32,7 +32,7 @@ async function forStatement6() {
 //// [es5-asyncFunctionForStatements.js]
 function forStatement0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             for (x; y; z) {
                 a;
             }
@@ -42,7 +42,7 @@ function forStatement0() {
 }
 function forStatement1() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -63,7 +63,7 @@ function forStatement1() {
 }
 function forStatement2() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     x;
@@ -84,7 +84,7 @@ function forStatement2() {
 }
 function forStatement3() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     x;
@@ -105,7 +105,7 @@ function forStatement3() {
 }
 function forStatement4() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     x;
@@ -128,7 +128,7 @@ function forStatement4() {
 function forStatement5() {
     return __awaiter(this, void 0, void 0, function () {
         var b;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             for (; y; z) {
                 a;
             }
@@ -139,7 +139,7 @@ function forStatement5() {
 function forStatement6() {
     return __awaiter(this, void 0, void 0, function () {
         var c;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             for (c = x; y; z) {
                 a;
             }
diff --git a/tests/baselines/reference/es5-asyncFunctionHoisting.js b/tests/baselines/reference/es5-asyncFunctionHoisting.js
index 6dc05e65bf31c..1ee846d0126fc 100644
--- a/tests/baselines/reference/es5-asyncFunctionHoisting.js
+++ b/tests/baselines/reference/es5-asyncFunctionHoisting.js
@@ -59,7 +59,7 @@ function hoisting() {
             var b0, b1 = 1;
         }
         var a0, a1, c0, c1, a, b, _i, y_1, c;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             a1 = 1;
             if (true) {
                 c1 = 1;
@@ -81,7 +81,7 @@ function hoistingWithAwait() {
             var b0, b1 = 1;
         }
         var a0, a1, c0, c1, a, b, _i, y_2, c;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     a1 = 1;
diff --git a/tests/baselines/reference/es5-asyncFunctionIfStatements.js b/tests/baselines/reference/es5-asyncFunctionIfStatements.js
index 9f7c71a7f3f22..7ac35c995e748 100644
--- a/tests/baselines/reference/es5-asyncFunctionIfStatements.js
+++ b/tests/baselines/reference/es5-asyncFunctionIfStatements.js
@@ -16,7 +16,7 @@ async function ifStatement3() {
 //// [es5-asyncFunctionIfStatements.js]
 function ifStatement1() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -33,7 +33,7 @@ function ifStatement1() {
 }
 function ifStatement2() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (!x)
@@ -52,7 +52,7 @@ function ifStatement2() {
 }
 function ifStatement3() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (!x)
diff --git a/tests/baselines/reference/es5-asyncFunctionNestedLoops.js b/tests/baselines/reference/es5-asyncFunctionNestedLoops.js
index 3290965d6cfe8..28ccc288b7e7a 100644
--- a/tests/baselines/reference/es5-asyncFunctionNestedLoops.js
+++ b/tests/baselines/reference/es5-asyncFunctionNestedLoops.js
@@ -16,7 +16,7 @@ async function nestedLoops() {
 //// [es5-asyncFunctionNestedLoops.js]
 function nestedLoops() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (!x)
diff --git a/tests/baselines/reference/es5-asyncFunctionNewExpressions.js b/tests/baselines/reference/es5-asyncFunctionNewExpressions.js
index b7d4514d24ed0..486bf0fdd7f91 100644
--- a/tests/baselines/reference/es5-asyncFunctionNewExpressions.js
+++ b/tests/baselines/reference/es5-asyncFunctionNewExpressions.js
@@ -88,7 +88,7 @@ async function newExpression20() {
 //// [es5-asyncFunctionNewExpressions.js]
 function newExpression0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, new x(y, z)];
                 case 1:
@@ -100,7 +100,7 @@ function newExpression0() {
 }
 function newExpression1() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -113,7 +113,7 @@ function newExpression1() {
 function newExpression2() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = x.bind;
@@ -128,7 +128,7 @@ function newExpression2() {
 function newExpression3() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = x.bind;
@@ -143,7 +143,7 @@ function newExpression3() {
 }
 function newExpression4() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, new (x.bind.apply(x, [void 0].concat(y, [z])))()];
                 case 1:
@@ -156,7 +156,7 @@ function newExpression4() {
 function newExpression5() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -169,7 +169,7 @@ function newExpression5() {
 function newExpression6() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c, _d, _e, _f;
-        return __generator(function (_g) {
+        return __generator(this, function (_g) {
             switch (_g.label) {
                 case 0:
                     _b = (_a = x.bind).apply;
@@ -186,7 +186,7 @@ function newExpression6() {
 function newExpression7() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c, _d, _e, _f, _g;
-        return __generator(function (_h) {
+        return __generator(this, function (_h) {
             switch (_h.label) {
                 case 0:
                     _b = (_a = x.bind).apply;
@@ -204,7 +204,7 @@ function newExpression7() {
 function newExpression8() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c, _d;
-        return __generator(function (_e) {
+        return __generator(this, function (_e) {
             switch (_e.label) {
                 case 0:
                     _b = (_a = x.bind).apply;
@@ -221,7 +221,7 @@ function newExpression8() {
 function newExpression9() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c, _d, _e, _f;
-        return __generator(function (_g) {
+        return __generator(this, function (_g) {
             switch (_g.label) {
                 case 0:
                     _b = (_a = x.bind).apply;
@@ -237,7 +237,7 @@ function newExpression9() {
 }
 function newExpression10() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, new x.a(y, z)];
                 case 1:
@@ -249,7 +249,7 @@ function newExpression10() {
 }
 function newExpression11() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x.a];
                 case 1:
@@ -261,7 +261,7 @@ function newExpression11() {
 }
 function newExpression12() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -274,7 +274,7 @@ function newExpression12() {
 function newExpression13() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     _b = (_a = x.a).bind;
@@ -289,7 +289,7 @@ function newExpression13() {
 function newExpression14() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     _b = (_a = x.a).bind;
@@ -304,7 +304,7 @@ function newExpression14() {
 }
 function newExpression15() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, new x[a](y, z)];
                 case 1:
@@ -316,7 +316,7 @@ function newExpression15() {
 }
 function newExpression16() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x[a]];
                 case 1:
@@ -328,7 +328,7 @@ function newExpression16() {
 }
 function newExpression17() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -341,7 +341,7 @@ function newExpression17() {
 function newExpression18() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -356,7 +356,7 @@ function newExpression18() {
 function newExpression19() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     _b = (_a = x[a]).bind;
@@ -371,7 +371,7 @@ function newExpression19() {
 function newExpression20() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b, _c;
-        return __generator(function (_d) {
+        return __generator(this, function (_d) {
             switch (_d.label) {
                 case 0:
                     _b = (_a = x[a]).bind;
diff --git a/tests/baselines/reference/es5-asyncFunctionObjectLiterals.js b/tests/baselines/reference/es5-asyncFunctionObjectLiterals.js
index 1c5d1fcd23b8c..8bc90935d379a 100644
--- a/tests/baselines/reference/es5-asyncFunctionObjectLiterals.js
+++ b/tests/baselines/reference/es5-asyncFunctionObjectLiterals.js
@@ -54,7 +54,7 @@ async function objectLiteral6() {
 function objectLiteral0() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = {};
@@ -71,7 +71,7 @@ function objectLiteral0() {
 function objectLiteral1() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = {
@@ -89,7 +89,7 @@ function objectLiteral1() {
 function objectLiteral2() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = {};
@@ -106,7 +106,7 @@ function objectLiteral2() {
 function objectLiteral3() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _b = {};
@@ -124,7 +124,7 @@ function objectLiteral3() {
 function objectLiteral4() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = {};
@@ -141,7 +141,7 @@ function objectLiteral4() {
 function objectLiteral5() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = {
@@ -159,7 +159,7 @@ function objectLiteral5() {
 function objectLiteral6() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _b = {
diff --git a/tests/baselines/reference/es5-asyncFunctionPropertyAccess.js b/tests/baselines/reference/es5-asyncFunctionPropertyAccess.js
index 47110ff11bcb4..436428a76c5ed 100644
--- a/tests/baselines/reference/es5-asyncFunctionPropertyAccess.js
+++ b/tests/baselines/reference/es5-asyncFunctionPropertyAccess.js
@@ -16,7 +16,7 @@ async function callExpression0() {
 //// [es5-asyncFunctionPropertyAccess.js]
 function propertyAccess0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x.a];
                 case 1:
@@ -28,7 +28,7 @@ function propertyAccess0() {
 }
 function propertyAccess1() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -40,7 +40,7 @@ function propertyAccess1() {
 }
 function callExpression0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x(y, z)];
                 case 1:
diff --git a/tests/baselines/reference/es5-asyncFunctionReturnStatements.js b/tests/baselines/reference/es5-asyncFunctionReturnStatements.js
index df279f3680d73..7574da05a3898 100644
--- a/tests/baselines/reference/es5-asyncFunctionReturnStatements.js
+++ b/tests/baselines/reference/es5-asyncFunctionReturnStatements.js
@@ -28,22 +28,22 @@ async function returnStatement5(): Promise<any>{
 
 //// [es5-asyncFunctionReturnStatements.js]
 function returnStatement0() {
-    return __awaiter(this, void 0, Promise, function () {
-        return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
             return [2 /*return*/];
         });
     });
 }
 function returnStatement1() {
-    return __awaiter(this, void 0, Promise, function () {
-        return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
             return [2 /*return*/, x];
         });
     });
 }
 function returnStatement2() {
-    return __awaiter(this, void 0, Promise, function () {
-        return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1: return [2 /*return*/, _a.sent()];
@@ -52,8 +52,8 @@ function returnStatement2() {
     });
 }
 function returnStatement3() {
-    return __awaiter(this, void 0, Promise, function () {
-        return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
             {
                 return [2 /*return*/];
             }
@@ -62,8 +62,8 @@ function returnStatement3() {
     });
 }
 function returnStatement4() {
-    return __awaiter(this, void 0, Promise, function () {
-        return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -77,8 +77,8 @@ function returnStatement4() {
     });
 }
 function returnStatement5() {
-    return __awaiter(this, void 0, Promise, function () {
-        return __generator(function (_a) {
+    return __awaiter(this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1: return [2 /*return*/, _a.sent()];
diff --git a/tests/baselines/reference/es5-asyncFunctionSwitchStatements.js b/tests/baselines/reference/es5-asyncFunctionSwitchStatements.js
index 7c6da63dfe4f7..0af5f8e1c60a1 100644
--- a/tests/baselines/reference/es5-asyncFunctionSwitchStatements.js
+++ b/tests/baselines/reference/es5-asyncFunctionSwitchStatements.js
@@ -70,7 +70,7 @@ async function switchStatement8() {
 //// [es5-asyncFunctionSwitchStatements.js]
 function switchStatement0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (x) {
                 case y:
                     a;
@@ -85,7 +85,7 @@ function switchStatement0() {
 }
 function switchStatement1() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -105,7 +105,7 @@ function switchStatement1() {
 function switchStatement2() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -129,7 +129,7 @@ function switchStatement2() {
 function switchStatement3() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -152,7 +152,7 @@ function switchStatement3() {
 function switchStatement4() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -175,7 +175,7 @@ function switchStatement4() {
 function switchStatement5() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -202,7 +202,7 @@ function switchStatement5() {
 function switchStatement6() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -230,7 +230,7 @@ function switchStatement6() {
 function switchStatement7() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -260,7 +260,7 @@ function switchStatement7() {
 function switchStatement8() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
diff --git a/tests/baselines/reference/es5-asyncFunctionTryStatements.js b/tests/baselines/reference/es5-asyncFunctionTryStatements.js
index 54371c5842fc6..c9c5507afa7d9 100644
--- a/tests/baselines/reference/es5-asyncFunctionTryStatements.js
+++ b/tests/baselines/reference/es5-asyncFunctionTryStatements.js
@@ -126,7 +126,7 @@ async function tryCatchFinally3() {
 function tryCatch0() {
     return __awaiter(this, void 0, void 0, function () {
         var x, y;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             try {
                 x;
             }
@@ -140,7 +140,7 @@ function tryCatch0() {
 function tryCatch1() {
     return __awaiter(this, void 0, void 0, function () {
         var x, y, e_1;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _a.trys.push([0, 2, , 3]);
@@ -160,7 +160,7 @@ function tryCatch1() {
 function tryCatch2() {
     return __awaiter(this, void 0, void 0, function () {
         var x, y, e_2;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _a.trys.push([0, 1, , 3]);
@@ -178,9 +178,9 @@ function tryCatch2() {
     });
 }
 function tryCatch3() {
-    return __awaiter(this, void 0, Promise, function () {
+    return __awaiter(this, void 0, void 0, function () {
         var x, y, e_3;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _a.trys.push([0, 2, , 3]);
@@ -199,7 +199,7 @@ function tryCatch3() {
 function tryFinally0() {
     return __awaiter(this, void 0, void 0, function () {
         var x, y;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             try {
                 x;
             }
@@ -213,7 +213,7 @@ function tryFinally0() {
 function tryFinally1() {
     return __awaiter(this, void 0, void 0, function () {
         var x, y;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _a.trys.push([0, , 2, 3]);
@@ -232,7 +232,7 @@ function tryFinally1() {
 function tryFinally2() {
     return __awaiter(this, void 0, void 0, function () {
         var x, y;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _a.trys.push([0, , 1, 3]);
@@ -250,7 +250,7 @@ function tryFinally2() {
 function tryCatchFinally0() {
     return __awaiter(this, void 0, void 0, function () {
         var x, y, z;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             try {
                 x;
             }
@@ -267,7 +267,7 @@ function tryCatchFinally0() {
 function tryCatchFinally1() {
     return __awaiter(this, void 0, void 0, function () {
         var x, y, z, e_4;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _a.trys.push([0, 2, 3, 4]);
@@ -290,7 +290,7 @@ function tryCatchFinally1() {
 function tryCatchFinally2() {
     return __awaiter(this, void 0, void 0, function () {
         var x, y, z, e_5;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _a.trys.push([0, 1, 3, 4]);
@@ -313,7 +313,7 @@ function tryCatchFinally2() {
 function tryCatchFinally3() {
     return __awaiter(this, void 0, void 0, function () {
         var x, y, z, e_6;
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     _a.trys.push([0, 1, 2, 4]);
diff --git a/tests/baselines/reference/es5-asyncFunctionWhileStatements.js b/tests/baselines/reference/es5-asyncFunctionWhileStatements.js
index 53ca2a2da37c7..c85aabb01e30a 100644
--- a/tests/baselines/reference/es5-asyncFunctionWhileStatements.js
+++ b/tests/baselines/reference/es5-asyncFunctionWhileStatements.js
@@ -80,7 +80,7 @@ async function whileStatement18() {
 //// [es5-asyncFunctionWhileStatements.js]
 function whileStatement0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             while (x) {
                 y;
             }
@@ -90,7 +90,7 @@ function whileStatement0() {
 }
 function whileStatement1() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -105,7 +105,7 @@ function whileStatement1() {
 }
 function whileStatement2() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (!x)
@@ -121,7 +121,7 @@ function whileStatement2() {
 }
 function whileStatement3() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             while (x) {
                 continue;
             }
@@ -131,7 +131,7 @@ function whileStatement3() {
 }
 function whileStatement4() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -145,7 +145,7 @@ function whileStatement4() {
 }
 function whileStatement5() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (!x)
@@ -161,7 +161,7 @@ function whileStatement5() {
 }
 function whileStatement6() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (!x)
@@ -179,7 +179,7 @@ function whileStatement6() {
 }
 function whileStatement7() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             A: while (x) {
                 continue A;
             }
@@ -189,7 +189,7 @@ function whileStatement7() {
 }
 function whileStatement8() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -203,7 +203,7 @@ function whileStatement8() {
 }
 function whileStatement9() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (!x)
@@ -219,7 +219,7 @@ function whileStatement9() {
 }
 function whileStatement10() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (!x)
@@ -237,7 +237,7 @@ function whileStatement10() {
 }
 function whileStatement11() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             while (x) {
                 break;
             }
@@ -247,7 +247,7 @@ function whileStatement11() {
 }
 function whileStatement12() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -261,7 +261,7 @@ function whileStatement12() {
 }
 function whileStatement13() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (!x)
@@ -277,7 +277,7 @@ function whileStatement13() {
 }
 function whileStatement14() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (!x)
@@ -295,7 +295,7 @@ function whileStatement14() {
 }
 function whileStatement15() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             E: while (x) {
                 break E;
             }
@@ -305,7 +305,7 @@ function whileStatement15() {
 }
 function whileStatement16() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -319,7 +319,7 @@ function whileStatement16() {
 }
 function whileStatement17() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (!x)
@@ -335,7 +335,7 @@ function whileStatement17() {
 }
 function whileStatement18() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             switch (_a.label) {
                 case 0:
                     if (!x)
diff --git a/tests/baselines/reference/es5-asyncFunctionWithStatements.js b/tests/baselines/reference/es5-asyncFunctionWithStatements.js
index 20bedc25da9f0..25ed4df5c1148 100644
--- a/tests/baselines/reference/es5-asyncFunctionWithStatements.js
+++ b/tests/baselines/reference/es5-asyncFunctionWithStatements.js
@@ -34,7 +34,7 @@ async function withStatement3() {
 //// [es5-asyncFunctionWithStatements.js]
 function withStatement0() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             with (x) {
                 y;
             }
@@ -45,7 +45,7 @@ function withStatement0() {
 function withStatement1() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0: return [4 /*yield*/, x];
                 case 1:
@@ -64,7 +64,7 @@ function withStatement1() {
 function withStatement2() {
     return __awaiter(this, void 0, void 0, function () {
         var _a;
-        return __generator(function (_b) {
+        return __generator(this, function (_b) {
             switch (_b.label) {
                 case 0:
                     _a = x;
@@ -87,7 +87,7 @@ function withStatement2() {
 function withStatement3() {
     return __awaiter(this, void 0, void 0, function () {
         var _a, _b;
-        return __generator(function (_c) {
+        return __generator(this, function (_c) {
             switch (_c.label) {
                 case 0:
                     _a = x;
diff --git a/tests/baselines/reference/es5-importHelpersAsyncFunctions.js b/tests/baselines/reference/es5-importHelpersAsyncFunctions.js
index b90e2248c2c53..0fcd8897018ff 100644
--- a/tests/baselines/reference/es5-importHelpersAsyncFunctions.js
+++ b/tests/baselines/reference/es5-importHelpersAsyncFunctions.js
@@ -22,7 +22,7 @@ export declare function __generator(body: Function): any;
 var tslib_1 = require("tslib");
 function foo() {
     return tslib_1.__awaiter(this, void 0, void 0, function () {
-        return tslib_1.__generator(function (_a) {
+        return tslib_1.__generator(this, function (_a) {
             return [2 /*return*/];
         });
     });
@@ -37,7 +37,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
         step((generator = generator.apply(thisArg, _arguments)).next());
     });
 };
-var __generator = (this && this.__generator) || function (body) {
+var __generator = (this && this.__generator) || function (thisArg, body) {
     var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
     function step(op) {
         if (f) throw new TypeError("Generator is already executing.");
@@ -62,7 +62,7 @@ var __generator = (this && this.__generator) || function (body) {
                         _.trys.pop();
                         continue;
                 }
-                op = body(_);
+                op = body.call(thisArg, _);
             }
             catch (e) { op = [6, e]; }
             finally { f = 0, sent = void 0; }
@@ -76,7 +76,7 @@ var __generator = (this && this.__generator) || function (body) {
 };
 function foo() {
     return __awaiter(this, void 0, void 0, function () {
-        return __generator(function (_a) {
+        return __generator(this, function (_a) {
             return [2 /*return*/];
         });
     });
diff --git a/tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts b/tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts
new file mode 100644
index 0000000000000..5ab13f88b36fd
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts
@@ -0,0 +1,7 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+type PromiseAlias<T> = Promise<T>;
+
+async function f(): PromiseAlias<void> {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncAwaitIsolatedModules_es5.ts b/tests/cases/conformance/async/es5/asyncAwaitIsolatedModules_es5.ts
new file mode 100644
index 0000000000000..4ee04b2b3e9b5
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncAwaitIsolatedModules_es5.ts
@@ -0,0 +1,42 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @isolatedModules: true
+import { MyPromise } from "missing";
+
+declare var p: Promise<number>;
+declare var mp: MyPromise<number>;
+
+async function f0() { }
+async function f1(): Promise<void> { }
+async function f3(): MyPromise<void> { }
+
+let f4 = async function() { }
+let f5 = async function(): Promise<void> { }
+let f6 = async function(): MyPromise<void> { }
+
+let f7 = async () => { };
+let f8 = async (): Promise<void> => { };
+let f9 = async (): MyPromise<void> => { };
+let f10 = async () => p;
+let f11 = async () => mp;
+let f12 = async (): Promise<number> => mp;
+let f13 = async (): MyPromise<number> => p;
+
+let o = {
+	async m1() { },
+	async m2(): Promise<void> { },
+	async m3(): MyPromise<void> { }
+};
+
+class C {
+	async m1() { }
+	async m2(): Promise<void> { }
+	async m3(): MyPromise<void> { }
+	static async m4() { }
+	static async m5(): Promise<void> { }
+	static async m6(): MyPromise<void> { }
+}
+
+module M {
+	export async function f1() { }
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncAwait_es5.ts b/tests/cases/conformance/async/es5/asyncAwait_es5.ts
new file mode 100644
index 0000000000000..88cda3201dcfb
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncAwait_es5.ts
@@ -0,0 +1,41 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+type MyPromise<T> = Promise<T>;
+declare var MyPromise: typeof Promise;
+declare var p: Promise<number>;
+declare var mp: MyPromise<number>;
+
+async function f0() { }
+async function f1(): Promise<void> { }
+async function f3(): MyPromise<void> { }
+
+let f4 = async function() { }
+let f5 = async function(): Promise<void> { }
+let f6 = async function(): MyPromise<void> { }
+
+let f7 = async () => { };
+let f8 = async (): Promise<void> => { };
+let f9 = async (): MyPromise<void> => { };
+let f10 = async () => p;
+let f11 = async () => mp;
+let f12 = async (): Promise<number> => mp;
+let f13 = async (): MyPromise<number> => p;
+
+let o = {
+	async m1() { },
+	async m2(): Promise<void> { },
+	async m3(): MyPromise<void> { }
+};
+
+class C {
+	async m1() { }
+	async m2(): Promise<void> { }
+	async m3(): MyPromise<void> { }
+	static async m4() { }
+	static async m5(): Promise<void> { }
+	static async m6(): MyPromise<void> { }
+}
+
+module M {
+	export async function f1() { }
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncClass_es5.ts b/tests/cases/conformance/async/es5/asyncClass_es5.ts
new file mode 100644
index 0000000000000..70f32702bd032
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncClass_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async class C {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncConstructor_es5.ts b/tests/cases/conformance/async/es5/asyncConstructor_es5.ts
new file mode 100644
index 0000000000000..57cb07561b912
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncConstructor_es5.ts
@@ -0,0 +1,7 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+class C {
+  async constructor() {
+  }
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncDeclare_es5.ts b/tests/cases/conformance/async/es5/asyncDeclare_es5.ts
new file mode 100644
index 0000000000000..aad035337d323
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncDeclare_es5.ts
@@ -0,0 +1,4 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare async function foo(): Promise<void>;
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncEnum_es5.ts b/tests/cases/conformance/async/es5/asyncEnum_es5.ts
new file mode 100644
index 0000000000000..7f0060bf04f2a
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncEnum_es5.ts
@@ -0,0 +1,6 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async enum E {
+  Value
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncGetter_es5.ts b/tests/cases/conformance/async/es5/asyncGetter_es5.ts
new file mode 100644
index 0000000000000..8c12c4f346294
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncGetter_es5.ts
@@ -0,0 +1,7 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+class C {
+  async get foo() {
+  }
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncImportedPromise_es5.ts b/tests/cases/conformance/async/es5/asyncImportedPromise_es5.ts
new file mode 100644
index 0000000000000..9e8494b3c2fdc
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncImportedPromise_es5.ts
@@ -0,0 +1,11 @@
+// @target: es5
+// @lib: es5,es2015.promise
+// @module: commonjs
+// @filename: task.ts
+export class Task<T> extends Promise<T> { }
+
+// @filename: test.ts
+import { Task } from "./task";
+class Test {
+    async example<T>(): Task<T> { return; }
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncInterface_es5.ts b/tests/cases/conformance/async/es5/asyncInterface_es5.ts
new file mode 100644
index 0000000000000..7ac70f40a69ac
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncInterface_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async interface I {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncMethodWithSuper_es5.ts b/tests/cases/conformance/async/es5/asyncMethodWithSuper_es5.ts
new file mode 100644
index 0000000000000..496d8d1c80247
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncMethodWithSuper_es5.ts
@@ -0,0 +1,53 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+class A {
+    x() {
+    }
+}
+
+class B extends A {
+    // async method with only call/get on 'super' does not require a binding
+    async simple() {
+        // call with property access
+        super.x();
+
+        // call with element access
+        super["x"]();
+
+        // property access (read)
+        const a = super.x;
+
+        // element access (read)
+        const b = super["x"];
+    }
+
+    // async method with assignment/destructuring on 'super' requires a binding
+    async advanced() {
+        const f = () => {};
+
+        // call with property access
+        super.x();
+
+        // call with element access
+        super["x"]();
+
+        // property access (read)
+        const a = super.x;
+
+        // element access (read)
+        const b = super["x"];
+
+        // property access (assign)
+        super.x = f;
+
+        // element access (assign)
+        super["x"] = f;
+
+        // destructuring assign with property access
+        ({ f: super.x } = { f });
+
+        // destructuring assign with element access
+        ({ f: super["x"] } = { f });
+    }
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncModule_es5.ts b/tests/cases/conformance/async/es5/asyncModule_es5.ts
new file mode 100644
index 0000000000000..55df9f89dc3d9
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncModule_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+async module M {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncMultiFile_es5.ts b/tests/cases/conformance/async/es5/asyncMultiFile_es5.ts
new file mode 100644
index 0000000000000..66d4f4e673f85
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncMultiFile_es5.ts
@@ -0,0 +1,6 @@
+// @target: es5
+// @lib: es5,es2015.promise
+// @filename: a.ts
+async function f() {}
+// @filename: b.ts
+function g() { }
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncQualifiedReturnType_es5.ts b/tests/cases/conformance/async/es5/asyncQualifiedReturnType_es5.ts
new file mode 100644
index 0000000000000..34fc1b13389bd
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncQualifiedReturnType_es5.ts
@@ -0,0 +1,10 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+namespace X {
+    export class MyPromise<T> extends Promise<T> {
+    }
+}
+
+async function f(): X.MyPromise<void> {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncSetter_es5.ts b/tests/cases/conformance/async/es5/asyncSetter_es5.ts
new file mode 100644
index 0000000000000..419922b080618
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncSetter_es5.ts
@@ -0,0 +1,7 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+class C {
+  async set foo(value) {
+  }
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncUseStrict_es5.ts b/tests/cases/conformance/async/es5/asyncUseStrict_es5.ts
new file mode 100644
index 0000000000000..cc20d594de55b
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncUseStrict_es5.ts
@@ -0,0 +1,9 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare var a: boolean;
+declare var p: Promise<boolean>;
+async function func(): Promise<void> {
+    "use strict";
+    var b = await p || a;
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitClassExpression_es5.ts b/tests/cases/conformance/async/es5/awaitClassExpression_es5.ts
new file mode 100644
index 0000000000000..27eafeb1af596
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitClassExpression_es5.ts
@@ -0,0 +1,10 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare class C { }
+declare var p: Promise<typeof C>;
+
+async function func(): Promise<void> {
+    class D extends (await p) {
+    }
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/awaitUnion_es5.ts b/tests/cases/conformance/async/es5/awaitUnion_es5.ts
new file mode 100644
index 0000000000000..44ceb1374d6f0
--- /dev/null
+++ b/tests/cases/conformance/async/es5/awaitUnion_es5.ts
@@ -0,0 +1,15 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+declare let a: number | string;
+declare let b: PromiseLike<number> | PromiseLike<string>;
+declare let c: PromiseLike<number | string>;
+declare let d: number | PromiseLike<string>;
+declare let e: number | PromiseLike<number | string>;
+async function f() {
+	let await_a = await a;
+	let await_b = await b;
+	let await_c = await c;
+	let await_d = await d;
+	let await_e = await e;
+}
\ No newline at end of file

From 644e4dacaf89882870fa0121df28b17adb13d7ce Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 27 Jun 2016 17:34:19 -0700
Subject: [PATCH 20/23] Added es5 conformance tests for async arrow functions,
 add error for referencing 'arguments' in a generator.

---
 src/compiler/checker.ts                       |  7 ++--
 src/compiler/diagnosticMessages.json          |  2 +-
 ...arrowFunctionWithParameterNameAsync_es5.js |  6 ++++
 ...FunctionWithParameterNameAsync_es5.symbols |  7 ++++
 ...owFunctionWithParameterNameAsync_es5.types |  8 +++++
 .../asyncArrowFunction10_es5.errors.txt       | 12 +++++++
 .../reference/asyncArrowFunction10_es5.js     | 16 ++++++++++
 .../reference/asyncArrowFunction1_es5.js      | 12 +++++++
 .../reference/asyncArrowFunction1_es5.symbols |  7 ++++
 .../reference/asyncArrowFunction1_es5.types   |  8 +++++
 .../reference/asyncArrowFunction2_es5.js      |  7 ++++
 .../reference/asyncArrowFunction2_es5.symbols |  5 +++
 .../reference/asyncArrowFunction2_es5.types   |  6 ++++
 .../asyncArrowFunction3_es5.errors.txt        |  8 +++++
 .../reference/asyncArrowFunction3_es5.js      |  8 +++++
 .../reference/asyncArrowFunction4_es5.js      |  7 ++++
 .../reference/asyncArrowFunction4_es5.symbols |  4 +++
 .../reference/asyncArrowFunction4_es5.types   |  5 +++
 .../asyncArrowFunction5_es5.errors.txt        | 24 ++++++++++++++
 .../reference/asyncArrowFunction5_es5.js      |  9 ++++++
 .../asyncArrowFunction6_es5.errors.txt        | 12 +++++++
 .../reference/asyncArrowFunction6_es5.js      | 15 +++++++++
 .../asyncArrowFunction7_es5.errors.txt        | 15 +++++++++
 .../reference/asyncArrowFunction7_es5.js      | 25 +++++++++++++++
 .../asyncArrowFunction8_es5.errors.txt        | 10 ++++++
 .../reference/asyncArrowFunction8_es5.js      | 21 ++++++++++++
 .../asyncArrowFunction9_es5.errors.txt        | 23 +++++++++++++
 .../reference/asyncArrowFunction9_es5.js      |  8 +++++
 ...owFunctionCapturesArguments_es5.errors.txt | 13 ++++++++
 ...asyncArrowFunctionCapturesArguments_es5.js | 25 +++++++++++++++
 .../asyncArrowFunctionCapturesThis_es5.js     | 23 +++++++++++++
 ...asyncArrowFunctionCapturesThis_es5.symbols | 13 ++++++++
 .../asyncArrowFunctionCapturesThis_es5.types  | 15 +++++++++
 ...eclarationCapturesArguments_es5.errors.txt | 15 +++++++++
 ...unctionDeclarationCapturesArguments_es5.js | 32 +++++++++++++++++++
 .../asyncUnParenthesizedArrowFunction_es5.js  | 20 ++++++++++++
 ...ncUnParenthesizedArrowFunction_es5.symbols | 19 +++++++++++
 ...syncUnParenthesizedArrowFunction_es5.types | 25 +++++++++++++++
 ...arrowFunctionWithParameterNameAsync_es5.ts |  5 +++
 .../asyncArrowFunction10_es5.ts               |  8 +++++
 .../asyncArrowFunction1_es5.ts                |  6 ++++
 .../asyncArrowFunction2_es5.ts                |  5 +++
 .../asyncArrowFunction3_es5.ts                |  5 +++
 .../asyncArrowFunction4_es5.ts                |  5 +++
 .../asyncArrowFunction5_es5.ts                |  6 ++++
 .../asyncArrowFunction6_es5.ts                |  6 ++++
 .../asyncArrowFunction7_es5.ts                |  9 ++++++
 .../asyncArrowFunction8_es5.ts                |  7 ++++
 .../asyncArrowFunction9_es5.ts                |  5 +++
 ...asyncArrowFunctionCapturesArguments_es5.ts |  9 ++++++
 .../asyncArrowFunctionCapturesThis_es5.ts     |  8 +++++
 .../asyncUnParenthesizedArrowFunction_es5.ts  |  7 ++++
 ...unctionDeclarationCapturesArguments_es5.ts | 11 +++++++
 53 files changed, 596 insertions(+), 3 deletions(-)
 create mode 100644 tests/baselines/reference/arrowFunctionWithParameterNameAsync_es5.js
 create mode 100644 tests/baselines/reference/arrowFunctionWithParameterNameAsync_es5.symbols
 create mode 100644 tests/baselines/reference/arrowFunctionWithParameterNameAsync_es5.types
 create mode 100644 tests/baselines/reference/asyncArrowFunction10_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncArrowFunction10_es5.js
 create mode 100644 tests/baselines/reference/asyncArrowFunction1_es5.js
 create mode 100644 tests/baselines/reference/asyncArrowFunction1_es5.symbols
 create mode 100644 tests/baselines/reference/asyncArrowFunction1_es5.types
 create mode 100644 tests/baselines/reference/asyncArrowFunction2_es5.js
 create mode 100644 tests/baselines/reference/asyncArrowFunction2_es5.symbols
 create mode 100644 tests/baselines/reference/asyncArrowFunction2_es5.types
 create mode 100644 tests/baselines/reference/asyncArrowFunction3_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncArrowFunction3_es5.js
 create mode 100644 tests/baselines/reference/asyncArrowFunction4_es5.js
 create mode 100644 tests/baselines/reference/asyncArrowFunction4_es5.symbols
 create mode 100644 tests/baselines/reference/asyncArrowFunction4_es5.types
 create mode 100644 tests/baselines/reference/asyncArrowFunction5_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncArrowFunction5_es5.js
 create mode 100644 tests/baselines/reference/asyncArrowFunction6_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncArrowFunction6_es5.js
 create mode 100644 tests/baselines/reference/asyncArrowFunction7_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncArrowFunction7_es5.js
 create mode 100644 tests/baselines/reference/asyncArrowFunction8_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncArrowFunction8_es5.js
 create mode 100644 tests/baselines/reference/asyncArrowFunction9_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncArrowFunction9_es5.js
 create mode 100644 tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5.js
 create mode 100644 tests/baselines/reference/asyncArrowFunctionCapturesThis_es5.js
 create mode 100644 tests/baselines/reference/asyncArrowFunctionCapturesThis_es5.symbols
 create mode 100644 tests/baselines/reference/asyncArrowFunctionCapturesThis_es5.types
 create mode 100644 tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5.errors.txt
 create mode 100644 tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5.js
 create mode 100644 tests/baselines/reference/asyncUnParenthesizedArrowFunction_es5.js
 create mode 100644 tests/baselines/reference/asyncUnParenthesizedArrowFunction_es5.symbols
 create mode 100644 tests/baselines/reference/asyncUnParenthesizedArrowFunction_es5.types
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/arrowFunctionWithParameterNameAsync_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction10_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction1_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction2_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction3_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction4_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction5_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction6_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction7_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction8_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction9_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesArguments_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesThis_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/asyncArrowFunction/asyncUnParenthesizedArrowFunction_es5.ts
 create mode 100644 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclarationCapturesArguments_es5.ts

diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 56ec54781e782..b839d86243018 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -8162,10 +8162,13 @@ namespace ts {
             // can explicitly bound arguments objects
             if (symbol === argumentsSymbol) {
                 const container = getContainingFunction(node);
-                if (container.kind === SyntaxKind.ArrowFunction) {
-                    if (languageVersion < ScriptTarget.ES6) {
+                if (languageVersion < ScriptTarget.ES6) {
+                    if (container.kind === SyntaxKind.ArrowFunction) {
                         error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression);
                     }
+                    else if (hasModifier(container, ModifierFlags.Async)) {
+                        error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method);
+                    }
                 }
 
                 if (node.flags & NodeFlags.AwaitContext) {
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index 75b5827ab4823..b2c67271001aa 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -1695,7 +1695,7 @@
         "category": "Error",
         "code": 2521
     },
-    "The 'arguments' object cannot be referenced in an async arrow function. Consider using a standard async function expression.": {
+    "The 'arguments' object cannot be referenced in an async function or method in ES3 and ES5. Consider using a standard function or method.": {
         "category": "Error",
         "code": 2522
     },
diff --git a/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es5.js b/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es5.js
new file mode 100644
index 0000000000000..df308028361ae
--- /dev/null
+++ b/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es5.js
@@ -0,0 +1,6 @@
+//// [arrowFunctionWithParameterNameAsync_es5.ts]
+
+const x = async => async;
+
+//// [arrowFunctionWithParameterNameAsync_es5.js]
+var x = function (async) { return async; };
diff --git a/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es5.symbols b/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es5.symbols
new file mode 100644
index 0000000000000..43c9c343efe7d
--- /dev/null
+++ b/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es5.symbols
@@ -0,0 +1,7 @@
+=== tests/cases/conformance/async/es5/asyncArrowFunction/arrowFunctionWithParameterNameAsync_es5.ts ===
+
+const x = async => async;
+>x : Symbol(x, Decl(arrowFunctionWithParameterNameAsync_es5.ts, 1, 5))
+>async : Symbol(async, Decl(arrowFunctionWithParameterNameAsync_es5.ts, 1, 9))
+>async : Symbol(async, Decl(arrowFunctionWithParameterNameAsync_es5.ts, 1, 9))
+
diff --git a/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es5.types b/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es5.types
new file mode 100644
index 0000000000000..bd567320f1d3f
--- /dev/null
+++ b/tests/baselines/reference/arrowFunctionWithParameterNameAsync_es5.types
@@ -0,0 +1,8 @@
+=== tests/cases/conformance/async/es5/asyncArrowFunction/arrowFunctionWithParameterNameAsync_es5.ts ===
+
+const x = async => async;
+>x : (async: any) => any
+>async => async : (async: any) => any
+>async : any
+>async : any
+
diff --git a/tests/baselines/reference/asyncArrowFunction10_es5.errors.txt b/tests/baselines/reference/asyncArrowFunction10_es5.errors.txt
new file mode 100644
index 0000000000000..0b3596282ff2c
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction10_es5.errors.txt
@@ -0,0 +1,12 @@
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction10_es5.ts(4,11): error TS2304: Cannot find name 'await'.
+
+
+==== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction10_es5.ts (1 errors) ====
+    
+    var foo = async (): Promise<void> => {
+       // Legal to use 'await' in a type context.
+       var v: await;
+              ~~~~~
+!!! error TS2304: Cannot find name 'await'.
+    }
+    
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncArrowFunction10_es5.js b/tests/baselines/reference/asyncArrowFunction10_es5.js
new file mode 100644
index 0000000000000..2fc2ac56f9f12
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction10_es5.js
@@ -0,0 +1,16 @@
+//// [asyncArrowFunction10_es5.ts]
+
+var foo = async (): Promise<void> => {
+   // Legal to use 'await' in a type context.
+   var v: await;
+}
+
+
+//// [asyncArrowFunction10_es5.js]
+var _this = this;
+var foo = function () { return __awaiter(_this, void 0, void 0, function () {
+    var v;
+    return __generator(this, function (_a) {
+        return [2 /*return*/];
+    });
+}); };
diff --git a/tests/baselines/reference/asyncArrowFunction1_es5.js b/tests/baselines/reference/asyncArrowFunction1_es5.js
new file mode 100644
index 0000000000000..aac185c63a1e5
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction1_es5.js
@@ -0,0 +1,12 @@
+//// [asyncArrowFunction1_es5.ts]
+
+var foo = async (): Promise<void> => {
+};
+
+//// [asyncArrowFunction1_es5.js]
+var _this = this;
+var foo = function () { return __awaiter(_this, void 0, void 0, function () {
+    return __generator(this, function (_a) {
+        return [2 /*return*/];
+    });
+}); };
diff --git a/tests/baselines/reference/asyncArrowFunction1_es5.symbols b/tests/baselines/reference/asyncArrowFunction1_es5.symbols
new file mode 100644
index 0000000000000..c37985dc34765
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction1_es5.symbols
@@ -0,0 +1,7 @@
+=== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction1_es5.ts ===
+
+var foo = async (): Promise<void> => {
+>foo : Symbol(foo, Decl(asyncArrowFunction1_es5.ts, 1, 3))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+};
diff --git a/tests/baselines/reference/asyncArrowFunction1_es5.types b/tests/baselines/reference/asyncArrowFunction1_es5.types
new file mode 100644
index 0000000000000..bde82d2b83603
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction1_es5.types
@@ -0,0 +1,8 @@
+=== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction1_es5.ts ===
+
+var foo = async (): Promise<void> => {
+>foo : () => Promise<void>
+>async (): Promise<void> => {} : () => Promise<void>
+>Promise : Promise<T>
+
+};
diff --git a/tests/baselines/reference/asyncArrowFunction2_es5.js b/tests/baselines/reference/asyncArrowFunction2_es5.js
new file mode 100644
index 0000000000000..d77837a5433e1
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction2_es5.js
@@ -0,0 +1,7 @@
+//// [asyncArrowFunction2_es5.ts]
+var f = (await) => {
+}
+
+//// [asyncArrowFunction2_es5.js]
+var f = function (await) {
+};
diff --git a/tests/baselines/reference/asyncArrowFunction2_es5.symbols b/tests/baselines/reference/asyncArrowFunction2_es5.symbols
new file mode 100644
index 0000000000000..b195e9c269524
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction2_es5.symbols
@@ -0,0 +1,5 @@
+=== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction2_es5.ts ===
+var f = (await) => {
+>f : Symbol(f, Decl(asyncArrowFunction2_es5.ts, 0, 3))
+>await : Symbol(await, Decl(asyncArrowFunction2_es5.ts, 0, 9))
+}
diff --git a/tests/baselines/reference/asyncArrowFunction2_es5.types b/tests/baselines/reference/asyncArrowFunction2_es5.types
new file mode 100644
index 0000000000000..e51a17abd3553
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction2_es5.types
@@ -0,0 +1,6 @@
+=== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction2_es5.ts ===
+var f = (await) => {
+>f : (await: any) => void
+>(await) => {} : (await: any) => void
+>await : any
+}
diff --git a/tests/baselines/reference/asyncArrowFunction3_es5.errors.txt b/tests/baselines/reference/asyncArrowFunction3_es5.errors.txt
new file mode 100644
index 0000000000000..01c74ab362028
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction3_es5.errors.txt
@@ -0,0 +1,8 @@
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction3_es5.ts(1,20): error TS2372: Parameter 'await' cannot be referenced in its initializer.
+
+
+==== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction3_es5.ts (1 errors) ====
+    function f(await = await) {
+                       ~~~~~
+!!! error TS2372: Parameter 'await' cannot be referenced in its initializer.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncArrowFunction3_es5.js b/tests/baselines/reference/asyncArrowFunction3_es5.js
new file mode 100644
index 0000000000000..3c73e6f9f58f9
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction3_es5.js
@@ -0,0 +1,8 @@
+//// [asyncArrowFunction3_es5.ts]
+function f(await = await) {
+}
+
+//// [asyncArrowFunction3_es5.js]
+function f(await) {
+    if (await === void 0) { await = await; }
+}
diff --git a/tests/baselines/reference/asyncArrowFunction4_es5.js b/tests/baselines/reference/asyncArrowFunction4_es5.js
new file mode 100644
index 0000000000000..cbaae99a9c6ba
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction4_es5.js
@@ -0,0 +1,7 @@
+//// [asyncArrowFunction4_es5.ts]
+var await = () => {
+}
+
+//// [asyncArrowFunction4_es5.js]
+var await = function () {
+};
diff --git a/tests/baselines/reference/asyncArrowFunction4_es5.symbols b/tests/baselines/reference/asyncArrowFunction4_es5.symbols
new file mode 100644
index 0000000000000..affb1f188a862
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction4_es5.symbols
@@ -0,0 +1,4 @@
+=== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction4_es5.ts ===
+var await = () => {
+>await : Symbol(await, Decl(asyncArrowFunction4_es5.ts, 0, 3))
+}
diff --git a/tests/baselines/reference/asyncArrowFunction4_es5.types b/tests/baselines/reference/asyncArrowFunction4_es5.types
new file mode 100644
index 0000000000000..3b45236509571
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction4_es5.types
@@ -0,0 +1,5 @@
+=== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction4_es5.ts ===
+var await = () => {
+>await : () => void
+>() => {} : () => void
+}
diff --git a/tests/baselines/reference/asyncArrowFunction5_es5.errors.txt b/tests/baselines/reference/asyncArrowFunction5_es5.errors.txt
new file mode 100644
index 0000000000000..e19113e66f85f
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction5_es5.errors.txt
@@ -0,0 +1,24 @@
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction5_es5.ts(2,11): error TS2304: Cannot find name 'async'.
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction5_es5.ts(2,18): error TS2304: Cannot find name 'await'.
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction5_es5.ts(2,24): error TS1005: ',' expected.
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction5_es5.ts(2,26): error TS2403: Subsequent variable declarations must have the same type.  Variable 'Promise' must be of type 'PromiseConstructor', but here has type 'void'.
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction5_es5.ts(2,33): error TS1005: '=' expected.
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction5_es5.ts(2,40): error TS1109: Expression expected.
+
+
+==== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction5_es5.ts (6 errors) ====
+    
+    var foo = async (await): Promise<void> => {
+              ~~~~~
+!!! error TS2304: Cannot find name 'async'.
+                     ~~~~~
+!!! error TS2304: Cannot find name 'await'.
+                           ~
+!!! error TS1005: ',' expected.
+                             ~~~~~~~
+!!! error TS2403: Subsequent variable declarations must have the same type.  Variable 'Promise' must be of type 'PromiseConstructor', but here has type 'void'.
+                                    ~
+!!! error TS1005: '=' expected.
+                                           ~~
+!!! error TS1109: Expression expected.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncArrowFunction5_es5.js b/tests/baselines/reference/asyncArrowFunction5_es5.js
new file mode 100644
index 0000000000000..ff5ee68d4c7ab
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction5_es5.js
@@ -0,0 +1,9 @@
+//// [asyncArrowFunction5_es5.ts]
+
+var foo = async (await): Promise<void> => {
+}
+
+//// [asyncArrowFunction5_es5.js]
+var foo = async(await), Promise = ;
+{
+}
diff --git a/tests/baselines/reference/asyncArrowFunction6_es5.errors.txt b/tests/baselines/reference/asyncArrowFunction6_es5.errors.txt
new file mode 100644
index 0000000000000..a957589bd945e
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction6_es5.errors.txt
@@ -0,0 +1,12 @@
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction6_es5.ts(2,22): error TS2524: 'await' expressions cannot be used in a parameter initializer.
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction6_es5.ts(2,27): error TS1109: Expression expected.
+
+
+==== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction6_es5.ts (2 errors) ====
+    
+    var foo = async (a = await): Promise<void> => {
+                         ~~~~~
+!!! error TS2524: 'await' expressions cannot be used in a parameter initializer.
+                              ~
+!!! error TS1109: Expression expected.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncArrowFunction6_es5.js b/tests/baselines/reference/asyncArrowFunction6_es5.js
new file mode 100644
index 0000000000000..ea61a1b44b5cb
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction6_es5.js
@@ -0,0 +1,15 @@
+//// [asyncArrowFunction6_es5.ts]
+
+var foo = async (a = await): Promise<void> => {
+}
+
+//// [asyncArrowFunction6_es5.js]
+var _this = this;
+var foo = function (a) {
+    if (a === void 0) { a = yield ; }
+    return __awaiter(_this, void 0, void 0, function () {
+        return __generator(this, function (_a) {
+            return [2 /*return*/];
+        });
+    });
+};
diff --git a/tests/baselines/reference/asyncArrowFunction7_es5.errors.txt b/tests/baselines/reference/asyncArrowFunction7_es5.errors.txt
new file mode 100644
index 0000000000000..cc5cf2bb61dda
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction7_es5.errors.txt
@@ -0,0 +1,15 @@
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction7_es5.ts(4,24): error TS2524: 'await' expressions cannot be used in a parameter initializer.
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction7_es5.ts(4,29): error TS1109: Expression expected.
+
+
+==== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction7_es5.ts (2 errors) ====
+    
+    var bar = async (): Promise<void> => {
+      // 'await' here is an identifier, and not an await expression.
+      var foo = async (a = await): Promise<void> => {
+                           ~~~~~
+!!! error TS2524: 'await' expressions cannot be used in a parameter initializer.
+                                ~
+!!! error TS1109: Expression expected.
+      }
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncArrowFunction7_es5.js b/tests/baselines/reference/asyncArrowFunction7_es5.js
new file mode 100644
index 0000000000000..19e589fa54292
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction7_es5.js
@@ -0,0 +1,25 @@
+//// [asyncArrowFunction7_es5.ts]
+
+var bar = async (): Promise<void> => {
+  // 'await' here is an identifier, and not an await expression.
+  var foo = async (a = await): Promise<void> => {
+  }
+}
+
+//// [asyncArrowFunction7_es5.js]
+var _this = this;
+var bar = function () { return __awaiter(_this, void 0, void 0, function () {
+    _this = this;
+    var foo;
+    return __generator(this, function (_a) {
+        foo = function (a) {
+            if (a === void 0) { a = yield ; }
+            return __awaiter(_this, void 0, void 0, function () {
+                return __generator(this, function (_a) {
+                    return [2 /*return*/];
+                });
+            });
+        };
+        return [2 /*return*/];
+    });
+}); var _this; };
diff --git a/tests/baselines/reference/asyncArrowFunction8_es5.errors.txt b/tests/baselines/reference/asyncArrowFunction8_es5.errors.txt
new file mode 100644
index 0000000000000..e2e69fc5bee65
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction8_es5.errors.txt
@@ -0,0 +1,10 @@
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction8_es5.ts(3,19): error TS1109: Expression expected.
+
+
+==== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction8_es5.ts (1 errors) ====
+    
+    var foo = async (): Promise<void> => {
+      var v = { [await]: foo }
+                      ~
+!!! error TS1109: Expression expected.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncArrowFunction8_es5.js b/tests/baselines/reference/asyncArrowFunction8_es5.js
new file mode 100644
index 0000000000000..3043294926252
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction8_es5.js
@@ -0,0 +1,21 @@
+//// [asyncArrowFunction8_es5.ts]
+
+var foo = async (): Promise<void> => {
+  var v = { [await]: foo }
+}
+
+//// [asyncArrowFunction8_es5.js]
+var _this = this;
+var foo = function () { return __awaiter(_this, void 0, void 0, function () {
+    var v, _a;
+    return __generator(this, function (_b) {
+        switch (_b.label) {
+            case 0:
+                _a = {};
+                return [4 /*yield*/, ];
+            case 1:
+                v = (_a[_b.sent()] = foo, _a);
+                return [2 /*return*/];
+        }
+    });
+}); };
diff --git a/tests/baselines/reference/asyncArrowFunction9_es5.errors.txt b/tests/baselines/reference/asyncArrowFunction9_es5.errors.txt
new file mode 100644
index 0000000000000..30846e06d6a16
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction9_es5.errors.txt
@@ -0,0 +1,23 @@
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction9_es5.ts(1,11): error TS2304: Cannot find name 'async'.
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction9_es5.ts(1,18): error TS2304: Cannot find name 'a'.
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction9_es5.ts(1,37): error TS1005: ',' expected.
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction9_es5.ts(1,39): error TS2403: Subsequent variable declarations must have the same type.  Variable 'Promise' must be of type 'PromiseConstructor', but here has type 'void'.
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction9_es5.ts(1,46): error TS1005: '=' expected.
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction9_es5.ts(1,53): error TS1109: Expression expected.
+
+
+==== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction9_es5.ts (6 errors) ====
+    var foo = async (a = await => await): Promise<void> => {
+              ~~~~~
+!!! error TS2304: Cannot find name 'async'.
+                     ~
+!!! error TS2304: Cannot find name 'a'.
+                                        ~
+!!! error TS1005: ',' expected.
+                                          ~~~~~~~
+!!! error TS2403: Subsequent variable declarations must have the same type.  Variable 'Promise' must be of type 'PromiseConstructor', but here has type 'void'.
+                                                 ~
+!!! error TS1005: '=' expected.
+                                                        ~~
+!!! error TS1109: Expression expected.
+    }
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncArrowFunction9_es5.js b/tests/baselines/reference/asyncArrowFunction9_es5.js
new file mode 100644
index 0000000000000..2506024f326d9
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunction9_es5.js
@@ -0,0 +1,8 @@
+//// [asyncArrowFunction9_es5.ts]
+var foo = async (a = await => await): Promise<void> => {
+}
+
+//// [asyncArrowFunction9_es5.js]
+var foo = async(a = function (await) { return await; }), Promise = ;
+{
+}
diff --git a/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5.errors.txt b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5.errors.txt
new file mode 100644
index 0000000000000..e0a1ef45e8c9f
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5.errors.txt
@@ -0,0 +1,13 @@
+tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesArguments_es5.ts(4,52): error TS2496: The 'arguments' object cannot be referenced in an arrow function in ES3 and ES5. Consider using a standard function expression.
+
+
+==== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesArguments_es5.ts (1 errors) ====
+    class C {
+       method() {
+          function other() {}
+          var fn = async () => await other.apply(this, arguments);
+                                                       ~~~~~~~~~
+!!! error TS2496: The 'arguments' object cannot be referenced in an arrow function in ES3 and ES5. Consider using a standard function expression.
+       }
+    }
+    
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5.js b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5.js
new file mode 100644
index 0000000000000..e73ef6ddd4d78
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5.js
@@ -0,0 +1,25 @@
+//// [asyncArrowFunctionCapturesArguments_es5.ts]
+class C {
+   method() {
+      function other() {}
+      var fn = async () => await other.apply(this, arguments);
+   }
+}
+
+
+//// [asyncArrowFunctionCapturesArguments_es5.js]
+var C = (function () {
+    function C() {
+    }
+    C.prototype.method = function () {
+        var _this = this;
+        function other() { }
+        var fn = function () { return __awaiter(_this, arguments, void 0, function () { return __generator(this, function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, other.apply(this, arguments)];
+                case 1: return [2 /*return*/, _a.sent()];
+            }
+        }); }); };
+    };
+    return C;
+}());
diff --git a/tests/baselines/reference/asyncArrowFunctionCapturesThis_es5.js b/tests/baselines/reference/asyncArrowFunctionCapturesThis_es5.js
new file mode 100644
index 0000000000000..5c9727bddabeb
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunctionCapturesThis_es5.js
@@ -0,0 +1,23 @@
+//// [asyncArrowFunctionCapturesThis_es5.ts]
+class C {
+   method() {
+      var fn = async () => await this;
+   }
+}
+
+
+//// [asyncArrowFunctionCapturesThis_es5.js]
+var C = (function () {
+    function C() {
+    }
+    C.prototype.method = function () {
+        var _this = this;
+        var fn = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+            switch (_a.label) {
+                case 0: return [4 /*yield*/, this];
+                case 1: return [2 /*return*/, _a.sent()];
+            }
+        }); }); };
+    };
+    return C;
+}());
diff --git a/tests/baselines/reference/asyncArrowFunctionCapturesThis_es5.symbols b/tests/baselines/reference/asyncArrowFunctionCapturesThis_es5.symbols
new file mode 100644
index 0000000000000..c041583989129
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunctionCapturesThis_es5.symbols
@@ -0,0 +1,13 @@
+=== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesThis_es5.ts ===
+class C {
+>C : Symbol(C, Decl(asyncArrowFunctionCapturesThis_es5.ts, 0, 0))
+
+   method() {
+>method : Symbol(C.method, Decl(asyncArrowFunctionCapturesThis_es5.ts, 0, 9))
+
+      var fn = async () => await this;
+>fn : Symbol(fn, Decl(asyncArrowFunctionCapturesThis_es5.ts, 2, 9))
+>this : Symbol(C, Decl(asyncArrowFunctionCapturesThis_es5.ts, 0, 0))
+   }
+}
+
diff --git a/tests/baselines/reference/asyncArrowFunctionCapturesThis_es5.types b/tests/baselines/reference/asyncArrowFunctionCapturesThis_es5.types
new file mode 100644
index 0000000000000..da378ee2718f9
--- /dev/null
+++ b/tests/baselines/reference/asyncArrowFunctionCapturesThis_es5.types
@@ -0,0 +1,15 @@
+=== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesThis_es5.ts ===
+class C {
+>C : C
+
+   method() {
+>method : () => void
+
+      var fn = async () => await this;
+>fn : () => Promise<this>
+>async () => await this : () => Promise<this>
+>await this : this
+>this : this
+   }
+}
+
diff --git a/tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5.errors.txt
new file mode 100644
index 0000000000000..7a35b1d5223aa
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5.errors.txt
@@ -0,0 +1,15 @@
+tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclarationCapturesArguments_es5.ts(5,36): error TS2522: The 'arguments' object cannot be referenced in an async function or method in ES3 and ES5. Consider using a standard function or method.
+
+
+==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclarationCapturesArguments_es5.ts (1 errors) ====
+    class C {
+       method() {
+          function other() {}
+          async function fn () {
+               await other.apply(this, arguments);
+                                       ~~~~~~~~~
+!!! error TS2522: The 'arguments' object cannot be referenced in an async function or method in ES3 and ES5. Consider using a standard function or method.
+          }
+       }
+    }
+    
\ No newline at end of file
diff --git a/tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5.js b/tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5.js
new file mode 100644
index 0000000000000..8881ad555a762
--- /dev/null
+++ b/tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5.js
@@ -0,0 +1,32 @@
+//// [asyncFunctionDeclarationCapturesArguments_es5.ts]
+class C {
+   method() {
+      function other() {}
+      async function fn () {
+           await other.apply(this, arguments);
+      }
+   }
+}
+
+
+//// [asyncFunctionDeclarationCapturesArguments_es5.js]
+var C = (function () {
+    function C() {
+    }
+    C.prototype.method = function () {
+        function other() { }
+        function fn() {
+            return __awaiter(this, arguments, void 0, function () {
+                return __generator(this, function (_a) {
+                    switch (_a.label) {
+                        case 0: return [4 /*yield*/, other.apply(this, arguments)];
+                        case 1:
+                            _a.sent();
+                            return [2 /*return*/];
+                    }
+                });
+            });
+        }
+    };
+    return C;
+}());
diff --git a/tests/baselines/reference/asyncUnParenthesizedArrowFunction_es5.js b/tests/baselines/reference/asyncUnParenthesizedArrowFunction_es5.js
new file mode 100644
index 0000000000000..20b0421d01324
--- /dev/null
+++ b/tests/baselines/reference/asyncUnParenthesizedArrowFunction_es5.js
@@ -0,0 +1,20 @@
+//// [asyncUnParenthesizedArrowFunction_es5.ts]
+
+declare function someOtherFunction(i: any): Promise<void>;
+const x = async i => await someOtherFunction(i)
+const x1 = async (i) => await someOtherFunction(i);
+
+//// [asyncUnParenthesizedArrowFunction_es5.js]
+var _this = this;
+var x = function (i) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+    switch (_a.label) {
+        case 0: return [4 /*yield*/, someOtherFunction(i)];
+        case 1: return [2 /*return*/, _a.sent()];
+    }
+}); }); };
+var x1 = function (i) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+    switch (_a.label) {
+        case 0: return [4 /*yield*/, someOtherFunction(i)];
+        case 1: return [2 /*return*/, _a.sent()];
+    }
+}); }); };
diff --git a/tests/baselines/reference/asyncUnParenthesizedArrowFunction_es5.symbols b/tests/baselines/reference/asyncUnParenthesizedArrowFunction_es5.symbols
new file mode 100644
index 0000000000000..0f43ba7773e01
--- /dev/null
+++ b/tests/baselines/reference/asyncUnParenthesizedArrowFunction_es5.symbols
@@ -0,0 +1,19 @@
+=== tests/cases/conformance/async/es5/asyncArrowFunction/asyncUnParenthesizedArrowFunction_es5.ts ===
+
+declare function someOtherFunction(i: any): Promise<void>;
+>someOtherFunction : Symbol(someOtherFunction, Decl(asyncUnParenthesizedArrowFunction_es5.ts, 0, 0))
+>i : Symbol(i, Decl(asyncUnParenthesizedArrowFunction_es5.ts, 1, 35))
+>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
+
+const x = async i => await someOtherFunction(i)
+>x : Symbol(x, Decl(asyncUnParenthesizedArrowFunction_es5.ts, 2, 5))
+>i : Symbol(i, Decl(asyncUnParenthesizedArrowFunction_es5.ts, 2, 15))
+>someOtherFunction : Symbol(someOtherFunction, Decl(asyncUnParenthesizedArrowFunction_es5.ts, 0, 0))
+>i : Symbol(i, Decl(asyncUnParenthesizedArrowFunction_es5.ts, 2, 15))
+
+const x1 = async (i) => await someOtherFunction(i);
+>x1 : Symbol(x1, Decl(asyncUnParenthesizedArrowFunction_es5.ts, 3, 5))
+>i : Symbol(i, Decl(asyncUnParenthesizedArrowFunction_es5.ts, 3, 18))
+>someOtherFunction : Symbol(someOtherFunction, Decl(asyncUnParenthesizedArrowFunction_es5.ts, 0, 0))
+>i : Symbol(i, Decl(asyncUnParenthesizedArrowFunction_es5.ts, 3, 18))
+
diff --git a/tests/baselines/reference/asyncUnParenthesizedArrowFunction_es5.types b/tests/baselines/reference/asyncUnParenthesizedArrowFunction_es5.types
new file mode 100644
index 0000000000000..745c56cf09b77
--- /dev/null
+++ b/tests/baselines/reference/asyncUnParenthesizedArrowFunction_es5.types
@@ -0,0 +1,25 @@
+=== tests/cases/conformance/async/es5/asyncArrowFunction/asyncUnParenthesizedArrowFunction_es5.ts ===
+
+declare function someOtherFunction(i: any): Promise<void>;
+>someOtherFunction : (i: any) => Promise<void>
+>i : any
+>Promise : Promise<T>
+
+const x = async i => await someOtherFunction(i)
+>x : (i: any) => Promise<void>
+>async i => await someOtherFunction(i) : (i: any) => Promise<void>
+>i : any
+>await someOtherFunction(i) : void
+>someOtherFunction(i) : Promise<void>
+>someOtherFunction : (i: any) => Promise<void>
+>i : any
+
+const x1 = async (i) => await someOtherFunction(i);
+>x1 : (i: any) => Promise<void>
+>async (i) => await someOtherFunction(i) : (i: any) => Promise<void>
+>i : any
+>await someOtherFunction(i) : void
+>someOtherFunction(i) : Promise<void>
+>someOtherFunction : (i: any) => Promise<void>
+>i : any
+
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/arrowFunctionWithParameterNameAsync_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/arrowFunctionWithParameterNameAsync_es5.ts
new file mode 100644
index 0000000000000..e6bb588b2b0ac
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/arrowFunctionWithParameterNameAsync_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+
+const x = async => async;
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction10_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction10_es5.ts
new file mode 100644
index 0000000000000..14540c2a232e4
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction10_es5.ts
@@ -0,0 +1,8 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+
+var foo = async (): Promise<void> => {
+   // Legal to use 'await' in a type context.
+   var v: await;
+}
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction1_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction1_es5.ts
new file mode 100644
index 0000000000000..d2aaea2a481ee
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction1_es5.ts
@@ -0,0 +1,6 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+
+var foo = async (): Promise<void> => {
+};
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction2_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction2_es5.ts
new file mode 100644
index 0000000000000..120b5127a0078
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction2_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+var f = (await) => {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction3_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction3_es5.ts
new file mode 100644
index 0000000000000..810d7bc7e0568
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction3_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+function f(await = await) {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction4_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction4_es5.ts
new file mode 100644
index 0000000000000..e6b2bab3c792a
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction4_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+var await = () => {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction5_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction5_es5.ts
new file mode 100644
index 0000000000000..728e2e8ee7252
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction5_es5.ts
@@ -0,0 +1,6 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+
+var foo = async (await): Promise<void> => {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction6_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction6_es5.ts
new file mode 100644
index 0000000000000..41e26b2e6955a
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction6_es5.ts
@@ -0,0 +1,6 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+
+var foo = async (a = await): Promise<void> => {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction7_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction7_es5.ts
new file mode 100644
index 0000000000000..f99ea629dd6c1
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction7_es5.ts
@@ -0,0 +1,9 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+
+var bar = async (): Promise<void> => {
+  // 'await' here is an identifier, and not an await expression.
+  var foo = async (a = await): Promise<void> => {
+  }
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction8_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction8_es5.ts
new file mode 100644
index 0000000000000..4331a1c151a06
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction8_es5.ts
@@ -0,0 +1,7 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+
+var foo = async (): Promise<void> => {
+  var v = { [await]: foo }
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction9_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction9_es5.ts
new file mode 100644
index 0000000000000..7f1e072a3f2ae
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction9_es5.ts
@@ -0,0 +1,5 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+var foo = async (a = await => await): Promise<void> => {
+}
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesArguments_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesArguments_es5.ts
new file mode 100644
index 0000000000000..4a800c1c2ceb8
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesArguments_es5.ts
@@ -0,0 +1,9 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+class C {
+   method() {
+      function other() {}
+      var fn = async () => await other.apply(this, arguments);
+   }
+}
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesThis_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesThis_es5.ts
new file mode 100644
index 0000000000000..e863af244903c
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesThis_es5.ts
@@ -0,0 +1,8 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+class C {
+   method() {
+      var fn = async () => await this;
+   }
+}
diff --git a/tests/cases/conformance/async/es5/asyncArrowFunction/asyncUnParenthesizedArrowFunction_es5.ts b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncUnParenthesizedArrowFunction_es5.ts
new file mode 100644
index 0000000000000..7db76c570848e
--- /dev/null
+++ b/tests/cases/conformance/async/es5/asyncArrowFunction/asyncUnParenthesizedArrowFunction_es5.ts
@@ -0,0 +1,7 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+
+declare function someOtherFunction(i: any): Promise<void>;
+const x = async i => await someOtherFunction(i)
+const x1 = async (i) => await someOtherFunction(i);
\ No newline at end of file
diff --git a/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclarationCapturesArguments_es5.ts b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclarationCapturesArguments_es5.ts
new file mode 100644
index 0000000000000..b5c82688ddf65
--- /dev/null
+++ b/tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclarationCapturesArguments_es5.ts
@@ -0,0 +1,11 @@
+// @target: ES5
+// @lib: es5,es2015.promise
+// @noEmitHelpers: true
+class C {
+   method() {
+      function other() {}
+      async function fn () {
+           await other.apply(this, arguments);
+      }
+   }
+}

From 9e3d6f8585539cc32cf96b7401c855d2afaba947 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 27 Jun 2016 17:39:24 -0700
Subject: [PATCH 21/23] Additional comments per PR feedback.

---
 src/compiler/binder.ts | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts
index 1634d94e439c9..aa06d7ac45d0b 100644
--- a/src/compiler/binder.ts
+++ b/src/compiler/binder.ts
@@ -2590,14 +2590,17 @@ namespace ts {
                 transformFlags |= TransformFlags.AssertTypeScript;
             }
 
-            // If a FunctionDeclaration has an asterisk token, is exported, or its
-            // subtree has marked the container as needing to capture the lexical `this`,
-            // then this node is ES6 syntax.
+            // If a FunctionDeclaration is exported or its subtree has marked the container as
+            // needing to capture the lexical `this`, then this node is ES6 syntax.
             if (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask) {
                 transformFlags |= TransformFlags.AssertES6;
             }
 
-            // Currently, we only support generators that were originally async function bodies.
+            // If a FunctionDeclaration is generator function and is the body of a
+            // transformed async function, then this node can be transformed to a
+            // down-level generator.
+            // Currently we do not support transforming any other generator fucntions
+            // down level.
             if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
                 transformFlags |= TransformFlags.AssertGenerator;
             }
@@ -2623,7 +2626,11 @@ namespace ts {
             transformFlags |= TransformFlags.AssertES6;
         }
 
-        // Currently, we only support generators that were originally async function bodies.
+        // If a FunctionExpression is generator function and is the body of a
+        // transformed async function, then this node can be transformed to a
+        // down-level generator.
+        // Currently we do not support transforming any other generator fucntions
+        // down level.
         if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
             transformFlags |= TransformFlags.AssertGenerator;
         }

From c832444f1efa518d1e066db66ecb82439ce6f456 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 18 Jul 2016 15:54:32 -0700
Subject: [PATCH 22/23] Accept baselines plus new linter warnings.

---
 .../asyncFunctionNoReturnType.errors.txt      |  5 +-
 .../reference/asyncFunctionNoReturnType.js    | 46 +++++++++++++++++--
 tests/cases/unittests/transpile.ts            |  6 +--
 3 files changed, 47 insertions(+), 10 deletions(-)

diff --git a/tests/baselines/reference/asyncFunctionNoReturnType.errors.txt b/tests/baselines/reference/asyncFunctionNoReturnType.errors.txt
index a7dbb6ecb6466..599bf41a7f2b5 100644
--- a/tests/baselines/reference/asyncFunctionNoReturnType.errors.txt
+++ b/tests/baselines/reference/asyncFunctionNoReturnType.errors.txt
@@ -1,5 +1,4 @@
 error TS2318: Cannot find global type 'Promise'.
-tests/cases/compiler/asyncFunctionNoReturnType.ts(1,1): error TS1311: Async functions are only available when targeting ECMAScript 2015 or higher.
 tests/cases/compiler/asyncFunctionNoReturnType.ts(1,1): error TS1057: An async function or method must have a valid awaitable return type.
 tests/cases/compiler/asyncFunctionNoReturnType.ts(1,1): error TS7030: Not all code paths return a value.
 tests/cases/compiler/asyncFunctionNoReturnType.ts(2,9): error TS2304: Cannot find name 'window'.
@@ -7,10 +6,8 @@ tests/cases/compiler/asyncFunctionNoReturnType.ts(3,9): error TS7030: Not all co
 
 
 !!! error TS2318: Cannot find global type 'Promise'.
-==== tests/cases/compiler/asyncFunctionNoReturnType.ts (5 errors) ====
+==== tests/cases/compiler/asyncFunctionNoReturnType.ts (4 errors) ====
     async () => {
-    ~~~~~
-!!! error TS1311: Async functions are only available when targeting ECMAScript 2015 or higher.
     ~~~~~~~~~~~~~
 !!! error TS1057: An async function or method must have a valid awaitable return type.
     ~~~~~~~~~~~~~
diff --git a/tests/baselines/reference/asyncFunctionNoReturnType.js b/tests/baselines/reference/asyncFunctionNoReturnType.js
index 1d321eea51c2c..a3635b85a094e 100644
--- a/tests/baselines/reference/asyncFunctionNoReturnType.js
+++ b/tests/baselines/reference/asyncFunctionNoReturnType.js
@@ -14,8 +14,48 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
         step((generator = generator.apply(thisArg, _arguments)).next());
     });
 };
+var __generator = (this && this.__generator) || function (thisArg, body) {
+    var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
+    function step(op) {
+        if (f) throw new TypeError("Generator is already executing.");
+        while (1) {
+            if (_.done) switch (op[0]) {
+                case 0: return { value: void 0, done: true };
+                case 1: case 6: throw op[1];
+                case 2: return { value: op[1], done: true };
+            }
+            try {
+                switch (f = 1, op[0]) {
+                    case 0: case 1: sent = op; break;
+                    case 4: return _.label++, { value: op[1], done: false };
+                    case 7: op = _.stack.pop(), _.trys.pop(); continue;
+                    default:
+                        var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
+                        if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; }
+                        if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; }
+                        if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; }
+                        if (r && _.label < r[2]) { _.label = r[2], _.stack.push(op); break; }
+                        if (r[2]) { _.stack.pop(); }
+                        _.trys.pop();
+                        continue;
+                }
+                op = body.call(thisArg, _);
+            }
+            catch (e) { op = [6, e]; }
+            finally { f = 0, sent = void 0; }
+        }
+    }
+    return {
+        next: function (v) { return step([0, v]); },
+        "throw": function (v) { return step([1, v]); },
+        "return": function (v) { return step([2, v]); }
+    };
+};
 var _this = this;
-(function () { return __awaiter(_this, void 0, void 0, function* () {
-    if (window)
-        return;
+(function () { return __awaiter(_this, void 0, void 0, function () {
+    return __generator(this, function (_a) {
+        if (window)
+            return [2 /*return*/];
+        return [2 /*return*/];
+    });
 }); });
diff --git a/tests/cases/unittests/transpile.ts b/tests/cases/unittests/transpile.ts
index 24db2cbf16aad..9581996bdd0e2 100644
--- a/tests/cases/unittests/transpile.ts
+++ b/tests/cases/unittests/transpile.ts
@@ -231,11 +231,11 @@ var x = 0;`, {
         });
 
         transpilesCorrectly("Report an error when compiler-options input is empty object", "", {
-            options: { compilerOptions: { module: <ModuleKind><any>{} }}
+            options: { compilerOptions: { module: <ModuleKind><any>{ } } }
         });
 
         transpilesCorrectly("Report an error when compiler-options input is empty string", "", {
-            options: { compilerOptions: { module: <ModuleKind><any>"" }}
+            options: { compilerOptions: { module: <ModuleKind><any>"" } }
         });
 
         transpilesCorrectly("Support options with lib values", "const a = 10;", {
@@ -475,5 +475,5 @@ var x = 0;`, {
                 }
             }
         });
-    })
+    });
 }

From c2857672dcb70b9985220b374ffec6c018346c55 Mon Sep 17 00:00:00 2001
From: Ron Buckton <rbuckton@microsoft.com>
Date: Mon, 18 Jul 2016 15:57:06 -0700
Subject: [PATCH 23/23] Updated comment

---
 src/compiler/binder.ts | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts
index 782ed87c81888..baa585fb9ba37 100644
--- a/src/compiler/binder.ts
+++ b/src/compiler/binder.ts
@@ -2643,8 +2643,9 @@ namespace ts {
                 transformFlags |= TransformFlags.AssertTypeScript;
             }
 
-            // If a FunctionDeclaration is exported or its subtree has marked the container as
-            // needing to capture the lexical `this`, then this node is ES6 syntax.
+            // If a FunctionDeclaration's subtree has marked the container as needing to capture the
+            // lexical this, or the function contains parameters with initializers, then this node is
+            // ES6 syntax.
             if (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask) {
                 transformFlags |= TransformFlags.AssertES6;
             }
@@ -2673,8 +2674,9 @@ namespace ts {
             transformFlags |= TransformFlags.AssertTypeScript;
         }
 
-        // If a FunctionExpression contains an asterisk token, or its subtree has marked the container
-        // as needing to capture the lexical this, then this node is ES6 syntax.
+        // If a FunctionExpression's subtree has marked the container as needing to capture the
+        // lexical this, or the function contains parameters with initializers, then this node is
+        // ES6 syntax.
         if (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask) {
             transformFlags |= TransformFlags.AssertES6;
         }