Skip to content

Upgrade WebKit to 456cd04b8d5be123bd451f2c007b97dbb3ffed57#29161

Open
sosukesuzuki wants to merge 4 commits intomainfrom
claude/webkit-upgrade-456cd04b8d5b
Open

Upgrade WebKit to 456cd04b8d5be123bd451f2c007b97dbb3ffed57#29161
sosukesuzuki wants to merge 4 commits intomainfrom
claude/webkit-upgrade-456cd04b8d5b

Conversation

@sosukesuzuki
Copy link
Copy Markdown
Contributor

WebKit Upgrade: c2010c47d12c → d924138e38f4

Merged 1316 upstream commits (306 touching JSC/WTF/bmalloc).

API Changes Affecting Bun

Change Impact
JSObject::globalObject()realm() (7d4583947a7b "Realm-less Objects") All call sites that fetch a cell's global must use realm(). Bun's JSPromise.cpp InternalPromise check and JSWebAssembly.cpp updated.
MarkedJSValueRefArrayMarkedVector<JSValueRef> testapi only; no Bun runtime impact.
JSCell::type()/indexingType*() now defined inline in JSCell.h (6eaeb2be1205) Bun's JS_EXPORT_PRIVATE on type() dropped — symbol no longer needed since definition is header-inline.
Heap::hasHeapAccess()/worldIsStopped() moved from HeapInlines.hHeap.h Bun's commented-out isMarked block kept; duplicate inline defs removed.
NODELETE annotations adopted widely (61dfe117a295) Merged with Bun's JS_EXPORT_PRIVATE additions where both apply.
GCMemoryOperations.h rewritten (7a412e324d10 "wider bulk copy") Upstream now has #if !OS(WINDOWS) guard around .p2align, superseding Bun's separate Windows-ARM64 SEH workaround. Took upstream wholesale.
WTF_MAKE_TZONE_ALLOCATED_IMPL(ScheduledTask) added in RunLoopGeneric.cpp Integrated above Bun's USE(BUN_EVENT_LOOP) constructor.
OSAllocatorPOSIX.cpp: Linux PR_SET_VMA memory tagging (b651d820ecaa) Added alongside Bun's Darwin BUN_VM_CHILD_PROCESS_INHERIT defines; dropped Bun's file-wide WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN (upstream now uses targeted scopes).
trunc/isnanstd::trunc/std::isnan (aaf28d392ef7) Propagated to Bun-relocated copies in JSCJSValueInlines.h.
JSCell::toThis removed upstream Bun's stale JS_EXPORT_PRIVATE declaration dropped (no implementation existed).
MarkedVector::set(i, v) removed Bun's NodeHTTPParser.cpp switched to args.at(i) = v. MarkedArgumentBuffer iterator now yields JSValue (not EncodedJSValue) — JSBundlerPlugin.cpp updated.
Vector(size, val) / FixedVector(size, val) now require WTF::FillWith{} tag (22a4dd063a31) BunHeapProfiler.cpp, InternalFieldObject.h, WebSocket.cpp updated.
String::characterAt()codeUnitAt() (e4f1bb7dd2dc) bindings.cpp, NodeModuleModule.cpp updated.
RootMarkReason::MarkedJSValueRefArray enum value removed BunV8HeapSnapshotBuilder.cpp switch case dropped.
InlineCacheHandler.h new transitive include of InlineCacheCompiler.h Added to PRIVATE_FRAMEWORK_HEADERS in JSC CMakeLists.txt.

Compatibility Shim Added (oven-sh/WebKit only)

JSObject::globalObject() and Structure::globalObject() were re-introduced under USE(BUN_JSC_ADDITIONS) as inline aliases of realmMayBeNull() / realm(). This avoids a 300+-call-site rename across Bun's bindings and codegen templates in this PR; the alias preserves the pre-rename nullable semantics. Migration to realm() can be done incrementally.

Notable JSC Commits

Performance

  • da43fc766f60 — ArrayLengthStore IC for array.length = N
  • 3ba3be2ff84e — IC for property keys undefined/true/false/null
  • 7aea7dd35f02 — Fold string length in DFG/FTL
  • 47263c1fcdf7 — toUpperCase intrinsic
  • 3a21b7550526 — String#indexOf one-char fast path in DFG/FTL
  • 6276c6b5f2b9 — Remove redundant mov in await/yield bytecode
  • 7d5f97e8a6c0 — Persist FunctionExecutable singleton invalidation
  • 7ba657c06781 — Cache default date formatters
  • f977b7aa6f76 — Refine clobberize for CheckPrivateBrand/SetPrivateBrand
  • 7a412e324d10 — Wider bulk copy in GC-safe memcpy/memmove
  • 65b433087d28 — Reserve/inline-capacity for JSC vectors
  • 85a8086c469f — SIMD-accelerate equalIgnoringASCIICase*
  • 72a6facdf6de — makeLatin1Identifier in parseString SIMD fast path

Correctness / Bugfixes

  • 24d4993f2796 — RegExp exec/test reload internal RegExp after ToLength(lastIndex)
  • 291f0457787d — DFG constant folding: handle TOP in CheckIsConstant
  • 83895848013f — isWithinPowerOfTwo unsound for BitAnd w/ negative mask
  • c3f07df74de4 — Propagate InstanceFieldEvalContext through arrows/nested scopes
  • 46479ddbd5e6 — import { "*" as x } not treated as namespace import
  • 6117e70109ac — TypedArray iterator-next-with-detached test262 fix
  • c16330f64843 — Date.toLocaleString() ICU crash from Worker
  • 036d2c0c8216 / 8c10428db1b8 / c4f242d634ec / f30b516527da — YARR backtracking/capture fixes

New Features

  • 7fdc018c4dd7 — Iterator.prototype.includes (behind flag)
  • 6de094278d71 — JSPI: WebAssembly.Suspending/SuspendError as data properties

Wasm

  • f9c6e4889485 — IPInt support for SIMD and atomics
  • 12997e819ca5 — Multimemory in BBQ/OMG SIMD/atomics
  • 599f35b67143 — Stack results match arguments
  • 7900f4775411 — OMG bounds check uses AboveEqual
  • Multiple Wasm-debugger improvements (LLDB integration, dynamic-module notify, exception interception)

WTF / bmalloc

  • e4f1bb7dd2dc — characterAt()/characterStartingAt()codeUnitAt()/codePointAt()
  • 0655a1df8268 — WTF::Unexpectedstd::unexpected
  • 41539422d60f — Removed ~9% of #includes from WTF
  • 75529ed6e070 — libpas: fix CSE of atomic-load under concurrent modification
  • 569d28c26a9b — libpas: MTE Previous-Tag-Exclusion
  • 83b6ec32bc25 — StringImpl::create (UTF-8) defensive against concurrent mutation
  • b7ac868d7113 / 2b9732f54c5e — = default constructor adoption
  • 3242d3d821c5 — roundUpToPowerOfTwo() no longer truncates to uint32_t

Merge Conflict Resolutions

28 conflicts. Patterns:

  • Include style "X.h"<JavaScriptCore/X.h> — adopted upstream bracket style (BlockDirectory.h, MarkedBlock.h, StrongInlines.h, Integrity.h, InPlaceInterpreter.h, WasmDebugServerUtilities.h, WebAssemblyGCStructure.h).
  • NODELETE × Bun's JS_EXPORT_PRIVATE/additions — combined both (MarkingConstraint.h, JSCell.h, VMManager.h, Nodes.h, SourceProvider.h, LiteralParser.h, CachedTypes.cpp, ExceptionHelpers.cpp, NodesCodegen.cpp, Options.cpp).
  • Heap.cpp — Bun intentionally removes growthMode/maxEdenSizeForRateLimiting (rate-limiting) and de-statics heap-sizing helpers; kept Bun's behavior, dropped upstream's NODELETE on the removed functions.
  • GCMemoryOperations.h — upstream rewrite supersedes Bun's Windows-ARM64 patches; took theirs.
  • JSCJSValue.h — upstream re-touched inline funcs Bun had moved to JSCJSValueInlines.h; kept Bun's relocation, ported std:: qualification fix.
  • JSPromise.cpp / JSWebAssembly.cpp — adopted realm() rename; kept Bun's InternalPromise short-circuit.
  • RunLoopGeneric.cpp — added WTF_MAKE_TZONE_ALLOCATED_IMPL before Bun's USE(BUN_EVENT_LOOP) ctor.
  • OSAllocatorPOSIX.cpp — kept both Bun's Darwin defines and upstream's Linux prctl block; dropped redundant file-wide unsafe-buffer wrap.
  • PlatformMac.cmakeplatform/mac/StringUtilities.h removed upstream (moved to platform/cocoa/).

Checks

  • JSType.h: no upstream changes — src/bun.js/bindings/JSType.zig still in sync.
  • WebCore bindings code generator: no relevant changes detected.

Adapt to JSC API changes from upstream d924138e38f4:
- String::characterAt -> codeUnitAt (bindings.cpp, NodeModuleModule.cpp)
- Vector/FixedVector(size, val) -> (FillWith{}, size, val) tag
  (BunHeapProfiler.cpp, v8/shim/InternalFieldObject.h, WebSocket.cpp)
- MarkedVector::set() removed -> at() = (NodeHTTPParser.cpp)
- MarkedArgumentBuffer iterator yields JSValue (JSBundlerPlugin.cpp)

JSObject::globalObject() retained as BUN_JSC_ADDITIONS alias for realm()
in the WebKit fork; no mass-rename required here.
@robobun
Copy link
Copy Markdown
Collaborator

robobun commented Apr 11, 2026

Updated 9:55 AM PT - Apr 11th, 2026

@sosukesuzuki, your commit 0293909 has 2 failures in Build #45082 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 29161

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

bun-29161 --bun

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 11, 2026

Walkthrough

Updates the pinned WebKit commit and modernizes several C++ bindings: vector initializations use WTF::FillWith{}, string inspections switch from characterAt() to codeUnitAt(), promise handling casts directly to JSPromise*, and HTTP callback arg writes use indexed assignment. No public APIs changed.

Changes

Cohort / File(s) Summary
WebKit Version Update
scripts/build/deps/webkit.ts
Updated WEBKIT_VERSION constant from c2010c47d12c525d36adabe3a17b2eb6ec85096042f80a684c5df57121a97e20825a3bcab7a0741b, affecting prebuilt release tag and cache destination computation.
Vector Initialization Modernization
src/bun.js/bindings/BunHeapProfiler.cpp, src/bun.js/bindings/v8/shim/InternalFieldObject.h
Replaced fill-constructor vector initializations with explicit WTF::FillWith{} forms to control value-initialization of fixed-size containers.
String Code Unit Access
src/bun.js/bindings/bindings.cpp, src/bun.js/modules/NodeModuleModule.cpp
Switched string separator/character checks from characterAt() to codeUnitAt() to operate on UTF-16 code units during path parsing and module lookup logic.
Binding Callback/Promise Handling
src/bun.js/bindings/JSBundlerPlugin.cpp, src/bun.js/bindings/node/http/NodeHTTPParser.cpp
Changed deferred promise processing to cast values directly to JSPromise*, and replaced MarkedArgumentBuffer::set(...) calls with indexed assignments (args.at(index) = value) when populating HTTP callback arguments.
WebSocket Protocol Handling
src/bun.js/bindings/webcore/WebSocket.cpp
Adjusted single-protocol WebSocket::create/connect overloads to pass a single-element Vector<String> (removed an extra leading element) for subprotocol negotiation.
🚥 Pre-merge checks | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title references a WebKit commit hash that does not appear in the PR description (456cd04b8d5be123bd451f2c007b97dbb3ffed57), while the actual upgrade documented is from c2010c47d12c to d924138e38f4 or 42f80a684c5df57121a97e20825a3bcab7a0741b. Update the PR title to reflect the actual WebKit version being upgraded to (e.g., 'Upgrade WebKit to 42f80a684c5df57121a97e20825a3bcab7a0741b') for clarity and consistency.

✏️ 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.

@github-actions
Copy link
Copy Markdown
Contributor

This PR may be a duplicate of:

  1. Upgrade WebKit to 5b194ac887f2 #26352 - Also upgrades WebKit (to commit 5b194ac887f2), updating the same WEBKIT_VERSION and JSC bindings
  2. Bump WebKit #26661 - Also bumps WebKit, targeting the same dependency upgrade
  3. testing webkit #27972 - WebKit testing/upgrade PR touching the same WebKit build configuration

🤖 Generated with Claude Code

Comment on lines 673 to 679
auto& vm = pluginObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
for (auto promiseValue : arguments) {
JSPromise* promise = jsCast<JSPromise*>(JSValue::decode(promiseValue));
JSPromise* promise = jsCast<JSPromise*>(promiseValue);
if (rejected) {
promise->reject(vm, globalObject, JSC::jsUndefined());
} else {
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.

🟣 Pre-existing bug: WriteBarrierList::moveTo() (WriteBarrierList.h:44-53) calls value.clear() on each entry but never calls m_list.clear(), leaving null WriteBarrier slots that accumulate over every watch-mode rebuild. The fix is to add m_list.clear() at the end of moveTo().

Extended reasoning...

What the bug is: WriteBarrierList<T>::moveTo() (WriteBarrierList.h:44–53) iterates m_list, appends non-null cells to arguments, and calls value.clear() on each entry — but never removes those entries from m_list itself. After every call, the vector retains all N slots, now holding null WriteBarrier<JSPromise> objects.

How it manifests in watch mode: Each build cycle, JSBundlerPlugin__appendDeferPromise calls deferredPromises.append(), which pushes new JSPromise entries to the end of m_list. After JSBundlerPlugin__drainDeferred calls deferredPromises.moveTo(), those entries are cleared but not removed. The next cycle appends on top of them. Over N build cycles with P deferred promises per build, m_list grows to N × P entries — unboundedly. This is an O(N) slow memory leak in long-running watch sessions.

Why existing code doesn't prevent it: The moveTo() implementation simply does not call m_list.clear() (or any shrink/compact operation) after the loop. The only removal path in this class is takeFirst(), which uses removeAt(0), and removeFirstMatching(). Neither is called during drain.

Secondary breakage — isEmpty() is always false after the first drain: isEmpty() (line 64) returns m_list.isEmpty(), which is never true once entries have been appended and cleared. Any caller checking deferredPromises.isEmpty() to guard work will get a false positive after the first build cycle.

GC overhead: The visit() traversal (line 55–62) iterates every entry in m_list regardless of whether the WriteBarrier holds a live object. After hundreds of builds, the GC visitor walks hundreds of dead null slots on each collection cycle.

Concrete proof — step by step:

  1. Build 1: 3 plugins each call defer()m_list = [WB(P1), WB(P2), WB(P3)] (size 3)
  2. drainDeferred() → each WB.clear()m_list = [WB(null), WB(null), WB(null)] (still size 3)
  3. Build 2: 3 new promises appended → m_list = [null, null, null, WB(P4), WB(P5), WB(P6)] (size 6)
  4. After drain: m_list = [null×6]
  5. After N builds: m_list has 3N null entries

How to fix: Add m_list.clear(); at the end of the moveTo() method (optionally followed by m_list.shrinkToFit() or a capacity cap to avoid keeping large allocations around). This is a three-line change in WriteBarrierList.h.

Relation to this PR: This PR directly modifies JSBundlerPlugin__drainDeferred (the sole caller of deferredPromises.moveTo()) to update the iterator value type from EncodedJSValue to JSValue following the upstream MarkedArgumentBuffer API change. The PR does not introduce or worsen the leak, but it directly touches this code path, making this a good opportunity to fix the underlying issue.

Includes follow-up CI fixes on top of the merge commit:
- 6e860391ad34: generate-unified-source-bundles.py Python 3.8 compat
- e5adfce303d1: disable NODELETE/annotate_type under clang-cl
- 4972e7d6850f + 42f80a684c5d: OFFLINE_ASM_ALIGN_TRAP_512/1024 for Windows ARM64
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@scripts/build/deps/webkit.ts`:
- Line 6: The current WEBKIT_VERSION constant (WEBKIT_VERSION) points to a
release that lacks the LTO assets (bun-webkit-windows-amd64-lto.tar.gz and
bun-webkit-macos-arm64-lto.tar.gz); fix by either rebuilding the referenced
release to include the missing LTO artifacts and republishing with the same
commit hash, or update WEBKIT_VERSION to a prior release hash that contains all
LTO variants so the build picks up complete assets; ensure the chosen
hash/version provides both bun-webkit-windows-amd64-lto.tar.gz and
bun-webkit-macos-arm64-lto.tar.gz before committing the change.
🪄 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: c13db8d1-0efc-4208-8a26-9fd395040e8e

📥 Commits

Reviewing files that changed from the base of the PR and between 67a210f and 4776017.

📒 Files selected for processing (1)
  • scripts/build/deps/webkit.ts

* From https://github.com/oven-sh/WebKit releases.
*/
export const WEBKIT_VERSION = "c2010c47d12c525d36adabe3a17b2eb6ec850960";
export const WEBKIT_VERSION = "42f80a684c5df57121a97e20825a3bcab7a0741b";
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

TAG="autobuild-42f80a684c5df57121a97e20825a3bcab7a0741b"
API="https://api.github.com/repos/oven-sh/WebKit/releases/tags/${TAG}"

json="$(curl -fsSL "$API")"

echo "Release tag:"
jq -r '.tag_name' <<<"$json"

echo
echo "Published assets:"
jq -r '.assets[].name' <<<"$json" | sort

# Sanity-check common Bun prebuilt targets.
required=(
  "bun-webkit-linux-amd64-lto.tar.gz"
  "bun-webkit-linux-amd64-musl-lto.tar.gz"
  "bun-webkit-linux-arm64-lto.tar.gz"
  "bun-webkit-linux-arm64-musl-lto.tar.gz"
  "bun-webkit-windows-amd64-lto.tar.gz"
  "bun-webkit-macos-arm64-lto.tar.gz"
)

missing=0
for a in "${required[@]}"; do
  if ! jq -r '.assets[].name' <<<"$json" | grep -Fxq "$a"; then
    echo "MISSING: $a"
    missing=1
  fi
done

if [ "$missing" -ne 0 ]; then
  echo "One or more expected assets are missing."
  exit 1
fi

echo "All required assets found."

Repository: oven-sh/bun

Length of output: 1411


Remove or rebuild WebKit release with complete LTO assets.

Release autobuild-42f80a684c5df57121a97e20825a3bcab7a0741b exists but is missing:

  • bun-webkit-windows-amd64-lto.tar.gz
  • bun-webkit-macos-arm64-lto.tar.gz

These prebuilt assets are required for LTO builds on Windows and macOS. Rebuild the release with all LTO variants or revert to a prior version with complete assets.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/build/deps/webkit.ts` at line 6, The current WEBKIT_VERSION constant
(WEBKIT_VERSION) points to a release that lacks the LTO assets
(bun-webkit-windows-amd64-lto.tar.gz and bun-webkit-macos-arm64-lto.tar.gz); fix
by either rebuilding the referenced release to include the missing LTO artifacts
and republishing with the same commit hash, or update WEBKIT_VERSION to a prior
release hash that contains all LTO variants so the build picks up complete
assets; ensure the chosen hash/version provides both
bun-webkit-windows-amd64-lto.tar.gz and bun-webkit-macos-arm64-lto.tar.gz before
committing the change.

Comment on lines +497 to 513
args.at(A_HEADERS) = headers;
if (m_parserData.type == HTTP_REQUEST) {
args.set(A_URL, m_url.toString(globalObject));
args.at(A_URL) = m_url.toString(globalObject);
}
}

m_numFields = 0;
m_numValues = 0;

if (m_parserData.type == HTTP_REQUEST) {
args.set(A_METHOD, jsNumber(m_parserData.method));
args.at(A_METHOD) = jsNumber(m_parserData.method);
}

if (m_parserData.type == HTTP_RESPONSE) {
args.set(A_STATUS_CODE, jsNumber(m_parserData.status_code));
args.set(A_STATUS_MESSAGE, m_statusMessage.toString(globalObject));
args.at(A_STATUS_CODE) = jsNumber(m_parserData.status_code);
args.at(A_STATUS_MESSAGE) = m_statusMessage.toString(globalObject);
}
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.

🟣 Pre-existing bug: in NodeHTTPParser.cpp onHeadersComplete(), the calls m_url.toString(globalObject) (HTTP_REQUEST path) and m_statusMessage.toString(globalObject) (HTTP_RESPONSE path) lack RETURN_IF_EXCEPTION(scope, -1) guards. If either call throws on OOM while allocating a JSString, execution continues with a pending VM exception and invokes profiledCall() — violating JSC's core invariant. The fix is to add RETURN_IF_EXCEPTION(scope, -1) after each toString() call; this bug predates the PR but the PR touches these exact lines.

Extended reasoning...

What the bug is and how it manifests: In NodeHTTPParser.cpp, onHeadersComplete() uses DECLARE_TOP_EXCEPTION_SCOPE. Two calls — m_url.toString(globalObject) at line 499 (HTTP_REQUEST path) and m_statusMessage.toString(globalObject) at line 512 (HTTP_RESPONSE path) — are not followed by RETURN_IF_EXCEPTION. StringPtr::toString() calls JSC::jsString(vm, WTF::String::fromUTF8(...)), which allocates a JSString on the GC heap. If that allocation fails with OutOfMemory, JSC stores a pending exception in the VM and the call returns a garbage JSValue. Without a guard, execution continues: m_numFields/m_numValues are cleared, further args slots are written, and eventually JSC::profiledCall() is invoked with a pending exception still set — which is undefined behavior in JSC and triggers assertions in debug builds.

The specific code path that triggers it: Under memory pressure, any GC heap allocation can fail with an OutOfMemoryError. In HTTP_REQUEST mode, args.at(A_URL) = m_url.toString(globalObject) stores a garbage value and sets a pending exception. Execution continues through m_numFields = 0 resets, the A_METHOD/A_VERSION_MAJOR/A_VERSION_MINOR/A_SHOULD_KEEP_ALIVE/A_UPGRADE assignments, and then hits JSC::profiledCall() at line 525 with a pending exception still live.

Why existing code does not prevent it: The DECLARE_TOP_EXCEPTION_SCOPE does NOT automatically propagate exceptions — it only asserts in debug builds that no exception is pending at scope boundaries. Protection requires manual RETURN_IF_EXCEPTION calls. Crucially, createHeaders() — called in the same function — uses RETURN_IF_EXCEPTION after every identical toString() call (m_fields[i].toString, m_values[i].toTrimmedString), confirming the codebase treats these as throwable. The omission in onHeadersComplete is an inconsistency, not a deliberate design choice.

Addressing the refutation: One verifier argued that jsString() never sets a JS exception and instead causes a hard crash on OOM. However, JSC's GC heap allocator can and does report OOM as a thrown JavaScript OutOfMemoryError — it does not always crash. The createHeaders() function in the same file guards the same toString() pattern with RETURN_IF_EXCEPTION. If jsString() truly could not throw, those guards would be harmless no-ops; their presence reflects the actual JSC semantics. The flush() function at the bottom of the file appends m_url.toString(globalObject) to args without a guard, which is the same bug.

Step-by-step proof: (1) HTTP request arrives; onHeadersComplete() is called. (2) m_haveFlushed is false, so createHeaders() succeeds and args.at(A_HEADERS) is set. (3) m_parserData.type == HTTP_REQUEST, so args.at(A_URL) = m_url.toString(globalObject) executes. (4) Under OOM, jsString() fails, sets an OutOfMemoryError on the VM, and returns a garbage JSValue — no guard catches this. (5) Execution falls through: m_numFields = 0; m_numValues = 0; args.at(A_METHOD) = jsNumber(...); additional slots filled. (6) JSC::profiledCall() is invoked with a pending exception. Debug builds ASSERT; release builds have undefined behavior.

How to fix it: Add RETURN_IF_EXCEPTION(scope, -1) immediately after args.at(A_URL) = m_url.toString(globalObject) (line 499) and after args.at(A_STATUS_MESSAGE) = m_statusMessage.toString(globalObject) (line 512). The flush() function also appends m_url.toString(globalObject) without a guard and should be fixed in the same pass.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants