diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5baffcf750405..1d8ca25170303 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24535,7 +24535,7 @@ namespace ts { // by default, jsx:'react' will use jsxFactory = React.createElement and jsxFragmentFactory = React.Fragment // if jsxFactory compiler option is provided, ensure jsxFragmentFactory compiler option or @jsxFrag pragma is provided too const nodeSourceFile = getSourceFileOfNode(node); - if (compilerOptions.jsx === JsxEmit.React && (compilerOptions.jsxFactory || nodeSourceFile.pragmas.has("jsx")) + if (getJSXTransformEnabled(compilerOptions) && (compilerOptions.jsxFactory || nodeSourceFile.pragmas.has("jsx")) && !compilerOptions.jsxFragmentFactory && !nodeSourceFile.pragmas.has("jsxfrag")) { error(node, compilerOptions.jsxFactory ? Diagnostics.The_jsxFragmentFactory_compiler_option_must_be_provided_to_use_JSX_fragments_with_the_jsxFactory_compiler_option @@ -37330,6 +37330,9 @@ namespace ts { // When resolved as an expression identifier, if the given node references an import, return the declaration of // that import. Otherwise, return undefined. function getReferencedImportDeclaration(nodeIn: Identifier): Declaration | undefined { + if (nodeIn.generatedImportReference) { + return nodeIn.generatedImportReference; + } const node = getParseTreeNode(nodeIn, isIdentifier); if (node) { const symbol = getReferencedValueSymbol(node); diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 4c6c0885182a1..11ffa5d3b5e8c 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -2,6 +2,17 @@ namespace ts { /* @internal */ export const compileOnSaveCommandLineOption: CommandLineOption = { name: "compileOnSave", type: "boolean" }; + const jsxOptionMap = new Map(getEntries({ + "preserve": JsxEmit.Preserve, + "react-native": JsxEmit.ReactNative, + "react": JsxEmit.React, + "react-jsx": JsxEmit.ReactJSX, + "react-jsxdev": JsxEmit.ReactJSXDev, + })); + + /* @internal */ + export const inverseJsxOptionMap = new Map(arrayFrom(mapIterator(jsxOptionMap.entries(), ([key, value]: [string, JsxEmit]) => ["" + value, key] as const))); + // NOTE: The order here is important to default lib ordering as entries will have the same // order in the generated program (see `getDefaultLibPriority` in program.ts). This // order also affects overload resolution when a type declared in one lib is @@ -366,11 +377,7 @@ namespace ts { }, { name: "jsx", - type: new Map(getEntries({ - "preserve": JsxEmit.Preserve, - "react-native": JsxEmit.ReactNative, - "react": JsxEmit.React - })), + type: jsxOptionMap, affectsSourceFile: true, paramType: Diagnostics.KIND, showInSimplifiedHelpView: true, @@ -781,6 +788,12 @@ namespace ts { category: Diagnostics.Advanced_Options, description: Diagnostics.Specify_the_JSX_fragment_factory_function_to_use_when_targeting_react_JSX_emit_with_jsxFactory_compiler_option_is_specified_e_g_Fragment }, + { + name: "jsxImportSource", + type: "string", + category: Diagnostics.Advanced_Options, + description: Diagnostics.Specify_the_module_specifier_to_be_used_to_import_the_jsx_and_jsxs_factory_functions_from_eg_react + }, { name: "resolveJsonModule", type: "boolean", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index e044440e002ac..a8047d51866f0 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3609,6 +3609,10 @@ "category": "Error", "code": 5088 }, + "Option '{0}' cannot be specified when option 'jsx' is '{1}'.": { + "category": "Error", + "code": 5089 + }, "Generates a sourcemap for each corresponding '.d.ts' file.": { "category": "Message", @@ -4508,6 +4512,10 @@ "category": "Message", "code": 6237 }, + "Specify the module specifier to be used to import the `jsx` and `jsxs` factory functions from. eg, react": { + "category": "Error", + "code": 6238 + }, "Projects to reference": { "category": "Message", diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index aa35f8a8421ce..af797435c9d4f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -8879,6 +8879,8 @@ namespace ts { } case "jsx": case "jsxfrag": + case "jsximportsource": + case "jsxruntime": return; // Accessed directly default: Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future? } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 0255067fcb827..98fbcb2ba6ae7 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -3196,6 +3196,9 @@ namespace ts { if (options.reactNamespace) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "reactNamespace", "jsxFactory"); } + if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFactory", inverseJsxOptionMap.get("" + options.jsx)); + } if (!parseIsolatedEntityName(options.jsxFactory, languageVersion)) { createOptionValueDiagnostic("jsxFactory", Diagnostics.Invalid_value_for_jsxFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFactory); } @@ -3208,11 +3211,26 @@ namespace ts { if (!options.jsxFactory) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "jsxFragmentFactory", "jsxFactory"); } + if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFragmentFactory", inverseJsxOptionMap.get("" + options.jsx)); + } if (!parseIsolatedEntityName(options.jsxFragmentFactory, languageVersion)) { createOptionValueDiagnostic("jsxFragmentFactory", Diagnostics.Invalid_value_for_jsxFragmentFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFragmentFactory); } } + if (options.reactNamespace) { + if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "reactNamespace", inverseJsxOptionMap.get("" + options.jsx)); + } + } + + if (options.jsxImportSource) { + if (options.jsx === JsxEmit.React) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxImportSource", inverseJsxOptionMap.get("" + options.jsx)); + } + } + // If the emit is enabled make sure that every output file is unique and not overwriting any of the input files if (!options.noEmit && !options.suppressOutputPathCheck) { const emitHost = getEmitHost(); diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 2172d152412df..f76652df95eb6 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -37,7 +37,6 @@ namespace ts { function getScriptTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean) { if (emitOnlyDtsFiles) return emptyArray; - const jsx = compilerOptions.jsx; const languageVersion = getEmitScriptTarget(compilerOptions); const moduleKind = getEmitModuleKind(compilerOptions); const transformers: TransformerFactory[] = []; @@ -47,7 +46,7 @@ namespace ts { transformers.push(transformTypeScript); transformers.push(transformClassFields); - if (jsx === JsxEmit.React) { + if (getJSXTransformEnabled(compilerOptions)) { transformers.push(transformJsx); } diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index d399408fbe41f..0766cfbbfcf16 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -1,15 +1,59 @@ /*@internal*/ namespace ts { export function transformJsx(context: TransformationContext) { + interface PerFileState { + importSpecifier?: string; + filenameDeclaration?: VariableDeclaration & { name: Identifier; }; + utilizedImplicitRuntimeImports?: Map; + } + const { factory, getEmitHelperFactory: emitHelpers, } = context; const compilerOptions = context.getCompilerOptions(); let currentSourceFile: SourceFile; + let currentFileState!: PerFileState; return chainBundle(context, transformSourceFile); + function getCurrentFileNameExpression(): Identifier { + if (currentFileState.filenameDeclaration) { + return currentFileState.filenameDeclaration.name; + } + const declaration = factory.createVariableDeclaration(factory.createUniqueName("_jsxFileName", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), /*exclaimationToken*/ undefined, /*type*/ undefined, factory.createStringLiteral(currentSourceFile.fileName)); + currentFileState.filenameDeclaration = declaration as VariableDeclaration & { name: Identifier }; + return currentFileState.filenameDeclaration.name; + } + + function getJsxFactoryCalleePrimitive(children: readonly JsxChild[] | undefined): "jsx" | "jsxs" | "jsxDEV" { + return compilerOptions.jsx === JsxEmit.ReactJSXDev ? "jsxDEV" : children && children.length > 1 ? "jsxs" : "jsx"; + } + + function getJsxFactoryCallee(children: readonly JsxChild[] | undefined) { + const type = getJsxFactoryCalleePrimitive(children); + return getImplicitImportForName(type); + } + + function getImplicitJsxFragmentReference() { + return getImplicitImportForName("Fragment"); + } + + function getImplicitImportForName(name: string) { + const existing = currentFileState.utilizedImplicitRuntimeImports?.get(name); + if (existing) { + return existing.name; + } + if (!currentFileState.utilizedImplicitRuntimeImports) { + currentFileState.utilizedImplicitRuntimeImports = createMap(); + } + const generatedName = factory.createUniqueName(`_${name}`, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel | GeneratedIdentifierFlags.AllowNameSubstitution); + const specifier = factory.createImportSpecifier(factory.createIdentifier(name), generatedName); + generatedName.generatedImportReference = specifier; + currentFileState.utilizedImplicitRuntimeImports.set(name, specifier); + return generatedName; + } + /** * Transform JSX-specific syntax in a SourceFile. * @@ -21,8 +65,43 @@ namespace ts { } currentSourceFile = node; - const visited = visitEachChild(node, visitor, context); + currentFileState = {}; + currentFileState.importSpecifier = getJSXImplicitImportBase(compilerOptions, node); + let visited = visitEachChild(node, visitor, context); addEmitHelpers(visited, context.readEmitHelpers()); + let statements: readonly Statement[] = visited.statements; + if (currentFileState.filenameDeclaration) { + statements = insertStatementAfterCustomPrologue(statements.slice(), factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([currentFileState.filenameDeclaration], NodeFlags.Const))); + } + if (currentFileState.utilizedImplicitRuntimeImports && currentFileState.utilizedImplicitRuntimeImports.size && currentFileState.importSpecifier !== undefined) { + const specifier = `${currentFileState.importSpecifier}/${compilerOptions.jsx === JsxEmit.ReactJSXDev ? "jsx-dev-runtime" : "jsx-runtime"}`; + if (isExternalModule(node)) { + // Add `import` statement + const importStatement = factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createImportClause(/*typeOnly*/ false, /*name*/ undefined, factory.createNamedImports(arrayFrom(currentFileState.utilizedImplicitRuntimeImports.values()))), factory.createStringLiteral(specifier)); + setParentRecursive(importStatement, /*incremental*/ false); + statements = insertStatementAfterCustomPrologue(statements.slice(), importStatement); + } + else if (isExternalOrCommonJsModule(node)) { + // Add `require` statement + const requireStatement = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([ + factory.createVariableDeclaration( + factory.createObjectBindingPattern(map(arrayFrom(currentFileState.utilizedImplicitRuntimeImports.values()), s => factory.createBindingElement(/*dotdotdot*/ undefined, s.propertyName, s.name))), + /*exclaimationToken*/ undefined, + /*type*/ undefined, + factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, [factory.createStringLiteral(specifier)]) + ) + ], NodeFlags.Const)); + setParentRecursive(requireStatement, /*incremental*/ false); + statements = insertStatementAfterCustomPrologue(statements.slice(), requireStatement); + } + else { + // Do nothing (script file) - consider an error in the checker? + } + } + if (statements !== visited.statements) { + visited = factory.updateSourceFile(visited, statements); + } + currentFileState = undefined!; return visited; } @@ -76,19 +155,122 @@ namespace ts { } } + /** + * The react jsx/jsxs transform falls back to `createElement` when an explicit `key` argument comes after a spread + */ + function hasKeyAfterPropsSpread(node: JsxOpeningLikeElement) { + let spread = false; + for (const elem of node.attributes.properties) { + if (isJsxSpreadAttribute(elem)) { + spread = true; + } + else if (spread && isJsxAttribute(elem) && elem.name.escapedText === "key") { + return true; + } + } + return false; + } + + function shouldUseCreateElement(node: JsxOpeningLikeElement) { + return currentFileState.importSpecifier === undefined || hasKeyAfterPropsSpread(node); + } + function visitJsxElement(node: JsxElement, isChild: boolean) { - return visitJsxOpeningLikeElement(node.openingElement, node.children, isChild, /*location*/ node); + const tagTransform = shouldUseCreateElement(node.openingElement) ? visitJsxOpeningLikeElementCreateElement : visitJsxOpeningLikeElementJSX; + return tagTransform(node.openingElement, node.children, isChild, /*location*/ node); } function visitJsxSelfClosingElement(node: JsxSelfClosingElement, isChild: boolean) { - return visitJsxOpeningLikeElement(node, /*children*/ undefined, isChild, /*location*/ node); + const tagTransform = shouldUseCreateElement(node) ? visitJsxOpeningLikeElementCreateElement : visitJsxOpeningLikeElementJSX; + return tagTransform(node, /*children*/ undefined, isChild, /*location*/ node); } function visitJsxFragment(node: JsxFragment, isChild: boolean) { - return visitJsxOpeningFragment(node.openingFragment, node.children, isChild, /*location*/ node); + const tagTransform = currentFileState.importSpecifier === undefined ? visitJsxOpeningFragmentCreateElement : visitJsxOpeningFragmentJSX; + return tagTransform(node.openingFragment, node.children, isChild, /*location*/ node); + } + + function convertJsxChildrenToChildrenPropObject(children: readonly JsxChild[]) { + if (children.length === 1) { + const result = transformJsxChildToExpression(children[0]); + return result && factory.createObjectLiteralExpression([ + factory.createPropertyAssignment("children", result) + ]); + } + const result = mapDefined(children, transformJsxChildToExpression); + return !result.length ? undefined : factory.createObjectLiteralExpression([ + factory.createPropertyAssignment("children", factory.createArrayLiteralExpression(result)) + ]); + } + + function visitJsxOpeningLikeElementJSX(node: JsxOpeningLikeElement, children: readonly JsxChild[] | undefined, isChild: boolean, location: TextRange) { + const tagName = getTagName(node); + let objectProperties: Expression; + const keyAttr = find(node.attributes.properties, p => !!p.name && isIdentifier(p.name) && p.name.escapedText === "key") as JsxAttribute | undefined; + const attrs = keyAttr ? filter(node.attributes.properties, p => p !== keyAttr) : node.attributes.properties; + if (attrs.length === 0) { + objectProperties = factory.createObjectLiteralExpression([]); + // When there are no attributes, React wants {} + } + else { + // Map spans of JsxAttribute nodes into object literals and spans + // of JsxSpreadAttribute nodes into expressions. + const segments = flatten( + spanMap(attrs, isJsxSpreadAttribute, (attrs, isSpread) => isSpread + ? map(attrs, transformJsxSpreadAttributeToExpression) + : factory.createObjectLiteralExpression(map(attrs, transformJsxAttributeToObjectLiteralElement)) + ) + ); + + if (children && children.length) { + const result = convertJsxChildrenToChildrenPropObject(children); + if (result) { + segments.push(result); + } + } + + if (isJsxSpreadAttribute(attrs[0])) { + // We must always emit at least one object literal before a spread + // argument.factory.createObjectLiteral + segments.unshift(factory.createObjectLiteralExpression()); + } + + // Either emit one big object literal (no spread attribs), or + // a call to the __assign helper. + objectProperties = singleOrUndefined(segments) || emitHelpers().createAssignHelper(segments); + } + + return visitJsxOpeningLikeElementOrFragmentJSX(tagName, objectProperties, keyAttr, children, isChild, location); } - function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: readonly JsxChild[] | undefined, isChild: boolean, location: TextRange) { + function visitJsxOpeningLikeElementOrFragmentJSX(tagName: Expression, objectProperties: Expression, keyAttr: JsxAttribute | undefined, children: readonly JsxChild[] | undefined, isChild: boolean, location: TextRange) { + const args: Expression[] = [tagName, objectProperties, !keyAttr ? factory.createVoidZero() : transformJsxAttributeInitializer(keyAttr.initializer)]; + if (compilerOptions.jsx === JsxEmit.ReactJSXDev) { + const originalFile = getOriginalNode(currentSourceFile); + if (originalFile && isSourceFile(originalFile)) { + // isStaticChildren development flag + args.push(children && children.length > 1 ? factory.createTrue() : factory.createFalse()); + // __source development flag + const lineCol = getLineAndCharacterOfPosition(originalFile, location.pos); + args.push(factory.createObjectLiteralExpression([ + factory.createPropertyAssignment("fileName", getCurrentFileNameExpression()), + factory.createPropertyAssignment("lineNumber", factory.createNumericLiteral(lineCol.line + 1)), + factory.createPropertyAssignment("columnNumber", factory.createNumericLiteral(lineCol.character + 1)) + ])); + // __self development flag + args.push(factory.createThis()); + } + } + const element = setTextRange(factory.createCallExpression(getJsxFactoryCallee(children), /*typeArguments*/ undefined, args), location); + + if (isChild) { + startOnNewLine(element); + } + + return element; + } + + function visitJsxOpeningLikeElementCreateElement(node: JsxOpeningLikeElement, children: readonly JsxChild[] | undefined, isChild: boolean, location: TextRange) { const tagName = getTagName(node); let objectProperties: Expression | undefined; const attrs = node.attributes.properties; @@ -138,7 +320,25 @@ namespace ts { return element; } - function visitJsxOpeningFragment(node: JsxOpeningFragment, children: readonly JsxChild[], isChild: boolean, location: TextRange) { + function visitJsxOpeningFragmentJSX(_node: JsxOpeningFragment, children: readonly JsxChild[], isChild: boolean, location: TextRange) { + let childrenProps: Expression | undefined; + if (children && children.length) { + const result = convertJsxChildrenToChildrenPropObject(children); + if (result) { + childrenProps = result; + } + } + return visitJsxOpeningLikeElementOrFragmentJSX( + getImplicitJsxFragmentReference(), + childrenProps || factory.createObjectLiteralExpression([]), + /*keyAttr*/ undefined, + children, + isChild, + location + ); + } + + function visitJsxOpeningFragmentCreateElement(node: JsxOpeningFragment, children: readonly JsxChild[], isChild: boolean, location: TextRange) { const element = createExpressionForJsxFragment( factory, context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index e439de686a9a5..b3053f7b13793 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -1763,7 +1763,7 @@ namespace ts { return node; } - if (!isGeneratedIdentifier(node) && !isLocalName(node)) { + if (!(isGeneratedIdentifier(node) && !(node.autoGenerateFlags & GeneratedIdentifierFlags.AllowNameSubstitution)) && !isLocalName(node)) { const exportContainer = resolver.getReferencedExportContainer(node, isExportName(node)); if (exportContainer && exportContainer.kind === SyntaxKind.SourceFile) { return setTextRange( diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 51665756232a5..67aa069196f76 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1083,6 +1083,7 @@ namespace ts { ReservedInNestedScopes = 1 << 3, // Reserve the generated name in nested scopes Optimistic = 1 << 4, // First instance won't use '_#' if there's no conflict FileLevel = 1 << 5, // Use only the file identifiers list and not generated names to search for conflicts + AllowNameSubstitution = 1 << 6, // Used by `module.ts` to indicate generated nodes which can have substitutions performed upon them (as they were generated by an earlier transform phase) } export interface Identifier extends PrimaryExpression, Declaration { @@ -1095,6 +1096,7 @@ namespace ts { readonly originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later /*@internal*/ readonly autoGenerateFlags?: GeneratedIdentifierFlags; // Specifies whether to auto-generate the text for an identifier. /*@internal*/ readonly autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name. + /*@internal*/ generatedImportReference?: ImportSpecifier; // Reference to the generated import specifier this identifier refers to isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace /*@internal*/ typeArguments?: NodeArray; // Only defined on synthesized nodes. Though not syntactically valid, used in emitting diagnostics, quickinfo, and signature help. /*@internal*/ jsdocDotPos?: number; // Identifier occurs in JSDoc-style generic: Id. @@ -5794,6 +5796,7 @@ namespace ts { reactNamespace?: string; jsxFactory?: string; jsxFragmentFactory?: string; + jsxImportSource?: string; composite?: boolean; incremental?: boolean; tsBuildInfoFile?: string; @@ -5868,7 +5871,9 @@ namespace ts { None = 0, Preserve = 1, React = 2, - ReactNative = 3 + ReactNative = 3, + ReactJSX = 4, + ReactJSXDev = 5, } export const enum ImportsNotUsedAsValues { @@ -8063,6 +8068,14 @@ namespace ts { args: [{ name: "factory" }], kind: PragmaKindFlags.MultiLine }, + "jsximportsource": { + args: [{ name: "factory" }], + kind: PragmaKindFlags.MultiLine + }, + "jsxruntime": { + args: [{ name: "factory" }], + kind: PragmaKindFlags.MultiLine + }, } as const; /* @internal */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 347ef95fafbb5..68e07b421752e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -5963,6 +5963,22 @@ namespace ts { return option.strictFlag ? getStrictOptionValue(options, option.name as StrictOptionName) : options[option.name]; } + export function getJSXTransformEnabled(options: CompilerOptions): boolean { + const jsx = options.jsx; + return jsx === JsxEmit.React || jsx === JsxEmit.ReactJSX || jsx === JsxEmit.ReactJSXDev; + } + + export function getJSXImplicitImportBase(compilerOptions: CompilerOptions, file: SourceFile): string | undefined { + const jsxImportSourcePragmas = file.pragmas.get("jsximportsource"); + const jsxImportSourcePragma = isArray(jsxImportSourcePragmas) ? jsxImportSourcePragmas[0] : jsxImportSourcePragmas; + return compilerOptions.jsx === JsxEmit.ReactJSX || + compilerOptions.jsx === JsxEmit.ReactJSXDev || + compilerOptions.jsxImportSource || + jsxImportSourcePragma ? + jsxImportSourcePragma?.arguments.factory || compilerOptions.jsxImportSource || "react" : + undefined; + } + export function hasZeroOrOneAsteriskCharacter(str: string): boolean { let seenAsterisk = false; for (let i = 0; i < str.length; i++) { diff --git a/src/testRunner/unittests/config/commandLineParsing.ts b/src/testRunner/unittests/config/commandLineParsing.ts index 70db9bc675492..1e64839d3ef7c 100644 --- a/src/testRunner/unittests/config/commandLineParsing.ts +++ b/src/testRunner/unittests/config/commandLineParsing.ts @@ -109,7 +109,7 @@ namespace ts { start: undefined, length: undefined, }, { - messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react'.", + messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react', 'react-jsx', 'react-jsxdev'.", category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index b82c6fca3a471..c8dc60e3fba29 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -618,7 +618,8 @@ declare namespace ts { None = 0, ReservedInNestedScopes = 8, Optimistic = 16, - FileLevel = 32 + FileLevel = 32, + AllowNameSubstitution = 64 } export interface Identifier extends PrimaryExpression, Declaration { readonly kind: SyntaxKind.Identifier; @@ -2850,6 +2851,7 @@ declare namespace ts { reactNamespace?: string; jsxFactory?: string; jsxFragmentFactory?: string; + jsxImportSource?: string; composite?: boolean; incremental?: boolean; tsBuildInfoFile?: string; @@ -2910,7 +2912,9 @@ declare namespace ts { None = 0, Preserve = 1, React = 2, - ReactNative = 3 + ReactNative = 3, + ReactJSX = 4, + ReactJSXDev = 5 } export enum ImportsNotUsedAsValues { Remove = 0, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 9a088619c9d58..bd523a5ad5a33 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -618,7 +618,8 @@ declare namespace ts { None = 0, ReservedInNestedScopes = 8, Optimistic = 16, - FileLevel = 32 + FileLevel = 32, + AllowNameSubstitution = 64 } export interface Identifier extends PrimaryExpression, Declaration { readonly kind: SyntaxKind.Identifier; @@ -2850,6 +2851,7 @@ declare namespace ts { reactNamespace?: string; jsxFactory?: string; jsxFragmentFactory?: string; + jsxImportSource?: string; composite?: boolean; incremental?: boolean; tsBuildInfoFile?: string; @@ -2910,7 +2912,9 @@ declare namespace ts { None = 0, Preserve = 1, React = 2, - ReactNative = 3 + ReactNative = 3, + ReactJSX = 4, + ReactJSXDev = 5 } export enum ImportsNotUsedAsValues { Remove = 0, diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).js b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).js new file mode 100644 index 0000000000000..2c38153a249e5 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).js @@ -0,0 +1,16 @@ +//// [jsxJsxsCjsTransformCustomImport.tsx] +/// +const a = <> +

+ text +
+ + +export {}; + +//// [jsxJsxsCjsTransformCustomImport.js] +"use strict"; +exports.__esModule = true; +var jsx_runtime_1 = require("preact/jsx-runtime"); +/// +var a = jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [jsx_runtime_1.jsx("p", {}, void 0), "text", jsx_runtime_1.jsx("div", { className: "foo" }, void 0)] }, void 0); diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).symbols b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).symbols new file mode 100644 index 0000000000000..adc13ae6506c8 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).symbols @@ -0,0 +1,18 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImport.tsx === +/// +const a = <> +>a : Symbol(a, Decl(jsxJsxsCjsTransformCustomImport.tsx, 1, 5)) + +

+>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) +>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) + + text +
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>className : Symbol(className, Decl(jsxJsxsCjsTransformCustomImport.tsx, 4, 6)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + + + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).types b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).types new file mode 100644 index 0000000000000..af6a4c9b9e01d --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsx).types @@ -0,0 +1,21 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImport.tsx === +/// +const a = <> +>a : JSX.Element +><>

text
: JSX.Element + +

+>

: JSX.Element +>p : any +>p : any + + text +
+>
: JSX.Element +>div : any +>className : string +>div : any + + + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).js b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).js new file mode 100644 index 0000000000000..5ab5e659850ce --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).js @@ -0,0 +1,17 @@ +//// [jsxJsxsCjsTransformCustomImport.tsx] +/// +const a = <> +

+ text +
+ + +export {}; + +//// [jsxJsxsCjsTransformCustomImport.js] +"use strict"; +exports.__esModule = true; +var jsx_dev_runtime_1 = require("preact/jsx-dev-runtime"); +var _jsxFileName = "tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImport.tsx"; +/// +var a = jsx_dev_runtime_1.jsxDEV(jsx_dev_runtime_1.Fragment, { children: [jsx_dev_runtime_1.jsxDEV("p", {}, void 0, false, { fileName: _jsxFileName, lineNumber: 3, columnNumber: 3 }, this), "text", jsx_dev_runtime_1.jsxDEV("div", { className: "foo" }, void 0, false, { fileName: _jsxFileName, lineNumber: 5, columnNumber: 3 }, this)] }, void 0, true, { fileName: _jsxFileName, lineNumber: 2, columnNumber: 10 }, this); diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).symbols b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).symbols new file mode 100644 index 0000000000000..adc13ae6506c8 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).symbols @@ -0,0 +1,18 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImport.tsx === +/// +const a = <> +>a : Symbol(a, Decl(jsxJsxsCjsTransformCustomImport.tsx, 1, 5)) + +

+>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) +>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) + + text +
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>className : Symbol(className, Decl(jsxJsxsCjsTransformCustomImport.tsx, 4, 6)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + + + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).types b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).types new file mode 100644 index 0000000000000..af6a4c9b9e01d --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImport(jsx=react-jsxdev).types @@ -0,0 +1,21 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImport.tsx === +/// +const a = <> +>a : JSX.Element +><>

text
: JSX.Element + +

+>

: JSX.Element +>p : any +>p : any + + text +
+>
: JSX.Element +>div : any +>className : string +>div : any + + + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).js b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).js new file mode 100644 index 0000000000000..200b3923f587d --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).js @@ -0,0 +1,39 @@ +//// [tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImportPragma.tsx] //// + +//// [preact.tsx] +/// +/* @jsxImportSource preact */ +const a = <> +

+ text +
+ + +export {}; +//// [react.tsx] +/// +/* @jsxImportSource react */ +import "./preact"; +const a = <> +

+ text +
+ + +export {}; + +//// [preact.js] +"use strict"; +exports.__esModule = true; +var jsx_runtime_1 = require("preact/jsx-runtime"); +/// +/* @jsxImportSource preact */ +var a = jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [jsx_runtime_1.jsx("p", {}, void 0), "text", jsx_runtime_1.jsx("div", { className: "foo" }, void 0)] }, void 0); +//// [react.js] +"use strict"; +exports.__esModule = true; +var jsx_runtime_1 = require("react/jsx-runtime"); +/// +/* @jsxImportSource react */ +require("./preact"); +var a = jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [jsx_runtime_1.jsx("p", {}, void 0), "text", jsx_runtime_1.jsx("div", { className: "foo" }, void 0)] }, void 0); diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).symbols b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).symbols new file mode 100644 index 0000000000000..c4bd360c1a3ea --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).symbols @@ -0,0 +1,39 @@ +=== tests/cases/conformance/jsx/jsxs/react.tsx === +/// +/* @jsxImportSource react */ +import "./preact"; +const a = <> +>a : Symbol(a, Decl(react.tsx, 3, 5)) + +

+>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) +>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) + + text +
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>className : Symbol(className, Decl(react.tsx, 6, 6)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + + + +export {}; +=== tests/cases/conformance/jsx/jsxs/preact.tsx === +/// +/* @jsxImportSource preact */ +const a = <> +>a : Symbol(a, Decl(preact.tsx, 2, 5)) + +

+>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) +>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) + + text +
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>className : Symbol(className, Decl(preact.tsx, 5, 6)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + + + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).types b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).types new file mode 100644 index 0000000000000..2cf985253e3c2 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsx).types @@ -0,0 +1,45 @@ +=== tests/cases/conformance/jsx/jsxs/react.tsx === +/// +/* @jsxImportSource react */ +import "./preact"; +const a = <> +>a : JSX.Element +><>

text
: JSX.Element + +

+>

: JSX.Element +>p : any +>p : any + + text +
+>
: JSX.Element +>div : any +>className : string +>div : any + + + +export {}; +=== tests/cases/conformance/jsx/jsxs/preact.tsx === +/// +/* @jsxImportSource preact */ +const a = <> +>a : JSX.Element +><>

text
: JSX.Element + +

+>

: JSX.Element +>p : any +>p : any + + text +
+>
: JSX.Element +>div : any +>className : string +>div : any + + + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).js b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).js new file mode 100644 index 0000000000000..136a67f48a5ca --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).js @@ -0,0 +1,41 @@ +//// [tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImportPragma.tsx] //// + +//// [preact.tsx] +/// +/* @jsxImportSource preact */ +const a = <> +

+ text +
+ + +export {}; +//// [react.tsx] +/// +/* @jsxImportSource react */ +import "./preact"; +const a = <> +

+ text +
+ + +export {}; + +//// [preact.js] +"use strict"; +exports.__esModule = true; +var jsx_dev_runtime_1 = require("preact/jsx-dev-runtime"); +var _jsxFileName = "tests/cases/conformance/jsx/jsxs/preact.tsx"; +/// +/* @jsxImportSource preact */ +var a = jsx_dev_runtime_1.jsxDEV(jsx_dev_runtime_1.Fragment, { children: [jsx_dev_runtime_1.jsxDEV("p", {}, void 0, false, { fileName: _jsxFileName, lineNumber: 4, columnNumber: 3 }, this), "text", jsx_dev_runtime_1.jsxDEV("div", { className: "foo" }, void 0, false, { fileName: _jsxFileName, lineNumber: 6, columnNumber: 3 }, this)] }, void 0, true, { fileName: _jsxFileName, lineNumber: 3, columnNumber: 10 }, this); +//// [react.js] +"use strict"; +exports.__esModule = true; +var jsx_dev_runtime_1 = require("react/jsx-dev-runtime"); +var _jsxFileName = "tests/cases/conformance/jsx/jsxs/react.tsx"; +/// +/* @jsxImportSource react */ +require("./preact"); +var a = jsx_dev_runtime_1.jsxDEV(jsx_dev_runtime_1.Fragment, { children: [jsx_dev_runtime_1.jsxDEV("p", {}, void 0, false, { fileName: _jsxFileName, lineNumber: 5, columnNumber: 3 }, this), "text", jsx_dev_runtime_1.jsxDEV("div", { className: "foo" }, void 0, false, { fileName: _jsxFileName, lineNumber: 7, columnNumber: 3 }, this)] }, void 0, true, { fileName: _jsxFileName, lineNumber: 4, columnNumber: 10 }, this); diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).symbols b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).symbols new file mode 100644 index 0000000000000..c4bd360c1a3ea --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).symbols @@ -0,0 +1,39 @@ +=== tests/cases/conformance/jsx/jsxs/react.tsx === +/// +/* @jsxImportSource react */ +import "./preact"; +const a = <> +>a : Symbol(a, Decl(react.tsx, 3, 5)) + +

+>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) +>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) + + text +
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>className : Symbol(className, Decl(react.tsx, 6, 6)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + + + +export {}; +=== tests/cases/conformance/jsx/jsxs/preact.tsx === +/// +/* @jsxImportSource preact */ +const a = <> +>a : Symbol(a, Decl(preact.tsx, 2, 5)) + +

+>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) +>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) + + text +
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>className : Symbol(className, Decl(preact.tsx, 5, 6)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + + + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).types b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).types new file mode 100644 index 0000000000000..2cf985253e3c2 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformCustomImportPragma(jsx=react-jsxdev).types @@ -0,0 +1,45 @@ +=== tests/cases/conformance/jsx/jsxs/react.tsx === +/// +/* @jsxImportSource react */ +import "./preact"; +const a = <> +>a : JSX.Element +><>

text
: JSX.Element + +

+>

: JSX.Element +>p : any +>p : any + + text +
+>
: JSX.Element +>div : any +>className : string +>div : any + + + +export {}; +=== tests/cases/conformance/jsx/jsxs/preact.tsx === +/// +/* @jsxImportSource preact */ +const a = <> +>a : JSX.Element +><>

text
: JSX.Element + +

+>

: JSX.Element +>p : any +>p : any + + text +
+>
: JSX.Element +>div : any +>className : string +>div : any + + + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsx).js b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsx).js new file mode 100644 index 0000000000000..1c239af6274cb --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsx).js @@ -0,0 +1,12 @@ +//// [jsxJsxsCjsTransformSubstitutesNames.tsx] +/// +const a =
+ +export {}; + +//// [jsxJsxsCjsTransformSubstitutesNames.js] +"use strict"; +exports.__esModule = true; +var jsx_runtime_1 = require("react/jsx-runtime"); +/// +var a = jsx_runtime_1.jsx("div", {}, void 0); diff --git a/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsx).symbols b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsx).symbols new file mode 100644 index 0000000000000..f9c6220bda54d --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsx).symbols @@ -0,0 +1,8 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNames.tsx === +/// +const a =
+>a : Symbol(a, Decl(jsxJsxsCjsTransformSubstitutesNames.tsx, 1, 5)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsx).types b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsx).types new file mode 100644 index 0000000000000..4ff260cb8ddfe --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsx).types @@ -0,0 +1,9 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNames.tsx === +/// +const a =
+>a : JSX.Element +>
: JSX.Element +>div : any +>div : any + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsxdev).js b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsxdev).js new file mode 100644 index 0000000000000..8f7a10afefb44 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsxdev).js @@ -0,0 +1,13 @@ +//// [jsxJsxsCjsTransformSubstitutesNames.tsx] +/// +const a =
+ +export {}; + +//// [jsxJsxsCjsTransformSubstitutesNames.js] +"use strict"; +exports.__esModule = true; +var jsx_dev_runtime_1 = require("react/jsx-dev-runtime"); +var _jsxFileName = "tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNames.tsx"; +/// +var a = jsx_dev_runtime_1.jsxDEV("div", {}, void 0, false, { fileName: _jsxFileName, lineNumber: 2, columnNumber: 10 }, this); diff --git a/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsxdev).symbols b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsxdev).symbols new file mode 100644 index 0000000000000..f9c6220bda54d --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsxdev).symbols @@ -0,0 +1,8 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNames.tsx === +/// +const a =
+>a : Symbol(a, Decl(jsxJsxsCjsTransformSubstitutesNames.tsx, 1, 5)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsxdev).types b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsxdev).types new file mode 100644 index 0000000000000..4ff260cb8ddfe --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNames(jsx=react-jsxdev).types @@ -0,0 +1,9 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNames.tsx === +/// +const a =
+>a : JSX.Element +>
: JSX.Element +>div : any +>div : any + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsx).js b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsx).js new file mode 100644 index 0000000000000..74944d20d7c31 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsx).js @@ -0,0 +1,16 @@ +//// [jsxJsxsCjsTransformSubstitutesNamesFragment.tsx] +/// +const a = <> +

+ text +
+ + +export {}; + +//// [jsxJsxsCjsTransformSubstitutesNamesFragment.js] +"use strict"; +exports.__esModule = true; +var jsx_runtime_1 = require("react/jsx-runtime"); +/// +var a = jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [jsx_runtime_1.jsx("p", {}, void 0), "text", jsx_runtime_1.jsx("div", {}, void 0)] }, void 0); diff --git a/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsx).symbols b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsx).symbols new file mode 100644 index 0000000000000..900b88a374742 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsx).symbols @@ -0,0 +1,17 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNamesFragment.tsx === +/// +const a = <> +>a : Symbol(a, Decl(jsxJsxsCjsTransformSubstitutesNamesFragment.tsx, 1, 5)) + +

+>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) +>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) + + text +
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + + + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsx).types b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsx).types new file mode 100644 index 0000000000000..7b03d8f188e03 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsx).types @@ -0,0 +1,20 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNamesFragment.tsx === +/// +const a = <> +>a : JSX.Element +><>

text
: JSX.Element + +

+>

: JSX.Element +>p : any +>p : any + + text +
+>
: JSX.Element +>div : any +>div : any + + + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsxdev).js b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsxdev).js new file mode 100644 index 0000000000000..810e1941eb985 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsxdev).js @@ -0,0 +1,17 @@ +//// [jsxJsxsCjsTransformSubstitutesNamesFragment.tsx] +/// +const a = <> +

+ text +
+ + +export {}; + +//// [jsxJsxsCjsTransformSubstitutesNamesFragment.js] +"use strict"; +exports.__esModule = true; +var jsx_dev_runtime_1 = require("react/jsx-dev-runtime"); +var _jsxFileName = "tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNamesFragment.tsx"; +/// +var a = jsx_dev_runtime_1.jsxDEV(jsx_dev_runtime_1.Fragment, { children: [jsx_dev_runtime_1.jsxDEV("p", {}, void 0, false, { fileName: _jsxFileName, lineNumber: 3, columnNumber: 3 }, this), "text", jsx_dev_runtime_1.jsxDEV("div", {}, void 0, false, { fileName: _jsxFileName, lineNumber: 5, columnNumber: 3 }, this)] }, void 0, true, { fileName: _jsxFileName, lineNumber: 2, columnNumber: 10 }, this); diff --git a/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsxdev).symbols b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsxdev).symbols new file mode 100644 index 0000000000000..900b88a374742 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsxdev).symbols @@ -0,0 +1,17 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNamesFragment.tsx === +/// +const a = <> +>a : Symbol(a, Decl(jsxJsxsCjsTransformSubstitutesNamesFragment.tsx, 1, 5)) + +

+>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) +>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) + + text +
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + + + +export {}; diff --git a/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsxdev).types b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsxdev).types new file mode 100644 index 0000000000000..7b03d8f188e03 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformSubstitutesNamesFragment(jsx=react-jsxdev).types @@ -0,0 +1,20 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNamesFragment.tsx === +/// +const a = <> +>a : JSX.Element +><>

text
: JSX.Element + +

+>

: JSX.Element +>p : any +>p : any + + text +
+>
: JSX.Element +>div : any +>div : any + + + +export {}; diff --git a/tests/baselines/reference/showConfig/Shows tsconfig for single option/jsxImportSource/tsconfig.json b/tests/baselines/reference/showConfig/Shows tsconfig for single option/jsxImportSource/tsconfig.json new file mode 100644 index 0000000000000..37e03603be717 --- /dev/null +++ b/tests/baselines/reference/showConfig/Shows tsconfig for single option/jsxImportSource/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "jsxImportSource": "someString" + } +} diff --git a/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImport.tsx b/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImport.tsx new file mode 100644 index 0000000000000..e75927dd758fb --- /dev/null +++ b/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImport.tsx @@ -0,0 +1,12 @@ +// @jsx: react-jsx,react-jsxdev +// @jsxImportSource: preact +// @strict: true +// @module: commonjs +/// +const a = <> +

+ text +
+ + +export {}; \ No newline at end of file diff --git a/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImportPragma.tsx b/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImportPragma.tsx new file mode 100644 index 0000000000000..a6c2d865f2080 --- /dev/null +++ b/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformCustomImportPragma.tsx @@ -0,0 +1,24 @@ +// @jsx: react-jsx,react-jsxdev +// @strict: true +// @module: commonjs +// @filename: preact.tsx +/// +/* @jsxImportSource preact */ +const a = <> +

+ text +
+ + +export {}; +// @filename: react.tsx +/// +/* @jsxImportSource react */ +import "./preact"; +const a = <> +

+ text +
+ + +export {}; \ No newline at end of file diff --git a/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNames.tsx b/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNames.tsx new file mode 100644 index 0000000000000..169efee411df9 --- /dev/null +++ b/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNames.tsx @@ -0,0 +1,7 @@ +// @jsx: react-jsx,react-jsxdev +// @strict: true +// @module: commonjs +/// +const a =
+ +export {}; \ No newline at end of file diff --git a/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNamesFragment.tsx b/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNamesFragment.tsx new file mode 100644 index 0000000000000..99cafb63148ae --- /dev/null +++ b/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformSubstitutesNamesFragment.tsx @@ -0,0 +1,11 @@ +// @jsx: react-jsx,react-jsxdev +// @strict: true +// @module: commonjs +/// +const a = <> +

+ text +
+ + +export {}; \ No newline at end of file