Merge branch '10758-always-strict' of https://github.com/slawomir/TypeScript into slawomir-10758-always-strict

This commit is contained in:
Mohamed Hegazy 2016-10-13 16:17:06 -07:00
commit 418a251237
24 changed files with 225 additions and 2 deletions

View File

@ -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;
@ -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);
@ -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);

View File

@ -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
}
];

View File

@ -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

View File

@ -2235,6 +2235,33 @@ namespace ts {
return statementOffset;
}
/**
* Ensures "use strict" directive is added
*
* @param node source file
*/
export function ensureUseStrict(node: SourceFile): SourceFile {
let foundUseStrict = false;
for (const statement of node.statements) {
if (isPrologueDirective(statement)) {
if (isUseStrictPrologue(statement as ExpressionStatement)) {
foundUseStrict = true;
break;
}
}
else {
break;
}
}
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.

View File

@ -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 = ensureUseStrict(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.

View File

@ -2925,6 +2925,7 @@ namespace ts {
allowSyntheticDefaultImports?: boolean;
allowUnreachableCode?: boolean;
allowUnusedLabels?: boolean;
alwaysStrict?: boolean;
baseUrl?: string;
charset?: string;
/* @internal */ configFilePath?: string;

View File

@ -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 }
});

View File

@ -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.
}

View File

@ -0,0 +1,11 @@
//// [alwaysStrict.ts]
function f() {
var arguments = [];
}
//// [alwaysStrict.js]
"use strict";
function f() {
var arguments = [];
}

View File

@ -0,0 +1,11 @@
//// [alwaysStrictAlreadyUseStrict.ts]
"use strict"
function f() {
var a = [];
}
//// [alwaysStrictAlreadyUseStrict.js]
"use strict";
function f() {
var a = [];
}

View File

@ -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))
}

View File

@ -0,0 +1,11 @@
=== tests/cases/compiler/alwaysStrictAlreadyUseStrict.ts ===
"use strict"
>"use strict" : "use strict"
function f() {
>f : () => void
var a = [];
>a : any[]
>[] : undefined[]
}

View File

@ -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.
}

View File

@ -0,0 +1,11 @@
//// [alwaysStrictES6.ts]
function f() {
var arguments = [];
}
//// [alwaysStrictES6.js]
"use strict";
function f() {
var arguments = [];
}

View File

@ -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.
}
}

View File

@ -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 = {}));

View File

@ -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.
}
}

View File

@ -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 = {}));

View File

@ -0,0 +1,3 @@
"use strict";
x;
//# sourceMappingURL=input.js.map

View File

@ -0,0 +1,5 @@
// @alwaysStrict: true
function f() {
var arguments = [];
}

View File

@ -0,0 +1,5 @@
// @alwaysStrict: true
"use strict"
function f() {
var a = [];
}

View File

@ -0,0 +1,6 @@
// @target: ES6
// @alwaysStrict: true
function f() {
var arguments = [];
}

View File

@ -0,0 +1,8 @@
// @module: commonjs
// @alwaysStrict: true
module M {
export function f() {
var arguments = [];
}
}

View File

@ -0,0 +1,9 @@
// @module: commonjs
// @alwaysStrict: true
// @noImplicitUseStrict: true
module M {
export function f() {
var arguments = [];
}
}