diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index b438811940d..18b58c34620 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -265,7 +265,7 @@ namespace ts { /** Resumes a suspended lexical environment, usually before visiting a function body. */ function resumeLexicalEnvironment(): void { Debug.assert(!scopeModificationDisabled, "Cannot resume a lexical environment during the print phase."); - Debug.assert(lexicalEnvironmentSuspended, "Lexical environment is not suspended suspended."); + Debug.assert(lexicalEnvironmentSuspended, "Lexical environment is not suspended."); lexicalEnvironmentSuspended = false; } diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index d80ef367dcf..7a11a62e7d7 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -840,14 +840,14 @@ namespace ts { * @param hasSynthesizedSuper A value indicating whether the constructor starts with a * synthesized `super` call. */ - function transformConstructorParameters(constructor: ConstructorDeclaration, hasSynthesizedSuper: boolean): ParameterDeclaration[] { + function transformConstructorParameters(constructor: ConstructorDeclaration, hasSynthesizedSuper: boolean) { // If the TypeScript transformer needed to synthesize a constructor for property // initializers, it would have also added a synthetic `...args` parameter and // `super` call. // If this is the case, we do not include the synthetic `...args` parameter and // will instead use the `arguments` object in ES5/3. return visitParameterList(constructor && !hasSynthesizedSuper && constructor.parameters, visitor, context) - || []; + || []; } /** diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index f380257365e..14f840f2e66 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -61,13 +61,10 @@ namespace ts { } function visitor(node: Node): VisitResult { - if (node.transformFlags & TransformFlags.ContainsES2017) { - return visitorWorker(node); + if ((node.transformFlags & TransformFlags.ContainsES2017) === 0) { + return node; } - return node; - } - function visitorWorker(node: Node): VisitResult { switch (node.kind) { case SyntaxKind.AsyncKeyword: // ES2017 async modifier should be elided for targets < ES2017 @@ -211,6 +208,8 @@ namespace ts { function transformAsyncFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody; function transformAsyncFunctionBody(node: ArrowFunction): ConciseBody; function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody { + resumeLexicalEnvironment(); + const original = getOriginalNode(node, isFunctionLike); const nodeType = original.type; const promiseConstructor = languageVersion < ScriptTarget.ES2015 ? getPromiseConstructor(nodeType) : undefined; @@ -222,7 +221,6 @@ namespace ts { // `this` and `arguments` objects to `__awaiter`. The generator function // passed to `__awaiter` is executed inside of the callback to the // promise constructor. - resumeLexicalEnvironment(); if (!isArrowFunction) { const statements: Statement[] = []; diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 2196c4ec5ff..ab980692416 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -5,11 +5,15 @@ namespace ts { export function transformESNext(context: TransformationContext) { const { + resumeLexicalEnvironment, endLexicalEnvironment } = context; return transformSourceFile; function transformSourceFile(node: SourceFile) { + if (isDeclarationFile(node)) { + return node; + } const visited = visitEachChild(node, visitor, context); addEmitHelpers(visited, context.readEmitHelpers()); @@ -346,6 +350,7 @@ namespace ts { function transformFunctionBody(node: FunctionDeclaration | FunctionExpression | ConstructorDeclaration | MethodDeclaration | AccessorDeclaration): FunctionBody; function transformFunctionBody(node: ArrowFunction): ConciseBody; function transformFunctionBody(node: FunctionLikeDeclaration): ConciseBody { + resumeLexicalEnvironment(); let leadingStatements: Statement[]; for (const parameter of node.parameters) { if (parameter.transformFlags & TransformFlags.ContainsObjectRest) { diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 6047a8d8edd..c383902d495 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -227,7 +227,7 @@ namespace ts { export function transformGenerators(context: TransformationContext) { const { - startLexicalEnvironment, + resumeLexicalEnvironment, endLexicalEnvironment, hoistFunctionDeclaration, hoistVariableDeclaration, @@ -450,11 +450,11 @@ namespace ts { node = setOriginalNode( createFunctionDeclaration( /*decorators*/ undefined, - /*modifiers*/ undefined, + node.modifiers, /*asteriskToken*/ undefined, node.name, /*typeParameters*/ undefined, - node.parameters, + visitParameterList(node.parameters, visitor, context), /*type*/ undefined, transformGeneratorFunctionBody(node.body), /*location*/ node @@ -501,7 +501,7 @@ namespace ts { /*asteriskToken*/ undefined, node.name, /*typeParameters*/ undefined, - node.parameters, + visitParameterList(node.parameters, visitor, context), /*type*/ undefined, transformGeneratorFunctionBody(node.body), /*location*/ node @@ -579,7 +579,7 @@ namespace ts { state = createTempVariable(/*recordTempVariable*/ undefined); // Build the generator - startLexicalEnvironment(); + resumeLexicalEnvironment(); const statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor); @@ -947,7 +947,7 @@ namespace ts { * @param node The node to visit. */ function visitArrayLiteralExpression(node: ArrayLiteralExpression) { - return visitElements(node.elements, node.multiLine); + return visitElements(node.elements, /*leadingElement*/ undefined, /*location*/ undefined, node.multiLine); } /** @@ -957,7 +957,7 @@ namespace ts { * @param elements The elements to visit. * @param multiLine Whether array literals created should be emitted on multiple lines. */ - function visitElements(elements: NodeArray, _multiLine?: boolean) { + function visitElements(elements: NodeArray, leadingElement?: Expression, location?: TextRange, multiLine?: boolean) { // [source] // ar = [1, yield, 2]; // @@ -972,18 +972,22 @@ namespace ts { const temp = declareLocal(); let hasAssignedTemp = false; if (numInitialElements > 0) { + const initialElements = visitNodes(elements, visitor, isExpression, 0, numInitialElements); emitAssignment(temp, createArrayLiteral( - visitNodes(elements, visitor, isExpression, 0, numInitialElements) + leadingElement + ? [leadingElement, ...initialElements] + : initialElements ) ); + leadingElement = undefined; hasAssignedTemp = true; } const expressions = reduceLeft(elements, reduceElement, [], numInitialElements); return hasAssignedTemp - ? createArrayConcat(temp, [createArrayLiteral(expressions)]) - : createArrayLiteral(expressions); + ? createArrayConcat(temp, [createArrayLiteral(expressions, /*location*/ undefined, multiLine)]) + : createArrayLiteral(leadingElement ? [leadingElement, ...expressions] : expressions, location, multiLine); function reduceElement(expressions: Expression[], element: Expression) { if (containsYield(element) && expressions.length > 0) { @@ -992,11 +996,16 @@ namespace ts { hasAssignedTemp ? createArrayConcat( temp, - [createArrayLiteral(expressions)] + [createArrayLiteral(expressions, /*location*/ undefined, multiLine)] + ) + : createArrayLiteral( + leadingElement ? [leadingElement, ...expressions] : expressions, + /*location*/ undefined, + multiLine ) - : createArrayLiteral(expressions) ); hasAssignedTemp = true; + leadingElement = undefined; expressions = []; } @@ -1132,7 +1141,10 @@ namespace ts { createFunctionApply( cacheExpression(visitNode(target, visitor, isExpression)), thisArg, - visitElements(node.arguments) + visitElements( + node.arguments, + /*leadingElement*/ createVoidZero() + ) ), /*typeArguments*/ undefined, [], diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 09dda7ae161..62b2022b7df 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -862,7 +862,6 @@ namespace ts { const statements: Statement[] = []; let indexOfFirstStatement = 0; - // The body of a constructor is a new lexical environment resumeLexicalEnvironment(); if (constructor) { diff --git a/tests/baselines/reference/es5-asyncFunctionNewExpressions.js b/tests/baselines/reference/es5-asyncFunctionNewExpressions.js index 486bf0fdd7f..0fb1140f129 100644 --- a/tests/baselines/reference/es5-asyncFunctionNewExpressions.js +++ b/tests/baselines/reference/es5-asyncFunctionNewExpressions.js @@ -119,7 +119,7 @@ function newExpression2() { _a = x.bind; return [4 /*yield*/, y]; case 1: - new (_a.apply(x, [_c.sent(), z]))(); + new (_a.apply(x, [void 0, _c.sent(), z]))(); return [2 /*return*/]; } }); @@ -132,7 +132,7 @@ function newExpression3() { switch (_c.label) { case 0: _a = x.bind; - _b = [y]; + _b = [void 0, y]; return [4 /*yield*/, z]; case 1: new (_a.apply(x, _b.concat([_c.sent()])))(); @@ -280,7 +280,7 @@ function newExpression13() { _b = (_a = x.a).bind; return [4 /*yield*/, y]; case 1: - new (_b.apply(_a, [_d.sent(), z]))(); + new (_b.apply(_a, [void 0, _d.sent(), z]))(); return [2 /*return*/]; } }); @@ -293,7 +293,7 @@ function newExpression14() { switch (_d.label) { case 0: _b = (_a = x.a).bind; - _c = [y]; + _c = [void 0, y]; return [4 /*yield*/, z]; case 1: new (_b.apply(_a, _c.concat([_d.sent()])))(); @@ -362,7 +362,7 @@ function newExpression19() { _b = (_a = x[a]).bind; return [4 /*yield*/, y]; case 1: - new (_b.apply(_a, [_d.sent(), z]))(); + new (_b.apply(_a, [void 0, _d.sent(), z]))(); return [2 /*return*/]; } }); @@ -375,7 +375,7 @@ function newExpression20() { switch (_d.label) { case 0: _b = (_a = x[a]).bind; - _c = [y]; + _c = [void 0, y]; return [4 /*yield*/, z]; case 1: new (_b.apply(_a, _c.concat([_d.sent()])))();