## Summary
Adds a new CLI flag `--compile-executable-path` that allows specifying a
custom Bun executable path for cross-compilation instead of downloading
from the npm registry.
## Usage
```bash
bun build --compile --target=bun-linux-x64 \
--compile-executable-path=/path/to/bun-linux-x64 app.ts
```
## Motivation
The `executablePath` option was already available in the JavaScript
`Bun.build()` API. This exposes the same functionality from the CLI.
## Changes
- Added `--compile-executable-path <STR>` CLI parameter in
`src/cli/Arguments.zig`
- Added `compile_executable_path` field to `BundlerOptions` in
`src/cli.zig`
- Wired the option through to `StandaloneModuleGraph.toExecutable()` in
`src/cli/build_command.zig`
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
- Add test that is broken before the changes in the code and fix
previous test making script in dependency takes a bit of time to be
executed. Without the `setTimeout` in the tests, due race conditions it
always success. I tried adding a test combining both tests, with
dependencies `dep0` and `larger-than-8-char`, but if the timeout is the
same it success.
- Fix for the use case added, by using the correct buffer for
`Dependency.name` otherwise it gets garbage when package name is larger
than 8 characters. This should fix#12203
### How did you verify your code works?
Undo the changes in the code to verify the new test fails and check it
again after adding the changes in the code.
## Summary
- Fix segmentation fault in `bun create` when using `--no-install` with
a template that has a `bun-create.postinstall` task starting with "bun "
- The bug was caused by unconditionally slicing `argv[2..]` which
created an empty array when `npm_client` was null
- Added check for `npm_client != null` before slicing
## Reproduction
```bash
# Create template with bun-create.postinstall
mkdir -p ~/.bun-create/test-template
echo '{"name":"test","bun-create":{"postinstall":"bun install"}}' > ~/.bun-create/test-template/package.json
# This would crash before the fix
bun create test-template /tmp/my-app --no-install
```
## Test plan
- [x] Verified the reproduction case crashes before the fix
- [x] Verified the reproduction case works after the fix
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
Fixes#13316Fixes#18275
Running `bunx cowsay ""` (or any package with an empty string argument)
on Windows caused a panic. Additionally, `bunx concurrently "command
with spaces"` was splitting quoted arguments incorrectly.
**Repro #13316:**
```bash
bunx cowsay ""
# panic(main thread): reached unreachable code
```
**Repro #18275:**
```bash
bunx concurrently "bun --version" "bun --version"
# Only runs once, arguments split incorrectly
# Expected: ["bun --version", "bun --version"]
# Actual: ["bun", "--version", "bun", "--version"]
```
## Root Cause
The bunx fast path on Windows bypasses libuv and calls `CreateProcessW`
directly to save 5-12ms. The command line building logic had two issues:
1. **Empty strings**: Not quoted at all, resulting in invalid command
line
2. **Arguments with spaces**: Not quoted, causing them to be split into
multiple arguments
## Solution
Implement Windows command-line argument quoting using libuv's proven
algorithm:
- Port of libuv's `quote_cmd_arg` function (process backwards + reverse)
- Empty strings become `""`
- Strings with spaces/tabs/quotes are wrapped in quotes
- Backslashes before quotes are properly escaped per Windows rules
**Why not use libuv directly?**
- Normal `Bun.spawn()` uses `uv_spawn()` which handles quoting
internally
- bunx fast path bypasses libuv to save 5-12ms (calls `CreateProcessW`
directly)
- libuv's `quote_cmd_arg` is a static function (not exported)
- Solution: port the algorithm to Zig
## Test Plan
- [x] Added regression test for empty strings (#13316)
- [x] Added regression test for arguments with spaces (#18275)
- [x] Verified system bun (v1.3.3) fails both tests
- [x] Verified fix passes both tests
- [x] Implementation based on battle-tested libuv algorithm
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude <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>
## Summary
- The default trusted dependencies list should only apply to packages
installed from npm
- Non-npm sources (file:, link:, git:, github:) now require explicit
trustedDependencies
- This prevents malicious packages from spoofing trusted names through
local paths or git repos
## Test plan
- [x] Added test: file: dependency named "esbuild" does NOT auto-run
postinstall scripts
- [x] Added test: file: dependency runs scripts when explicitly added to
trustedDependencies
- [x] Verified tests fail with system bun (old behavior) and pass with
new build
- [x] Build compiles successfully
🤖 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: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
## 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 [@mschwarzl's Fuzzilli Support
PR](https://github.com/oven-sh/bun/pull/23862) with the changes
necessary to be able to:
- Run it in CI
- Make no impact on `debug` and `release` mode.
### How did you verify your code works?
---------
Co-authored-by: Martin Schwarzl <mschwarzl@cloudflare.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
### What does this PR do?
This was creating `Zig::FFIFunction` when we could instead use a plain
`JSC::JSFunction`
### How did you verify your code works?
Added a test
### What does this PR do?
We must use the right number of properties or we should set it to 0
### How did you verify your code works?
Read the code to check the amount of properties + CI
## Summary
Implements `--no-env-file` CLI flag and bunfig configuration options to
disable automatic `.env` file loading at runtime and in the bundler.
## Motivation
Users may want to disable automatic `.env` file loading for:
- Production environments where env vars are managed externally
- CI/CD pipelines where .env files should be ignored
- Testing scenarios where explicit env control is needed
- Security contexts where .env files should not be trusted
## Changes
### CLI Flag
- Added `--no-env-file` flag that disables loading of default .env files
- Still respects explicit `--env-file` arguments for intentional env
loading
### Bunfig Configuration
Added support for disabling .env loading via `bunfig.toml`:
- `env = false` - disables default .env file loading
- `env = null` - disables default .env file loading
- `env.file = false` - disables default .env file loading
- `env.file = null` - disables default .env file loading
### Implementation
- Added `disable_default_env_files` field to `api.TransformOptions` with
serialization support
- Added `disable_default_env_files` field to `options.Env` struct
- Implemented `loadEnvConfig` in bunfig parser to handle env
configuration
- Wired up flag throughout runtime and bundler code paths
- Preserved package.json script runner behavior (always skips default
.env files)
## Tests
Added comprehensive test suite (`test/cli/run/no-envfile.test.ts`) with
9 tests covering:
- `--no-env-file` flag with `.env`, `.env.local`,
`.env.development.local`
- Bunfig configurations: `env = false`, `env.file = false`, `env = true`
- `--no-env-file` with `-e` eval flag
- `--no-env-file` combined with `--env-file` (explicit files still load)
- Production mode behavior
All tests pass with debug bun and fail with system bun (as expected).
## Example Usage
```bash
# Disable all default .env files
bun --no-env-file index.js
# Disable defaults but load explicit file
bun --no-env-file --env-file .env.production index.js
# Disable via bunfig.toml
cat > bunfig.toml << 'CONFIG'
env = false
CONFIG
bun index.js
```
## Files Changed
- `src/cli/Arguments.zig` - CLI flag parsing
- `src/api/schema.zig` - API schema field with encode/decode
- `src/options.zig` - Env struct field and wiring
- `src/bunfig.zig` - Config parsing with loadEnvConfig
- `src/transpiler.zig` - Runtime wiring
- `src/bun.js.zig` - Runtime wiring
- `src/cli/exec_command.zig` - Runtime wiring
- `src/cli/run_command.zig` - Preserved package.json script runner
behavior
- `test/cli/run/no-envfile.test.ts` - Comprehensive test suite
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Fixes ENG-21481
Updates ci_info to include more CIs. It makes it codegen the ci
detection based on the json from the ci-info package. Also it supports
setting CI=true to force ci detected.
---------
Co-authored-by: pfg <pfg@pfg.pw>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
Fixes `bun pm ls --all` crash with unresolved optional peer
dependencies.
Fixes `bun pm ls` crash with empty lockfiles.
Fixes#24502
### How did you verify your code works?
Added a test for both crashes
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
This PR introduces a new postinstall optimization system that
significantly reduces the need to run lifecycle scripts for certain
packages by intelligently handling their requirements at install time.
## Key Features
### 1. Native Binlink Optimization
When packages like `esbuild` ship platform-specific binaries as optional
dependencies, we now:
- Detect the native binlink pattern (enabled by default for `esbuild`)
- Find the matching platform-specific dependency based on target CPU/OS
- Link binaries directly from the platform-specific package (e.g.,
`@esbuild/darwin-arm64`)
- Fall back gracefully if the platform-specific package isn't found
**Result**: No postinstall scripts needed for esbuild and similar
packages.
### 2. Lifecycle Script Skipping
For packages like `sharp` that run heavy postinstall scripts:
- Skip lifecycle scripts entirely (enabled by default for `sharp`)
- Prevents downloading large binaries or compiling native code
unnecessarily
- Reduces install time and potential failures in restricted environments
## Configuration
Both features can be configured via `package.json`:
```json
{
"nativeDependencies": ["esbuild", "my-custom-package"],
"ignoreScripts": ["sharp", "another-package"]
}
```
Set to empty arrays to disable defaults:
```json
{
"nativeDependencies": [],
"ignoreScripts": []
}
```
Environment variable overrides:
- `BUN_FEATURE_FLAG_DISABLE_NATIVE_DEPENDENCY_LINKER=1` - disable native
binlink
- `BUN_FEATURE_FLAG_DISABLE_IGNORE_SCRIPTS=1` - disable script ignoring
## Implementation Details
### Core Components
- **`postinstall_optimizer.zig`**: New file containing the optimizer
logic
- `PostinstallOptimizer` enum with `native_binlink` and `ignore`
variants
- `List` type to track optimization strategies per package hash
- Defaults for `esbuild` (native binlink) and `sharp` (ignore)
- **`Bin.Linker` changes**: Extended to support separate target paths
- `target_node_modules_path`: Where to find the actual binary
- `target_package_name`: Name of the package containing the binary
- Fallback logic when native binlink optimization fails
### Modified Components
- **PackageInstaller.zig**: Checks optimizer before:
- Enqueueing lifecycle scripts
- Linking binaries (with platform-specific package resolution)
- **isolated_install/Installer.zig**: Similar checks for isolated linker
mode
- `maybeReplaceNodeModulesPath()` resolves platform-specific packages
- Retry logic without optimization on failure
- **Lockfile**: Added `postinstall_optimizer` field to persist
configuration
## Changes Included
- Updated `esbuild` from 0.21.5 to 0.25.11 (testing with latest)
- VS Code launch config updates for debugging install with new flags
- New feature flags in `env_var.zig`
## Test Plan
- [x] Existing install tests pass
- [ ] Test esbuild install without postinstall scripts running
- [ ] Test sharp install with scripts skipped
- [ ] Test custom package.json configuration
- [ ] Test fallback when platform-specific package not found
- [ ] Test feature flag overrides
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Native binlink optimization: installs platform-specific binaries when
available, with a safe retry fallback and verbose logging option.
* Per-package postinstall controls to optionally skip lifecycle scripts.
* New feature flags to disable native binlink optimization and to
disable lifecycle-script ignoring.
* **Tests**
* End-to-end tests and test packages added to validate native binlink
behavior across install scenarios and linker modes.
* **Documentation**
* Bench README and sample app migrated to a Next.js-based setup.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
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>
### What does this PR do?
fixes#23901
### How did you verify your code works?
with a test
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
Fixes a bug where `bun update --interactive` only updated `package.json`
but didn't actually install the updated packages. Users had to manually
run `bun install` afterwards.
## Root Cause
The bug was in `savePackageJson()` in
`src/cli/update_interactive_command.zig`:
1. The function wrote the updated `package.json` to disk
2. But it **didn't update the in-memory cache**
(`WorkspacePackageJSONCache`)
3. When `installWithManager()` ran, it called `getWithPath()` which
returned the **stale cached version**
4. So the installation proceeded with the old dependencies
## The Fix
Update the cache entry after writing to disk (line 116):
```zig
package_json.*.source.contents = new_package_json_source;
```
This matches the behavior in `updatePackageJSONAndInstall.zig` line 269.
## Test Plan
Added comprehensive regression tests in
`test/cli/update_interactive_install.test.ts`:
- ✅ Verifies that `package.json` is updated
- ✅ Verifies that `node_modules` is updated (this was failing before the
fix)
- ✅ Tests both normal update and `--latest` flag
- ✅ Compares installed version to confirm packages were actually
installed
Run tests with:
```bash
bun bd test test/cli/update_interactive_install.test.ts
```
🤖 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?
calling `loadConfigPath` could allow loading bunfig more than once.
### How did you verify your code works?
manually
---------
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
## Summary
This PR makes `bun list` an alias for `bun pm ls`, allowing users to
list their dependency tree with a shorter command.
## Changes
- Updated `src/cli.zig` to route `list` command to
`PackageManagerCommand` instead of `ReservedCommand`
- Modified `src/cli/package_manager_command.zig` to detect when `bun
list` is invoked directly and treat it as `ls`
- Updated help text in `bun pm --help` to show both `bun list` and `bun
pm ls` as valid options
## Implementation Details
The implementation follows the same pattern used for `bun whoami`, which
is also a direct alias to a pm subcommand. When `bun list` is detected,
it's internally converted to the `ls` subcommand.
## Testing
Tested locally:
- ✅ `bun list` shows the dependency tree
- ✅ `bun list --all` works correctly with the `--all` flag
- ✅ `bun pm ls` continues to work (backward compatible)
## Test Output
```bash
$ bun list
/tmp/test-bun-list node_modules (3)
└── react@18.3.1
$ bun list --all
/tmp/test-bun-list node_modules
├── js-tokens@4.0.0
├── loose-envify@1.4.0
└── react@18.3.1
$ bun pm ls
/tmp/test-bun-list node_modules (3)
└── react@18.3.1
```
🤖 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>
## Summary
Implements the `--cpu-prof` CLI flag for Bun to profile CPU usage and
save results in Chrome CPU Profiler JSON format, compatible with Chrome
DevTools and VSCode.
## Implementation Details
- Uses JSC's `SamplingProfiler` to collect CPU samples during execution
- Converts samples to Chrome CPU Profiler JSON format on exit
- Supports `--cpu-prof-name` to customize output filename
- Supports `--cpu-prof-dir` to specify output directory
- Default filename: `CPU.YYYYMMDD.HHMMSS.PID.0.001.cpuprofile`
## Key Features
✅ **Chrome DevTools Compatible** - 100% compatible with Node.js CPU
profile format
✅ **Absolute Timestamps** - Uses wall clock time (microseconds since
epoch)
✅ **1ms Sampling** - Matches Node.js sampling frequency for comparable
granularity
✅ **Thread-Safe** - Properly shuts down background sampling thread
before processing
✅ **Memory-Safe** - Uses HeapIterationScope and DeferGC for safe heap
access
✅ **Cross-Platform** - Compiles on Windows, macOS, and Linux with proper
path handling
## Technical Challenges Solved
1. **Heap Corruption** - Fixed by calling `profiler->shutdown()` before
processing traces
2. **Memory Safety** - Added `HeapIterationScope` and `DeferGC` when
accessing JSCells
3. **Timestamp Accuracy** - Explicitly start stopwatch and convert to
absolute wall clock time
4. **Path Handling** - Used `bun.path.joinAbsStringBufZ` with proper cwd
resolution
5. **Windows Support** - UTF-16 path conversion for Windows
compatibility
6. **Atomic Writes** - Used `bun.sys.File.writeFile` with ENOENT retry
## Testing
All tests pass (4/4):
- ✅ Generates profile with default name
- ✅ `--cpu-prof-name` sets custom filename
- ✅ `--cpu-prof-dir` sets custom directory
- ✅ Profile captures function names
Verified format compatibility:
- JSON structure matches Node.js exactly
- All samples reference valid nodes
- Timestamps use absolute microseconds since epoch
- Cross-platform compilation verified with `bun run zig:check-all`
## Example Usage
```bash
# Basic usage
bun --cpu-prof script.js
# Custom filename
bun --cpu-prof --cpu-prof-name my-profile.cpuprofile script.js
# Custom directory
bun --cpu-prof --cpu-prof-dir ./profiles script.js
```
Output can be opened in Chrome DevTools (Performance → Load Profile) or
VSCode's CPU profiling viewer.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Fixed a bug in the Windows bunx fast path code where UTF-8 byte length
was incorrectly used instead of UTF-16 code unit length when calculating
buffer offsets.
## Details
In `run_command.zig:1565`, the code was using `target_name.len` (UTF-8
byte length) instead of `encoded.len` (UTF-16 code unit length) when
calculating the total path length. This caused an index out of bounds
panic when package names contained multi-byte UTF-8 characters.
**Example scenario:**
- Package name contains character "中" (U+4E2D)
- UTF-8: 3 bytes (0xE4 0xB8 0xAD) → `target_name.len` counts as 3
- UTF-16: 1 code unit (0x4E2D) → `encoded.len` counts as 1
- Using the wrong length led to: `panic: index out of bounds: index 62,
len 60`
## Changes
- Changed line 1565 from `target_name.len` to `encoded.len`
## Test plan
- [x] Build compiles successfully
- [x] Code review confirms the fix addresses the root cause
- [ ] Windows-specific testing (if available)
Fixes the panic reported in Sentry/crash reports.
🤖 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>
### What does this PR do?
Adds support for `publicHoistPattern` in `bunfig.toml` and
`public-hoist-pattern` from `.npmrc`. This setting allows you to select
transitive packages to hoist to the root node_modules making them
available for all workspace packages.
```toml
[install]
# can be a string
publicHoistPattern = "@types*"
# or an array
publicHoistPattern = [ "@types*", "*eslint*" ]
```
`publicHoistPattern` only affects the isolated linker.
---
Adds `hoistPattern`. `hoistPattern` is the same as `publicHoistPattern`,
but applies to the `node_modules/.bun/node_modules` directory instead of
the root node_modules. Also the default value of `hoistPattern` is `*`
(everything is hoisted to `node_modules/.bun/node_modules` by default).
---
Fixes a determinism issue constructing the
`node_modules/.bun/node_modules` directory.
---
closes#23481closes#6160closes#23548
### How did you verify your code works?
Added tests for
- [x] only include patterns
- [x] only exclude patterns
- [x] mix of include and exclude
- [x] errors for unexpected expression types
- [x] excluding direct dependency (should still include)
- [x] match all with `*`
- [x] string and array expression types
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Fixes#19652
## Summary
Fixes a crash that occurred when using the `--production` flag with `bun
build`, particularly on Windows where assertions are enabled in release
builds.
## Root Cause
The crash occurred because an assertion for `jsx.development` was
running **before** `jsx.development` was properly configured. The
problematic sequence was:
1. Set `NODE_ENV=production` in env map
2. Call `configureDefines()` which reads `NODE_ENV` and calls
`setProduction(true)`, setting `jsx.development=false`
3. ❌ **Assert `jsx.development` is false** (assertion fired here, before
line 203 below)
4. Set `jsx.development = !production` on line 203 (too late)
## Changes
This PR reorders the code to move the assertion **after**
`jsx.development` is properly set:
1. Set both `BUN_ENV` and `NODE_ENV` to `"production"` in env map
2. Call `configureDefines()`
3. Set `jsx.development = !production` (now happens first)
4. ✅ **Assert `jsx.development` is false** (now runs after it's set)
Also adds `BUN_ENV=production` to match the behavior of setting
`NODE_ENV`.
## Test Plan
Added regression test in `test/regression/issue/19652.test.ts` that
verifies `bun build --production` doesn't crash.
The test:
- ✅ Passes on this branch
- ❌ Would fail on main (assertion failure)
🤖 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: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
## Summary
Adds a new `--only-failures` flag to `bun test` that only displays test
failures, similar to `--dots` but without printing dots for each test.
## Motivation
When running large test suites or in CI environments, users often only
care about test failures. The existing `--dots` reporter reduces
verbosity by showing dots, but still requires visual scanning to find
failures. The `--only-failures` flag provides a cleaner output by
completely suppressing passing tests.
## Changes
- Added `--only-failures` CLI flag in `Arguments.zig`
- Added `only_failures` boolean to the test reporters struct in
`cli.zig`
- Updated test output logic in `test_command.zig` to skip non-failures
when flag is set
- Updated `jest.zig` and `bun_test.zig` to handle the new flag
- Added comprehensive tests in `only-failures.test.ts`
## Usage
```bash
bun test --only-failures
```
Example output (only shows failures):
```
test/example.test.ts:
(fail) failing test
error: expect(received).toBe(expected)
Expected: 3
Received: 2
5 pass
1 skip
2 fail
Ran 8 tests across 1 file.
```
## Test Plan
- Verified `--only-failures` flag only shows failing tests
- Verified normal test output still works without the flag
- Verified `--dots` reporter still works correctly
- Added regression tests with snapshot comparisons
🤖 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: pfg <pfg@pfg.pw>
Fixes#23569
## Summary
HTML imports require bundling to work correctly, as they need to process
and transform linked assets (JS/CSS). When `--no-bundle` is used, no
bundling or transformation happens, which causes a crash.
This change adds validation to detect HTML entrypoints when
`--no-bundle` is used and provides a clear error message explaining that
"HTML imports are only supported when bundling".
## Changes
- Added validation in `src/cli/build_command.zig` to check for HTML
entrypoints when `--no-bundle` flag is used
- Shows clear error message: "HTML imports are only supported when
bundling"
- Added regression tests in `test/regression/issue/23569.test.ts`
## Test Plan
### Before
```bash
$ bun build ./index.html --no-bundle
# Crashes without helpful error
```
### After
```bash
$ bun build ./index.html --no-bundle
error: HTML imports are only supported when bundling
```
### Tests
- ✅ Test with `--no-bundle` flag errors correctly
- ✅ Test with `--no-bundle --outdir` errors correctly
- ✅ Test without `--no-bundle` works normally
- ✅ All 3 regression tests pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
### What does this PR do?
Fixes#23521
### How did you verify your code works?
Added 3 previously failing tests for `"bin"`, `"directories.bin"`, and
deduplicating entry in both `"bin.directories"` and `"files"`
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
This PR adds support for the `--pass-with-no-tests` CLI flag to the test
runner, addressing issue #20814.
With the latest v1.2.8 release, the test runner now fails when no tests
match a filter. While this is useful for agentic coding workflows, there
are legitimate cases where the previous behavior is preferred, such as
in monorepos where a standard test file pattern is used as a filter but
not all packages contain tests.
This flag makes the test runner behave like Jest and Vitest, exiting
with code 0 when no tests are found.
## Changes
- Added `--pass-with-no-tests` flag to CLI arguments in
`src/cli/Arguments.zig`
- Added `pass_with_no_tests` field to `TestOptions` struct in
`src/cli.zig`
- Updated test runner logic in `src/cli/test_command.zig` to respect the
flag
- Added comprehensive tests in
`test/cli/test/pass-with-no-tests.test.ts`
## Test Plan
All new tests pass:
- ✅ `--pass-with-no-tests` exits with 0 when no test files found
- ✅ `--pass-with-no-tests` exits with 0 when filters match no tests
- ✅ Without flag, still exits with 1 when no tests found (preserves
existing behavior)
- ✅ `--pass-with-no-tests` still fails when actual tests fail
Closes#20814🤖 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: pfg <pfg@pfg.pw>
## Summary
Fixes a race condition on macOS where editing the entrypoint with vim's
atomic save causes "Module not found" errors during hot reload.
## Root Cause
On macOS, kqueue watches file descriptors/inodes, not paths. Vim's
atomic save sequence:
1. Rename `a.js` to `a.js~` → kqueue reports `NOTE_RENAME` on watched fd
2. Hot reloader immediately triggers reload
3. New file hasn't been created yet → `ENOENT` error
4. Vim re-creates `a.js`, and writes file contents into it
5. Directory gets `NOTE_WRITE` but file already removed from watchlist
```
rename("a.js", "a.js~") = 0
openat(AT_FDCWD, "a.js", O_WRONLY|O_CREAT, 0664) = 3
ftruncate(3, 0) = 0
write(3, "foobar\n", 7) = 7
close(3) = 0
```
This is macOS-specific because:
- **kqueue**: watches inodes, fd becomes stale when inode deleted
- **inotify (Linux)**: watches paths, gets `IN.MOVED_TO` (not
`IN.MOVE_SELF`), so files stay in watchlist
## Solution
When the entrypoint receives `NOTE_RENAME` on macOS:
1. Set `is_waiting_for_dir_change` flag
2. Skip immediate reload
3. Wait for parent directory `NOTE_WRITE` event
4. Use `faccessat()` to verify file exists
5. Trigger reload
This only applies to the entrypoint because dependencies have buffering
time during import graph traversal.
## Test Plan
Manual testing with vim on macOS:
1. Run `bun --hot entrypoint.js`
2. Edit entrypoint with vim (`:w`)
3. Verify no "Module not found" errors
4. Verify hot reload succeeds
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: taylor.fish <contact@taylor.fish>
### What does this PR do?
### How did you verify your code works?
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
### What does this PR do?
Fixes `bun -p "process.stderr.write('Hello' +
String.fromCharCode(0xd800))"`.
Also fixes potential index out of bounds if there are many invalid
sequences.
This also affects `TextEncoder`.
### How did you verify your code works?
Added tests for edgecases
---------
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Fixes#23380 - this is a use-case for the `--only` flag that I missed
Adds back the `--only` flag. When running `bun test` on a full test
suite, without this flag it will run only that test in its file, but it
will run all other tests from other files. With this flag, it will not
run things from other files.
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: pfg <pfg@pfg.pw>