2026 06 16 upstream changes#6822
Conversation
…ckV2 V8 14.9 deprecates the `AccessorNameSetterCallback` (V1) overload of `Template::SetNativeDataProperty`, emitting a `-Wdeprecated-declarations` warning. The V2 signature takes `PropertyCallbackInfo<Boolean>` instead of `PropertyCallbackInfo<void>`, with the boolean return value indicating whether the setter operation succeeded. Update both `SetterCallback` specializations in `resource.h` to the V2 signature so the non-deprecated `SetNativeDataProperty` overload is selected. `LiftKj_::apply` also needs to learn about this signature: it currently calls `info.GetReturnValue().SetUndefined()` for void-returning callbacks unless the info is a V1 setter, but `ReturnValue<Boolean>::SetUndefined` fails to compile (the in-header `static_assert(is_base_of_v<T, Primitive>)` rejects `Boolean`). Skip the call for `PropertyCallbackInfo<Boolean>` as well; per V8's contract, leaving the return value unset is interpreted as setter success.
The `external_include_paths` cc toolchain feature converts `cc_library` `includes` to `-isystem`, which suppresses warnings emitted from inside external dependencies' headers. It was previously enabled on Linux only; there's no architectural reason for the restriction — the feature is provided by Bazel's generic C++ toolchain support and works the same on both platforms. Move the directive from `build:linux` to the shared `build:unix` config so macOS picks it up as well. This also silences benign warnings from V8 14.9 headers on macOS (e.g., `-Wcast-function-type-mismatch` from V8's in-header `IndexedPropertyDefinerCallback` backwards-compat shim) that Linux was already shielded from.
The JIT code event handler builds a per-isolate mapping from compiled code addresses to JS source locations, consumed by getJsStackTrace() for crash reporting. workerd itself never calls getJsStackTrace(), so the overhead of installing the handler on every isolate is wasted. Add a JitCodeEventTracking strong-bool parameter (defaulting to NO) on each V8System constructor so embedders can opt in. IsolateBase only calls SetJitCodeEventHandler when the V8System has it enabled.
Throw error when expectedServerHostname is passed to startTls in prod See merge request cloudflare/ew/workerd!161
just update capnproto See merge request cloudflare/ew/workerd!184
… JSG_STRUCT unwrap to prevent process abort via prototype pollution FieldWrapper::unwrap in src/workerd/jsg/struct.h used v8::Object::Get() which performs a full ECMA-262 [[Get]] with prototype chain traversal. When called from inside V8's ValueDeserializer host-object callback (which installs a DisallowJavascriptExecution scope), a getter installed on Object.prototype by attacker-controlled JS would trigger V8_Fatal → abort(), killing the entire workerd process and all co-located tenant isolates. The slow-path FieldWrapper::wrap (compat date < 2025-12-03) also omitted kj::none Optional fields from the serialized init-dict object, leaving those field names absent as own properties and forcing the prototype chain lookup during deserialization. The fix conditionally replaces Get() with HasOwnProperty + GetRealNamedProperty (own-property-only, no prototype chain traversal) in unwrap. The regression test installs Object.prototype getters on several RequestInitializerDict field names (redirect, method, signal) and calls structuredClone(new Request(...)) — pre-patch this deterministically aborted the process; post-patch the clone succeeds normally. Test validation: VALIDATED LOCALLY Pre-patch run: FAIL (bazel test //src/workerd/api/tests:struct-prototype-pollution-test@) Post-patch run: PASS (bazel test //src/workerd/api/tests:struct-prototype-pollution-test@) Refs: AUTOVULN-CLOUDFLARE-WORKERD-369 See merge request cloudflare/ew/workerd!39
VULN-136602: fix(jsg): conditionally use own-property-only lookups in JSG_STRUCT unwrap to prevent process abort via prototype pollution See merge request cloudflare/ew/workerd!39
Restore external memory accounting for global actor channels See merge request cloudflare/ew/workerd!201
…il next turn of event loop * fix(server): defer dynamic WorkerService destruction until next turn of event loop DeleteQueue::scheduleDeletion() previously took the synchronous inline-delete fast path whenever IoContext::current() matched, regardless of whether the caller was inside a cppgc finalizer. When a WorkerStub (holding a child v8::Isolate via WorkerStubImpl → WorkerService → Worker::Isolate) was garbage-collected by the parent isolate, the parent's CppgcShim::~CppgcShim() set the thread-local inCppgcShimDestructor flag and then synchronously destroyed the child isolate chain. The child's HeapTracer::clearWrappers() hit KJ_ASSERT(!inCppgcShimDestructor) at wrappable.c++:40 (the flag is process-wide, not per-isolate), throwing from inside V8's noexcept cppgc sweeper and triggering std::terminate(). The new worker-loader-gc-test exercises the exact crash scenario: load an anonymous child worker, make a request to force full construction, drop the stub, and trigger gc(). Pre-fix this aborts the process; post-fix the deferred deletion completes safely. (AUTOVULN-CLOUDFLARE-WORKERD-102) Test validation: VALIDATED LOCALLY Pre-patch run: FAIL (bazel test //src/workerd/api/tests:worker-loader-gc-test@) Post-patch run: PASS (bazel test //src/workerd/api/tests:worker-loader-gc-test@) Refs: AUTOVULN-CLOUDFLARE-WORKERD-102 See merge request cloudflare/ew/workerd!6
VULN-136569: fix(server): defer dynamic WorkerService destruction until next turn of event loop See merge request cloudflare/ew/workerd!6
Bump v8 to 14.9 See merge request cloudflare/ew/workerd!121
Normally, messages are caught by TryCatch scopes, but in some cases there is no scope. This causes the message to be logged by the DefaultMessageListener to stdout, which pollutes Kibana with things that should be js exceptions.
Add v8::Isolate MessageListener to log any messages See merge request cloudflare/ew/workerd!205
GC tracing of the queue is unnecessary and potentially
dangerous. Most of it was non-op already. The danger
comes from cases like:
```cpp
struct Foo {
jsg::Ref<Bar> bar;
void visitForGc(jsg::GcVisitor& visitor) {
visitor.visit(bar);
}
}
auto foo = kj::heap<Foo>();
// something gc visits foo...
auto foo2 = kj::mv(foo);
// nothing visits foo2!
```
In the first visit, `bar` is marked weak. After
the move, if nothing gc visits `foo2` before the
next GC cycle, the garbage collector can decide
that `bar` is unreachable and collect it. There's
nothing in the move that would cause `bar` to be
marked strong again (unlike moving the `jsg::Ref`
itself).
A handful of changes in here, focused on improving the robustness of queue.h/queue.c++. Extracted from the larger reverted commit.
And as a bonus, fix two streams WPTs
Allow the standard AllReader to support strings and SAB's
Remove the original path and the autogate. Autogate has been deployed for a while.
Add focused coverage for ctx.restore service-stub replay through direct use and storage, along with basic restore error cases. The new target currently exposes a segfault in the first real ctx.restore() path and is committed as requested for follow-up debugging. Also keep the supporting hardening changes found while debugging: safer Cap'n Proto token-message copying, guarded Frankenvalue cap-table decoding, and explicit client movement when wrapping restored RpcStubs.
`RestoreServiceCustomEvent` / `RestoreRpcStubCustomEvent` deliver a `restoreParams` `Frankenvalue` to a `[restore]()` handler. In environments where Frankenvalue cap-table entries are stored in a "dehydrated" form not tied to any `IoContext` (e.g. the edge runtime, where they are channel tokens), a live channel cannot be constructed until the `IoContext` in which `[restore]()` runs actually exists. Add an optional `RestoreRehydrateCallback` to both events. It is applied via `restoreParams.rewriteCaps()` inside `run()`, after entering the `IoContext` and before converting the params to JS, turning each dehydrated entry into a live, IoContext-bound channel. When null (workerd's own usage, where caps are already live), params are used as-is.
The promised-channel helper was only specialized for SubrequestChannel and ActorClassChannel. Add the RpcChannel specialization (backed by the existing PromisedRpcChannel) so that callers decoding RpcChannel tokens can return a promised channel when the underlying decode is asynchronous (e.g. an actor-token usage exchange).
The correct way to serialize Frankenvalues to capnp can differ depending on what kind of RPC target we're delivering to (e.g. process sandbox vs. network). So we pass this callback object to `RpcWorkerInterface` which passes it down to `sendRpc()`, similar to how we pass HttpOverCapnpFactory and ByteStreamFactory. This commit mostly just updates all the implementations of `sendRpc()`. This isn't used yet.
…ents The `sendRpc()` path for `RestoreServiceCustomEvent` / `RestoreRpcStubCustomEvent` serialized `restoreParams` with plain `Frankenvalue::toCapnp()`, which records only the cap-table *size*, not its contents (those are filled by a higher layer). Any caps in `restoreParams` were therefore dropped on send, and the receiving `Frankenvalue::fromCapnp()` would fail its cap-count check. Workerd never hits this since it dispatches restore events locally, but the edge runtime sends them over RPC. * Use the new `FrankenvalueHandler` to fix this. * Also add static `receiveRpc()` helpers to both events, modeled on `JsRpcSessionCustomEvent::receiveRpc()`, implementing the server side of `EventDispatcher::restoreService()` / `restoreRpcStub()`. `restoreService` returns a `WorkerdBootstrap` (minimal self-contained impl in restore.c++, mirroring the private one in server.c++) wrapping the restored SubrequestChannel; `restoreRpcStub` returns the JsRpcTarget + session like jsRpcSession. The caller constructs the event with the deserialized params + a RestoreRehydrateCallback.
Restored ServiceStubs could outlive the RestoreServiceCustomEvent that produced their underlying channel. When the restored service was a dynamic-worker ServiceStub, the follow-up JS-RPC call observed the restore event's IoContext as canceled. Keep the service restore event alive until the restored service channel is dropped, matching the persistent RpcStub session lifetime behavior. TODO: It's not immediately clear to me why this is needed, but reverting it breaks the tests in the edge runtime. I plan to investigate further and hopefully revert this commit later, as it would seem to unnecessarily block hiberantion of a parent actor that is part of the restore chain into a persistent stub in a facet.
Otherwise, if an actor holds a stub to another actor, and their respective namespaces are torn down in the wrong order, we can get a UaF. This fixes as ASAN error in persistent-stubs-test.js.
The workers-rpc.c++ instance was caught by ASAN. The others probably got by due to the channel still being referenced by the app until GC.
Don't use JSRPC for AI binding's toMarkdown() API. See merge request cloudflare/ew/workerd!297
* Guard against WeakRef being torn down after isolate See merge request cloudflare/ew/workerd!303
Guard against WeakRef being torn down after isolate See merge request cloudflare/ew/workerd!303
Implement persistent stubs See merge request cloudflare/ew/workerd!267
update capnp to bring Pin/Ptr/Weak improvements See merge request cloudflare/ew/workerd!305
…yi/2026-06-16-upstream # Conflicts: # cfsetup.yaml # ci/build.yml # src/workerd/api/actor.c++
8b67028 to
418e9d3
Compare
|
The generated output of Full Type Diffdiff -r types/generated-snapshot/latest/index.d.ts bazel-bin/types/definitions/latest/index.d.ts
653a654,655
> | "apac-ne"
> | "apac-se"
diff -r types/generated-snapshot/latest/index.ts bazel-bin/types/definitions/latest/index.ts
655a656,657
> | "apac-ne"
> | "apac-se" |
Merging this PR will improve performance by 71.04%
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ⚡ | request[RegExpBenchmark] |
7 ms | 4.1 ms | +71.04% |
Tip
Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.
Comparing maizatskyi/2026-06-16-upstream (311ea56) with main (df2a06c)
Footnotes
-
129 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
8d4ae57 to
311ea56
Compare
No description provided.