Skip to content

Commit 6a1ff4b

Browse files
committed
Report error unconditionally since TypeScript assumes strict mode
Update the fix to report the error regardless of strict mode context, as TypeScript assumes strict mode at all times. Also improved the error message to be more helpful: "Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration."
1 parent f55c6a2 commit 6a1ff4b

7 files changed

Lines changed: 67 additions & 67 deletions

src/compiler/binder.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2705,16 +2705,12 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
27052705
file.bindDiagnostics.push(createFileDiagnostic(file, errorSpan.start, errorSpan.length, getStrictModeBlockScopeFunctionDeclarationMessage(node)));
27062706
}
27072707
}
2708-
// In strict mode, function declarations are not allowed as the direct child of a statement.
2709-
// For example: `if (true) function f() {}` is a syntax error in strict mode.
2710-
// This applies regardless of the target version.
2711-
if (inStrictMode && isFunctionDeclarationStatementChild(node)) {
2712-
const errorSpan = getErrorSpanForNode(file, node);
2713-
file.bindDiagnostics.push(createFileDiagnostic(file, errorSpan.start, errorSpan.length, Diagnostics.In_strict_mode_code_functions_can_only_be_declared_at_top_level_or_inside_a_block));
2714-
}
27152708
}
27162709

2717-
function isFunctionDeclarationStatementChild(node: FunctionDeclaration): boolean {
2710+
// Function declarations are not allowed as the direct child of a statement.
2711+
// For example: `if (true) function f() {}` is a syntax error in strict mode.
2712+
// Since TypeScript assumes strict mode at all times, this is always an error.
2713+
function checkFunctionDeclarationStatementChild(node: FunctionDeclaration) {
27182714
const parent = node.parent;
27192715
switch (parent.kind) {
27202716
case SyntaxKind.IfStatement:
@@ -2725,9 +2721,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
27252721
case SyntaxKind.ForOfStatement:
27262722
case SyntaxKind.WithStatement:
27272723
case SyntaxKind.LabeledStatement:
2728-
return true;
2729-
default:
2730-
return false;
2724+
const errorSpan = getErrorSpanForNode(file, node);
2725+
file.bindDiagnostics.push(createFileDiagnostic(file, errorSpan.start, errorSpan.length, Diagnostics.Function_declarations_are_not_allowed_inside_statements_Use_a_block_statement_to_wrap_the_function_declaration));
2726+
break;
27312727
}
27322728
}
27332729

@@ -3737,6 +3733,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
37373733
}
37383734

37393735
checkStrictModeFunctionName(node);
3736+
// Function declarations as direct children of statements are always an error
3737+
// since TypeScript assumes strict mode at all times.
3738+
checkFunctionDeclarationStatementChild(node);
37403739
if (inStrictMode) {
37413740
checkStrictModeFunctionDeclaration(node);
37423741
bindBlockScopedDeclaration(node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);

src/compiler/diagnosticMessages.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@
823823
"category": "Error",
824824
"code": 1255
825825
},
826-
"In strict mode code, functions can only be declared at top level or inside a block.": {
826+
"Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.": {
827827
"category": "Error",
828828
"code": 1256
829829
},

tests/baselines/reference/functionDeclarationAsStatementInStrictMode.errors.txt

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,36 @@
1-
functionDeclarationAsStatementInStrictMode.ts(2,20): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
2-
functionDeclarationAsStatementInStrictMode.ts(3,23): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
3-
functionDeclarationAsStatementInStrictMode.ts(4,13): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
4-
functionDeclarationAsStatementInStrictMode.ts(5,19): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
5-
functionDeclarationAsStatementInStrictMode.ts(6,28): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
6-
functionDeclarationAsStatementInStrictMode.ts(7,28): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
7-
functionDeclarationAsStatementInStrictMode.ts(8,1): error TS1344: 'A label is not allowed here.
8-
functionDeclarationAsStatementInStrictMode.ts(8,17): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
1+
functionDeclarationAsStatementInStrictMode.ts(3,20): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
2+
functionDeclarationAsStatementInStrictMode.ts(4,23): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
3+
functionDeclarationAsStatementInStrictMode.ts(5,13): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
4+
functionDeclarationAsStatementInStrictMode.ts(6,19): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
5+
functionDeclarationAsStatementInStrictMode.ts(7,28): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
6+
functionDeclarationAsStatementInStrictMode.ts(8,28): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
7+
functionDeclarationAsStatementInStrictMode.ts(9,17): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
98

109

11-
==== functionDeclarationAsStatementInStrictMode.ts (8 errors) ====
12-
// Error cases - function declarations as direct children of statements in strict mode
10+
==== functionDeclarationAsStatementInStrictMode.ts (7 errors) ====
11+
// Error cases - function declarations as direct children of statements
12+
// TypeScript assumes strict mode at all times, so these are always errors
1313
if (true) function f1() {}
1414
~~
15-
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
15+
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
1616
while (true) function f2() {}
1717
~~
18-
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
18+
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
1919
do function f3() {} while (false);
2020
~~
21-
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
21+
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
2222
for (;;) function f4() {}
2323
~~
24-
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
24+
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
2525
for (let x in {}) function f5() {}
2626
~~
27-
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
27+
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
2828
for (let x of []) function f6() {}
2929
~~
30-
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
30+
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
3131
label: function f7() {}
32-
~~~~~
33-
!!! error TS1344: 'A label is not allowed here.
3432
~~
35-
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
33+
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
3634

3735
// Valid cases - function declarations inside blocks
3836
if (true) { function g1() {} }

tests/baselines/reference/functionDeclarationAsStatementInStrictMode.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//// [tests/cases/compiler/functionDeclarationAsStatementInStrictMode.ts] ////
22

33
//// [functionDeclarationAsStatementInStrictMode.ts]
4-
// Error cases - function declarations as direct children of statements in strict mode
4+
// Error cases - function declarations as direct children of statements
5+
// TypeScript assumes strict mode at all times, so these are always errors
56
if (true) function f1() {}
67
while (true) function f2() {}
78
do function f3() {} while (false);
@@ -29,8 +30,8 @@ function outer() {
2930

3031

3132
//// [functionDeclarationAsStatementInStrictMode.js]
32-
"use strict";
33-
// Error cases - function declarations as direct children of statements in strict mode
33+
// Error cases - function declarations as direct children of statements
34+
// TypeScript assumes strict mode at all times, so these are always errors
3435
if (true)
3536
function f1() { }
3637
while (true)
Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,64 @@
11
//// [tests/cases/compiler/functionDeclarationAsStatementInStrictMode.ts] ////
22

33
=== functionDeclarationAsStatementInStrictMode.ts ===
4-
// Error cases - function declarations as direct children of statements in strict mode
4+
// Error cases - function declarations as direct children of statements
5+
// TypeScript assumes strict mode at all times, so these are always errors
56
if (true) function f1() {}
6-
>f1 : Symbol(f1, Decl(functionDeclarationAsStatementInStrictMode.ts, 1, 9))
7+
>f1 : Symbol(f1, Decl(functionDeclarationAsStatementInStrictMode.ts, 2, 9))
78

89
while (true) function f2() {}
9-
>f2 : Symbol(f2, Decl(functionDeclarationAsStatementInStrictMode.ts, 2, 12))
10+
>f2 : Symbol(f2, Decl(functionDeclarationAsStatementInStrictMode.ts, 3, 12))
1011

1112
do function f3() {} while (false);
12-
>f3 : Symbol(f3, Decl(functionDeclarationAsStatementInStrictMode.ts, 3, 2))
13+
>f3 : Symbol(f3, Decl(functionDeclarationAsStatementInStrictMode.ts, 4, 2))
1314

1415
for (;;) function f4() {}
15-
>f4 : Symbol(f4, Decl(functionDeclarationAsStatementInStrictMode.ts, 4, 8))
16+
>f4 : Symbol(f4, Decl(functionDeclarationAsStatementInStrictMode.ts, 5, 8))
1617

1718
for (let x in {}) function f5() {}
18-
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 5, 8))
19-
>f5 : Symbol(f5, Decl(functionDeclarationAsStatementInStrictMode.ts, 5, 17))
19+
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 6, 8))
20+
>f5 : Symbol(f5, Decl(functionDeclarationAsStatementInStrictMode.ts, 6, 17))
2021

2122
for (let x of []) function f6() {}
22-
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 6, 8))
23-
>f6 : Symbol(f6, Decl(functionDeclarationAsStatementInStrictMode.ts, 6, 17))
23+
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 7, 8))
24+
>f6 : Symbol(f6, Decl(functionDeclarationAsStatementInStrictMode.ts, 7, 17))
2425

2526
label: function f7() {}
26-
>f7 : Symbol(f7, Decl(functionDeclarationAsStatementInStrictMode.ts, 7, 6))
27+
>f7 : Symbol(f7, Decl(functionDeclarationAsStatementInStrictMode.ts, 8, 6))
2728

2829
// Valid cases - function declarations inside blocks
2930
if (true) { function g1() {} }
30-
>g1 : Symbol(g1, Decl(functionDeclarationAsStatementInStrictMode.ts, 10, 11))
31+
>g1 : Symbol(g1, Decl(functionDeclarationAsStatementInStrictMode.ts, 11, 11))
3132

3233
while (true) { function g2() {} }
33-
>g2 : Symbol(g2, Decl(functionDeclarationAsStatementInStrictMode.ts, 11, 14))
34+
>g2 : Symbol(g2, Decl(functionDeclarationAsStatementInStrictMode.ts, 12, 14))
3435

3536
do { function g3() {} } while (false);
36-
>g3 : Symbol(g3, Decl(functionDeclarationAsStatementInStrictMode.ts, 12, 4))
37+
>g3 : Symbol(g3, Decl(functionDeclarationAsStatementInStrictMode.ts, 13, 4))
3738

3839
for (;;) { function g4() {} }
39-
>g4 : Symbol(g4, Decl(functionDeclarationAsStatementInStrictMode.ts, 13, 10))
40+
>g4 : Symbol(g4, Decl(functionDeclarationAsStatementInStrictMode.ts, 14, 10))
4041

4142
for (let x in {}) { function g5() {} }
42-
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 14, 8))
43-
>g5 : Symbol(g5, Decl(functionDeclarationAsStatementInStrictMode.ts, 14, 19))
43+
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 15, 8))
44+
>g5 : Symbol(g5, Decl(functionDeclarationAsStatementInStrictMode.ts, 15, 19))
4445

4546
for (let x of []) { function g6() {} }
46-
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 15, 8))
47-
>g6 : Symbol(g6, Decl(functionDeclarationAsStatementInStrictMode.ts, 15, 19))
47+
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 16, 8))
48+
>g6 : Symbol(g6, Decl(functionDeclarationAsStatementInStrictMode.ts, 16, 19))
4849

4950
label: { function g7() {} }
50-
>g7 : Symbol(g7, Decl(functionDeclarationAsStatementInStrictMode.ts, 16, 8))
51+
>g7 : Symbol(g7, Decl(functionDeclarationAsStatementInStrictMode.ts, 17, 8))
5152

5253
// Valid - top level
5354
function topLevel() {}
54-
>topLevel : Symbol(topLevel, Decl(functionDeclarationAsStatementInStrictMode.ts, 16, 27))
55+
>topLevel : Symbol(topLevel, Decl(functionDeclarationAsStatementInStrictMode.ts, 17, 27))
5556

5657
// Valid - inside function body
5758
function outer() {
58-
>outer : Symbol(outer, Decl(functionDeclarationAsStatementInStrictMode.ts, 19, 22))
59+
>outer : Symbol(outer, Decl(functionDeclarationAsStatementInStrictMode.ts, 20, 22))
5960

6061
function inner() {}
61-
>inner : Symbol(inner, Decl(functionDeclarationAsStatementInStrictMode.ts, 22, 18))
62+
>inner : Symbol(inner, Decl(functionDeclarationAsStatementInStrictMode.ts, 23, 18))
6263
}
6364

tests/baselines/reference/functionDeclarationAsStatementInStrictMode.types

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//// [tests/cases/compiler/functionDeclarationAsStatementInStrictMode.ts] ////
22

33
=== functionDeclarationAsStatementInStrictMode.ts ===
4-
// Error cases - function declarations as direct children of statements in strict mode
4+
// Error cases - function declarations as direct children of statements
5+
// TypeScript assumes strict mode at all times, so these are always errors
56
if (true) function f1() {}
67
>true : true
78
> : ^^^^
@@ -33,10 +34,10 @@ for (let x in {}) function f5() {}
3334
> : ^^^^^^^^^^
3435

3536
for (let x of []) function f6() {}
36-
>x : never
37-
> : ^^^^^
38-
>[] : never[]
39-
> : ^^^^^^^
37+
>x : any
38+
> : ^^^
39+
>[] : undefined[]
40+
> : ^^^^^^^^^^^
4041
>f6 : () => void
4142
> : ^^^^^^^^^^
4243

@@ -78,10 +79,10 @@ for (let x in {}) { function g5() {} }
7879
> : ^^^^^^^^^^
7980

8081
for (let x of []) { function g6() {} }
81-
>x : never
82-
> : ^^^^^
83-
>[] : never[]
84-
> : ^^^^^^^
82+
>x : any
83+
> : ^^^
84+
>[] : undefined[]
85+
> : ^^^^^^^^^^^
8586
>g6 : () => void
8687
> : ^^^^^^^^^^
8788

tests/cases/compiler/functionDeclarationAsStatementInStrictMode.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
// @strict: true
21
// @target: ES2020
32

4-
// Error cases - function declarations as direct children of statements in strict mode
3+
// Error cases - function declarations as direct children of statements
4+
// TypeScript assumes strict mode at all times, so these are always errors
55
if (true) function f1() {}
66
while (true) function f2() {}
77
do function f3() {} while (false);

0 commit comments

Comments
 (0)