Skip to content

Upgrade to upstream WebKit baf4a9a7ec0b - #488

Closed
robobun wants to merge 1237 commits into
mainfrom
bun/upgrade-to-baf4a9a7ec0b
Closed

Upgrade to upstream WebKit baf4a9a7ec0b#488
robobun wants to merge 1237 commits into
mainfrom
bun/upgrade-to-baf4a9a7ec0b

Conversation

@robobun

@robobun robobun commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

Merges upstream WebKit main at baf4a9a7ec0b (2026-08-22): 387 commits since the previous merge base 47f7250137c6 (2026-08-16), 82 of them touching JavaScriptCore, WTF or bmalloc.

#455 was squash-merged, so the fork's history no longer contains the upstream commits it merged and git merge-base origin/main upstream/main reports the older 3722912ff800. The merge was done with the squash commit grafted as a merge of its PR parents (git replace --graft e462c38dd3 a2f8782020 47f7250137c6), which gives the correct base. This merge commit has baf4a9a7ec0b as its second parent, so the next upgrade does not need the graft as long as it lands as a merge commit rather than a squash.

The fork's main moved while this PR was open (#330 DFG/FTL byte-offset accessors, #450 critical-collection headroom, #491 pending TerminationException in the microtask job). d0fae3b merges it in without conflicts; the 12 buffer-accessor-jit*.js tests pass on the merged debug build with --useDollarVM=1, and a Bun built from bun main (which needs #330) links and passes its Buffer suites against it.

Conflict resolutions

  • yarr/YarrJIT.cpp: kept at the fork's version (Yarr: JIT lookbehinds, first-code-point alternation dispatch, Boyer-Moore and /u·/v spec alignment, RegExp correctness fixes #299 policy, same as Upgrade to upstream WebKit 47f7250137c6 #455). Upstream's 01f04c4fb4 (JIT lookbehinds that contain backreferences) restructures the backreference codegen that the fork already reworked for mirrored frames; the fork compiles these patterns already. Upstream's three new tests (regexp-lookbehind-jit-backreferences.js, regexp-lookbehind-jit-backreferences-unicode.js, regexp-backreference-greedy-non-bmp-capture-restore-pos.js) pass on this build in JIT and --useRegExpJIT=false mode. 2165451fd3 (interpreter tryConsumeBackReference position restore) was already in the fork. de9231d86e (FixedVector ovector) merged cleanly.
  • WTF/URLParser.cpp and .h: kept at the fork's version. Upstream's eb44b6cfaa SIMD-scans path, query, fragment and opaque-path runs, which the fork's URLParser rewrite (0cbb4a1946, c6cfe90c60, eeab04040f) already does with its own table-driven scanners. Upstream's CodePointIterator::span()/advanceBy() additions and the two new TestWebKitAPI cases are in.
  • Atomics.wait termination (03e836de2f vs the fork's [JSC] Atomics.wait / memory.atomic.wait: wake up for a termination requested from another thread #432): WaiterListManager::waitSyncImpl keeps the fork's version (termination wake-up delivered under the waiter list lock, deferred termination respected, trap consumed and the TerminationException thrown before returning Terminated). The two callers take upstream's vm.throwTerminationExceptionIfNeeded(), which is a no-op when the exception is already pending. throwWasmToJSException's early-out for a pending TerminationException is in.
  • Module map (f324cca020): upstream no longer registers a module entry for a fetch failure and evicts a FetchFailed entry on the next loadModule. The fork's ModuleLoader: record a non-Error fetch rejection as a fetch failure #262 (setFetchError for a non-ErrorInstance fetch rejection in moduleLoadTopSettled) is dropped: that path no longer registers anything for any fetch failure, so the poisoned EvaluationFailed entry ModuleLoader: record a non-Error fetch rejection as a fetch failure #262 fixed cannot be created. Verified ModuleLoader: record a non-Error fetch rejection as a fetch failure #262's repro (import a file with a parse error, then import a file that statically imports it) completes on a Bun built against this tree. JSModuleLoader.h/.cpp: both sides' additions kept (removeFailedFetchEntry, public getRegisteredMayBeNull, the fork's registryEntry/removeEntry/clearAll/loadModuleSync).
  • CodeCache.cpp: upstream's c823243598 generates CodeForConstruct for class constructors via UnlinkedFunctionExecutable::isClassConstructorFunction(). The fork's "NOTE: We changed this in Bun" loop called isConstructor() on the UnlinkedFunctionExecutable, which resolves to JSCell::isConstructor() and is always false for a non-object cell, so it never generated anything but CodeForCall. Upstream's version replaces it. The fork's recordParseFromUnlinkedCodeBlock now takes an UnlinkedGlobalCodeBlock* because 3d0e6c14b1 moved the parse results off UnlinkedCodeBlock (follow-up commit d7ff6be).
  • CachedTypes.cpp: 3d0e6c14b1 moves m_features/m_lexicallyScopedFeatures into the new CachedGlobalCodeBlock; the fork's unsigned : N bitfields (fix: use unsigned bitfields for portable bytecode cache struct layout #141, portable layout across MSVC and Itanium) are kept for the fields that stay in CachedCodeBlock (m_parseMode, m_codeGenerationMode). The new CachedGlobalCodeBlock fields are plain (non-bitfield) members, which lay out the same on both ABIs.
  • SyntheticModuleRecord: db2d849cbe changes tryCreateWithExportNamesAndValues to take ArgList; the fork's lazy-export overloads (SyntheticModuleRecord: exports whose values are produced on first binding #408) follow. MarkedArgumentBuffer converts implicitly.
  • ThreadingPOSIX.cpp (9a18171a13, RT threads removed, per-QOS sched_setattr on Linux): the fork's !USE(BUN_JSC_ADDITIONS) main-thread detection branch keeps its guard and takes the new Thread(QOS, SchedulingPolicy, IsMain) constructor. Thread::updateSchedulingAttributes is a no-op under USE(BUN_JSC_ADDITIONS) on Linux: upstream now resets every WTF thread to SCHED_OTHER nice 0 with a 100% utilization clamp and puts JIT/Wasm compiler threads on SCHED_BATCH nice 10 when the host has 4 or fewer cores. Bun's threads keep inheriting the process's scheduling policy, nice level and clamps, as they did before this merge. Drop that hunk if following upstream is preferred. RealTimeThreads.cpp is deleted (the fork only added an include to it).
  • Options.h, JSWebAssemblyInstance.h: upstream's new includes (OSCheck.h, WasmLimits.h, <wtf/BitSet.h>) added in the fork's quoted-include style.
  • JSType.h, .github/workflows and the release tarball names are unchanged. PromiseOperations.js is gone upstream (see 38027ff0ec below): Bun's six $newPromiseCapability call sites move to $newPromise() plus $resolvePromise/$rejectPromise (or the ...WithFirstResolvingFunctionCallCheck variants) in the Bun PR.

Verification

  • bun run jsc:build:debug (Linux x64, debug + ASAN): builds, jsc shell runs.
  • JSTests: the 464 regexp*/string-*/yarr* stress tests (including the three regexp tests upstream added in this range), each in JIT and --useRegExpJIT=false mode: 890 of 928 runs pass as-is. The rest: 4 files need --useDollarVM=1 (pass with it), 2 need the --useRegExpBufferBoundaries option the fork does not have (\A/\z, same as Upgrade to upstream WebKit 47f7250137c6 #455), regexp-unicode-code-unit-read-for-bmp-terms.js is the Yarr: JIT lookbehinds, first-code-point alternation dispatch, Boyer-Moore and /u·/v spec alignment, RegExp correctness fixes #299 match-start behaviour documented in Upgrade to upstream WebKit 47f7250137c6 #455, 4 are //@ skip upstream (too-long-rope, memory hog), 1 needs the //@ runDefault(--watchdog) options (an infinite loop by design), 3 need ICU locale data the bundled libicudata only exposes through Bun's decompress hook (toLocaleString, localeCompare; they pass when run through Bun), and 2 exceed a 600 s limit under ASAN (string-substring-jit.js, string-iterator-surrogate-pairs.js: identical timings on the current pin and on this tree at a reduced loop count).
  • bun run build:local: Bun links and runs against this tree. Bun's test/js/bun/jsc, node/vm, node/module, bun/resolve, node/worker_threads, bun/wasm, node/util, node/events, node/dgram, web/url, web/atomics, node/http/node-http-connect, node/async_hooks, node/string_decoder suites: the only failures are 5-second-timeout tests, an IPv6 multicast ENODEV, and a Valkey client debug_assert that a Bun debug build on the current WebKit pin fails the same way on this (shared, debug + ASAN) machine.
  • Atomics.wait: a worker parked in Atomics.wait terminates in under 100 ms on worker.terminate().

Upstream changes

Each remaining commit appears once, under the most specific heading that applies. The 17 commits in the range whose only engine-side footprint is a WebCore/WebKit preference entry, a WTF build-file list change, or Cocoa/GTK/WPE-only code the JSCOnly port does not compile are omitted (7d86b2c8a0, 94f879afe6, 2f072fbfec, 3dfdbed8e4, 86a8860a42, 0c33544154, 722d0b38a9, cc7a6821b7, d8ad5b5f9a, b66aab8e21, 5e3cb10ac4, c2b3e55128, 2dce2395a4, d27b7fd89e, 6248fa7145, 8bd2ba0d3e, f0a1fd2b32).

API and ABI changes

  • cffd5ed032 — [API][PERF] WTF::PriorityQueue now follows std::priority_queue conventions: the template takes a less-than functor type (default std::less<T>, function pointers are rejected by static_assert) instead of an isHigherPriority function pointer and serves the greatest element first; the isLessThan/isLessThanEqual/isGreaterThan/isGreaterThanEqual helpers were removed from wtf/MathExtras.h. This fixes Wasm::Worklist, whose comparator was never flipped when it moved off std::priority_queue (present in Bun's previous WebKit): compilation plans were served in reverse priority (Preparation before Compilation before Synchronous before Shutdown) and newest-first within a priority, and completePlanSynchronously bumped the plan with decreaseKey instead of increaseKey, so synchronous WebAssembly.Module/Instance compiles could wait behind queued async work. DFG inlining, Wasm inlining and the greedy register allocator were adapted to the new convention with no change in ordering; Bun has no direct PriorityQueue usage.

  • 9a18171a13 — [API][PERF] Linux thread scheduling in WTF is reworked: the RealTimeThreads/SCHED_RR machinery is removed (wtf/linux/RealTimeThreads.h renamed to HighPriorityThreads.h, rtkit nice-boosting only under USE(GLIB)), and every WTF::Thread now applies its QOS from its own entry point via sched_setattr: the default UserInitiated QOS maps to SCHED_OTHER, nice 0 plus SCHED_FLAG_UTIL_CLAMP_MIN = 1024 (a 100% DVFS frequency floor, with automatic fallback on kernels that reject uclamp), Default gets a 20% floor, Utility gets SCHED_BATCH/nice 10 and Background gets SCHED_IDLE/nice 19. JIT and Wasm worklist threads now pass compilerThreadQOS(), which is Utility on Linux hosts with <= 4 cores, so concurrent compilation is deprioritized on small machines/containers. API surface: the protected Thread ctor is now Thread(QOS, SchedulingPolicy, IsMain), AutomaticThread gains a ThreadQOS ctor overload, Thread::qos() is added and isRealtime() is derived from the scheduling policy, and ThreadingEnums.h adds ThreadSchedulingState, defaultThreadQOS, defaultThreadSchedulingPolicy, compilerThreadQOS(); Darwin and Windows behaviour is unchanged.

  • e1fdc80a34 — [API] WTF::weekDay(int32_t days) in wtf/DateMath.h is rewritten as a branchless unsigned multiply-and-shift (Ben Joffe's method) that is well-defined for the whole int32_t range (the old (days + 4) % 7 was signed overflow for days > INT32_MAX - 4, unreachable from JS since day counts are clipped to +-1e8), and the unused WTF::msToWeekDay(double) is removed. ISO8601::dayOfWeek (Temporal PlainDate/PlainDateTime dayOfWeek) drops its private Int128 copy of the modulo and uses daysFromYearMonth + WTF::weekDay. Results are unchanged (upstream checked all 2^32 inputs); authored by Bun's Sosuke Suzuki.

  • 75a9d414a4 — [API] (additive) Correctness fix for VM::deleteAllCode / Heap::deleteAllCodeBlocks: the VM-level m_syncResumeCallCache (the MicrotaskCallCache used to resume async functions/async generators from the microtask queue) lives outside any VMEntryScope and kept stale Executable->CodeBlock entry points after all code was detached, so a later resumption could call into a detached CodeBlock. Adds MicrotaskCall::clear(), MicrotaskCallCache::clear() and public VM::clearMicrotaskCallCaches(), which Heap::deleteAllCodeBlocks now calls; CodeCache::clear() also now calls write() first. Directly relevant to Bun, which calls vm.deleteAllCode(...) in WebWorker__teardownJSCVM, JSC__VM__deleteAllCode, and via the debugger's recompileAllJSFunctions path while async work may still be pending.

  • 3302d7a455 — [PERF][API] SourceProviderCache now pre-reserves its m_map hash map from the source length (sourceLength / 512 entries, capped at 64K) to avoid repeated rehash/realloc while a large script is parsed. The public default constructor is replaced by a private explicit SourceProviderCache(unsigned sourceLength) plus static Ref<SourceProviderCache> create(unsigned); VM::addSourceProviderCache is updated. Bun only includes the header (src/jsc/modules/BunJSCModule.h) and never constructs one directly, so no Bun changes are needed.

  • 1450e69522 — [API] WTF DequeIterator and DequeConstIterator gain defaulted default constructors (required by the C++20 bidirectional_iterator concept, and by MSVC's STL std::reverse_iterator, which value-initializes its stored iterator). Purely additive; Bun's many WTF::Deque uses (streams, JSBufferList, worker queues) are unaffected and this may help MSVC-STL builds that instantiate Deque::rbegin().

  • f2d69489c6 — Removes the unused tryAllocateBuffer helper from VectorBufferBase/VectorBuffer in wtf/Vector.h; allocateBuffer<FailureAction::Report> remains for the same purpose. [API] Technically a public-header removal, but Bun's src/ has no references to it, so no action needed.

  • 03e836de2f — [BEHAVIOR] Fixes a thread blocked in Atomics.wait / Wasm memory.atomic.wait never unblocking after VM::notifyNeedTermination(): WaiterListManager::waitSyncImpl now also observes the pending NeedTermination trap (not just hasTerminationRequest()), dequeues the waiter and returns Terminated, and the new VM::throwTerminationExceptionIfNeeded() materializes the TerminationException through handleTraps. This directly affects Bun, whose VmHandle::request_termination (used by worker.terminate()) fires exactly that trap, so a worker parked in Atomics.wait now terminates instead of hanging. [API] Adds VM::throwTerminationExceptionIfNeeded(); throwWasmToJSException now early-outs whenever a TerminationException is already pending.

  • 88b46e6bc7 — [API] wtf/BorrowedBytes.h is deleted and replaced by wtf/EscapableByteSpan.h: BorrowedBytes/BorrowedSpanScope/BorrowedVectorScope are gone, replaced by a stack-only, non-refcounted EscapableByteSpan (plus escapableSpan() helper and SpanUInt8/MutableSpanUInt8/VectorUInt8 aliases) that RELEASE_ASSERTs if a copy outlives the borrow. This is a Swift-interop type used only by PAL crypto on Cocoa; Bun has no references to either header, so no impact beyond the header rename in WTF_PUBLIC_HEADERS.

  • f324cca020 — [BEHAVIOR] [API] The module loader stops caching fetch failures: JSModuleLoader::loadModule now evicts a FetchFailed registry entry (new removeFailedFetchEntry) and re-fetches instead of re-rejecting with a duplicated copy of the old error, and the top-level rejection paths in JSMicrotask.cpp no longer call ensureRegistered just to stash an error (evaluation errors are still cached; maybeDuplicateFetchError is no longer used on that path). For Bun this means a second import() of a specifier whose fetch previously rejected (e.g. a missing file or failed loader) will invoke Bun's module-loader fetch hook again rather than rejecting immediately from the cache, so anything that relied on the cached rejection (tests, error identity) may see different behavior. JSModuleLoader::getRegisteredMayBeNull is also moved from private to public.

  • 905a225671 — [API] wtf/UniStdExtras.h is now wrapped in #if OS(UNIX), so setCloseOnExec/unsetCloseOnExec/dupCloseOnExec/closeWithRetry/setNonBlock are no longer declared on Windows (done to keep the Windows Swift C++ importer happy). Only matters if the embedder includes that header on Windows; Bun's bindings do not reference it.

  • 76b474b322 — [API] Refactors JSC::Wasm::TypeKind: the type-section forms Func, Struct, Array, Rec, Sub, Subfinal are removed from TypeKind and moved to a new generated Wasm::DefinedTypeKind enum (with isValidDefinedTypeKind / makeString(DefinedTypeKind)), and the section parser dispatches on that. Pure cleanup that removes dummy switch cases; no behavior change. Bun does not reference these enumerators, so nothing to update.

  • 218421554b — [PERF] [API] JSON.parse now buffers array elements on a MarkedArgumentBuffer element stack and allocates each JSArray once at its final length and indexing type (Int32/Double/Contiguous) instead of growing the butterfly via putDirectIndex per element; also skips two Structure loads for outOfLineCapacity when a property offset is still inline. Drive-by change to the inlined MarkedVector::append fast path (stays inline once heap-allocated and registered with a mark set, rather than calling slowAppend on every append) and an additive MarkedVector::shrink(size_t) — both are inlined into Bun's many MarkedArgumentBuffer users, but no signature changes. Also speeds up Bun's native JSONParse/JSONParseWithException callers (JSON module loading, .json(), SQL client, etc.).

  • 6446fdc8e0 — WebCore ISO-BMFF box serialization work; the only engine touch is JSC::DataView::get<T>() and DataView::read<T>() in runtime/DataView.h becoming const member functions. [API] Source-compatible (header-only inline templates, only adds const), so no embedder action needed.

  • 38027ff0ec — Removes the @newPromiseCapability private builtin/link-time constant from JSC (builtins/BuiltinNames.h, bytecode/LinkTimeConstant.h, host function in runtime/JSGlobalObject.cpp), since upstream builtins now use @newPromise + @resolvePromiseWithFirstResolvingFunctionCallCheck/@rejectPromiseWithFirstResolvingFunctionCallCheck (no tuple object allocation, no property lookups). [API] After this upgrade @newPromiseCapability no longer resolves as a private name. Bun's bundled modules called $newPromiseCapability(Promise) in src/js/node/dgram.ts, events.ts, _http_server.ts (3 sites) and util.ts; the Bun PR rewrites them to $newPromise() plus the $resolvePromise/$rejectPromise family. Note the preceding upstream commit 7f38ebbabf had already deleted builtins/PromiseOperations.js (the JS implementation); the C++ JSPromise::createNewPromiseCapability() used by src/jsc/bindings/JSMockFunction.cpp is unaffected.

  • 0b92c2bcd0 — [PERF] Deletes UnlinkedCodeBlock::m_jumpTargets (a per-label offset list that nothing in a shipping configuration read; DFG/liveness already recompute targets via computePreciseJumpTargets()), saving 4 bytes per label (~38 KB after loading typescript.js), shrinking UnlinkedFunctionCodeBlock from 216 to 208 bytes (GC cell 224 -> 208), and cutting the serialized bytecode cache by ~1.4%. [API] Removes CodeBlock::numberOfJumpTargets()/jumpTarget(), UnlinkedCodeBlock::numberOfJumpTargets()/jumpTarget()/lastJumpTarget(), UnlinkedCodeBlockGenerator::addJumpTarget() etc., and recomputePreciseJumpTargets(), adding a computePreciseJumpTargets(UnlinkedCodeBlock*, ...) overload — Bun's bindings use none of these. The CachedCodeBlock layout changes (field dropped from runtime/CachedTypes.cpp), but bun build --bytecode output is already keyed to the build via computeJSCBytecodeCacheVersion(), so old caches are rejected rather than misread.

  • 3d0e6c14b1 — [PERF][API] Memory: moves m_features, m_lexicallyScopedFeatures, m_hasCapturedVariables, m_lineCount, m_endColumn and the sourceURL/sourceMappingURL directive pointers from UnlinkedCodeBlock down to UnlinkedGlobalCodeBlock (only Program/Eval/Module code uses them), shrinking UnlinkedFunctionCodeBlock from 216 to 192 bytes (cell 224 -> 192; ~53 KB saved after loading typescript.js). The accessors codeFeatures(), allowDirectEvalCache(), lexicallyScopedFeatures(), hasCapturedVariables(), lineCount(), endColumn(), sourceURLDirective(), sourceMappingURLDirective() and recordParse() are removed from UnlinkedCodeBlock and now exist only on UnlinkedGlobalCodeBlock; UnlinkedCodeBlock::usesImportMeta() is deleted outright (Bun's bindings use none of these; Bun's sourceURLDirective() calls are on SourceProvider). The serialized CachedCodeBlock layout for the bytecode cache also changes (split into CachedCodeBlock + CachedGlobalCodeBlock), which is covered by Bun keying the cache version on BUN_WEBKIT_VERSION.

  • 0bbbac7b52 — [BEHAVIOR] [API] Wasm memory64 now works together with multi-memory: the WasmSectionParser check that rejected any module combining a 64-bit memory with multiple memories ("if using memory64 then multiple memories are illegal for now") is removed, so such modules now validate/compile/run instead of failing with CompileError. IPInt decides whether to zero-extend an i32 address per accessed memory using a new WTF::BitSet<Wasm::maxMemories> (JSWebAssemblyInstance::m_memoryIsMemory64Bits) instead of a single memory-0 flag. JSWebAssemblyInstance::cachedMemory0IsMemory64() and offsetOfCachedMemory0IsMemory64() are removed (replaced by offsetOfMemoryIsMemory64Bits()); Bun does not reference them.

  • 71144530c1 — [API] Bumps the vendored wtf/simdutf single-header from 8.2.0 to 9.0.0 (now requires C++17): simdutf::to_string(encoding_type) and implementation::name()/description() return std::string_view instead of std::string, full_result gains a padding_error field and the base64 decoders now report the = position as the error location for padding errors, the SIMDUTF_FEATURE_* macros become #ifndef-overridable, and the icelake (AVX-512) simdutf::find now masks its tail load so searching for NUL no longer false-matches past the end of the input. error_code values, struct result, and every function Bun's src/simdutf_sys shim (bun-simdutf.cpp, simdutf.rs Status constants) calls are unchanged, and Bun falls back to its scalar decoder on any base64 error rather than reading the error offset, so no Bun-side change is needed.

  • ee4b208267 — [PERF] [API] Generator/async function bodies whose wrapper has no parameters no longer allocate a 64-byte UnlinkedFunctionExecutable::RareData just to hold an empty parameter-name list (every async () => {...}, async function f() {}, function* g() {} paid this; ~6.4 MB saved per 100k such functions). UnlinkedFunctionExecutable::create and the BytecodeGenerator now take Vector<Identifier>&& instead of std::optional<Vector<Identifier>>&&; Bun does not call UnlinkedFunctionExecutable::create directly, so no action needed.

  • b1701b3489 — [BEHAVIOR] [API] Uint8Array.prototype.setFromBase64 on a zero-length target now returns { read: 0, written: 0 } without inspecting the input at all (even an invalid base64 string is accepted), matching step 3 of the proposal spec; Uint8Array.fromBase64 is unchanged. WTF::fromBase64() gains a required fifth parameter OutputSizeIsMaxLength (new enum in wtf/text/Base64.h); Bun does not call WTF::fromBase64 directly, so no source change is needed.

  • 870de4ab77 — WTF fix in wtf/text/TextBreakIterator.{h,cpp}: NonSharedCharacterBreakIterator and NonSharedSentenceBreakIterator leaked their ICU UBreakIterator when setTextForIterator() failed (reachable via a null StringView), and the 8-bit path skipped utext_close() on ubrk_setUText() failure. Ownership is now expressed with a new WTF::UBreakIteratorPtr (std::unique_ptr<UBreakIterator, ICUDeleter<ubrk_close>>) and m_iterator becomes that smart pointer; the public operator UBreakIterator*() is unchanged. [API] Only the private member type and the file-static helpers changed, so this is source-compatible for embedders, and Bun does not use these classes at all (JSC only references them from the offline CharacterPropertyDataGenerator tool), so it is a no-op for Bun in practice.

Behavior changes

  • 3b9afb2b4f — [BEHAVIOR] Wasm correctness fix in BBQ and OMG (B3 lowering): ref.cast/ref.test on a nullable reference now only elides the explicit null check when Options::useWasmFaultSignalHandler() is on, so configurations running without the fault handler (e.g. Bun's Linux ASAN builds, where Options.cpp turns it off unless ASAN_OPTIONS contains allow_user_segv_handler=1) get a proper Wasm trap instead of dereferencing null. In signaling-memory mode, the decision to emit an explicit bounds check for large constant offsets now uses the last accessed byte (offset + size - 1) rather than the base offset; the old computation was slightly off but always still trapped via the PROT_NONE redzone.

  • b74760b182 — [BEHAVIOR] The non-ARM64 WTF::roundeven/roundevenf polyfill returned +0.0 for the tie that rounds to zero (roundeven(-0.5) gave +0.0 instead of -0.0); the result is now wrapped in copysign. In JSC this feeds BBQ's constant folding of Wasm f32.nearest/f64.nearest, so on x86_64 a constant -0.5 operand folded to the wrong sign of zero; ARM64 uses __builtin_roundeven (frintn) and was already correct.

  • 3c0f403d81 — [PERF] [BEHAVIOR] WasmGC array.fill / array.copy are reworked in BBQ and OMG: null and bounds checks are now emitted inline in JIT code, the runtime call is skipped entirely when size == 0 (observed to be very common), non-ref array.copy uses B3 MemoryCopy, and non-ref array.fill uses MemoryFill or new operationWasmArrayFill{2B,4B,8B,16B} (memset_pattern* on Darwin, std::ranges::fill elsewhere), while ref-typed arrays keep GC-safe loops (operationWasmArrayFillRefs / operationWasmArrayCopyRefs via gcSafeMemmove). Observable change: the trap message for a null array in these ops becomes the generic "access to a null reference" instead of "array.fill to a null reference" / "array.copy to a null reference" (the NullArrayFill / NullArrayCopy enumerators were removed from the internal Wasm::ExceptionType enum, which Bun does not reference). Old operationWasmArrayFill{,Vector} / operationWasmArrayCopy JIT operations are removed.

  • 2165451fd3 — [BEHAVIOR] Correctness fix in the YARR interpreter's tryConsumeBackReference: in Forward direction it speculatively advanced the input by matchSize before comparing, and when the captured character was non-BMP and the input at that offset was not a valid surrogate pair, the early errorCodePoint return only restored the position for Backward, so a failed greedy iteration consumed input. Fixes wrong results like /(\u{1F601})\1*$/u.exec("\u{1F601}ab") matching instead of returning null, and /(\u{1F601})(\1*)?/u splitting a surrogate pair; the check now falls through to the common mismatch path which restores the position in both directions. Only affects patterns that run in the interpreter (authored by Sosuke Suzuki from Bun).

  • e88b92e29f — [BEHAVIOR] (bug fix) Fixes a BBQ-tier miscompile of Wasm i64.mul_wide_s/i64.mul_wide_u on x86_64: the 128-bit product comes back in rdx:rax, and if the register allocator handed out rax/rdx as the result or scratch registers the halves were clobbered, producing wrong results. Now uses the same PREPARE_FOR_MOD_OR_DIV pattern as div/mod (clobber + lock rax/rdx). Only reachable when Options::useWasmWideArithmetic is on (default off, Bun does not enable it), so this matters only for users opting in via BUN_JSC_useWasmWideArithmetic=1.

  • 5cfff9fe44 — [BEHAVIOR] In JSC's Wasm ESM integration (WebAssemblyModuleRecord), immutable exported globals are now exposed in the module namespace as plain JS values instead of WebAssembly.Global wrappers, per the esm-integration spec/WPT; v128 and exnref globals stay TDZ, Instance.exports is unchanged, and wasm-to-wasm ESM imports fall back to the Instance.exports wrapper when the namespace binding is empty. No Bun-visible change today because Bun's .wasm loader (src/runtime/jsc_hooks.rs, L::Wasm arm) returns a file path / wasi-runner instead of creating a JSC Wasm module record; it would matter if Bun ever adopts JSC's native Wasm ESM path.

  • b7afce9416 — [BEHAVIOR] When several Wasm functions fail validation during concurrent compilation, the WebAssembly.CompileError message now deterministically reports the lowest-index failing function instead of whichever worker thread finished first; non-function failures (OOM/parse/cancel) still take precedence. Adds protected Plan::failAtFunction / EntryPlan::failFunctionCompilation and an m_errorFunctionIndex field; error messages become stable across runs (useful for snapshot tests).

  • 010e57fb4b — [BEHAVIOR] WebAssembly.Module.imports() / WebAssembly.Module.exports() descriptors no longer include the non-standard js-types-proposal type field unless Options::useWasmJSTypes() is enabled (default false, and Bun does not set it). At the merge base this field was emitted unconditionally and could throw for unrepresentable ref types; descriptors now have the spec shape {module, name, kind} / {name, kind}, matching V8/Node. Also tweaks the WasmJSTypesEnabled description in UnifiedWebPreferences.yaml.

  • 20c0bd7d62 — [BEHAVIOR] Wasm JS API spec fix: re-exporting an imported immutable WebAssembly.Global now yields the same JS object that was imported (instance.exports.g === importedGlobal), matching the WPT constructor-caching expectations; previously a fresh wrapper was created each time (mutable globals already preserved identity). JSWebAssemblyInstance gains an m_importedGlobalWrappers map (new setImportedGlobalWrapper/importedGlobalWrapper methods, visited by GC). Plain-number global imports still get a new wrapper.

  • 39de2d4eea — [BEHAVIOR] Wasm: importing a WebAssembly.Tag and re-exporting it now yields the same JS object (previously a fresh JSWebAssemblyTag wrapper was created on every export, so === identity failed), and locally defined tags are cached on first export so two export names share one wrapper. Implemented via a new m_tagWrappers map on JSWebAssemblyInstance that is visited by GC; no embedder-facing API change.

  • 7f38ebbabf — [BEHAVIOR] Promise.try follows the updated spec (Normative: make Promise.try use PromiseResolve in non-error case tc39/ecma262#3883): the result comes from PromiseResolve(C, value) / PromiseReject(C, error) instead of NewPromiseCapability(C), so Promise.try(() => p) now returns p itself when p is a native Promise, and a subclass constructor is invoked after the callback runs rather than before. builtins/PromiseOperations.js is deleted (@newPromiseCapabilitySlow gone) and @newPromiseCapability becomes a C++ link-time constant wrapping JSPromise::createNewPromiseCapability. Heads-up: follow-up upstream commit 38027ff0ec (also in this range) removes @newPromiseCapability entirely; see that entry under "API and ABI changes" for the Bun $newPromiseCapability(Promise) call sites that must be rewritten.

Performance

  • 958a13ecad — [PERF] Wasm BBQ emitIndirectCall computed the CallProfile address with addPtr(TrustedImm32, ...), which on large offsets (functions with many call profiles) silently spills through scratchRegister, clobbering the profile value loaded just before; it now does move + register addPtr. No observable behavior change, but affected call_indirect sites were left permanently un-optimized (polymorphic-callee detection never kicked in), so this restores expected tiering for large wasm functions.

  • 01f04c4fb4 — [PERF] YARR JIT now compiles backreferences inside lookbehinds (e.g. /(?<=(a)\1)b/); previously any such pattern forced the entire regex to the interpreter. The backward match compares the capture from its end down to its start, with checkNotEnoughInput becoming index >= length in Backward mode and case-insensitive, duplicate-named-group and surrogate-pair handling reused with the index direction flipped; forward codegen is unchanged. ~10.8x faster on the new regexp-lookbehind-backreference microbenchmark, no intended change in match results (authored by Sosuke Suzuki from Bun).

  • 7ef4708559 — [PERF] Parser: when parseFunctionInfo has already computed a function's free-variable list for the SourceProviderCache entry, that span is now handed to popScope, so Scope::collectFreeVariablesFrom (renamed from collectFreeVariables, internal to parser/Parser.h) no longer re-derives it by re-walking used/declared/lexical sets. Pure parse-time speedup for cacheable (>=16/8 byte) function bodies; SourceProviderCacheItemCreationParameters gains a freeVariableCount field and freeVariables() accessor. No behavior change.

  • 0ca8f08b89 — [PERF] Lexer::shift drops the 14-year-old "unconditionally zero m_current then overwrite" micro-optimization in favor of a plain if/else, which measures faster on current hardware. Semantics are identical; lexer hot-path only.

  • 24a6944b57 — [PERF] In Parser::parseMemberExpression, when the TreeBuilder is SyntaxChecker (the pre-parse/syntax-only pass), the new token start positions are now tracked by a counting placeholder instead of a Vector<JSTextPosition, 4>, since SyntaxChecker::createNewExpr ignores them anyway. Saves allocation/copy work for nested new chains during syntax checking; no behavior change.

  • a5fa580c84 — [PERF] B3 LICM (hoistLoopInvariantValues) can now hoist trapping loads (plain Load*, WasmStructGet, WasmArrayLength without fences) and control-dependent values out of loops that contain side exits, as long as no earlier "trap barrier" (write/fence/side-exit) precedes the value on the path from the loop header. Previously any side exit in the loop disabled hoisting of control-dependent values entirely; mainly benefits Wasm OMG and FTL code with bounds/null checks in loops. Adds Effects::isWrite()/isTrapBarrier().

  • 6fbae40455 — [PERF] FTL switch on a string that is an unresolved concatenation rope now calls a new noexcept operation (operationSwitchStringResolveRopeAndGetCharacters8) to resolve the rope, and if the result is 8-bit uses the inline binary-search StringSwitch on the resolved characters instead of falling back to the generic slow path. Resolution uses tryGetValue() so an OOM falls through to the slow path rather than throwing from the JIT operation.

  • de9231d86e — [PERF] RegExp::m_ovector and RegExp::RareData::m_captureGroupNames switch from Vector to FixedVector, shrinking the RegExp GC cell from 96 to 80 bytes and allocating exactly offsetVectorSize ints instead of Vector::resize's 16-element minimum capacity (64 bytes). Upstream measured per-RegExp cell+ovector going from 160 to 96 bytes and max RSS with 200k live RegExps dropping from 137.5 MB to 115.0 MB; estimatedSize now reports the exact ovector byteSize(). Authored by a Bun contributor.

  • 1c2c282d06 — [PERF] Options::computeNumberOfWorkerThreads now caps its result at 32 on non-Darwin platforms; in practice this only affects the default numberOfWasmCompilerThreads (previously cores - 1 with no cap; other callers already pass caps of 3 or 8), limiting it to 31 on Linux/Windows machines with more than 32 cores. Motivated by Wasm compilation OOMs on high-core-count, low-memory hosts; Bun does not override this option (it only sets numberOfGCMarkers), so large Linux servers will see fewer Wasm compiler threads and lower peak memory.

  • ce878e190f — [PERF] Map.prototype.forEach/Set.prototype.forEach get inline DFG and FTL lowering for MapIterationNext/MapIterationEntry/MapIterationEntryKey/MapIterationEntryValue, scanning the ordered hash table directly instead of making four C++ operation calls per element (the for-of MapIterator* nodes already did this and now share loadMapEntryData). Upstream microbenchmarks show 1.23x-1.65x speedups on forEach-heavy loops; the now-unreachable operationMap/SetIterationEntry* JIT operations are removed and the remaining operationMap/SetIterationNext become noexcept and only handle obsolete tables. Internal DFG operations only, no embedder-facing API or JS-visible behavior change (new stress tests cover mutation during iteration).

  • c823243598 — [PERF] The bytecode cache (generateUnlinkedCodeBlockForFunctions in CodeCache.cpp) now emits CodeForConstruct instead of CodeForCall for class constructors, so cached programs no longer reparse every class constructor body (and its nested functions) on the first new C(); upstream measured 253 -> 4 parses constructing 182 three.js classes and 133 -> 9 parses for babylon.js startup. Cache output grows by the previously missing constructor bodies (three.js +10.8%, a 50 MB bundle +0.5%), which is relevant to Bun's --bytecode builds and node:vm cached-data paths that use generateProgramBytecode/generateModuleBytecode. No API or JS behavior change.

  • 9516ed8a4f — [PERF] DFG/FTL switch on strings now handles 8-bit substring ropes inline by reading the base string's buffer at the substring offset, instead of bailing to the slow operationSwitchString call (which resolves the rope). Previously only flat 8-bit strings took the inline binary-switch path, so JIT'd code doing switch (s.slice(...)) / switch (s.substring(...)) gets faster. Internal-only signature rename in DFGSpeculativeJIT.h; no public API change.

  • a7a9e233ce — [PERF] The JSON.parse lexer accumulates the int32 value while scanning the digit run instead of re-walking the digits a second time in lexNumber; micro-optimization for integer-heavy JSON. No API or behavior change.

  • 6b13bfa7ba — [PERF] TypedArray.prototype.sort() without a comparator now uses an LSD radix sort (8-bit digits, stable passes, skipping digits with a single bucket) for 2/4/8-byte element types above measured thresholds (128 / 512 / 8192 elements), with a SIMD already-sorted pre-scan and a sampled few-distinct-values check that falls back to std::sort; upstream reports 2.3-4.6x on large Int16/Uint16/Int32/Uint32/Float32/Float64 arrays and 6.7x on presorted Int32 (geomean 1.5x). It temporarily allocates an O(n) scratch buffer (plus a snapshot copy for shared buffers) and falls back to std::sort on allocation failure; results are unchanged (NaN canonicalization matches the old sortFloat path). Also adds WTF::SIMD::bitXor/bitXor2 helpers to SIMDHelpers.h.

  • db2d849cbe — [PERF] Replaces heap-registering MarkedArgumentBuffer with a stack std::array<EncodedJSValue, N> wrapped in ArgList at every call site where the argument count is statically known (37 files: Promise resolve/reject/then/finally and microtask jobs, VM::callPromiseRejectionCallback, Proxy traps, JSON toJSON/reviver, RegExp/String Symbol.* protocol, iterator protocol, typed-array callbacks, Map/Set/WeakMap constructors, DFG slow paths). This trims per-call overhead and removes the never-hit hasOverflowed()/OOM checks whenever the engine calls back into JS from C++. No public API or JS-visible behavior change; the only signature change (SyntheticModuleRecord::tryCreateWithExportNamesAndValues now takes ArgList) is a private method Bun does not call.

  • eb44b6cfaa — [PERF] WTF::URLParser now SIMD-scans the path, opaque-path, query, and fragment states (via SIMD::find from wtf/SIMDHelpers.h) for the first delimiter, encode-set member, control, or non-ASCII code point and consumes the whole preceding run at once (skipped for canonical input, bulk-appended when building the output buffer) instead of looping per code point; upstream measures ~1.33x on 82k real-world URLs and 3-4x on ~100-char components. This directly speeds up every WTF::URL parse in Bun (new URL(), URLPattern, Request/fetch URL handling, module URL resolution). Additive-only header changes: CodePointIterator::span()/advanceBy() and a private URLParser::appendToASCIIBuffer(std::span<const char16_t>) overload; a consteval static_assert verifies each stop-character set covers its percent-encode set, so no parsing behavior changes.

  • 70eb5015ae — [PERF] Memory: the buffered-structures set, its lock and bufferingCountdown move from the PropertyInlineCache base class into RepatchingPropertyInlineCache, since handler ICs never buffer; sizeof(HandlerPropertyInlineCache) drops 112 -> 88 bytes per IC site in Baseline/DFG JITData (about -1.27 MB on Octane typescript). Side effect: handler ICs that fail to cache a structure now retry tryCache on the next few visits instead of skipping them; repatching ICs are unchanged. Internal JIT data structure only, not referenced by Bun.

  • 1969cf2d9e — [PERF] StringImpl::replace(char16_t, char16_t) (behind String::replace(char, char)) now finds the first occurrence with SIMD WTF::find() instead of a scalar byte-at-a-time loop, for both 8-bit and 16-bit strings; same fix already applied to makeStringByReplacingAll. No behavior change.

  • 2d0855229c — [PERF] WTF::copyElements (used throughout string building/concatenation) now handles 2..32-byte copies with inlined overlapping unaligned loads/stores instead of calling libc memcpy, whose size dispatch costs more than the copy itself for short runs. The B3 operationMemoryCopy fast path is hoisted into new WTF helpers copySmallMemory<min,max>(), copyOverlappingEnds, copyOverlappingEndPairs, WidestUnalignedUnit and maxSmallCopySize in wtf/UnalignedAccess.h, available for Bun's own C++ to use; no behavior change.

  • 7375405d8e — [PERF] base64EncodeInternal()/base64DecodeInternal() in WTF bound the chosen lookup table with auto, copying the whole 64-byte encode map or 128-byte decode map onto the stack on every call; now auto& references the constexpr table directly. Affects Bun's uses of WTF::base64Decode/base64URLDecode/base64URLEncode (WebCrypto JWK import/export in src/jsc/bindings/webcrypto/CryptoKey*.cpp); no behavior change.

Wasm

  • ce60d5d618 — WasmGC concurrent-GC correctness fix in the BBQ tier: struct.new/struct.new_default skipped the mutator fence when every stored field was a constant, but a struct with reference fields still needs the store-store fence before the new object is published to the concurrent marker. BBQ now emits emitMutatorFence() whenever the struct type has ref fields, matching IPInt/OMG; the fence is a no-op on x86_64, so this matters on ARM64.

  • c25fbbd346 — Debug-only: fixes a copy-paste typo in an ASSERT in Wasm BBQ emitModOrDiv (x64) that tested lhsLocation twice instead of rhsLocation != edx. No release-build or behavior impact.

  • 4cc12fa76b — Debug-build-only fix: assertCalleeIsReferenced in WasmOperations.cpp now returns early when the frame's callee is not a NativeCallee, which happens when a stack overflow during a JS↔Wasm transition reaches operationWasmToJSException with a JS callee still in the frame. Fixes a spurious asNativeCallee() crash under ASSERT_ENABLED; no release behavior change.

  • 3400ff6aa7 — Wasm: ModuleInformation now stores the importedStringConstants / qualifiedBuiltinSetNames compile options as UTF-8 byte vectors (Wasm::Name) instead of isolatedCopy()'d WTF::Strings, so no StringImpl is ever shared between the main thread and Wasm compiler threads (not all StringImpl fields are atomic). Import-name matching now compares raw bytes directly, dropping a makeString per import. Internal importedStringConstantsEquals()/builtinSetsInclude() signatures change to const Name& (Bun does not call them); only affects modules compiled with JS string builtins / importedStringConstants options.

  • 20d622b6d6 — Build fix: Wasm::CalleeGroup::BBQCalleeReference::operator= is replaced with a named set() method so clang 18's -Wthread-safety-precise analyzer can see the WTF_REQUIRES_LOCK requirement. No runtime behavior change; internal type only.

Other JSC

  • 9d03f48340 — Removes the dead CallLinkInfo::m_slowPathCount field (plus offsetOfSlowPathCount()/slowPathCount()) and its increments in the LLInt and JIT virtual-call thunks; CallLinkStatus::computeFromCallLinkInfo already bailed via takesSlowPath() for any m_clearedByVirtual site, so the reads always saw zero. Minor: one fewer memory increment per virtual call and 4 bytes less in CallLinkInfo. Internal-only, not used by Bun.

  • 3ddc7045b7 — DFG OSR-exit correctness fix: SpeculativeJIT::emitSwitchChar's StringUse path called op1.use() before speculateString(), so the operand's death preceded the BadType exit and baseline re-executed op_switch_char on a dead/poisoned scrutinee value when the speculation failed (e.g. a switch with single-character string cases later fed a non-string). Now speculates before releasing the operand, matching emitSwitchString; fixes a potential crash/miscompile in optimized code, no API change.

  • bdb7246737 — Adds an opt-in DFG/FTL "global inlining planner" (Options::useGlobalInliningPlanner, default false) that surveys and ranks all inlining candidates of a compilation up front (weighted by callee tier and inline depth) and spends a single compilation-wide budget, instead of deciding per call site in bytecode order. Adds nine new Options knobs (globalInliningPlanBudgetForDFG/FTL, maximumGlobalInliningPlanSites, inliningPlanTierBonus*, inliningPlanDepthPenalty). No effect unless enabled; upstream notes the current budget is high enough that it barely changes inlining decisions yet.

WTF and bmalloc

  • 386c27f080 — Build-only tweak: the ALWAYS_INLINE fast path of WTFCrashWithInfo (Darwin/PlayStation on x86_64/ARM64) is additionally disabled when compiling under the clang static analyzer (__clang_analyzer__) so the analyzer sees the out-of-line no-return version. No effect on normal Bun builds.

  • 390e2c91dc — Only engine-side change is a one-line #import#include of <wtf/Platform.h> in wtf/MachSendRightAnnotated.h (a Cocoa-only header); the rest is WebKit modulemap hygiene for Swift/Windows. No effect on Bun's JSCOnly build.

  • 1f7ab2fec8 — Fixes WTF::symbolize() in wtf/StackTrace.cpp under USE(LIBBACKTRACE): consults the symbol table (mangled names) before DWARF so clang debug builds get fully-qualified frame names, initializes the symbol pointer (previously read uninitialized on lookup miss), and passes a non-null error callback (libbacktrace always invokes it, so null crashed on the first failed lookup). No effect on Bun: USE_LIBBACKTRACE defaults to OFF for the JSCOnly port and Bun's build does not enable it.

  • f0148cf5ab — Changes Source/WTF/wtf/module.modulemap so the WTF Core clang module declares requires cplusplus23 instead of cplusplus, and bumps the module-cache touch count to force a rebuild. Only affects builds that consume WTF as a clang module (-fmodules, Apple/Swift-interop builds); Bun's build already uses -std=c++23 and does not enable clang modules, so no effect on Bun.

lauromoura and others added 30 commits August 18, 2026 12:32
…bleStreamDefaultReader::read() fires when a worker is terminated mid-read

https://bugs.webkit.org/show_bug.cgi?id=321607

Reviewed by Youenn Fablet.

The test streams/pipeTo-in-worker-terminate-crash.html terminates
workers mid-flight, which should not trigger a crash. In such scenarios,
the read operation might happen while we have a pending
TerminationException. With the current assertion, instead of returning
silently as a non-assertion build would, we end up with a crash.

To address it, this commit relaxes the assertion by accepting this
termination state as valid, an approach also currently taken by
ReadableStreamDefaultController.cpp (since 243538@main).

* LayoutTests/platform/wpe/TestExpectations:
* Source/WebCore/Modules/streams/ReadableStreamDefaultReader.cpp:
(WebCore::ReadableStreamDefaultReader::read):

Canonical link: https://commits.webkit.org/319395@main
https://bugs.webkit.org/show_bug.cgi?id=321999
rdar://185184613

Reviewed by Yijia Huang.

Let's just use `@newPromise` and
@rejectPromiseWithFirstResolvingFunctionCallCheck etc. that is much more
efficient (not allocating an object for a tuple), not doing any property
lookup. As a result, nobody is using @newPromiseCapability anymore. So
this patch removes it from builtin JS.

* Source/JavaScriptCore/builtins/BuiltinNames.h:
* Source/JavaScriptCore/bytecode/LinkTimeConstant.h:
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* Source/WebCore/Modules/streams/ReadableStreamDefaultReader.js:
(getter.closed):
* Source/WebCore/Modules/streams/ReadableStreamInternals.js:
(readableStreamDefaultReaderClosedForBindings):
(readableStreamDefaultReaderClosedPromise):
(readableStreamReaderGenericInitialize):
(readableStreamTee):
(const.pullAlgorithm):
(readableStreamTeePullFunction):
(readableStreamTeeBranch1CancelFunction):
(readableStreamTeeBranch2CancelFunction):
(readableStreamError):
(readableStreamClose):
(readableStreamReaderGenericRelease):
* Source/WebCore/Modules/streams/TransformStreamInternals.js:
(createInternalTransformStreamFromTransformer):
(createTransformStream):
(transformStreamSetBackpressure):
(transformStreamDefaultControllerPerformTransform):
(transformStreamDefaultSinkWriteAlgorithm):
(transformStreamDefaultSinkCloseAlgorithm):
(transformStreamDefaultSourcePullAlgorithm):
* Source/WebCore/Modules/streams/WritableStreamInternals.js:
(writableStreamDefaultWriterClosedForBindings):
(writableStreamDefaultWriterReadyForBindings):
(setUpWritableStreamDefaultWriter):
(writableStreamAbort):
(writableStreamClose):
(writableStreamAddWriteRequest):
(writableStreamFinishErroring):
(writableStreamFinishInFlightWrite):
(writableStreamFinishInFlightWriteWithError):
(writableStreamRejectCloseAndClosedPromiseIfNeeded):
(writableStreamUpdateBackpressure):
(writableStreamDefaultWriterEnsureClosedPromiseRejected):
(writableStreamDefaultWriterEnsureReadyPromiseRejected):
(writableStreamDefaultWriterClosedPromise):
(writableStreamDefaultWriterReadyPromise):

Canonical link: https://commits.webkit.org/319396@main
https://bugs.webkit.org/show_bug.cgi?id=321579
rdar://184690236

Reviewed by Charlie Wolfe.

CookieRequestHeaderFieldValue returned the full Cookie header to a web process,
HttpOnly cookies included. A web process must never see an HttpOnly value. The
message also validated only firstParty, which does not constrain the url the
cookies are read for.

Its only caller is Vary: Cookie cache validation, which compares the value and
never reads it. Return a SHA-1 digest instead, as a std::array<uint8_t, 20> with
std::nullopt for "no Cookie header". The digest is salted per network process
launch, so a web process cannot recover the header by hashing candidates.

collectVaryingRequestHeaders() stores its values in a Vector<std::pair<String,
String>> that the network cache writes to disk, so the digest is base64 encoded
at that boundary.

std::array<uint8_t, N> is an opaque IPC data type, so the reply parameter needs
an entry in opaque_ipc_types.tracking.in. messages.py did not know a header for
std::array yet.

Dropping frameID, pageID and webPageProxyID preserves behavior, because that
caller always passed std::nullopt for the first two and
shouldRelaxThirdPartyCookieBlockingForPage() already returned No.

Existing cache entries hold a raw header, so Vary: Cookie entries revalidate
once. The cache version stays the same on purpose, because a bump would discard
every cached resource instead of only those.

WebCookieJar::cookieRequestHeaderFieldValue now returns nothing. Its only WebKit2
caller is Web Inspector WebSocket handshake reporting, and both channels discard
it. WebKitLegacy uses the unchanged base class implementation.

Test: Tools/TestWebKitAPI/Tests/WebKit/WKWebView/IPCTestingAPI.mm

* Source/WebCore/loader/CookieJar.cpp:
(WebCore::CookieJar::cookieRequestHeaderFieldValueDigest const):
* Source/WebCore/loader/CookieJar.h:
* Source/WebCore/platform/network/CacheValidation.cpp:
(WebCore::computeCookieHeaderDigestForVary):
(WebCore::encodeCookieHeaderDigestForVary):
(WebCore::cookieRequestHeaderFieldValueForVary):
(WebCore::collectVaryingRequestHeaders):
(WebCore::verifyVaryingRequestHeaders):
(WebCore::cookieRequestHeaderFieldValue): Deleted.
* Source/WebCore/platform/network/CacheValidation.h:
* Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp:
(WebKit::NetworkConnectionToWebProcess::cookieRequestHeaderFieldValueDigest):
(WebKit::NetworkConnectionToWebProcess::cookieRequestHeaderFieldValue): Deleted.
* Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h:
* Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in:
* Source/WebKit/NetworkProcess/NetworkProcess.h:
* Source/WebKit/Scripts/webkit/messages.py:
* Source/WebKit/Scripts/webkit/opaque_ipc_types.tracking.in:
* Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp:
(WebKit::WebCookieJar::cookieRequestHeaderFieldValue const):
(WebKit::WebCookieJar::cookieRequestHeaderFieldValueDigest const):
* Source/WebKit/WebProcess/WebPage/WebCookieJar.h:
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/IPCTestingAPI.mm:
(EmptyFirstPartyForCookiesCookieRequestHeaderFieldValueDigest)):
(InvalidSameSiteInfoCookieRequestHeaderFieldValueDigest)):
(EmptyFirstPartyForCookiesCookieRequestHeaderFieldValue)): Deleted.
(InvalidSameSiteInfoCookieRequestHeaderFieldValue)): Deleted.

Canonical link: https://commits.webkit.org/319397@main
https://bugs.webkit.org/show_bug.cgi?id=322043
rdar://185140001

Reviewed by Megan Gardner, Lily Spiniolas, Aditya Keerthi, and Abrar Rahman Protyasha.

* Source/WTF/wtf/PlatformEnable.h:
Temporarily disable this flag.

Canonical link: https://commits.webkit.org/319398@main
…IsolatedSiteStore.PersistsAcrossSessions is a flaky failure

https://bugs.webkit.org/show_bug.cgi?id=321957
rdar://185141546

Unreviewed test Gardening

The test is a flaky failure, so updating the test expectation to reflect the correct flag.

* TestExpectations/apitests:

Canonical link: https://commits.webkit.org/319399@main
https://bugs.webkit.org/show_bug.cgi?id=322041

Reviewed by Adrian Perez de Castro.

The test started failing when the bots switched to clang in 318539@main.

WebKitCompilerFlags.cmake passes "-mllvm -dwarf-linkage-names=Abstract", which
GCC ignores but which makes clang drop the mangled name from the debug info of
regular function definitions. Only the plain name is left, so symbolize() named
the test frame "TestBody" instead of
"TestWebKitAPI::StackTraceTest_StackTraceWorks_Test::TestBody()". Every frame of
a debug build backtrace lost its namespace and class this way. Release builds
were fine because they have no debug info to begin with.

Look the name up in the symbol table first, which always stores the mangled
name, and only ask the debug info when the symbol table has nothing.

Also fix two smaller problems in the same code: the symbol was read
uninitialized when neither lookup found anything, and libbacktrace always calls
the error callback, so passing null for it would crash on the first failed
lookup.

* Source/WTF/wtf/StackTrace.cpp:
(WTF::backtraceErrorCallback):
(WTF::backtraceState):
(WTF::backtraceSyminfoCallback):
(WTF::backtraceFullCallback):
(WTF::symbolize):

Canonical link: https://commits.webkit.org/319400@main
https://bugs.webkit.org/show_bug.cgi?id=321746

Reviewed by Devin Rousso.

WebPageProxy::close() cancels tracking of the active popup menu, but only
drops its reference to the active context menu without dismissing it. On
macOS and Windows the menu runs a nested run loop that keeps the proxy
alive, so the menu stays on screen tracking a closed page.

Cancel tracking of the active context menu in close(), matching popup menus.
Implemented with -[NSMenu cancelTracking] on macOS and ::EndMenu() on
Windows. GTK needs no override since its menus are non-modal and popped down
by the proxy destructor; WPE shows no native menu.

Test: Tools/TestWebKitAPI/Tests/WebKit/WKWebView/mac/ContextMenuTests.mm

* Source/WebKit/UIProcess/WebContextMenuProxy.h:
(WebKit::WebContextMenuProxy::cancelTracking):
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::close):
* Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h:
* Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm:
(WebKit::WebContextMenuProxyMac::cancelTracking):
* Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp:
(WebKit::WebContextMenuProxyWin::cancelTracking):
(WebKit::WebContextMenuProxyWin::showContextMenuWithItems):
* Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h:
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/mac/ContextMenuTests.mm:
(TestWebKitAPI::TEST(ContextMenuTests, MenuTrackingCancelledWhenPageCloses)):

Canonical link: https://commits.webkit.org/319401@main
….html

https://bugs.webkit.org/show_bug.cgi?id=322050

Unreviewed gardening.

The pixel test result now matches the legacy SVG engine, remove the LBSE baseline.

* LayoutTests/platform/mac-tahoe-wk2-lbse-text/svg/zoom/page/zoom-background-images-expected.png: Removed.

Canonical link: https://commits.webkit.org/319402@main
https://bugs.webkit.org/show_bug.cgi?id=321991

Reviewed by Nikolas Zimmermann.

Added background color support to GraphicsLayerCoordinated,
CoordinatedPlatformLayer and SkiaCompositingLayer.

The "paint flushing" feature of WebInspector is using
GraphicsLayer::setBackgroundColor. For Skia compositor, there is one more bug
for the "paint flushing" feature. See <https://webkit.org/b/321993>.

* Source/WebCore/platform/graphics/skia/SkiaCompositingLayer.h:
* Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedPlatformLayer.cpp:
(WebCore::CoordinatedPlatformLayer::setBackgroundColor):
(WebCore::CoordinatedPlatformLayer::flushCompositingStateOnTarget):
(WebCore::CoordinatedPlatformLayer::flushCompositingStateOnSkiaTarget):
* Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedPlatformLayer.h:
* Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.cpp:
(WebCore::GraphicsLayerCoordinated::setBackgroundColor):
(WebCore::GraphicsLayerCoordinated::commitLayerChanges):
* Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.h:
* Source/WebCore/platform/graphics/skia/SkiaCompositingLayer.cpp:
(WebCore::SkiaCompositingLayer::paintContents):

Canonical link: https://commits.webkit.org/319403@main
…ests before reporting results

https://bugs.webkit.org/show_bug.cgi?id=319725
rdar://182558497

Reviewed by Aakash Jain.

The Site-Isolation-Tests EWS queue reported a change as failing after a single test run, skipping
the retry ladder that every other layout-test queue uses to avoid blaming a change for flaky or
pre-existing failures.

The queue can reuse the existing ladder as-is. Both the first run and the re-run need the site-isolation
flavor, since each consults results-db and can pass the build early when every failure is already known.
Without it the re-run would query regular WK2 history for this queue, which could mark a
site-isolation-specific regression as pre-existing and hide it.

* Tools/CISupport/ews-build/steps.py:
(RunWebKitTests.rerun_step): Added, so a queue can substitute its own re-run step.
(RunWebKitTests.evaluateCommand): Use rerun_step().
(RunWebKitTestsInSiteIsolationMode.doStepIf):
(SiteIsolationResultsDBMixin): Added, holding the site-isolation results-db flavor and reports_to_results_db
for both site-isolation steps.
(SiteIsolationResultsDBMixin.results_db_query_configuration): Moved from RunWebKitTestsEWSSiteIsolation.
(RunWebKitTestsEWSSiteIsolation): Moved below ReRunWebKitTests so it can reference the re-run step.
Removed the single-run evaluateCommand and the filter_failures_using_results_db override that duplicated
the base implementation.
(RunWebKitTestsEWSSiteIsolation.rerun_step):
(ReRunWebKitTestsEWSSiteIsolation): Added, the re-run step for this queue.
(RunWebKitTestsEWSSiteIsolation.results_db_query_configuration): Deleted.
(RunWebKitTestsEWSSiteIsolation.filter_failures_using_results_db): Deleted.
(RunWebKitTestsEWSSiteIsolation.evaluateCommand): Deleted.
* Tools/CISupport/ews-build/steps_unittest.py: Add unit tests.

Canonical link: https://commits.webkit.org/319404@main
…reeSyncData when a remote web process terminates while loading cross-site iframes in private browsing

https://bugs.webkit.org/show_bug.cgi?id=321633
rdar://184724123

Reviewed by Abrar Rahman Protyasha.

broadcastFrameTreeSyncData has a RELEASE_ASSERT that site isolation is enabled.
Four of its five callers check the preference first; the one in
remoteProcessDidTerminate does not. 7e7db43 added the assert, the guarded
callsite in didCommitLoad, and this unguarded one, all in the same commit.

siteIsolationEnabled is a mutable preference, and nothing tears down a
RemotePageProxy or removes a page from its BrowsingContextGroup when it is turned
off on a live page - WebPreferences::update() only calls
WebPageProxy::preferencesDidChange(). So a remote page created while site
isolation was enabled outlives the preference change, and when its process later
terminates, RemotePageProxy::processDidTerminate reaches
remoteProcessDidTerminate, which broadcasts unconditionally and the release
assert kills the UI process.

Check the preference at the callsite, the way didCommitLoad does.

The test kills the iframe process and waits for it to exit rather than waiting on
-waitForWebContentProcessDidTerminate. An iframe process is not the page's
siteIsolatedProcess(), so WebProcessProxy::terminationReason() reports
NonMainFrameWebContentProcessCrash, and
NavigationState::NavigationClient::processDidTerminate returns early for that reason
without invoking the delegate. Waiting on it never completes, so the test times out
instead of failing.

* Source/WebKit/UIProcess/WebFrameProxy.cpp:
(WebKit::WebFrameProxy::remoteProcessDidTerminate):
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/SiteIsolation.mm:
(TestWebKitAPI::setFeatureEnabled):
(TestWebKitAPI::enableFeature):

Canonical link: https://commits.webkit.org/319406@main
…n-picture/picture-in-picture-interruption.html is a flaky failure

https://bugs.webkit.org/show_bug.cgi?id=322051
rdar://185244348

Unreviewed test gardening

* LayoutTests/platform/mac-wk2/TestExpectations:

Canonical link: https://commits.webkit.org/319407@main
https://bugs.webkit.org/show_bug.cgi?id=321769
rdar://172301423

Reviewed by Sihui Liu.

The existing process count limiter depends on various codepaths maintaining an LRU list of all
WebProcesses at navigation time. With Site Isolation enabled, this strategy doesn't work, since the
LRU list maintenance didn't fan out to remote frame processes, so processes that should logically be
clustered together in the LRU list ended up spread apart.

This patch replaces the LRU list of WebProcess with an LRU list of WebPageProxy. LRU in this case
means:

1. Non-visible pages, in order of creation time
2. Visible pages, in order of last visible or focused time

So we upon reaching the process count limit, we first try to kill the page that was visible the
longest time ago.

This also contains a couple of other drive-by fixes:

1. We arbitrarily raise the process count limit from 400 to 512 when Site Isolation is enabled.
2. We stop prewarming processes if we're close to the process count limit.

Tests: Tools/TestWebKitAPI/Tests/WebKit/WKWebView/SiteIsolation.mm
       Tools/TestWebKitAPI/Tests/WebKit/WKWebView/WebContentProcessDidTerminate.mm

* Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
* Source/WebKit/UIProcess/BrowsingContextGroup.cpp:
(WebKit::BrowsingContextGroup::hasVisiblePage const):
* Source/WebKit/UIProcess/BrowsingContextGroup.h:
* Source/WebKit/UIProcess/ProvisionalFrameProxy.cpp:
(WebKit::ProvisionalFrameProxy::ProvisionalFrameProxy):
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::leastRecentlyVisiblePages):
(WebKit::leastRecentlyHiddenPages):
(WebKit::m_pageForTesting):
(WebKit::WebPageProxy::close):
(WebKit::WebPageProxy::loadRequestWithNavigationShared):
(WebKit::WebPageProxy::loadFile):
(WebKit::WebPageProxy::loadDataWithNavigationShared):
(WebKit::WebPageProxy::loadSimulatedRequest):
(WebKit::WebPageProxy::loadAlternateHTML):
(WebKit::WebPageProxy::reload):
(WebKit::WebPageProxy::goToBackForwardItem):
(WebKit::WebPageProxy::sendGoToBackForwardItemForFrame):
(WebKit::WebPageProxy::dispatchActivityStateChange):
(WebKit::WebPageProxy::leastRecentlyVisiblePageToUnload):
(WebKit::WebPageProxy::viewIsBecomingVisible):
(WebKit::WebPageProxy::viewIsBecomingInvisible):
* Source/WebKit/UIProcess/WebPageProxy.h:
* Source/WebKit/UIProcess/WebProcessCache.cpp:
(WebKit::WebProcessCache::canCacheProcess const):
* Source/WebKit/UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::prewarmProcess):
(WebKit::WebProcessPool::didReachGoodTimeToPrewarm):
(WebKit::WebProcessPool::reclaimIdleProcesses):
(WebKit::WebProcessPool::handleMemoryPressureWarning):
(WebKit::WebProcessPool::hasAnyProcessPoolUsedSiteIsolation):
(WebKit::WebProcessPool::processForNavigation):
* Source/WebKit/UIProcess/WebProcessPool.h:
* Source/WebKit/UIProcess/WebProcessProxy.cpp:
(WebKit::maxProcessCount):
(WebKit::WebProcessProxy::setProcessCountLimit):
(WebKit::WebProcessProxy::runningProcessCount):
(WebKit::WebProcessProxy::isNearingProcessCountLimit):
(WebKit::WebProcessProxy::hasReachedProcessCountLimit):
(WebKit::WebProcessProxy::didStartRunningProcess):
(WebKit::WebProcessProxy::didStopRunningProcess):
(WebKit::WebProcessProxy::create):
(WebKit::WebProcessProxy::reclaimProcessesIfNeeded):
(WebKit::WebProcessProxy::createForRemoteWorkers):
(WebKit::WebProcessProxy::~WebProcessProxy):
(WebKit::WebProcessProxy::addProvisionalPageProxy):
(WebKit::WebProcessProxy::addRemotePageProxy):
(WebKit::WebProcessProxy::shutDown):
(WebKit::WebProcessProxy::addExistingWebPage):
(WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch):
(WebKit::WebProcessProxy::didFinishLaunching):
(WebKit::WebProcessProxy::establishRemoteWorkerContext):
(WebKit::liveProcessesLRU): Deleted.
(WebKit::WebProcessProxy::markProcessAsRecentlyUsed): Deleted.
* Source/WebKit/UIProcess/WebProcessProxy.h:
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/SiteIsolation.mm:
(TestWebKitAPI::(SiteIsolation, ProcessLimitUnloadsAllProcessesOfLeastRecentlyVisiblePage)):
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/WebContentProcessDidTerminate.mm:
(TEST(WKNavigation, WebProcessLimit)):
(TEST(WKNavigation, WebProcessLimitPrefersUnloadingNonVisiblePages)):

Canonical link: https://commits.webkit.org/319408@main
…serting it

https://bugs.webkit.org/show_bug.cgi?id=322030

Reviewed by Alex Christensen.

FetchOptions::encodePersistent() writes destination as its raw value, and says
that changes to its encoding should bump the NetworkCache Storage format
version. We can just avoid the change in order.

* Source/WebCore/Modules/fetch/FetchRequestDestination.idl:
* Source/WebCore/loader/FetchOptions.h:
* Source/WebCore/loader/FetchOptionsDestination.h:
* Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in:

Canonical link: https://commits.webkit.org/319409@main
rdar://180057740
https://bugs.webkit.org/show_bug.cgi?id=317430

Reviewed by Jean-Yves Avenard.

ISOBoxes and their subclasses are parsed representations of ISO-BMFF media data. In addition
to reading these boxes from files and memory, we may also want to serialize these boxes to
memory, for features like mp4-file authoring and editing.

Add the ability to write a box (and all its children) to memory. Each box must be able to
calculate its own size, so there is a new pair of methods: `partialSize` and `requiredSize`.
Base ISOBoxes boxes need their subclasses' sizes to be fully calculated, hence the split
between the two functions. Also add a `serialize` and virtual `write` method, and a convenience
template `checkedReadSequence` and `checkedWriteSequence` to support reading and writing
data arrays.

Test: Tools/TestWebKitAPI/Tests/WebCore/ISOBox.cpp

* Source/WebCore/platform/graphics/iso/ISOBox.cpp:
(WebCore::ISOBox::ISOBox):
(WebCore::ISOBox::peekBox):
(WebCore::ISOBox::read):
(WebCore::ISOBox::updateSize):
(WebCore::ISOBox::partialSize const):
(WebCore::ISOBox::requiredSize const):
(WebCore::ISOBox::parse):
(WebCore::ISOBox::write const):
(WebCore::ISOBox::serialize const):
(WebCore::ISOFullBox::ISOFullBox):
(WebCore::ISOFullBox::parse):
(WebCore::ISOFullBox::write const):
(WebCore::ISOFullBox::parseVersionAndFlags):
* Source/WebCore/platform/graphics/iso/ISOBox.h:
(WebCore::ISOBox::checkedRead):
(WebCore::ISOBox::checkedReadSequence):
(WebCore::ISOBox::checkedWrite):
(WebCore::ISOBox::checkedWriteSequence):
(WebCore::ISOFullBox::setVersion):
(WebCore::ISOFullBox::setFlags):
* Source/WebCore/platform/graphics/iso/ISOOriginalFormatBox.cpp:
(WebCore::ISOOriginalFormatBox::ISOOriginalFormatBox):
(WebCore::ISOOriginalFormatBox::parse):
* Source/WebCore/platform/graphics/iso/ISOOriginalFormatBox.h:
* Source/WebCore/platform/graphics/iso/ISOProtectionSchemeInfoBox.cpp:
(WebCore::ISOProtectionSchemeInfoBox::ISOProtectionSchemeInfoBox):
(WebCore::ISOProtectionSchemeInfoBox::parse):
(WebCore::ISOProtectionSchemeInfoBox::updateSize):
(WebCore::ISOProtectionSchemeInfoBox::partialSize const):
* Source/WebCore/platform/graphics/iso/ISOProtectionSchemeInfoBox.h:
* Source/WebCore/platform/graphics/iso/ISOProtectionSystemSpecificHeaderBox.cpp:
(WebCore::ISOProtectionSystemSpecificHeaderBox::commonSystemID const):
(WebCore::ISOProtectionSystemSpecificHeaderBox::ISOProtectionSystemSpecificHeaderBox):
(WebCore::ISOProtectionSystemSpecificHeaderBox::peekSystemID):
(WebCore::ISOProtectionSystemSpecificHeaderBox::parse):
(WebCore::ISOProtectionSystemSpecificHeaderBox::parseData):
(WebCore::ISOProtectionSystemSpecificHeaderBox::write const):
(WebCore::ISOProtectionSystemSpecificHeaderBox::writeData const):
(WebCore::ISOProtectionSystemSpecificHeaderBox::partialSize const):
* Source/WebCore/platform/graphics/iso/ISOProtectionSystemSpecificHeaderBox.h:
* Source/WebCore/platform/graphics/iso/ISOSchemeInformationBox.cpp:
(WebCore::ISOSchemeInformationBox::ISOSchemeInformationBox):
(WebCore::ISOSchemeInformationBox::parse):
(WebCore::ISOSchemeInformationBox::updateSize):
(WebCore::ISOSchemeInformationBox::partialSize const):
* Source/WebCore/platform/graphics/iso/ISOSchemeInformationBox.h:
* Source/WebCore/platform/graphics/iso/ISOSchemeTypeBox.cpp:
(WebCore::ISOSchemeTypeBox::ISOSchemeTypeBox):
(WebCore::ISOSchemeTypeBox::parse):
* Source/WebCore/platform/graphics/iso/ISOSchemeTypeBox.h:
* Source/WebCore/platform/graphics/iso/ISOTrackEncryptionBox.cpp:
(WebCore::ISOTrackEncryptionBox::ISOTrackEncryptionBox):
(WebCore::ISOTrackEncryptionBox::parse):
(WebCore::ISOTrackEncryptionBox::parsePayload):
* Source/WebCore/platform/graphics/iso/ISOTrackEncryptionBox.h:
* Source/WebCore/platform/graphics/iso/ISOVTTCue.cpp:
(WebCore::ISOWebVTTCue::ISOWebVTTCue):
* Source/WebCore/platform/graphics/iso/ISOVTTCue.h:
* Tools/TestWebKitAPI/Tests/WebCore/ISOBox.cpp:
(TestWebKitAPI::TEST(ISOBox, ISOFairPlayStreamingPsshBox)):
(TestWebKitAPI::serializeBox):
(TestWebKitAPI::TEST(ISOBox, FairPlay_KeyRequestInfoBox_Write)):
(TestWebKitAPI::TEST(ISOBox, FairPlay_KeyRequestInfoBox_Roundtrip)):
(TestWebKitAPI::TEST(ISOBox, FairPlay_InfoBox_Write)):
(TestWebKitAPI::TEST(ISOBox, FairPlay_InfoBox_Roundtrip)):
(TestWebKitAPI::TEST(ISOBox, FairPlay_KeyAssetIdBox_ParseAndRewrite)):
(TestWebKitAPI::TEST(ISOBox, FairPlay_KeyRequestBox_WriteWithFkriOnly)):
(TestWebKitAPI::TEST(ISOBox, FairPlay_KeyRequestBox_RoundtripWithAssetId)):
(TestWebKitAPI::TEST(ISOBox, FairPlay_InitDataBox_WriteAndRoundtrip)):
(TestWebKitAPI::TEST(ISOBox, FairPlay_PsshBox_ParseWriteParseRoundtrip)):
(TestWebKitAPI::TEST(ISOBox, PsshBox_V1_PartialSizeIncludesSystemIDAndDataSize)):

Canonical link: https://commits.webkit.org/319410@main
https://bugs.webkit.org/show_bug.cgi?id=320910
rdar://183940963

Reviewed by Simon Fraser.

Flips SVGExternalResourcesEnabled from preview to stable.

* Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml:

Canonical link: https://commits.webkit.org/319411@main
rdar://183688843
https://bugs.webkit.org/show_bug.cgi?id=320705

Reviewed by Tim Nguyen.

This patch implements parsing support for @supports named-feature().
The supported name features are hardcoded; it's expected that features
will be added rather sparingly (at most one or two yearly), and only
when it's implemented in WebKit.

Test: imported/w3c/web-platform-tests/css/css-conditional/at-supports-named-feature-001.html

* LayoutTests/imported/w3c/web-platform-tests/css/css-conditional/at-supports-named-feature-001-expected.txt:
    - Test progression.

* LayoutTests/imported/w3c/web-platform-tests/css/css-conditional/at-supports-named-feature-001.html:
    - Add some invalid test cases.
    - Fix a bug where the test uses `Boolean.prototype.toString` to
      serialize a string, but that method returns "false" for every
      input, including `true`.

* Source/WebCore/css/CSSValueKeywords.in:
* Source/WebCore/css/parser/CSSSupportsParser.cpp:
(WebCore::CSSSupportsParser::consumeSupportsFunction):
(WebCore::CSSSupportsParser::consumeSupportsNamedFeatureFunction):
* Source/WebCore/css/parser/CSSSupportsParser.h:

Canonical link: https://commits.webkit.org/319412@main
…owed to play can interrupt play in another app

https://bugs.webkit.org/show_bug.cgi?id=322011
rdar://184545492

Reviewed by Eric Carlson.

Playing a trailer in the TV app on visionOS and then opening a page carrying an
autoplaying video paused the trailer, and it did not resume.

Following 317782@main, void MediaSessionManagerInterface::sessionCanProduceAudioChanged() unconditionally called maybeActivateAudioSession() synchronously;
When the element was first loaded, and not yet known to have audible content,
it was allowed to play and the MediaSession state became Playing,
shortly after when the metadata was loaded and readyState moved to HAVE_METADATA
(having canProduceAudio() now returning true but not yet actually audible
having not loaded any content to render), maybeActivateAudioSession() activated
the AudioSession only to then immediately deny playback and pause the video.
This caused any other application currently playing audio on visionOS or iPadOS to be paused.

The audio session is now activated only for a session whose client would be
allowed to begin playing. PlatformMediaSessionInterface gains playbackPermitted(),
defaulting to true so that AudioContext, MediaSession and MediaStream sessions are
unaffected, and MediaElementSession answers it with
playbackStateChangePermitted(MediaPlaybackState::Playing).
MediaSessionManagerInterface::audioSessionActivationRequired() is
activeAudioSessionRequired() plus that condition and is consulted only by
maybeActivateAudioSession(). maybeDeactivateAudioSession() keeps using
activeAudioSessionRequired(): the permission is state-dependent and can be false
for a session that is legitimately playing, and deactivation must stay
conservative.

Asserting that no activation happened needs the GPU process's view, as a web
process's own AudioSession reports the state it asked for and reports it
optimistically. AudioSession counts transitions from inactive to active, and the
count is readable through internals.systemAudioSessionActivationCount(), plumbed
the way systemAudioSessionCategory() already is.

* LayoutTests/fast/harness/internals-object-property-access-on-window-without-frame-crash.html:
Skip the new internals function, which sends IPC behind AllowTestOnlyIPC that this test does not set.
* LayoutTests/media/audio-session-not-activated-for-denied-audible-element-expected.txt: Added.
* LayoutTests/media/audio-session-not-activated-for-denied-audible-element.html: Added.
* LayoutTests/media/audio-session-not-activated-when-unmuting-denied-element-expected.txt: Added.
* LayoutTests/media/audio-session-not-activated-when-unmuting-denied-element.html: Added.
* LayoutTests/platform/glib/TestExpectations: Skip both, no USE(AUDIO_SESSION) support.
* Source/WebCore/html/MediaElementSession.h:
* Source/WebCore/platform/audio/AudioSession.cpp:
(WebCore::AudioSession::tryToSetActive): Count activations.
* Source/WebCore/platform/audio/AudioSession.h:
* Source/WebCore/platform/audio/MediaSessionManagerInterface.cpp:
(WebCore::MediaSessionManagerInterface::audioSessionActivationRequired const): Added.
(WebCore::MediaSessionManagerInterface::maybeActivateAudioSession): Use it.
* Source/WebCore/platform/audio/MediaSessionManagerInterface.h:
* Source/WebCore/platform/audio/PlatformMediaSessionInterface.h:
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::systemAudioSessionActivationCount): Added.
* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:
* Source/WebKit/GPUProcess/media/RemoteAudioSessionProxy.cpp:
(WebKit::RemoteAudioSessionProxy::systemActivationCountForTesting): Added.
* Source/WebKit/GPUProcess/media/RemoteAudioSessionProxy.h:
* Source/WebKit/GPUProcess/media/RemoteAudioSessionProxy.messages.in:
* Source/WebKit/WebProcess/GPU/media/RemoteAudioSession.cpp:
(WebKit::RemoteAudioSession::systemActivationCountForTesting): Added.
* Source/WebKit/WebProcess/GPU/media/RemoteAudioSession.h:

Canonical link: https://commits.webkit.org/319413@main
https://bugs.webkit.org/show_bug.cgi?id=321523
rdar://184633468

Reviewed by Basuke Suzuki.

In 317835@main I thought there was no way to get a sec_protocol_metadata_t from a
nw_protocol_metadata_t for WebTransport, so I introduced SecurityProtocolMetadata
to get it from the TLS handshake and I was going to introduce a new function
nw_webtransport_metadata_copy_sec_protocol_metadata to get it directly.  In my review
feedback, I was informed that there's already a way to get the sec_protocol_metadata_t.
It's different if WebTransport is using H2 or H3, but it works both ways.

I introduce a test that not only uses H2 with WebTransport for the first time in
WebKit's tests, but it also generates keying material on the server to verify that
the client and the server are able to generate the exact same bytes, which is the
whole point of exportKeyingMaterial but it's currently not tested in wpt.

Test: Tools/TestWebKitAPI/Tests/WebKit/WKWebView/WebTransport.mm

* Source/WebCore/PAL/pal/spi/cocoa/NetworkSPI.h:
* Source/WebKit/Configurations/AllowedSPI.toml:
* Source/WebKit/NetworkProcess/cocoa/NetworkSoftLink.h:
* Source/WebKit/NetworkProcess/cocoa/NetworkSoftLink.mm:
* Source/WebKit/NetworkProcess/webtransport/NetworkTransportSession.h:
(WebKit::NetworkTransportSession::SecurityProtocolMetadata::create): Deleted.
(WebKit::NetworkTransportSession::SecurityProtocolMetadata::receivedMetadata): Deleted.
(WebKit::NetworkTransportSession::SecurityProtocolMetadata::metadata const): Deleted.
* Source/WebKit/NetworkProcess/webtransport/cocoa/NetworkTransportSessionCocoa.mm:
(WebKit::NetworkTransportSession::create):
(WebKit::NetworkTransportSession::NetworkTransportSession):
(WebKit::createParameters):
(WebKit::NetworkTransportSession::securityMetadata const):
(WebKit::NetworkTransportSession::exportKeyingMaterial):
* Tools/TestWebKitAPI/Helpers/cocoa/NetworkConnection.h:
* Tools/TestWebKitAPI/Helpers/cocoa/NetworkConnection.mm:
(TestWebKitAPI::securityMetadata):
(TestWebKitAPI::ConnectionGroup::exportKeyingMaterial const):
* Tools/TestWebKitAPI/Helpers/cocoa/WebTransportServer.h:
* Tools/TestWebKitAPI/Helpers/cocoa/WebTransportServer.mm:
(TestWebKitAPI::WebTransportServer::WebTransportServer):
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/WebTransport.mm:
(TestWebKitAPI::ExportKeyingMaterial)):

Canonical link: https://commits.webkit.org/319414@main
…/the-audio-api/the-audionode-interface/audionode-channel-rules.html is a flaky crash

https://bugs.webkit.org/show_bug.cgi?id=321961
rdar://185147134

Unreviewed test gardening

* LayoutTests/platform/mac-wk2/TestExpectations:

Canonical link: https://commits.webkit.org/319415@main
…only be used in the WKContentWorld.pageWorld

https://bugs.webkit.org/show_bug.cgi?id=322036
rdar://185228555

Reviewed by Alex Christensen.

This patch implements a version of WKWebView._hitTest(at:inFrameCoordinates:) that allows to specify a WKContentWorld.

* Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _hitTestAtPoint:inFrameCoordinateSpace:completionHandler:]):
(-[WKWebView _hitTestAtPoint:inFrameCoordinateSpace:inContentWorld:completionHandler:]):
* Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h:
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::hitTestAtPoint):
* Source/WebKit/UIProcess/WebPageProxy.h:
* Source/WebKit/WebProcess/WebPage/WebFrame.cpp:
(WebKit::createJSHandle):
(WebKit::WebFrame::createAndPrepareToSendJSHandle const):
* Source/WebKit/WebProcess/WebPage/WebFrame.h:
* Source/WebKit/WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::hitTestAtPoint):
* Source/WebKit/WebProcess/WebPage/WebPage.h:
* Source/WebKit/WebProcess/WebPage/WebPage.messages.in:
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/SiteIsolation.mm:
(TestWebKitAPI::(SiteIsolation, HitTesting)):
(TestWebKitAPI::(SiteIsolation, HitTestingInContentWorld)):

Canonical link: https://commits.webkit.org/319416@main
…ork.html is a flakey text failure

https://bugs.webkit.org/show_bug.cgi?id=225430
rdar://77587091

Reviewed by Alexey Proskuryakov.

CFNetwork was missing counting a \r\n of the chunked response before, but now
with it correctly counts them.  This also matches the value of the gtk test expectations.

318278@main made it happen more reliably by using the same network loader for tests as our users use.

* LayoutTests/platform/mac-site-isolation/TestExpectations:
* LayoutTests/platform/mac-wk2/TestExpectations:
* LayoutTests/platform/mac/http/tests/inspector/network/resource-sizes-network-expected.txt:

Canonical link: https://commits.webkit.org/319417@main
…ntPolicy /Volumes/Data/worker/Apple-Tahoe-Debug-Build/build/Source/WebCore/loader/DocumentLoader.cpp

https://bugs.webkit.org/show_bug.cgi?id=320913
rdar://183941470

Reviewed by Alex Christensen.

318278@main turned the CFNetwork NW loader on unconditionally. For
multipart/x-mixed-replace it hands the network process the follow-up parts, their
data and the end of the load without waiting for the previous part's response
completion handler, whose content-policy check is asynchronous
(DocumentLoader::responseReceived() -> checkContentPolicy() IPCs to the
UIProcess).

313118@main made NetworkResourceLoader tolerate the extra responses by queuing
the response completion handlers in a Deque instead of overwriting a single one,
but it kept forwarding every message to the WebProcess immediately. The
WebProcess cannot process anything past a response it has not validated yet: a
follow-up response hits ASSERT(!m_waitingForContentPolicy) in
DocumentLoader::responseReceived(), and a follow-up didFinishLoading() runs
SubresourceLoader::didFinishLoading() through releaseResources(), which clears
the loader's identifier, so WebResourceLoader never sends
ContinueDidReceiveResponse and the load hangs.

Re-serialize delivery, restoring the one-part-at-a-time semantics the legacy
NSURLSession loader provided. didReceiveResponse() claims the pipeline via
m_isProcessingResponse and wraps the completion handler so that it is released
once the response is resolved, which for a main resource is when the WebProcess
answers ContinueDidReceiveResponse. While the pipeline is claimed, every
follow-up message is held in m_deferredMessages, and it is replayed in order once
the response is released, stopping at the next response so it too waits.

The state is tracked explicitly rather than derived from
m_responseCompletionHandlers for two reasons. didReceiveResponse() can take
asynchronous steps before appending the handler (processClearSiteDataHeader()),
and nothing may be delivered in that window. It also resolves responses without
appending anything at all: when a main resource is blocked by CSP frame-ancestors
or X-Frame-Options, by COOP/COEP, by NetworkLoadChecker::validateResponse(), by
content filtering, or is dropped for keepalive, it answers PolicyAction::Ignore
having sent no DidReceiveResponse. Messages queued behind such a response are
dropped rather than replayed, so that WebContent is never handed the body of a
part the network process just blocked, nor a DidReceiveData with no preceding
DidReceiveResponse. Deferred messages are likewise dropped with
PolicyAction::Ignore on teardown so their completion handlers are still answered,
and the queue is bounded so a WebProcess that never answers cannot grow the
network process' memory without limit.

This is a workaround for the CFNetwork bug, so it is gated on the new
HAVE(BROKEN_MULTIPART_RESPONSE_FLOW_CONTROL), on by default on COCOA ports. A
FIXME points at rdar://185073080 to turn it off on platforms that have the
CFNetwork fix.

Nothing outside multipart is affected: m_isProcessingResponse is false when those
messages arrive for subresources and for single-response loads.

No new tests, unskipped existing test.

* LayoutTests/platform/mac-wk2/TestExpectations:
* Source/WTF/wtf/PlatformHave.h:
* Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::~NetworkResourceLoader):
(WebKit::NetworkResourceLoader::convertToDownload):
(WebKit::NetworkResourceLoader::didReceiveResponse):
(WebKit::NetworkResourceLoader::didReceiveBuffer):
(WebKit::NetworkResourceLoader::didFinishLoading):
(WebKit::NetworkResourceLoader::didFailLoading):
(WebKit::NetworkResourceLoader::continueDidReceiveResponse):
(WebKit::NetworkResourceLoader::responseProcessingCompleted):
(WebKit::NetworkResourceLoader::deliverDeferredMessages):
(WebKit::NetworkResourceLoader::cancelDeferredMessages):
(WebKit::NetworkResourceLoader::failDueToExcessiveDeferredMessages):
* Source/WebKit/NetworkProcess/NetworkResourceLoader.h:

Canonical link: https://commits.webkit.org/319418@main
… again

https://bugs.webkit.org/show_bug.cgi?id=322054
rdar://185245662

Reviewed by Dan Hecht.

Basically applying the similar optimization to 318347@main. Let's avoid
lexing int32 value twice in the fast path.

* Source/JavaScriptCore/runtime/LiteralParser.cpp:
(JSC::reviverMode>::Lexer::lexNumber):

Canonical link: https://commits.webkit.org/319419@main
https://bugs.webkit.org/show_bug.cgi?id=322048
rdar://185243612

Reviewed by Sosuke Suzuki.

This patch introduces deferred Array materialization mechanism in JSON.parse.
Instead of placing an element each time, we push it to the stack, and we
materialize Array at the end of Array literal. This stack is used for
arrays nested way, so when materializing, we use the slice between
[stackBase, end). This avoids growing and reallocating butterflies,
which reduces wasted allocation during JSON.parse.

Also we do drive-by fixes,

1. MarkedVector::append ends up calling slowAppend after it gets
   mallocBase(). This is inefficient and not correct. We should do it
   only when (1) expanding capacity or (2) newly registering a
   m_markSet.
2. Accessing outOfLineCapacity requires some additional loads. But we do
   not need to care about it when offset is not reaching to
   firstOutOfLineOffset. Let's avoid loading them.

Test: JSTests/stress/json-parse-array-materialization.js

* JSTests/stress/json-parse-array-materialization.js: Added.
(shouldBe):
(shouldThrow):
(Array.isArray):
* Source/JavaScriptCore/runtime/LiteralParser.cpp:
(JSC::reviverMode>::materializeArray):
(JSC::requires):
* Source/JavaScriptCore/runtime/LiteralParser.h:
* Source/JavaScriptCore/runtime/MarkedVector.h:
(JSC::MarkedVector::append):

Canonical link: https://commits.webkit.org/319420@main
…k per spec

https://bugs.webkit.org/show_bug.cgi?id=313736
rdar://182678875

Reviewed by Pascoe.

A credential request's promise is now settled from a queued task, as the spec requires. It
used to settle straight away, or from inside the picker's dismissal callback. The promise,
the abort signal and the abort algorithm also move off the per-page coordinator and onto a
new DigitalCredentialsSession, which belongs to the document that asked for the credential.
The coordinator said it was an ActiveDOMObject, but it is created before the main frame has
a document, so it was never really registered as one. That meant nothing told it when a
document was stopped or suspended, which is why get-non-fully-active.https.html kept
failing (webkit.org/b/317884). Its mac-wk2 and ios expectations are removed.

When the picker returns an answer we no longer ask it to dismiss, because it dismisses
itself in the same call. The abort path still asks it to, since nothing there guarantees the
picker is gone before the promise settles. There is no test for a document that is suspended
and then destroyed. This also stops the picker reporting a good response twice.

Canonical link: https://commits.webkit.org/319421@main
https://bugs.webkit.org/show_bug.cgi?id=322002

Reviewed by Darin Adler.

Fixes crash that happens when a StyleSingleAnimationRange's offset is a
calc value and the Animation.rangeStart or Animation.rangeEnd getters are
called. The code was unconditionally accessing the result of tryPercentage()
which returns std::nullopt in the calc case. To fix this, we use the switchOn
form to ensure all alternatives are handled.

Test: fast/animation/css-animation-range-calc-crash.html
* LayoutTests/fast/animation/css-animation-range-calc-crash-expected.txt: Added.
* LayoutTests/fast/animation/css-animation-range-calc-crash.html: Added.
* Source/WebCore/style/values/animations/StyleSingleAnimationRange.cpp:

Canonical link: https://commits.webkit.org/319422@main
…undaries (to reduce false positives when redacting PII)

https://bugs.webkit.org/show_bug.cgi?id=322061
rdar://185254024

Reviewed by Abrar Rahman Protyasha.

Adjust the string replacement heuristics for text extractions, such that it only redacts text if it
spans word boundaries, in order to limit false positives (which may actually cause us to indirectly
and unintentionally leak information, which the agent would not have otherwise observed).

Test: TextExtractionTests.ReplacementStringsWordBoundaries

* Source/WebKit/Shared/TextExtractionToStringConversion.cpp:
(WebKit::isWordCharacter):
(WebKit::anchorsToWordBoundary):
(WebKit::matchIsWordBounded):
(WebKit::applyReplacements):
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/TextExtractionTests.mm:
(TestWebKitAPI::TEST(TextExtractionTests, ReplacementStringsWordBoundaries)):

Canonical link: https://commits.webkit.org/319423@main
…credentials

https://bugs.webkit.org/show_bug.cgi?id=322068

Reviewed by Michael Catanzaro.

nce an authentication challenge has been answered for a host, libsoup's
SoupAuthManager stamps the cached credentials onto every later request in that
protection space, replacing an Authorization header the page had set itself.
The Fetch standard uses the cached credential only "If httpRequest's header
list does not contain `Authorization`", and the Cocoa and curl ports already
behave that way.

Set SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE, libsoup's per-message opt-out, when the
request already carries an Authorization header. A challenge still reaches the
authentication handler and the retry authenticates as before.

Test: Tools/TestWebKitAPI/Tests/WebKit/WKWebView/glib/TestAuthentication.cpp

* Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp:
(WebKit::NetworkDataTaskSoup::createRequest):
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/glib/TestAuthentication.cpp:
(testWebViewAuthenticationPageProvidedAuthorizationHeader):
(serverCallback):
(beforeAll):

Canonical link: https://commits.webkit.org/319424@main
bnham and others added 13 commits August 21, 2026 16:33
https://bugs.webkit.org/show_bug.cgi?id=322231
rdar://185461584

Reviewed by Ryosuke Niwa.

A newly created page can run with the wrong hidden page throttling timer state:

- If the page is created in a new WebProcess, then the initial state is incorrect, because we don't
  pass the hidden page throttling state as part of process creation.

- If the page is created in an existing WebProcess, then the initial state is incorrect, because we
  don't store the last used hidden page throttling state anywhere and apply it to the newly created
  page.

Fix this by adding hiddenPageDOMTimerThrottlingIncreaseLimit as a process creation parameter and
also store it globally on the WebProcess side.

This happens more when Site Isolation is enabled, since creating a new iframe while hidden will
create a new process with potentially stale throttling flags.

* LayoutTests/http/tests/site-isolation/hidden-page-dom-timer-throttling-limit-expected.txt: Added.
* LayoutTests/http/tests/site-isolation/hidden-page-dom-timer-throttling-limit.html: Added.
* LayoutTests/http/tests/site-isolation/resources/dom-timer-throttling-state-frame.html: Added.
* Source/WebCore/page/Page.h:
(WebCore::Page::domTimerAlignmentIntervalIncreaseLimit const):
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::domTimerAlignmentInterval const):
(WebCore::Internals::domTimerAlignmentIntervalIncreaseLimit const):
* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:
* Source/WebKit/Shared/WebProcessCreationParameters.h:
* Source/WebKit/Shared/WebProcessCreationParameters.serialization.in:
* Source/WebKit/UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::initializeNewWebProcess):
(WebKit::WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit):
* Source/WebKit/UIProcess/WebProcessPool.h:
* Source/WebKit/WebProcess/WebProcess.cpp:
(WebKit::WebProcess::initializeWebProcess):
(WebKit::WebProcess::createWebPage):
(WebKit::WebProcess::setHiddenPageDOMTimerThrottlingIncreaseLimit):
* Source/WebKit/WebProcess/WebProcess.h:

Canonical link: https://commits.webkit.org/319630@main
…ase enum values.

https://bugs.webkit.org/show_bug.cgi?id=322307
rdar://185544976

Reviewed by Tim Nguyen.

The values of GridLanesLayout::Phase repeated the name of the enum
itself (LayoutPhase, MinContentPhase, MaxContentPhase). Drop the
redundant suffix so the values read as Phase::Layout, Phase::MinContent
and Phase::MaxContent. No change in behavior.

* Source/WebCore/rendering/GridLanesLayout.cpp:
(WebCore::GridLanesLayout::calculateGridLanesIntrinsicLogicalWidth):
(WebCore::GridLanesLayout::insertIntoGridAndLayoutItem):
* Source/WebCore/rendering/GridLanesLayout.h:
* Source/WebCore/rendering/RenderGrid.cpp:
(WebCore::RenderGrid::layoutGridLanes):
(WebCore::RenderGrid::computeIntrinsicLogicalWidths):

Canonical link: https://commits.webkit.org/319631@main
… in inline layout

https://bugs.webkit.org/show_bug.cgi?id=321473
<rdar://problem/185157814>

Reviewed by Antti Koivisto.

Marker content is inline content: what it measures, where it sits on the line and how bidi orders it are inline layout's answers to give.
Every kind of marker goes through it except a disc, circle or square, which the marker measures and paints itself from the font metrics,
into a box it sizes for that purpose alone. So marker drawing exists twice, and the two have to be kept in step.

It is also what stands in the way of making an inside marker an inline box, which is where this is going:
an inline box has no box of its own to paint into, so anything the marker draws for itself has nowhere to go.

A list-style-image that fails to load now rebuilds the marker rather than relaying it out. It falls
back to its list-style-type, and that text needs renderers the marker was not built with. Nothing
about the element's style changed, and a pseudo-element list item is only revisited through its host
(RenderTreeUpdater::updateAfterDescendants), so imageChanged() invalidates the host's renderers
instead of the element's style.

* Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp:
(WebCore::Layout::TextUtil::width):
* Source/WebCore/layout/integration/LayoutIntegrationBoxTreeUpdater.cpp:
(WebCore::LayoutIntegration::markerTextSynthesizesGlyph):
(WebCore::LayoutIntegration::BoxTreeUpdater::createLayoutBox):
(WebCore::LayoutIntegration::updateContentCharacteristic):
(WebCore::LayoutIntegration::BoxTreeUpdater::updateContent):
* Source/WebCore/layout/layouttree/LayoutInlineTextBox.h:
(WebCore::Layout::InlineTextBox::hasSynthesizedGlyph const):
* Source/WebCore/rendering/RenderListMarker.cpp:
(WebCore::RenderListMarker::textNeedsBidiResolution const):
(WebCore::RenderListMarker::needsContentContainer const):
(WebCore::RenderListMarker::paint):
(WebCore::RenderListMarker::layoutContentContainer):
(WebCore::RenderListMarker::imageChanged):
(WebCore::RenderListMarker::updateContent):
(WebCore::RenderListMarker::updateContentContainerText):
(WebCore::RenderListMarker::computeIntrinsicLogicalWidthContributions):
(WebCore::RenderListMarker::updateInlineMargins):
(WebCore::RenderListMarker::relativeMarkerRect):
(WebCore::RenderListMarker::synthesizesGlyph const):
(WebCore::RenderListMarker::drawsBulletShape const): Deleted.
* Source/WebCore/rendering/RenderListMarker.h:
* Source/WebCore/rendering/RenderTreeAsText.cpp:
(WebCore::write):
* Source/WebCore/rendering/TextBoxPainter.cpp:
(WebCore::TextBoxPainter::paint):
(WebCore::TextBoxPainter::hasSynthesizedGlyph const):
(WebCore::TextBoxPainter::paintSynthesizedGlyph):
* Source/WebCore/rendering/TextBoxPainter.h:

Canonical link: https://commits.webkit.org/319632@main
…e/aria-owns-id-change.html (layout-tests) is a constant Timeout.

https://bugs.webkit.org/show_bug.cgi?id=322313
rdar://185553044

Unreviewed test gardening.

* LayoutTests/platform/mac/TestExpectations:

Canonical link: https://commits.webkit.org/319633@main
https://bugs.webkit.org/show_bug.cgi?id=322303
rdar://185541345

Reviewed by Dan Hecht.

We found that WasmWorklist's PriorityQueue's ordering is opposite and
not correct. The reason is that PriorityQueue and std::priority_queue's
comparator is opposite and when changing std::priority_queue to
PriorityQueue, we didn't change the comparator. But this is error-prone.
This patch fixes that issue and also change PriorityQueue's comparator
to align it to std::priority_queue's one. So by default, taking
std::less, and populating the greatest value first. Doing the same in
PriorityQueue.

Test: Tools/TestWebKitAPI/Tests/WTF/PriorityQueue.cpp

* Source/JavaScriptCore/b3/air/AirAllocateRegistersByGreedy.cpp:
(JSC::B3::Air::Greedy::TmpPriority::operator<):
(JSC::B3::Air::Greedy::TmpPriority::isHigherPriority): Deleted.
* Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:
(JSC::DFG::InliningCandidateIsLowerPriority::operator() const):
(JSC::DFG::InliningPlan::build):
(JSC::DFG::isHigherPriorityInliningCandidate): Deleted.
* Source/JavaScriptCore/wasm/WasmInliningDecision.cpp:
(JSC::Wasm::InliningNodeIsLowerPriority::operator() const):
(JSC::Wasm::InliningDecision::expand):
(JSC::Wasm::isHigherPriority): Deleted.
* Source/JavaScriptCore/wasm/WasmWorklist.cpp:
(JSC::Wasm::Worklist::completePlanSynchronously):
* Source/JavaScriptCore/wasm/WasmWorklist.h:
(JSC::Wasm::Worklist::QueueElementIsLowerPriority::operator() const):
(JSC::Wasm::Worklist::isHigherPriority): Deleted.
* Source/WTF/wtf/MathExtras.h:
(isLessThan): Deleted.
(isLessThanEqual): Deleted.
(isGreaterThan): Deleted.
(isGreaterThanEqual): Deleted.
* Source/WTF/wtf/PriorityQueue.h:
* Source/WebCore/loader/ResourceMonitorThrottler.h:
* Source/WebCore/page/ImageAnalysisQueue.h:
(WebCore::ImageAnalysisQueue::firstIsHigherPriority): Deleted.
* Source/WebKit/NetworkProcess/cache/NetworkCacheStorage.cpp:
(WebKit::NetworkCache::Storage::ReadOperationIsLowerPriority::operator() const):
(WebKit::NetworkCache::Storage::isHigherPriority): Deleted.
* Source/WebKit/NetworkProcess/cache/NetworkCacheStorage.h:
* Tools/TestWebKitAPI/Tests/WTF/PriorityQueue.cpp:
(enqueue):
(dequeue):
(TEST(WTF_PriorityQueue, Basic)):
(TEST(WTF_PriorityQueue, ReversedComparator)):
(MoveOnlyIsLessThan::operator() const):
(MoveOnlyIsGreaterThan::operator() const):
(TEST(WTF_PriorityQueue, MoveOnly)):
(TEST(WTF_PriorityQueue, DecreaseKey)):
(TEST(WTF_PriorityQueue, IncreaseKey)):
(TEST(WTF_PriorityQueue, IncreaseKeyWithAReversedComparator)):
(TEST(WTF_PriorityQueue, Iteration)):
(TEST(WTF_PriorityQueue, EqualElementsAreAValidHeap)):
(ReversibleComparator::operator() const):
(TEST(WTF_PriorityQueue, IsValidHeapDetectsAGreaterChild)):
(PrioritizedTaskIsLowerPriority::operator() const):
(TEST(WTF_PriorityQueue, IncreaseKeyMovesTowardsTheFront)):
(TEST(WTF_PriorityQueue, RandomActions)):
(isHigherPriority): Deleted.
(TEST(WTF_PriorityQueue, CustomPriorityFunction)): Deleted.

Canonical link: https://commits.webkit.org/319634@main
…roke

https://bugs.webkit.org/show_bug.cgi?id=322250
rdar://185485580

Reviewed by Simon Fraser.

PathOrShapeGradientApplier bracketed each gradient apply in its own
context->save()/restore() pair, costing two IPC messages per gradient-filled shape
paint when rendering in the GPU process. The pair has been vestigial since
32921@main moved the CTM mutations it was originally added for into the gradient's
own space transform.

Remove it. All callers already bracket the apply/postApply sequence in an outer
GraphicsContextStateSaver, and LegacyRenderSVGResourceSolidColor has never restored
this state either, so gradient paint now behaves like solid-color paint.

Worth ~2.5% on MotionMark 1.3 Suits.

* Source/WebCore/rendering/svg/legacy/LegacyRenderSVGResourceGradient.cpp:
(WebCore::PathOrShapeGradientApplier::applyResource):
(WebCore::PathOrShapeGradientApplier::postApplyResource):

Canonical link: https://commits.webkit.org/319635@main
https://bugs.webkit.org/show_bug.cgi?id=322259
rdar://185490398

Reviewed by Kimmo Kinnunen.

Timeout's constructor eagerly computes ApproximateTime::now() + delta, but
StreamClientConnection::send() only consults the deadline if tryAcquire() has to
block, which is rare since the ring buffer normally has room. The cost was paid
on every message, and showed up in MotionMark 1.3 Suits profiles where IPC
accounted for ~22% of samples.

Add StreamClientConnectionBuffer::acquireNoWait() for the non-blocking case and
try it first when the destination ID is unchanged, falling back to the existing
Timeout-based path otherwise. Skipping trySendDestinationIDIfNeeded() on that
fast path is equivalent to the early return it would have taken, since
m_currentDestinationID is only assigned after the SetStreamDestinationID message
has been released. Timeout keeps its by-value semantics, so the shared budget
across trySendDestinationIDIfNeeded() + tryAcquire() is unaffected.

* Source/WebKit/Platform/IPC/StreamClientConnection.h:
(IPC::StreamClientConnection::send):
* Source/WebKit/Platform/IPC/StreamClientConnectionBuffer.h:
(IPC::StreamClientConnectionBuffer::acquireNoWait):

Canonical link: https://commits.webkit.org/319636@main
https://bugs.webkit.org/show_bug.cgi?id=255434
rdar://108030923

Reviewed by Alan Baradlay.

Now that margin-trim only applies to block containers, RenderBlockFlow is the
only renderer that can trim one of its children's margins. The
machinery for it does not need to sit on RenderBox anymore, where every other
layout system can see it.

To help cleanup the code a bit and make the responsibility clear we can
move most of the code that lives in RenderBox into RenderBlockFlow.

* Source/WebCore/rendering/RenderBox.cpp:
(WebCore::RenderBox::computeLogicalWidth const):
(WebCore::RenderBox::computeOrTrimInlineMargin const): Deleted.
Instead of having a "compute or trim," function let's just replace it
with the code inline since it's really only used in one place.

Canonical link: https://commits.webkit.org/319637@main
https://bugs.webkit.org/show_bug.cgi?id=322240
rdar://181259623

Reviewed by Sihui Liu.

This can happen when a LocalFrame is trying to access its RemoteFrame parent, as the RemoteFrame
is being destroyed -- for example in response to the message WebPage::frameWasRemovedInAnotherProcess.

Fix this by by calling detachFromParent on all the children in FrameTree::~FrameTree().

No new tests, since reproducing this issue depends on having an extension installed in Safari.

* Source/WebCore/page/FrameTree.cpp:
(WebCore::FrameTree::~FrameTree):

Canonical link: https://commits.webkit.org/319638@main
https://bugs.webkit.org/show_bug.cgi?id=322300

Reviewed by Sihui Liu.

Always enable UseUIProcessForBackForwardItemLoading in the test.

* LayoutTests/fast/events/suspend-timers.html:

Canonical link: https://commits.webkit.org/319639@main
…cus is inside the dialog or it was modal

https://bugs.webkit.org/show_bug.cgi?id=322310
rdar://185549474

Reviewed by Tim Nguyen.

The close the dialog steps gate the focus restore [1]:

    If subject's node document's focused area of the document's DOM anchor is a
    shadow-including inclusive descendant of subject, or wasModal is true, then
    run the focusing steps for element; the viewport should not be scrolled by
    doing this step.

We ran that unconditionally, so closing a non-modal dialog yanked focus back
even when the author had moved it elsewhere. The stray focus change is
observable: it fires focusin, letting a listener re-enter the dialog's own state
machine. Capture wasModal after removing the open attribute, matching the spec's
step order, and gate on it.

The check uses the composed tree, not the shadow-including tree: a node slotted
into a dialog inside a shadow root is not a shadow-including descendant, yet
focus restore is expected for it. See whatwg/html#8904 [2], cited by
dialog-focus-previous-outside.html for that case.

This removes the FIXME from 319173@main and fixes the bug by handling focus
properly.

[1] https://html.spec.whatwg.org/multipage/interactive-elements.html#close-the-dialog
[2] whatwg/html#8904

* LayoutTests/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-closedby-corner-cases-expected.txt: Progression
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-focus-previous-outside-expected.txt: Ditto
* Source/WebCore/html/HTMLDialogElement.cpp:
(WebCore::HTMLDialogElement::close):

Canonical link: https://commits.webkit.org/319640@main
…deBlock

Upstream 3d0e6c1 moved the parse results (features, line count, end
column, the source URL directives) from UnlinkedCodeBlock to
UnlinkedGlobalCodeBlock. Both callers pass a program or module code block.
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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

Upstream 9a18171 replaced linux/RealTimeThreads.cpp with
linux/HighPriorityThreads.cpp. The fork's Android source list still named
the removed file.
Comment thread CMakePresets.json

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks — 6281729 fixes the Android PlatformJSCOnly.cmake entry (now builds linux/HighPriorityThreads.cpp), and this pass found no further issues.

Given the scope — a 387-commit upstream merge with hand-resolved conflicts across YarrJIT, URLParser, Atomics.wait termination, the module loader, CodeCache/CachedTypes, and ThreadingPOSIX — a human review of the conflict resolutions is still warranted.

What was reviewed:

  • Confirmed the ANDROID branch of PlatformJSCOnly.cmake now lists HighPriorityThreads.cpp and RealTimeThreads.cpp is gone from the tree.
  • Re-checked the other fork-only build lists for stale references to files this merge deletes/renames — none found.
  • Spot-checked the recordParseFromUnlinkedCodeBlock follow-up (d7ff6be) against the UnlinkedGlobalCodeBlock split from 3d0e6c14b1.
Extended reasoning...

Overview

This PR merges upstream WebKit baf4a9a7ec0b (387 commits, 82 touching JSC/WTF/bmalloc) into the Bun fork. Beyond the mechanical merge, it includes hand-resolved conflicts in yarr/YarrJIT.cpp, WTF/URLParser.{cpp,h}, WaiterListManager::waitSyncImpl (Atomics.wait termination, reconciling upstream 03e836de2f with the fork's #432), JSModuleLoader/JSMicrotask (dropping the fork's #262 in favor of upstream's f324cca020), CodeCache.cpp, CachedTypes.cpp (bitfield layout across the new CachedGlobalCodeBlock split), SyntheticModuleRecord, and ThreadingPOSIX.cpp (opting out of upstream's new Linux sched_setattr policy under USE(BUN_JSC_ADDITIONS)). It also removes @newPromiseCapability, requiring coordinated changes on the Bun side. Two follow-up commits landed after the merge: d7ff6bea27 (adapting recordParseFromUnlinkedCodeBlock to the UnlinkedGlobalCodeBlock split) and 6281729b4e (the Android CMake fix from my previous review).

Previous review resolved

My prior review flagged that the fork-only elseif (ANDROID) branch in Source/WTF/wtf/PlatformJSCOnly.cmake still listed the deleted linux/RealTimeThreads.cpp. Commit 6281729b4e renames it to linux/HighPriorityThreads.cpp, which I've verified at HEAD (line 127). The bug hunting system found no further issues this pass.

Security risks

No new attack surface is introduced by the merge mechanics themselves; the upstream commits are already public and reviewed. The hand-resolved conflicts do touch security-adjacent code (Yarr JIT codegen, CachedTypes serialized layout, module loader error handling), where a mis-merge could introduce memory-safety or cache-poisoning issues — which is precisely why these resolutions need human eyes rather than automated sign-off.

Level of scrutiny

High. This is not a mechanical change: each conflict resolution in the description encodes a judgment call (keep fork, take upstream, or blend), several of which the description explicitly flags for the reviewer ("Drop that hunk if following upstream is preferred" for the ThreadingPOSIX scheduling opt-out; the #262 drop with a repro-based justification). The bytecode cache layout change (CachedCodeBlock/CachedGlobalCodeBlock split with the fork's MSVC-portable bitfields) and the WaiterListManager reconciliation are correctness-critical and non-obvious.

Other factors

The author reports a debug+ASAN build passes, the new upstream regexp tests pass in both JIT and interpreter mode, and Bun links against the tree — good signal, but not a substitute for reviewing the conflict hunks. The PR description is unusually thorough and makes a human review tractable; it also documents an explicit policy question (Linux thread scheduling opt-out) that a maintainer should decide on. Given all of this, deferring to a human reviewer is the right call even with zero automated findings.

@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown

Preview Builds

Commit Release Date
d0fae3b3 autobuild-preview-pr-488-d0fae3b3 2026-08-23 09:46:56 UTC
6281729b autobuild-preview-pr-488-6281729b 2026-08-22 06:16:30 UTC

robobun added a commit to oven-sh/bun that referenced this pull request Aug 22, 2026
Points WEBKIT_VERSION at the oven-sh/WebKit#488 preview build, which merges
upstream WebKit main at baf4a9a7ec0b into the fork (387 commits since the
previous merge base 47f7250137c6, 82 of them in JavaScriptCore, WTF or
bmalloc) and includes the fork's commits since b7f217b4a6.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for the fix in 6281729 — the ANDROID branch of PlatformJSCOnly.cmake now lists linux/HighPriorityThreads.cpp, so the Android CI configure will succeed. I re-reviewed after that commit and the origin/main merge and didn't find further issues. Given the scope — a 387-commit upstream merge with hand-resolved conflicts in YarrJIT, Atomics.wait termination, the module loader, CachedTypes layout, and Linux thread scheduling — a human pass over the conflict resolutions is still worthwhile.

Checked on this pass: the ThreadingPOSIX.cpp USE(BUN_JSC_ADDITIONS) guard around updateSchedulingAttributes is intact; the waitSyncImpl merge keeps the fork's under-lock termination delivery with upstream's throwTerminationExceptionIfNeeded() at the callers; the CachedCodeBlock bitfield-width changes for #141 portable layout are preserved after fields moved to CachedGlobalCodeBlock; and recordParseFromUnlinkedCodeBlock's signature change to UnlinkedGlobalCodeBlock* is consistent with the moved accessors.

Extended reasoning...

Overview

This PR merges upstream WebKit baf4a9a7ec0b (387 commits, 82 touching JSC/WTF/bmalloc) into Bun's fork, plus a follow-up merge of origin/main (d0fae3b) to pick up #330, #450, #491. It touches 300+ files across JSC runtime, DFG/FTL, Yarr JIT, Wasm, WTF threading, the module loader, bytecode cache serialization, and a large volume of tests/LayoutTests. The PR description documents each conflict resolution and per-commit API/behavior notes in detail.

The one issue flagged in my previous review — the fork-only elseif (ANDROID) branch in PlatformJSCOnly.cmake still listing the deleted linux/RealTimeThreads.cpp — was fixed in 6281729 and verified at HEAD (line 127 now reads linux/HighPriorityThreads.cpp). That inline thread is resolved.

Security risks

Several conflict-resolved areas are security-relevant: yarr/YarrJIT.cpp (regex JIT codegen, kept at the fork's version per #299 policy), CachedTypes.cpp (bytecode cache deserialization layout), Wasm bounds-check/signal-handler changes, and AtomicsObject termination handling. These are upstream-authored changes plus fork-side merge resolutions; nothing in the diff or the bug-hunt pass surfaced a concrete issue, but the attack surface is exactly the kind that merits a human maintainer confirming the resolutions match intent.

Level of scrutiny

High. This is not a mechanical change: it is a large upstream merge with ~10 hand-resolved conflicts in core engine paths (JIT, GC-adjacent cache invalidation, module loader semantics, thread scheduling policy), several of which the PR author explicitly flags as judgment calls (e.g., the Linux sched_setattr no-op under USE(BUN_JSC_ADDITIONS), dropping the fork's #262 in favor of upstream's fetch-failure eviction). An automated review cannot substitute for a maintainer signing off on those policy choices.

Other factors

The PR description includes verification (debug+ASAN build, 928 regexp/string/yarr stress runs, Bun link + test suites, Atomics.wait worker-terminate check), and CI preview builds were published for 6281729. The author addressed my prior finding promptly. No outstanding unaddressed reviewer comments. Still, per the approval guidelines — large, complex, touches critical code paths, contains design/policy decisions — this should not be auto-approved.

@robobun

robobun commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by #503, which merges the fork's current main (including the bytecode cache rework in #490, #493, #494, #497) with this PR's head d0fae3b3c9 and then upstream 8c4fd56347. The conflict resolutions and the upstream review from this PR are carried over there.

@robobun

robobun commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by #501. That PR merges this branch's head (d0fae3b, with its conflict resolutions and review fixes) and then upstream main at 55d9d90 on top of the fork's current main. This branch conflicts with main since the bytecode cache work (#490, #493, #494, #497) landed; the CachedTypes.cpp resolution is described in #501. Closing as a duplicate.

sosukesuzuki pushed a commit to oven-sh/bun that referenced this pull request Aug 25, 2026
### Problem
- Bun's WebKit pin `aea1f010b6` is 412 upstream commits behind
`8c4fd56347`, 90 of them in JavaScriptCore, WTF or bmalloc.
oven-sh/WebKit#503 merges that range into the fork.
- Upstream removed the `@newPromiseCapability` private builtin
(`38027ff0ec`). Six call sites in Bun's bundled modules use it, so
`node:events`, `node:util`, `node:dgram` and the HTTP server fail to
load (`Private symbol not found: newPromiseCapability`).
- #40263 and oven-sh/WebKit#501 were a parallel attempt at `55d9d9007f`,
one WebCore-only commit ahead. Both are closed in favor of this pair.

### Fix
- oven-sh/WebKit#503 is merged. `WEBKIT_VERSION` is
`cb61607f1a4bae79d7701965062634dee9efb349`, its merge commit on the
fork's main (release
`autobuild-cb61607f1a4bae79d7701965062634dee9efb349`, 42 tarballs). That
commit is the preview build this PR was tested against (`d2654c3b`) plus
oven-sh/WebKit `a0a80b2276` (an optional depth bound on
`recursivelyGenerateUnlinkedCodeBlockForProgram/ForModuleProgram`).
- The six call sites create their promise with `$newPromise()` and
settle it with `$resolvePromise` / `$rejectPromise`, or the
`...WithFirstResolvingFunctionCallCheck` variants where a second settle
is possible. `builtins.d.ts` follows.
- `EncodeURIComponent.cpp` includes `<wtf/HexNumber.h>` itself (upstream
`314133b7a6` no longer does).
- Verified: `test/js/bun/jsc/webkit-upgrade-8c4fd56347.test.ts` pins
four JavaScript-visible engine changes that fail at the current pin. The
events, util and dgram tests cover the ported settlement paths.

### Background
- Bun links a prebuilt JavaScriptCore from oven-sh/WebKit releases.
`scripts/build/deps/webkit.ts` names the release tag.
- Built-in modules (`src/js/`) go through JavaScriptCore's builtin
compiler. A `$name` call becomes the private name `@name`, which has to
exist in the engine.
- `$newPromise` creates a pending promise. `$resolvePromise` /
`$rejectPromise` settle it and require it to be pending. The
`...WithFirstResolvingFunctionCallCheck` variants ignore calls after the
first, like a Promise executor's functions.

<details><summary>Notes</summary>

- Duplicate resolution: oven-sh/WebKit#501 and #503 have the same
structure (main at `62f427b86f`, then #488's head `d0fae3b3c9`, then
upstream/main) and the same `CachedTypes.cpp` resolution (the two files
differ in comments and an unused alias). WTF and bmalloc are identical.
The only upstream difference is WebCore's `55d9d9007f`
(`MediaElementAudioSourceNode` use-after-free), which the JSCOnly port
does not compile. #503 was kept because this PR's CI run was green
(Build #104490). The test file `webkit-upgrade-8c4fd56347.test.ts` is
carried over from #40263.
- oven-sh/WebKit#488 (upstream `baf4a9a7ec0b`) stopped merging after the
fork's bytecode cache rework (#490, #493, #494, #497). The per-commit
review of the upstream range (API and ABI changes, behavior changes,
performance) and the conflict resolutions are in oven-sh/WebKit#503. The
new conflict in this round is `CachedTypes.cpp`: the fork's new code
block record layout against upstream moving the global-only fields
(`features`, `lineCount`, source URL directives) to
`UnlinkedGlobalCodeBlock` and deleting `m_jumpTargets`.
- The ported call sites (the changes of #40054, carried over):
`node:events` (`once`), `node:util` (`aborted`), `node:dgram`
(`Symbol.asyncDispose`) and the HTTP server (CONNECT, Upgrade, the
per-request completion promise). `builtins.d.ts` declares `$newPromise`,
`$resolvePromiseWithFirstResolvingFunctionCallCheck` and
`$rejectPromiseWithFirstResolvingFunctionCallCheck` and drops
`$newPromiseCapability`. `@newPromise` is a bytecode intrinsic and
`@resolvePromise` / `@rejectPromise` are link-time constants, so they
exist in every engine build. `util.aborted` registers and unregisters
its `FinalizationRegistry` entry with the same token (the promise).
- Behavior changes in the upstream range that are visible from
JavaScript: `Promise.try` follows the updated spec (`PromiseResolve`
instead of `NewPromiseCapability`); the module map no longer caches
fetch failures, so a second `import()` of a specifier whose load failed
re-runs Bun's module loader instead of rejecting with the cached error;
`Uint8Array.prototype.setFromBase64` on a zero-length target returns `{
read: 0, written: 0 }` without validating the input;
`WebAssembly.Module.imports()/exports()` descriptors drop the
non-standard `type` field; re-exported imported Wasm globals and tags
keep object identity; a DFG `++`/`--` on an `int32` that overflows with
an unused result now deoptimizes instead of wrapping (`7711916200`). The
first, third, fourth and last of these are pinned by
`test/js/bun/jsc/webkit-upgrade-8c4fd56347.test.ts`.
- Performance changes of note: `SymbolTableEntry` no longer allocates a
`WatchpointSet` per watched variable until the DFG watches it
(`cea233cede`); `Object.assign` with several sources clones the first
one through `objectCloneFast` (`96ca975b2a`); `JSON.parse` allocates
arrays once at their final size; `TypedArray.prototype.sort()` without a
comparator uses a radix sort for 2/4/8-byte element types; `Map`/`Set`
`forEach` is inlined in the DFG and FTL; `RegExp` cells shrink from 96
to 80 bytes; `UnlinkedFunctionCodeBlock` shrinks from 216 to 192 bytes.
- `src/jsc/bindings/NodeVMSyntheticModule.cpp` calls
`SymbolTable::set(NoLockingNecessary, ...)`. After `cea233cede` only the
locked overload exists. `NoLockingNecessary` converts to a
`ConcurrentJSLocker`, so the call compiles unchanged.
- The upstream change to Linux thread scheduling (per-QOS
`sched_setattr` on every WTF thread, `SCHED_BATCH` compiler threads on
hosts with 4 or fewer cores) is gated off for Bun in the fork: Bun's
threads keep inheriting the process scheduling attributes.
- Suites run on a local debug + ASAN build against the merged WebKit
(`bun run build:local`): `test/js/bun/jsc`, `bun/jsc-stress` (116/116),
`node/events`, `node/util`, `node/dgram`, `node/vm`, `node/module`,
`bun/resolve`, `node/worker_threads`, `bun/wasm`, `web/url`,
`web/atomics`, `node/http/node-http-connect`, `node/async_hooks`,
`node/string_decoder`, `bundler/bundler_compile`,
`bundler/bun-build-api`: 3,548 pass. The failures are 5 s timeouts under
debug + ASAN, this machine's IPv6 multicast `ENODEV`, and one test that
fails the same way at the current pin. `bun build --bytecode` output
from that build loads and runs. A debug + ASAN build against the
`autobuild-preview-pr-503-311eab61` prebuilt runs
`test/js/bun/jsc/webkit-upgrade-8c4fd56347.test.ts`,
`test/js/bun/jsc/webkit-upgrade-3722912f.test.ts`,
`node/events/event-emitter.test.ts` and
`node/util/test-aborted.test.ts`: 106 pass.
- Every push to oven-sh/WebKit#503 produces a new preview tag
(`autobuild-preview-pr-503-<first 8 of the head sha>`), and this PR's
`WEBKIT_VERSION` follows it. CI lanes that fetch the prebuilt fail on
the download until that tag's Actions run has published the release.
- Rebase over #40201: Bun main moved its pin to the fork's
`c148a12dd82b` and calls the bytecode APIs that release added
(`EncoderStringTable`, persistent payloads). The `311eab61` preview
predates them, so the branch could not rebase until oven-sh/WebKit#503
merged the fork's main (head `d2654c3b`, 0 commits behind). The rebase
itself conflicted only on the `WEBKIT_VERSION` line. A debug + ASAN
build against `autobuild-preview-pr-503-d2654c3b` passes
`webkit-upgrade-8c4fd56347.test.ts`,
`node/events/event-emitter.test.ts`, `node/util/test-aborted.test.ts`,
`node/dgram` (except the IPv6 multicast `ENODEV` of this machine),
`node/http/node-http-connect.test.ts`, `web/atomics`, `web/url`,
`node/string_decoder` and `test/js/bun/jsc`. The compiled-executable
bytecode paths of #40201 work against it: the aliasing run keeps 12 MB
of instruction streams out of anonymous memory and 45 internal modules
load from embedded bytecode. The failures on this machine are the DOMJIT
hot loops and two `bun-build-compile` tests that exceed their timeouts
under debug + ASAN (the compile alone takes 5 to 47 s here), and the
nested `node-http-connect.node.mts` run that takes 5.0 s against a 5 s
limit.
- The `$newPromiseCapability` call in `src/node-fallbacks/events.js`
(the browser polyfill, not a JSC builtin) is a pre-existing bug and was
reported separately by #40054.
</details>

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

---

**no test proof** · iteration 2 · platform-specific test(s) that do not
run on this machine, deferring to CI, which covers all platforms:
test/js/node/dgram/node-dgram.test.js

<!-- robobun:evidence:end -->
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.