Skip to content

2026 06 16 upstream changes#6822

Open
mikea wants to merge 484 commits into
mainfrom
maizatskyi/2026-06-16-upstream
Open

2026 06 16 upstream changes#6822
mikea wants to merge 484 commits into
mainfrom
maizatskyi/2026-06-16-upstream

Conversation

@mikea

@mikea mikea commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

No description provided.

npaun and others added 30 commits June 1, 2026 07:47
…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.
kentonv and others added 14 commits June 16, 2026 10:44
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
@mikea mikea requested review from a team as code owners June 16, 2026 20:22
@mikea mikea requested a review from james-elicx June 16, 2026 20:22
…yi/2026-06-16-upstream

# Conflicts:
#	cfsetup.yaml
#	ci/build.yml
#	src/workerd/api/actor.c++
@mikea mikea force-pushed the maizatskyi/2026-06-16-upstream branch from 8b67028 to 418e9d3 Compare June 16, 2026 20:26
@github-actions

Copy link
Copy Markdown

The generated output of @cloudflare/workers-types has been changed by this PR. If this is intentional, run just generate-types to update the snapshot. Alternatively, you can download the full generated types:

Full Type Diff
diff -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"

@codspeed-hq

codspeed-hq Bot commented Jun 16, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 71.04%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
✅ 71 untouched benchmarks
⏩ 129 skipped benchmarks1

Performance Changes

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)

Open in CodSpeed

Footnotes

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

@mikea mikea force-pushed the maizatskyi/2026-06-16-upstream branch from 8d4ae57 to 311ea56 Compare June 17, 2026 15:48
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.