Disallow [await] using statements under case/default clauses (#62709)

This commit is contained in:
René
2025-11-19 22:08:45 +00:00
committed by GitHub
parent 0c801e6efb
commit 60e99ecee4
23 changed files with 2671 additions and 1970 deletions

View File

@@ -504,6 +504,7 @@ import {
isCallLikeOrFunctionLikeExpression,
isCallOrNewExpression,
isCallSignatureDeclaration,
isCaseOrDefaultClause,
isCatchClause,
isCatchClauseVariableDeclaration,
isCatchClauseVariableDeclarationOrBindingElement,
@@ -53175,6 +53176,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_an_await_using_declaration,
);
}
else if (isVariableStatement(declarationList.parent) && isCaseOrDefaultClause(declarationList.parent.parent)) {
return grammarErrorOnNode(
declarationList,
blockScopeFlags === NodeFlags.Using ?
Diagnostics.using_declarations_are_not_allowed_in_case_or_default_clauses_unless_contained_within_a_block :
Diagnostics.await_using_declarations_are_not_allowed_in_case_or_default_clauses_unless_contained_within_a_block,
);
}
if (declarationList.flags & NodeFlags.Ambient) {
return grammarErrorOnNode(

View File

@@ -1849,6 +1849,14 @@
"category": "Error",
"code": 1546
},
"'using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.": {
"category": "Error",
"code": 1547
},
"'await using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.": {
"category": "Error",
"code": 1548
},
"The types of '{0}' are incompatible between these types.": {
"category": "Error",

View File

@@ -6,7 +6,6 @@ import {
BindingElement,
Block,
Bundle,
CaseOrDefaultClause,
chainBundle,
ClassDeclaration,
Debug,
@@ -25,7 +24,6 @@ import {
isArray,
isBindingPattern,
isBlock,
isCaseClause,
isCustomPrologue,
isExpression,
isGeneratedIdentifier,
@@ -49,7 +47,6 @@ import {
skipOuterExpressions,
SourceFile,
Statement,
SwitchStatement,
SyntaxKind,
TransformationContext,
TransformFlags,
@@ -123,9 +120,6 @@ export function transformESNext(context: TransformationContext): (x: SourceFile
case SyntaxKind.ForOfStatement:
return visitForOfStatement(node as ForOfStatement);
case SyntaxKind.SwitchStatement:
return visitSwitchStatement(node as SwitchStatement);
default:
return visitEachChild(node, visitor, context);
}
@@ -339,72 +333,6 @@ export function transformESNext(context: TransformationContext): (x: SourceFile
return visitEachChild(node, visitor, context);
}
function visitCaseOrDefaultClause(node: CaseOrDefaultClause, envBinding: Identifier) {
if (getUsingKindOfStatements(node.statements) !== UsingKind.None) {
if (isCaseClause(node)) {
return factory.updateCaseClause(
node,
visitNode(node.expression, visitor, isExpression),
transformUsingDeclarations(node.statements, /*start*/ 0, node.statements.length, envBinding, /*topLevelStatements*/ undefined),
);
}
else {
return factory.updateDefaultClause(
node,
transformUsingDeclarations(node.statements, /*start*/ 0, node.statements.length, envBinding, /*topLevelStatements*/ undefined),
);
}
}
return visitEachChild(node, visitor, context);
}
function visitSwitchStatement(node: SwitchStatement) {
// given:
//
// switch (expr) {
// case expr:
// using res = expr;
// }
//
// produces:
//
// const env_1 = { stack: [], error: void 0, hasError: false };
// try {
// switch(expr) {
// case expr:
// const res = __addDisposableResource(env_1, expr, false);
// }
// }
// catch (e_1) {
// env_1.error = e_1;
// env_1.hasError = true;
// }
// finally {
// __disposeResources(env_1);
// }
//
const usingKind = getUsingKindOfCaseOrDefaultClauses(node.caseBlock.clauses);
if (usingKind) {
const envBinding = createEnvBinding();
return createDownlevelUsingStatements(
[
factory.updateSwitchStatement(
node,
visitNode(node.expression, visitor, isExpression),
factory.updateCaseBlock(
node.caseBlock,
node.caseBlock.clauses.map(clause => visitCaseOrDefaultClause(clause, envBinding)),
),
),
],
envBinding,
usingKind === UsingKind.Async,
);
}
return visitEachChild(node, visitor, context);
}
/**
* Transform `using` declarations in a statement list.
*/
@@ -870,13 +798,3 @@ function getUsingKindOfStatements(statements: readonly Statement[]): UsingKind {
}
return result;
}
function getUsingKindOfCaseOrDefaultClauses(clauses: readonly CaseOrDefaultClause[]): UsingKind {
let result = UsingKind.None;
for (const clause of clauses) {
const usingKind = getUsingKindOfStatements(clause.statements);
if (usingKind === UsingKind.Async) return UsingKind.Async;
if (usingKind > result) result = usingKind;
}
return result;
}