diff --git a/src/workerd/api/basics.c++ b/src/workerd/api/basics.c++ index d0e5f91335f..6af25c91376 100644 --- a/src/workerd/api/basics.c++ +++ b/src/workerd/api/basics.c++ @@ -585,4 +585,27 @@ jsg::Optional> ExtendableEvent::getActorState() { }); } +CustomEvent::CustomEvent(kj::String ownType, CustomEventInit init) + : Event(kj::mv(ownType), (Event::Init)init), + detail(kj::mv(init.detail)) {} + +jsg::Ref CustomEvent::constructor(jsg::Lock& js, kj::String type, + jsg::Optional init) { + return jsg::alloc(kj::mv(type), kj::mv(init).orDefault({})); +} + +jsg::Optional CustomEvent::getDetail(jsg::Lock& js) { + return detail.map([&](jsg::JsRef& val) { + return val.getHandle(js); + }); +} + +CustomEvent::CustomEventInit::operator Event::Init() { + return { + .bubbles = this->bubbles.map([](auto& val) { return val; }), + .cancelable = this->cancelable.map([](auto& val) { return val; }), + .composed = this->composed.map([](auto& val) { return val; }), + }; +} + } // namespace workerd::api diff --git a/src/workerd/api/basics.h b/src/workerd/api/basics.h index ab17de3d8f2..2658a51f30b 100644 --- a/src/workerd/api/basics.h +++ b/src/workerd/api/basics.h @@ -190,6 +190,35 @@ class ExtendableEvent: public Event { } }; +// An implementation of the Web Platform Standard CustomEvent API +class CustomEvent: public Event { +public: + struct CustomEventInit final { + jsg::Optional bubbles; + jsg::Optional cancelable; + jsg::Optional composed; + jsg::Optional> detail; + JSG_STRUCT(bubbles, cancelable, composed, detail); + + operator Event::Init(); + }; + + explicit CustomEvent(kj::String ownType, CustomEventInit init = CustomEventInit()); + + static jsg::Ref constructor(jsg::Lock& js, kj::String type, + jsg::Optional init); + + jsg::Optional getDetail(jsg::Lock& js); + + JSG_RESOURCE_TYPE(CustomEvent) { + JSG_INHERIT(Event); + JSG_READONLY_PROTOTYPE_PROPERTY(detail, getDetail); + } + +private: + jsg::Optional> detail; +}; + // An implementation of the Web Platform Standard EventTarget API class EventTarget: public jsg::Object { public: @@ -632,7 +661,9 @@ class Scheduler final: public jsg::Object { api::AbortSignal, \ api::Scheduler, \ api::Scheduler::WaitOptions, \ - api::ExtendableEvent + api::ExtendableEvent, \ + api::CustomEvent, \ + api::CustomEvent::CustomEventInit // The list of basics.h types that are added to worker.c++'s JSG_DECLARE_ISOLATE_TYPE } // namespace workerd::api diff --git a/src/workerd/api/global-scope.h b/src/workerd/api/global-scope.h index c605fe00d55..5202f76851b 100644 --- a/src/workerd/api/global-scope.h +++ b/src/workerd/api/global-scope.h @@ -413,6 +413,7 @@ class ServiceWorkerGlobalScope: public WorkerGlobalScope { JSG_NESTED_TYPE(Event); JSG_NESTED_TYPE(ExtendableEvent); + JSG_NESTED_TYPE(CustomEvent); JSG_NESTED_TYPE(PromiseRejectionEvent); JSG_NESTED_TYPE(FetchEvent); JSG_NESTED_TYPE(TailEvent); diff --git a/src/workerd/api/tests/events-test.js b/src/workerd/api/tests/events-test.js index afbdc8f35d3..947beb4a165 100644 --- a/src/workerd/api/tests/events-test.js +++ b/src/workerd/api/tests/events-test.js @@ -1,7 +1,8 @@ import { deepStrictEqual, strictEqual, - throws + throws, + ok, } from 'node:assert'; // Test for the Event and EventTarget standard Web API implementations. @@ -369,3 +370,12 @@ export const nullUndefinedHandler = { // target.addEventListener('foo', undefined); } }; + +export const customEvent = { + test() { + const event = new CustomEvent('foo', { detail: { a: 123 } }); + ok(event instanceof Event); + strictEqual(event.type, 'foo'); + deepStrictEqual(event.detail, { a: 123 }); + } +};