Skip to content

Commit 60e99ec

Browse files
authored
Disallow [await] using statements under case/default clauses (#62709)
1 parent 0c801e6 commit 60e99ec

23 files changed

+2488
-1787
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ import {
504504
isCallLikeOrFunctionLikeExpression,
505505
isCallOrNewExpression,
506506
isCallSignatureDeclaration,
507+
isCaseOrDefaultClause,
507508
isCatchClause,
508509
isCatchClauseVariableDeclaration,
509510
isCatchClauseVariableDeclarationOrBindingElement,
@@ -53175,6 +53176,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
5317553176
Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_an_await_using_declaration,
5317653177
);
5317753178
}
53179+
else if (isVariableStatement(declarationList.parent) && isCaseOrDefaultClause(declarationList.parent.parent)) {
53180+
return grammarErrorOnNode(
53181+
declarationList,
53182+
blockScopeFlags === NodeFlags.Using ?
53183+
Diagnostics.using_declarations_are_not_allowed_in_case_or_default_clauses_unless_contained_within_a_block :
53184+
Diagnostics.await_using_declarations_are_not_allowed_in_case_or_default_clauses_unless_contained_within_a_block,
53185+
);
53186+
}
5317853187

5317953188
if (declarationList.flags & NodeFlags.Ambient) {
5318053189
return grammarErrorOnNode(

src/compiler/diagnosticMessages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,6 +1849,14 @@
18491849
"category": "Error",
18501850
"code": 1546
18511851
},
1852+
"'using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.": {
1853+
"category": "Error",
1854+
"code": 1547
1855+
},
1856+
"'await using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.": {
1857+
"category": "Error",
1858+
"code": 1548
1859+
},
18521860

18531861
"The types of '{0}' are incompatible between these types.": {
18541862
"category": "Error",

src/compiler/transformers/esnext.ts

Lines changed: 0 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
BindingElement,
77
Block,
88
Bundle,
9-
CaseOrDefaultClause,
109
chainBundle,
1110
ClassDeclaration,
1211
Debug,
@@ -25,7 +24,6 @@ import {
2524
isArray,
2625
isBindingPattern,
2726
isBlock,
28-
isCaseClause,
2927
isCustomPrologue,
3028
isExpression,
3129
isGeneratedIdentifier,
@@ -49,7 +47,6 @@ import {
4947
skipOuterExpressions,
5048
SourceFile,
5149
Statement,
52-
SwitchStatement,
5350
SyntaxKind,
5451
TransformationContext,
5552
TransformFlags,
@@ -123,9 +120,6 @@ export function transformESNext(context: TransformationContext): (x: SourceFile
123120
case SyntaxKind.ForOfStatement:
124121
return visitForOfStatement(node as ForOfStatement);
125122

126-
case SyntaxKind.SwitchStatement:
127-
return visitSwitchStatement(node as SwitchStatement);
128-
129123
default:
130124
return visitEachChild(node, visitor, context);
131125
}
@@ -339,72 +333,6 @@ export function transformESNext(context: TransformationContext): (x: SourceFile
339333
return visitEachChild(node, visitor, context);
340334
}
341335

342-
function visitCaseOrDefaultClause(node: CaseOrDefaultClause, envBinding: Identifier) {
343-
if (getUsingKindOfStatements(node.statements) !== UsingKind.None) {
344-
if (isCaseClause(node)) {
345-
return factory.updateCaseClause(
346-
node,
347-
visitNode(node.expression, visitor, isExpression),
348-
transformUsingDeclarations(node.statements, /*start*/ 0, node.statements.length, envBinding, /*topLevelStatements*/ undefined),
349-
);
350-
}
351-
else {
352-
return factory.updateDefaultClause(
353-
node,
354-
transformUsingDeclarations(node.statements, /*start*/ 0, node.statements.length, envBinding, /*topLevelStatements*/ undefined),
355-
);
356-
}
357-
}
358-
return visitEachChild(node, visitor, context);
359-
}
360-
361-
function visitSwitchStatement(node: SwitchStatement) {
362-
// given:
363-
//
364-
// switch (expr) {
365-
// case expr:
366-
// using res = expr;
367-
// }
368-
//
369-
// produces:
370-
//
371-
// const env_1 = { stack: [], error: void 0, hasError: false };
372-
// try {
373-
// switch(expr) {
374-
// case expr:
375-
// const res = __addDisposableResource(env_1, expr, false);
376-
// }
377-
// }
378-
// catch (e_1) {
379-
// env_1.error = e_1;
380-
// env_1.hasError = true;
381-
// }
382-
// finally {
383-
// __disposeResources(env_1);
384-
// }
385-
//
386-
const usingKind = getUsingKindOfCaseOrDefaultClauses(node.caseBlock.clauses);
387-
if (usingKind) {
388-
const envBinding = createEnvBinding();
389-
return createDownlevelUsingStatements(
390-
[
391-
factory.updateSwitchStatement(
392-
node,
393-
visitNode(node.expression, visitor, isExpression),
394-
factory.updateCaseBlock(
395-
node.caseBlock,
396-
node.caseBlock.clauses.map(clause => visitCaseOrDefaultClause(clause, envBinding)),
397-
),
398-
),
399-
],
400-
envBinding,
401-
usingKind === UsingKind.Async,
402-
);
403-
}
404-
405-
return visitEachChild(node, visitor, context);
406-
}
407-
408336
/**
409337
* Transform `using` declarations in a statement list.
410338
*/
@@ -870,13 +798,3 @@ function getUsingKindOfStatements(statements: readonly Statement[]): UsingKind {
870798
}
871799
return result;
872800
}
873-
874-
function getUsingKindOfCaseOrDefaultClauses(clauses: readonly CaseOrDefaultClause[]): UsingKind {
875-
let result = UsingKind.None;
876-
for (const clause of clauses) {
877-
const usingKind = getUsingKindOfStatements(clause.statements);
878-
if (usingKind === UsingKind.Async) return UsingKind.Async;
879-
if (usingKind > result) result = usingKind;
880-
}
881-
return result;
882-
}

tests/baselines/reference/awaitUsingDeclarations.1(target=es2015).errors.txt

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
awaitUsingDeclarations.1.ts(1,1): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
22
awaitUsingDeclarations.1.ts(36,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
33
awaitUsingDeclarations.1.ts(41,9): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
4-
awaitUsingDeclarations.1.ts(45,9): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
5-
awaitUsingDeclarations.1.ts(52,13): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
6-
awaitUsingDeclarations.1.ts(57,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
7-
awaitUsingDeclarations.1.ts(60,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
8-
awaitUsingDeclarations.1.ts(63,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
9-
awaitUsingDeclarations.1.ts(67,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
10-
awaitUsingDeclarations.1.ts(70,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
4+
awaitUsingDeclarations.1.ts(46,9): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
5+
awaitUsingDeclarations.1.ts(51,9): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
6+
awaitUsingDeclarations.1.ts(58,13): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
7+
awaitUsingDeclarations.1.ts(63,13): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
8+
awaitUsingDeclarations.1.ts(68,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
9+
awaitUsingDeclarations.1.ts(71,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
1110
awaitUsingDeclarations.1.ts(74,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
12-
awaitUsingDeclarations.1.ts(79,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
11+
awaitUsingDeclarations.1.ts(78,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
12+
awaitUsingDeclarations.1.ts(81,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
1313
awaitUsingDeclarations.1.ts(85,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
1414
awaitUsingDeclarations.1.ts(90,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
15-
awaitUsingDeclarations.1.ts(94,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
15+
awaitUsingDeclarations.1.ts(96,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
16+
awaitUsingDeclarations.1.ts(101,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
17+
awaitUsingDeclarations.1.ts(105,5): error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
1618

1719

18-
==== awaitUsingDeclarations.1.ts (15 errors) ====
20+
==== awaitUsingDeclarations.1.ts (17 errors) ====
1921
await using d1 = { async [Symbol.asyncDispose]() {} };
2022
~~~~~
2123
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
@@ -59,85 +61,100 @@ awaitUsingDeclarations.1.ts(94,5): error TS2854: Top-level 'await using' stateme
5961
}
6062

6163
switch (Math.random()) {
62-
case 0:
64+
case 0: {
6365
await using d20 = { async [Symbol.asyncDispose]() {} };
6466
~~~~~
6567
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
6668
break;
69+
}
6770

68-
case 1:
71+
case 1: {
6972
await using d21 = { async [Symbol.asyncDispose]() {} };
7073
~~~~~
7174
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
7275
break;
76+
}
77+
78+
default: {
79+
await using d22 = { async [Symbol.asyncDispose]() {} };
80+
~~~~~
81+
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
82+
}
7383
}
7484

7585
if (true)
7686
switch (0) {
77-
case 0:
78-
await using d22 = { async [Symbol.asyncDispose]() {} };
87+
case 0: {
88+
await using d23 = { async [Symbol.asyncDispose]() {} };
7989
~~~~~
8090
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
8191
break;
92+
}
93+
94+
default: {
95+
await using d24 = { async [Symbol.asyncDispose]() {} };
96+
~~~~~
97+
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
98+
}
8299
}
83100

84101
try {
85-
await using d23 = { async [Symbol.asyncDispose]() {} };
102+
await using d25 = { async [Symbol.asyncDispose]() {} };
86103
~~~~~
87104
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
88105
}
89106
catch {
90-
await using d24 = { async [Symbol.asyncDispose]() {} };
107+
await using d26 = { async [Symbol.asyncDispose]() {} };
91108
~~~~~
92109
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
93110
}
94111
finally {
95-
await using d25 = { async [Symbol.asyncDispose]() {} };
112+
await using d27 = { async [Symbol.asyncDispose]() {} };
96113
~~~~~
97114
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
98115
}
99116

100117
if (true) {
101-
await using d26 = { async [Symbol.asyncDispose]() {} };
118+
await using d28 = { async [Symbol.asyncDispose]() {} };
102119
~~~~~
103120
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
104121
}
105122
else {
106-
await using d27 = { async [Symbol.asyncDispose]() {} };
123+
await using d29 = { async [Symbol.asyncDispose]() {} };
107124
~~~~~
108125
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
109126
}
110127

111128
while (true) {
112-
await using d28 = { async [Symbol.asyncDispose]() {} };
129+
await using d30 = { async [Symbol.asyncDispose]() {} };
113130
~~~~~
114131
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
115132
break;
116133
}
117134

118135
do {
119-
await using d29 = { async [Symbol.asyncDispose]() {} };
136+
await using d31 = { async [Symbol.asyncDispose]() {} };
120137
~~~~~
121138
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
122139
break;
123140
}
124141
while (true);
125142

126143
for (;;) {
127-
await using d30 = { async [Symbol.asyncDispose]() {} };
144+
await using d32 = { async [Symbol.asyncDispose]() {} };
128145
~~~~~
129146
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
130147
break;
131148
}
132149

133150
for (const x in {}) {
134-
await using d31 = { async [Symbol.asyncDispose]() {} };
151+
await using d33 = { async [Symbol.asyncDispose]() {} };
135152
~~~~~
136153
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
137154
}
138155

139156
for (const x of []) {
140-
await using d32 = { async [Symbol.asyncDispose]() {} };
157+
await using d34 = { async [Symbol.asyncDispose]() {} };
141158
~~~~~
142159
!!! error TS2854: Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.
143160
}

0 commit comments

Comments
 (0)