From d0a93a8b0294697d455b0ef52cbc612f798fee80 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Sat, 12 Jul 2025 10:17:55 -0400 Subject: [PATCH] script: Minimize layout queries for window scroll offsets. (#38018) These changes reduce the number of times we need to query layout for the same information when creating mouse/pointer events. Testing: No new tests required for maintaining existing behaviour. Signed-off-by: Josh Matthews --- components/script/dom/mouseevent.rs | 11 +++++--- components/script/dom/pointerevent.rs | 6 ++--- components/script/dom/wheelevent.rs | 3 +++ components/script/dom/window.rs | 27 ++++++++++--------- .../script_bindings/codegen/Bindings.conf | 6 ++++- 5 files changed, 32 insertions(+), 21 deletions(-) diff --git a/components/script/dom/mouseevent.rs b/components/script/dom/mouseevent.rs index e2e304b195a..bb02f9451e3 100644 --- a/components/script/dom/mouseevent.rs +++ b/components/script/dom/mouseevent.rs @@ -278,9 +278,10 @@ impl MouseEventMethods for MouseEvent { ) -> Fallible> { let bubbles = EventBubbles::from(init.parent.parent.parent.bubbles); let cancelable = EventCancelable::from(init.parent.parent.parent.cancelable); + let scroll_offset = window.scroll_offset(can_gc); let page_point = Point2D::new( - window.ScrollX() + init.clientX, - window.ScrollY() + init.clientY, + scroll_offset.x as i32 + init.clientX, + scroll_offset.y as i32 + init.clientY, ); let event = MouseEvent::new_with_proto( window, @@ -478,6 +479,7 @@ impl MouseEventMethods for MouseEvent { meta_key_arg: bool, button_arg: i16, related_target_arg: Option<&EventTarget>, + can_gc: CanGc, ) { if self.upcast::().dispatching() { return; @@ -496,9 +498,10 @@ impl MouseEventMethods for MouseEvent { .set(Point2D::new(client_x_arg, client_y_arg)); let global = self.global(); + let scroll_offset = global.as_window().scroll_offset(can_gc); self.page_point.set(Point2D::new( - global.as_window().ScrollX() + client_x_arg, - global.as_window().ScrollY() + client_y_arg, + scroll_offset.x as i32 + client_x_arg, + scroll_offset.y as i32 + client_y_arg, )); let mut modifiers = Modifiers::empty(); diff --git a/components/script/dom/pointerevent.rs b/components/script/dom/pointerevent.rs index 64dd2aed685..88238f64dd2 100644 --- a/components/script/dom/pointerevent.rs +++ b/components/script/dom/pointerevent.rs @@ -8,7 +8,6 @@ use dom_struct::dom_struct; use euclid::Point2D; use js::rust::HandleObject; use keyboard_types::Modifiers; -use script_bindings::codegen::GenericBindings::WindowBinding::WindowMethods; use style_traits::CSSPixel; use super::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods; @@ -234,9 +233,10 @@ impl PointerEventMethods for PointerEvent { ) -> DomRoot { let bubbles = EventBubbles::from(init.parent.parent.parent.parent.bubbles); let cancelable = EventCancelable::from(init.parent.parent.parent.parent.cancelable); + let scroll_offset = window.scroll_offset(can_gc); let page_point = Point2D::new( - window.ScrollX() + init.parent.clientX, - window.ScrollY() + init.parent.clientY, + scroll_offset.x as i32 + init.parent.clientX, + scroll_offset.y as i32 + init.parent.clientY, ); PointerEvent::new_with_proto( window, diff --git a/components/script/dom/wheelevent.rs b/components/script/dom/wheelevent.rs index 6f2b0d535e3..2923e49d5a2 100644 --- a/components/script/dom/wheelevent.rs +++ b/components/script/dom/wheelevent.rs @@ -95,6 +95,7 @@ impl WheelEvent { delta_y, delta_z, delta_mode, + can_gc, ); ev @@ -160,6 +161,7 @@ impl WheelEventMethods for WheelEvent { delta_y_arg: Finite, delta_z_arg: Finite, delta_mode_arg: u32, + can_gc: CanGc, ) { if self.upcast::().dispatching() { return; @@ -181,6 +183,7 @@ impl WheelEventMethods for WheelEvent { self.mouseevent.MetaKey(), self.mouseevent.Button(), self.mouseevent.GetRelatedTarget().as_deref(), + can_gc, ); self.delta_x.set(delta_x_arg); self.delta_y.set(delta_y_arg); diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index a88e7be215d..d2802841835 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1596,11 +1596,7 @@ impl WindowMethods for Window { /// fn ScrollX(&self) -> i32 { - self.scroll_offset_query_with_external_scroll_id( - self.pipeline_id().root_scroll_id(), - CanGc::note(), - ) - .x as i32 + self.scroll_offset(CanGc::note()).x as i32 } // https://drafts.csswg.org/cssom-view/#dom-window-pagexoffset @@ -1610,11 +1606,7 @@ impl WindowMethods for Window { /// fn ScrollY(&self) -> i32 { - self.scroll_offset_query_with_external_scroll_id( - self.pipeline_id().root_scroll_id(), - CanGc::note(), - ) - .y as i32 + self.scroll_offset(CanGc::note()).y as i32 } // https://drafts.csswg.org/cssom-view/#dom-window-pageyoffset @@ -1656,10 +1648,11 @@ impl WindowMethods for Window { // https://drafts.csswg.org/cssom-view/#dom-window-scrollby fn ScrollBy_(&self, x: f64, y: f64, can_gc: CanGc) { + let scroll_offset = self.scroll_offset(can_gc); // Step 3 - let left = x + self.ScrollX() as f64; + let left = x + scroll_offset.x as f64; // Step 4 - let top = y + self.ScrollY() as f64; + let top = y + scroll_offset.y as f64; // Step 5 self.scroll(left, top, ScrollBehavior::Auto, can_gc); @@ -1984,6 +1977,13 @@ impl WindowMethods for Window { } impl Window { + pub(crate) fn scroll_offset(&self, can_gc: CanGc) -> Vector2D { + self.scroll_offset_query_with_external_scroll_id( + self.pipeline_id().root_scroll_id(), + can_gc, + ) + } + // https://heycam.github.io/webidl/#named-properties-object // https://html.spec.whatwg.org/multipage/#named-access-on-the-window-object #[allow(unsafe_code)] @@ -2102,7 +2102,8 @@ impl Window { // Step 10 //TODO handling ongoing smooth scrolling - if x == self.ScrollX() as f64 && y == self.ScrollY() as f64 { + let scroll_offset = self.scroll_offset(can_gc); + if x == scroll_offset.x as f64 && y == scroll_offset.y as f64 { return; } diff --git a/components/script_bindings/codegen/Bindings.conf b/components/script_bindings/codegen/Bindings.conf index 97f4fb58f6f..af1b0435d6d 100644 --- a/components/script_bindings/codegen/Bindings.conf +++ b/components/script_bindings/codegen/Bindings.conf @@ -488,7 +488,7 @@ DOMInterfaces = { }, 'MouseEvent': { - 'canGc': ['OffsetX', 'OffsetY'], + 'canGc': ['InitMouseEvent', 'OffsetX', 'OffsetY'], }, 'NavigationPreloadManager': { @@ -649,6 +649,10 @@ DOMInterfaces = { 'additionalTraits': ['crate::interfaces::WebGL2RenderingContextHelpers'], }, +'WheelEvent': { + 'canGc': ['InitWheelEvent'], +}, + 'Window': { 'canGc': ['Stop', 'Fetch', 'Scroll', 'Scroll_','ScrollBy', 'ScrollBy_', 'Stop', 'Fetch', 'Open', 'CreateImageBitmap', 'CreateImageBitmap_', 'TrustedTypes', 'WebdriverCallback', 'WebdriverException'], 'inRealms': ['Fetch', 'GetOpener', 'WebdriverCallback', 'WebdriverException'],