From a928961c517b51156ea0d8c7d5a30f38691eda36 Mon Sep 17 00:00:00 2001
From: robobun <117481402+robobun@users.noreply.github.com>
Date: Thu, 30 Jul 2026 14:15:22 +0000
Subject: [PATCH 1/5] docs(jsx): note "react-jsx" selects the production
runtime; JSDoc for Bun.build jsx options
Follow-up to #34422, which made tsconfig "react-jsx" emit the production
automatic runtime instead of the development one. The behavior now matches
TypeScript and esbuild, but users upgrading from a version that always
emitted jsxDEV may not expect the change.
- docs/runtime/jsx.mdx: add a Note under the jsx table spelling out that
"react-jsx" = prod / "react-jsxdev" = dev, point users who want DevTools
source locations at "react-jsxdev", and record the pre-1.4 behavior.
- packages/bun-types/bun.d.ts: document each value of TSConfig
compilerOptions.jsx, and add per-field JSDoc to the Bun.build jsx config
object (runtime, importSource, factory, fragment, sideEffects,
development).
---
docs/runtime/jsx.mdx | 10 +++++++++
packages/bun-types/bun.d.ts | 45 ++++++++++++++++++++++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/docs/runtime/jsx.mdx b/docs/runtime/jsx.mdx
index af3f4882ca1c..f2b583052ef6 100644
--- a/docs/runtime/jsx.mdx
+++ b/docs/runtime/jsx.mdx
@@ -38,6 +38,16 @@ How JSX constructs are transformed into vanilla JavaScript internally. The follo
| `json { "jsx": "react-jsxdev" } ` | `tsx import { jsxDEV } from "react/jsx-dev-runtime"; jsxDEV( "Box", { width: 5, children: "Hello" }, undefined, false, undefined, this, ); `
The `jsxDEV` variable name is a React convention. The `DEV` suffix marks code intended for development. The development version of React is slower and includes additional validity checks & debugging tools. |
| `json { "jsx": "preserve" } ` | `tsx // JSX is not transpiled // "preserve" is not supported by Bun currently Hello ` |
+
+ `"react-jsx"` selects the production automatic runtime (`jsx`/`jsxs` from `/jsx-runtime`) and `"react-jsxdev"`
+ selects the development runtime (`jsxDEV` from `/jsx-dev-runtime`), matching TypeScript and esbuild. If you
+ rely on the extra debug information `jsxDEV` provides (component source locations for React DevTools, key warnings),
+ use `"react-jsxdev"` during development.
+
+Prior to Bun 1.4, `"react-jsx"` behaved like `"react-jsxdev"` and emitted the development runtime.
+
+
+
### [`jsxFactory`](https://www.typescriptlang.org/tsconfig#jsxFactory)
Only applicable when `jsx` is `react`.
diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts
index 87d0f34d25d6..1183e8d55769 100644
--- a/packages/bun-types/bun.d.ts
+++ b/packages/bun-types/bun.d.ts
@@ -2387,7 +2387,16 @@ declare module "bun" {
compilerOptions?: {
paths?: Record;
baseUrl?: string;
- /** "preserve" is not supported yet */
+ /**
+ * How JSX is transformed.
+ *
+ * - `"react"`: classic runtime. Emits `React.createElement(...)` (or the configured {@link jsxFactory}).
+ * - `"react-jsx"`: automatic runtime, production. Emits `jsx`/`jsxs` imported from `/jsx-runtime`.
+ * - `"react-jsxdev"`: automatic runtime, development. Emits `jsxDEV` imported from `/jsx-dev-runtime`, including source location and `__self` for React DevTools.
+ * - `"preserve"`: not supported yet; currently falls back to the automatic runtime.
+ *
+ * Prior to Bun 1.4, `"react-jsx"` emitted the development runtime. It now matches TypeScript and esbuild.
+ */
jsx?: "preserve" | "react" | "react-jsx" | "react-jsxdev";
jsxFactory?: string;
jsxFragmentFactory?: string;
@@ -2899,11 +2908,45 @@ declare module "bun" {
* JSX configuration options
*/
jsx?: {
+ /**
+ * - `"automatic"`: auto-import `jsx`/`jsxs` (or `jsxDEV`) from `/jsx-runtime`.
+ * - `"classic"`: emit `factory(type, props, ...children)` with no auto-import.
+ *
+ * @default "automatic"
+ */
runtime?: "automatic" | "classic";
+ /**
+ * Package the automatic runtime imports from. Bun appends `/jsx-runtime` or `/jsx-dev-runtime`.
+ * Only used when `runtime` is `"automatic"`.
+ *
+ * @default "react"
+ */
importSource?: string;
+ /**
+ * Function called for each JSX element when `runtime` is `"classic"`.
+ *
+ * @default "React.createElement"
+ */
factory?: string;
+ /**
+ * Value used for JSX fragments (`<>...>`) when `runtime` is `"classic"`.
+ *
+ * @default "React.Fragment"
+ */
fragment?: string;
+ /**
+ * Treat the auto-imported JSX runtime module as having side effects, disabling tree-shaking of the import.
+ *
+ * @default false
+ */
sideEffects?: boolean;
+ /**
+ * Use the development automatic runtime: import `jsxDEV` from `/jsx-dev-runtime` and
+ * pass source location / `__self` for React DevTools. When `false`, import `jsx`/`jsxs` from
+ * `/jsx-runtime`. Only used when `runtime` is `"automatic"`.
+ *
+ * When not set, derived from `NODE_ENV` and tsconfig `compilerOptions.jsx`.
+ */
development?: boolean;
};
From 97258c76932680512d4054d2576387a1543dbc08 Mon Sep 17 00:00:00 2001
From: robobun <117481402+robobun@users.noreply.github.com>
Date: Thu, 30 Jul 2026 14:17:34 +0000
Subject: [PATCH 2/5] docs(jsx): drop source-location claim; Bun emits
undefined for the jsxDEV source arg
---
docs/runtime/jsx.mdx | 4 ++--
packages/bun-types/bun.d.ts | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/docs/runtime/jsx.mdx b/docs/runtime/jsx.mdx
index f2b583052ef6..279421d3dc4c 100644
--- a/docs/runtime/jsx.mdx
+++ b/docs/runtime/jsx.mdx
@@ -41,8 +41,8 @@ How JSX constructs are transformed into vanilla JavaScript internally. The follo
`"react-jsx"` selects the production automatic runtime (`jsx`/`jsxs` from `/jsx-runtime`) and `"react-jsxdev"`
selects the development runtime (`jsxDEV` from `/jsx-dev-runtime`), matching TypeScript and esbuild. If you
- rely on the extra debug information `jsxDEV` provides (component source locations for React DevTools, key warnings),
- use `"react-jsxdev"` during development.
+ rely on React's development-mode checks that `jsxDEV` enables (for example, missing `key` warnings), use
+ `"react-jsxdev"` during development.
Prior to Bun 1.4, `"react-jsx"` behaved like `"react-jsxdev"` and emitted the development runtime.
diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts
index 1183e8d55769..acb995868c32 100644
--- a/packages/bun-types/bun.d.ts
+++ b/packages/bun-types/bun.d.ts
@@ -2392,7 +2392,7 @@ declare module "bun" {
*
* - `"react"`: classic runtime. Emits `React.createElement(...)` (or the configured {@link jsxFactory}).
* - `"react-jsx"`: automatic runtime, production. Emits `jsx`/`jsxs` imported from `/jsx-runtime`.
- * - `"react-jsxdev"`: automatic runtime, development. Emits `jsxDEV` imported from `/jsx-dev-runtime`, including source location and `__self` for React DevTools.
+ * - `"react-jsxdev"`: automatic runtime, development. Emits `jsxDEV` imported from `/jsx-dev-runtime` with the extra arguments React uses for development-mode checks.
* - `"preserve"`: not supported yet; currently falls back to the automatic runtime.
*
* Prior to Bun 1.4, `"react-jsx"` emitted the development runtime. It now matches TypeScript and esbuild.
@@ -2941,8 +2941,8 @@ declare module "bun" {
*/
sideEffects?: boolean;
/**
- * Use the development automatic runtime: import `jsxDEV` from `/jsx-dev-runtime` and
- * pass source location / `__self` for React DevTools. When `false`, import `jsx`/`jsxs` from
+ * Use the development automatic runtime: import `jsxDEV` from `/jsx-dev-runtime` with the
+ * extra arguments React uses for development-mode checks. When `false`, import `jsx`/`jsxs` from
* `/jsx-runtime`. Only used when `runtime` is `"automatic"`.
*
* When not set, derived from `NODE_ENV` and tsconfig `compilerOptions.jsx`.
From f15636f3d5dd9cf247f865b74df43dc6b1e9af15 Mon Sep 17 00:00:00 2001
From: robobun <117481402+robobun@users.noreply.github.com>
Date: Thu, 30 Jul 2026 14:28:40 +0000
Subject: [PATCH 3/5] types(jsx): correct sideEffects semantics (pure
annotation, not import tree-shaking); split runtime from-clause
---
packages/bun-types/bun.d.ts | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts
index acb995868c32..2be2ae3fe178 100644
--- a/packages/bun-types/bun.d.ts
+++ b/packages/bun-types/bun.d.ts
@@ -2909,7 +2909,8 @@ declare module "bun" {
*/
jsx?: {
/**
- * - `"automatic"`: auto-import `jsx`/`jsxs` (or `jsxDEV`) from `/jsx-runtime`.
+ * - `"automatic"`: auto-import `jsx`/`jsxs` from `/jsx-runtime`, or `jsxDEV` from
+ * `/jsx-dev-runtime` when {@link development} is `true`.
* - `"classic"`: emit `factory(type, props, ...children)` with no auto-import.
*
* @default "automatic"
@@ -2935,7 +2936,8 @@ declare module "bun" {
*/
fragment?: string;
/**
- * Treat the auto-imported JSX runtime module as having side effects, disabling tree-shaking of the import.
+ * Treat JSX elements as having side effects. Disables the pure annotation on each emitted
+ * `jsx(...)` / `createElement(...)` call so unused JSX elements are not removed.
*
* @default false
*/
From bf5c795870a7e56816fda6885c1d522b4361c445 Mon Sep 17 00:00:00 2001
From: robobun <117481402+robobun@users.noreply.github.com>
Date: Thu, 30 Jul 2026 14:50:59 +0000
Subject: [PATCH 4/5] docs(jsx): drop key-warning example and development
default clause
React fires missing-key warnings from react/jsx-runtime too (gated on
NODE_ENV, not on jsxDEV), so the example was misleading. The "derived from
NODE_ENV and tsconfig" default clause for BuildConfig.jsx.development does
not match current Bun.build behavior (tsconfig is not consulted and an
explicit value can be overridden by NODE_ENV); removed rather than
documenting in-flux precedence.
---
docs/runtime/jsx.mdx | 5 ++---
packages/bun-types/bun.d.ts | 9 +++------
2 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/docs/runtime/jsx.mdx b/docs/runtime/jsx.mdx
index 279421d3dc4c..657ddf8a9707 100644
--- a/docs/runtime/jsx.mdx
+++ b/docs/runtime/jsx.mdx
@@ -40,9 +40,8 @@ How JSX constructs are transformed into vanilla JavaScript internally. The follo
`"react-jsx"` selects the production automatic runtime (`jsx`/`jsxs` from `/jsx-runtime`) and `"react-jsxdev"`
- selects the development runtime (`jsxDEV` from `/jsx-dev-runtime`), matching TypeScript and esbuild. If you
- rely on React's development-mode checks that `jsxDEV` enables (for example, missing `key` warnings), use
- `"react-jsxdev"` during development.
+ selects the development runtime (`jsxDEV` from `/jsx-dev-runtime`), matching TypeScript and esbuild. Use
+ `"react-jsxdev"` during development if you want the `jsxDEV` entry point.
Prior to Bun 1.4, `"react-jsx"` behaved like `"react-jsxdev"` and emitted the development runtime.
diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts
index 2be2ae3fe178..1edc972d8874 100644
--- a/packages/bun-types/bun.d.ts
+++ b/packages/bun-types/bun.d.ts
@@ -2392,7 +2392,7 @@ declare module "bun" {
*
* - `"react"`: classic runtime. Emits `React.createElement(...)` (or the configured {@link jsxFactory}).
* - `"react-jsx"`: automatic runtime, production. Emits `jsx`/`jsxs` imported from `/jsx-runtime`.
- * - `"react-jsxdev"`: automatic runtime, development. Emits `jsxDEV` imported from `/jsx-dev-runtime` with the extra arguments React uses for development-mode checks.
+ * - `"react-jsxdev"`: automatic runtime, development. Emits `jsxDEV` imported from `/jsx-dev-runtime`.
* - `"preserve"`: not supported yet; currently falls back to the automatic runtime.
*
* Prior to Bun 1.4, `"react-jsx"` emitted the development runtime. It now matches TypeScript and esbuild.
@@ -2943,11 +2943,8 @@ declare module "bun" {
*/
sideEffects?: boolean;
/**
- * Use the development automatic runtime: import `jsxDEV` from `/jsx-dev-runtime` with the
- * extra arguments React uses for development-mode checks. When `false`, import `jsx`/`jsxs` from
- * `/jsx-runtime`. Only used when `runtime` is `"automatic"`.
- *
- * When not set, derived from `NODE_ENV` and tsconfig `compilerOptions.jsx`.
+ * Use the development automatic runtime: import `jsxDEV` from `/jsx-dev-runtime`. When `false`,
+ * import `jsx`/`jsxs` from `/jsx-runtime`. Only used when `runtime` is `"automatic"`.
*/
development?: boolean;
};
From 61584a5915a68fc95302c548cf99173d39409a65 Mon Sep 17 00:00:00 2001
From: robobun <117481402+robobun@users.noreply.github.com>
Date: Thu, 30 Jul 2026 14:52:13 +0000
Subject: [PATCH 5/5] drop packages/bun-types JSDoc; keep the docs-only Note
JSDoc comments in .d.ts have no runtime or type-check observable effect, so
there is no fail-before test the gate can run for them. The docs/runtime/jsx.mdx
Note is the primary visibility deliverable.
---
packages/bun-types/bun.d.ts | 44 +------------------------------------
1 file changed, 1 insertion(+), 43 deletions(-)
diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts
index 1edc972d8874..87d0f34d25d6 100644
--- a/packages/bun-types/bun.d.ts
+++ b/packages/bun-types/bun.d.ts
@@ -2387,16 +2387,7 @@ declare module "bun" {
compilerOptions?: {
paths?: Record;
baseUrl?: string;
- /**
- * How JSX is transformed.
- *
- * - `"react"`: classic runtime. Emits `React.createElement(...)` (or the configured {@link jsxFactory}).
- * - `"react-jsx"`: automatic runtime, production. Emits `jsx`/`jsxs` imported from `/jsx-runtime`.
- * - `"react-jsxdev"`: automatic runtime, development. Emits `jsxDEV` imported from `/jsx-dev-runtime`.
- * - `"preserve"`: not supported yet; currently falls back to the automatic runtime.
- *
- * Prior to Bun 1.4, `"react-jsx"` emitted the development runtime. It now matches TypeScript and esbuild.
- */
+ /** "preserve" is not supported yet */
jsx?: "preserve" | "react" | "react-jsx" | "react-jsxdev";
jsxFactory?: string;
jsxFragmentFactory?: string;
@@ -2908,44 +2899,11 @@ declare module "bun" {
* JSX configuration options
*/
jsx?: {
- /**
- * - `"automatic"`: auto-import `jsx`/`jsxs` from `/jsx-runtime`, or `jsxDEV` from
- * `/jsx-dev-runtime` when {@link development} is `true`.
- * - `"classic"`: emit `factory(type, props, ...children)` with no auto-import.
- *
- * @default "automatic"
- */
runtime?: "automatic" | "classic";
- /**
- * Package the automatic runtime imports from. Bun appends `/jsx-runtime` or `/jsx-dev-runtime`.
- * Only used when `runtime` is `"automatic"`.
- *
- * @default "react"
- */
importSource?: string;
- /**
- * Function called for each JSX element when `runtime` is `"classic"`.
- *
- * @default "React.createElement"
- */
factory?: string;
- /**
- * Value used for JSX fragments (`<>...>`) when `runtime` is `"classic"`.
- *
- * @default "React.Fragment"
- */
fragment?: string;
- /**
- * Treat JSX elements as having side effects. Disables the pure annotation on each emitted
- * `jsx(...)` / `createElement(...)` call so unused JSX elements are not removed.
- *
- * @default false
- */
sideEffects?: boolean;
- /**
- * Use the development automatic runtime: import `jsxDEV` from `/jsx-dev-runtime`. When `false`,
- * import `jsx`/`jsxs` from `/jsx-runtime`. Only used when `runtime` is `"automatic"`.
- */
development?: boolean;
};