Skip to content

Upgrade WebKit to 5488984d: fix require(ESM) diamond-dep deadlock#30527

Merged
Jarred-Sumner merged 6 commits into
mainfrom
claude/webkit-upgrade-2b6b1c39
May 12, 2026
Merged

Upgrade WebKit to 5488984d: fix require(ESM) diamond-dep deadlock#30527
Jarred-Sumner merged 6 commits into
mainfrom
claude/webkit-upgrade-2b6b1c39

Conversation

@alii

@alii alii commented May 12, 2026

Copy link
Copy Markdown
Member

WebKit changes (88b2f7a2 → 5488984d)

Single commit on top of the previous pin:

module-loader: don't double-fire moduleRegistryModuleSettled after inline sync replay (oven-sh/WebKit#225, rebased #217)

File: Source/JavaScriptCore/runtime/JSMicrotask.cpp

What: Adds a modulePromise->status() != Pending early-return guard to moduleRegistryModuleSettled, symmetric with the guard already present in moduleRegistryFetchSettled. Gated under #if USE(BUN_JSC_ADDITIONS).

Why: require() of an ESM whose graph contained a diamond dependency through a barrel deadlocked (release) / aborted on ASSERTION FAILED: m_status == Status::Fetching (debug). hostLoadImportedModule's synchronous-replay branch (taken when require(esm) is draining the synchronous module queue) calls fetchComplete + fulfills modulePromise inline. If a ModuleRegistryFetchSettled reaction had already run on the normal microtask queue for the same entry before sync mode was entered, it left a stale ModuleRegistryModuleSettled reaction queued there. When the normal queue later drained, that reaction re-entered fetchComplete on an already-Fetched entry.

No changes to JSType.h. No WebCore code-generator changes.


Verification:

  • test/regression/issue/30493.test.ts fails on current main (assertion crash, empty stdout)
  • ✅ Same test passes on bun run build:local with the patched WebKit
  • ✅ Same test passes on bun bd with the prebuilt preview tarball
  • ✅ Full bun CI green against autobuild-preview-pr-225-2b6b1c39 (build #53556 — 67 pass, 3 pre-existing main flakes also red on publish: add --provenance (npm provenance via Sigstore keyless signing) #30522)

Fixes #30493
Fixes #30281
Closes #30283 (the dependency-free 6-file repro in this PR covers the same root cause without needing a react+MUI install)

…0493, #30281)

Bumps WebKit to oven-sh/WebKit#225 (rebased #217 — adds the
modulePromise->status() != Pending guard to moduleRegistryModuleSettled).

require() of an ESM module whose graph contained a diamond dependency
through a barrel deadlocked (release) / aborted on `m_status == Fetching`
(debug). Regressed by the require(esm) sync-replay path; root cause was
moduleRegistryModuleSettled firing twice for the same entry when
hostLoadImportedModule's synchronous-replay branch had already driven
fetchComplete inline while a stale normal-queue reaction was pending.

WEBKIT_VERSION temporarily points at the preview-PR autobuild tag so CI
can validate against the patched WebKit before #225 merges; will switch
to the real sha before this lands.

Fixes #30493
Fixes #30281
@robobun

robobun commented May 12, 2026

Copy link
Copy Markdown
Collaborator
Updated 8:15 PM PT - May 11th, 2026

@robobun, your commit 95258bf has 1 failures in Build #53572 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 30527

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

bun-30527 --bun

@github-actions

Copy link
Copy Markdown
Contributor

Found 1 issue this PR may fix:

  1. bun hangs on repeated dynamic imports of a file with invalid contents #23139 - Hang on repeated dynamic imports of a file with invalid contents matches the stale microtask reaction bug in moduleRegistryModuleSettled — the second import() re-enters settlement on an already-rejected module promise

If this is helpful, copy the block below into the PR description to auto-close this issue on merge.

Fixes #23139

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

@alii alii changed the title Upgrade WebKit to 2b6b1c39: fix require(ESM) diamond-dep deadlock Upgrade WebKit to 5488984d: fix require(ESM) diamond-dep deadlock May 12, 2026
@alii alii marked this pull request as ready for review May 12, 2026 01:51
@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2fbefb5f-479a-4b70-b3d3-6464e6795618

📥 Commits

Reviewing files that changed from the base of the PR and between 28e69e2 and 95258bf.

📒 Files selected for processing (1)
  • test/regression/issue/30493.test.ts

Walkthrough

Bumps the WebKit dependency commit hash used by the build script and adds a regression test that spawns Bun to require() an ESM diamond dependency graph, asserting the process completes successfully and produces the expected output without assertion failures.

Changes

Fix require() deadlock in diamond dependency graph

Layer / File(s) Summary
WebKit version update
scripts/build/deps/webkit.ts
WEBKIT_VERSION updated to a new commit hash, changing the WebKit prebuilt/tag identity used by the build scripts.
Regression test for diamond dependency deadlock
test/regression/issue/30493.test.ts
Adds a regression test that constructs a temporary ESM module graph and runs a CommonJS entry via bun (spawn with timeout) to ensure require() of the ESM graph completes without deadlocking, asserts expected stdout snapshot, normal exit, and absence of "ASSERTION FAILED" on stderr.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Upgrade WebKit to 5488984d: fix require(ESM) diamond-dep deadlock' clearly and specifically summarizes the main change: a WebKit version upgrade addressing a specific require(ESM) deadlock bug.
Description check ✅ Passed The PR description is comprehensive and well-structured. It covers the WebKit version change (commit hash), explains the specific fix (moduleRegistryModuleSettled guard), provides the rationale (diamond dependency deadlock scenario), and includes verification details (test status and CI results).
Linked Issues check ✅ Passed All code changes align with linked issues: WebKit version update (5488984d) addresses deadlock in #30493 and abort in #30281, and the regression test file covers both the diamond dependency case and the react+MUI scenario.
Out of Scope Changes check ✅ Passed All changes are in scope: the WebKit version bump fixes the core issue, and the regression test directly validates the fix for the reported problems without introducing unrelated modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/regression/issue/30493.test.ts`:
- Around line 44-48: Remove the in-test watchdog: delete the
KILL_SIGNAL/KILL_AFTER_MS constants, the setTimeout that assigns to killer, the
proc.kill(...) call, and the clearTimeout(killer); instead rely on awaiting the
process condition with the existing Promise.all([proc.stdout.text(),
proc.stderr.text(), proc.exited]) and the test runner's timeout; specifically
remove the lines that create/clear killer and the call to proc.kill so the test
no longer uses a timing-based watchdog.
- Line 51: Remove the panic-style negative assertion
expect(stderr).not.toContain("ASSERTION FAILED") from the test; locate the
assertion in test/regression/issue/30493.test.ts (the exact statement
expect(stderr).not.toContain("ASSERTION FAILED")) and delete it so the test
relies on existing exit/signal or explicit failure checks instead of checking
for absence of a panic string.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c10f1f76-18b1-4427-a58a-e37d87126539

📥 Commits

Reviewing files that changed from the base of the PR and between 37bfbed and 7c5a59d.

📒 Files selected for processing (2)
  • scripts/build/deps/webkit.ts
  • test/regression/issue/30493.test.ts

Comment thread test/regression/issue/30493.test.ts Outdated
Comment thread test/regression/issue/30493.test.ts Outdated
Comment thread test/regression/issue/30493.test.ts Outdated
Comment thread test/regression/issue/30493.test.ts Outdated
@alii

alii commented May 12, 2026

Copy link
Copy Markdown
Member Author

@robobun adopt

@robobun

robobun commented May 12, 2026

Copy link
Copy Markdown
Collaborator

✅ Adopted — diff is green, ready to merge modulo a pre-existing Windows flake.

What changed since @robobun adopt:

CI (#53572 → retrigger → #53577):

  • test/regression/issue/30493.test.ts passes on every lane, both runs.
  • Only hard failure on both runs is test/js/bun/test/parallel/test-http-should-emit-close-when-connection-is-aborted.ts timing out on Windows — a node:http + AbortController test with no relation to module loading. The identical failure (same 3 Windows lanes) is on unrelated-branch build #53561 (farm/9555d6db/minimum-release-age-defaul), so it's not caused by this WebKit bump.
  • Remaining annotations are retried-and-passed flakes (jsc-stress mprotect, hot.test.ts sourcemap race, fetch-http2-client AtomStringImpl — all also present on #53561/#53552).

Needs a maintainer to merge past the Windows flake.

- Replace manual setTimeout/clearTimeout with Bun.spawn's native timeout
  option (matches spawn-pipe-read-error-leak.test.ts pattern).
- Drop the negative 'ASSERTION FAILED' stderr check; stdout snapshot +
  signalCode + exitCode cover both the abort and deadlock failure modes.
- Fix stale comment: 30281.test.ts was never landed (this test subsumes
  the react+MUI repro from #30283), and the fix is WebKit#225 not #217.

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/regression/issue/30493.test.ts`:
- Around line 18-51: The test uses a 10_000ms subprocess timeout (see Bun.spawn
timeout: 10_000) but relies on the test runner's default (5_000ms), so add an
explicit test timeout greater than the subprocess timeout so the test process
can finish and assertions on proc.signalCode/exitCode run; update the test
declaration (the test("require() of ESM with diamond dependency through barrel
does not deadlock", ...)) to specify a larger timeout (e.g. 20_000) or call the
global runner timeout helper (e.g. jest.setTimeout(20000)) before spawning the
subprocess.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c074803a-cc06-4ac9-a5ed-9f1ba0651f4a

📥 Commits

Reviewing files that changed from the base of the PR and between 7c5a59d and 28e69e2.

📒 Files selected for processing (1)
  • test/regression/issue/30493.test.ts

Comment thread test/regression/issue/30493.test.ts Outdated
Local `bun test` defaults to 5s per-test, which would mask the 10s
subprocess timeout in the (future-regression) deadlock case. CI already
passes --timeout=90000 so this only affects local runs.
Comment thread test/regression/issue/30493.test.ts
@Jarred-Sumner Jarred-Sumner merged commit 2043f9c into main May 12, 2026
74 of 76 checks passed
@Jarred-Sumner Jarred-Sumner deleted the claude/webkit-upgrade-2b6b1c39 branch May 12, 2026 04:00
alii added a commit that referenced this pull request May 12, 2026
… module no longer hangs (#30537)

A second `await import()` of a path whose first import threw used to
hang forever instead of re-throwing. Two reported variants:

- **#23139**: same path twice
- **#22743**: path X, then a *different* error path Y, then X again
(true regression, 1.2.20 → 1.2.21)

While verifying #30527 I checked whether oven-sh/WebKit#225 covered
these — turns out both were **already fixed** before that bump (main +
WebKit `88b2f7a2` doesn't hang either). The fix landed somewhere in the
module-loader rewrite window (#29393#30262); the issues just never
got re-tested.

| build | #23139 | #22743 |
|---|---|---|
| 1.3.13 | hangs | hangs |
| main + WebKit `88b2f7a2` (pre-#30527) | ✅ | ✅ |
| main + WebKit `5488984d` | ✅ | ✅ |

Both tests fail on `USE_SYSTEM_BUN=1` (stdout missing the post-hang
lines, killed by spawn timeout) and pass on `bun bd test`.

Fixes #23139
Fixes #22743
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants