Skip to content

Bun.password: report an argon2 memory cost that cannot be allocated as OutOfMemory instead of aborting - #39021

Open
robobun wants to merge 1 commit into
mainfrom
farm/2c85f6c1/argon2-oom
Open

robobun wants to merge 1 commit into
mainfrom
farm/2c85f6c1/argon2-oom

Conversation

@robobun

@robobun robobun commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Problem

  • Bun.password.hash / hashSync accept memoryCost up to 4294967295 KiB (4 TiB), and verify / verifySync take m= from the encoded hash (the existing prescan caps it at 4 GiB). pwhash::argon2::str_hash / str_verify (src/runtime/crypto/pwhash.rs) hand the cost to rust-argon2, whose Memory::new allocates the block matrix with vec![Block::zero(); n] (rust-argon2 3.0.0 memory.rs:36, reached from run() for both hashing and verifying). When that allocation fails the process aborts: memory allocation of N bytes failed, panic(main thread): abort() called, and a "Bun has crashed" report, for a value the caller passed in (or, for verify, for a hash string somebody else produced).
  • Reproduced on the current release build: sh -c 'ulimit -v 4194304; exec bun -e "Bun.password.hashSync(\"pw\", { algorithm: \"argon2id\", memoryCost: 4194304 })"' aborts with memory allocation of 4294967296 bytes failed; a 512 MiB cost under a 1 GB limit aborts the same way, and so does the 4 TiB maximum on a machine with Linux's default overcommit setting (the request exceeds RAM plus swap, so mmap refuses it).
  • Before the Rust port, Zig's std.crypto.pwhash.argon2 took an allocator and returned error.OutOfMemory, which PasswordObject.zig reported like every other hash failure: Password hashing failed with error "OutOfMemory" with code: "PASSWORD_OUT_OF_MEMORY".

Fix

  • check_memory_is_allocatable(m) reserves m * 1024 bytes with try_reserve_exact, drops the probe, and returns Error::Alloc on failure. str_hash calls it right before hash_encoded; str_verify records m in the prescan it already runs over the cost fields and calls it right before verify_encoded (the decoder only accepts strings with exactly one m=, so this is the cost it would allocate for; anything else fails to decode before allocating).
  • Error::Alloc names itself OutOfMemory, so the unchanged password_error_instance in PasswordObject.rs produces exactly the pre-port error, on both the sync path and the work-pool path: Password hashing failed with error "OutOfMemory" / Password verification failed with error "OutOfMemory", code: "PASSWORD_OUT_OF_MEMORY".
  • Where this changes behavior: wherever the allocation itself fails. That is every Windows machine without the commit charge to spare (Windows does not overcommit), Linux with the default overcommit heuristic whenever the cost exceeds RAM plus swap (for example a cost given in bytes or MiB instead of KiB, or the m= of a hash string an attacker controls), and any address-space or commit limit. It deliberately changes nothing when the allocation succeeds and the machine later runs out of memory while argon2 touches the blocks (overcommit_memory=1, cgroup limits); that is the OOM killer's domain, as before.
  • Why a probe: rust-argon2 has no API that takes caller-provided memory or fails on allocation, and the two ways to change that (patching the crate, which build: fetch and patch rust-argon2 as a vendored cargo path dependency #33153 is the open infrastructure for, or switching to RustCrypto's argon2, which changes the PHC codec and the verify semantics) are much larger changes than this needs. The probe is best effort by construction (another thread can take the memory between the probe and the crate's allocation, and the crate rounds the cost down to a multiple of 4 blocks), which is acceptable: it cannot make anything that works today fail, and it converts every deterministic failure into the error. It costs one untouched reservation and release per call, microseconds next to the hash itself. The function is pub(crate) so the node:crypto argon2 binding proposed in node:crypto: implement argon2 and argon2Sync #37015, which drives the same crate, can use the same check.
  • Not changed here: the memoryCost ceiling for hash. Bun.password: reject argon2 cost options that verify would refuse #33865 proposes capping it at verify's 4 GiB; that is compatible with this and does not replace it, since the costs that fail to allocate in practice (64 MiB default, 4 GiB maximum) are well inside any plausible ceiling. crypto: accept argon2 PHC params in any order in Bun.password.verify #32314 edits the same prescan loop; whichever lands second has a three-line conflict.
  • Verified with test/js/bun/util/password.test.ts: the same child script runs hashSync, hash, verifySync and verify against an unallocatable cost and checks an allocatable one still works afterwards, in two variants. Under ASAN (test.skipIf(!isASAN)) with allocator_may_return_null=1:max_allocation_size_mb=32 and the default 64 MiB cost: fails on main with memory allocation of 67108864 bytes failed, passes here. On Linux release builds (test.skipIf(isASAN || !isLinux); ASAN builds cannot start under an address-space limit) with ulimit -v 4194304 and a 4 GiB cost, which can never fit while bun itself starts in about 0.35 GB: fails against the current release build with memory allocation of 4294967296 bytes failed (output below); its passing side runs on CI's Linux release lanes, since the local debug build is ASAN. The rest of the file: 72 pass, 9 debug-only skips.
  • This was split out of TextEncoderStream: throw out of memory instead of aborting when a chunk's output buffer cannot be allocated #38941 (the TextEncoderStream half of the same port regression), which shares no code with it.

Background

  • argon2's memory cost m is in KiB: the algorithm fills a matrix of m one-kibibyte blocks, allocated up front in one piece, and reads it back while hashing, so it is the dominant allocation of a hash or verify call. verify gets it from the PHC string it is given ($argon2id$v=19$m=65536,t=2,p=1$salt$hash), so it is input, not configuration.
  • Vec::try_reserve_exact returns Err when the allocator returns null, where the crate's vec! calls handle_alloc_error and aborts. Reserving without writing touches no pages, so the probe costs the allocator a reservation and a release and nothing else.
  • Error::Alloc(AllocError) is the runtime crate's out-of-memory variant; Error::name() reports it as OutOfMemory, and Bun.password builds both the message and the PASSWORD_* code from that name, which is also how the Zig implementation formatted error.OutOfMemory.
  • Under ASAN the global allocator is libc's, and ASAN_OPTIONS=allocator_may_return_null=1:max_allocation_size_mb=N makes any single allocation above N MiB return null; ulimit -v (RLIMIT_AS) makes mmap fail once the process's address space would exceed the limit, which is how mimalloc ends up returning null in the release variant.
Release build, without the fix, address-space variant of the test
memory allocation of 4294967296 bytes failed
...
RSS: 29.65 MB | Peak: 0.35 GB | Commit: 25.10 MB | Faults: 0 | Machine: 34.36 GB

panic(main thread): abort() called
oh no: Bun has crashed. This indicates a bug in Bun, not your code.

With the fix, all four entry points report
{"name":"Error","code":"PASSWORD_OUT_OF_MEMORY","message":"Password hashing failed with error \"OutOfMemory\""}
(verification for the verify pair) and a hash with memoryCost: 8 still round-trips afterwards.

…s OutOfMemory instead of aborting

rust-argon2 allocates the block matrix infallibly, so a memoryCost the system
cannot satisfy (hash options, or the m= field of a hash given to verify)
aborted the process. Reserve the same amount fallibly first and report it as
OutOfMemory, which Bun.password surfaces as the PASSWORD_OUT_OF_MEMORY error
it produced before the Rust port.
@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 29 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f5a13d45-89ff-482d-a437-8e79d153a875

📥 Commits

Reviewing files that changed from the base of the PR and between 732491c and df83a0a.

📒 Files selected for processing (2)
  • src/runtime/crypto/pwhash.rs
  • test/js/bun/util/password.test.ts

Comment @coderabbitai help to get the list of available commands.

@robobun

robobun commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator Author

Status: fixed, waiting on CI. Split out of #38941.

  • Reproduced on the current release build: sh -c 'ulimit -v 4194304; exec bun -e "Bun.password.hashSync(\"pw\", { algorithm: \"argon2id\", memoryCost: 4194304 })"' aborts with memory allocation of 4294967296 bytes failed and a crash report; the debug (ASAN) build aborts the same way for the default 64 MiB cost under max_allocation_size_mb=32, on hash and on verify of a hash string claiming that cost.
  • With this branch all four entry points throw or reject with PASSWORD_OUT_OF_MEMORY, the error the pre-port implementation produced, and the process continues.
  • Test: test/js/bun/util/password.test.ts, an ASAN variant (fails on main, passes here locally) and a Linux release variant under ulimit -v (fails against the current release build; its passing side runs on the Linux release lanes).

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this PR and didn't find any bugs. The probe-then-allocate approach is sound and strictly additive (can only turn aborts into errors, never the reverse), but since it's a deliberate interim design choice in Bun.password — chosen over patching rust-argon2 or switching crates — a maintainer should confirm they're happy landing it this way.

What was reviewed

  • check_memory_is_allocatable: u32 → usize widening + checked_mul(1024) before try_reserve_exact; ? on bun_alloc::AllocError reaches crate::Error::Alloc via #[from], and Error::name() returns "OutOfMemory" → PASSWORD_OUT_OF_MEMORY in password_error_instance.
  • Verify path: m= recorded inside the existing prescan; the ulimit test's m=4194304 is exactly MAX_VERIFY_MEMORY_COST (1 << 22), so it passes the WeakParameters cap and reaches the probe as intended.
  • Probe uses the global allocator, same as rust-argon2's vec[Block; n], so ASAN's max_allocation_size_mb and mimalloc under ulimit -v see the same failure the real allocation would.
Extended reasoning...

Overview

The PR adds a fallible allocation probe (check_memory_is_allocatable) in src/runtime/crypto/pwhash.rs that reserves memoryCost * 1024 bytes via Vec::try_reserve_exact before rust-argon2's infallible vec[Block::zero(); n] runs. It is called from str_hash (using config.mem_cost) and from str_verify (using the m= value already parsed by the existing cost-cap prescan). On failure it returns Error::Alloc(AllocError), which Error::name() reports as "OutOfMemory" and password_error_instance formats as PASSWORD_OUT_OF_MEMORY — the same error the pre-port Zig implementation produced. Two new subprocess tests cover all four entry points (hash/hashSync/verify/verifySync) under ASAN's max_allocation_size_mb cap and under a Linux ulimit -v address-space limit.

Security risks

None introduced. This does not touch the argon2/bcrypt primitives, salts, or comparison logic; it only front-runs an allocation that would otherwise abort the process. If anything it hardens verify slightly against a hostile PHC string whose m= is sized to abort the process — that now becomes a catchable error. The probe cannot cause a previously-successful hash to fail: if the probe reservation succeeds it is immediately dropped, and the subsequent real allocation sees the same allocator state modulo a TOCTOU window the PR description explicitly acknowledges.

Level of scrutiny

Moderate-to-high. The Rust change is ~20 lines and mechanically simple, but it lives in Bun.password and encodes a design choice: a best-effort probe rather than patching rust-argon2 (blocked on #33153) or switching to RustCrypto's argon2 (which would change PHC codec/verify semantics). The PR description makes the case for this tradeoff thoroughly, and it also flags interactions with three other open PRs (#33865 memoryCost ceiling, #37015 node:crypto argon2, #32314 same prescan loop). That's exactly the kind of context where a maintainer should sign off on the direction, even though the implementation itself is straightforward and correct.

Other factors

I verified the error-plumbing chain end to end: bun_alloc::AllocError → crate::Error::Alloc (via #[from] at src/runtime/error.rs:419) → name() == "OutOfMemory" (line 782) → password_error_instance builds PASSWORD_OUT_OF_MEMORY. The verify test's m=4194304 sits exactly at MAX_VERIFY_MEMORY_COST so it clears the existing > limit check and reaches the new probe. The checked_mul guards 32-bit overflow. The tests follow harness conventions (bunEnv spread, concurrent pipe drain, exit-code asserted last, skipIf with stated reasons) and each has a plausible CI lane where it runs (ASAN debug for the first, Linux release for the second). No bugs found by the multi-agent hunt or by this pass; deferring purely so a human confirms the probe approach is the interim fix they want.

Jarred-Sumner pushed a commit that referenced this pull request Aug 22, 2026
…nk's output buffer cannot be allocated (#38941)

### Problem
- A `TextEncoderStream` chunk whose encoded output cannot be allocated
aborts the process: `memory allocation of N bytes failed`, then
`panic(main thread): abort() called` and a "Bun has crashed" report. The
output buffer is 1x to 3x the chunk, so for a large chunk this is where
the API runs out of memory.
- `encode_latin1_into`
(`src/runtime/webcore/TextEncoderStreamEncoder.rs`) reserves infallibly
at three places (the up-front reservation, the `reserve(2)` retry when a
two-byte char does not fit, the grow-to-fit reservation) and returns
nothing. `encode_utf16_into` returns a `Result`, but its main
reservation is infallible too, and the replacement encoder it falls back
to for invalid UTF-16, `to_utf8_list_with_type_bun`
(`src/bun_core/string/immutable/unicode.rs`), returns `Result<_,
AllocError>` while growing with `reserve_exact`, so its `Err` was
unreachable.
- The Zig version (`TextEncoderStreamEncoder.zig` at the parent of
23427db, lines 68 to 169) returned `throwOutOfMemoryValue()` at each
of these sites; the port lost that. #33014 fixed the same regression in
the decoding direction (`to_utf16_alloc*`, `TextDecoder`).

### Fix
- Every reservation in `encode_latin1_into`, `encode_utf16_into` and
`to_utf8_list_with_type_bun` is a `try_reserve` / `try_reserve_exact`
mapped to `AllocError`. The amounts are unchanged:
`ensure_total_capacity(len + remain + 1)` is `try_reserve(remain + 1)`,
and the old `reserve_exact((i + count + len + extra) - len)` is
`try_reserve_exact(i + count + extra)`.
- `encode_latin1_into` returns `Result` like its UTF-16 sibling, and the
two callers that did not handle an error yet (`encode_latin1`, and the
Latin-1 arm of `TextEncoderStreamEncoder__encodeIntoSink`) throw
out-of-memory the way `encode_utf16` and the UTF-16 arm already did.
`to_utf8_list_with_type_bun` has no other caller.
- Why this is the right behavior: the buffer's size is chosen by the
caller's data, and a failure to get it was part of the JS contract
before the port. The C++ transform step (`encodeAndEnqueue` in
`JSTextEncoderStream.cpp`) already turns a pending exception into a
rejected transform promise, so the `write()` rejects and the stream
errors with `RangeError: Out of memory`; nothing else needed to change.
This does not touch the abort-on-OOM policy for internal allocations; it
is the same shape as #33014 and the `try_reserve` sites in
`encoding.rs`, `PBKDF2.rs` and `TextDecoder`.
- Verified with `test/js/web/encoding/text-encoder-stream.test.ts`, two
ASAN-only tests (the gate and the ASAN lanes) that run a child under
`allocator_may_return_null=1:max_allocation_size_mb=4`. JSC allocates
the input strings outside that cap, so each of five inputs makes a
different encoder reservation fail: the Latin-1 up-front reservation,
the Latin-1 grow-to-fit reservation, the Latin-1 `reserve(2)` retry (an
ASCII byte plus an odd number of two-byte chars leaves one spare byte),
the UTF-16 simdutf-sized reservation, and the replacement encoder's
first reservation (a lone surrogate ahead of N ASCII units: simdutf's N
+ 2 fits, 1.2N + 3 does not). One test feeds the chunks to a JS reader
(write and read both reject with `RangeError: Out of memory`, and
encoding still works afterwards); the other serves them through
Bun.serve's native response sink, each behind a dangling lead surrogate
so the output is assembled in the encoder's own buffer (the arm that
stays the encoder's job if #36877 hands plain chunks to the sink
directly), which also covers the prepend variant of every reservation;
the errored transform cancels the source with the error and the server
keeps serving. Without the fix both children abort on the first input
(`memory allocation of 8388608 bytes failed`); the per-site sizes are in
the details below.
- Also run: `bun bd test test/js/web/encoding/` (577 pass),
`test/js/web/streams/streams.test.js`,
`test/regression/issue/29225.test.ts`,
`test/js/node/test/parallel/test-whatwg-webstreams-encoding.js`, `cargo
fmt --check`.
- Scope: this PR originally also contained the `Bun.password` argon2
change; that is an unrelated allocation with its own design question and
now lives in #39021. The same port regression exists in other user-sized
buffers that are not touched here and have been handed off separately:
the `Bun.gzipSync` / `gunzipSync` / `deflateSync` / `inflateSync` output
buffers (`BunObject.rs`, including the one sized from the gzip trailer's
ISIZE) and `Bun.zstdCompressSync` plus zstd decompression
(`BunObject.rs`, `zstd/lib.rs`). The sinks and SQL buffers are covered
by #38888's follow-up plan.

### Background
- `Vec::try_reserve` returns `Err` when the allocator returns null,
where `reserve` calls `handle_alloc_error` and aborts. Under ASAN the
allocator is libc's, and
`ASAN_OPTIONS=allocator_may_return_null=1:max_allocation_size_mb=N`
makes it return null for any single allocation above N MiB, which is
what makes these failures reproducible; JSC allocates JS strings through
its own allocator, which the cap does not apply to.
- `AllocError` is the unit error type the crates' `Error` enums wrap as
`Alloc(..)`; `JSGlobalObject::throw_out_of_memory_value` sets JSC's
out-of-memory `RangeError` as the pending exception.
- A TextEncoderStream transform that throws rejects the transform
promise, which errors both halves of the stream and, through
`pipeThrough`, cancels the stream being piped in with the same error;
that cancel reason is what the native-sink test observes.
- Native-sink path: when the stream's readable is consumed by a native
sink such as an HTTP response,
`TextEncoderStreamEncoder__encodeIntoSink` encodes into a reusable
buffer and hands it to the sink instead of enqueueing a `Uint8Array` per
chunk. A lead surrogate left over from the previous chunk is encoded as
a prefix of the next chunk's output, so that case always needs the
encoder's buffer.

<details>
<summary>Per-site aborts without the fix (debug ASAN build), each size
identifying the reservation that failed</summary>

48 MiB cap, JS path:

```
latin1, 64 MiB ASCII                      memory allocation of 67108864 bytes failed   (up-front reservation)
latin1, 40 MiB of 0xE9                    memory allocation of 83886080 bytes failed   (grow-to-fit, amortized from 40 MiB)
latin1, "a" + odd run of 0xE9             memory allocation of 83886084 bytes failed   (reserve(2) retry, amortized from 40 MiB + 2)
utf16, 20M x U+65E5                       memory allocation of 62914560 bytes failed   (simdutf-sized reservation, 3 bytes/unit)
utf16, U+D800 + 44 MiB of "a"             memory allocation of 55364815 bytes failed   (replacement encoder: 3 + 1.2 * 46137344)
```

4 MiB cap (the sizes the tests use), with the fix, ASAN's refused
allocation per case; JS path then native-sink path behind a carried lead
surrogate (+3 bytes of replacement prefix in each reservation):

```
latin1        8388608    8388611
latin1Grow    6291456    6291462
latin1Stuck   6291460    6291466
utf16         6291456    6291459
utf16Invalid  4718595    4718598
```

Every case reports `{"name":"RangeError","message":"Out of memory"}` and
the child exits 0.

</details>

<!-- robobun:evidence:begin -->

---

**[review]** gate passed · iteration 0 · 3 files touched

<details><summary>fails on main (without fix)</summary>

```console
ASAN without fix: BUILD FAILED (no junit output)
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test "--reporter=junit" "--reporter-outfile=/tmp/mechgate.xml" test/js/web/encoding/text-encoder-stream.test.ts
ninja: Entering directory `/workspace/bun/build/debug'
[1/85] gen BunProcess.lut.h
Generating /workspace/bun/build/debug/codegen/BunProcess.lut.h from /workspace/bun/src/jsc/bindings/BunProcess.cpp
[2/85] gen generated_host_exports.rs
generated_host_exports.rs: 92 exports (host=3, lazy=10, generic=79, rust=0); 240 extern-C blocks audited
[3/85] gen cpp.rs (cppbind)
[4/85] gen JS modules (bundle-modules)
Preprocess modules (11911ms)
Bundle modules (45ms)
Postprocesss modules (181ms)
Bundle Functions (696ms)
Generate Code (13ms)

[12.87s] Bundled "src/js" for development
  2826 kb
  197 internal modules
  13 native modules
  91 internal functions across 17 files
[4/80] cargo bun_bin → libbun_rust.a (--target x86_64-unknown-linux-gnu)

  nightly-2026-07-20-x86_64-unknown-linux-gnu unchanged - rustc 1.99.0-nightly (9f36de775 2026-07-19)

[76/80] cxx obj/codegen/ZigGeneratedClasses.cpp.o
FAILED: rust-target/x86_64-unknown-linux-gnu/debug/libbun_rust.a 
/workspace/bun/build/release/bun /work
... (truncated)

release without fix: 2 skipped
bun test v1.4.0-canary.1 (eabb96d)

test/js/web/encoding/text-encoder-stream.test.ts:
(pass) encoding one string of UTF-8 should give one complete chunk [0.61ms]
(pass) a character split between chunks should be correctly encoded [0.06ms]
(pass) a character following one split between chunks should be correctly encoded [0.04ms]
(pass) two consecutive astral characters each split down the middle should be correctly reassembled [0.03ms]
(pass) two consecutive astral characters each split down the middle with an invalid surrogate in the middle should be correctly encoded [0.06ms]
(pass) a stream ending in a leading surrogate should emit a replacement character as a final chunk [0.02ms]
(pass) an unmatched surrogate at the end of a chunk followed by an astral character in the next chunk should be replaced with the replacement character at the start of the next output chunk [0.03ms]
(pass) an unmatched surrogate at the end of a chunk followed by an ascii character in the next chunk should be replaced with the replacement character at the start of the next output chunk [0.02ms]
(pass) an unmatched surrogate at the end of a chunk followed by a plane 1 character split int
... (truncated)
```

</details>

<details><summary>passes on PR (with fix)</summary>

```console
ASAN with fix: all passed
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test "--reporter=junit" "--reporter-outfile=/tmp/mechgate.xml" test/js/web/encoding/text-encoder-stream.test.ts
bun test v1.4.0 (3250eb4)

test/js/web/encoding/text-encoder-stream.test.ts:
(pass) encoding one string of UTF-8 should give one complete chunk [41.59ms]
(pass) a character split between chunks should be correctly encoded [8.27ms]
(pass) a character following one split between chunks should be correctly encoded [6.15ms]
(pass) two consecutive astral characters each split down the middle should be correctly reassembled [6.95ms]
(pass) two consecutive astral characters each split down the middle with an invalid surrogate in the middle should be correctly encoded [9.03ms]
(pass) a stream ending in a leading surrogate should emit a replacement character as a final chunk [4.68ms]
(pass) an unmatched surrogate at the end of a chunk followed by an astral character in the next chunk should be replaced with the replacement character at the start of the next output chunk [5.68ms]
(pass) an unmatched surrogate at the end of a chunk followed by an ascii character in the next chunk should be replac
... (truncated)

release with fix: 2 skipped
$ bun scripts/build.ts --profile=release
[configured] bun-profile → bun (stripped)
  target       linux-x64-gnu
  build type   Release
  build dir    ./build/release
  revision     3250eb4
  features     baseline

22 deps, 123 codegen, 1176 objects in 1165ms

ninja: Entering directory `/workspace/bun/build/release'
[1/1238] gen ErrorCode+*.h
[2/1238] gen bindgenv2
[3/1238] install /workspace/bun
bun install v1.4.0-canary.1 (eabb96d)

Checked 107 installs across 153 packages (no changes) [74.00ms]
[4/1238] install /workspace/bun/packages/bun-error
bun install v1.4.0-canary.1 (eabb96d)

Checked 1 install across 2 packages (no changes) [4.00ms]
[5/1238] fetch zlib
[zlib] up to date
[6/1238] gen .bind.ts → GeneratedBindings.cpp
[7/1238] fetch tinycc
[tinycc] up to date
[8/1237] fetch libjpeg-turbo
[libjpeg-turbo] up to date
[9/1237] install /workspace/bun/src/node-fallbacks
bun install v1.4.0-canary.1 (eabb96d)

Checked 129 installs across 147 packages (no changes) [55.00ms]
[10/1237] subst deps/zlib/zconf.h
[11/1237] subst deps/zlib/zlib.h
[12/1188] gen JSEvent.lut.h
Generating /workspace/bun/build/release/codegen/JSEvent.lut.h from /workspace/bun/src/jsc/
... (truncated)
```

</details>

<details><summary>diff hotspot</summary>

```
src/bun_core/string/immutable/unicode.rs         |  17 +--
 src/runtime/webcore/TextEncoderStreamEncoder.rs  |  49 ++++---
 test/js/web/encoding/text-encoder-stream.test.ts | 163 ++++++++++++++++++++++-
 3 files changed, 195 insertions(+), 34 deletions(-)
```

</details>

**gate history** · 1 passed · 0 rejected · iteration 0

<details><summary>evidence per changed file</summary>

```
file                                              reads  edits  tests
src/bun_core/string/immutable/unicode.rs              5      5      0
src/runtime/webcore/TextEncoderStreamEncoder.rs       4     11      0
test/js/web/encoding/text-encoder-stream.test.ts      3      7      0
```

</details>

<!-- robobun:evidence:end -->

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant