From ea808f52fe3dd70dedc6294ebda26a4100767ad1 Mon Sep 17 00:00:00 2001 From: Slawomir Sadziak Date: Mon, 10 Oct 2016 12:15:34 +0200 Subject: [PATCH] Fix #10758 Add compiler option to parse in strict mode * add unit test to ensure "use strict" is not added twice * fix code --- src/compiler/factory.ts | 30 +++++++++++++++++++ src/compiler/transformers/ts.ts | 9 +----- .../reference/alwaysStrictAlreadyUseStrict.js | 11 +++++++ .../alwaysStrictAlreadyUseStrict.symbols | 8 +++++ .../alwaysStrictAlreadyUseStrict.types | 11 +++++++ .../compiler/alwaysStrictAlreadyUseStrict.ts | 5 ++++ 6 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/alwaysStrictAlreadyUseStrict.js create mode 100644 tests/baselines/reference/alwaysStrictAlreadyUseStrict.symbols create mode 100644 tests/baselines/reference/alwaysStrictAlreadyUseStrict.types create mode 100644 tests/cases/compiler/alwaysStrictAlreadyUseStrict.ts diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 97a36f46b1..6bf6259c36 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2235,6 +2235,36 @@ namespace ts { return statementOffset; } + /** + * Ensures "use strict" directive is added + * + * @param node source file + */ + export function ensureUseStrict(node: SourceFile): SourceFile { + let foundUseStrict = false; + let statementOffset = 0; + const numStatements = node.statements.length; + while (statementOffset < numStatements) { + const statement = node.statements[statementOffset]; + if (isPrologueDirective(statement)) { + if (isUseStrictPrologue(statement as ExpressionStatement)) { + foundUseStrict = true; + } + } + else { + break; + } + statementOffset++; + } + if (!foundUseStrict) { + const statements: Statement[] = []; + statements.push(startOnNewLine(createStatement(createLiteral("use strict")))); + // add "use strict" as the first statement + return updateSourceFileNode(node, statements.concat(node.statements)); + } + return node; + } + /** * Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended * order of operations. diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 7b6c28a8f4..112f838a37 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -438,7 +438,7 @@ namespace ts { // ensure "use strict"" is emitted in all scenarios in alwaysStrict mode if (compilerOptions.alwaysStrict) { - node = emitUseStrict(node); + node = ensureUseStrict(node); } // If the source file requires any helpers and is an external module, and @@ -477,13 +477,6 @@ namespace ts { return node; } - function emitUseStrict(node: SourceFile): SourceFile { - const statements: Statement[] = []; - statements.push(startOnNewLine(createStatement(createLiteral("use strict")))); - // add "use strict" as the first statement - return updateSourceFileNode(node, statements.concat(node.statements)); - } - /** * Tests whether we should emit a __decorate call for a class declaration. */ diff --git a/tests/baselines/reference/alwaysStrictAlreadyUseStrict.js b/tests/baselines/reference/alwaysStrictAlreadyUseStrict.js new file mode 100644 index 0000000000..cc3be45ded --- /dev/null +++ b/tests/baselines/reference/alwaysStrictAlreadyUseStrict.js @@ -0,0 +1,11 @@ +//// [alwaysStrictAlreadyUseStrict.ts] +"use strict" +function f() { + var a = []; +} + +//// [alwaysStrictAlreadyUseStrict.js] +"use strict"; +function f() { + var a = []; +} diff --git a/tests/baselines/reference/alwaysStrictAlreadyUseStrict.symbols b/tests/baselines/reference/alwaysStrictAlreadyUseStrict.symbols new file mode 100644 index 0000000000..143f579b94 --- /dev/null +++ b/tests/baselines/reference/alwaysStrictAlreadyUseStrict.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/alwaysStrictAlreadyUseStrict.ts === +"use strict" +function f() { +>f : Symbol(f, Decl(alwaysStrictAlreadyUseStrict.ts, 0, 12)) + + var a = []; +>a : Symbol(a, Decl(alwaysStrictAlreadyUseStrict.ts, 2, 7)) +} diff --git a/tests/baselines/reference/alwaysStrictAlreadyUseStrict.types b/tests/baselines/reference/alwaysStrictAlreadyUseStrict.types new file mode 100644 index 0000000000..0181b40de2 --- /dev/null +++ b/tests/baselines/reference/alwaysStrictAlreadyUseStrict.types @@ -0,0 +1,11 @@ +=== tests/cases/compiler/alwaysStrictAlreadyUseStrict.ts === +"use strict" +>"use strict" : "use strict" + +function f() { +>f : () => void + + var a = []; +>a : any[] +>[] : undefined[] +} diff --git a/tests/cases/compiler/alwaysStrictAlreadyUseStrict.ts b/tests/cases/compiler/alwaysStrictAlreadyUseStrict.ts new file mode 100644 index 0000000000..1d804a6cf9 --- /dev/null +++ b/tests/cases/compiler/alwaysStrictAlreadyUseStrict.ts @@ -0,0 +1,5 @@ +// @alwaysStrict: true +"use strict" +function f() { + var a = []; +} \ No newline at end of file