From ead9fc6403f717c0ff01e89942bf30f506ae4fa9 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 19 Aug 2026 07:48:09 -0700 Subject: [PATCH] Add docs/changelog for EventTarget/AbortSignal improvements workerd PR: https://github.com/cloudflare/workerd/pull/7053 --- .../2026-08-19-abort-signal-global-scope.mdx | 27 +++++++++++++++++ .../2026-08-19-event-spec-compliance.mdx | 29 +++++++++++++++++++ ...-19-spec-compliant-dispatch-exceptions.mdx | 17 +++++++++++ .../spec-compliant-dispatch-exceptions.md | 18 ++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 src/content/changelog/workers/2026-08-19-abort-signal-global-scope.mdx create mode 100644 src/content/changelog/workers/2026-08-19-event-spec-compliance.mdx create mode 100644 src/content/changelog/workers/2026-08-19-spec-compliant-dispatch-exceptions.mdx create mode 100644 src/content/compatibility-flags/spec-compliant-dispatch-exceptions.md diff --git a/src/content/changelog/workers/2026-08-19-abort-signal-global-scope.mdx b/src/content/changelog/workers/2026-08-19-abort-signal-global-scope.mdx new file mode 100644 index 00000000000..2ea216d1419 --- /dev/null +++ b/src/content/changelog/workers/2026-08-19-abort-signal-global-scope.mdx @@ -0,0 +1,27 @@ +--- +title: AbortController and AbortSignal can be created at global scope +description: AbortController, AbortSignal, and WritableStream no longer throw when constructed during module evaluation. +products: + - workers +date: 2026-08-19 +--- + +`new AbortController()`, `AbortSignal.abort()`, `new WritableStream()`, and `request.signal` no longer throw when used during module evaluation (that is, at the top level of your Worker module, outside of a request handler). Previously, these APIs required an active request context and would throw if called at the top level. + +```js +// This now works — no error during module startup +const controller = new AbortController(); + +export default { + async fetch(request) { + // The signal can be used across requests + return new Response("OK", { signal: controller.signal }); + }, +}; +``` + +Signals can also be observed and aborted across different requests, making it easier to coordinate cancellation in long-lived Workers such as Durable Objects. + +`AbortSignal.timeout()` still requires an active request context because it needs to schedule a timer. + +For more details, refer to the [AbortController documentation](/workers/runtime-apis/web-standards/abort-controller/). diff --git a/src/content/changelog/workers/2026-08-19-event-spec-compliance.mdx b/src/content/changelog/workers/2026-08-19-event-spec-compliance.mdx new file mode 100644 index 00000000000..39707e227f4 --- /dev/null +++ b/src/content/changelog/workers/2026-08-19-event-spec-compliance.mdx @@ -0,0 +1,29 @@ +--- +title: Event and EventTarget spec compliance improvements +description: Several fixes bring Event subclasses, event handler attributes, and MessagePort closer to their web platform specifications. +products: + - workers +date: 2026-08-19 +--- + +Several improvements bring the Workers runtime's `Event`, `EventTarget`, and related APIs closer to their web platform specifications. + +### `isTrusted` is now correct for user-constructed events + +User-constructed event subclasses (`new MessageEvent(...)`, `new CustomEvent(...)`, `new ErrorEvent(...)`, `new CloseEvent(...)`) now correctly report `isTrusted` as `false`. Previously, these incorrectly reported `isTrusted` as `true`. + +### `on` handlers fire in registration order + +Event handler attributes such as `onmessage` and `onabort` now fire in their registration order relative to `addEventListener()` calls, matching browser behavior. Previously, `on` handlers always fired before any `addEventListener()` listeners regardless of when they were assigned. + +### `MessageEvent` constructor improvements + +`new MessageEvent(type)` now works without providing an init object — `data` defaults to `null` per spec. The `MessageEventInit` dictionary also now supports the full spec surface: `origin`, `lastEventId`, `source`, and `ports`, in addition to `data`. + +### `CloseEvent` and `ErrorEvent` constructor improvements + +The `CloseEventInit` and `ErrorEventInit` dictionaries now accept the standard `EventInit` members `bubbles`, `cancelable`, and `composed`. + +### `MessagePort` starts on any `message` listener + +Adding a `message` event listener to a `MessagePort` via `addEventListener("message", ...)` now starts the port, matching browser behavior. Previously, only assigning `onmessage` would start the port. diff --git a/src/content/changelog/workers/2026-08-19-spec-compliant-dispatch-exceptions.mdx b/src/content/changelog/workers/2026-08-19-spec-compliant-dispatch-exceptions.mdx new file mode 100644 index 00000000000..7d2f1c82ed0 --- /dev/null +++ b/src/content/changelog/workers/2026-08-19-spec-compliant-dispatch-exceptions.mdx @@ -0,0 +1,17 @@ +--- +title: Spec-compliant dispatchEvent() exception handling +description: A new compatibility flag aligns event dispatch exception handling with the DOM specification. +products: + - workers +date: 2026-08-19 +--- + +A new compatibility flag, `spec_compliant_dispatch_exceptions`, aligns the Workers runtime's event dispatch behavior with the [DOM specification](https://dom.spec.whatwg.org/#dispatching-events). This flag becomes the default for all Workers with a compatibility date of `2026-09-01` or later. + +Previously, when an event listener threw an exception during `dispatchEvent()`, the runtime propagated the exception immediately and skipped all remaining listeners for that event. The spec instead requires that listener exceptions are reported (via the global `error` event and the console) without interrupting the dispatch — remaining listeners still run. + +This change affects the JS-visible `dispatchEvent()`, `AbortSignal` abort dispatch, and runtime-fired events on `WebSocket`, `EventSource`, and `MessagePort`. Top-level event delivery for legacy Service Worker syntax entry points (such as `addEventListener("fetch", ...)`) is not affected. + +To opt in before the default date, add `spec_compliant_dispatch_exceptions` to your `compatibility_flags`. To preserve the old behavior after the default date, use `no_spec_compliant_dispatch_exceptions`. + +For more details, refer to the [compatibility flags documentation](/workers/configuration/compatibility-flags/). diff --git a/src/content/compatibility-flags/spec-compliant-dispatch-exceptions.md b/src/content/compatibility-flags/spec-compliant-dispatch-exceptions.md new file mode 100644 index 00000000000..830f640715a --- /dev/null +++ b/src/content/compatibility-flags/spec-compliant-dispatch-exceptions.md @@ -0,0 +1,18 @@ +--- +_build: + publishResources: false + render: never + list: never + +name: "Spec-compliant `dispatchEvent()` exception handling" +sort_date: "2026-09-01" +enable_date: "2026-09-01" +enable_flag: "spec_compliant_dispatch_exceptions" +disable_flag: "no_spec_compliant_dispatch_exceptions" +--- + +Per the [DOM specification](https://dom.spec.whatwg.org/#dispatching-events), exceptions thrown by event listeners during `dispatchEvent()` should be reported (via the global `error` event and the console) but should not interrupt the dispatch or propagate to the `dispatchEvent()` caller. The remaining listeners for that event should still run. + +The original Workers runtime implementation propagated the first listener exception and skipped all remaining listeners for that event. This affected the JS-visible `dispatchEvent()`, `AbortSignal` abort dispatch, and runtime-fired events on `WebSocket`, `EventSource`, and `MessagePort`. + +When this flag is enabled, all of these event dispatch surfaces use the spec's report-and-continue semantics. A throwing listener's exception is reported on the global `error` event and logged to the console, but the dispatch continues through the remaining listeners. Top-level event delivery for legacy Service Worker syntax entry points (such as `addEventListener("fetch", ...)`) is not affected and always propagates exceptions.