mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 03:09:39 -06:00
WIP: Add guards to prevent infinite recursion in type checking
- Added parser fix for incomplete keyof operator (missing operand) - Working on checker fix for stack overflow with union types + destructuring + undefined shorthand properties - Current approach: prevent recursion in isConstContext when computing contextual types Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
This commit is contained in:
parent
c0ff10a906
commit
cf4425cd6b
@ -1,20 +0,0 @@
|
||||
import * as ts from "./built/local/typescript.js";
|
||||
|
||||
const sourceFile = ts.createSourceFile(
|
||||
"test.ts",
|
||||
`const { c, f }: keyof = { c: 0, f };`,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
|
||||
function printNode(node, indent = 0) {
|
||||
const prefix = " ".repeat(indent);
|
||||
console.log(`${prefix}${ts.SyntaxKind[node.kind]}`);
|
||||
if (ts.isTypeOperatorNode(node)) {
|
||||
console.log(`${prefix} operator: ${ts.SyntaxKind[node.operator]}`);
|
||||
console.log(`${prefix} type: ${ts.SyntaxKind[node.type.kind]}`);
|
||||
}
|
||||
ts.forEachChild(node, child => printNode(child, indent + 1));
|
||||
}
|
||||
|
||||
printNode(sourceFile);
|
||||
@ -1,23 +0,0 @@
|
||||
import * as ts from "./built/local/typescript.js";
|
||||
|
||||
const sourceFile = ts.createSourceFile(
|
||||
"test.ts",
|
||||
`const { c, f }: keyof = { c: 0, f };`,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
|
||||
function printNode(node, indent = 0) {
|
||||
const prefix = " ".repeat(indent);
|
||||
let info = `${prefix}${ts.SyntaxKind[node.kind]}`;
|
||||
if (ts.isTypeOperatorNode(node)) {
|
||||
info += ` (operator: ${ts.SyntaxKind[node.operator]})`;
|
||||
}
|
||||
if (ts.isIdentifier(node)) {
|
||||
info += ` (text: "${node.text}")`;
|
||||
}
|
||||
console.log(info);
|
||||
ts.forEachChild(node, child => printNode(child, indent + 1));
|
||||
}
|
||||
|
||||
printNode(sourceFile);
|
||||
@ -41397,7 +41397,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const parent = node.parent;
|
||||
return isAssertionExpression(parent) && isConstTypeReference(parent.type) ||
|
||||
isJSDocTypeAssertion(parent) && isConstTypeReference(getJSDocTypeAssertionType(parent)) ||
|
||||
isValidConstAssertionArgument(node) && isConstTypeVariable(getContextualType(node, ContextFlags.None)) ||
|
||||
// Avoid calling getContextualType if we're already computing contextual types to prevent infinite recursion
|
||||
isValidConstAssertionArgument(node) && findContextualNode(node, /*includeCaches*/ true) < 0 && isConstTypeVariable(getContextualType(node, ContextFlags.None)) ||
|
||||
(isParenthesizedExpression(parent) || isArrayLiteralExpression(parent) || isSpreadElement(parent)) && isConstContext(parent) ||
|
||||
(isPropertyAssignment(parent) || isShorthandPropertyAssignment(parent) || isTemplateSpan(parent)) && isConstContext(parent.parent);
|
||||
}
|
||||
|
||||
@ -4752,7 +4752,16 @@ namespace Parser {
|
||||
function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword) {
|
||||
const pos = getNodePos();
|
||||
parseExpected(operator);
|
||||
return finishNode(factory.createTypeOperatorNode(operator, parseTypeOperatorOrHigher()), pos);
|
||||
// Check if the next token is a valid type start. If not, report an error and use 'any' as a placeholder.
|
||||
let type: TypeNode;
|
||||
if (isStartOfType()) {
|
||||
type = parseTypeOperatorOrHigher();
|
||||
}
|
||||
else {
|
||||
parseErrorAtCurrentToken(Diagnostics.Type_expected);
|
||||
type = finishNode(factory.createToken(SyntaxKind.AnyKeyword), getNodePos());
|
||||
}
|
||||
return finishNode(factory.createTypeOperatorNode(operator, type), pos);
|
||||
}
|
||||
|
||||
function tryParseConstraintOfInferType() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user