Commit Graph

199 Commits

Author SHA1 Message Date
robobun
7076a49bb1 feat(archive): add TypeScript types, docs, and files() benchmark (#25922)
## Summary

- Add comprehensive TypeScript type definitions for `Bun.Archive` in
`bun.d.ts`
  - `ArchiveInput` and `ArchiveCompression` types
- Full JSDoc documentation with examples for all methods (`from`,
`write`, `extract`, `blob`, `bytes`, `files`)
- Add documentation page at `docs/runtime/archive.mdx`
  - Quickstart examples
  - Creating and extracting archives
  - `files()` method with glob filtering
  - Compression support
  - Full API reference section
- Add Archive to docs sidebar under "Data & Storage"
- Add `files()` benchmark comparing `Bun.Archive.files()` vs node-tar
- Shows ~7x speedup for reading archive contents into memory (59µs vs
434µs)

## Test plan

- [x] TypeScript types compile correctly
- [x] Documentation renders properly in Mintlify format
- [x] Benchmark runs successfully and shows performance comparison
- [x] Verified `files()` method works correctly with both Bun.Archive
and node-tar

🤖 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>
2026-01-09 19:00:19 -08:00
robobun
70fa6af355 feat: add Bun.Archive API for creating and extracting tarballs (#25665)
## Summary

- Adds new `Bun.Archive` API for working with tar archives
- `Bun.Archive.from(data)` - Create archive from object, Blob,
TypedArray, or ArrayBuffer
- `Bun.Archive.write(path, data, compress?)` - Write archive to disk
(async)
- `archive.extract(path)` - Extract to directory, returns
`Promise<number>` (file count)
- `archive.blob(compress?)` - Get archive as Blob (async)
- `archive.bytes(compress?)` - Get archive as Uint8Array (async)

Key implementation details:
- Uses existing libarchive bindings for tarball creation/extraction via
`extractToDisk`
- Uses libdeflate for gzip compression
- Immediate byte copying for GC safety (no JSValue protection, no
`hasPendingActivity`)
- Async operations run on worker pool threads with proper VM reference
handling
- Growing memory buffer via `archive_write_open2` callbacks for
efficient tarball creation

## Test plan

- [x] 65 comprehensive tests covering:
  - Normal operations (create, extract, blob, bytes, write)
  - GC safety (unreferenced archives, mutation isolation)  
  - Error handling (invalid args, corrupted data, I/O errors)
- Edge cases (large files, many files, special characters, path
normalization)
  - Concurrent operations

🤖 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: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2026-01-09 00:33:35 -08:00
robobun
604c83c8a6 perf(ipc): fix O(n²) JSON scanning for large chunked messages (#25743)
## Summary

- Fix O(n²) performance bug in JSON mode IPC when receiving large
messages that arrive in chunks
- Add `JsonIncomingBuffer` wrapper that tracks newline positions to
avoid re-scanning
- Each byte is now scanned exactly once (on arrival or when preceding
message is consumed)

## Problem

When data arrives in chunks in JSON mode, `decodeIPCMessage` was calling
`indexOfChar(data, '\n')` on the ENTIRE accumulated buffer every time.
For a 10MB message arriving in 160 chunks of 64KB:

- Chunk 1: scan 64KB
- Chunk 2: scan 128KB  
- Chunk 3: scan 192KB
- ...
- Chunk 160: scan 10MB

Total: ~800MB scanned for one 10MB message.

## Solution

Introduced a `JsonIncomingBuffer` struct that:
1. Tracks `newline_pos: ?u32` - position of known upcoming newline (if
any)
2. On `append(bytes)`: Only scans new chunk for `\n` if no position is
cached
3. On `consume(bytes)`: Updates or re-scans as needed after message
processing

This ensures O(n) scanning instead of O(n²).

## Test plan

- [x] `bun run zig:check-all` passes (all platforms compile)
- [x] `bun bd test test/js/bun/spawn/spawn.ipc.test.ts` - 4 tests pass
- [x] `bun bd test test/js/node/child_process/child_process_ipc.test.js`
- 1 test pass
- [x] `bun bd test test/js/bun/spawn/bun-ipc-inherit.test.ts` - 1 test
pass
- [x] `bun bd test test/js/bun/spawn/spawn.ipc.bun-node.test.ts` - 1
test pass
- [x] `bun bd test test/js/bun/spawn/spawn.ipc.node-bun.test.ts` - 1
test pass
- [x] `bun bd test
test/js/node/child_process/child_process_ipc_large_disconnect.test.js` -
1 test pass
- [x] Manual verification with `child-process-send-cb-more.js` (32KB
messages)

🤖 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>
2025-12-29 20:02:18 -08:00
robobun
1d7cb4bbad perf(Response.json): use JSC's FastStringifier by passing undefined for space (#25717)
## Summary

- Fix performance regression where `Response.json()` was 2-3x slower
than `JSON.stringify() + new Response()`
- Root cause: The existing code called `JSC::JSONStringify` with
`indent=0`, which internally passes `jsNumber(0)` as the space
parameter. This bypasses WebKit's FastStringifier optimization.
- Fix: Add a new `jsonStringifyFast` binding that passes `jsUndefined()`
for the space parameter, triggering JSC's FastStringifier
(SIMD-optimized) code path.

## Root Cause Analysis

In WebKit's `JSONObject.cpp`, the `stringify()` function has this logic:

```cpp
static NEVER_INLINE String stringify(JSGlobalObject& globalObject, JSValue value, JSValue replacer, JSValue space)
{
    // ...
    if (String result = FastStringifier<Latin1Character, BufferMode::StaticBuffer>::stringify(globalObject, value, replacer, space, failureReason); !result.isNull())
        return result;
    // Falls back to slow Stringifier...
}
```

And `FastStringifier::stringify()` checks:
```cpp
if (!space.isUndefined()) {
    logOutcome("space"_s);
    return { };  // Bail out to slow path
}
```

So when we called `JSONStringify(globalObject, value, (unsigned)0)`, it
converted to `jsNumber(0)` which is NOT `undefined`, causing
FastStringifier to bail out.

## Performance Results

### Before (3.5x slower than manual approach)
```
Response.json():                2415ms
JSON.stringify() + Response():  689ms
Ratio:                          3.50x
```

### After (parity with manual approach)
```
Response.json():                ~700ms  
JSON.stringify() + Response():  ~700ms
Ratio:                          ~1.09x
```

## Test plan

- [x] Existing `Response.json()` tests pass
(`test/regression/issue/21257.test.ts`)
- [x] Response tests pass (`test/js/web/fetch/response.test.ts`)
- [x] Manual verification that output is correct for various JSON inputs

Fixes #25693

🤖 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: Sosuke Suzuki <sosuke@bun.com>
2025-12-27 15:01:28 -08:00
SUZUKI Sosuke
01de0ecbd9 Add simple benchmark for Array.of (#25711)
**before:**

```
$ bun bench/snippets/array-of.js
cpu: Apple M4 Max
runtime: bun 1.3.5 (arm64-darwin)

benchmark                                  time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------------------------- -----------------------------
int: Array.of(1,2,3,4,5)                 9.19 ns/iter       (8.1 ns … 108 ns)   9.28 ns  13.63 ns  69.44 ns
int: Array.of(100 elements)             1'055 ns/iter   (94.58 ns … 1'216 ns)  1'108 ns  1'209 ns  1'216 ns
double: Array.of(1.1,2.2,3.3,4.4,5.5)   10.34 ns/iter      (8.81 ns … 102 ns)  10.17 ns  17.19 ns  73.51 ns
double: Array.of(100 elements)          1'073 ns/iter     (124 ns … 1'215 ns)  1'136 ns  1'204 ns  1'215 ns
object: Array.of(obj x5)                19.19 ns/iter     (16.58 ns … 122 ns)  19.06 ns   77.6 ns  85.75 ns
object: Array.of(100 elements)          1'340 ns/iter     (294 ns … 1'568 ns)  1'465 ns  1'537 ns  1'568 ns
```

**after:**

```
$ ./build/release/bun bench/snippets/array-of.js
cpu: Apple M4 Max
runtime: bun 1.3.6 (arm64-darwin)

benchmark                                  time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------------------------- -----------------------------
int: Array.of(1,2,3,4,5)                 2.68 ns/iter    (2.14 ns … 92.96 ns)   2.52 ns   3.95 ns  59.73 ns
int: Array.of(100 elements)             23.69 ns/iter     (18.88 ns … 155 ns)  20.91 ns  83.82 ns  96.66 ns
double: Array.of(1.1,2.2,3.3,4.4,5.5)    3.62 ns/iter    (2.97 ns … 75.44 ns)   3.46 ns   5.05 ns  65.82 ns
double: Array.of(100 elements)          26.96 ns/iter     (20.14 ns … 156 ns)  24.45 ns  87.75 ns  96.88 ns
object: Array.of(obj x5)                11.82 ns/iter     (9.6 ns … 87.38 ns)  11.23 ns  68.99 ns  77.09 ns
object: Array.of(100 elements)            236 ns/iter       (206 ns … 420 ns)    273 ns    325 ns    386 ns
```
2025-12-27 00:05:57 -08:00
SUZUKI Sosuke
92f105dbe1 Add microbench for String#includes (#25699)
note: This is due to constant folding by the JIT. For `String#includes`
on dynamic strings, the performance improvement is not this significant.

**before:**
```
$ bun ./bench/snippets/string-includes.mjs
cpu: Apple M4 Max
runtime: bun 1.3.5 (arm64-darwin)

benchmark                                  time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------------------------- -----------------------------
String.includes - short, hit (middle)   82.24 ns/iter     (14.95 ns … 881 ns)  84.98 ns    470 ns    791 ns
String.includes - short, hit (start)    37.44 ns/iter      (8.46 ns … 774 ns)  26.08 ns    379 ns    598 ns
String.includes - short, hit (end)      97.27 ns/iter     (16.93 ns … 823 ns)    107 ns    537 ns    801 ns
String.includes - short, miss             102 ns/iter       (0 ps … 1'598 µs)     42 ns    125 ns    167 ns
String.includes - long, hit (middle)    16.01 ns/iter     (14.34 ns … 115 ns)  16.03 ns   20.1 ns   53.1 ns
String.includes - long, miss              945 ns/iter       (935 ns … 972 ns)    948 ns    960 ns    972 ns
String.includes - with position          9.83 ns/iter    (8.44 ns … 58.45 ns)   9.83 ns  12.31 ns  15.69 ns
```

**after:**
```
$ ./build/release/bun bench/snippets/string-includes.mjs
cpu: Apple M4 Max
runtime: bun 1.3.6 (arm64-darwin)

benchmark                                  time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------------------------- -----------------------------
String.includes - short, hit (middle)     243 ps/iter     (203 ps … 10.13 ns)    244 ps    325 ps    509 ps !
String.includes - short, hit (start)      374 ps/iter     (244 ps … 19.78 ns)    387 ps    488 ps    691 ps
String.includes - short, hit (end)        708 ps/iter     (407 ps … 18.03 ns)    651 ps   2.62 ns   2.69 ns
String.includes - short, miss            1.49 ns/iter     (407 ps … 27.93 ns)   2.87 ns   3.09 ns   3.78 ns
String.includes - long, hit (middle)     3.28 ns/iter      (3.05 ns … 118 ns)   3.15 ns   8.75 ns  16.07 ns
String.includes - long, miss             7.28 ns/iter      (3.44 ns … 698 ns)   9.34 ns  42.85 ns    240 ns
String.includes - with position          7.97 ns/iter       (3.7 ns … 602 ns)   9.68 ns  52.19 ns    286 ns
```
2025-12-26 21:49:00 -08:00
Jarred Sumner
0dd4f025b6 [publish images] (+ add Object.hasOwn benchmark) 2025-12-24 19:55:44 -08:00
Jarred Sumner
79067037ff Add Promise.race microbenchmark 2025-12-23 22:53:24 -08:00
Jarred Sumner
0305f3d4d2 feat(url): implement URLPattern API (#25168)
## Summary

Implements the [URLPattern Web
API](https://developer.mozilla.org/en-US/docs/Web/API/URLPattern) based
on WebKit's implementation. URLPattern provides declarative pattern
matching for URLs, similar to how regular expressions work for strings.

### Features

- **Constructor**: Create patterns from strings or `URLPatternInit`
dictionaries
- **`test()`**: Check if a URL matches the pattern (returns boolean)
- **`exec()`**: Extract matched groups from a URL (returns
`URLPatternResult` or null)
- **Pattern properties**: `protocol`, `username`, `password`,
`hostname`, `port`, `pathname`, `search`, `hash`
- **`hasRegExpGroups`**: Detect if the pattern uses custom regular
expressions

### Example Usage

```js
// Match URLs with a user ID parameter
const pattern = new URLPattern({ pathname: '/users/:id' });

pattern.test('https://example.com/users/123'); // true
pattern.test('https://example.com/posts/456'); // false

const result = pattern.exec('https://example.com/users/123');
console.log(result.pathname.groups.id); // "123"

// Wildcard matching
const filesPattern = new URLPattern({ pathname: '/files/*' });
const match = filesPattern.exec('https://example.com/files/image.png');
console.log(match.pathname.groups[0]); // "image.png"
```

## Implementation Notes

- Adapted from WebKit's URLPattern implementation
- Modified JS bindings to work with Bun's infrastructure (simpler
`convertDictionary` patterns, WTF::Variant handling)
- Added IsoSubspaces for proper GC integration

## Test Plan

- [x] 408 tests from Web Platform Tests pass
- [x] Tests fail with system Bun (URLPattern not defined), pass with
debug build
- [x] Manual testing of basic functionality

Fixes https://github.com/oven-sh/bun/issues/2286

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2025-11-28 00:04:30 -08:00
Meghan Denny
5702b39ef1 runtime: implement CompressionStream/DecompressionStream (#24757)
Closes https://github.com/oven-sh/bun/issues/1723
Closes https://github.com/oven-sh/bun/pull/22214
Closes https://github.com/oven-sh/bun/pull/24241

also supports the `"brotli"` and `"zstd"` formats

<img width="1244" height="547" alt="image"
src="https://github.com/user-attachments/assets/aecf4489-29ad-411d-9f6b-3bee50ed1b27"
/>
2025-11-20 17:14:37 -08:00
Meghan Denny
fa219a2f8e js: update node:_http_agent (#24275)
pulled out of https://github.com/oven-sh/bun/pull/21809

+7 node tests

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2025-11-04 11:56:33 -08:00
Jarred Sumner
033c977fea Avoid emitting DCE annotations at runtime (#22300)
### What does this PR do?

### How did you verify your code works?
2025-09-01 02:56:59 -07:00
Jarred Sumner
4fa69773a3 Introduce Bun.stripANSI (#21801)
### What does this PR do?

Introduce `Bun.stripANSI`, a SIMD-accelerated drop-in replacement for
the popular `"strip-ansi"` package.

`Bun.stripANSI` performs >10x faster and fixes several bugs in
`strip-ansi`, like [this long-standing
one](https://github.com/chalk/strip-ansi/issues/43).

### How did you verify your code works?

There are tests that check the output of `strip-ansi` matches
`Bun.stripANSI`. For cases where `strip-ansi`'s behavior is incorrect,
the expected value is manually provided.

---------

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>
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: taylor.fish <contact@taylor.fish>
2025-08-14 22:42:05 -07:00
Jarred Sumner
7726e5c670 Update node-zlib-brotli.mjs 2025-08-01 14:35:04 -07:00
Jarred Sumner
55a9cccac0 bun.sh -> bun.com (#20909) 2025-07-10 00:10:43 -07:00
Jarred Sumner
454316ffc3 Implement "node:module"'s findSourceMap and SourceMap class (#20863)
Co-authored-by: Claude <claude@anthropic.ai>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2025-07-07 23:08:12 -07:00
Joel Shepherd
13c5b0d9cb Added rapidhash algorithm (#20163) 2025-06-03 03:34:35 -07:00
Meghan Denny
d774baa28a tidyings from 18962 (#19644) 2025-05-14 18:47:51 -07:00
Jarred Sumner
acf0b68299 Make request.method getter not allocate memory (#18961) 2025-04-11 20:59:38 -07:00
Jarred Sumner
02023810ba Clean up some docs 2025-04-08 03:57:35 -07:00
Kai Tamkun
4a0e982bb2 node:http improvements (#17093)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Pham Minh Triet <92496972+Nanome203@users.noreply.github.com>
Co-authored-by: snwy <snwy@snwy.me>
Co-authored-by: Ciro Spaciari <ciro.spaciari@gmail.com>
Co-authored-by: cirospaciari <cirospaciari@users.noreply.github.com>
Co-authored-by: Ben Grant <ben@bun.sh>
2025-03-10 20:19:29 -07:00
Meghan Denny
5ae28d27a0 node: fix buffer includes+indexof (#16642) 2025-02-18 13:12:03 -08:00
Jarred Sumner
f29e912a91 Add routes to Bun.serve() (#17357) 2025-02-16 00:42:05 -08:00
Meghan Denny
6353fa4806 node:buffer: fix read (#17299) 2025-02-12 23:37:36 -08:00
chloe caruso
f17ce2b756 hmr fixes (#17239)
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-12 23:14:02 -08:00
Meghan Denny
180500181f js: fix Buffer constructor and Buffer.from (#16731) 2025-02-07 15:13:21 -08:00
Jarred Sumner
f1cfb10658 Update buffer-create.mjs 2025-01-24 23:37:41 -08:00
Jarred Sumner
274859584d Add docs for html imports 2025-01-15 16:33:24 -08:00
Don Isaac
81ecf7556c ci: repair lint setup and run it in CI (#15720)
Co-authored-by: Don Isaac <don@bun.sh>
2025-01-08 07:12:18 +00:00
Jarred Sumner
912a2cbc12 Expose some no-ops (#16125)
Co-authored-by: Jarred-Sumner <Jarred-Sumner@users.noreply.github.com>
2025-01-03 13:57:46 -08:00
Jarred Sumner
ab8fe1a6c3 Bump 2025-01-02 21:17:47 -08:00
Jarred Sumner
19191659cf Avoid resolving substrings in bun:sqlite and Buffer.byteLength (#16092) 2024-12-31 19:48:33 -08:00
Jarred Sumner
608101c975 Add zlib microbenchmark
need to improve this
2024-12-24 04:20:24 -08:00
Michael H
b54137174b Bench updates (#15029)
Co-authored-by: RiskyMH <RiskyMH@users.noreply.github.com>
2024-11-08 23:15:24 -08:00
Dylan Conway
7283453eed use memset_patternN in Buffer.fill (#14599) 2024-10-15 21:16:57 -07:00
Ashcon Partovi
27a157b6c1 Improve command detection in CMake 2024-10-01 13:50:15 -07:00
Zack Radisic
274e5a2022 CSS Parser (#14122)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2024-09-26 13:39:26 -07:00
Jarred Sumner
d9d4cff303 Micro-optimize path.resolve(), path.resolve("") (#13930) 2024-09-14 01:42:49 -04:00
Jarred Sumner
ff6f8bd2d1 Update path-resolve.mjs 2024-09-12 15:00:52 -07:00
Jarred Sumner
872c7f0d91 Why is path slow (#13908) 2024-09-12 14:05:16 -07:00
Jarred Sumner
cd6785771e run prettier and add back format action (#13722) 2024-09-03 21:32:52 -07:00
Jarred Sumner
f7d459eea5 Create text-decoder-stream.mjs 2024-08-10 17:09:51 -07:00
Jarred Sumner
7d018fb323 Update text-encoder-stream.mjs 2024-08-10 03:20:14 -07:00
Jarred Sumner
5f08478229 Update text-encoder-stream.mjs 2024-08-10 03:15:11 -07:00
Jarred Sumner
d861347dc5 Optimize TextEncoderStream, part 1 (#13222) 2024-08-10 02:13:36 -07:00
dave caruso
749c51d71a simpler version of simplifyUnusedExpr rewrite (#12384) 2024-07-05 20:20:45 -07:00
Jarred Sumner
a0032d1b5c Replace libbase64 with simdutf (#11982) 2024-06-19 23:02:56 -07:00
Jarred Sumner
1b8a72e724 Fixes #11703 (#11776) 2024-06-11 03:52:40 -07:00
Jarred Sumner
45d0c1432b rewrite timers for setTimeout, setInterval, setImmediate (#11419)
Co-authored-by: Jarred-Sumner <Jarred-Sumner@users.noreply.github.com>
Co-authored-by: Georgijs Vilums <=>
Co-authored-by: Georgijs <48869301+gvilums@users.noreply.github.com>
Co-authored-by: Georgijs Vilums <georgijs.vilums@gmail.com>
Co-authored-by: gvilums <gvilums@users.noreply.github.com>
2024-05-30 02:11:12 -07:00
Jarred Sumner
b15d47dfe8 Introduce bun.dns.prefetch API (#11176)
Co-authored-by: Jarred-Sumner <Jarred-Sumner@users.noreply.github.com>
Co-authored-by: Eric L. Goldstein <3359116+mangs@users.noreply.github.com>
2024-05-19 18:08:16 -07:00