Skip to content

Commit d56ac44

Browse files
committed
[Transforms] fix _this = this capture emitted before "use strict" directives in AMD module output (microsoft#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
1 parent c21ff64 commit d56ac44

3 files changed

Lines changed: 21 additions & 3 deletions

File tree

src/compiler/factory.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,7 +1252,18 @@ namespace ts {
12521252
return (node.expression as StringLiteral).text === "use strict";
12531253
}
12541254

1255+
/**
1256+
* Add any necessary prologue-directives into target statement-array.
1257+
* The function needs to be called during each transformation step.
1258+
* This function needs to be called whenever we transform the statement
1259+
* list of a source file, namespace, or function-like body.
1260+
*
1261+
* @param target: result statements array
1262+
* @param source: origin statements array
1263+
* @param ensureUseStrict: boolean determining whether the function need to add prologue-directives
1264+
*/
12551265
export function addPrologueDirectives(target: Statement[], source: Statement[], ensureUseStrict?: boolean): number {
1266+
Debug.assert(target.length === 0, "PrologueDirectives should be at the first statement in the target statements array");
12561267
let foundUseStrict = false;
12571268
for (let i = 0; i < source.length; i++) {
12581269
if (isPrologueDirective(source[i])) {

src/compiler/transformers/es6.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,15 @@ namespace ts {
12111211
let statementsLocation: TextRange;
12121212

12131213
const statements: Statement[] = [];
1214+
const body = node.body;
1215+
let statementOffset: number;
1216+
12141217
startLexicalEnvironment();
1218+
if (isBlock(body)) {
1219+
// ensureUseStrict is false because no new prologue-directive should be added.
1220+
// addPrologueDirectives will simply put already-existing directives at the beginning of the target statement-array
1221+
statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false);
1222+
}
12151223
addCaptureThisForNodeIfNeeded(statements, node);
12161224
addDefaultValueAssignmentsIfNeeded(statements, node);
12171225
addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false);
@@ -1221,10 +1229,9 @@ namespace ts {
12211229
multiLine = true;
12221230
}
12231231

1224-
const body = node.body;
12251232
if (isBlock(body)) {
12261233
statementsLocation = body.statements;
1227-
addRange(statements, visitNodes(body.statements, visitor, isStatement));
1234+
addRange(statements, visitNodes(body.statements, visitor, isStatement, statementOffset));
12281235

12291236
// If the original body was a multi-line block, this must be a multi-line block.
12301237
if (!multiLine && body.multiLine) {

src/compiler/transformers/module/system.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ namespace ts {
193193
startLexicalEnvironment();
194194

195195
// Add any prologue directives.
196-
const statementOffset = addPrologueDirectives(statements, node.statements, !compilerOptions.noImplicitUseStrict);
196+
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict);
197197

198198
// var __moduleName = context_1 && context_1.id;
199199
addNode(statements,

0 commit comments

Comments
 (0)