### What does this PR do?
This PR adds `Bun.YAML.stringify`. The stringifier will double quote
strings only when necessary (looks for keywords, numbers, or containing
non-printable or escaped characters). Anchors and aliases are detected
by object equality, and anchor name is chosen from property name, array
item, or the root collection.
```js
import { YAML } from "bun"
YAML.stringify(null) // null
YAML.stringify("hello YAML"); // "hello YAML"
YAML.stringify("123.456"); // "\"123.456\""
// anchors and aliases
const userInfo = { name: "bun" };
const obj = { user1: { userInfo }, user2: { userInfo } };
YAML.stringify(obj, null, 2);
// # output
// user1:
// userInfo:
// &userInfo
// name: bun
// user2:
// userInfo:
// *userInfo
// will handle cycles
const obj = {};
obj.cycle = obj;
YAML.stringify(obj, null, 2);
// # output
// &root
// cycle:
// *root
// default no space
const obj = { one: { two: "three" } };
YAML.stringify(obj);
// # output
// {one: {two: three}}
```
### How did you verify your code works?
Added tests for basic use and edgecases
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- New Features
- Added YAML.stringify to the YAML API, producing YAML from JavaScript
values with quoting, anchors, and indentation support.
- Improvements
- YAML.parse now accepts a wider range of inputs, including Buffer,
ArrayBuffer, TypedArrays, DataView, Blob/File, and SharedArrayBuffer,
with better error propagation and stack protection.
- Tests
- Extensive new tests for YAML.parse and YAML.stringify across data
types, edge cases, anchors/aliases, deep nesting, and round-trip
scenarios.
- Chores
- Added a YAML stringify benchmark script covering multiple libraries
and data shapes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
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>
## Summary
Fixes#20596
This PR resolves the "Unable to deserialize data" error when using
`structuredClone()` with nested objects containing `Blob` or `File`
objects, and ensures that `File` objects preserve their `name` property
during structured clone operations.
## Problem
### Issue 1: "Unable to deserialize data" Error
When cloning nested structures containing Blob/File objects,
`structuredClone()` would throw:
```
TypeError: Unable to deserialize data.
```
**Root Cause**: The `StructuredCloneableDeserialize::fromTagDeserialize`
function wasn't advancing the pointer (`m_ptr`) after deserializing
Blob/File objects. This caused subsequent property reads in nested
scenarios to start from the wrong position in the serialized data.
**Affected scenarios**:
- ✅ `structuredClone(blob)` - worked fine (direct cloning)
- ❌ `structuredClone({blob})` - threw error (nested cloning)
- ❌ `structuredClone([blob])` - threw error (array cloning)
- ❌ `structuredClone({data: {files: [file]}})` - threw error (complex
nesting)
### Issue 2: File Name Property Lost
Even when File cloning worked, the `name` property was not preserved:
```javascript
const file = new File(["content"], "test.txt");
const cloned = structuredClone(file);
console.log(cloned.name); // undefined (should be "test.txt")
```
**Root Cause**: The structured clone serialization only handled basic
Blob properties but didn't serialize/deserialize the File-specific
`name` property.
## Solution
### Part 1: Fix Pointer Advancement
**Modified Code Generation** (`src/codegen/generate-classes.ts`):
- Changed `fromTagDeserialize` function signature from `const uint8_t*`
to `const uint8_t*&` (pointer reference)
- Updated implementation to cast pointer correctly: `(uint8_t**)&ptr`
- Fixed both C++ extern declarations and Zig wrapper signatures
**Updated Zig Functions**:
- **Blob.zig**: Modified `onStructuredCloneDeserialize` to take `ptr:
*[*]u8` and advance it by `buffer_stream.pos`
- **BlockList.zig**: Applied same fix for consistency across all
structured clone types
### Part 2: Add File Name Preservation
**Enhanced Serialization Format**:
- Incremented serialization version from 2 to 3 to support File name
serialization
- Added File name serialization using `getNameString()` to handle all
name storage scenarios
- Added proper deserialization with `bun.String.cloneUTF8()` for UTF-8
string creation
- Maintained backwards compatibility with existing serialization
versions
## Testing
Created comprehensive test suite
(`test/js/web/structured-clone-blob-file.test.ts`) with **24 tests**
covering:
### Core Functionality
- Direct Blob/File cloning (6 tests)
- Nested Blob/File in objects and arrays (8 tests)
- Mixed Blob/File scenarios (4 tests)
### Edge Cases
- Blob/File with empty data (6 tests)
- File with empty data and empty name (2 tests)
### Regression Tests
- Original issue 20596 reproduction cases (3 tests)
**Results**: All **24/24 tests pass** (up from 5/18 before the fix)
## Key Changes
1. **src/codegen/generate-classes.ts**:
- Updated `fromTagDeserialize` signature and implementation
- Fixed C++ extern declarations for pointer references
2. **src/bun.js/webcore/Blob.zig**:
- Enhanced pointer advancement in deserialization
- Added File name serialization/deserialization
- Incremented serialization version with backwards compatibility
3. **src/bun.js/node/net/BlockList.zig**:
- Applied consistent pointer advancement fix
4. **test/js/web/structured-clone-blob-file.test.ts**:
- Comprehensive test suite covering all scenarios and edge cases
## Backwards Compatibility
- ✅ Existing structured clone functionality unchanged
- ✅ All other structured clone tests continue to pass (118/118 worker
tests pass)
- ✅ Serialization version 3 supports versions 1-2 with proper fallback
- ✅ No breaking changes to public APIs
## Performance Impact
- ✅ No performance regression in existing functionality
- ✅ Minimal overhead for File name serialization (only when
`is_jsdom_file` is true)
- ✅ Efficient pointer arithmetic for advancement
---
🤖 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>
### What does this PR do?
The async_hooks warning is mostly just noise. There's no action you can
take. And React is now using this to track the error.stack of every
single promise with a no-op if it's not in use, so let's be silent about
this by default instead of noisy.
### How did you verify your code works?
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
Originally, we attempted to avoid the "dual package hazard" right before
we enqueue a parse task, but that code gets called in a
non-deterministic order. This meant that some of your modules would use
the right variant and some of them would not.
We have to instead do that in a separate pass, after all the files are
parsed.
The thing to watch out for with this PR is how it impacts the dev
server.
### How did you verify your code works?
Unskipped tests. Plus manual.
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
## Summary
Fixes a crash with `panic: attempt to use null value` in
`html_rewriter.zig:1190` when accessing TextChunk properties after
HTMLRewriter cleanup.
The crash occurred in the `lastInTextNode` and `removed` methods when
they tried to dereference a null `text_chunk` pointer using
`this.text_chunk.?` without proper null checks.
## Root Cause
The TextChunk methods `removed()` and `lastInTextNode()` were missing
null checks that other methods like `getText()` and `remove()` already
had. When TextChunk objects are accessed after the HTMLRewriter
transformation completes and internal cleanup occurs, the `text_chunk`
pointer becomes null, causing a panic.
## Changes
- **src/bun.js/api/html_rewriter.zig**:
- Add null check to `removed()` method - returns `false` when
`text_chunk` is null
- Add null check to `lastInTextNode()` method - returns `false` when
`text_chunk` is null
- **test/regression/issue/text-chunk-null-access.test.ts**:
- Add regression test that reproduces the original crash scenario
- Test verifies that accessing TextChunk properties after cleanup
returns sensible defaults instead of crashing
## Crash Reproduction
The regression test successfully reproduces the crash:
- **Regular `bun test`**: ❌ CRASHES with `panic: attempt to use null
value`
- **With fix `bun bd test`**: ✅ PASSES
## Test Plan
- [x] Existing HTMLRewriter tests still pass
- [x] New regression test passes with the fix
- [x] New regression test crashes without the fix (confirmed on regular
bun)
- [x] Both `removed` and `lastInTextNode` now return sensible defaults
(`false`) when called on cleaned up TextChunk objects
🤖 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: Jarred Sumner <jarred@jarredsumner.com>
### What does this PR do?
SecretSchema was missing some reserved fields.
fixes#22246fixes#22190
### How did you verify your code works?
manually
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
### How did you verify your code works?
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Tests**
* Enabled multiple previously skipped bundler and esbuild test cases by
removing todo flags, increasing test suite coverage.
* Broadened cross-platform applicability by removing OS-specific gating
in certain tests, ensuring they run consistently across environments.
* Activated additional scenarios around resolve/load behavior, dead code
elimination, package.json handling, and extra edge cases.
* No impact on runtime behavior or public APIs; changes are limited to
test execution and reliability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
handle Int24 to be numbers
### How did you verify your code works?
tests
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
ebe0cdac31..e0b7c318f3
It hides it in typeInfo even in the current file, unlike private
declarations which are only hidden in other files.
This allows you to formatted print a type with private fields, but the
private fields are not shown. The alternative would be to allow
accessing private fields through `@field()` but that looked like it was
going to be more complicated (need to add an argument to
structFieldVal/structFieldPtr which are called by fieldVal/fieldPtr
which have 36 callsites)
---------
Co-authored-by: taylor.fish <contact@taylor.fish>
### 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: Ciro Spaciari <ciro.spaciari@gmail.com>
### What does this PR do?
fixes https://github.com/oven-sh/bun/issues/21945
### How did you verify your code works?
Run the code bellow and will be way harder the encounter the same
problem (I got it 1 times after 10 tries the same effect as Bun.sleep
mentioned before)
```ts
const sql = new Bun.SQL("postgres://localhost");
using conn1 = await sql.reserve();
using conn2 = await sql.reserve();
await sql`DROP TABLE IF EXISTS test1`;
await sql`CREATE TABLE IF NOT EXISTS test1 (
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
uuid UUID NOT NULL
)`;
await sql`INSERT INTO test1 (uuid) VALUES (gen_random_uuid())`;
type Row = {
id: number;
uuid: string;
};
for (let i = 0; i < 100_000; i++) {
const [original]: Array<Row> = await conn1`SELECT id, uuid FROM test1 LIMIT 1`;
const [updated]: Array<Row> =
await conn1`UPDATE test1 SET uuid = gen_random_uuid() WHERE id = ${original.id} RETURNING id, uuid`;
const [retrieved]: Array<Row> = await conn2`SELECT id, uuid FROM test1 WHERE id = ${original.id}`;
if (retrieved.uuid !== updated.uuid) {
console.log("Expected retrieved and updated to match", retrieved, updated, i);
break;
}
}
```
### What does this PR do?
add `lastInsertRowid` (matching SQLite)
add `affectedRows`
fix `mysql_native_password` deprecated authentication
fix AuthSwitch
Fixes:
https://github.com/oven-sh/bun/issues/22178#issuecomment-3228716080
### How did you verify your code works?
tests
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
Fix handling BIT(1) and BIT(N) on binary protocol and text protocol, now
behavior is consistent
### How did you verify your code works?
Tests
### What does this PR do?
- Instead of storing `len` in `BoundedArray` as a `usize`, store it as
either a `u8` or ` u16` depending on the `buffer_capacity`
- Copy-paste `BoundedArray` from the standard library into Bun's
codebase as it was removed in
https://github.com/ziglang/zig/pull/24699/files#diff-cbd8cbbc17583cb9ea5cc0f711ce0ad447b446e62ea5ddbe29274696dce89e4f
and we will probably continue using it
### How did you verify your code works?
Ran `bun run zig:check`
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: taylor.fish <contact@taylor.fish>
in JS, `new TextDecoder("latin1").decode(...)` uses cp1252. In python,
latin1 is half-width utf-16. In our code, latin1 typically refers to
half-width utf-16 because JavaScriptCore uses that for most strings, but
sometimes it refers to cp1252. Rename the cp1252 functions to be called
cp1252
Also fixes an issue where Buffer.from with utf-16le would sometimes
output the wrong value:
```js
$> bun -p "Buffer.from('\x80', 'utf-16le')"
<Buffer ac 20>
$> node -p "Buffer.from('\x80', 'utf-16le')"
<Buffer 80 00>
$> bun-debug -p "Buffer.from('\x80', 'utf-16le')"
<Buffer 80 00>
```
## Summary
- Fixed allocator threading violation when `BUN_INSPECT_CONNECT_TO` is
set
- Created thread-local `env_loader` with proper allocator isolation in
debugger thread
- Added regression test to verify the fix works correctly
## Problem
When `BUN_INSPECT_CONNECT_TO` environment variable is set, Bun creates a
debugger thread that spawns its own `VirtualMachine` instance.
Previously, this VM would fall back to the global `DotEnv.instance`
which was created with the main thread's allocator, causing threading
violations when the debugger thread accessed environment files via
`--env-file` or other env loading operations.
## Solution
Modified `startJSDebuggerThread` in `src/bun.js/Debugger.zig` to:
1. Create a thread-local `DotEnv.Map` and `DotEnv.Loader` using the
debugger thread's allocator
2. Pass this thread-local `env_loader` to `VirtualMachine.init()` to
ensure proper allocator isolation
3. Prevent sharing of allocators across threads
## Test plan
- [x] Added regression test in
`test/regression/issue/test_env_loader_threading.test.ts`
- [x] Verified basic Bun functionality still works
- [x] Test passes with both normal execution and with
`BUN_INSPECT_CONNECT_TO` set
🤖 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>
ZLS was tested manually and works with private fields (after restarting)
Zig diff:
d1a4e0b0dd..ebe0cdac31
ZLS diff:
15730e8e5d..3733f39c8d
Increases `zig build check` time by maybe 10ms?
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
Fixes an issue where compiled standalone binaries included an extra
executable name argument in `process.argv`, breaking code that uses
`node:util.parseArgs()` with `process.argv.slice(2)`.
## Problem
When running a compiled binary, `process.argv` incorrectly included the
executable name as a third argument:
```bash
./my-app
# process.argv = ["bun", "/$bunfs/root/my-app", "./my-app"] # BUG
```
This caused `parseArgs()` to fail with "Unexpected argument" errors,
breaking previously valid code.
## Solution
Fixed the `offset_for_passthrough` calculation in `cli.zig` to always
skip the executable name for standalone binaries, ensuring
`process.argv` only contains the runtime name and script path:
```bash
./my-app
# process.argv = ["bun", "/$bunfs/root/my-app"] # FIXED
```
## Test plan
- [x] Added regression test in `test/regression/issue/22157.test.ts`
- [x] Verified existing exec-argv functionality still works correctly
- [x] Manual testing confirms the fix resolves the parseArgs issue
Fixes#22157🤖 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: Michael H <git@riskymh.dev>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This PR adds a guide for deploying Bun apps on Railway with PostgreSQL
(optional), including both CLI and dashboard methods, and deploy
template
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.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>
### What does this PR do?
Change tinyint/bool type from mysql to number instead of bool to match
mariadb and mysql2 behavior since tinyint/bool can be bigger than 1 in
mysql
Fixes https://github.com/oven-sh/bun/issues/22158
### How did you verify your code works?
Test
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
### How did you verify your code works?
---------
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
Updates build instructions in `CONTRIBUTING.md`
### How did you verify your code works?
N/A
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Replace `catch bun.outOfMemory()`, which can accidentally catch
non-OOM-related errors, with either `bun.handleOom` or a manual `catch
|err| switch (err)`.
(For internal tracking: fixes STAB-1070)
---------
Co-authored-by: Dylan Conway <dylan.conway567@gmail.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>