Cache started nonexistent property error checks to prevent reentrancy in the check (#60683)

This commit is contained in:
Wesley Wigham 2024-12-04 15:13:20 -08:00 committed by GitHub
parent 4105134626
commit 517da72a57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 111 additions and 0 deletions

View File

@ -34466,6 +34466,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function reportNonexistentProperty(propNode: Identifier | PrivateIdentifier, containingType: Type, isUncheckedJS: boolean) {
const links = getNodeLinks(propNode);
const cache = (links.nonExistentPropCheckCache ||= new Set());
const key = `${getTypeId(containingType)}|${isUncheckedJS}`;
if (cache.has(key)) {
return;
}
cache.add(key);
let errorInfo: DiagnosticMessageChain | undefined;
let relatedInfo: Diagnostic | undefined;
if (!isPrivateIdentifier(propNode) && containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) {

View File

@ -6254,6 +6254,7 @@ export interface NodeLinks {
potentialUnusedRenamedBindingElementsInTypes?: BindingElement[];
externalHelpersModule?: Symbol; // Resolved symbol for the external helpers module
instantiationExpressionTypes?: Map<number, Type>; // Cache of instantiation expression types for the node
nonExistentPropCheckCache?: Set<string>;
}
/** @internal */

View File

@ -0,0 +1,16 @@
checkingObjectWithThisInNamePositionNoCrash.ts(2,5): error TS7023: 'doit' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
checkingObjectWithThisInNamePositionNoCrash.ts(4,19): error TS2339: Property 'a' does not exist on type '{ doit(): { [x: number]: string; }; }'.
==== checkingObjectWithThisInNamePositionNoCrash.ts (2 errors) ====
export const thing = {
doit() {
~~~~
!!! error TS7023: 'doit' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
return {
[this.a]: "", // should refer to the outer object with the doit method, notably not present
~
!!! error TS2339: Property 'a' does not exist on type '{ doit(): { [x: number]: string; }; }'.
}
}
}

View File

@ -0,0 +1,31 @@
//// [tests/cases/compiler/checkingObjectWithThisInNamePositionNoCrash.ts] ////
//// [checkingObjectWithThisInNamePositionNoCrash.ts]
export const thing = {
doit() {
return {
[this.a]: "", // should refer to the outer object with the doit method, notably not present
}
}
}
//// [checkingObjectWithThisInNamePositionNoCrash.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.thing = void 0;
exports.thing = {
doit: function () {
var _a;
return _a = {},
_a[this.a] = "",
_a;
}
};
//// [checkingObjectWithThisInNamePositionNoCrash.d.ts]
export declare const thing: {
doit(): {
[x: number]: string;
};
};

View File

@ -0,0 +1,16 @@
//// [tests/cases/compiler/checkingObjectWithThisInNamePositionNoCrash.ts] ////
=== checkingObjectWithThisInNamePositionNoCrash.ts ===
export const thing = {
>thing : Symbol(thing, Decl(checkingObjectWithThisInNamePositionNoCrash.ts, 0, 12))
doit() {
>doit : Symbol(doit, Decl(checkingObjectWithThisInNamePositionNoCrash.ts, 0, 22))
return {
[this.a]: "", // should refer to the outer object with the doit method, notably not present
>[this.a] : Symbol([this.a], Decl(checkingObjectWithThisInNamePositionNoCrash.ts, 2, 16))
>this : Symbol(thing, Decl(checkingObjectWithThisInNamePositionNoCrash.ts, 0, 20))
}
}
}

View File

@ -0,0 +1,31 @@
//// [tests/cases/compiler/checkingObjectWithThisInNamePositionNoCrash.ts] ////
=== checkingObjectWithThisInNamePositionNoCrash.ts ===
export const thing = {
>thing : { doit(): { [x: number]: string; }; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>{ doit() { return { [this.a]: "", // should refer to the outer object with the doit method, notably not present } }} : { doit(): { [x: number]: string; }; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
doit() {
>doit : () => { [x: number]: string; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
return {
>{ [this.a]: "", // should refer to the outer object with the doit method, notably not present } : { [x: number]: string; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^
[this.a]: "", // should refer to the outer object with the doit method, notably not present
>[this.a] : string
> : ^^^^^^
>this.a : any
> : ^^^
>this : { doit(): { [x: number]: string; }; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : any
> : ^^^
>"" : ""
> : ^^
}
}
}

View File

@ -0,0 +1,9 @@
// @strict: true
// @declaration: true
export const thing = {
doit() {
return {
[this.a]: "", // should refer to the outer object with the doit method, notably not present
}
}
}