From 73c59bbf859a22424871ced74997b15e1c6d2f60 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 28 Oct 2016 14:43:08 -0700 Subject: [PATCH] do not inline async IIFEs in control flow graph --- src/compiler/binder.ts | 4 +-- tests/baselines/reference/asyncIIFE.js | 28 +++++++++++++++++++++ tests/baselines/reference/asyncIIFE.symbols | 16 ++++++++++++ tests/baselines/reference/asyncIIFE.types | 25 ++++++++++++++++++ tests/cases/compiler/asyncIIFE.ts | 10 ++++++++ 5 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/asyncIIFE.js create mode 100644 tests/baselines/reference/asyncIIFE.symbols create mode 100644 tests/baselines/reference/asyncIIFE.types create mode 100644 tests/cases/compiler/asyncIIFE.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 447a7625d38..c0466e7871a 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -490,8 +490,8 @@ namespace ts { const saveReturnTarget = currentReturnTarget; const saveActiveLabels = activeLabels; const saveHasExplicitReturn = hasExplicitReturn; - const isIIFE = containerFlags & ContainerFlags.IsFunctionExpression && !!getImmediatelyInvokedFunctionExpression(node); - // An IIFE is considered part of the containing control flow. Return statements behave + const isIIFE = containerFlags & ContainerFlags.IsFunctionExpression && !hasModifier(node, ModifierFlags.Async) && !!getImmediatelyInvokedFunctionExpression(node); + // A non-async IIFE is considered part of the containing control flow. Return statements behave // similarly to break statements that exit to a label just past the statement body. if (isIIFE) { currentReturnTarget = createBranchLabel(); diff --git a/tests/baselines/reference/asyncIIFE.js b/tests/baselines/reference/asyncIIFE.js new file mode 100644 index 00000000000..79779af62f3 --- /dev/null +++ b/tests/baselines/reference/asyncIIFE.js @@ -0,0 +1,28 @@ +//// [asyncIIFE.ts] + +function f1() { + (async () => { + await 10 + throw new Error(); + })(); + + var x = 1; +} + + +//// [asyncIIFE.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()); + }); +}; +function f1() { + (() => __awaiter(this, void 0, void 0, function* () { + yield 10; + throw new Error(); + }))(); + var x = 1; +} diff --git a/tests/baselines/reference/asyncIIFE.symbols b/tests/baselines/reference/asyncIIFE.symbols new file mode 100644 index 00000000000..92eb054bff0 --- /dev/null +++ b/tests/baselines/reference/asyncIIFE.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/asyncIIFE.ts === + +function f1() { +>f1 : Symbol(f1, Decl(asyncIIFE.ts, 0, 0)) + + (async () => { + await 10 + throw new Error(); +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + })(); + + var x = 1; +>x : Symbol(x, Decl(asyncIIFE.ts, 7, 7)) +} + diff --git a/tests/baselines/reference/asyncIIFE.types b/tests/baselines/reference/asyncIIFE.types new file mode 100644 index 00000000000..e49ab96681f --- /dev/null +++ b/tests/baselines/reference/asyncIIFE.types @@ -0,0 +1,25 @@ +=== tests/cases/compiler/asyncIIFE.ts === + +function f1() { +>f1 : () => void + + (async () => { +>(async () => { await 10 throw new Error(); })() : Promise +>(async () => { await 10 throw new Error(); }) : () => Promise +>async () => { await 10 throw new Error(); } : () => Promise + + await 10 +>await 10 : 10 +>10 : 10 + + throw new Error(); +>new Error() : Error +>Error : ErrorConstructor + + })(); + + var x = 1; +>x : number +>1 : 1 +} + diff --git a/tests/cases/compiler/asyncIIFE.ts b/tests/cases/compiler/asyncIIFE.ts new file mode 100644 index 00000000000..904476d855c --- /dev/null +++ b/tests/cases/compiler/asyncIIFE.ts @@ -0,0 +1,10 @@ +// @target: ES6 + +function f1() { + (async () => { + await 10 + throw new Error(); + })(); + + var x = 1; +}