script: Change signature of Event::dispatch to match the spec and simplify things (#38566)

- [Dispatch Event](https://dom.spec.whatwg.org/#concept-event-dispatch)
should return a Boolean. This function is used frequently in spec and
the change makes things easier to follow.
- Remove `enum EventStatus` and related functions.
- Update some dead spec link.
- Update some steps.

This is intended as cleanup before working on #38435 and reduces binary
size by 488KB in Release profile.

Testing: No behaviour change.

---------

Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
This commit is contained in:
Euclid Ye 2025-08-09 16:04:31 +08:00 committed by GitHub
parent 21717158eb
commit 589d188a3f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 40 additions and 68 deletions

View file

@ -24,7 +24,6 @@ use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::trace::CustomTraceable; use crate::dom::bindings::trace::CustomTraceable;
use crate::dom::bindings::utils::define_all_exposed_interfaces; use crate::dom::bindings::utils::define_all_exposed_interfaces;
use crate::dom::event::EventStatus;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::types::{DebuggerEvent, Event}; use crate::dom::types::{DebuggerEvent, Event};
#[cfg(feature = "testbinding")] #[cfg(feature = "testbinding")]
@ -124,10 +123,9 @@ impl DebuggerGlobalScope {
} }
pub(crate) fn fire_add_debuggee(&self, can_gc: CanGc, global: &GlobalScope) { pub(crate) fn fire_add_debuggee(&self, can_gc: CanGc, global: &GlobalScope) {
assert_eq!( assert!(
DomRoot::upcast::<Event>(DebuggerEvent::new(self.upcast(), global, can_gc)) DomRoot::upcast::<Event>(DebuggerEvent::new(self.upcast(), global, can_gc))
.fire(self.upcast(), can_gc), .fire(self.upcast(), can_gc),
EventStatus::NotCanceled,
"Guaranteed by DebuggerEvent::new" "Guaranteed by DebuggerEvent::new"
); );
} }

View file

@ -46,7 +46,7 @@ use crate::dom::bindings::trace::{CustomTraceable, RootedTraceableBox};
use crate::dom::bindings::utils::define_all_exposed_interfaces; use crate::dom::bindings::utils::define_all_exposed_interfaces;
use crate::dom::csp::{Violation, parse_csp_list_from_metadata}; use crate::dom::csp::{Violation, parse_csp_list_from_metadata};
use crate::dom::errorevent::ErrorEvent; use crate::dom::errorevent::ErrorEvent;
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::messageevent::MessageEvent; use crate::dom::messageevent::MessageEvent;
@ -737,11 +737,9 @@ impl DedicatedWorkerGlobalScope {
HandleValue::null(), HandleValue::null(),
CanGc::note(), CanGc::note(),
); );
let event_status =
event.upcast::<Event>().fire(worker.upcast::<EventTarget>(), CanGc::note());
// Step 2. // Step 2.
if event_status == EventStatus::NotCanceled { if event.upcast::<Event>().fire(worker.upcast::<EventTarget>(), CanGc::note()) {
global.report_an_error(error_info, HandleValue::null(), CanGc::note()); global.report_an_error(error_info, HandleValue::null(), CanGc::note());
} }
})); }));

View file

@ -151,7 +151,7 @@ use crate::dom::element::{
CustomElementCreationMode, Element, ElementCreator, ElementPerformFullscreenEnter, CustomElementCreationMode, Element, ElementCreator, ElementPerformFullscreenEnter,
ElementPerformFullscreenExit, ElementPerformFullscreenExit,
}; };
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventDefault, EventStatus}; use crate::dom::event::{Event, EventBubbles, EventCancelable, EventDefault};
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::focusevent::FocusEvent; use crate::dom::focusevent::FocusEvent;
use crate::dom::fontfaceset::FontFaceSet; use crate::dom::fontfaceset::FontFaceSet;
@ -1678,11 +1678,12 @@ impl Document {
vec![], // predicted_events vec![], // predicted_events
can_gc, can_gc,
); );
let event = menu_event.upcast::<Event>();
event.fire(target, can_gc);
// if the event was not canceled, notify the embedder to show the context menu // Step 3. Let result = dispatch menuevent at target.
if event.status() == EventStatus::NotCanceled { let result = menu_event.upcast::<Event>().fire(target, can_gc);
// Step 4. If result is true, then show the UA context menu
if result {
let (sender, receiver) = let (sender, receiver) =
ipc::channel::<ContextMenuResult>().expect("Failed to create IPC channel."); ipc::channel::<ContextMenuResult>().expect("Failed to create IPC channel.");
self.send_to_embedder(EmbedderMsg::ShowContextMenu( self.send_to_embedder(EmbedderMsg::ShowContextMenu(
@ -2393,13 +2394,8 @@ impl Document {
false, false,
can_gc, can_gc,
); );
let event = event.upcast::<Event>();
let result = event.fire(&target, can_gc);
match result { TouchEventResult::Processed(event.upcast::<Event>().fire(&target, can_gc))
EventStatus::Canceled => TouchEventResult::Processed(false),
EventStatus::NotCanceled => TouchEventResult::Processed(true),
}
} }
// If hittest fails, we still need to update the active point information. // If hittest fails, we still need to update the active point information.
@ -3026,8 +3022,7 @@ impl Document {
); );
let event = event.upcast::<Event>(); let event = event.upcast::<Event>();
event.set_trusted(true); event.set_trusted(true);
let _ = self self.window
.window
.dispatch_event_with_target_override(event, can_gc); .dispatch_event_with_target_override(event, can_gc);
// Step 6 Update the visibility state of oldDocument to "hidden". // Step 6 Update the visibility state of oldDocument to "hidden".
self.update_visibility_state(DocumentVisibilityState::Hidden, can_gc); self.update_visibility_state(DocumentVisibilityState::Hidden, can_gc);
@ -3044,8 +3039,7 @@ impl Document {
event.set_trusted(true); event.set_trusted(true);
let event_target = self.window.upcast::<EventTarget>(); let event_target = self.window.upcast::<EventTarget>();
let has_listeners = event_target.has_listeners_for(&atom!("unload")); let has_listeners = event_target.has_listeners_for(&atom!("unload"));
let _ = self self.window
.window
.dispatch_event_with_target_override(&event, can_gc); .dispatch_event_with_target_override(&event, can_gc);
self.fired_unload.set(true); self.fired_unload.set(true);
// Step 9 // Step 9

View file

@ -279,7 +279,7 @@ impl Event {
legacy_target_override: bool, legacy_target_override: bool,
can_gc: CanGc, can_gc: CanGc,
// TODO legacy_did_output_listeners_throw_flag for indexeddb // TODO legacy_did_output_listeners_throw_flag for indexeddb
) -> EventStatus { ) -> bool {
let mut target = DomRoot::from_ref(target); let mut target = DomRoot::from_ref(target);
// Step 1. Set events dispatch flag. // Step 1. Set events dispatch flag.
@ -629,15 +629,7 @@ impl Event {
} }
// Step 12 Return false if events canceled flag is set; otherwise true. // Step 12 Return false if events canceled flag is set; otherwise true.
self.status() !self.DefaultPrevented()
}
pub(crate) fn status(&self) -> EventStatus {
if self.DefaultPrevented() {
EventStatus::Canceled
} else {
EventStatus::NotCanceled
}
} }
#[inline] #[inline]
@ -673,8 +665,8 @@ impl Event {
self.composed.set(composed); self.composed.set(composed);
} }
/// <https://html.spec.whatwg.org/multipage/#fire-a-simple-event> /// <https://dom.spec.whatwg.org/#firing-events>
pub(crate) fn fire(&self, target: &EventTarget, can_gc: CanGc) -> EventStatus { pub(crate) fn fire(&self, target: &EventTarget, can_gc: CanGc) -> bool {
self.set_trusted(true); self.set_trusted(true);
target.dispatch_event(self, can_gc) target.dispatch_event(self, can_gc)
} }
@ -1105,12 +1097,6 @@ pub(crate) enum EventDefault {
Handled, Handled,
} }
#[derive(Debug, PartialEq)]
pub(crate) enum EventStatus {
Canceled,
NotCanceled,
}
/// <https://dom.spec.whatwg.org/#concept-event-fire> /// <https://dom.spec.whatwg.org/#concept-event-fire>
pub(crate) struct EventTask { pub(crate) struct EventTask {
pub(crate) target: Trusted<EventTarget>, pub(crate) target: Trusted<EventTarget>,

View file

@ -57,7 +57,7 @@ use crate::dom::csp::{CspReporting, InlineCheckType};
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::element::Element; use crate::dom::element::Element;
use crate::dom::errorevent::ErrorEvent; use crate::dom::errorevent::ErrorEvent;
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventComposed, EventStatus}; use crate::dom::event::{Event, EventBubbles, EventCancelable, EventComposed};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlformelement::FormControlElementHelpers; use crate::dom::htmlformelement::FormControlElementHelpers;
use crate::dom::node::{Node, NodeTraits}; use crate::dom::node::{Node, NodeTraits};
@ -430,7 +430,7 @@ impl EventTarget {
.map_or(EventListeners(vec![]), |listeners| listeners.clone()) .map_or(EventListeners(vec![]), |listeners| listeners.clone())
} }
pub(crate) fn dispatch_event(&self, event: &Event, can_gc: CanGc) -> EventStatus { pub(crate) fn dispatch_event(&self, event: &Event, can_gc: CanGc) -> bool {
event.dispatch(self, false, can_gc) event.dispatch(self, false, can_gc)
} }
@ -994,10 +994,7 @@ impl EventTargetMethods<crate::DomTypeHolder> for EventTarget {
return Err(Error::InvalidState); return Err(Error::InvalidState);
} }
event.set_trusted(false); event.set_trusted(false);
Ok(match self.dispatch_event(event, can_gc) { Ok(self.dispatch_event(event, can_gc))
EventStatus::Canceled => false,
EventStatus::NotCanceled => true,
})
} }
} }

View file

@ -100,7 +100,7 @@ use crate::dom::dedicatedworkerglobalscope::{
DedicatedWorkerControlMsg, DedicatedWorkerGlobalScope, DedicatedWorkerControlMsg, DedicatedWorkerGlobalScope,
}; };
use crate::dom::errorevent::ErrorEvent; use crate::dom::errorevent::ErrorEvent;
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::eventsource::EventSource; use crate::dom::eventsource::EventSource;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::file::File; use crate::dom::file::File;
@ -2645,15 +2645,18 @@ impl GlobalScope {
/// <https://html.spec.whatwg.org/multipage/#report-the-error> /// <https://html.spec.whatwg.org/multipage/#report-the-error>
pub(crate) fn report_an_error(&self, error_info: ErrorInfo, value: HandleValue, can_gc: CanGc) { pub(crate) fn report_an_error(&self, error_info: ErrorInfo, value: HandleValue, can_gc: CanGc) {
// Step 1. // Step 6. Early return if global is in error reporting mode,
if self.in_error_reporting_mode.get() { if self.in_error_reporting_mode.get() {
return; return;
} }
// Step 2. // Step 6.1. Set global's in error reporting mode to true.
self.in_error_reporting_mode.set(true); self.in_error_reporting_mode.set(true);
// Steps 3-6. // Step 6.2. Set notHandled to the result of firing an event named error at global,
// using ErrorEvent, with the cancelable attribute initialized to true,
// and additional attributes initialized according to errorInfo.
// FIXME(#13195): muted errors. // FIXME(#13195): muted errors.
let event = ErrorEvent::new( let event = ErrorEvent::new(
self, self,
@ -2668,16 +2671,15 @@ impl GlobalScope {
can_gc, can_gc,
); );
// Step 7. let not_handled = event
let event_status = event
.upcast::<Event>() .upcast::<Event>()
.fire(self.upcast::<EventTarget>(), can_gc); .fire(self.upcast::<EventTarget>(), can_gc);
// Step 8. // Step 6.3. Set global's in error reporting mode to false.
self.in_error_reporting_mode.set(false); self.in_error_reporting_mode.set(false);
// Step 9. // Step 7.
if event_status == EventStatus::NotCanceled { if not_handled {
// https://html.spec.whatwg.org/multipage/#runtime-script-errors-2 // https://html.spec.whatwg.org/multipage/#runtime-script-errors-2
if let Some(dedicated) = self.downcast::<DedicatedWorkerGlobalScope>() { if let Some(dedicated) = self.downcast::<DedicatedWorkerGlobalScope>() {
dedicated.forward_error_to_worker_object(error_info); dedicated.forward_error_to_worker_object(error_info);

View file

@ -65,7 +65,7 @@ use crate::dom::element::{
referrer_policy_for_element, reflect_cross_origin_attribute, reflect_referrer_policy_attribute, referrer_policy_for_element, reflect_cross_origin_attribute, reflect_referrer_policy_attribute,
set_cross_origin_attribute, set_cross_origin_attribute,
}; };
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlelement::HTMLElement; use crate::dom::htmlelement::HTMLElement;
use crate::dom::node::{ChildrenMutation, CloneChildrenFlag, Node, NodeTraits}; use crate::dom::node::{ChildrenMutation, CloneChildrenFlag, Node, NodeTraits};
@ -1416,7 +1416,7 @@ impl HTMLScriptElement {
bubbles: EventBubbles, bubbles: EventBubbles,
cancelable: EventCancelable, cancelable: EventCancelable,
can_gc: CanGc, can_gc: CanGc,
) -> EventStatus { ) -> bool {
let window = self.owner_window(); let window = self.owner_window();
let event = Event::new(window.upcast(), type_, bubbles, cancelable, can_gc); let event = Event::new(window.upcast(), type_, bubbles, cancelable, can_gc);
event.fire(self.upcast(), can_gc) event.fire(self.upcast(), can_gc)

View file

@ -130,7 +130,7 @@ use crate::dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration
use crate::dom::customelementregistry::CustomElementRegistry; use crate::dom::customelementregistry::CustomElementRegistry;
use crate::dom::document::{AnimationFrameCallback, Document}; use crate::dom::document::{AnimationFrameCallback, Document};
use crate::dom::element::Element; use crate::dom::element::Element;
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::gamepad::{Gamepad, contains_user_gesture}; use crate::dom::gamepad::{Gamepad, contains_user_gesture};
use crate::dom::gamepadevent::GamepadEventType; use crate::dom::gamepadevent::GamepadEventType;
@ -705,12 +705,8 @@ impl Window {
} }
// see note at https://dom.spec.whatwg.org/#concept-event-dispatch step 2 // see note at https://dom.spec.whatwg.org/#concept-event-dispatch step 2
pub(crate) fn dispatch_event_with_target_override( pub(crate) fn dispatch_event_with_target_override(&self, event: &Event, can_gc: CanGc) {
&self, event.dispatch(self.upcast(), true, can_gc);
event: &Event,
can_gc: CanGc,
) -> EventStatus {
event.dispatch(self.upcast(), true, can_gc)
} }
pub(crate) fn font_context(&self) -> &Arc<FontContext> { pub(crate) fn font_context(&self) -> &Arc<FontContext> {

View file

@ -75,7 +75,7 @@ use crate::dom::bindings::root::trace_roots;
use crate::dom::bindings::utils::DOM_CALLBACKS; use crate::dom::bindings::utils::DOM_CALLBACKS;
use crate::dom::bindings::{principals, settings_stack}; use crate::dom::bindings::{principals, settings_stack};
use crate::dom::csp::CspReporting; use crate::dom::csp::CspReporting;
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
@ -559,10 +559,11 @@ pub(crate) fn notify_about_rejected_promises(global: &GlobalScope) {
CanGc::note() CanGc::note()
); );
let event_status = event.upcast::<Event>().fire(&target, CanGc::note()); let not_canceled = event.upcast::<Event>().fire(&target, CanGc::note());
// Step 4-3. // Step 4-3. If notCanceled is true, then the user agent
if event_status == EventStatus::Canceled { // may report p.[[PromiseResult]] to a developer console.
if not_canceled {
// TODO: The promise rejection is not handled; we need to add it back to the list. // TODO: The promise rejection is not handled; we need to add it back to the list.
} }