Skip to content

Commit 47c9b94

Browse files
authored
Merge pull request #5404 from cloudflare/jasnell/minor-event-tweaks
2 parents 3731fb5 + ea1ebe0 commit 47c9b94

File tree

2 files changed

+63
-48
lines changed

2 files changed

+63
-48
lines changed

src/workerd/api/basics.c++

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ namespace {
2525
// console.
2626
// It's important to keep this list in sync with any other top level events that are emitted
2727
// when in worker syntax but called as exports in module syntax.
28-
bool isSpecialEventType(kj::StringPtr type) {
28+
constexpr bool isSpecialEventType(kj::StringPtr type) {
2929
// TODO(someday): How should we cover custom events here? Since it's just for a warning I'm
3030
// leaving them out for now.
3131
return type == "fetch" || type == "scheduled" || type == "tail" || type == "trace" ||
@@ -167,7 +167,7 @@ kj::StringPtr Event::getType() {
167167
}
168168

169169
kj::Maybe<jsg::Ref<EventTarget>> Event::getCurrentTarget() {
170-
if (isBeingDispatched) {
170+
if (flags.isBeingDispatched) {
171171
return getTarget();
172172
}
173173
return kj::none;
@@ -178,7 +178,7 @@ jsg::Optional<jsg::Ref<EventTarget>> Event::getTarget() {
178178
}
179179

180180
kj::Array<jsg::Ref<EventTarget>> Event::composedPath() {
181-
if (isBeingDispatched) {
181+
if (flags.isBeingDispatched) {
182182
// When isBeingDispatched is true, target should always be non-null.
183183
// If it's not, there's a bug that we need to know about.
184184
return kj::arr(KJ_ASSERT_NONNULL(target).addRef());
@@ -187,8 +187,9 @@ kj::Array<jsg::Ref<EventTarget>> Event::composedPath() {
187187
}
188188

189189
void Event::beginDispatch(jsg::Ref<EventTarget> target) {
190-
JSG_REQUIRE(!isBeingDispatched, DOMInvalidStateError, "The event is already being dispatched.");
191-
isBeingDispatched = true;
190+
JSG_REQUIRE(
191+
!flags.isBeingDispatched, DOMInvalidStateError, "The event is already being dispatched.");
192+
flags.isBeingDispatched = true;
192193
this->target = kj::mv(target);
193194
}
194195

@@ -226,7 +227,7 @@ void EventTarget::addEventListener(jsg::Lock& js,
226227
kj::Maybe<jsg::Identified<Handler>> maybeHandler,
227228
jsg::Optional<AddEventListenerOpts> maybeOptions,
228229
const jsg::TypeHandler<jsg::Ref<EventTarget>>& eventTargetHandler) {
229-
if (warnOnSpecialEvents && isSpecialEventType(type)) {
230+
if (flags.warnOnSpecialEvents && isSpecialEventType(type)) {
230231
js.logWarning(kj::str("When using module syntax, the '", type,
231232
"' event handler should be "
232233
"declared as an exported function on the root module as opposed to using "
@@ -410,6 +411,7 @@ bool EventTarget::dispatchEventImpl(jsg::Lock& js, jsg::Ref<Event> event) {
410411
}
411412

412413
KJ_IF_SOME(handlerSet, typeMap.find(event->getType())) {
414+
callbacks.reserve(handlerSet.handlers.size());
413415
for (auto& handler: handlerSet.handlers.ordered<kj::InsertionOrderIndex>()) {
414416
KJ_SWITCH_ONEOF(handler->handler) {
415417
KJ_CASE_ONEOF(jsh, EventHandler::JavaScriptHandler) {
@@ -504,8 +506,8 @@ bool EventTarget::dispatchEventImpl(jsg::Lock& js, jsg::Ref<Event> event) {
504506
if (handle->IsTrue()) {
505507
event->preventDefault();
506508
}
507-
if (warnOnHandlerReturn && !handle->IsBoolean()) {
508-
warnOnHandlerReturn = false;
509+
if (flags.warnOnHandlerReturn && !handle->IsBoolean()) {
510+
flags.warnOnHandlerReturn = false;
509511
// To help make debugging easier, let's tailor the warning a bit if it was a promise.
510512
if (handle->IsPromise()) {
511513
js.logWarning(kj::str(

src/workerd/api/basics.h

Lines changed: 53 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -33,41 +33,46 @@ class Event: public jsg::Object {
3333
JSG_STRUCT(bubbles, cancelable, composed);
3434
};
3535

36-
inline explicit Event(kj::String ownType, Init init = Init(), bool trusted = true)
36+
inline explicit Event(kj::String ownType, Init init = {}, bool trusted = true)
3737
: ownType(kj::mv(ownType)),
38-
type(this->ownType),
39-
init(init),
40-
trusted(trusted) {}
38+
type(this->ownType) {
39+
flags.trusted = trusted;
40+
flags.bubbles = init.bubbles.orDefault(false);
41+
flags.cancelable = init.cancelable.orDefault(false);
42+
flags.composed = init.composed.orDefault(false);
43+
}
4144

42-
inline explicit Event(kj::StringPtr type, Init init = Init(), bool trusted = true)
43-
: type(type),
44-
init(init),
45-
trusted(trusted) {}
45+
inline explicit Event(kj::StringPtr type, Init init = {}, bool trusted = true): type(type) {
46+
flags.trusted = trusted;
47+
flags.bubbles = init.bubbles.orDefault(false);
48+
flags.cancelable = init.cancelable.orDefault(false);
49+
flags.composed = init.composed.orDefault(false);
50+
}
4651

4752
inline bool isPreventDefault() const {
48-
return preventedDefault;
53+
return flags.preventedDefault;
4954
}
5055
inline void clearPreventDefault() {
51-
preventedDefault = false;
56+
flags.preventedDefault = false;
5257
}
5358

5459
void beginDispatch(jsg::Ref<EventTarget> target);
5560
inline void endDispatch() {
56-
isBeingDispatched = false;
61+
flags.isBeingDispatched = false;
5762
}
5863

5964
inline bool isStopped() const {
60-
return stopped;
65+
return flags.stopped;
6166
}
6267

6368
static jsg::Ref<Event> constructor(jsg::Lock& js, kj::String type, jsg::Optional<Init> init);
6469
kj::StringPtr getType();
6570

6671
inline void stopImmediatePropagation() {
67-
stopped = true;
72+
flags.stopped = true;
6873
}
6974
inline void preventDefault() {
70-
preventedDefault = true;
75+
flags.preventedDefault = true;
7176
}
7277

7378
// The only phases we actually use are NONE and AT_TARGET but we provide
@@ -80,7 +85,7 @@ class Event: public jsg::Object {
8085
};
8186

8287
inline int getEventPhase() const {
83-
return isBeingDispatched ? AT_TARGET : NONE;
88+
return flags.isBeingDispatched ? AT_TARGET : NONE;
8489
}
8590

8691
// Much of the following is not used in our implementation of Event
@@ -89,25 +94,25 @@ class Event: public jsg::Object {
8994
// provided to fill-out Event spec compliance.
9095

9196
inline bool getCancelBubble() const {
92-
return propagationStopped;
97+
return flags.propagationStopped;
9398
}
9499
inline void setCancelBubble(bool stopped) {
95-
propagationStopped = stopped;
100+
flags.propagationStopped = stopped;
96101
}
97102
inline void stopPropagation() {
98-
propagationStopped = true;
103+
flags.propagationStopped = true;
99104
}
100105
inline bool getComposed() const {
101-
return init.composed.orDefault(false);
106+
return flags.composed;
102107
}
103108
inline bool getBubbles() const {
104-
return init.bubbles.orDefault(false);
109+
return flags.bubbles;
105110
}
106111
inline bool getCancelable() const {
107-
return init.cancelable.orDefault(false);
112+
return flags.cancelable;
108113
}
109114
inline bool getDefaultPrevented() const {
110-
return getCancelable() && preventedDefault;
115+
return getCancelable() && flags.preventedDefault;
111116
}
112117
inline bool getReturnValue() const {
113118
return !getDefaultPrevented();
@@ -124,7 +129,7 @@ class Event: public jsg::Object {
124129
// by EW internally is Trusted, any Event created using new Event() in JS
125130
// is not trusted.
126131
inline bool getIsTrusted() const {
127-
return trusted;
132+
return flags.trusted;
128133
}
129134

130135
// The currentTarget is the EventTarget on which the Event is being
@@ -215,14 +220,20 @@ class Event: public jsg::Object {
215220
// listing ownType first so type can be initialized with it in constructor
216221
kj::String ownType;
217222
kj::StringPtr type;
218-
Init init;
219-
bool trusted = true;
220-
bool stopped = false;
221-
bool preventedDefault = false;
222-
bool isBeingDispatched = false;
223-
bool propagationStopped = false;
224223
kj::Maybe<jsg::Ref<EventTarget>> target;
225224

225+
struct Flags {
226+
uint8_t trusted : 1 = 1;
227+
uint8_t stopped : 1 = 0;
228+
uint8_t preventedDefault : 1 = 0;
229+
uint8_t isBeingDispatched : 1 = 0;
230+
uint8_t propagationStopped : 1 = 0;
231+
uint8_t composed : 1 = 0;
232+
uint8_t bubbles : 1 = 0;
233+
uint8_t cancelable : 1 = 0;
234+
};
235+
Flags flags{};
236+
226237
void visitForGc(jsg::GcVisitor& visitor) {
227238
visitor.visit(target);
228239
}
@@ -306,7 +317,7 @@ class EventTarget: public jsg::Object {
306317
}
307318

308319
inline void enableWarningOnSpecialEvents() {
309-
warnOnSpecialEvents = true;
320+
flags.warnOnSpecialEvents = true;
310321
}
311322

312323
// The EventListenerCallback, if given, is called whenever addEventListener
@@ -530,18 +541,20 @@ class EventTarget: public jsg::Object {
530541

531542
kj::HashMap<kj::String, EventHandlerSet> typeMap;
532543

533-
// When using module syntax, the "fetch", "scheduled", "trace", etc.
534-
// events are handled by exports rather than events. When warnOnSpecialEvents is true,
535-
// when using module syntax, attempts to register event handlers for these special
536-
// types of events will result in a warning being emitted.
537-
bool warnOnSpecialEvents = false;
538-
539-
// Event handlers are not supposed to return values. The first time one does, we'll
540-
// emit a warning to help users debug things but we'll otherwise ignore it.
541-
bool warnOnHandlerReturn = true;
542-
543544
kj::Maybe<EventListenerCallback> maybeListenerCallback;
544545

546+
struct Flags {
547+
// When using module syntax, the "fetch", "scheduled", "trace", etc.
548+
// events are handled by exports rather than events. When warnOnSpecialEvents is true,
549+
// when using module syntax, attempts to register event handlers for these special
550+
// types of events will result in a warning being emitted.
551+
uint8_t warnOnSpecialEvents : 1 = 0;
552+
// Event handlers are not supposed to return values. The first time one does, we'll
553+
// emit a warning to help users debug things but we'll otherwise ignore it.
554+
uint8_t warnOnHandlerReturn : 1 = 1;
555+
};
556+
Flags flags;
557+
545558
void visitForGc(jsg::GcVisitor& visitor);
546559

547560
friend class NativeHandler;

0 commit comments

Comments
 (0)