## Summary
- Adds `import { feature } from "bun:bundle"` for compile-time feature
flag checking
- `feature("FLAG_NAME")` calls are replaced with `true`/`false` at
bundle time
- Enables dead-code elimination through `--feature=FLAG_NAME` CLI
argument
- Works in `bun build`, `bun run`, and `bun test`
- Available in both CLI and `Bun.build()` JavaScript API
## Usage
```ts
import { feature } from "bun:bundle";
if (feature("SUPER_SECRET")) {
console.log("Secret feature enabled!");
} else {
console.log("Normal mode");
}
```
### CLI
```bash
# Enable feature during build
bun build --feature=SUPER_SECRET index.ts
# Enable at runtime
bun run --feature=SUPER_SECRET index.ts
# Enable in tests
bun test --feature=SUPER_SECRET
```
### JavaScript API
```ts
await Bun.build({
entrypoints: ['./index.ts'],
outdir: './out',
features: ['SUPER_SECRET', 'ANOTHER_FLAG'],
});
```
## Implementation
- Added `bundler_feature_flags` (as `*const bun.StringSet`) to
`RuntimeFeatures` and `BundleOptions`
- Added `bundler_feature_flag_ref` to Parser struct to track the
`feature` import
- Handle `bun:bundle` import at parse time (similar to macros) - capture
ref, return empty statement
- Handle `feature()` calls in `e_call` visitor - replace with boolean
based on flags
- Wire feature flags through CLI arguments and `Bun.build()` API to
bundler options
- Added `features` option to `JSBundler.zig` for JavaScript API support
- Added TypeScript types in `bun.d.ts`
- Added documentation to `docs/bundler/index.mdx`
## Test plan
- [x] Basic feature flag enabled/disabled tests (both CLI and API
backends)
- [x] Multiple feature flags test
- [x] Dead code elimination verification tests
- [x] Error handling for invalid arguments
- [x] Runtime tests with `bun run --feature=FLAG`
- [x] Test runner tests with `bun test --feature=FLAG`
- [x] Aliased import tests (`import { feature as checkFeature }`)
- [x] Ternary operator DCE tests
- [x] Tests use `itBundled` with both `backend: "cli"` and `backend:
"api"`
🤖 Generated with [Claude Code](https://claude.com/claude-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>
Co-authored-by: Alistair Smith <hi@alistair.sh>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
## Summary
By default, standalone executables no longer load `tsconfig.json` and
`package.json` at runtime. This improves startup performance and
prevents unexpected behavior from config files in the runtime
environment.
- Added `--compile-autoload-tsconfig` / `--no-compile-autoload-tsconfig`
CLI flags (default: false)
- Added `--compile-autoload-package-json` /
`--no-compile-autoload-package-json` CLI flags (default: false)
- Added `autoloadTsconfig` and `autoloadPackageJson` options to the
`Bun.build()` compile config
- Flags are stored in `StandaloneModuleGraph.Flags` and applied at
runtime boot
This follows the same pattern as the existing
`--compile-autoload-dotenv` and `--compile-autoload-bunfig` flags.
## Test plan
- [x] Added tests in `test/bundler/bundler_compile_autoload.test.ts`
- [x] Verified standalone executables work correctly with runtime config
files that differ from compile-time configs
- [x] Verified the new CLI flags are properly parsed and applied
- [x] Verified the JS API options work correctly
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
### What does this PR do?
Adds `"configVersion"` to bun.lock(b). The version will be used to keep
default settings the same if they would be breaking across bun versions.
fixes ENG-21389
fixes ENG-21388
### How did you verify your code works?
TODO:
- [ ] new project
- [ ] existing project without configVersion
- [ ] existing project with configVersion
- [ ] same as above but with bun.lockb
- [ ] configVersion@0 defaults to hoisted linker
- [ ] new projects use isolated linker
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
### What does this PR do?
### How did you verify your code works?
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Claude Bot <claude-bot@bun.sh>
## 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>
### What does this PR do?
This branch:
> Ran 1600 tests across 46 files. [63.24s]
Main:
> Ran 1600 tests across 46 files. [137.05s]
This makes the bundler tests run about 60 seconds faster
### How did you verify your code works?
## Summary
- Fixes incorrect banner positioning when using `--banner` with
`--format=cjs` and `--target=bun`
- Ensures Bun-specific comments (`// @bun @bun-cjs`) appear before user
banner content
- Properly extracts and positions hashbangs from banner content
## Problem
When using `--banner` with `--format=cjs --target=bun`, the banner was
incorrectly placed before the `// @bun @bun-cjs` comment and CJS wrapper
function, breaking the module format that Bun expects.
## Solution
Implemented proper ordering:
1. **Hashbang** (from source file or extracted from banner if it starts
with `#!`)
2. **@bun comments** (e.g., `// @bun`, `// @bun @bun-cjs`, `// @bun
@bytecode`)
3. **CJS wrapper** `(function(exports, require, module, __filename,
__dirname) {`
4. **Banner content** (excluding any extracted hashbang)
## Test plan
- [x] Added comprehensive tests for banner positioning with CJS/ESM and
Bun target
- [x] Tests cover hashbang extraction from banners
- [x] Tests verify proper ordering with bytecode generation
- [x] All existing tests pass
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Removes unused function and class expression names when
`--minify-syntax` is enabled during bundling
- Adds `--keep-names` flag to preserve original names when minifying
- Matches esbuild's minification behavior
## Problem
When minifying with `--minify-syntax`, Bun was keeping function and
class expression names even when they were never referenced, resulting
in larger bundle sizes compared to esbuild.
**Before:**
```js
export var AB = function A() { };
// Bun output: var AB = function A() {};
// esbuild output: var AB = function() {};
```
## Solution
This PR adds logic to remove unused function and class expression names
during minification, matching esbuild's behavior. Names are only removed
when:
- `--minify-syntax` is enabled
- Bundling is enabled (not transform-only mode)
- The scope doesn't contain direct eval (which could reference the name
dynamically)
- The symbol's usage count is 0
Additionally, a `--keep-names` flag has been added to preserve original
names when desired (useful for debugging or runtime reflection).
## Testing
- Updated existing test in `bundler_minify.test.ts`
- All transpiler tests pass
- Manually verified output matches esbuild for various cases
## Examples
```bash
# Without --keep-names (names removed)
bun build --minify-syntax input.js
# var AB = function() {}
# With --keep-names (names preserved)
bun build --minify-syntax --keep-names input.js
# var AB = function A() {}
```
🤖 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>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
## Summary
Implements the `jsxSideEffects` option to control whether JSX elements
are marked as pure for dead code elimination, matching esbuild's
behavior from their TestJSXSideEffects test case.
## Features Added
- **tsconfig.json support**: `{"compilerOptions": {"jsxSideEffects":
true}}`
- **CLI flag support**: `--jsx-side-effects`
- **Dual runtime support**: Works with both classic
(`React.createElement`) and automatic (`jsx`/`jsxs`) JSX runtimes
- **Production/Development modes**: Works in both production and
development environments
- **Backward compatible**: Default value is `false` (maintains existing
behavior)
## Behavior
- **Default (`jsxSideEffects: false`)**: JSX elements marked with `/*
@__PURE__ */` comments (can be eliminated by bundlers)
- **When `jsxSideEffects: true`**: JSX elements NOT marked as pure
(always preserved)
## Example Usage
### tsconfig.json
```json
{
"compilerOptions": {
"jsxSideEffects": true
}
}
```
### CLI
```bash
bun build --jsx-side-effects
```
### Output Comparison
```javascript
// Input: console.log(<div>test</div>);
// Default (jsxSideEffects: false):
console.log(/* @__PURE__ */ React.createElement("div", null, "test"));
// With jsxSideEffects: true:
console.log(React.createElement("div", null, "test"));
```
## Implementation Details
- Added `side_effects: bool = false` field to `JSX.Pragma` struct
- Updated tsconfig.json parser to handle `jsxSideEffects` option
- Added CLI argument parsing for `--jsx-side-effects` flag
- Modified JSX element visiting logic to respect the `side_effects`
setting
- Updated API schema with proper encode/decode support
- Enhanced test framework to support the new JSX option
## Comprehensive Test Coverage (12 Tests)
### Core Functionality (4 tests)
- ✅ Classic JSX runtime with default behavior (includes `/* @__PURE__
*/`)
- ✅ Classic JSX runtime with `side_effects: true` (no `/* @__PURE__ */`)
- ✅ Automatic JSX runtime with default behavior (includes `/* @__PURE__
*/`)
- ✅ Automatic JSX runtime with `side_effects: true` (no `/* @__PURE__
*/`)
### Production Mode (4 tests)
- ✅ Classic JSX runtime in production with default behavior
- ✅ Classic JSX runtime in production with `side_effects: true`
- ✅ Automatic JSX runtime in production with default behavior
- ✅ Automatic JSX runtime in production with `side_effects: true`
### tsconfig.json Integration (4 tests)
- ✅ Default tsconfig.json behavior (automatic runtime, includes `/*
@__PURE__ */`)
- ✅ tsconfig.json with `jsxSideEffects: true` (automatic runtime, no `/*
@__PURE__ */`)
- ✅ tsconfig.json with `jsx: "react"` and `jsxSideEffects: true`
(classic runtime)
- ✅ tsconfig.json with `jsx: "react-jsx"` and `jsxSideEffects: true`
(automatic runtime)
### Snapshot Testing
All tests include inline snapshots demonstrating the exact output
differences, providing clear documentation of the expected behavior.
### Existing Compatibility
- ✅ All existing JSX tests continue to pass
- ✅ Cross-platform Zig compilation succeeds
## Closes
Fixes#22295🤖 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>
### What does this PR do?
- Implements .onEnd
Fixes#22061
Once #22144 is merged, this also fixes:
Fixes#9862Fixes#20806
### How did you verify your code works?
Tests
---
TODO in a followup (#22144)
> ~~Make all entrypoints be called in onResolve~~
> ~~Fixes # 9862~~
> ~~Fixes # 20806~~
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
in the name
### How did you verify your code works?
tests, but using ci to see if anything else broke
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
## Summary
This PR adds a new `--compile-argv` option to `bun build --compile` that
allows developers to embed runtime arguments into standalone
executables. The specified arguments are stored in the executable
metadata during compilation and provide **dual functionality**:
1. **🔧 Actually processed by Bun runtime** (like passing them on command
line)
2. **📊 Available in `process.execArgv`** (for application inspection)
This means flags like `--user-agent`, `--smol`, `--max-memory` will
actually take effect AND be visible to your application!
## Motivation & Use Cases
### 1. **Global User Agent for Web Scraping**
Perfect for @thdxr's opencode use case - the user agent actually gets
applied:
```bash
# Compile with custom user agent that ACTUALLY works
bun build --compile --compile-argv="--user-agent='OpenCode/1.0'" ./scraper.ts --outfile=opencode
# The user agent is applied by Bun runtime AND visible in execArgv
./opencode # All HTTP requests use the custom user agent!
```
### 2. **Memory-Optimized Builds**
Create builds with actual runtime memory optimizations:
```bash
# Compile with memory optimization that ACTUALLY takes effect
bun build --compile --compile-argv="--smol --max-memory=512mb" ./app.ts --outfile=app-optimized
# Bun runtime actually runs in smol mode with memory limit
```
### 3. **Performance & Debug Builds**
Different builds with different runtime characteristics:
```bash
# Production: optimized for memory
bun build --compile --compile-argv="--smol --gc-frequency=high" ./app.ts --outfile=app-prod
# Debug: with inspector enabled
bun build --compile --compile-argv="--inspect=0.0.0.0:9229" ./app.ts --outfile=app-debug
```
### 4. **Security & Network Configuration**
Embed security settings that actually apply:
```bash
# TLS and network settings that work
bun build --compile --compile-argv="--tls-min-version=1.3 --dns-timeout=5000" ./secure-app.ts
```
## How It Works
### Dual Processing Architecture
The implementation provides both behaviors:
```bash
# Compiled with: --compile-argv="--smol --user-agent=Bot/1.0"
./my-app --config=prod.json
```
**What happens:**
1. **🔧 Runtime Processing**: Bun processes `--smol` and
`--user-agent=Bot/1.0` as if passed on command line
2. **📊 Application Access**: Your app can inspect these via
`process.execArgv`
```javascript
// In your compiled application:
// 1. The flags actually took effect:
// - Bun is running in smol mode (--smol processed)
// - All HTTP requests use Bot/1.0 user agent (--user-agent processed)
// 2. You can also inspect what flags were used:
console.log(process.execArgv); // ["--smol", "--user-agent=Bot/1.0"]
console.log(process.argv); // ["./my-app", "--config=prod.json"]
// 3. Your application logic can adapt:
if (process.execArgv.includes("--smol")) {
console.log("Running in memory-optimized mode");
}
```
### Implementation Details
1. **Build Time**: Arguments stored in executable metadata
2. **Runtime Startup**:
- Arguments prepended to actual argv processing (so Bun processes them)
- Arguments also populate `process.execArgv` (so app can inspect them)
3. **Result**: Flags work as if passed on command line + visible to
application
## Example Usage
```bash
# User agent that actually works
bun build --compile --compile-argv="--user-agent='MyBot/1.0'" ./scraper.ts --outfile=scraper
# Memory optimization that actually applies
bun build --compile --compile-argv="--smol --max-memory=256mb" ./microservice.ts --outfile=micro
# Debug build with working inspector
bun build --compile --compile-argv="--inspect=127.0.0.1:9229" ./app.ts --outfile=app-debug
# Multiple working flags
bun build --compile --compile-argv="--smol --user-agent=Bot/1.0 --tls-min-version=1.3" ./secure-scraper.ts
```
## Runtime Verification
```javascript
// Check what runtime flags are active
const hasSmol = process.execArgv.includes("--smol");
const userAgent = process.execArgv.find(arg => arg.startsWith("--user-agent="))?.split("=")[1];
const maxMemory = process.execArgv.find(arg => arg.startsWith("--max-memory="))?.split("=")[1];
console.log("Memory optimized:", hasSmol);
console.log("User agent:", userAgent);
console.log("Memory limit:", maxMemory);
// These flags also actually took effect in the runtime!
```
## Changes Made
### Core Implementation
- **Arguments.zig**: Added `--compile-argv <STR>` flag with validation
- **StandaloneModuleGraph.zig**: Serialization/deserialization for
`compile_argv`
- **build_command.zig**: Pass `compile_argv` to module graph
- **cli.zig**: **Prepend arguments to actual argv processing** (so Bun
processes them)
- **node_process.zig**: **Populate `process.execArgv`** from stored
arguments
- **bun.zig**: Made `appendOptionsEnv()` public for reuse
### Testing
- **expectBundled.ts**: Added `compileArgv` test support
- **compile-argv.test.ts**: Tests verifying dual behavior
## Behavior
### Complete Dual Functionality
```javascript
// With --compile-argv="--smol --user-agent=TestBot/1.0":
// ✅ Runtime flags actually processed by Bun:
// - Memory usage optimized (--smol effect)
// - HTTP requests use TestBot/1.0 user agent (--user-agent effect)
// ✅ Flags visible to application:
process.execArgv // ["--smol", "--user-agent=TestBot/1.0"]
process.argv // ["./app", ...script-args] (unchanged)
```
## Backward Compatibility
- ✅ Purely additive feature - no breaking changes
- ✅ Optional flag - existing behavior unchanged when not used
- ✅ No impact on non-compile builds
## Perfect for @thdxr's Use Case!
```bash
# Compile opencode with working user agent
bun build --compile --compile-argv="--user-agent='OpenCode/1.0'" ./opencode.ts --outfile=opencode
# Results in:
# 1. All HTTP requests actually use OpenCode/1.0 user agent ✨
# 2. process.execArgv contains ["--user-agent=OpenCode/1.0"] for inspection ✨
```
The user agent will actually work in all HTTP requests made by the
compiled executable, not just be visible as metadata!
🚀 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
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>
Co-authored-by: Claude <claude@anthropic.ai>