From d56ac44a27d54a7050ffaa8c29d037e0a8ffc466 Mon Sep 17 00:00:00 2001 From: Yui Date: Thu, 14 Apr 2016 09:41:12 -0700 Subject: [PATCH] [Transforms] fix `_this = this` capture emitted before `"use strict"` directives in AMD module output (#7953) * Fix 7913: emit prologue directives as a first statement in emitted AMD module * Do not ensure that prologue-directive is added when using it when transforming function body * Address PR: preserve prologue directives location and make sure it is the first statement in the result statements array * Address PR: fix comment --- src/compiler/factory.ts | 11 +++++++++++ src/compiler/transformers/es6.ts | 11 +++++++++-- src/compiler/transformers/module/system.ts | 2 +- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index e35c5a08297..928ba76699e 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1252,7 +1252,18 @@ namespace ts { return (node.expression as StringLiteral).text === "use strict"; } + /** + * Add any necessary prologue-directives into target statement-array. + * The function needs to be called during each transformation step. + * This function needs to be called whenever we transform the statement + * list of a source file, namespace, or function-like body. + * + * @param target: result statements array + * @param source: origin statements array + * @param ensureUseStrict: boolean determining whether the function need to add prologue-directives + */ export function addPrologueDirectives(target: Statement[], source: Statement[], ensureUseStrict?: boolean): 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])) { diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index 796dd9529ad..7b769889dca 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -1211,7 +1211,15 @@ namespace ts { let statementsLocation: TextRange; const statements: Statement[] = []; + const body = node.body; + let statementOffset: number; + startLexicalEnvironment(); + 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); + } addCaptureThisForNodeIfNeeded(statements, node); addDefaultValueAssignmentsIfNeeded(statements, node); addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false); @@ -1221,10 +1229,9 @@ namespace ts { multiLine = true; } - const body = node.body; if (isBlock(body)) { statementsLocation = body.statements; - addRange(statements, visitNodes(body.statements, visitor, isStatement)); + addRange(statements, visitNodes(body.statements, visitor, isStatement, statementOffset)); // If the original body was a multi-line block, this must be a multi-line block. if (!multiLine && body.multiLine) { diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 663917170ef..eee50781f32 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -193,7 +193,7 @@ namespace ts { startLexicalEnvironment(); // Add any prologue directives. - const statementOffset = addPrologueDirectives(statements, node.statements, !compilerOptions.noImplicitUseStrict); + const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict); // var __moduleName = context_1 && context_1.id; addNode(statements,