Skip to content

Commit a36f17c

Browse files
authored
Add emit support for jsx/jsxs experimental jsx runtime api (#39199)
1 parent 083129f commit a36f17c

File tree

42 files changed

+885
-21
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+885
-21
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24535,7 +24535,7 @@ namespace ts {
2453524535
// by default, jsx:'react' will use jsxFactory = React.createElement and jsxFragmentFactory = React.Fragment
2453624536
// if jsxFactory compiler option is provided, ensure jsxFragmentFactory compiler option or @jsxFrag pragma is provided too
2453724537
const nodeSourceFile = getSourceFileOfNode(node);
24538-
if (compilerOptions.jsx === JsxEmit.React && (compilerOptions.jsxFactory || nodeSourceFile.pragmas.has("jsx"))
24538+
if (getJSXTransformEnabled(compilerOptions) && (compilerOptions.jsxFactory || nodeSourceFile.pragmas.has("jsx"))
2453924539
&& !compilerOptions.jsxFragmentFactory && !nodeSourceFile.pragmas.has("jsxfrag")) {
2454024540
error(node, compilerOptions.jsxFactory
2454124541
? Diagnostics.The_jsxFragmentFactory_compiler_option_must_be_provided_to_use_JSX_fragments_with_the_jsxFactory_compiler_option
@@ -37330,6 +37330,9 @@ namespace ts {
3733037330
// When resolved as an expression identifier, if the given node references an import, return the declaration of
3733137331
// that import. Otherwise, return undefined.
3733237332
function getReferencedImportDeclaration(nodeIn: Identifier): Declaration | undefined {
37333+
if (nodeIn.generatedImportReference) {
37334+
return nodeIn.generatedImportReference;
37335+
}
3733337336
const node = getParseTreeNode(nodeIn, isIdentifier);
3733437337
if (node) {
3733537338
const symbol = getReferencedValueSymbol(node);

src/compiler/commandLineParser.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@ namespace ts {
22
/* @internal */
33
export const compileOnSaveCommandLineOption: CommandLineOption = { name: "compileOnSave", type: "boolean" };
44

5+
const jsxOptionMap = new Map(getEntries({
6+
"preserve": JsxEmit.Preserve,
7+
"react-native": JsxEmit.ReactNative,
8+
"react": JsxEmit.React,
9+
"react-jsx": JsxEmit.ReactJSX,
10+
"react-jsxdev": JsxEmit.ReactJSXDev,
11+
}));
12+
13+
/* @internal */
14+
export const inverseJsxOptionMap = new Map(arrayFrom(mapIterator(jsxOptionMap.entries(), ([key, value]: [string, JsxEmit]) => ["" + value, key] as const)));
15+
516
// NOTE: The order here is important to default lib ordering as entries will have the same
617
// order in the generated program (see `getDefaultLibPriority` in program.ts). This
718
// order also affects overload resolution when a type declared in one lib is
@@ -366,11 +377,7 @@ namespace ts {
366377
},
367378
{
368379
name: "jsx",
369-
type: new Map(getEntries({
370-
"preserve": JsxEmit.Preserve,
371-
"react-native": JsxEmit.ReactNative,
372-
"react": JsxEmit.React
373-
})),
380+
type: jsxOptionMap,
374381
affectsSourceFile: true,
375382
paramType: Diagnostics.KIND,
376383
showInSimplifiedHelpView: true,
@@ -781,6 +788,12 @@ namespace ts {
781788
category: Diagnostics.Advanced_Options,
782789
description: Diagnostics.Specify_the_JSX_fragment_factory_function_to_use_when_targeting_react_JSX_emit_with_jsxFactory_compiler_option_is_specified_e_g_Fragment
783790
},
791+
{
792+
name: "jsxImportSource",
793+
type: "string",
794+
category: Diagnostics.Advanced_Options,
795+
description: Diagnostics.Specify_the_module_specifier_to_be_used_to_import_the_jsx_and_jsxs_factory_functions_from_eg_react
796+
},
784797
{
785798
name: "resolveJsonModule",
786799
type: "boolean",

src/compiler/diagnosticMessages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3609,6 +3609,10 @@
36093609
"category": "Error",
36103610
"code": 5088
36113611
},
3612+
"Option '{0}' cannot be specified when option 'jsx' is '{1}'.": {
3613+
"category": "Error",
3614+
"code": 5089
3615+
},
36123616

36133617
"Generates a sourcemap for each corresponding '.d.ts' file.": {
36143618
"category": "Message",
@@ -4508,6 +4512,10 @@
45084512
"category": "Message",
45094513
"code": 6237
45104514
},
4515+
"Specify the module specifier to be used to import the `jsx` and `jsxs` factory functions from. eg, react": {
4516+
"category": "Error",
4517+
"code": 6238
4518+
},
45114519

45124520
"Projects to reference": {
45134521
"category": "Message",

src/compiler/parser.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8879,6 +8879,8 @@ namespace ts {
88798879
}
88808880
case "jsx":
88818881
case "jsxfrag":
8882+
case "jsximportsource":
8883+
case "jsxruntime":
88828884
return; // Accessed directly
88838885
default: Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future?
88848886
}

src/compiler/program.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3196,6 +3196,9 @@ namespace ts {
31963196
if (options.reactNamespace) {
31973197
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "reactNamespace", "jsxFactory");
31983198
}
3199+
if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) {
3200+
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFactory", inverseJsxOptionMap.get("" + options.jsx));
3201+
}
31993202
if (!parseIsolatedEntityName(options.jsxFactory, languageVersion)) {
32003203
createOptionValueDiagnostic("jsxFactory", Diagnostics.Invalid_value_for_jsxFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFactory);
32013204
}
@@ -3208,11 +3211,26 @@ namespace ts {
32083211
if (!options.jsxFactory) {
32093212
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "jsxFragmentFactory", "jsxFactory");
32103213
}
3214+
if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) {
3215+
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFragmentFactory", inverseJsxOptionMap.get("" + options.jsx));
3216+
}
32113217
if (!parseIsolatedEntityName(options.jsxFragmentFactory, languageVersion)) {
32123218
createOptionValueDiagnostic("jsxFragmentFactory", Diagnostics.Invalid_value_for_jsxFragmentFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFragmentFactory);
32133219
}
32143220
}
32153221

3222+
if (options.reactNamespace) {
3223+
if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) {
3224+
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "reactNamespace", inverseJsxOptionMap.get("" + options.jsx));
3225+
}
3226+
}
3227+
3228+
if (options.jsxImportSource) {
3229+
if (options.jsx === JsxEmit.React) {
3230+
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxImportSource", inverseJsxOptionMap.get("" + options.jsx));
3231+
}
3232+
}
3233+
32163234
// If the emit is enabled make sure that every output file is unique and not overwriting any of the input files
32173235
if (!options.noEmit && !options.suppressOutputPathCheck) {
32183236
const emitHost = getEmitHost();

src/compiler/transformer.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ namespace ts {
3737
function getScriptTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean) {
3838
if (emitOnlyDtsFiles) return emptyArray;
3939

40-
const jsx = compilerOptions.jsx;
4140
const languageVersion = getEmitScriptTarget(compilerOptions);
4241
const moduleKind = getEmitModuleKind(compilerOptions);
4342
const transformers: TransformerFactory<SourceFile | Bundle>[] = [];
@@ -47,7 +46,7 @@ namespace ts {
4746
transformers.push(transformTypeScript);
4847
transformers.push(transformClassFields);
4948

50-
if (jsx === JsxEmit.React) {
49+
if (getJSXTransformEnabled(compilerOptions)) {
5150
transformers.push(transformJsx);
5251
}
5352

0 commit comments

Comments
 (0)