Skip to content

Commit ed70d48

Browse files
Merge pull request #25633 from Kingwl/strictParameter
add use strict and simple parameter check
2 parents ddedfd4 + 0d3adff commit ed70d48

12 files changed

+913
-13
lines changed

src/compiler/checker.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28822,11 +28822,40 @@ namespace ts {
2882228822
}
2882328823
}
2882428824

28825+
function getNonSimpleParameters(parameters: ReadonlyArray<ParameterDeclaration>): ReadonlyArray<ParameterDeclaration> {
28826+
return filter(parameters, parameter => !!parameter.initializer || isBindingPattern(parameter.name) || isRestParameter(parameter));
28827+
}
28828+
28829+
function checkGrammarForUseStrictSimpleParameterList(node: FunctionLikeDeclaration): boolean {
28830+
if (languageVersion >= ScriptTarget.ES2016) {
28831+
const useStrictDirective = node.body && isBlock(node.body) && findUseStrictPrologue(node.body.statements);
28832+
if (useStrictDirective) {
28833+
const nonSimpleParameters = getNonSimpleParameters(node.parameters);
28834+
if (length(nonSimpleParameters)) {
28835+
forEach(nonSimpleParameters, parameter => {
28836+
addRelatedInfo(
28837+
error(parameter, Diagnostics.This_parameter_is_not_allowed_with_use_strict_directive),
28838+
createDiagnosticForNode(useStrictDirective, Diagnostics.use_strict_directive_used_here)
28839+
);
28840+
});
28841+
28842+
const diagnostics = nonSimpleParameters.map((parameter, index) => (
28843+
index === 0 ? createDiagnosticForNode(parameter, Diagnostics.Non_simple_parameter_declared_here) : createDiagnosticForNode(parameter, Diagnostics.and_here)
28844+
)) as [DiagnosticWithLocation, ...DiagnosticWithLocation[]];
28845+
addRelatedInfo(error(useStrictDirective, Diagnostics.use_strict_directive_cannot_be_used_with_non_simple_parameter_list), ...diagnostics);
28846+
return true;
28847+
}
28848+
}
28849+
}
28850+
return false;
28851+
}
28852+
2882528853
function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration | MethodSignature): boolean {
2882628854
// Prevent cascading error by short-circuit
2882728855
const file = getSourceFileOfNode(node);
2882828856
return checkGrammarDecoratorsAndModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) ||
28829-
checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file);
28857+
checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file) ||
28858+
(isFunctionLikeDeclaration(node) && checkGrammarForUseStrictSimpleParameterList(node));
2883028859
}
2883128860

2883228861
function checkGrammarClassLikeDeclaration(node: ClassLikeDeclaration): boolean {

src/compiler/diagnosticMessages.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,22 @@
991991
"category": "Error",
992992
"code": 1345
993993
},
994+
"This parameter is not allowed with 'use strict' directive.": {
995+
"category": "Error",
996+
"code": 1346
997+
},
998+
"'use strict' directive cannot be used with non-simple parameter list.": {
999+
"category": "Error",
1000+
"code": 1347
1001+
},
1002+
"Non-simple parameter declared here.": {
1003+
"category": "Error",
1004+
"code": 1348
1005+
},
1006+
"'use strict' directive used here.": {
1007+
"category": "Error",
1008+
"code": 1349
1009+
},
9941010

9951011
"Duplicate identifier '{0}'.": {
9961012
"category": "Error",

src/compiler/factory.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3894,6 +3894,20 @@ namespace ts {
38943894
return statementOffset;
38953895
}
38963896

3897+
export function findUseStrictPrologue(statements: ReadonlyArray<Statement>): Statement | undefined {
3898+
for (const statement of statements) {
3899+
if (isPrologueDirective(statement)) {
3900+
if (isUseStrictPrologue(statement)) {
3901+
return statement;
3902+
}
3903+
}
3904+
else {
3905+
break;
3906+
}
3907+
}
3908+
return undefined;
3909+
}
3910+
38973911
export function startsWithUseStrict(statements: ReadonlyArray<Statement>) {
38983912
const firstStatement = firstOrUndefined(statements);
38993913
return firstStatement !== undefined
@@ -3907,18 +3921,7 @@ namespace ts {
39073921
* @param statements An array of statements
39083922
*/
39093923
export function ensureUseStrict(statements: NodeArray<Statement>): NodeArray<Statement> {
3910-
let foundUseStrict = false;
3911-
for (const statement of statements) {
3912-
if (isPrologueDirective(statement)) {
3913-
if (isUseStrictPrologue(statement as ExpressionStatement)) {
3914-
foundUseStrict = true;
3915-
break;
3916-
}
3917-
}
3918-
else {
3919-
break;
3920-
}
3921-
}
3924+
const foundUseStrict = findUseStrictPrologue(statements);
39223925

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

0 commit comments

Comments
 (0)