Skip to content

Commit cdfef4f

Browse files
committed
add use strict and simple parameter check
1 parent 60986ad commit cdfef4f

12 files changed

+838
-13
lines changed

src/compiler/checker.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28515,11 +28515,49 @@ namespace ts {
2851528515
}
2851628516
}
2851728517

28518+
function getNonSimpleParameters(parameters: ReadonlyArray<ParameterDeclaration>): ReadonlyArray<ParameterDeclaration> {
28519+
// ECMA-262 14.1.13
28520+
if (parameters.length === 0) return [];
28521+
28522+
const last = lastOrUndefined(parameters);
28523+
if (last && isRestParameter(last)) return [last];
28524+
28525+
return filter(parameters, parameter => {
28526+
// ECMA-262 13.3.3.4
28527+
return !!parameter.initializer || isBindingPattern(parameter.name);
28528+
});
28529+
}
28530+
28531+
function checkGrammarForUseStrictSimpleParameterList(node: FunctionLikeDeclaration): boolean {
28532+
if (languageVersion >= ScriptTarget.ES2016) {
28533+
const useStrictDirective = node.body && isBlock(node.body) && findUseStrictPrologue(node.body.statements);
28534+
if (useStrictDirective) {
28535+
const nonSimpleParameters = getNonSimpleParameters(node.parameters);
28536+
if (length(nonSimpleParameters)) {
28537+
forEach(nonSimpleParameters, parameter => {
28538+
addRelatedInfo(
28539+
error(parameter, Diagnostics.This_parameter_is_not_allowed_with_use_strict_directive),
28540+
createDiagnosticForNode(useStrictDirective, Diagnostics._0_is_here, "use strict directive")
28541+
);
28542+
});
28543+
28544+
const diagnostics = nonSimpleParameters.map((parameter, index) => (
28545+
index === 0 ? createDiagnosticForNode(parameter, Diagnostics._0_is_here, "parameter") : createDiagnosticForNode(parameter, Diagnostics.and_here)
28546+
)) as [DiagnosticWithLocation, ...DiagnosticWithLocation[]];
28547+
addRelatedInfo(error(useStrictDirective, Diagnostics.use_strict_directive_cannot_be_used_with_non_simple_parameter_list), ...diagnostics);
28548+
return true;
28549+
}
28550+
}
28551+
}
28552+
return false;
28553+
}
28554+
2851828555
function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration | MethodSignature): boolean {
2851928556
// Prevent cascading error by short-circuit
2852028557
const file = getSourceFileOfNode(node);
2852128558
return checkGrammarDecoratorsAndModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) ||
28522-
checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file);
28559+
checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file) ||
28560+
(isFunctionLikeDeclaration(node) && checkGrammarForUseStrictSimpleParameterList(node));
2852328561
}
2852428562

2852528563
function checkGrammarClassLikeDeclaration(node: ClassLikeDeclaration): boolean {

src/compiler/diagnosticMessages.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,18 @@
983983
"category": "Error",
984984
"code": 1343
985985
},
986+
"This parameter is not allowed with 'use strict' directive.": {
987+
"category": "Error",
988+
"code": 1344
989+
},
990+
"'use strict' directive cannot be used with non simple parameter list.": {
991+
"category": "Error",
992+
"code": 1345
993+
},
994+
"{0} is here.": {
995+
"category": "Error",
996+
"code": 1346
997+
},
986998

987999
"Duplicate identifier '{0}'.": {
9881000
"category": "Error",

src/compiler/factory.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3934,6 +3934,20 @@ namespace ts {
39343934
return statementOffset;
39353935
}
39363936

3937+
export function findUseStrictPrologue(statements: ReadonlyArray<Statement>): Statement | undefined {
3938+
for (const statement of statements) {
3939+
if (isPrologueDirective(statement)) {
3940+
if (isUseStrictPrologue(statement)) {
3941+
return statement;
3942+
}
3943+
}
3944+
else {
3945+
break;
3946+
}
3947+
}
3948+
return undefined;
3949+
}
3950+
39373951
export function startsWithUseStrict(statements: ReadonlyArray<Statement>) {
39383952
const firstStatement = firstOrUndefined(statements);
39393953
return firstStatement !== undefined
@@ -3947,18 +3961,7 @@ namespace ts {
39473961
* @param statements An array of statements
39483962
*/
39493963
export function ensureUseStrict(statements: NodeArray<Statement>): NodeArray<Statement> {
3950-
let foundUseStrict = false;
3951-
for (const statement of statements) {
3952-
if (isPrologueDirective(statement)) {
3953-
if (isUseStrictPrologue(statement as ExpressionStatement)) {
3954-
foundUseStrict = true;
3955-
break;
3956-
}
3957-
}
3958-
else {
3959-
break;
3960-
}
3961-
}
3964+
const foundUseStrict = findUseStrictPrologue(statements);
39623965

39633966
if (!foundUseStrict) {
39643967
return setTextRange(
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//// [functionWithUseStrictAndSimpleParameterList.ts]
2+
function a(a = 10) {
3+
"use strict";
4+
}
5+
6+
export var foo = 10;
7+
function b(a = 10) {
8+
}
9+
10+
function container() {
11+
"use strict";
12+
function f(a = 10) {
13+
}
14+
}
15+
16+
function rest(...args: any[]) {
17+
'use strict';
18+
}
19+
20+
function paramDefault(param = 1) {
21+
'use strict';
22+
}
23+
24+
function objectBindingPattern({foo}: any) {
25+
'use strict';
26+
}
27+
28+
function arrayBindingPattern([foo]: any[]) {
29+
'use strict';
30+
}
31+
32+
function manyParameter(a = 10, b = 20) {
33+
"use strict";
34+
}
35+
36+
function manyPrologue(a = 10, b = 20) {
37+
"foo";
38+
"use strict";
39+
}
40+
41+
function invalidPrologue(a = 10, b = 20) {
42+
"foo";
43+
const c = 1;
44+
"use strict";
45+
}
46+
47+
48+
//// [functionWithUseStrictAndSimpleParameterList.js]
49+
"use strict";
50+
exports.__esModule = true;
51+
function a(a) {
52+
"use strict";
53+
if (a === void 0) { a = 10; }
54+
}
55+
exports.foo = 10;
56+
function b(a) {
57+
if (a === void 0) { a = 10; }
58+
}
59+
function container() {
60+
"use strict";
61+
function f(a) {
62+
if (a === void 0) { a = 10; }
63+
}
64+
}
65+
function rest() {
66+
'use strict';
67+
var args = [];
68+
for (var _i = 0; _i < arguments.length; _i++) {
69+
args[_i] = arguments[_i];
70+
}
71+
}
72+
function paramDefault(param) {
73+
'use strict';
74+
if (param === void 0) { param = 1; }
75+
}
76+
function objectBindingPattern(_a) {
77+
'use strict';
78+
var foo = _a.foo;
79+
}
80+
function arrayBindingPattern(_a) {
81+
'use strict';
82+
var foo = _a[0];
83+
}
84+
function manyParameter(a, b) {
85+
"use strict";
86+
if (a === void 0) { a = 10; }
87+
if (b === void 0) { b = 20; }
88+
}
89+
function manyPrologue(a, b) {
90+
"foo";
91+
"use strict";
92+
if (a === void 0) { a = 10; }
93+
if (b === void 0) { b = 20; }
94+
}
95+
function invalidPrologue(a, b) {
96+
"foo";
97+
if (a === void 0) { a = 10; }
98+
if (b === void 0) { b = 20; }
99+
var c = 1;
100+
"use strict";
101+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
=== tests/cases/conformance/functions/functionWithUseStrictAndSimpleParameterList.ts ===
2+
function a(a = 10) {
3+
>a : Symbol(a, Decl(functionWithUseStrictAndSimpleParameterList.ts, 0, 0))
4+
>a : Symbol(a, Decl(functionWithUseStrictAndSimpleParameterList.ts, 0, 11))
5+
6+
"use strict";
7+
}
8+
9+
export var foo = 10;
10+
>foo : Symbol(foo, Decl(functionWithUseStrictAndSimpleParameterList.ts, 4, 10))
11+
12+
function b(a = 10) {
13+
>b : Symbol(b, Decl(functionWithUseStrictAndSimpleParameterList.ts, 4, 20))
14+
>a : Symbol(a, Decl(functionWithUseStrictAndSimpleParameterList.ts, 5, 11))
15+
}
16+
17+
function container() {
18+
>container : Symbol(container, Decl(functionWithUseStrictAndSimpleParameterList.ts, 6, 1))
19+
20+
"use strict";
21+
function f(a = 10) {
22+
>f : Symbol(f, Decl(functionWithUseStrictAndSimpleParameterList.ts, 9, 17))
23+
>a : Symbol(a, Decl(functionWithUseStrictAndSimpleParameterList.ts, 10, 15))
24+
}
25+
}
26+
27+
function rest(...args: any[]) {
28+
>rest : Symbol(rest, Decl(functionWithUseStrictAndSimpleParameterList.ts, 12, 1))
29+
>args : Symbol(args, Decl(functionWithUseStrictAndSimpleParameterList.ts, 14, 14))
30+
31+
'use strict';
32+
}
33+
34+
function paramDefault(param = 1) {
35+
>paramDefault : Symbol(paramDefault, Decl(functionWithUseStrictAndSimpleParameterList.ts, 16, 1))
36+
>param : Symbol(param, Decl(functionWithUseStrictAndSimpleParameterList.ts, 18, 22))
37+
38+
'use strict';
39+
}
40+
41+
function objectBindingPattern({foo}: any) {
42+
>objectBindingPattern : Symbol(objectBindingPattern, Decl(functionWithUseStrictAndSimpleParameterList.ts, 20, 1))
43+
>foo : Symbol(foo, Decl(functionWithUseStrictAndSimpleParameterList.ts, 22, 31))
44+
45+
'use strict';
46+
}
47+
48+
function arrayBindingPattern([foo]: any[]) {
49+
>arrayBindingPattern : Symbol(arrayBindingPattern, Decl(functionWithUseStrictAndSimpleParameterList.ts, 24, 1))
50+
>foo : Symbol(foo, Decl(functionWithUseStrictAndSimpleParameterList.ts, 26, 30))
51+
52+
'use strict';
53+
}
54+
55+
function manyParameter(a = 10, b = 20) {
56+
>manyParameter : Symbol(manyParameter, Decl(functionWithUseStrictAndSimpleParameterList.ts, 28, 1))
57+
>a : Symbol(a, Decl(functionWithUseStrictAndSimpleParameterList.ts, 30, 23))
58+
>b : Symbol(b, Decl(functionWithUseStrictAndSimpleParameterList.ts, 30, 30))
59+
60+
"use strict";
61+
}
62+
63+
function manyPrologue(a = 10, b = 20) {
64+
>manyPrologue : Symbol(manyPrologue, Decl(functionWithUseStrictAndSimpleParameterList.ts, 32, 1))
65+
>a : Symbol(a, Decl(functionWithUseStrictAndSimpleParameterList.ts, 34, 22))
66+
>b : Symbol(b, Decl(functionWithUseStrictAndSimpleParameterList.ts, 34, 29))
67+
68+
"foo";
69+
"use strict";
70+
}
71+
72+
function invalidPrologue(a = 10, b = 20) {
73+
>invalidPrologue : Symbol(invalidPrologue, Decl(functionWithUseStrictAndSimpleParameterList.ts, 37, 1))
74+
>a : Symbol(a, Decl(functionWithUseStrictAndSimpleParameterList.ts, 39, 25))
75+
>b : Symbol(b, Decl(functionWithUseStrictAndSimpleParameterList.ts, 39, 32))
76+
77+
"foo";
78+
const c = 1;
79+
>c : Symbol(c, Decl(functionWithUseStrictAndSimpleParameterList.ts, 41, 9))
80+
81+
"use strict";
82+
}
83+

0 commit comments

Comments
 (0)