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; };