Skip to content

Commit c3055e5

Browse files
authored
Fix compiler crash with object rest in catch binding (#31522)
1 parent b3dc32f commit c3055e5

File tree

6 files changed

+73
-1
lines changed

6 files changed

+73
-1
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30169,12 +30169,17 @@ namespace ts {
3016930169
return undefined;
3017030170
}
3017130171

30172+
function isSymbolOfDestructuredElementOfCatchBinding(symbol: Symbol) {
30173+
return isBindingElement(symbol.valueDeclaration)
30174+
&& walkUpBindingElementsAndPatterns(symbol.valueDeclaration).parent.kind === SyntaxKind.CatchClause;
30175+
}
30176+
3017230177
function isSymbolOfDeclarationWithCollidingName(symbol: Symbol): boolean {
3017330178
if (symbol.flags & SymbolFlags.BlockScoped && !isSourceFile(symbol.valueDeclaration)) {
3017430179
const links = getSymbolLinks(symbol);
3017530180
if (links.isDeclarationWithCollidingName === undefined) {
3017630181
const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration);
30177-
if (isStatementWithLocals(container)) {
30182+
if (isStatementWithLocals(container) || isSymbolOfDestructuredElementOfCatchBinding(symbol)) {
3017830183
const nodeLinks = getNodeLinks(symbol.valueDeclaration);
3017930184
if (resolveName(container.parent, symbol.escapedName, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)) {
3018030185
// redeclaration - always should be renamed

src/compiler/transformers/es2018.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ namespace ts {
7777
return visitObjectLiteralExpression(node as ObjectLiteralExpression);
7878
case SyntaxKind.BinaryExpression:
7979
return visitBinaryExpression(node as BinaryExpression, noDestructuringValue);
80+
case SyntaxKind.CatchClause:
81+
return visitCatchClause(node as CatchClause);
8082
case SyntaxKind.VariableDeclaration:
8183
return visitVariableDeclaration(node as VariableDeclaration);
8284
case SyntaxKind.ForOfStatement:
@@ -272,6 +274,28 @@ namespace ts {
272274
return visitEachChild(node, visitor, context);
273275
}
274276

277+
function visitCatchClause(node: CatchClause) {
278+
if (node.variableDeclaration &&
279+
isBindingPattern(node.variableDeclaration.name) &&
280+
node.variableDeclaration.name.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
281+
const name = getGeneratedNameForNode(node.variableDeclaration.name);
282+
const updatedDecl = updateVariableDeclaration(node.variableDeclaration, node.variableDeclaration.name, /*type*/ undefined, name);
283+
const visitedBindings = flattenDestructuringBinding(updatedDecl, visitor, context, FlattenLevel.ObjectRest);
284+
let block = visitNode(node.block, visitor, isBlock);
285+
if (some(visitedBindings)) {
286+
block = updateBlock(block, [
287+
createVariableStatement(/*modifiers*/ undefined, visitedBindings),
288+
...block.statements,
289+
]);
290+
}
291+
return updateCatchClause(
292+
node,
293+
updateVariableDeclaration(node.variableDeclaration, name, /*type*/ undefined, /*initializer*/ undefined),
294+
block);
295+
}
296+
return visitEachChild(node, visitor, context);
297+
}
298+
275299
/**
276300
* Visits a VariableDeclaration node with a binding pattern.
277301
*
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//// [objectRestCatchES5.ts]
2+
let a = 1, b = 2;
3+
try {} catch ({ a, ...b }) {}
4+
5+
//// [objectRestCatchES5.js]
6+
var __rest = (this && this.__rest) || function (s, e) {
7+
var t = {};
8+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
9+
t[p] = s[p];
10+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
11+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
12+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
13+
t[p[i]] = s[p[i]];
14+
}
15+
return t;
16+
};
17+
var a = 1, b = 2;
18+
try { }
19+
catch (_a) {
20+
var a_1 = _a.a, b_1 = __rest(_a, ["a"]);
21+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
=== tests/cases/conformance/types/rest/objectRestCatchES5.ts ===
2+
let a = 1, b = 2;
3+
>a : Symbol(a, Decl(objectRestCatchES5.ts, 0, 3))
4+
>b : Symbol(b, Decl(objectRestCatchES5.ts, 0, 10))
5+
6+
try {} catch ({ a, ...b }) {}
7+
>a : Symbol(a, Decl(objectRestCatchES5.ts, 1, 15))
8+
>b : Symbol(b, Decl(objectRestCatchES5.ts, 1, 18))
9+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/conformance/types/rest/objectRestCatchES5.ts ===
2+
let a = 1, b = 2;
3+
>a : number
4+
>1 : 1
5+
>b : number
6+
>2 : 2
7+
8+
try {} catch ({ a, ...b }) {}
9+
>a : any
10+
>b : any
11+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
let a = 1, b = 2;
2+
try {} catch ({ a, ...b }) {}

0 commit comments

Comments
 (0)