Skip to content

Commit b845fd2

Browse files
authored
fix fragment resolving behavior with jsx: preserve and jsxFragmentFactory: null (#60122)
1 parent ca18009 commit b845fd2

7 files changed

+23
-102
lines changed

src/compiler/checker.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29873,10 +29873,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2987329873
const jsxFactoryNamespace = getJsxNamespace(node);
2987429874
const jsxFactoryLocation = isJsxOpeningLikeElement(node) ? node.tagName : node;
2987529875

29876-
// allow null as jsxFragmentFactory
29876+
// #38720/60122, allow null as jsxFragmentFactory
2987729877
let jsxFactorySym: Symbol | undefined;
2987829878
if (!(isJsxOpeningFragment(node) && jsxFactoryNamespace === "null")) {
29879-
jsxFactorySym = resolveName(jsxFactoryLocation, jsxFactoryNamespace, SymbolFlags.Value, jsxFactoryRefErr, /*isUse*/ true);
29879+
jsxFactorySym = resolveName(jsxFactoryLocation, jsxFactoryNamespace, compilerOptions.jsx === JsxEmit.Preserve ? SymbolFlags.Value & ~SymbolFlags.Enum : SymbolFlags.Value, jsxFactoryRefErr, /*isUse*/ true);
2988029880
}
2988129881

2988229882
if (jsxFactorySym) {
@@ -29890,12 +29890,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2989029890
}
2989129891
}
2989229892

29893-
// For JsxFragment, mark jsx pragma as referenced via resolveName
29893+
// if JsxFragment, additionally mark jsx pragma as referenced, since `getJsxNamespace` above would have resolved to only the fragment factory if they are distinct
2989429894
if (isJsxOpeningFragment(node)) {
2989529895
const file = getSourceFileOfNode(node);
2989629896
const localJsxNamespace = getLocalJsxNamespace(file);
2989729897
if (localJsxNamespace) {
29898-
resolveName(jsxFactoryLocation, localJsxNamespace, SymbolFlags.Value, jsxFactoryRefErr, /*isUse*/ true);
29898+
resolveName(jsxFactoryLocation, localJsxNamespace, compilerOptions.jsx === JsxEmit.Preserve ? SymbolFlags.Value & ~SymbolFlags.Enum : SymbolFlags.Value, jsxFactoryRefErr, /*isUse*/ true);
2989929899
}
2990029900
}
2990129901
}
@@ -32918,7 +32918,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3291832918
}
3291932919

3292032920
checkJsxChildren(node);
32921-
return getJsxElementTypeAt(node) || anyType;
32921+
const jsxElementType = getJsxElementTypeAt(node);
32922+
return isErrorType(jsxElementType) ? anyType : jsxElementType;
3292232923
}
3292332924

3292432925
function isHyphenatedJsxName(name: string | __String) {
@@ -36643,9 +36644,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3664336644
if (sourceFileLinks.jsxFragmentType !== undefined) return sourceFileLinks.jsxFragmentType;
3664436645

3664536646
const jsxFragmentFactoryName = getJsxNamespace(node);
36647+
// #38720/60122, allow null as jsxFragmentFactory
36648+
if (jsxFragmentFactoryName === "null") return sourceFileLinks.jsxFragmentType = anyType;
36649+
3664636650
const jsxFactoryRefErr = diagnostics ? Diagnostics.Using_JSX_fragments_requires_fragment_factory_0_to_be_in_scope_but_it_could_not_be_found : undefined;
3664736651
const jsxFactorySymbol = getJsxNamespaceContainerForImplicitImport(node) ??
36648-
resolveName(node, jsxFragmentFactoryName, SymbolFlags.Value, /*nameNotFoundMessage*/ jsxFactoryRefErr, /*isUse*/ true);
36652+
resolveName(node, jsxFragmentFactoryName, compilerOptions.jsx === JsxEmit.Preserve ? SymbolFlags.Value & ~SymbolFlags.Enum : SymbolFlags.Value, /*nameNotFoundMessage*/ jsxFactoryRefErr, /*isUse*/ true);
3664936653

3665036654
if (jsxFactorySymbol === undefined) return sourceFileLinks.jsxFragmentType = errorType;
3665136655
if (jsxFactorySymbol.escapedName === ReactNames.Fragment) return sourceFileLinks.jsxFragmentType = getTypeOfSymbol(jsxFactorySymbol);

tests/baselines/reference/inlineJsxAndJsxFragPragma.errors.txt

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
preacty-no-fragment.tsx(5,12): error TS6133: 'Fragment' is declared but its value is never read.
22
preacty-only-fragment-no-jsx.tsx(6,1): error TS2874: This JSX tag requires 'h' to be in scope, but it could not be found.
33
snabbdomy-only-fragment-no-jsx.tsx(4,1): error TS2874: This JSX tag requires 'jsx' to be in scope, but it could not be found.
4-
snabbdomy-only-fragment-no-jsx.tsx(4,1): error TS2879: Using JSX fragments requires fragment factory 'null' to be in scope, but it could not be found.
5-
snabbdomy-only-fragment.tsx(4,1): error TS2879: Using JSX fragments requires fragment factory 'null' to be in scope, but it could not be found.
6-
snabbdomy.tsx(4,1): error TS2879: Using JSX fragments requires fragment factory 'null' to be in scope, but it could not be found.
74

85

96
==== renderer.d.ts (0 errors) ====
@@ -26,13 +23,11 @@ snabbdomy.tsx(4,1): error TS2879: Using JSX fragments requires fragment factory
2623
import {h, Fragment} from "./renderer";
2724
<><div></div></>
2825

29-
==== snabbdomy.tsx (1 errors) ====
26+
==== snabbdomy.tsx (0 errors) ====
3027
/* @jsx jsx */
3128
/* @jsxfrag null */
3229
import {jsx} from "./renderer";
3330
<><span></span></>
34-
~~
35-
!!! error TS2879: Using JSX fragments requires fragment factory 'null' to be in scope, but it could not be found.
3631

3732
==== preacty-only-fragment.tsx (0 errors) ====
3833
/**
@@ -42,13 +37,11 @@ snabbdomy.tsx(4,1): error TS2879: Using JSX fragments requires fragment factory
4237
import {h, Fragment} from "./renderer";
4338
<></>
4439

45-
==== snabbdomy-only-fragment.tsx (1 errors) ====
40+
==== snabbdomy-only-fragment.tsx (0 errors) ====
4641
/* @jsx jsx */
4742
/* @jsxfrag null */
4843
import {jsx} from "./renderer";
4944
<></>
50-
~~
51-
!!! error TS2879: Using JSX fragments requires fragment factory 'null' to be in scope, but it could not be found.
5245

5346
==== preacty-only-fragment-no-jsx.tsx (1 errors) ====
5447
/**
@@ -60,15 +53,13 @@ snabbdomy.tsx(4,1): error TS2879: Using JSX fragments requires fragment factory
6053
~~
6154
!!! error TS2874: This JSX tag requires 'h' to be in scope, but it could not be found.
6255

63-
==== snabbdomy-only-fragment-no-jsx.tsx (2 errors) ====
56+
==== snabbdomy-only-fragment-no-jsx.tsx (1 errors) ====
6457
/* @jsx jsx */
6558
/* @jsxfrag null */
6659
import {} from "./renderer";
6760
<></>
6861
~~
6962
!!! error TS2874: This JSX tag requires 'jsx' to be in scope, but it could not be found.
70-
~~
71-
!!! error TS2879: Using JSX fragments requires fragment factory 'null' to be in scope, but it could not be found.
7263

7364
==== preacty-no-fragment.tsx (1 errors) ====
7465
/**

tests/baselines/reference/inlineJsxAndJsxFragPragmaOverridesCompilerOptions.errors.txt

Lines changed: 0 additions & 49 deletions
This file was deleted.

tests/baselines/reference/inlineJsxAndJsxFragPragmaOverridesCompilerOptions.types

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@ import {createElement, Fragment} from "./react";
4444

4545
<><span></span></>
4646
><><span></span></> : any
47-
> : ^^^
48-
><span></span> : any
49-
> : ^^^
47+
><span></span> : error
5048
>span : any
5149
> : ^^^
5250
>span : any
@@ -65,9 +63,7 @@ import {h, Frag} from "./preact";
6563

6664
<><div></div></>
6765
><><div></div></> : any
68-
> : ^^^
69-
><div></div> : any
70-
> : ^^^
66+
><div></div> : error
7167
>div : any
7268
> : ^^^
7369
>div : any
@@ -84,9 +80,7 @@ import {h} from "./snabbdom";
8480

8581
<><div></div></>
8682
><><div></div></> : any
87-
> : ^^^
88-
><div></div> : any
89-
> : ^^^
83+
><div></div> : error
9084
>div : any
9185
> : ^^^
9286
>div : any
@@ -105,9 +99,7 @@ import {Fragment} from "./react";
10599

106100
<><span></span></>
107101
><><span></span></> : any
108-
> : ^^^
109-
><span></span> : any
110-
> : ^^^
102+
><span></span> : error
111103
>span : any
112104
> : ^^^
113105
>span : any

tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.types

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ declare var Frag: any;
88
>Frag : any
99

1010
<></>;
11-
><></> : error
11+
><></> : any
1212

1313
<><span>1</span><><span>2.1</span><span>2.2</span></></>;
14-
><><span>1</span><><span>2.1</span><span>2.2</span></></> : error
14+
><><span>1</span><><span>2.1</span><span>2.2</span></></> : any
1515
><span>1</span> : error
1616
>span : any
1717
> : ^^^
1818
>span : any
1919
> : ^^^
20-
><><span>2.1</span><span>2.2</span></> : error
20+
><><span>2.1</span><span>2.2</span></> : any
2121
><span>2.1</span> : error
2222
>span : any
2323
> : ^^^

tests/baselines/reference/jsxFactoryAndJsxFragmentFactoryNull.errors.txt

Lines changed: 0 additions & 10 deletions
This file was deleted.

tests/baselines/reference/jsxFactoryAndJsxFragmentFactoryNull.types

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,24 @@
33
=== jsxFactoryAndJsxFragmentFactoryNull.tsx ===
44
declare var h: any;
55
>h : any
6-
> : ^^^
76

87
<></>;
98
><></> : any
10-
> : ^^^
119

1210
<><span>1</span><><span>2.1</span><span>2.2</span></></>;
1311
><><span>1</span><><span>2.1</span><span>2.2</span></></> : any
14-
> : ^^^
15-
><span>1</span> : any
16-
> : ^^^
12+
><span>1</span> : error
1713
>span : any
1814
> : ^^^
1915
>span : any
2016
> : ^^^
2117
><><span>2.1</span><span>2.2</span></> : any
22-
> : ^^^
23-
><span>2.1</span> : any
24-
> : ^^^
18+
><span>2.1</span> : error
2519
>span : any
2620
> : ^^^
2721
>span : any
2822
> : ^^^
29-
><span>2.2</span> : any
30-
> : ^^^
23+
><span>2.2</span> : error
3124
>span : any
3225
> : ^^^
3326
>span : any

0 commit comments

Comments
 (0)