script: JSContextify parts of DocumentEventHandler (#44241)

This "JSContextify"s part of DocumentEventHandler, namely the actions
from `handle_pending_input_events`.
Additionally, we also switch the MouseEvent and KeyboardEvent. This does
not change yet PointerEvent and some other events used to keep the diff
reasonable.

Testing: This is part of the JSContextify work that is fundamental and
tested by WPT.

---------

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
This commit is contained in:
Narfinger
2026-04-15 15:59:07 +02:00
committed by GitHub
parent d4729c05b2
commit 4fafdd1c23
7 changed files with 184 additions and 140 deletions

View File

@@ -5226,60 +5226,65 @@ impl DocumentMethods<crate::DomTypeHolder> for Document {
}
/// <https://dom.spec.whatwg.org/#dom-document-createevent>
fn CreateEvent(&self, mut interface: DOMString, can_gc: CanGc) -> Fallible<DomRoot<Event>> {
fn CreateEvent(
&self,
cx: &mut js::context::JSContext,
mut interface: DOMString,
) -> Fallible<DomRoot<Event>> {
interface.make_ascii_lowercase();
match &*interface.str() {
"beforeunloadevent" => Ok(DomRoot::upcast(BeforeUnloadEvent::new_uninitialized(
&self.window,
can_gc,
CanGc::from_cx(cx),
))),
"compositionevent" | "textevent" => Ok(DomRoot::upcast(
CompositionEvent::new_uninitialized(&self.window, can_gc),
CompositionEvent::new_uninitialized(&self.window, CanGc::from_cx(cx)),
)),
"customevent" => Ok(DomRoot::upcast(CustomEvent::new_uninitialized(
self.window.upcast(),
can_gc,
CanGc::from_cx(cx),
))),
// FIXME(#25136): devicemotionevent, deviceorientationevent
// FIXME(#7529): dragevent
"events" | "event" | "htmlevents" | "svgevents" => {
Ok(Event::new_uninitialized(self.window.upcast(), can_gc))
},
"events" | "event" | "htmlevents" | "svgevents" => Ok(Event::new_uninitialized(
self.window.upcast(),
CanGc::from_cx(cx),
)),
"focusevent" => Ok(DomRoot::upcast(FocusEvent::new_uninitialized(
&self.window,
can_gc,
CanGc::from_cx(cx),
))),
"hashchangeevent" => Ok(DomRoot::upcast(HashChangeEvent::new_uninitialized(
&self.window,
can_gc,
CanGc::from_cx(cx),
))),
"keyboardevent" => Ok(DomRoot::upcast(KeyboardEvent::new_uninitialized(
cx,
&self.window,
can_gc,
))),
"messageevent" => Ok(DomRoot::upcast(MessageEvent::new_uninitialized(
self.window.upcast(),
can_gc,
CanGc::from_cx(cx),
))),
"mouseevent" | "mouseevents" => Ok(DomRoot::upcast(MouseEvent::new_uninitialized(
cx,
&self.window,
can_gc,
))),
"storageevent" => Ok(DomRoot::upcast(StorageEvent::new_uninitialized(
&self.window,
"".into(),
can_gc,
CanGc::from_cx(cx),
))),
"touchevent" => Ok(DomRoot::upcast(DomTouchEvent::new_uninitialized(
&self.window,
&TouchList::new(&self.window, &[], can_gc),
&TouchList::new(&self.window, &[], can_gc),
&TouchList::new(&self.window, &[], can_gc),
can_gc,
&TouchList::new(&self.window, &[], CanGc::from_cx(cx)),
&TouchList::new(&self.window, &[], CanGc::from_cx(cx)),
&TouchList::new(&self.window, &[], CanGc::from_cx(cx)),
CanGc::from_cx(cx),
))),
"uievent" | "uievents" => Ok(DomRoot::upcast(UIEvent::new_uninitialized(
&self.window,
can_gc,
CanGc::from_cx(cx),
))),
_ => Err(Error::NotSupported(None)),
}

View File

@@ -500,23 +500,23 @@ impl ContextMenuNodes {
},
ContextMenuAction::Cut => {
window.Document().event_handler().handle_editing_action(
cx,
self.text_input_element.clone(),
EditingActionEvent::Cut,
CanGc::from_cx(cx),
);
},
ContextMenuAction::Copy => {
window.Document().event_handler().handle_editing_action(
cx,
self.text_input_element.clone(),
EditingActionEvent::Copy,
CanGc::from_cx(cx),
);
},
ContextMenuAction::Paste => {
window.Document().event_handler().handle_editing_action(
cx,
self.text_input_element.clone(),
EditingActionEvent::Paste,
CanGc::from_cx(cx),
);
},
ContextMenuAction::SelectAll => {

View File

@@ -22,6 +22,7 @@ use embedder_traits::{
GamepadEvent as EmbedderGamepadEvent, GamepadSupportedHapticEffects, GamepadUpdateType,
};
use euclid::{Point2D, Vector2D};
use js::context::JSContext;
use js::jsapi::JSAutoRealm;
use keyboard_types::{Code, Key, KeyState, Modifiers, NamedKey};
use layout_api::{ScrollContainerQueryFlags, node_id_from_scroll_id};
@@ -297,7 +298,7 @@ impl DocumentEventHandler {
}
}
pub(crate) fn handle_pending_input_events(&self, can_gc: CanGc) {
pub(crate) fn handle_pending_input_events(&self, cx: &mut JSContext) {
debug_assert!(
!self.pending_input_events.borrow().is_empty(),
"handle_pending_input_events called with no events"
@@ -328,11 +329,11 @@ impl DocumentEventHandler {
.set(event.active_keyboard_modifiers);
let result = match event.event.event {
InputEvent::MouseButton(mouse_button_event) => {
self.handle_native_mouse_button_event(mouse_button_event, &event, can_gc);
self.handle_native_mouse_button_event(cx, mouse_button_event, &event);
InputEventResult::default()
},
InputEvent::MouseMove(_) => {
self.handle_native_mouse_move_event(&event, can_gc);
self.handle_native_mouse_move_event(cx, &event);
input_event_outcomes.extend(
mem::take(&mut coalesced_move_event_ids)
.into_iter()
@@ -344,14 +345,12 @@ impl DocumentEventHandler {
InputEventResult::default()
},
InputEvent::MouseLeftViewport(mouse_leave_event) => {
self.handle_mouse_left_viewport_event(&event, &mouse_leave_event, can_gc);
self.handle_mouse_left_viewport_event(cx, &event, &mouse_leave_event);
InputEventResult::default()
},
InputEvent::Touch(touch_event) => {
self.handle_touch_event(touch_event, &event, can_gc)
},
InputEvent::Touch(touch_event) => self.handle_touch_event(cx, touch_event, &event),
InputEvent::Wheel(wheel_event) => {
let result = self.handle_wheel_event(wheel_event, &event, can_gc);
let result = self.handle_wheel_event(cx, wheel_event, &event);
input_event_outcomes.extend(
mem::take(&mut coalesced_wheel_event_ids)
.into_iter()
@@ -360,16 +359,16 @@ impl DocumentEventHandler {
result
},
InputEvent::Keyboard(keyboard_event) => {
self.handle_keyboard_event(keyboard_event, can_gc)
self.handle_keyboard_event(cx, keyboard_event)
},
InputEvent::Ime(ime_event) => self.handle_ime_event(ime_event, can_gc),
InputEvent::Ime(ime_event) => self.handle_ime_event(cx, ime_event),
#[cfg(feature = "gamepad")]
InputEvent::Gamepad(gamepad_event) => {
self.handle_gamepad_event(gamepad_event);
InputEventResult::default()
},
InputEvent::EditingAction(editing_action_event) => {
self.handle_editing_action(None, editing_action_event, can_gc)
self.handle_editing_action(cx, None, editing_action_event)
},
};
@@ -427,9 +426,9 @@ impl DocumentEventHandler {
fn handle_mouse_left_viewport_event(
&self,
cx: &mut JSContext,
input_event: &ConstellationInputEvent,
mouse_leave_event: &MouseLeftViewportEvent,
can_gc: CanGc,
) {
if let Some(current_hover_target) = self.current_hover_target.get() {
let current_hover_target = current_hover_target.upcast::<Node>();
@@ -447,30 +446,30 @@ impl DocumentEventHandler {
.and_then(|point| self.window.hit_test_from_point_in_viewport(point))
{
let mouse_out_event = MouseEvent::new_for_platform_motion_event(
cx,
&self.window,
FireMouseEventType::Out,
&hit_test_result,
input_event,
can_gc,
);
// Fire pointerout before mouseout
mouse_out_event
.to_pointer_hover_event("pointerout", can_gc)
.to_pointer_hover_event("pointerout", CanGc::from_cx(cx))
.upcast::<Event>()
.fire(current_hover_target.upcast(), can_gc);
.fire(current_hover_target.upcast(), CanGc::from_cx(cx));
mouse_out_event
.upcast::<Event>()
.fire(current_hover_target.upcast(), can_gc);
.fire(current_hover_target.upcast(), CanGc::from_cx(cx));
self.handle_mouse_enter_leave_event(
cx,
DomRoot::from_ref(current_hover_target),
None,
FireMouseEventType::Leave,
&hit_test_result,
input_event,
can_gc,
);
}
}
@@ -496,12 +495,12 @@ impl DocumentEventHandler {
fn handle_mouse_enter_leave_event(
&self,
cx: &mut JSContext,
event_target: DomRoot<Node>,
related_target: Option<DomRoot<Node>>,
event_type: FireMouseEventType,
hit_test_result: &HitTestResult,
input_event: &ConstellationInputEvent,
can_gc: CanGc,
) {
assert!(matches!(
event_type,
@@ -541,11 +540,11 @@ impl DocumentEventHandler {
for target in targets {
let mouse_event = MouseEvent::new_for_platform_motion_event(
cx,
&self.window,
event_type,
hit_test_result,
input_event,
can_gc,
);
mouse_event
.upcast::<Event>()
@@ -553,17 +552,23 @@ impl DocumentEventHandler {
// Fire pointer event before mouse event
mouse_event
.to_pointer_hover_event(pointer_event_name, can_gc)
.to_pointer_hover_event(pointer_event_name, CanGc::from_cx(cx))
.upcast::<Event>()
.fire(target.upcast(), can_gc);
.fire(target.upcast(), CanGc::from_cx(cx));
// Fire mouse event
mouse_event.upcast::<Event>().fire(target.upcast(), can_gc);
mouse_event
.upcast::<Event>()
.fire(target.upcast(), CanGc::from_cx(cx));
}
}
/// <https://w3c.github.io/uievents/#handle-native-mouse-move>
fn handle_native_mouse_move_event(&self, input_event: &ConstellationInputEvent, can_gc: CanGc) {
fn handle_native_mouse_move_event(
&self,
cx: &mut JSContext,
input_event: &ConstellationInputEvent,
) {
// Ignore all incoming events without a hit test.
let Some(hit_test_result) = self.window.hit_test_from_input_event(input_event) else {
return;
@@ -615,11 +620,11 @@ impl DocumentEventHandler {
}
let mouse_out_event = MouseEvent::new_for_platform_motion_event(
cx,
&self.window,
FireMouseEventType::Out,
&hit_test_result,
input_event,
can_gc,
);
mouse_out_event
.upcast::<Event>()
@@ -627,24 +632,24 @@ impl DocumentEventHandler {
// Fire pointerout before mouseout
mouse_out_event
.to_pointer_hover_event("pointerout", can_gc)
.to_pointer_hover_event("pointerout", CanGc::from_cx(cx))
.upcast::<Event>()
.fire(old_target.upcast(), can_gc);
.fire(old_target.upcast(), CanGc::from_cx(cx));
mouse_out_event
.upcast::<Event>()
.fire(old_target.upcast(), can_gc);
.fire(old_target.upcast(), CanGc::from_cx(cx));
if !old_target_is_ancestor_of_new_target {
let event_target = DomRoot::from_ref(old_target.upcast::<Node>());
let moving_into = Some(DomRoot::from_ref(new_target.upcast::<Node>()));
self.handle_mouse_enter_leave_event(
cx,
event_target,
moving_into,
FireMouseEventType::Leave,
&hit_test_result,
input_event,
can_gc,
);
}
}
@@ -659,11 +664,11 @@ impl DocumentEventHandler {
}
let mouse_over_event = MouseEvent::new_for_platform_motion_event(
cx,
&self.window,
FireMouseEventType::Over,
&hit_test_result,
input_event,
can_gc,
);
mouse_over_event
.upcast::<Event>()
@@ -671,49 +676,52 @@ impl DocumentEventHandler {
// Fire pointerover before mouseover
mouse_over_event
.to_pointer_hover_event("pointerover", can_gc)
.to_pointer_hover_event("pointerover", CanGc::from_cx(cx))
.upcast::<Event>()
.dispatch(new_target.upcast(), false, can_gc);
.dispatch(new_target.upcast(), false, CanGc::from_cx(cx));
mouse_over_event
.upcast::<Event>()
.dispatch(new_target.upcast(), false, can_gc);
mouse_over_event.upcast::<Event>().dispatch(
new_target.upcast(),
false,
CanGc::from_cx(cx),
);
let moving_from =
old_hover_target.map(|old_target| DomRoot::from_ref(old_target.upcast::<Node>()));
let event_target = DomRoot::from_ref(new_target.upcast::<Node>());
self.handle_mouse_enter_leave_event(
cx,
event_target,
moving_from,
FireMouseEventType::Enter,
&hit_test_result,
input_event,
can_gc,
);
}
// Send mousemove event to topmost target, unless it's an iframe, in which case
// `Paint` should have also sent an event to the inner document.
let mouse_event = MouseEvent::new_for_platform_motion_event(
cx,
&self.window,
FireMouseEventType::Move,
&hit_test_result,
input_event,
can_gc,
);
// Send pointermove event before mousemove.
let pointer_event = mouse_event.to_pointer_event(Atom::from("pointermove"), can_gc);
let pointer_event =
mouse_event.to_pointer_event(Atom::from("pointermove"), CanGc::from_cx(cx));
pointer_event.upcast::<Event>().set_composed(true);
pointer_event
.upcast::<Event>()
.fire(new_target.upcast(), can_gc);
.fire(new_target.upcast(), CanGc::from_cx(cx));
// Send mousemove event to topmost target, unless it's an iframe, in which case
// `Paint` should have also sent an event to the inner document.
mouse_event
.upcast::<Event>()
.fire(new_target.upcast(), can_gc);
.fire(new_target.upcast(), CanGc::from_cx(cx));
self.update_current_hover_target_and_status(Some(new_target));
}
@@ -801,9 +809,9 @@ impl DocumentEventHandler {
/// Handles native mouse down, mouse up, mouse click.
fn handle_native_mouse_button_event(
&self,
cx: &mut JSContext,
event: MouseButtonEvent,
input_event: &ConstellationInputEvent,
can_gc: CanGc,
) {
// Ignore all incoming events without a hit test.
let Some(hit_test_result) = self.window.hit_test_from_input_event(input_event) else {
@@ -869,6 +877,7 @@ impl DocumentEventHandler {
}
let dom_event = DomRoot::upcast::<Event>(MouseEvent::for_platform_button_event(
cx,
mouse_event_type,
event,
input_event.pressed_mouse_buttons,
@@ -876,7 +885,6 @@ impl DocumentEventHandler {
&hit_test_result,
input_event.active_keyboard_modifiers,
self.click_counting_info.borrow().count + 1,
can_gc,
));
match event.action {
@@ -895,14 +903,16 @@ impl DocumentEventHandler {
let pointer_event = dom_event
.downcast::<MouseEvent>()
.unwrap()
.to_pointer_event(event_type.into(), can_gc);
.to_pointer_event(event_type.into(), CanGc::from_cx(cx));
pointer_event.upcast::<Event>().fire(node.upcast(), can_gc);
pointer_event
.upcast::<Event>()
.fire(node.upcast(), CanGc::from_cx(cx));
self.down_button_count.set(down_button_count + 1);
// Step 7. Let result = dispatch event at target
let result = dom_event.dispatch(node.upcast(), false, can_gc);
let result = dom_event.dispatch(node.upcast(), false, CanGc::from_cx(cx));
// Step 8. If result is true and target is a focusable area
// that is click focusable, then Run the focusing steps at target.
@@ -913,7 +923,7 @@ impl DocumentEventHandler {
self.window.Document().focus_handler().focus(
FocusOperation::Focus(node.find_click_focusable_area()),
FocusInitiator::Local,
can_gc,
CanGc::from_cx(cx),
);
}
@@ -924,7 +934,7 @@ impl DocumentEventHandler {
node.upcast(),
&hit_test_result,
input_event,
can_gc,
CanGc::from_cx(cx),
);
}
},
@@ -945,12 +955,14 @@ impl DocumentEventHandler {
let pointer_event = dom_event
.downcast::<MouseEvent>()
.unwrap()
.to_pointer_event(event_type.into(), can_gc);
.to_pointer_event(event_type.into(), CanGc::from_cx(cx));
pointer_event.upcast::<Event>().fire(node.upcast(), can_gc);
pointer_event
.upcast::<Event>()
.fire(node.upcast(), CanGc::from_cx(cx));
// Step 7. dispatch event at target.
dom_event.dispatch(node.upcast(), false, can_gc);
dom_event.dispatch(node.upcast(), false, CanGc::from_cx(cx));
// Click counts should still work for other buttons even though they
// do not trigger "click" and "dblclick" events, so we increment
@@ -960,11 +972,11 @@ impl DocumentEventHandler {
.increment_click_count(event.button, hit_test_result.point_in_frame);
self.maybe_trigger_click_for_mouse_button_down_event(
cx,
event,
input_event,
&hit_test_result,
&element,
can_gc,
);
},
}
@@ -974,11 +986,11 @@ impl DocumentEventHandler {
/// <https://w3c.github.io/pointerevents/#handle-native-mouse-double-click>
fn maybe_trigger_click_for_mouse_button_down_event(
&self,
cx: &mut JSContext,
event: MouseButtonEvent,
input_event: &ConstellationInputEvent,
hit_test_result: &HitTestResult,
element: &Element,
can_gc: CanGc,
) {
if event.button != MouseButton::Left {
return;
@@ -1010,6 +1022,7 @@ impl DocumentEventHandler {
let click_count = self.click_counting_info.borrow().count;
element.set_click_in_progress(true);
MouseEvent::for_platform_button_event(
cx,
atom!("click"),
event,
input_event.pressed_mouse_buttons,
@@ -1017,10 +1030,9 @@ impl DocumentEventHandler {
hit_test_result,
input_event.active_keyboard_modifiers,
click_count,
can_gc,
)
.upcast::<Event>()
.dispatch(element.upcast(), false, can_gc);
.dispatch(element.upcast(), false, CanGc::from_cx(cx));
element.set_click_in_progress(false);
// The firing of "dbclick" events is dependent on the platform, so we have
@@ -1033,6 +1045,7 @@ impl DocumentEventHandler {
// even numbered clicks is a series of double clicks.
if click_count % 2 == 0 {
MouseEvent::for_platform_button_event(
cx,
Atom::from("dblclick"),
event,
input_event.pressed_mouse_buttons,
@@ -1040,10 +1053,9 @@ impl DocumentEventHandler {
hit_test_result,
input_event.active_keyboard_modifiers,
2,
can_gc,
)
.upcast::<Event>()
.dispatch(element.upcast(), false, can_gc);
.dispatch(element.upcast(), false, CanGc::from_cx(cx));
}
}
@@ -1105,9 +1117,9 @@ impl DocumentEventHandler {
fn handle_touch_event(
&self,
cx: &mut JSContext,
event: EmbedderTouchEvent,
input_event: &ConstellationInputEvent,
can_gc: CanGc,
) -> InputEventResult {
// Ignore all incoming events without a hit test.
let Some(hit_test_result) = self.window.hit_test_from_input_event(input_event) else {
@@ -1147,7 +1159,7 @@ impl DocumentEventHandler {
client_y,
page_x,
page_y,
can_gc,
CanGc::from_cx(cx),
);
// Dispatch pointer event before updating active touch points and before touch event.
@@ -1174,9 +1186,11 @@ impl DocumentEventHandler {
input_event.active_keyboard_modifiers,
true, // cancelable
Some(hit_test_result.point_in_node),
can_gc,
CanGc::from_cx(cx),
);
pointer_over.upcast::<Event>().fire(&current_target, can_gc);
pointer_over
.upcast::<Event>()
.fire(&current_target, CanGc::from_cx(cx));
// Fire pointerenter hierarchically (from topmost ancestor to target)
self.fire_pointer_event_for_touch(
@@ -1187,7 +1201,7 @@ impl DocumentEventHandler {
is_primary,
input_event,
&hit_test_result,
can_gc,
CanGc::from_cx(cx),
);
}
@@ -1199,11 +1213,11 @@ impl DocumentEventHandler {
input_event.active_keyboard_modifiers,
event.is_cancelable(),
Some(hit_test_result.point_in_node),
can_gc,
CanGc::from_cx(cx),
);
pointer_event
.upcast::<Event>()
.fire(&current_target, can_gc);
.fire(&current_target, CanGc::from_cx(cx));
// For touch devices, fire pointerout/pointerleave after pointerup/pointercancel
// <https://w3c.github.io/pointerevents/#mapping-for-devices-that-do-not-support-hover>
@@ -1220,9 +1234,11 @@ impl DocumentEventHandler {
input_event.active_keyboard_modifiers,
true, // cancelable
Some(hit_test_result.point_in_node),
can_gc,
CanGc::from_cx(cx),
);
pointer_out.upcast::<Event>().fire(&current_target, can_gc);
pointer_out
.upcast::<Event>()
.fire(&current_target, CanGc::from_cx(cx));
// Fire pointerleave hierarchically (from target to topmost ancestor)
self.fire_pointer_event_for_touch(
@@ -1233,7 +1249,7 @@ impl DocumentEventHandler {
is_primary,
input_event,
&hit_test_result,
can_gc,
CanGc::from_cx(cx),
);
}
@@ -1275,7 +1291,7 @@ impl DocumentEventHandler {
client_y,
page_x,
page_y,
can_gc,
CanGc::from_cx(cx),
);
// Update or remove the stored touch
@@ -1320,18 +1336,22 @@ impl DocumentEventHandler {
EventComposed::Composed,
Some(window),
0i32,
&TouchList::new(window, self.active_touch_points.borrow().r(), can_gc),
&TouchList::new(window, from_ref(&&*changed_touch), can_gc),
&TouchList::new(window, target_touches.r(), can_gc),
&TouchList::new(
window,
self.active_touch_points.borrow().r(),
CanGc::from_cx(cx),
),
&TouchList::new(window, from_ref(&&*changed_touch), CanGc::from_cx(cx)),
&TouchList::new(window, target_touches.r(), CanGc::from_cx(cx)),
// FIXME: modifier keys
false,
false,
false,
false,
can_gc,
CanGc::from_cx(cx),
);
let event = touch_event.upcast::<Event>();
event.fire(&touch_dispatch_target, can_gc);
event.fire(&touch_dispatch_target, CanGc::from_cx(cx));
event.flags().into()
}
@@ -1367,22 +1387,22 @@ impl DocumentEventHandler {
/// The entry point for all key processing for web content
fn handle_keyboard_event(
&self,
cx: &mut JSContext,
keyboard_event: EmbedderKeyboardEvent,
can_gc: CanGc,
) -> InputEventResult {
let target = &self.target_for_events_following_focus();
let keyevent = KeyboardEvent::new_with_platform_keyboard_event(
cx,
&self.window,
keyboard_event.event.state.event_type().into(),
&keyboard_event.event,
can_gc,
);
let event = keyevent.upcast::<Event>();
event.set_composed(true);
event.fire(target, can_gc);
event.fire(target, CanGc::from_cx(cx));
let mut flags = event.flags();
if flags.contains(EventFlags::Canceled) {
@@ -1404,28 +1424,28 @@ impl DocumentEventHandler {
{
// https://w3c.github.io/uievents/#keypress-event-order
let keypress_event = KeyboardEvent::new_with_platform_keyboard_event(
cx,
&self.window,
atom!("keypress"),
&keyboard_event.event,
can_gc,
);
keypress_event.upcast::<Event>().set_composed(true);
let event = keypress_event.upcast::<Event>();
event.fire(target, can_gc);
event.fire(target, CanGc::from_cx(cx));
flags = event.flags();
}
flags.into()
}
fn handle_ime_event(&self, event: ImeEvent, can_gc: CanGc) -> InputEventResult {
fn handle_ime_event(&self, cx: &mut JSContext, event: ImeEvent) -> InputEventResult {
let document = self.window.Document();
let composition_event = match event {
ImeEvent::Dismissed => {
document.focus_handler().focus(
FocusOperation::Focus(FocusableArea::Viewport),
FocusInitiator::Local,
can_gc,
CanGc::from_cx(cx),
);
return Default::default();
},
@@ -1451,19 +1471,19 @@ impl DocumentEventHandler {
Some(&self.window),
0,
DOMString::from(composition_event.data),
can_gc,
CanGc::from_cx(cx),
);
let event = event.upcast::<Event>();
event.fire(focused_element.upcast(), can_gc);
event.fire(focused_element.upcast(), CanGc::from_cx(cx));
event.flags().into()
}
fn handle_wheel_event(
&self,
cx: &mut JSContext,
event: EmbedderWheelEvent,
input_event: &ConstellationInputEvent,
can_gc: CanGc,
) -> InputEventResult {
// Ignore all incoming events without a hit test.
let Some(hit_test_result) = self.window.hit_test_from_input_event(input_event) else {
@@ -1511,13 +1531,13 @@ impl DocumentEventHandler {
Finite::wrap(-event.delta.y),
Finite::wrap(-event.delta.z),
event.delta.mode as u32,
can_gc,
CanGc::from_cx(cx),
);
let dom_event = dom_event.upcast::<Event>();
dom_event.set_trusted(true);
dom_event.set_composed(true);
dom_event.fire(node.upcast(), can_gc);
dom_event.fire(node.upcast(), CanGc::from_cx(cx));
dom_event.flags().into()
}
@@ -1651,9 +1671,9 @@ impl DocumentEventHandler {
/// <https://www.w3.org/TR/clipboard-apis/#clipboard-actions>
pub(crate) fn handle_editing_action(
&self,
cx: &mut JSContext,
element: Option<DomRoot<Element>>,
action: EditingActionEvent,
can_gc: CanGc,
) -> InputEventResult {
let clipboard_event_type = match action {
EditingActionEvent::Copy => ClipboardEventType::Copy,
@@ -1676,7 +1696,7 @@ impl DocumentEventHandler {
// Step 2 Fire a clipboard event
let clipboard_event =
self.fire_clipboard_event(element.clone(), clipboard_event_type, can_gc);
self.fire_clipboard_event(element.clone(), clipboard_event_type, CanGc::from_cx(cx));
// Step 3 If a script doesn't call preventDefault()
// the event will be handled inside target's VirtualMethods::handle_event
@@ -1709,7 +1729,7 @@ impl DocumentEventHandler {
}
// Step 4.2 Fire a clipboard event named clipboardchange
self.fire_clipboard_event(element, ClipboardEventType::Change, can_gc);
self.fire_clipboard_event(element, ClipboardEventType::Change, CanGc::from_cx(cx));
},
// Step 4.1 Return false.
// Note: This function deviates from the specification a bit by returning

View File

@@ -6,6 +6,7 @@ use std::cell::Cell;
use std::str::FromStr;
use dom_struct::dom_struct;
use js::context::JSContext;
use js::rust::HandleObject;
use keyboard_types::{Code, Key, Modifiers, NamedKey};
use style::Atom;
@@ -16,13 +17,12 @@ use crate::dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEvent
use crate::dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
use crate::dom::bindings::reflector::reflect_dom_object_with_proto_and_cx;
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::event::Event;
use crate::dom::uievent::UIEvent;
use crate::dom::window::Window;
use crate::script_runtime::CanGc;
#[dom_struct]
pub(crate) struct KeyboardEvent {
@@ -59,30 +59,31 @@ impl KeyboardEvent {
}
}
pub(crate) fn new_uninitialized(window: &Window, can_gc: CanGc) -> DomRoot<KeyboardEvent> {
Self::new_uninitialized_with_proto(window, None, can_gc)
pub(crate) fn new_uninitialized(cx: &mut JSContext, window: &Window) -> DomRoot<KeyboardEvent> {
Self::new_uninitialized_with_proto(cx, window, None)
}
fn new_uninitialized_with_proto(
cx: &mut JSContext,
window: &Window,
proto: Option<HandleObject>,
can_gc: CanGc,
) -> DomRoot<KeyboardEvent> {
reflect_dom_object_with_proto(
reflect_dom_object_with_proto_and_cx(
Box::new(KeyboardEvent::new_inherited()),
window,
proto,
can_gc,
cx,
)
}
pub(crate) fn new_with_platform_keyboard_event(
cx: &mut JSContext,
window: &Window,
event_type: Atom,
keyboard_event: &keyboard_types::KeyboardEvent,
can_gc: CanGc,
) -> DomRoot<KeyboardEvent> {
Self::new_with_proto(
cx,
window,
None,
event_type,
@@ -99,12 +100,12 @@ impl KeyboardEvent {
keyboard_event.modifiers,
0, /* char_code */
keyboard_event.key.legacy_keycode(),
can_gc,
)
}
#[expect(clippy::too_many_arguments)]
fn new_with_proto(
cx: &mut JSContext,
window: &Window,
proto: Option<HandleObject>,
event_type: Atom,
@@ -121,9 +122,8 @@ impl KeyboardEvent {
modifiers: Modifiers,
char_code: u32,
key_code: u32,
can_gc: CanGc,
) -> DomRoot<KeyboardEvent> {
let event = KeyboardEvent::new_uninitialized_with_proto(window, proto, can_gc);
let event = KeyboardEvent::new_uninitialized_with_proto(cx, window, proto);
event.init_event(
event_type,
can_bubble,
@@ -188,9 +188,9 @@ impl KeyboardEvent {
impl KeyboardEventMethods<crate::DomTypeHolder> for KeyboardEvent {
/// <https://w3c.github.io/uievents/#dom-keyboardevent-keyboardevent>
fn Constructor(
cx: &mut JSContext,
window: &Window,
proto: Option<HandleObject>,
can_gc: CanGc,
event_type: DOMString,
init: &KeyboardEventBinding::KeyboardEventInit,
) -> Fallible<DomRoot<KeyboardEvent>> {
@@ -200,6 +200,7 @@ impl KeyboardEventMethods<crate::DomTypeHolder> for KeyboardEvent {
modifiers.set(Modifiers::SHIFT, init.parent.shiftKey);
modifiers.set(Modifiers::META, init.parent.metaKey);
let event = KeyboardEvent::new_with_proto(
cx,
window,
proto,
event_type.into(),
@@ -216,7 +217,6 @@ impl KeyboardEventMethods<crate::DomTypeHolder> for KeyboardEvent {
modifiers,
init.charCode,
init.keyCode,
can_gc,
);
*event.key.borrow_mut() = init.key.clone();
Ok(event)

View File

@@ -8,6 +8,7 @@ use std::f64::consts::PI;
use dom_struct::dom_struct;
use euclid::Point2D;
use js::context::JSContext;
use js::rust::HandleObject;
use keyboard_types::Modifiers;
use script_bindings::codegen::GenericBindings::WindowBinding::WindowMethods;
@@ -22,7 +23,7 @@ use crate::dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethod
use crate::dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object_with_proto};
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object_with_proto_and_cx};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::document::FireMouseEventType;
@@ -95,20 +96,26 @@ impl MouseEvent {
}
}
pub(crate) fn new_uninitialized(window: &Window, can_gc: CanGc) -> DomRoot<MouseEvent> {
Self::new_uninitialized_with_proto(window, None, can_gc)
pub(crate) fn new_uninitialized(cx: &mut JSContext, window: &Window) -> DomRoot<MouseEvent> {
Self::new_uninitialized_with_proto(cx, window, None)
}
fn new_uninitialized_with_proto(
cx: &mut JSContext,
window: &Window,
proto: Option<HandleObject>,
can_gc: CanGc,
) -> DomRoot<MouseEvent> {
reflect_dom_object_with_proto(Box::new(MouseEvent::new_inherited()), window, proto, can_gc)
reflect_dom_object_with_proto_and_cx(
Box::new(MouseEvent::new_inherited()),
window,
proto,
cx,
)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(
cx: &mut JSContext,
window: &Window,
event_type: Atom,
can_bubble: EventBubbles,
@@ -123,9 +130,9 @@ impl MouseEvent {
buttons: u16,
related_target: Option<&EventTarget>,
point_in_target: Option<Point2D<f32, CSSPixel>>,
can_gc: CanGc,
) -> DomRoot<MouseEvent> {
Self::new_with_proto(
cx,
window,
None,
event_type,
@@ -141,12 +148,12 @@ impl MouseEvent {
buttons,
related_target,
point_in_target,
can_gc,
)
}
#[allow(clippy::too_many_arguments)]
fn new_with_proto(
cx: &mut JSContext,
window: &Window,
proto: Option<HandleObject>,
event_type: Atom,
@@ -162,9 +169,8 @@ impl MouseEvent {
buttons: u16,
related_target: Option<&EventTarget>,
point_in_target: Option<Point2D<f32, CSSPixel>>,
can_gc: CanGc,
) -> DomRoot<MouseEvent> {
let ev = MouseEvent::new_uninitialized_with_proto(window, proto, can_gc);
let ev = MouseEvent::new_uninitialized_with_proto(cx, window, proto);
ev.initialize_mouse_event(
event_type,
can_bubble,
@@ -223,11 +229,11 @@ impl MouseEvent {
}
pub(crate) fn new_for_platform_motion_event(
cx: &mut JSContext,
window: &Window,
event_name: FireMouseEventType,
hit_test_result: &HitTestResult,
input_event: &ConstellationInputEvent,
can_gc: CanGc,
) -> DomRoot<Self> {
// These values come from the event tables in
// <https://w3c.github.io/pointerevents/#mouse-event-types>.
@@ -243,6 +249,7 @@ impl MouseEvent {
};
let mouse_event = Self::new(
cx,
window,
Atom::from(event_name.as_str()),
bubbles,
@@ -259,7 +266,6 @@ impl MouseEvent {
input_event.pressed_mouse_buttons,
None,
None,
can_gc,
);
let event = mouse_event.upcast::<Event>();
@@ -274,6 +280,7 @@ impl MouseEvent {
/// <https://w3c.github.io/pointerevents/#create-a-cancelable-mouseevent>
#[expect(clippy::too_many_arguments)]
pub(crate) fn for_platform_button_event(
cx: &mut JSContext,
event_type: Atom,
event: embedder_traits::MouseButtonEvent,
pressed_mouse_buttons: u16,
@@ -281,7 +288,6 @@ impl MouseEvent {
hit_test_result: &HitTestResult,
modifiers: Modifiers,
click_count: usize,
can_gc: CanGc,
) -> DomRoot<Self> {
let client_point = hit_test_result.point_in_frame.to_i32();
let page_point = hit_test_result
@@ -289,6 +295,7 @@ impl MouseEvent {
.to_i32();
let mouse_event = Self::new(
cx,
window,
event_type,
EventBubbles::Bubbles,
@@ -303,7 +310,6 @@ impl MouseEvent {
pressed_mouse_buttons,
None,
Some(hit_test_result.point_in_node),
can_gc,
);
mouse_event.upcast::<Event>().set_trusted(true);
@@ -459,9 +465,9 @@ impl MouseEvent {
impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
/// <https://w3c.github.io/pointerevents/#dom-mouseevent-constructor>
fn Constructor(
cx: &mut JSContext,
window: &Window,
proto: Option<HandleObject>,
can_gc: CanGc,
event_type: DOMString,
init: &MouseEventBinding::MouseEventInit,
) -> Fallible<DomRoot<MouseEvent>> {
@@ -473,6 +479,7 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
scroll_offset.y as i32 + init.clientY,
);
let event = MouseEvent::new_with_proto(
cx,
window,
proto,
event_type.into(),
@@ -488,7 +495,6 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
init.buttons,
init.relatedTarget.as_deref(),
None,
can_gc,
);
event
.upcast::<Event>()

View File

@@ -1061,7 +1061,11 @@ impl ScriptThread {
}
/// Process input events as part of a "update the rendering task".
fn process_pending_input_events(&self, pipeline_id: PipelineId, can_gc: CanGc) {
fn process_pending_input_events(
&self,
cx: &mut js::context::JSContext,
pipeline_id: PipelineId,
) {
let Some(document) = self.documents.borrow().find_document(pipeline_id) else {
warn!("Processing pending input events for closed pipeline {pipeline_id}.");
return;
@@ -1076,7 +1080,7 @@ impl ScriptThread {
}
let _guard = ScriptUserInteractingGuard::new(self.is_user_interacting.clone());
document.event_handler().handle_pending_input_events(can_gc);
document.event_handler().handle_pending_input_events(cx);
}
fn cancel_scheduled_update_the_rendering(&self) {
@@ -1186,7 +1190,7 @@ impl ScriptThread {
// TODO: Should this be broken and to match the specification more closely? For instance see
// https://html.spec.whatwg.org/multipage/#flush-autofocus-candidates.
self.process_pending_input_events(*pipeline_id, CanGc::from_cx(cx));
self.process_pending_input_events(cx, *pipeline_id);
// > 8. For each doc of docs, run the resize steps for doc. [CSSOMVIEW]
let resized = document.window().run_the_resize_steps(CanGc::from_cx(cx));

View File

@@ -200,7 +200,7 @@ DOMInterfaces = {
'Document': {
'additionalTraits': ["crate::interfaces::DocumentHelpers"],
'canGc': ['CreateEvent', 'CreateRange', 'SetBgColor', 'SetFgColor', 'Fonts', 'ExitFullscreen', 'CreateExpression', 'CreateNSResolver', 'Evaluate', 'StyleSheets', 'Implementation', 'GetElementsByTagName', 'GetElementsByTagNameNS', 'GetElementsByClassName', 'CreateNodeIterator', 'GetElementsByName', 'Images', 'Embeds', 'Plugins', 'Links', 'Forms', 'Scripts', 'Anchors', 'Applets', 'Children', 'GetSelection', 'NamedGetter', 'AdoptedStyleSheets', 'SetAdoptedStyleSheets'],
'canGc': ['CreateRange', 'SetBgColor', 'SetFgColor', 'Fonts', 'ExitFullscreen', 'CreateExpression', 'CreateNSResolver', 'Evaluate', 'StyleSheets', 'Implementation', 'GetElementsByTagName', 'GetElementsByTagNameNS', 'GetElementsByClassName', 'CreateNodeIterator', 'GetElementsByName', 'Images', 'Embeds', 'Plugins', 'Links', 'Forms', 'Scripts', 'Anchors', 'Applets', 'Children', 'GetSelection', 'NamedGetter', 'AdoptedStyleSheets', 'SetAdoptedStyleSheets'],
'cx': [
'AdoptNode',
'Append',
@@ -212,6 +212,7 @@ DOMInterfaces = {
'CreateDocumentFragment',
'CreateElement',
'CreateElementNS',
'CreateEvent',
'CreateProcessingInstruction',
'CreateTextNode',
'ExecCommand',
@@ -633,6 +634,10 @@ DOMInterfaces = {
'canGc': ['Thresholds']
},
'KeyboardEvent': {
'cx': ['Constructor'],
},
'LayoutResult': {
'canGc': ['Phases']
},
@@ -689,6 +694,10 @@ DOMInterfaces = {
'canGc': ['Ports'],
},
'MouseEvent': {
'cx': ['Constructor'],
},
'NamedNodeMap': {
'cx': ['SetNamedItem', 'SetNamedItemNS', 'RemoveNamedItem', 'RemoveNamedItemNS', 'RemoveAttribute'],
},
@@ -898,7 +907,7 @@ DOMInterfaces = {
'cx': [
'Focus',
'GetLocalStorage',
'GetSessionStorage',
'GetSessionStorage',
'Location',
'Open',
'PostMessage',