Skip to content

Commit

Permalink
Fix microsoft#10758 Add compiler option to parse in strict mode
Browse files Browse the repository at this point in the history
 * add compiler option alwaysStrict
 * compile in strict mode when option is set
 * emit "use strict"
  • Loading branch information
slawomir committed Oct 9, 2016
1 parent d34916a commit 29a85e0
Show file tree
Hide file tree
Showing 19 changed files with 170 additions and 2 deletions.
15 changes: 13 additions & 2 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ namespace ts {

// If this file is an external module, then it is automatically in strict-mode according to
// ES6. If it is not an external module, then we'll determine if it is in strict mode or
// not depending on if we see "use strict" in certain places (or if we hit a class/namespace).
// not depending on if we see "use strict" in certain places or if we hit a class/namespace
// or if compiler options contain alwaysStrict.
let inStrictMode: boolean;

let symbolCount = 0;
Expand All @@ -139,7 +140,7 @@ namespace ts {
file = f;
options = opts;
languageVersion = getEmitScriptTarget(options);
inStrictMode = !!file.externalModuleIndicator;
inStrictMode = bindInStrictMode(file, opts);
classifiableNames = createMap<string>();
symbolCount = 0;
skipTransformFlagAggregation = isDeclarationFile(file);
Expand Down Expand Up @@ -174,6 +175,16 @@ namespace ts {

return bindSourceFile;

function bindInStrictMode(file: SourceFile, opts: CompilerOptions): boolean {
if (opts.alwaysStrict && !isDeclarationFile(file)) {
// bind in strict mode source files with alwaysStrict option
return true;
}
else {
return !!file.externalModuleIndicator;
}
}

function createSymbol(flags: SymbolFlags, name: string): Symbol {
symbolCount++;
return new Symbol(flags, name);
Expand Down
5 changes: 5 additions & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,11 @@ namespace ts {
name: "importHelpers",
type: "boolean",
description: Diagnostics.Import_emit_helpers_from_tslib
},
{
name: "alwaysStrict",
type: "boolean",
description: Diagnostics.Parse_in_strict_mode_and_emit_use_strict_for_each_source_file
}
];

Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2861,6 +2861,10 @@
"category": "Error",
"code": 6140
},
"Parse in strict mode and emit \"use strict\" for each source file": {
"category": "Message",
"code": 6141
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
Expand Down
12 changes: 12 additions & 0 deletions src/compiler/transformers/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,11 @@ namespace ts {
function visitSourceFile(node: SourceFile) {
currentSourceFile = node;

// ensure "use strict"" is emitted in all scenarios in alwaysStrict mode
if (compilerOptions.alwaysStrict) {
node = emitUseStrict(node);
}

// If the source file requires any helpers and is an external module, and
// the importHelpers compiler option is enabled, emit a synthesized import
// statement for the helpers library.
Expand Down Expand Up @@ -472,6 +477,13 @@ 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.
*/
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2929,6 +2929,7 @@ namespace ts {
allowSyntheticDefaultImports?: boolean;
allowUnreachableCode?: boolean;
allowUnusedLabels?: boolean;
alwaysStrict?: boolean;
baseUrl?: string;
charset?: string;
/* @internal */ configFilePath?: string;
Expand Down
4 changes: 4 additions & 0 deletions src/harness/unittests/transpile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ var x = 0;`, {
options: { compilerOptions: { allowUnusedLabels: true }, fileName: "input.js", reportDiagnostics: true }
});

transpilesCorrectly("Supports setting 'alwaysStrict'", "x;", {
options: { compilerOptions: { alwaysStrict: true }, fileName: "input.js", reportDiagnostics: true }
});

transpilesCorrectly("Supports setting 'baseUrl'", "x;", {
options: { compilerOptions: { baseUrl: "./folder/baseUrl" }, fileName: "input.js", reportDiagnostics: true }
});
Expand Down
10 changes: 10 additions & 0 deletions tests/baselines/reference/alwaysStrict.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
tests/cases/compiler/alwaysStrict.ts(3,9): error TS1100: Invalid use of 'arguments' in strict mode.


==== tests/cases/compiler/alwaysStrict.ts (1 errors) ====

function f() {
var arguments = [];
~~~~~~~~~
!!! error TS1100: Invalid use of 'arguments' in strict mode.
}
11 changes: 11 additions & 0 deletions tests/baselines/reference/alwaysStrict.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//// [alwaysStrict.ts]

function f() {
var arguments = [];
}

//// [alwaysStrict.js]
"use strict";
function f() {
var arguments = [];
}
10 changes: 10 additions & 0 deletions tests/baselines/reference/alwaysStrictES6.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
tests/cases/compiler/alwaysStrictES6.ts(3,9): error TS1100: Invalid use of 'arguments' in strict mode.


==== tests/cases/compiler/alwaysStrictES6.ts (1 errors) ====

function f() {
var arguments = [];
~~~~~~~~~
!!! error TS1100: Invalid use of 'arguments' in strict mode.
}
11 changes: 11 additions & 0 deletions tests/baselines/reference/alwaysStrictES6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//// [alwaysStrictES6.ts]

function f() {
var arguments = [];
}

//// [alwaysStrictES6.js]
"use strict";
function f() {
var arguments = [];
}
12 changes: 12 additions & 0 deletions tests/baselines/reference/alwaysStrictModule.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
tests/cases/compiler/alwaysStrictModule.ts(4,13): error TS1100: Invalid use of 'arguments' in strict mode.


==== tests/cases/compiler/alwaysStrictModule.ts (1 errors) ====

module M {
export function f() {
var arguments = [];
~~~~~~~~~
!!! error TS1100: Invalid use of 'arguments' in strict mode.
}
}
17 changes: 17 additions & 0 deletions tests/baselines/reference/alwaysStrictModule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//// [alwaysStrictModule.ts]

module M {
export function f() {
var arguments = [];
}
}

//// [alwaysStrictModule.js]
"use strict";
var M;
(function (M) {
function f() {
var arguments = [];
}
M.f = f;
})(M || (M = {}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
tests/cases/compiler/alwaysStrictNoImplicitUseStrict.ts(4,13): error TS1100: Invalid use of 'arguments' in strict mode.


==== tests/cases/compiler/alwaysStrictNoImplicitUseStrict.ts (1 errors) ====

module M {
export function f() {
var arguments = [];
~~~~~~~~~
!!! error TS1100: Invalid use of 'arguments' in strict mode.
}
}
17 changes: 17 additions & 0 deletions tests/baselines/reference/alwaysStrictNoImplicitUseStrict.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//// [alwaysStrictNoImplicitUseStrict.ts]

module M {
export function f() {
var arguments = [];
}
}

//// [alwaysStrictNoImplicitUseStrict.js]
"use strict";
var M;
(function (M) {
function f() {
var arguments = [];
}
M.f = f;
})(M || (M = {}));

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions tests/cases/compiler/alwaysStrict.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// @alwaysStrict: true

function f() {
var arguments = [];
}
6 changes: 6 additions & 0 deletions tests/cases/compiler/alwaysStrictES6.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @target: ES6
// @alwaysStrict: true

function f() {
var arguments = [];
}
8 changes: 8 additions & 0 deletions tests/cases/compiler/alwaysStrictModule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @module: commonjs
// @alwaysStrict: true

module M {
export function f() {
var arguments = [];
}
}
9 changes: 9 additions & 0 deletions tests/cases/compiler/alwaysStrictNoImplicitUseStrict.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// @module: commonjs
// @alwaysStrict: true
// @noImplicitUseStrict: true

module M {
export function f() {
var arguments = [];
}
}

0 comments on commit 29a85e0

Please sign in to comment.