aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Dylan Conway <35280289+dylan-conway@users.noreply.github.com> 2023-06-02 20:35:00 -0700
committerGravatar GitHub <noreply@github.com> 2023-06-02 20:35:00 -0700
commitd8e7436db02f38f74ce29b4a0e7c0efcd133ec53 (patch)
tree6606ff8423f33643260d0ddd54077519491070cf
parentf798a0cfe8372e7df62d9514e6785e6f16549d25 (diff)
downloadbun-d8e7436db02f38f74ce29b4a0e7c0efcd133ec53.tar.gz
bun-d8e7436db02f38f74ce29b4a0e7c0efcd133ec53.tar.zst
bun-d8e7436db02f38f74ce29b4a0e7c0efcd133ec53.zip
use NODE_ENV for react-jsx or react-jsxdev (#3184)
-rw-r--r--src/bun.js/api/JSTranspiler.zig1
-rw-r--r--src/resolver/resolver.zig2
-rw-r--r--src/resolver/tsconfig_json.zig14
-rw-r--r--test/bundler/bundler_jsx.test.ts2
-rw-r--r--test/bundler/esbuild/tsconfig.test.ts126
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