Skip to content

Commit 2a19580

Browse files
authored
Introduce more caching and deferral into jsx checking (#25302)
* Introduce more caching and deferral into jsx checking * Accept baseline with removed duplicated error
1 parent 53e163d commit 2a19580

File tree

4 files changed

+40
-15
lines changed

4 files changed

+40
-15
lines changed

src/compiler/checker.ts

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16365,14 +16365,18 @@ namespace ts {
1636516365
type.flags & TypeFlags.UnionOrIntersection && every((<UnionOrIntersectionType>type).types, isValidSpreadType));
1636616366
}
1636716367

16368-
function checkJsxSelfClosingElement(node: JsxSelfClosingElement, checkMode: CheckMode | undefined): Type {
16369-
checkJsxOpeningLikeElementOrOpeningFragment(node, checkMode);
16368+
function checkJsxSelfClosingElementDeferred(node: JsxSelfClosingElement) {
16369+
checkJsxOpeningLikeElementOrOpeningFragment(node, CheckMode.Normal);
16370+
}
16371+
16372+
function checkJsxSelfClosingElement(node: JsxSelfClosingElement, _checkMode: CheckMode | undefined): Type {
16373+
checkNodeDeferred(node);
1637016374
return getJsxElementTypeAt(node) || anyType;
1637116375
}
1637216376

16373-
function checkJsxElement(node: JsxElement, checkMode: CheckMode | undefined): Type {
16377+
function checkJsxElementDeferred(node: JsxElement) {
1637416378
// Check attributes
16375-
checkJsxOpeningLikeElementOrOpeningFragment(node.openingElement, checkMode);
16379+
checkJsxOpeningLikeElementOrOpeningFragment(node.openingElement, CheckMode.Normal);
1637616380

1637716381
// Perform resolution on the closing tag so that rename/go to definition/etc work
1637816382
if (isJsxIntrinsicIdentifier(node.closingElement.tagName)) {
@@ -16381,6 +16385,10 @@ namespace ts {
1638116385
else {
1638216386
checkExpression(node.closingElement.tagName);
1638316387
}
16388+
}
16389+
16390+
function checkJsxElement(node: JsxElement, _checkMode: CheckMode | undefined): Type {
16391+
checkNodeDeferred(node);
1638416392

1638516393
return getJsxElementTypeAt(node) || anyType;
1638616394
}
@@ -16661,12 +16669,24 @@ namespace ts {
1666116669
}
1666216670

1666316671
function getJsxNamespaceAt(location: Node | undefined): Symbol {
16664-
const namespaceName = getJsxNamespace(location);
16665-
const resolvedNamespace = resolveName(location, namespaceName, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined, namespaceName, /*isUse*/ false);
16666-
if (resolvedNamespace) {
16667-
const candidate = getSymbol(getExportsOfSymbol(resolveSymbol(resolvedNamespace)), JsxNames.JSX, SymbolFlags.Namespace);
16668-
if (candidate) {
16669-
return candidate;
16672+
const links = location && getNodeLinks(location);
16673+
if (links && links.jsxNamespace) {
16674+
return links.jsxNamespace;
16675+
}
16676+
if (!links || links.jsxNamespace !== false) {
16677+
const namespaceName = getJsxNamespace(location);
16678+
const resolvedNamespace = resolveName(location, namespaceName, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined, namespaceName, /*isUse*/ false);
16679+
if (resolvedNamespace) {
16680+
const candidate = getSymbol(getExportsOfSymbol(resolveSymbol(resolvedNamespace)), JsxNames.JSX, SymbolFlags.Namespace);
16681+
if (candidate) {
16682+
if (links) {
16683+
links.jsxNamespace = candidate;
16684+
}
16685+
return candidate;
16686+
}
16687+
if (links) {
16688+
links.jsxNamespace = false;
16689+
}
1667016690
}
1667116691
}
1667216692
// JSX global fallback
@@ -17146,7 +17166,7 @@ namespace ts {
1714617166
// sourceAttributesType is a type of an attributes properties.
1714717167
// i.e <div attr1={10} attr2="string" />
1714817168
// attr1 and attr2 are treated as JSXAttributes attached in the JsxOpeningLikeElement as "attributes".
17149-
const sourceAttributesType = createJsxAttributesTypeFromAttributesProperty(openingLikeElement, checkMode);
17169+
const sourceAttributesType = checkExpressionCached(openingLikeElement.attributes, checkMode);
1715017170

1715117171
// Check if sourceAttributesType assignable to targetAttributesType though this check will allow excess properties
1715217172
const isSourceAttributeTypeAssignableToTarget = isTypeAssignableTo(sourceAttributesType, targetAttributesType);
@@ -26115,6 +26135,12 @@ namespace ts {
2611526135
case SyntaxKind.ClassExpression:
2611626136
checkClassExpressionDeferred(<ClassExpression>node);
2611726137
break;
26138+
case SyntaxKind.JsxSelfClosingElement:
26139+
checkJsxSelfClosingElementDeferred(<JsxSelfClosingElement>node);
26140+
break;
26141+
case SyntaxKind.JsxElement:
26142+
checkJsxElementDeferred(<JsxElement>node);
26143+
break;
2611826144
}
2611926145
});
2612026146
}

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3658,6 +3658,7 @@ namespace ts {
36583658
hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt.
36593659
superCall?: SuperCall; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
36603660
switchTypes?: Type[]; // Cached array of switch case expression types
3661+
jsxNamespace?: Symbol | false; // Resolved jsx namespace symbol for this node
36613662
}
36623663

36633664
export const enum TypeFlags {

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3196,6 +3196,7 @@ declare namespace ts {
31963196
hasSuperCall?: boolean;
31973197
superCall?: SuperCall;
31983198
switchTypes?: Type[];
3199+
jsxNamespace?: Symbol | false;
31993200
}
32003201
enum TypeFlags {
32013202
Any = 1,

tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.errors.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ tests/cases/conformance/jsx/inline/index.tsx(21,22): error TS2322: Type '{ child
66
Types of property 'children' are incompatible.
77
Type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element[]' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element[]'.
88
Type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
9-
tests/cases/conformance/jsx/inline/index.tsx(21,40): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
109
tests/cases/conformance/jsx/inline/index.tsx(21,40): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
1110
Property '__domBrand' is missing in type 'MyClass'.
1211
tests/cases/conformance/jsx/inline/index.tsx(21,63): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
@@ -77,7 +76,7 @@ tests/cases/conformance/jsx/inline/index.tsx(24,23): error TS2322: Type '{ child
7776

7877
export default <h></h>
7978

80-
==== tests/cases/conformance/jsx/inline/index.tsx (7 errors) ====
79+
==== tests/cases/conformance/jsx/inline/index.tsx (6 errors) ====
8180
/** @jsx dom */
8281
import { dom } from "./renderer"
8382
import prerendered, {MySFC, MyClass, tree} from "./component";
@@ -111,8 +110,6 @@ tests/cases/conformance/jsx/inline/index.tsx(24,23): error TS2322: Type '{ child
111110
!!! error TS2322: Type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element[]' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element[]'.
112111
!!! error TS2322: Type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
113112
~~~~~~~~~~~~~~~~~~~~~~~
114-
!!! error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
115-
~~~~~~~~~~~~~~~~~~~~~~~
116113
!!! error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
117114
!!! error TS2605: Property '__domBrand' is missing in type 'MyClass'.
118115
~~~~~~~~~~~~~~~~~~~~~~~

0 commit comments

Comments
 (0)