Skip to content

Bump WebKit: bun build --bytecode builds a function whose jump sizes take 16 passes to settle - #45827

Draft
robobun wants to merge 6 commits into
mainfrom
robobun/4e01407e/bytecode-optimizer-relaxation
Draft

robobun wants to merge 6 commits into
mainfrom
robobun/4e01407e/bytecode-optimizer-relaxation

Conversation

@robobun

@robobun robobun commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #44926

Problem

  • bun build --bytecode aborts on @google-cloud/tasks 7.2.1 with panic(main thread): abort() called. --no-optimize-bytecode avoids it.
  • The bytecode optimizer re-emits a function until a pass repeats the previous pass's jump offsets, then runs one more pass and asserts that nothing moved. At iteration 16 it also forces every branch wide. When offsets settle at iteration 15, the extra pass is iteration 16, so the forced widening runs in it and the assertion fails.

Fix

Test

  • test/bundler/bun-build-compile.test.ts generates functions in which each branch jumps over some padding and the next branch. With the right padding a branch's offset fits in 8 bits only until the next branch is widened, so each pass widens one more branch and the number of branches sets the number of passes.
  • It sweeps 13 to 17 branches and 36 to 42 padding statements, builds them with --bytecode, and runs the output from the bytecode cache. Without the fix the function with 15 branches and 39 padding statements aborts the build.

Verified

Two release builds of Bun for Linux x64 from CI, both on WebKit with oven-sh/WebKit#860: one without the fix (WebKit 5e3554fa) and one with it (the preview build of oven-sh/WebKit#807, the same tree as 5cfcac0f).

without the fix with the fix
The issue's command, bun build index.ts --compile --bytecode --format=esm --outfile=app, on @google-cloud/tasks 7.2.1 exit 134, panic(main thread): abort() called exit 0, 359 modules
The new test fails, the build exits 134 passes in 77 ms

Downsides

  • None found.

… pass

oven-sh/WebKit#807 fixes an abort in bun build --bytecode on a function whose
jump-size relaxation settles at the pass where the optimizer forces every
branch wide. This points WEBKIT_VERSION at its preview build and adds a test
with the reduced fixture.
@coderabbitai

coderabbitai Bot commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 4 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: oven-sh/bun/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: b094637a-98ed-4d2e-a0d0-4eb6646e023c
📥 Commits

Reviewing files that changed from the base of the PR and between fd539ca and 6a5b6be.

📒 Files selected for processing: 2
  • scripts/build/deps/webkit.ts
  • test/bundler/bun-build-compile.test.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@robobun

robobun commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 5:20 AM PT - Oct 22nd, 2026

❌ @dylan-conway, your commit deddd94 has 4 failures in Build #130729 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 45827

That installs a local version of the PR into your bun-45827 executable, so you can run:

bun-45827 --bun

@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.

Findings marked 🟡 are optional suggestions and need no follow-up push.

Comment thread scripts/build/deps/webkit.ts Outdated
* From https://github.com/oven-sh/WebKit releases.
*/
export const WEBKIT_VERSION = "87ee10da087b63e011bd1ada64d1814a850a4395";
export const WEBKIT_VERSION = "autobuild-preview-pr-807-cc56b17b";

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.

🔴 Every CI and local prebuilt build of bun will fail with an HTTP 404 the moment oven-sh/WebKit PR #807 merges or closes, and this commit can never be built again. WEBKIT_VERSION at scripts/build/deps/webkit.ts:6 is an autobuild-preview-pr-* tag; scripts/build/download.ts:320-321 states GitHub deletes that release on merge or close. The repo rule in .claude/docs/landing-prs.md:47 is to never merge a pin to a preview tag. Fix: before merging, land oven-sh/WebKit#807 and set WEBKIT_VERSION to the merge commit's 40-hex sha (or autobuild-<sha>), after confirming the prebuilt tarball exists for every os x arch x flavor suffix prebuiltUrl() can emit. The PR text says the pin moves later; that step must happen in this PR, not after.

Why this was flagged

The pin at scripts/build/deps/webkit.ts:6 is "autobuild-preview-pr-807-cc56b17b". prebuiltUrl() at scripts/build/deps/webkit.ts:81-82 uses it verbatim as the GitHub release tag for every prebuilt download, which is the default mode for bun bd and for CI's ci-build profile (scripts/build/CLAUDE.md line 180). scripts/build/download.ts:319-321 documents that GitHub deletes autobuild-preview-pr-* releases when the WebKit PR merges or closes, so every build then throws the BuildError at download.ts:329 ("WebKit preview release is gone"). On the base branch the pin is a 40-hex sha whose autobuild-<sha> release is permanent. .claude/commands/upgrade-webkit.md:34 and .claude/docs/landing-prs.md:47 both require swapping to the merged sha before the bun PR merges; the PR description instead defers that to after merge, leaving a window where main does not build and leaving this commit permanently unbuildable for bisects. No code path in the repo re-resolves a deleted preview tag to the merged sha.

Verification: scripts/build/deps/webkit.ts:6 sets WEBKIT_VERSION to the preview tag autobuild-preview-pr-807-cc56b17b (was a 40-hex sha on the base); webkit.ts:80-82 uses it verbatim as the GitHub release for every prebuilt download. scripts/build/download.ts:318-338 states GitHub deletes the preview release when the PR merges or closes, so every build 404s at once. Nothing in the repo enforces the swap before merge.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed, the preview tag must not merge. The PR is a draft until oven-sh/WebKit#807 lands. Then the pin moves to the merge commit's sha in this PR, before it leaves draft.

Comment thread test/bundler/bun-build-compile.test.ts Outdated
Comment thread test/bundler/bun-build-compile.test.ts Outdated
@robobun
robobun marked this pull request as draft October 19, 2026 14:50

@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.

Code review found no new issues

No new issues were found in this update; 1 finding from earlier reviews is still open above.

Still open from earlier reviews (1):

  • 🔴 scripts/build/deps/webkit.ts:6 — Every CI and local prebuilt build of bun will fail with an HTTP 404 the moment oven-sh/WebKit PR #807 merges or closes,…

If you have decided not to act on one of these findings, resolve its thread (a reply alone leaves it open) and the next review stops counting it. To review this commit again now, use Re-run on its "Claude Code Review" check.

Jarred-Sumner added a commit that referenced this pull request Oct 21, 2026
…6270)

### What does this PR do?

Hardening follow-up to #46021. It fixes regressions from #46021 and
#44618 that were never released, includes more of the open pull requests
that fix a crash, and fixes a few crashes that had no pull request.

#### Regressions fixed (none was released)

- `spyOn(Bun, "$")`, and the same for `"sql"`, `"postgres"` and `"SQL"`,
threw "does not support accessor properties yet".
- Async `fs.read`, `fs.write` and `zlib.brotliCompress` on a view over a
`WebAssembly.Memory` could lose data or copy far more than they needed.
- `node:vm` with `vm.constants.DONT_CONTEXTIFY`: `this` in host
accessors, prototype handling, `util.types.isProxy`, `Bun.deepEquals`,
`assert.deepEqual` and `console.log` of a context.
- `zlib` `stream.flush()` threw for arguments it used to accept, and
streams had a new enumerable property.
- `Bun.Transpiler` `exports.replace` with the name `"default"`.
- `process.env.X = 3000` could store the number once the function was
JIT-compiled.
- `node:sqlite` and `bun:sqlite` could lose rows at exit.
- Dev server: stylesheets shared between pages after a build error.
- Shell `cp` of a file onto itself exited 1.
- `error.stack`: the frame of `require()` reads `at anonymous (unknown)`
again.
- `import * as process from "process"` followed by `process.on(...)`
threw at load. The EventEmitter methods that the module exports now act
on `process`.
- `delete res.statusCode; res.end()` in a `node:http` handler threw. It
sends 200, as in Node. (from #46128)
- `node:tls`, `node:https` and `node:http2`: connection teardown and
write callbacks behave as in 1.4.3 and Node again.

#### Crash fixes

Bundler, parser and CSS: #42286, #46092, #46097, #46177, #46239, #36334,
#43024, #40769.
`bun test`, `--hot` and `--watch`: #30776, #38206, #38974.
Shell: #43183, #37743, #46168, #46207, #34900.
`node:http`, `node:http2`, `Bun.serve`, streams: #43449, #45380, #44457,
#42197, #42485, #38082, #38124, #46074, #45999, #46045.
`node:vm`, native addons, workers: #46129, #46198, #45615, #33412,
#38031.
Dev server: #42790, #42850, #39488.
Other: #35991, #38030, #38586, #40526, #41830, #46029, #46078, #46114,
and the bug of #42215.

#### Behavior changes

- `crypto.randomFill(view, cb)` reports `ERR_CRYPTO_OPERATION_FAILED` if
it could not fill the view. It used to report success.
- A function registered twice on `process` runs twice, as in Node.
(#41830)
- Under `--hot`, a reload after an uncaught exception cancels the timers
that the failed run created. The new run's timers fire, and so do timers
and `fs.watchFile` watchers that earlier runs kept on `globalThis`. The
reload also resets the exit code to 0. (#38206)
- The parent of a Worker no longer gets an `'error'` event for a failed
`Bun.serve` request in that Worker. The error is printed, as on the main
thread.
- `hash.write()` after `digest()` drops the chunk, as in Node. (#35991)
- `http2` over TLS with `server.emit("connection", socket)`:
`session.socket` is a `TLSSocket` and a `'connection'` listener fires,
as in Node. (#38124)
- A `slice()` with no type of a body `Blob` has `type === ""`, as in
Node. (#46114)
- `util.types.isProxy(globalThis)` is false, as in Node.
- A write on a `node:net` or `node:tls` socket that is still pending
when the connection closes calls back with `ECANCELED`, as in Node.
- `HTMLRewriter.on()` throws for a selector that is nested too deeply.
- `Bun.Image`: `maxPixels` also bounds PNG metadata, `metadata()` of a
GIF reports the size that gets decoded, and a path with a NUL byte
throws. (#40526)
- `bun build --no-bundle` with the `base64` or `dataurl` loader prints
an error. (#36334)
- Bundled output for a default-exported function or class expression
changes to `var file_default = function name() {}`, as in esbuild.
`.name` is unchanged. (#46097)
- A Proxy in the prototype chain of a `node:vm` global is allowed. jsdom
30 with `runScripts` needs this.
- `bun:sqlite` commits a write that `iterate()` left open when the main
thread exits. An explicit `BEGIN` is still rolled back.
- When a Worker stops while a native addon's async work is still
running, the addon's finalizers run after that work is done, as in Node.
- Shell: `mv -n` and `cp -n` don't overwrite, and `cp` reads `R`, `v`
and `n` anywhere in a flag group.

#### Performance

- Ordinary `node:vm` contexts run at the same speed. With
`DONT_CONTEXTIFY`, stores to globals and reads of inherited names in a
hot loop cost 10 to 20 % more than on `main`.
- A `process.env` write costs 20 to 35 % less than after #46021.
- An async read into a `WebAssembly.Memory` view looks through the live
memories: about 1.5 µs more with one memory.

#### Not included

- Taken in part, so these should stay open for the rest: #36334, #38974,
#39488, #40526, #40769, #42485, #45615, #45999, #46029, #46092, #46114,
#46168, #46207, #46239.
- Needs a WebKit change: #34655 #39204 #40170 #40253 #41587 #41900
#42699 #42897 #42903 #43084 #43813 #44518 #44949 #45770 #45804 #45827.
- #44723 (covered by #46097), #41675, #42753, #38762, #41475, #46016.

### How did you verify your code works?

- Every item was reproduced first on release builds of `main`, of its
parent and of 1.4.3, and compared with Node v26 where Node has the API.
- Every fix has a test that fails on `main` and passes on a debug + ASAN
build of this branch, except where that isn't practical (huge inputs,
code that only runs on Windows or macOS).
- The regressions were checked on grids of calls against the build
before #46021 and against 1.4.3.
- Bun's own test suites and Node's `test-vm-*`, `test-http2-*` and
`test-zlib-*` files for the areas touched.
@dylan-conway dylan-conway changed the title Bump WebKit: the bytecode optimizer keeps the first stable relaxation pass Bump WebKit: bun build --bytecode builds a function whose jump sizes take 16 passes to settle Oct 22, 2026

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.

Bun 1.4.3 ESM bytecode optimizer aborts compiling @google-cloud/tasks 7.2.1 (2-line repro)

2 participants