refactor: move jsxSideEffects from tsconfig to jsx build config (#22665)

## Summary
- Moved `jsxSideEffects` (now `sideEffects`) from tsconfig.json compiler
options to the jsx object in the build API
- Updated all jsx bundler tests to use the new jsx.sideEffects
configuration
- Added jsx configuration parsing to JSBundler.zig

## Changes
- Removed jsxSideEffects parsing from `src/resolver/tsconfig_json.zig`
- Added jsx configuration parsing to `src/bun.js/api/JSBundler.zig`
Config.fromJS
- Fixed TransformOptions to properly pass jsx config to the transpiler
in `src/bundler/bundle_v2.zig`
- Updated TypeScript definitions to include jsx field in BuildConfigBase
- Modified test framework to support jsx configuration in API mode
- Updated all jsx tests to use `sideEffects` in the jsx config instead
of `side_effects` in tsconfig

## Test plan
All 27 jsx bundler tests are passing with the new configuration
structure.

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
robobun
2025-09-20 05:50:30 -07:00
committed by GitHub
parent 7c0574eeb4
commit 71a8900013
7 changed files with 149 additions and 33 deletions

View File

@@ -449,11 +449,11 @@ describe("bundler", () => {
runtime: "classic",
factory: "React.createElement",
fragment: "React.Fragment",
side_effects: true,
sideEffects: true,
},
onAfterBundle(api) {
const file = api.readFile("out.js");
// When jsxSideEffects is true: should NOT include /* @__PURE__ */ comments
// When sideEffects is true: should NOT include /* @__PURE__ */ comments
expect(file).not.toContain("/* @__PURE__ */");
expect(file).toContain("React.createElement");
expect(normalizeBunSnapshot(file)).toMatchInlineSnapshot(`
@@ -510,11 +510,11 @@ describe("bundler", () => {
target: "bun",
jsx: {
runtime: "automatic",
side_effects: true,
sideEffects: true,
},
onAfterBundle(api) {
const file = api.readFile("out.js");
// When jsxSideEffects is true: should NOT include /* @__PURE__ */ comments
// When sideEffects is true: should NOT include /* @__PURE__ */ comments
expect(file).not.toContain("/* @__PURE__ */");
expect(normalizeBunSnapshot(file)).toMatchInlineSnapshot(`
"// @bun
@@ -573,18 +573,19 @@ describe("bundler", () => {
...helpers,
},
target: "bun",
backend: "api",
jsx: {
runtime: "classic",
factory: "React.createElement",
fragment: "React.Fragment",
side_effects: true,
sideEffects: true,
},
env: {
NODE_ENV: "production",
},
onAfterBundle(api) {
const file = api.readFile("out.js");
// When jsxSideEffects is true in production: should NOT include /* @__PURE__ */ comments
// When sideEffects is true in production: should NOT include /* @__PURE__ */ comments
expect(file).not.toContain("/* @__PURE__ */");
expect(file).toContain("React.createElement");
expect(normalizeBunSnapshot(file)).toMatchInlineSnapshot(`
@@ -639,16 +640,18 @@ describe("bundler", () => {
...helpers,
},
target: "bun",
backend: "api",
jsx: {
runtime: "automatic",
side_effects: true,
sideEffects: true,
development: false,
},
env: {
NODE_ENV: "production",
},
onAfterBundle(api) {
const file = api.readFile("out.js");
// When jsxSideEffects is true in production: should NOT include /* @__PURE__ */ comments
// When sideEffects is true in production: should NOT include /* @__PURE__ */ comments
expect(file).not.toContain("/* @__PURE__ */");
expect(normalizeBunSnapshot(file)).toMatchInlineSnapshot(`
"// @bun
@@ -709,13 +712,16 @@ describe("bundler", () => {
itBundled("jsx/sideEffectsTrueTsconfig", {
files: {
"/index.jsx": /* jsx */ `console.log(<a></a>); console.log(<></>);`,
"/tsconfig.json": /* json */ `{"compilerOptions": {"jsxSideEffects": true}}`,
"/tsconfig.json": /* json */ `{"compilerOptions": {}}`,
...helpers,
},
jsx: {
sideEffects: true,
},
target: "bun",
onAfterBundle(api) {
const file = api.readFile("out.js");
// When jsxSideEffects is true via tsconfig: should NOT include /* @__PURE__ */ comments
// When sideEffects is true via tsconfig: should NOT include /* @__PURE__ */ comments
expect(file).not.toContain("/* @__PURE__ */");
expect(normalizeBunSnapshot(file)).toMatchInlineSnapshot(`
"// @bun
@@ -743,13 +749,19 @@ describe("bundler", () => {
itBundled("jsx/sideEffectsTrueTsconfigClassic", {
files: {
"/index.jsx": /* jsx */ `console.log(<a></a>); console.log(<></>);`,
"/tsconfig.json": /* json */ `{"compilerOptions": {"jsx": "react", "jsxSideEffects": true}}`,
"/tsconfig.json": /* json */ `{"compilerOptions": {"jsx": "react"}}`,
...helpers,
},
jsx: {
runtime: "classic",
factory: "React.createElement",
fragment: "React.Fragment",
sideEffects: true,
},
target: "bun",
onAfterBundle(api) {
const file = api.readFile("out.js");
// When jsxSideEffects is true via tsconfig with classic jsx: should NOT include /* @__PURE__ */ comments
// When sideEffects is true via tsconfig with classic jsx: should NOT include /* @__PURE__ */ comments
expect(file).not.toContain("/* @__PURE__ */");
expect(file).toContain("React.createElement");
expect(normalizeBunSnapshot(file)).toMatchInlineSnapshot(`
@@ -764,13 +776,17 @@ describe("bundler", () => {
itBundled("jsx/sideEffectsTrueTsconfigAutomatic", {
files: {
"/index.jsx": /* jsx */ `console.log(<a></a>); console.log(<></>);`,
"/tsconfig.json": /* json */ `{"compilerOptions": {"jsx": "react-jsx", "jsxSideEffects": true}}`,
"/tsconfig.json": /* json */ `{"compilerOptions": {"jsx": "react-jsx"}}`,
...helpers,
},
jsx: {
runtime: "automatic",
sideEffects: true,
},
target: "bun",
onAfterBundle(api) {
const file = api.readFile("out.js");
// When jsxSideEffects is true via tsconfig with automatic jsx: should NOT include /* @__PURE__ */ comments
// When sideEffects is true via tsconfig with automatic jsx: should NOT include /* @__PURE__ */ comments
expect(file).not.toContain("/* @__PURE__ */");
expect(normalizeBunSnapshot(file)).toMatchInlineSnapshot(`
"// @bun

View File

@@ -186,6 +186,8 @@ export interface BundlerTestInput {
importSource?: string; // for automatic
factory?: string; // for classic
fragment?: string; // for classic
sideEffects?: boolean; // whether jsx has side effects
development?: boolean; // whether to use development runtime
};
root?: string;
/** Defaults to `/out.js` */
@@ -574,10 +576,6 @@ function expectBundled(
if (!backend) {
backend =
dotenv ||
jsx.factory ||
jsx.fragment ||
jsx.runtime ||
jsx.importSource ||
typeof production !== "undefined" ||
bundling === false ||
(run && target === "node") ||
@@ -773,7 +771,7 @@ function expectBundled(
// jsx.preserve && "--jsx=preserve",
jsx.factory && `--jsx-factory=${jsx.factory}`,
jsx.fragment && `--jsx-fragment=${jsx.fragment}`,
jsx.side_effects && `--jsx-side-effects`,
jsx.sideEffects && `--jsx-side-effects`,
env?.NODE_ENV !== "production" && `--jsx-dev`,
entryNaming &&
entryNaming !== "[dir]/[name].[ext]" &&
@@ -1089,6 +1087,14 @@ function expectBundled(
define: define ?? {},
throw: _throw ?? false,
compile,
jsx: jsx ? {
runtime: jsx.runtime,
importSource: jsx.importSource,
factory: jsx.factory,
fragment: jsx.fragment,
sideEffects: jsx.sideEffects,
development: jsx.development,
} : undefined,
} as BuildConfig;
if (dotenv) {