diff options
-rw-r--r-- | src/bun.js/api/JSTranspiler.zig | 1 | ||||
-rw-r--r-- | src/resolver/resolver.zig | 2 | ||||
-rw-r--r-- | src/resolver/tsconfig_json.zig | 14 | ||||
-rw-r--r-- | test/bundler/bundler_jsx.test.ts | 2 | ||||
-rw-r--r-- | test/bundler/esbuild/tsconfig.test.ts | 126 |
5 files changed, 128 insertions, 17 deletions
diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index c58029c5e..83e3b741f 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -464,7 +464,6 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std &transpiler.log, logger.Source.initPathString("tsconfig.json", transpiler.tsconfig_buf), &VirtualMachine.get().bundler.resolver.caches.json, - true, ) catch null) |parsed_tsconfig| { transpiler.tsconfig = parsed_tsconfig; } diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index e23f00c9a..8a6a2bc5e 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -2332,7 +2332,7 @@ pub const Resolver = struct { const source = logger.Source.initPathString(key_path.text, entry.contents); const file_dir = source.path.sourceDir(); - var result = (try TSConfigJSON.parse(bun.fs_allocator, r.log, source, &r.caches.json, r.opts.jsx.development)) orelse return null; + var result = (try TSConfigJSON.parse(bun.fs_allocator, r.log, source, &r.caches.json)) orelse return null; if (result.hasBaseURL()) { diff --git a/src/resolver/tsconfig_json.zig b/src/resolver/tsconfig_json.zig index 7ec6b3e0b..4f04c39ca 100644 --- a/src/resolver/tsconfig_json.zig +++ b/src/resolver/tsconfig_json.zig @@ -104,9 +104,7 @@ pub const TSConfigJSON = struct { log: *logger.Log, source: logger.Source, json_cache: *cache.Json, - is_jsx_development_: bool, ) anyerror!?*TSConfigJSON { - var is_jsx_development = is_jsx_development_; // Unfortunately "tsconfig.json" isn't actually JSON. It's some other // format that appears to be defined by the implementation details of the // TypeScript compiler. @@ -155,20 +153,18 @@ pub const TSConfigJSON = struct { } } + // https://www.typescriptlang.org/docs/handbook/jsx.html#basic-usages if (compiler_opts.expr.asProperty("jsx")) |jsx_prop| { if (jsx_prop.expr.asString(allocator)) |str| { var str_lower = allocator.alloc(u8, str.len) catch unreachable; defer allocator.free(str_lower); _ = strings.copyLowercase(str, str_lower); - // we don't support "preserve" yet + // - We don't support "preserve" yet + // - We rely on NODE_ENV for "jsx" or "jsxDEV" + // - We treat "react-jsx" and "react-jsxDEV" identically + // because it is too easy to auto-import the wrong one. if (options.JSX.RuntimeMap.get(str_lower)) |runtime| { result.jsx.runtime = runtime; - if (runtime == .automatic) { - result.jsx.setProduction(!strings.contains(str_lower, "jsxdev")); - is_jsx_development = result.jsx.development; - result.jsx_flags.insert(.development); - } - result.jsx_flags.insert(.runtime); } } diff --git a/test/bundler/bundler_jsx.test.ts b/test/bundler/bundler_jsx.test.ts index 455deea91..a77eec0d0 100644 --- a/test/bundler/bundler_jsx.test.ts +++ b/test/bundler/bundler_jsx.test.ts @@ -118,7 +118,6 @@ function itBundledDevAndProd( ) { const { devStdout, prodStdout, ...rest } = opts; itBundled(id + "Dev", { - todo: opts.devTodo, ...rest, env: { NODE_ENV: "development", @@ -131,7 +130,6 @@ function itBundledDevAndProd( : rest.run, }); itBundled(id + "Prod", { - todo: opts.prodTodo, ...rest, env: { NODE_ENV: "production", diff --git a/test/bundler/esbuild/tsconfig.test.ts b/test/bundler/esbuild/tsconfig.test.ts index 2b9521954..e83a1eb23 100644 --- a/test/bundler/esbuild/tsconfig.test.ts +++ b/test/bundler/esbuild/tsconfig.test.ts @@ -411,13 +411,15 @@ describe("bundler", () => { "/Users/user/project/tsconfig.json": /* json */ ` { "compilerOptions": { - "jsx": "react-jsx", "jsxImportSource": "notreact" } } `, }, outfile: "/Users/user/project/out.js", + env: { + NODE_ENV: "production", + }, external: ["notreact"], onAfterBundle(api) { api.expectFile("/Users/user/project/out.js").toContain(`from "notreact/jsx-runtime`); @@ -438,7 +440,6 @@ describe("bundler", () => { "/Users/user/project/tsconfig.json": /* json */ ` { "compilerOptions": { - "jsx": "react-jsx", "jsxImportSource": "@notreact/jsx" } } @@ -446,6 +447,9 @@ describe("bundler", () => { }, outfile: "/Users/user/project/out.js", external: ["@notreact/jsx"], + env: { + NODE_ENV: "production", + }, onAfterBundle(api) { api.expectFile("/Users/user/project/out.js").toContain(`from "@notreact/jsx/jsx-runtime`); }, @@ -503,11 +507,11 @@ describe("bundler", () => { api.expectFile("/Users/user/project/out.js").toContain(`from "react/jsx-dev-runtime`); }, }); - itBundled("tsconfig/ReactJSX", { + itBundled("tsconfig/ReactJSXDevTSConfigProduction", { // GENERATED files: { "/Users/user/project/entry.tsx": `console.log(<><div/><div/></>)`, - "/Users/user/project/node_modules/react/jsx-runtime.ts": ` + "/Users/user/project/node_modules/react/jsx-dev-runtime.ts": ` export const Fragment = (props: { key?: string; children?: Child[] }): JSXNode => { return new JSXFragmentNode('', {}, props.children || []) } @@ -524,11 +528,125 @@ describe("bundler", () => { `, }, external: ["react"], + env: { + NODE_ENV: "development", + }, + outfile: "/Users/user/project/out.js", + onAfterBundle(api) { + api.expectFile("/Users/user/project/out.js").toContain(`from "react/jsx-dev-runtime`); + }, + }); + itBundled("tsconfig/ReactJSX", { + // GENERATED + files: { + "/Users/user/project/entry.tsx": `console.log(<><div/><div/></>)`, + "/Users/user/project/node_modules/react/jsx-runtime.ts": ` + export const Fragment = (props: { key?: string; children?: Child[] }): JSXNode => { + return new JSXFragmentNode('', {}, props.children || []) + } + export const jsx = (tag: string | JSXComponent, props: { key?: string; children?: Child[] }, ...children: Child[]): JSXNode => { + return new JSXNode(tag, props, children) + } + `, + }, + external: ["react"], + env: { + NODE_ENV: "production", + }, outfile: "/Users/user/project/out.js", onAfterBundle(api) { api.expectFile("/Users/user/project/out.js").toContain(`from "react/jsx-runtime`); }, }); + + itBundled("tsconfig/ReactJSXClassic", { + // GENERATED + files: { + "/Users/user/project/entry.tsx": `console.log(<><div/><div/></>)`, + "/Users/user/project/node_modules/react/jsx-dev-runtime.ts": ` + export const Fragment = (props: { key?: string; children?: Child[] }): JSXNode => { + return new JSXFragmentNode('', {}, props.children || []) + } + export const jsx = (tag: string | JSXComponent, props: { key?: string; children?: Child[] }, ...children: Child[]): JSXNode => { + return new JSXNode(tag, props, children) + } + `, + "/Users/user/project/tsconfig.json": /* json */ ` + { + "compilerOptions": { + "jsx": "react" + } + } + `, + }, + external: ["react"], + outfile: "/Users/user/project/out.js", + onAfterBundle(api) { + api.expectFile("/Users/user/project/out.js").toContain(`React.Fragment`); + api.expectFile("/Users/user/project/out.js").toContain(`React.createElement`); + }, + }); + itBundled("tsconfig/ReactJSXClassicWithNODE_ENV=Production", { + // GENERATED + files: { + "/Users/user/project/entry.tsx": `console.log(<><div/><div/></>)`, + "/Users/user/project/node_modules/react/jsx-dev-runtime.ts": ` + export const Fragment = (props: { key?: string; children?: Child[] }): JSXNode => { + return new JSXFragmentNode('', {}, props.children || []) + } + export const jsx = (tag: string | JSXComponent, props: { key?: string; children?: Child[] }, ...children: Child[]): JSXNode => { + return new JSXNode(tag, props, children) + } + `, + "/Users/user/project/tsconfig.json": /* json */ ` + { + "compilerOptions": { + "jsx": "react" + } + } + `, + }, + external: ["react"], + outfile: "/Users/user/project/out.js", + env: { + NODE_ENV: "production", + }, + onAfterBundle(api) { + api.expectFile("/Users/user/project/out.js").toContain(`React.Fragment`); + api.expectFile("/Users/user/project/out.js").toContain(`React.createElement`); + }, + }); + + itBundled("tsconfig/ReactJSXClassicWithNODE_ENV=Development", { + // GENERATED + files: { + "/Users/user/project/entry.tsx": `console.log(<><div/><div/></>)`, + "/Users/user/project/node_modules/react/jsx-dev-runtime.ts": ` + export const Fragment = (props: { key?: string; children?: Child[] }): JSXNode => { + return new JSXFragmentNode('', {}, props.children || []) + } + export const jsx = (tag: string | JSXComponent, props: { key?: string; children?: Child[] }, ...children: Child[]): JSXNode => { + return new JSXNode(tag, props, children) + } + `, + "/Users/user/project/tsconfig.json": /* json */ ` + { + "compilerOptions": { + "jsx": "react" + } + } + `, + }, + external: ["react"], + outfile: "/Users/user/project/out.js", + env: { + NODE_ENV: "development", + }, + onAfterBundle(api) { + api.expectFile("/Users/user/project/out.js").toContain(`React.Fragment`); + api.expectFile("/Users/user/project/out.js").toContain(`React.createElement`); + }, + }); return; itBundled("tsconfig/PathsTypeOnly", { // GENERATED |