Skip to content

Commit 4e927bd

Browse files
committed
Create js-inferred rest params in getSignatureOfDeclaration
Previously they were created too late, in resolveCall, via mutation. The mutation of the signature caused bug #16139 because recursion detection in type checking didn't work.
1 parent 70c1c57 commit 4e927bd

File tree

1 file changed

+23
-18
lines changed

1 file changed

+23
-18
lines changed

src/compiler/checker.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2825,6 +2825,17 @@ namespace ts {
28252825

28262826
function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext): ParameterDeclaration {
28272827
const parameterDeclaration = getDeclarationOfKind<ParameterDeclaration>(parameterSymbol, SyntaxKind.Parameter);
2828+
if (isTransientSymbol(parameterSymbol) && parameterSymbol.isRestParameter) {
2829+
// special-case synthetic rest parameters in JS files
2830+
return createParameter(
2831+
/*decorators*/ undefined,
2832+
/*modifiers*/ undefined,
2833+
parameterSymbol.isRestParameter ? createToken(SyntaxKind.DotDotDotToken) : undefined,
2834+
"args",
2835+
/*questionToken*/ undefined,
2836+
typeToTypeNodeHelper(anyArrayType, context),
2837+
/*initializer*/ undefined);
2838+
}
28282839
const modifiers = parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone);
28292840
const dotDotDotToken = isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.DotDotDotToken) : undefined;
28302841
const name = parameterDeclaration.name ?
@@ -6384,8 +6395,17 @@ namespace ts {
63846395
const typePredicate = declaration.type && declaration.type.kind === SyntaxKind.TypePredicate ?
63856396
createTypePredicateFromTypePredicateNode(declaration.type as TypePredicateNode) :
63866397
undefined;
6398+
// JS functions get a free rest parameter if they reference `arguments`
6399+
let hasRestLikeParameter = hasRestParameter(declaration);
6400+
if (!hasRestLikeParameter && isInJavaScriptFile(declaration) && !hasJSDocParameterTags(declaration) && containsArgumentsReference(declaration)) {
6401+
hasRestLikeParameter = true;
6402+
const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args");
6403+
syntheticArgsSymbol.type = anyArrayType;
6404+
syntheticArgsSymbol.isRestParameter = true;
6405+
parameters.push(syntheticArgsSymbol);
6406+
}
63876407

6388-
links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, returnType, typePredicate, minArgumentCount, hasRestParameter(declaration), hasLiteralTypes);
6408+
links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, returnType, typePredicate, minArgumentCount, hasRestLikeParameter, hasLiteralTypes);
63896409
}
63906410
return links.resolvedSignature;
63916411
}
@@ -6420,14 +6440,14 @@ namespace ts {
64206440
}
64216441
}
64226442

6423-
function containsArgumentsReference(declaration: FunctionLikeDeclaration): boolean {
6443+
function containsArgumentsReference(declaration: SignatureDeclaration): boolean {
64246444
const links = getNodeLinks(declaration);
64256445
if (links.containsArgumentsReference === undefined) {
64266446
if (links.flags & NodeCheckFlags.CaptureArguments) {
64276447
links.containsArgumentsReference = true;
64286448
}
64296449
else {
6430-
links.containsArgumentsReference = traverse(declaration.body);
6450+
links.containsArgumentsReference = traverse((declaration as FunctionLikeDeclaration).body);
64316451
}
64326452
}
64336453
return links.containsArgumentsReference;
@@ -15482,21 +15502,6 @@ namespace ts {
1548215502
}
1548315503
}
1548415504

15485-
if (signatures.length === 1) {
15486-
const declaration = signatures[0].declaration;
15487-
if (declaration && isInJavaScriptFile(declaration) && !hasJSDocParameterTags(declaration)) {
15488-
if (containsArgumentsReference(<FunctionLikeDeclaration>declaration)) {
15489-
const signatureWithRest = cloneSignature(signatures[0]);
15490-
const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args");
15491-
syntheticArgsSymbol.type = anyArrayType;
15492-
syntheticArgsSymbol.isRestParameter = true;
15493-
signatureWithRest.parameters = concatenate(signatureWithRest.parameters, [syntheticArgsSymbol]);
15494-
signatureWithRest.hasRestParameter = true;
15495-
signatures = [signatureWithRest];
15496-
}
15497-
}
15498-
}
15499-
1550015505
const candidates = candidatesOutArray || [];
1550115506
// reorderCandidates fills up the candidates array directly
1550215507
reorderCandidates(signatures, candidates);

0 commit comments

Comments
 (0)