You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
7ef33d Codemod: Fix glob pattern handling on Windows
Normalize backslashes to forward slashes in glob patterns before passing
them to tinyglobby. On Windows, path.join() produces backslash-separated
paths, but glob libraries require forward slashes.
7ef33d Codemod: Fix glob pattern handling on Windows
Normalize backslashes to forward slashes in glob patterns before passing
them to tinyglobby. On Windows, path.join() produces backslash-separated
paths, but glob libraries require forward slashes.
7ef33d Codemod: Fix glob pattern handling on Windows
Normalize backslashes to forward slashes in glob patterns before passing
them to tinyglobby. On Windows, path.join() produces backslash-separated
paths, but glob libraries require forward slashes.
9d68ec require --compile for ESM bytecode (#26624)
Summary
Add validation to require --compile when using ESM bytecode
Update documentation to clarify ESM bytecode requirements
Why
ESM module resolution is two-phase: (1) analyze imports/exports, (2)
evaluate. Without --compile, there's no module_info embedded, so JSC
must still parse the file for module analysis even with bytecode -
causing a double-parse deopt.
Changes
CLI: Error when --bytecode --format=esm is used without --compile
JS API: Error when bytecode: true, format: 'esm' is used without compile: true
Docs: Update bytecode.mdx, executables.mdx, index.mdx to clarify
requirements
Types: Update JSDoc for bytecode option in bun.d.ts
Test plan
# Should error
bun build ./test.js --bytecode --format=esm --outdir=./out
# error: ESM bytecode requires --compile. Use --format=cjs for bytecode without --compile.# Should work
bun build ./test.js --bytecode --format=esm --compile --outfile=./mytest
bun build ./test.js --bytecode --format=cjs --outdir=./out
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Adds --cpu-prof-interval to configure the CPU profiler sampling
interval in microseconds (default: 1000), matching Node.js's --cpu-prof-interval flag.
bun --cpu-prof --cpu-prof-interval 500 index.js
Parsed as u32, truncated to c_int when passed to JSC's SamplingProfiler::setTimingInterval
Invalid values silently fall back to the default (1000μs)
Warns if used without --cpu-prof or --cpu-prof-md
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
56b5be fix(shell): prevent double-free during GC finalization (#26626)
Summary
Fixes #26625
This fixes a segmentation fault that occurred on Windows x64 when the GC
finalizer tried to free shell interpreter resources that were already
partially freed during normal shell completion.
Added explicit cleanup_state enum to track resource ownership state
needs_full_cleanup: Nothing cleaned up yet, finalizer must clean
everything
runtime_cleaned: finish() already cleaned IO/shell, finalizer
skips those
Early return in #derefRootShellAndIOIfNeeded() when already cleaned
Explicit state-based cleanup in deinitFromFinalizer()
The vulnerability existed on all platforms but was most reliably
triggered on Windows with high GC pressure (many concurrent shell
commands).
Test plan
Build passes (bun bd)
New regression test added (test/regression/issue/26625.test.ts)
Existing shell tests pass (same 4 pre-existing failures, no new
failures)
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
6c119d Simplify bun run build:local to auto-build JSC (#26645)
Summary
bun run build:local now handles everything: configuring JSC,
building JSC, and building Bun in a single command on all platforms
(macOS, Linux, Windows). Previously required manually running bun run jsc:build:debug, deleting a duplicate InspectorProtocolObjects.h
header, and then running the Bun build separately.
Incremental JSC rebuilds: JSC is built via add_custom_target that
delegates to JSC's inner Ninja, which tracks WebKit source file changes
and only rebuilds what changed. ninja -Cbuild/debug-local also works
after the first build.
Cross-platform support:
macOS: Uses system ICU automatically
Linux: Uses system ICU via find_package instead of requiring bundled
static libs
Windows: Builds ICU from source automatically (only when libs don't
already exist), sets up static CRT and ICU naming conventions
Changes
cmake/tools/SetupWebKit.cmake: Replace the old WEBKIT_LOCAL block
(which just set include paths and assumed JSC was pre-built) with full
JSC configure + build integration for all platforms
cmake/targets/BuildBun.cmake: Add jsc as a build dependency, use
system ICU on Linux for local builds, handle bmalloc linking for local
builds
CONTRIBUTING.md / docs/project/contributing.mdx: Simplify "Building
WebKit locally" docs from ~15 lines of manual steps to 3 lines
a14a89 fix(proxy): respect NO_PROXY for explicit proxy options in fetch and ws (#26608)
What does this PR do?
Extract NO_PROXY checking logic from getHttpProxyFor into a reusable
isNoProxy method on the env Loader. This allows both fetch() and
WebSocket to check NO_PROXY even when a proxy is explicitly provided via
the proxy option (not just via http_proxy env var).
Changes:
env_loader.zig: Extract isNoProxy() from getHttpProxyFor()
FetchTasklet.zig: Check isNoProxy() before using explicit proxy
WebSocket.cpp: Check Bun__isNoProxy() before using explicit proxy
virtual_machine_exports.zig: Export Bun__isNoProxy for C++ access
Add NO_PROXY tests for both fetch and WebSocket proxy paths
3feea9 ci: add QEMU JIT stress tests when WebKit is updated (#26589)
Summary
Add a CI step that runs JSC JIT stress tests under QEMU when SetupWebKit.cmake is modified. This complements #26571 (basic baseline
CPU verification) by also testing JIT-generated code.
Motivation
PR #26571 added QEMU-based verification that catches illegal
instructions in:
Startup code
Static initialization
Basic interpreter execution
However, JIT compilers (DFG, FTL, Wasm BBQ/OMG) generate code at runtime
that could emit AVX or LSE instructions even if the compiled binary
doesn't. The JSC stress tests from #26380 exercise all JIT tiers through
hot loops that trigger tier-up.
How it works
Detects if cmake/tools/SetupWebKit.cmake is modified in the PR
If WebKit changes are detected, runs verify-jit-stress-qemu.sh
after the build
Executes all 78 JIT stress test fixtures under QEMU with restricted
CPU features:
x64: qemu-x86_64 -cpu Nehalem (SSE4.2, no AVX)
aarch64: qemu-aarch64 -cpu cortex-a53 (ARMv8.0-A, no LSE)
Any SIGILL from JIT-generated code fails the build
Platforms tested
Target
CPU Model
What it catches
linux-x64-baseline
Nehalem
JIT emitting AVX/AVX2/AVX512
linux-x64-musl-baseline
Nehalem
JIT emitting AVX/AVX2/AVX512
linux-aarch64
Cortex-A53
JIT emitting LSE atomics, SVE
linux-aarch64-musl
Cortex-A53
JIT emitting LSE atomics, SVE
Timeout
The step has a 30-minute timeout since QEMU emulation is ~10-50x slower
than native. This only runs on WebKit update PRs, so it won't affect
most CI runs.
Refs
#26380 - Added JSC JIT stress tests
#26571 - Added basic QEMU baseline verification
bb4d5b feat(cli/run): add --parallel and --sequential for running multiple scripts with workspace support (#26551)
Summary
Adds bun run --parallel and bun run --sequential — new flags for
running multiple package.json scripts concurrently or sequentially with
Foreman-style prefixed output. Includes full --filter/--workspaces
integration for running scripts across workspace packages.
Usage
# Run "build" and "test" concurrently from the current package.json
bun run --parallel build test# Run "build" and "test" sequentially with prefixed output
bun run --sequential build test# Glob-matched script names
bun run --parallel "build:*"# Run "build" in all workspace packages concurrently
bun run --parallel --filter '*' build
# Run "build" in all workspace packages sequentially
bun run --sequential --workspaces build
# Glob-matched scripts across all packages
bun run --parallel --filter '*'"build:*"# Multiple scripts across all packages
bun run --parallel --filter '*' build lint test# Continue running even if one package fails
bun run --parallel --no-exit-on-error --filter '*'test# Skip packages missing the script
bun run --parallel --workspaces --if-present build
How it works
Output format
Each script's stdout/stderr is prefixed with a colored, padded label:
Without --filter/--workspaces: labels are just the script name
→ build | output
With --filter/--workspaces: labels are package:script → pkg-a:build | output
Fallback: if a package.json has no name field, the relative path
from the workspace root is used (e.g., packages/my-pkg:build)
Execution model
--parallel: all scripts start immediately, output is interleaved
with prefixes
--sequential: scripts run one at a time in order, each waiting
for the previous to finish
Pre/post scripts (prebuild/postbuild) are grouped with their
main script and run in dependency order within each group
By default, a failure kills all remaining scripts. --no-exit-on-error lets all scripts finish.
Workspace integration
The workspace branch in multi_run.zig uses a two-pass approach for
deterministic ordering:
Collect: iterate workspace packages using FilterArg.PackageFilterIterator (same infrastructure as filter_run.zig), filtering with FilterArg.FilterSet, collecting
matched packages with their scripts, PATH, and cwd.
Sort: sort matched packages by name (tiebreak by directory path)
for deterministic ordering — filesystem iteration order from the glob
walker is nondeterministic.
Build configs: for each sorted package, expand script names
(including globs like build:*) against that package's scripts map,
creating ScriptConfig entries with pkg:script labels and per-package
cwd/PATH.
Behavioral consistency with filter_run.zig
Behavior
filter_run.zig
multi_run.zig (this PR)
--workspaces skips root package
Yes
Yes
--workspaces errors on missing script
Yes
Yes
--if-present silently skips missing
Yes
Yes
--filter without --workspaces includes root
Yes (if matches)
Yes (if matches)
Pre/post script chains
Per-package
Per-package
Per-package cwd
Yes
Yes
Per-package PATH (node_modules/.bin)
Yes
Yes
Key implementation details
Each workspace package script runs in its own package directory with
its own node_modules/.bin PATH
dirpath from the glob walker is duped to avoid use-after-free when
the iterator's arena is freed between patterns
addScriptConfigs takes an optional label_prefix parameter — null
for single-package mode, package name for workspace mode
MultiRunProcessHandle is registered in the ProcessExitHandler
tagged pointer union in process.zig
All 118 tests pass with debug build (bun bd test test/cli/run/multi-run.test.ts). The 16 new workspace tests all fail
with system bun (USE_SYSTEM_BUN=1), confirming they test new
functionality.
Workspace integration tests (16 tests)
--parallel --filter='*' runs script in all packages
--parallel --filter='pkg-a' runs only in matching package
--parallel --workspaces matches all workspace packages
--parallel --filter='*' with glob expands per-package scripts
--sequential --filter='*' runs in sequence (deterministic order)
Workspace + failure aborts other scripts
Workspace + --no-exit-on-error lets all finish
--workspaces skips root package
Each workspace script runs in its own package directory (cwd
verification)
Multiple script names across workspaces (build + test)
Pre/post scripts work per workspace package
--filter skips packages without the script (no error)
--workspaces errors when a package is missing the script
Fixes illegal instruction (SIGILL) crashes on ARMv8.0 aarch64 CPUs
(Cortex-A53, Raspberry Pi 4, AWS a1 instances).
Root cause
Upstream mimalloc force-enables MI_OPT_ARCH on arm64, which adds -march=armv8.1-a and emits LSE atomic instructions (casa, swpa, ldaddl). These are not available on ARMv8.0 CPUs.
Fix
Pass MI_NO_OPT_ARCH=ON to mimalloc on aarch64 (has priority over MI_OPT_ARCH in mimalloc's CMake)
Update WebKit to autobuild-596e48e22e3a1090e5b802744a7938088b1ea860
which explicitly passes -march flags to the WebKit build
Verification
Includes QEMU-based baseline CPU verification CI steps (#26571) that
catch these regressions automatically.
baea21 ci: add QEMU-based baseline CPU verification steps (#26571)
Summary
Add CI steps that verify baseline builds don't use CPU instructions
beyond their target. Uses QEMU user-mode emulation with restricted CPU
features — any illegal instruction causes SIGILL and fails the build.
Platforms verified
Build Target
QEMU Command
What it catches
linux-x64-baseline (glibc)
qemu-x86_64 -cpu Nehalem
AVX, AVX2,
AVX512
linux-x64-musl-baseline
qemu-x86_64 -cpu Nehalem
AVX, AVX2,
AVX512
linux-aarch64 (glibc)
qemu-aarch64 -cpu cortex-a35
LSE
atomics, SVE, dotprod
linux-aarch64-musl
qemu-aarch64 -cpu cortex-a35
LSE atomics,
SVE, dotprod
How it works
Each verify step:
Downloads the built binary artifact from the build-bun step
Runs two smoke tests under QEMU with restricted CPU features:
bun --version — validates startup, linker, static init code
bun -e eval — validates JSC initialization and basic execution
Hard fails on SIGILL (exit code 132)
The verify step runs in the build group after build-bun, with a
5-minute timeout.
Known issue this will surface
mimalloc on aarch64: Built with MI_OPT_ARCH=ON which adds -march=armv8.1-a, enabling LSE atomics. This will SIGILL on
Cortex-A35/A53 CPUs. The aarch64 verify steps are expected to fail
initially, confirming the test catches real issues. Fix can be done
separately in cmake/targets/BuildMimalloc.cmake.
fc4624 fix(node:vm): propagate async context tracking flag to NodeVMGlobalObject (#26542)
When a SyntheticModule callback was wrapped in an AsyncContextFrame
on the main globalObject (where async context tracking is enabled),
evaluating it on a NodeVMGlobalObject would crash because the tracking
flag wasn't propagated.
AsyncContextFrame::call checks isAsyncContextTrackingEnabled() to
decide whether to unwrap the frame — without the flag, it takes the fast
path and tries to call the AsyncContextFrame wrapper directly, which
is not callable.
The async context data (m_asyncContextData) was already shared between
parent and NodeVMGlobalObject, but the tracking flag was missing. This
adds propagation of isAsyncContextTrackingEnabled alongside the data.
Repro:react-email v5.2.5 preview server crashes when rendering a
template because it imports node:async_hooks (enabling async context
tracking) and uses node:vmSyntheticModule for module evaluation.
Renders markdown with custom JavaScript callbacks for each element. Each
callback receives children as a string and optional metadata, and
returns a string:
// Custom HTML with classesconsthtml=Bun.markdown.render("# Title\n\nHello **world**",{heading: (children,{ level })=>`<h${level} class="title">${children}</h${level}>`,paragraph: (children)=>`<p>${children}</p>`,strong: (children)=>`<b>${children}</b>`,});// ANSI terminal outputconstansi=Bun.markdown.render("# Hello\n\n**bold**",{heading: (children)=>`\x1b[1;4m${children}\x1b[0m\n`,paragraph: (children)=>children+"\n",strong: (children)=>`\x1b[1m${children}\x1b[22m`,});// Strip all formattingconsttext=Bun.markdown.render("# Hello **world**",{heading: (children)=>children,paragraph: (children)=>children,strong: (children)=>children,});// "Hello world"// Return null to omit elementsconstresult=Bun.markdown.render("# Title\n\n\n\nHello",{image: ()=>null,heading: (children)=>children,paragraph: (children)=>children+"\n",});// "Title\nHello\n"
Parser options can be included alongside callbacks:
Returns a React Fragment element — use it directly as a component return
value:
// Use as a componentfunctionMarkdown({ text }: {text: string}){returnBun.markdown.react(text);}// With custom componentsfunctionHeading({ children }: {children: React.ReactNode}){return<h1className="title">{children}</h1>;}constelement=Bun.markdown.react("# Hello",{h1: Heading});// Server-side renderingimport{renderToString}from"react-dom/server";consthtml=renderToString(Bun.markdown.react("# Hello **world**"));// "<h1>Hello <strong>world</strong></h1>"
React 18 and older
By default, react() uses Symbol.for('react.transitional.element') as
the $$typeof symbol, which is what React 19 expects. For React 18 and
older, pass reactVersion: 18:
bun bd test test/js/bun/md/md-spec.test.ts # 792 pass
bun bd test test/js/bun/md/md-render-api.test.ts # 114 pass
bun bd test test/js/bun/md/gfm-compat.test.ts # 58 pass
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <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>
7ebfdf fix(npm): remove shebang from placeholder scripts to fix npm i -g bun on Windows (#26517)
Summary
Removes the #!/bin/sh shebang from placeholder bin/bun.exe and bin/bunx.exe scripts in the npm package
Fixes npm i -g bun being completely broken on Windows since v1.3.7
Problem
PR #26259 added a #!/bin/sh shebang to the placeholder scripts to show
a helpful error when postinstall hasn't run. However, npm's cmd-shim
reads shebangs to generate .ps1/.cmd wrappers before postinstall
runs, and bakes the interpreter path into them. On Windows, the wrappers
referenced /bin/sh which doesn't exist, causing:
& "/bin/sh$exe" "$basedir/node_modules/bun/bin/bun.exe" $args
~~~~~~~~~~~~~
The term '/bin/sh.exe' is not recognized...
Even after postinstall successfully replaced the placeholder with the
real binary, the stale wrappers still tried to invoke /bin/sh.
Fix
Remove the shebang. Without it, cmd-shim generates a direct invocation
wrapper that works after postinstall replaces the placeholder. On Unix,
bash/zsh still execute shebang-less files as shell scripts via ENOEXEC
fallback, so the helpful error message is preserved.
Test plan
bun bd test test/regression/issue/24329.test.ts passes (2/2
tests)
7ef33d Codemod: Fix glob pattern handling on Windows
Normalize backslashes to forward slashes in glob patterns before passing
them to tinyglobby. On Windows, path.join() produces backslash-separated
paths, but glob libraries require forward slashes.
7ef33d Codemod: Fix glob pattern handling on Windows
Normalize backslashes to forward slashes in glob patterns before passing
them to tinyglobby. On Windows, path.join() produces backslash-separated
paths, but glob libraries require forward slashes.
7ef33d Codemod: Fix glob pattern handling on Windows
Normalize backslashes to forward slashes in glob patterns before passing
them to tinyglobby. On Windows, path.join() produces backslash-separated
paths, but glob libraries require forward slashes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Updated Packages