Skip to content
File

Blob: src/workerd/api/events.c++

6.0 KB
1#include "events.h"
2 
3#include "blob.h"
4#include "messagechannel.h"
5 
6namespace workerd::api {
7 
8MessageEvent::MessageEvent(jsg::Lock& js,
9 const jsg::JsValue& data,
10 kj::String lastEventId,
11 kj::Maybe<jsg::Ref<MessagePort>> source,
12 kj::Maybe<jsg::Url&> urlForOrigin)
13 : Event("message"),
14 data(jsg::JsRef(js, data)),
15 lastEventId(kj::mv(lastEventId)),
16 maybeSource(kj::mv(source)),
17 maybeOrigin(urlForOrigin.map([](auto& url) { return url.getOrigin(); })) {}
18MessageEvent::MessageEvent(jsg::Lock& js,
19 jsg::JsRef<jsg::JsValue> data,
20 kj::String lastEventId,
21 kj::Maybe<jsg::Ref<MessagePort>> source,
22 kj::Maybe<jsg::Url&> urlForOrigin)
23 : Event("message"),
24 data(kj::mv(data)),
25 lastEventId(kj::mv(lastEventId)),
26 maybeSource(kj::mv(source)),
27 maybeOrigin(urlForOrigin.map([](auto& url) { return url.getOrigin(); })) {}
28MessageEvent::MessageEvent(jsg::Lock& js,
29 kj::String type,
30 const jsg::JsValue& data,
31 kj::String lastEventId,
32 kj::Maybe<jsg::Ref<MessagePort>> source,
33 kj::Maybe<jsg::Url&> urlForOrigin)
34 : Event(kj::mv(type)),
35 data(jsg::JsRef(js, kj::mv(data))),
36 lastEventId(kj::mv(lastEventId)),
37 maybeSource(kj::mv(source)),
38 maybeOrigin(urlForOrigin.map([](auto& url) { return url.getOrigin(); })) {}
39MessageEvent::MessageEvent(jsg::Lock& js,
40 kj::String type,
41 kj::OneOf<jsg::JsRef<jsg::JsValue>, jsg::Ref<Blob>> data,
42 kj::String lastEventId,
43 kj::Maybe<jsg::Ref<MessagePort>> source,
44 kj::Maybe<jsg::Url&> urlForOrigin)
45 : Event(kj::mv(type)),
46 data(kj::mv(data)),
47 lastEventId(kj::mv(lastEventId)),
48 maybeSource(kj::mv(source)),
49 maybeOrigin(urlForOrigin.map([](auto& url) { return url.getOrigin(); })) {}
50 
51jsg::Ref<MessageEvent> MessageEvent::constructor(
52 jsg::Lock& js, kj::String type, Initializer initializer) {
53 return js.alloc<MessageEvent>(js, kj::mv(type), kj::mv(initializer.data));
54}
55 
56kj::OneOf<jsg::JsValue, jsg::Ref<Blob>> MessageEvent::getData(jsg::Lock& js) {
57 KJ_SWITCH_ONEOF(data) {
58 KJ_CASE_ONEOF(jsValue, jsg::JsRef<jsg::JsValue>) {
59 return jsValue.getHandle(js);
60 }
61 KJ_CASE_ONEOF(blob, jsg::Ref<Blob>) {
62 return blob.addRef();
63 }
64 }
65 KJ_UNREACHABLE;
66}
67 
68kj::Maybe<kj::ArrayPtr<const char>> MessageEvent::getOrigin() {
69 return maybeOrigin.map([](auto& a) -> kj::ArrayPtr<const char> { return a.asPtr(); });
70}
71 
72kj::StringPtr MessageEvent::getLastEventId() {
73 return lastEventId;
74}
75 
76// Per the spec, the source of a MessageEvent is one of a MessagePort,
77// ServiceWorker, WindowProxy, etc. The only one of these we actually
78// support is MessagePort, return that if its set or null if not.
79kj::Maybe<jsg::Ref<MessagePort>> MessageEvent::getSource() {
80 return maybeSource.map([](auto& port) mutable -> jsg::Ref<MessagePort> { return port.addRef(); });
81}
82kj::ArrayPtr<jsg::Ref<MessagePort>> MessageEvent::getPorts() {
83 // We don't support transferring MessagePorts in MessageEvent
84 // for now, so we return an empty array. Later we might support
85 // this.
86 return nullptr;
87}
88 
89void MessageEvent::visitForMemoryInfo(jsg::MemoryTracker& tracker) const {
90 KJ_SWITCH_ONEOF(data) {
91 KJ_CASE_ONEOF(jsValue, jsg::JsRef<jsg::JsValue>) {
92 tracker.trackField("data", jsValue);
93 }
94 KJ_CASE_ONEOF(blob, jsg::Ref<Blob>) {
95 tracker.trackField("data", blob);
96 }
97 }
98 tracker.trackField("source", maybeSource);
99}
100 
101void MessageEvent::visitForGc(jsg::GcVisitor& visitor) {
102 KJ_SWITCH_ONEOF(data) {
103 KJ_CASE_ONEOF(jsValue, jsg::JsRef<jsg::JsValue>) {
104 visitor.visit(jsValue);
105 }
106 KJ_CASE_ONEOF(blob, jsg::Ref<Blob>) {
107 visitor.visit(blob);
108 }
109 }
110 visitor.visit(maybeSource);
111}
112 
113// ======================================================================================
114namespace {
115const kj::StringPtr kDefaultErrorEventName = "error"_kj;
116} // namespace
117 
118ErrorEvent::ErrorEvent(ErrorEventInit init): Event(kDefaultErrorEventName), init(kj::mv(init)) {}
119 
120ErrorEvent::ErrorEvent(kj::String type, ErrorEventInit init)
121 : Event(kj::mv(type)),
122 init(kj::mv(init)) {}
123 
124ErrorEvent::ErrorEvent(jsg::Lock& js, jsg::JsValue error)
125 : ErrorEvent(ErrorEventInit{.error = jsg::JsRef(js, error)}) {}
126 
127jsg::Ref<ErrorEvent> ErrorEvent::constructor(
128 jsg::Lock& js, kj::String type, jsg::Optional<ErrorEventInit> init) {
129 return js.alloc<ErrorEvent>(kj::mv(type), kj::mv(init).orDefault({}));
130}
131 
132kj::StringPtr ErrorEvent::getFilename() {
133 return init.filename.orDefault(nullptr);
134}
135 
136kj::StringPtr ErrorEvent::getMessage() {
137 return init.message.orDefault(nullptr);
138}
139 
140int ErrorEvent::getLineno() {
141 return init.lineno.orDefault(0);
142}
143 
144int ErrorEvent::getColno() {
145 return init.colno.orDefault(0);
146}
147 
148jsg::JsValue ErrorEvent::getError(jsg::Lock& js) {
149 KJ_IF_SOME(error, init.error) {
150 return error.getHandle(js);
151 } else {
152 return js.undefined();
153 }
154}
155 
156void ErrorEvent::visitForMemoryInfo(jsg::MemoryTracker& tracker) const {
157 tracker.trackField("message", init.message);
158 tracker.trackField("filename", init.filename);
159 tracker.trackField("error", init.error);
160}
161 
162void ErrorEvent::visitForGc(jsg::GcVisitor& visitor) {
163 visitor.visit(init.error);
164}
165 
166// ======================================================================================
167namespace {
168constexpr kj::StringPtr kUnhandledRejectionEventName = "unhandledrejection"_kj;
169constexpr kj::StringPtr kRejectionHandledEventName = "rejectionhandled"_kj;
170 
171constexpr kj::StringPtr getPromiseRejectionEventName(v8::PromiseRejectEvent type) {
172 switch (type) {
173 case v8::PromiseRejectEvent::kPromiseRejectWithNoHandler:
174 return kUnhandledRejectionEventName;
175 case v8::PromiseRejectEvent::kPromiseHandlerAddedAfterReject:
176 return kRejectionHandledEventName;
177 default:
178 // Events are not emitted for the other reject types.
179 KJ_UNREACHABLE;
180 }
181}
182 
183} // namespace
184 
185PromiseRejectionEvent::PromiseRejectionEvent(
186 v8::PromiseRejectEvent type, jsg::V8Ref<v8::Promise> promise, jsg::Value reason)
187 : Event(getPromiseRejectionEventName(type)),
188 promise(kj::mv(promise)),
189 reason(kj::mv(reason)) {}
190 
191} // namespace workerd::api