Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 418a251

Browse filesBrowse files
committed
Merge branch '10758-always-strict' of https://github.com/slawomir/TypeScript into slawomir-10758-always-strict
2 parents a6443e3 + 8210634 commit 418a251
Copy full SHA for 418a251

24 files changed

+225-2Lines changed: 225 additions & 2 deletions
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/binder.ts‎

Copy file name to clipboardExpand all lines: src/compiler/binder.ts
+13-2Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ namespace ts {
121121

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

127128
let symbolCount = 0;
@@ -139,7 +140,7 @@ namespace ts {
139140
file = f;
140141
options = opts;
141142
languageVersion = getEmitScriptTarget(options);
142-
inStrictMode = !!file.externalModuleIndicator;
143+
inStrictMode = bindInStrictMode(file, opts);
143144
classifiableNames = createMap<string>();
144145
symbolCount = 0;
145146
skipTransformFlagAggregation = isDeclarationFile(file);
@@ -174,6 +175,16 @@ namespace ts {
174175

175176
return bindSourceFile;
176177

178+
function bindInStrictMode(file: SourceFile, opts: CompilerOptions): boolean {
179+
if (opts.alwaysStrict && !isDeclarationFile(file)) {
180+
// bind in strict mode source files with alwaysStrict option
181+
return true;
182+
}
183+
else {
184+
return !!file.externalModuleIndicator;
185+
}
186+
}
187+
177188
function createSymbol(flags: SymbolFlags, name: string): Symbol {
178189
symbolCount++;
179190
return new Symbol(flags, name);
Collapse file

‎src/compiler/commandLineParser.ts‎

Copy file name to clipboardExpand all lines: src/compiler/commandLineParser.ts
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,11 @@ namespace ts {
444444
name: "importHelpers",
445445
type: "boolean",
446446
description: Diagnostics.Import_emit_helpers_from_tslib
447+
},
448+
{
449+
name: "alwaysStrict",
450+
type: "boolean",
451+
description: Diagnostics.Parse_in_strict_mode_and_emit_use_strict_for_each_source_file
447452
}
448453
];
449454

Collapse file

‎src/compiler/diagnosticMessages.json‎

Copy file name to clipboardExpand all lines: src/compiler/diagnosticMessages.json
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2861,6 +2861,10 @@
28612861
"category": "Error",
28622862
"code": 6140
28632863
},
2864+
"Parse in strict mode and emit \"use strict\" for each source file": {
2865+
"category": "Message",
2866+
"code": 6141
2867+
},
28642868
"Variable '{0}' implicitly has an '{1}' type.": {
28652869
"category": "Error",
28662870
"code": 7005
Collapse file

‎src/compiler/factory.ts‎

Copy file name to clipboardExpand all lines: src/compiler/factory.ts
+27Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2235,6 +2235,33 @@ namespace ts {
22352235
return statementOffset;
22362236
}
22372237

2238+
/**
2239+
* Ensures "use strict" directive is added
2240+
*
2241+
* @param node source file
2242+
*/
2243+
export function ensureUseStrict(node: SourceFile): SourceFile {
2244+
let foundUseStrict = false;
2245+
for (const statement of node.statements) {
2246+
if (isPrologueDirective(statement)) {
2247+
if (isUseStrictPrologue(statement as ExpressionStatement)) {
2248+
foundUseStrict = true;
2249+
break;
2250+
}
2251+
}
2252+
else {
2253+
break;
2254+
}
2255+
}
2256+
if (!foundUseStrict) {
2257+
const statements: Statement[] = [];
2258+
statements.push(startOnNewLine(createStatement(createLiteral("use strict"))));
2259+
// add "use strict" as the first statement
2260+
return updateSourceFileNode(node, statements.concat(node.statements));
2261+
}
2262+
return node;
2263+
}
2264+
22382265
/**
22392266
* Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended
22402267
* order of operations.
Collapse file

‎src/compiler/transformers/ts.ts‎

Copy file name to clipboardExpand all lines: src/compiler/transformers/ts.ts
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,11 @@ namespace ts {
436436
function visitSourceFile(node: SourceFile) {
437437
currentSourceFile = node;
438438

439+
// ensure "use strict" is emitted in all scenarios in alwaysStrict mode
440+
if (compilerOptions.alwaysStrict) {
441+
node = ensureUseStrict(node);
442+
}
443+
439444
// If the source file requires any helpers and is an external module, and
440445
// the importHelpers compiler option is enabled, emit a synthesized import
441446
// statement for the helpers library.
Collapse file

‎src/compiler/types.ts‎

Copy file name to clipboardExpand all lines: src/compiler/types.ts
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2925,6 +2925,7 @@ namespace ts {
29252925
allowSyntheticDefaultImports?: boolean;
29262926
allowUnreachableCode?: boolean;
29272927
allowUnusedLabels?: boolean;
2928+
alwaysStrict?: boolean;
29282929
baseUrl?: string;
29292930
charset?: string;
29302931
/* @internal */ configFilePath?: string;
Collapse file

‎src/harness/unittests/transpile.ts‎

Copy file name to clipboardExpand all lines: src/harness/unittests/transpile.ts
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ var x = 0;`, {
253253
options: { compilerOptions: { allowUnusedLabels: true }, fileName: "input.js", reportDiagnostics: true }
254254
});
255255

256+
transpilesCorrectly("Supports setting 'alwaysStrict'", "x;", {
257+
options: { compilerOptions: { alwaysStrict: true }, fileName: "input.js", reportDiagnostics: true }
258+
});
259+
256260
transpilesCorrectly("Supports setting 'baseUrl'", "x;", {
257261
options: { compilerOptions: { baseUrl: "./folder/baseUrl" }, fileName: "input.js", reportDiagnostics: true }
258262
});
Collapse file
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
tests/cases/compiler/alwaysStrict.ts(3,9): error TS1100: Invalid use of 'arguments' in strict mode.
2+
3+
4+
==== tests/cases/compiler/alwaysStrict.ts (1 errors) ====
5+
6+
function f() {
7+
var arguments = [];
8+
~~~~~~~~~
9+
!!! error TS1100: Invalid use of 'arguments' in strict mode.
10+
}
Collapse file
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//// [alwaysStrict.ts]
2+
3+
function f() {
4+
var arguments = [];
5+
}
6+
7+
//// [alwaysStrict.js]
8+
"use strict";
9+
function f() {
10+
var arguments = [];
11+
}
Collapse file
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//// [alwaysStrictAlreadyUseStrict.ts]
2+
"use strict"
3+
function f() {
4+
var a = [];
5+
}
6+
7+
//// [alwaysStrictAlreadyUseStrict.js]
8+
"use strict";
9+
function f() {
10+
var a = [];
11+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.