Skip to content

Commit 330af8d

Browse files
committed
Add emit support for jsx/jsxs experimental jsx runtime api
1 parent 0ae5cb6 commit 330af8d

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -23769,7 +23769,7 @@ namespace ts {
2376923769
// by default, jsx:'react' will use jsxFactory = React.createElement and jsxFragmentFactory = React.Fragment
2377023770
// if jsxFactory compiler option is provided, ensure jsxFragmentFactory compiler option or @jsxFrag pragma is provided too
2377123771
const nodeSourceFile = getSourceFileOfNode(node);
23772-
if (compilerOptions.jsx === JsxEmit.React && (compilerOptions.jsxFactory || nodeSourceFile.pragmas.has("jsx"))
23772+
if (getJSXTransformEnabled(compilerOptions) && (compilerOptions.jsxFactory || nodeSourceFile.pragmas.has("jsx"))
2377323773
&& !compilerOptions.jsxFragmentFactory && !nodeSourceFile.pragmas.has("jsxfrag")) {
2377423774
error(node, compilerOptions.jsxFactory
2377523775
? Diagnostics.The_jsxFragmentFactory_compiler_option_must_be_provided_to_use_JSX_fragments_with_the_jsxFactory_compiler_option
@@ -36360,6 +36360,9 @@ namespace ts {
3636036360
// When resolved as an expression identifier, if the given node references an import, return the declaration of
3636136361
// that import. Otherwise, return undefined.
3636236362
function getReferencedImportDeclaration(nodeIn: Identifier): Declaration | undefined {
36363+
if (nodeIn.generatedImportReference) {
36364+
return nodeIn.generatedImportReference;
36365+
}
3636336366
const node = getParseTreeNode(nodeIn, isIdentifier);
3636436367
if (node) {
3636536368
const symbol = getReferencedValueSymbol(node);

src/compiler/commandLineParser.ts

+18-5
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 = createMapFromTemplate({
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 = mapMap(jsxOptionMap, (value, key) => ["" + value, key]);
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
@@ -356,11 +367,7 @@ namespace ts {
356367
},
357368
{
358369
name: "jsx",
359-
type: createMapFromTemplate({
360-
"preserve": JsxEmit.Preserve,
361-
"react-native": JsxEmit.ReactNative,
362-
"react": JsxEmit.React
363-
}),
370+
type: jsxOptionMap,
364371
affectsSourceFile: true,
365372
paramType: Diagnostics.KIND,
366373
showInSimplifiedHelpView: true,
@@ -771,6 +778,12 @@ namespace ts {
771778
category: Diagnostics.Advanced_Options,
772779
description: Diagnostics.Specify_the_JSX_fragment_factory_function_to_use_when_targeting_react_JSX_emit_with_jsxFactory_compiler_option_is_specified_e_g_Fragment
773780
},
781+
{
782+
name: "jsxImportSource",
783+
type: "string",
784+
category: Diagnostics.Advanced_Options,
785+
description: Diagnostics.Specify_the_module_specifier_to_be_used_to_import_the_jsx_and_jsxs_factory_functions_from_eg_react
786+
},
774787
{
775788
name: "resolveJsonModule",
776789
type: "boolean",

src/compiler/diagnosticMessages.json

+8
Original file line numberDiff line numberDiff line change
@@ -3542,6 +3542,10 @@
35423542
"category": "Error",
35433543
"code": 5088
35443544
},
3545+
"Option '{0}' cannot be specified when option 'jsx' is '{1}'.": {
3546+
"category": "Error",
3547+
"code": 5089
3548+
},
35453549

35463550
"Generates a sourcemap for each corresponding '.d.ts' file.": {
35473551
"category": "Message",
@@ -4429,6 +4433,10 @@
44294433
"category": "Error",
44304434
"code": 6234
44314435
},
4436+
"Specify the module specifier to be used to import the `jsx` and `jsxs` factory functions from. eg, react": {
4437+
"category": "Error",
4438+
"code": 6235
4439+
},
44324440

44334441
"Projects to reference": {
44344442
"category": "Message",

src/compiler/parser.ts

+2
Original file line numberDiff line numberDiff line change
@@ -8763,6 +8763,8 @@ namespace ts {
87638763
}
87648764
case "jsx":
87658765
case "jsxfrag":
8766+
case "jsximportsource":
8767+
case "jsxruntime":
87668768
return; // Accessed directly
87678769
default: Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future?
87688770
}

src/compiler/program.ts

+18
Original file line numberDiff line numberDiff line change
@@ -3184,6 +3184,9 @@ namespace ts {
31843184
if (options.reactNamespace) {
31853185
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "reactNamespace", "jsxFactory");
31863186
}
3187+
if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) {
3188+
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFactory", inverseJsxOptionMap.get("" + options.jsx));
3189+
}
31873190
if (!parseIsolatedEntityName(options.jsxFactory, languageVersion)) {
31883191
createOptionValueDiagnostic("jsxFactory", Diagnostics.Invalid_value_for_jsxFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFactory);
31893192
}
@@ -3196,11 +3199,26 @@ namespace ts {
31963199
if (!options.jsxFactory) {
31973200
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "jsxFragmentFactory", "jsxFactory");
31983201
}
3202+
if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) {
3203+
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFragmentFactory", inverseJsxOptionMap.get("" + options.jsx));
3204+
}
31993205
if (!parseIsolatedEntityName(options.jsxFragmentFactory, languageVersion)) {
32003206
createOptionValueDiagnostic("jsxFragmentFactory", Diagnostics.Invalid_value_for_jsxFragmentFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFragmentFactory);
32013207
}
32023208
}
32033209

3210+
if (options.reactNamespace) {
3211+
if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) {
3212+
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "reactNamespace", inverseJsxOptionMap.get("" + options.jsx));
3213+
}
3214+
}
3215+
3216+
if (options.jsxImportSource) {
3217+
if (options.jsx === JsxEmit.React) {
3218+
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxImportSource", inverseJsxOptionMap.get("" + options.jsx));
3219+
}
3220+
}
3221+
32043222
// If the emit is enabled make sure that every output file is unique and not overwriting any of the input files
32053223
if (!options.noEmit && !options.suppressOutputPathCheck) {
32063224
const emitHost = getEmitHost();

src/compiler/transformer.ts

+1-2
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)