From 900dd8d191d139e6ac7e528ba49edc2b9597a132 Mon Sep 17 00:00:00 2001 From: Jo Steven Novaryo <65610990+stevennovaryo@users.noreply.github.com> Date: Wed, 30 Jul 2025 16:13:54 +0800 Subject: [PATCH] layout: Consider transform for bounding box queries (#37871) The recent changes that cached the Scroll Tree present an opportunity to calculate the queries that consider transform and scroll (dubbed as post composite queries) accurately. This PR propose a solution for this calculation by noting the lowest scroll tree nodes that would affect a fragment. To do this, each fragment would store a new attribute `spatial_tree_node` -- scroll tree node id that we could use for the query. This referencing is considered because the scroll tree node construction is managed by the fragment itself. Therefore it would ease the managing the possibly stale reference and future query cache invalidation considering the development of incremental layout. The bounding box query then could transform the bounding content rect of a fragment using the computed current transformation matrix. Fixes: https://github.com/servo/servo/issues/35768 Testing: Existing and new WPT --------- Signed-off-by: stevennovaryo Signed-off-by: Jo Steven Novaryo Signed-off-by: Martin Robinson Co-authored-by: Martin Robinson --- .../layout/display_list/stacking_context.rs | 10 ++ .../layout/fragment_tree/box_fragment.rs | 12 ++ components/layout/fragment_tree/fragment.rs | 10 +- components/layout/layout_impl.rs | 29 +++- components/layout/query.rs | 66 ++++++++- components/shared/base/id.rs | 2 +- components/shared/compositing/display_list.rs | 52 ++++++- tests/wpt/meta/MANIFEST.json | 7 + ...ition-sticky-transforms-translate.html.ini | 3 - .../3d-rendering-context-behavior.html.ini | 9 -- ...ansform-getBoundingClientRect-001.html.ini | 3 - .../css/cssom-view/GetBoundingRect.html.ini | 3 - .../elementsFromPoint-iframes.html.ini | 3 - .../elementsFromPoint-simple.html.ini | 3 - .../bounding-box.html.ini | 9 -- .../edge-inclusive-intersection.html.ini | 12 -- .../isIntersecting-threshold.html.ini | 3 - .../multiple-targets.html.ini | 9 -- .../multiple-thresholds.html.ini | 21 --- .../observer-without-js-reference.html.ini | 3 - .../remove-element.html.ini | 6 +- .../root-margin-root-element.html.ini | 3 - .../root-margin.html.ini | 9 -- .../same-document-no-root.html.ini | 6 - .../same-document-root.html.ini | 3 - .../same-document-with-document-root.html.ini | 3 - .../same-document-zero-size-target.html.ini | 6 - .../text-target.html.ini | 6 - .../unclipped-root.html.ini | 6 - .../visibility-hidden.html.ini | 3 - .../getBoundingClientRect-scroll.html | 130 ++++++++++++++++++ 31 files changed, 304 insertions(+), 146 deletions(-) delete mode 100644 tests/wpt/meta/css/css-transforms/transform-getBoundingClientRect-001.html.ini delete mode 100644 tests/wpt/meta/css/cssom-view/GetBoundingRect.html.ini delete mode 100644 tests/wpt/meta/css/cssom-view/elementsFromPoint-simple.html.ini delete mode 100644 tests/wpt/meta/intersection-observer/edge-inclusive-intersection.html.ini delete mode 100644 tests/wpt/meta/intersection-observer/multiple-targets.html.ini delete mode 100644 tests/wpt/meta/intersection-observer/multiple-thresholds.html.ini delete mode 100644 tests/wpt/meta/intersection-observer/observer-without-js-reference.html.ini delete mode 100644 tests/wpt/meta/intersection-observer/root-margin.html.ini delete mode 100644 tests/wpt/meta/intersection-observer/same-document-no-root.html.ini delete mode 100644 tests/wpt/meta/intersection-observer/same-document-with-document-root.html.ini delete mode 100644 tests/wpt/meta/intersection-observer/same-document-zero-size-target.html.ini delete mode 100644 tests/wpt/meta/intersection-observer/text-target.html.ini delete mode 100644 tests/wpt/meta/intersection-observer/unclipped-root.html.ini delete mode 100644 tests/wpt/meta/intersection-observer/visibility-hidden.html.ini create mode 100644 tests/wpt/tests/css/cssom-view/getBoundingClientRect-scroll.html diff --git a/components/layout/display_list/stacking_context.rs b/components/layout/display_list/stacking_context.rs index 3dce9b4a019..060589fd5fd 100644 --- a/components/layout/display_list/stacking_context.rs +++ b/components/layout/display_list/stacking_context.rs @@ -201,6 +201,7 @@ impl StackingContextTree { fn push_reference_frame( &mut self, origin: LayoutPoint, + frame_origin_for_query: LayoutPoint, parent_scroll_node_id: &ScrollTreeNodeId, transform_style: wr::TransformStyle, transform: LayoutTransform, @@ -210,6 +211,7 @@ impl StackingContextTree { Some(parent_scroll_node_id), SpatialTreeNodeInfo::ReferenceFrame(ReferenceFrameNodeInfo { origin, + frame_origin_for_query, transform_style, transform, kind, @@ -994,8 +996,11 @@ impl BoxFragment { return; } + let frame_origin_for_query = self.cumulative_border_box_rect().origin.to_webrender(); + let new_spatial_id = stacking_context_tree.push_reference_frame( reference_frame_data.origin.to_webrender(), + frame_origin_for_query, &containing_block.scroll_node_id, self.style.get_box().transform_style.to_webrender(), reference_frame_data.transform, @@ -1212,6 +1217,11 @@ impl BoxFragment { add_fragment(StackingContextSection::Outline); } + // Spatial tree node that will affect the transform of the fragment. Note that the next frame, + // scroll frame, does not affect the transform of the fragment but affect the transform of it + // children. + *self.spatial_tree_node.borrow_mut() = Some(new_scroll_node_id); + // We want to build the scroll frame after the background and border, because // they shouldn't scroll with the rest of the box content. if let Some(overflow_frame_data) = self.build_overflow_frame_if_necessary( diff --git a/components/layout/fragment_tree/box_fragment.rs b/components/layout/fragment_tree/box_fragment.rs index 0e032b5b9f8..b11126d80ad 100644 --- a/components/layout/fragment_tree/box_fragment.rs +++ b/components/layout/fragment_tree/box_fragment.rs @@ -4,6 +4,7 @@ use app_units::{Au, MAX_AU, MIN_AU}; use atomic_refcell::AtomicRefCell; +use base::id::ScrollTreeNodeId; use base::print_tree::PrintTree; use malloc_size_of_derive::MallocSizeOf; use servo_arc::Arc as ServoArc; @@ -109,6 +110,12 @@ pub(crate) struct BoxFragment { /// Additional information for block-level boxes. pub block_level_layout_info: Option>, + + /// The containing spatial tree node of this [`BoxFragment`]. This is assigned during + /// `StackingContextTree` construction, so isn't available before that time. This is + /// used to for determining final viewport size and position of this node and will + /// also be used in the future for hit testing. + pub spatial_tree_node: AtomicRefCell>, } impl BoxFragment { @@ -138,6 +145,7 @@ impl BoxFragment { background_mode: BackgroundMode::Normal, specific_layout_info, block_level_layout_info: None, + spatial_tree_node: AtomicRefCell::default(), } } @@ -270,6 +278,10 @@ impl BoxFragment { rect.translate(self.cumulative_containing_block_rect.origin.to_vector()) } + pub(crate) fn cumulative_border_box_rect(&self) -> PhysicalRect { + self.offset_by_containing_block(&self.border_rect()) + } + pub(crate) fn padding_rect(&self) -> PhysicalRect { self.content_rect.outer_rect(self.padding) } diff --git a/components/layout/fragment_tree/fragment.rs b/components/layout/fragment_tree/fragment.rs index 00efe9ac64b..77072b2797b 100644 --- a/components/layout/fragment_tree/fragment.rs +++ b/components/layout/fragment_tree/fragment.rs @@ -205,8 +205,7 @@ impl Fragment { pub(crate) fn cumulative_border_box_rect(&self) -> Option> { match self { Fragment::Box(fragment) | Fragment::Float(fragment) => { - let fragment = fragment.borrow(); - Some(fragment.offset_by_containing_block(&fragment.border_rect())) + Some(fragment.borrow().cumulative_border_box_rect()) }, Fragment::Positioning(fragment) => { let fragment = fragment.borrow(); @@ -325,6 +324,13 @@ impl Fragment { Fragment::IFrame(iframe_fragment) => iframe_fragment.borrow_mut().style = style.clone(), } } + + pub(crate) fn retrieve_box_fragment(&self) -> Option<&ArcRefCell> { + match self { + Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => Some(box_fragment), + _ => None, + } + } } impl TextFragment { diff --git a/components/layout/layout_impl.rs b/components/layout/layout_impl.rs index 5d70bccd8dc..eab280ac85b 100644 --- a/components/layout/layout_impl.rs +++ b/components/layout/layout_impl.rs @@ -253,16 +253,34 @@ impl Layout for LayoutThread { .remove_all_web_fonts_from_stylesheet(&stylesheet); } + /// Return the union of this node's content boxes in the coordinate space of the Document. + /// to implement `getBoundingClientRect()`. + /// + /// Part of + /// TODO(stevennovaryo): Rename and parameterize the function, allowing padding area + /// query and possibly, query without consideration of transform. #[servo_tracing::instrument(skip_all)] fn query_content_box(&self, node: TrustedNodeAddress) -> Option> { let node = unsafe { ServoLayoutNode::new(&node) }; - process_content_box_request(node) + let stacking_context_tree = self.stacking_context_tree.borrow(); + let stacking_context_tree = stacking_context_tree + .as_ref() + .expect("Should always have a StackingContextTree for geometry queries"); + process_content_box_request(stacking_context_tree, node) } + /// Get a `Vec` of bounding boxes of this node's `Fragement`s in the coordinate space of the + /// Document. This is used to implement `getClientRects()`. + /// + /// See . #[servo_tracing::instrument(skip_all)] fn query_content_boxes(&self, node: TrustedNodeAddress) -> Vec> { let node = unsafe { ServoLayoutNode::new(&node) }; - process_content_boxes_request(node) + let stacking_context_tree = self.stacking_context_tree.borrow(); + let stacking_context_tree = stacking_context_tree + .as_ref() + .expect("Should always have a StackingContextTree for geometry queries"); + process_content_boxes_request(stacking_context_tree, node) } #[servo_tracing::instrument(skip_all)] @@ -1431,12 +1449,11 @@ impl ReflowPhases { QueryMsg::NodesFromPointQuery => { Self::StackingContextTreeConstruction | Self::DisplayListConstruction }, - QueryMsg::ResolvedStyleQuery | QueryMsg::ScrollingAreaOrOffsetQuery => { - Self::StackingContextTreeConstruction - }, - QueryMsg::ClientRectQuery | QueryMsg::ContentBox | QueryMsg::ContentBoxes | + QueryMsg::ResolvedStyleQuery | + QueryMsg::ScrollingAreaOrOffsetQuery => Self::StackingContextTreeConstruction, + QueryMsg::ClientRectQuery | QueryMsg::ElementInnerOuterTextQuery | QueryMsg::InnerWindowDimensionsQuery | QueryMsg::OffsetParentQuery | diff --git a/components/layout/query.rs b/components/layout/query.rs index 1761faed012..429f2d92da2 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -6,6 +6,7 @@ use std::rc::Rc; use app_units::Au; +use compositing_traits::display_list::ScrollTree; use euclid::default::{Point2D, Rect}; use euclid::{SideOffsets2D, Size2D}; use itertools::Itertools; @@ -13,6 +14,7 @@ use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafe use layout_api::{LayoutElementType, LayoutNodeType, OffsetParentResponse}; use script::layout_dom::ServoLayoutNode; use servo_arc::Arc as ServoArc; +use servo_geometry::{au_rect_to_f32_rect, f32_rect_to_au_rect}; use servo_url::ServoUrl; use style::computed_values::display::T as Display; use style::computed_values::position::T as Position; @@ -37,8 +39,10 @@ use style::values::specified::GenericGridTemplateComponent; use style::values::specified::box_::DisplayInside; use style::values::specified::text::TextTransformCase; use style_traits::{ParsingMode, ToCss}; +use webrender_api::units::LayoutTransform; use crate::ArcRefCell; +use crate::display_list::StackingContextTree; use crate::dom::NodeExt; use crate::flow::inline::construct::{TextTransformation, WhitespaceCollapse, capitalize_string}; use crate::fragment_tree::{ @@ -46,7 +50,28 @@ use crate::fragment_tree::{ }; use crate::taffy::SpecificTaffyGridInfo; -pub fn process_content_box_request(node: ServoLayoutNode<'_>) -> Option> { +/// Get a scroll node that would represents this [`ServoLayoutNode`]'s transform and +/// calculate its cumlative transform from its root scroll node to the scroll node. +fn root_transform_for_layout_node( + scroll_tree: &ScrollTree, + node: ServoLayoutNode<'_>, +) -> Option { + let fragments = node.fragments_for_pseudo(None); + let box_fragment = fragments + .first() + .and_then(Fragment::retrieve_box_fragment)? + .borrow(); + let scroll_tree_node_id = box_fragment + .spatial_tree_node + .borrow() + .expect("Should always have a scroll tree node when querying bounding box."); + Some(scroll_tree.cumulative_node_transform(&scroll_tree_node_id)) +} + +pub(crate) fn process_content_box_request( + stacking_context_tree: &StackingContextTree, + node: ServoLayoutNode<'_>, +) -> Option> { let rects: Vec<_> = node .fragments_for_pseudo(None) .iter() @@ -55,17 +80,37 @@ pub fn process_content_box_request(node: ServoLayoutNode<'_>) -> Option if rects.is_empty() { return None; } - - Some(rects.iter().fold(Rect::zero(), |unioned_rect, rect| { + let rect_union = rects.iter().fold(Rect::zero(), |unioned_rect, rect| { rect.to_untyped().union(&unioned_rect) - })) + }); + + let Some(transform) = + root_transform_for_layout_node(&stacking_context_tree.compositor_info.scroll_tree, node) + else { + return Some(rect_union); + }; + + Some(transform_au_rectangle(rect_union, transform)) } -pub fn process_content_boxes_request(node: ServoLayoutNode<'_>) -> Vec> { - node.fragments_for_pseudo(None) +pub(crate) fn process_content_boxes_request( + stacking_context_tree: &StackingContextTree, + node: ServoLayoutNode<'_>, +) -> Vec> { + let fragments = node.fragments_for_pseudo(None); + let content_boxes = fragments .iter() .filter_map(Fragment::cumulative_border_box_rect) - .map(|rect| rect.to_untyped()) + .map(|rect| rect.to_untyped()); + + let Some(transform) = + root_transform_for_layout_node(&stacking_context_tree.compositor_info.scroll_tree, node) + else { + return content_boxes.collect(); + }; + + content_boxes + .map(|rect| transform_au_rectangle(rect, transform)) .collect() } @@ -1104,3 +1149,10 @@ where Some(computed_values.clone_font()) } + +fn transform_au_rectangle(rect_to_transform: Rect, transform: LayoutTransform) -> Rect { + transform + .outer_transformed_rect(&au_rect_to_f32_rect(rect_to_transform).cast_unit()) + .map(|transformed_rect| f32_rect_to_au_rect(transformed_rect.to_untyped())) + .unwrap_or(rect_to_transform) +} diff --git a/components/shared/base/id.rs b/components/shared/base/id.rs index e52e5d579ac..616fb5adf23 100644 --- a/components/shared/base/id.rs +++ b/components/shared/base/id.rs @@ -397,7 +397,7 @@ pub const TEST_WEBVIEW_ID: WebViewId = WebViewId(TEST_BROWSING_CONTEXT_ID); /// An id for a ScrollTreeNode in the ScrollTree. This contains both the index /// to the node in the tree's array of nodes as well as the corresponding SpatialId /// for the SpatialNode in the WebRender display list. -#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct ScrollTreeNodeId { /// The index of this scroll tree node in the tree's array of nodes. pub index: usize, diff --git a/components/shared/compositing/display_list.rs b/components/shared/compositing/display_list.rs index b85fc84956e..af55dbd2449 100644 --- a/components/shared/compositing/display_list.rs +++ b/components/shared/compositing/display_list.rs @@ -10,7 +10,7 @@ use base::id::ScrollTreeNodeId; use base::print_tree::PrintTree; use bitflags::bitflags; use embedder_traits::{Cursor, ViewportDetails}; -use euclid::SideOffsets2D; +use euclid::{SideOffsets2D, Transform3D}; use malloc_size_of_derive::MallocSizeOf; use serde::{Deserialize, Serialize}; use style::values::specified::Overflow; @@ -88,6 +88,8 @@ pub struct StickyNodeInfo { #[derive(Debug, Deserialize, Serialize)] pub struct ReferenceFrameNodeInfo { pub origin: LayoutPoint, + /// Origin of this frame relative to the document for bounding box queries. + pub frame_origin_for_query: LayoutPoint, pub transform_style: TransformStyle, pub transform: LayoutTransform, pub kind: ReferenceFrameKind, @@ -422,6 +424,53 @@ impl ScrollTree { _ => None, }) } + + /// Traverse a scroll node to its root to calculate the transform. + /// + /// TODO(stevennovaryo): Add caching mechanism for this. + pub fn cumulative_node_transform(&self, node_id: &ScrollTreeNodeId) -> LayoutTransform { + let current_node = self.get_node(node_id); + + let change_basis = + |transform: &Transform3D, x: f32, y: f32, z: f32| { + let pre_translation = Transform3D::translation(x, y, z); + let post_translation = Transform3D::translation(-x, -y, -z); + post_translation.then(transform).then(&pre_translation) + }; + + // FIXME(stevennovaryo): Ideally we should optimize the computation of simpler + // transformation like translate as it could be done + // in smaller amount of operation compared to a normal + // matrix multiplication. + let node_transform = match ¤t_node.info { + // To apply a transformation we need to make sure the rectangle's + // coordinate space is the same as reference frame's coordinate space. + // TODO(stevennovaryo): contrary to how Firefox are handling the coordinate space, + // we are ignoring zoom in transforming the coordinate + // space, and we might need to consider zoom here if it was + // implemented completely. + SpatialTreeNodeInfo::ReferenceFrame(info) => change_basis( + &info.transform, + info.frame_origin_for_query.x, + info.frame_origin_for_query.y, + 0.0, + ), + SpatialTreeNodeInfo::Scroll(info) => { + Transform3D::translation(-info.offset.x, -info.offset.y, 0.0) + }, + // TODO(stevennovaryo): Need to consider sticky frame accurately. + SpatialTreeNodeInfo::Sticky(_) => Default::default(), + }; + + match current_node.parent { + // If a node is not a root, accumulate the transforms. + Some(parent_id) => { + let ancestors_transform = self.cumulative_node_transform(&parent_id); + node_transform.then(&ancestors_transform) + }, + None => node_transform, + } + } } /// In order to pretty print the [ScrollTree] structure, we are converting @@ -539,6 +588,7 @@ impl CompositorDisplayListInfo { None, SpatialTreeNodeInfo::ReferenceFrame(ReferenceFrameNodeInfo { origin: Default::default(), + frame_origin_for_query: Default::default(), transform_style: TransformStyle::Flat, transform: LayoutTransform::identity(), kind: ReferenceFrameKind::default(), diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index abb70ae5e86..38d9c3169c5 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -626509,6 +626509,13 @@ {} ] ], + "getBoundingClientRect-scroll.html": [ + "4bcfe5e3de7bbc052732c8737345e5ca8acb6304", + [ + null, + {} + ] + ], "getBoundingClientRect-shy.html": [ "55349e93969af0d527da4bcb589804239164bafc", [ diff --git a/tests/wpt/meta/css/css-position/sticky/position-sticky-transforms-translate.html.ini b/tests/wpt/meta/css/css-position/sticky/position-sticky-transforms-translate.html.ini index c166df2af5f..b582ea88032 100644 --- a/tests/wpt/meta/css/css-position/sticky/position-sticky-transforms-translate.html.ini +++ b/tests/wpt/meta/css/css-position/sticky/position-sticky-transforms-translate.html.ini @@ -1,7 +1,4 @@ [position-sticky-transforms-translate.html] - [Translation transform can move sticky element past sticking point] - expected: FAIL - [Stuck elements can still be moved via translations] expected: FAIL diff --git a/tests/wpt/meta/css/css-transforms/3d-rendering-context-behavior.html.ini b/tests/wpt/meta/css/css-transforms/3d-rendering-context-behavior.html.ini index 8bc8338d202..449cefa8ec8 100644 --- a/tests/wpt/meta/css/css-transforms/3d-rendering-context-behavior.html.ini +++ b/tests/wpt/meta/css/css-transforms/3d-rendering-context-behavior.html.ini @@ -8,15 +8,6 @@ [Intermediate DOM nodes cause rendering context to end (fixed)] expected: FAIL - [Perspective applies to direct DOM normal-flow children] - expected: FAIL - - [Perspective applies to direct DOM abs-pos children] - expected: FAIL - - [Perspective applies to direct DOM fixed-pos children] - expected: FAIL - [Perspective does not apply to DOM normal-flow grandchildren] expected: FAIL diff --git a/tests/wpt/meta/css/css-transforms/transform-getBoundingClientRect-001.html.ini b/tests/wpt/meta/css/css-transforms/transform-getBoundingClientRect-001.html.ini deleted file mode 100644 index bc93b7b9a2b..00000000000 --- a/tests/wpt/meta/css/css-transforms/transform-getBoundingClientRect-001.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[transform-getBoundingClientRect-001.html] - [correct getBoundingClientRect() result within set of transforms] - expected: FAIL diff --git a/tests/wpt/meta/css/cssom-view/GetBoundingRect.html.ini b/tests/wpt/meta/css/cssom-view/GetBoundingRect.html.ini deleted file mode 100644 index d009f77ff63..00000000000 --- a/tests/wpt/meta/css/cssom-view/GetBoundingRect.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[GetBoundingRect.html] - [getBoundingClientRect] - expected: FAIL diff --git a/tests/wpt/meta/css/cssom-view/elementsFromPoint-iframes.html.ini b/tests/wpt/meta/css/cssom-view/elementsFromPoint-iframes.html.ini index 78f6aab8d85..3e7b0a9bc9c 100644 --- a/tests/wpt/meta/css/cssom-view/elementsFromPoint-iframes.html.ini +++ b/tests/wpt/meta/css/cssom-view/elementsFromPoint-iframes.html.ini @@ -1,6 +1,3 @@ [elementsFromPoint-iframes.html] - [elementsFromPoint on the root document for points in iframe elements] - expected: FAIL - [elementsFromPoint on inner documents] expected: FAIL diff --git a/tests/wpt/meta/css/cssom-view/elementsFromPoint-simple.html.ini b/tests/wpt/meta/css/cssom-view/elementsFromPoint-simple.html.ini deleted file mode 100644 index 5334b943293..00000000000 --- a/tests/wpt/meta/css/cssom-view/elementsFromPoint-simple.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[elementsFromPoint-simple.html] - [elementsFromPoint for each corner of a div with a 3d transform] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/bounding-box.html.ini b/tests/wpt/meta/intersection-observer/bounding-box.html.ini index 160e4f39981..711233bec08 100644 --- a/tests/wpt/meta/intersection-observer/bounding-box.html.ini +++ b/tests/wpt/meta/intersection-observer/bounding-box.html.ini @@ -1,12 +1,3 @@ [bounding-box.html] - [First rAF.] - expected: FAIL - - [target.style.transform = 'translateY(195px)'] - expected: FAIL - - [target.style.transform = 'translateY(300px)'] - expected: FAIL - [target.style.zoom = 2] expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/edge-inclusive-intersection.html.ini b/tests/wpt/meta/intersection-observer/edge-inclusive-intersection.html.ini deleted file mode 100644 index 8604521fec7..00000000000 --- a/tests/wpt/meta/intersection-observer/edge-inclusive-intersection.html.ini +++ /dev/null @@ -1,12 +0,0 @@ -[edge-inclusive-intersection.html] - [First rAF.] - expected: FAIL - - [Set transform=translateY(200px) on target.] - expected: FAIL - - [Set transform=translateY(201px) on target.] - expected: FAIL - - [Set transform=translateY(185px) on target.] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/isIntersecting-threshold.html.ini b/tests/wpt/meta/intersection-observer/isIntersecting-threshold.html.ini index 74bd96c9688..63dda4d7602 100644 --- a/tests/wpt/meta/intersection-observer/isIntersecting-threshold.html.ini +++ b/tests/wpt/meta/intersection-observer/isIntersecting-threshold.html.ini @@ -1,6 +1,3 @@ [isIntersecting-threshold.html] [Scrolled to half way through target element] expected: FAIL - - [Scrolled to target element completely off screen] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/multiple-targets.html.ini b/tests/wpt/meta/intersection-observer/multiple-targets.html.ini deleted file mode 100644 index bfead81117d..00000000000 --- a/tests/wpt/meta/intersection-observer/multiple-targets.html.ini +++ /dev/null @@ -1,9 +0,0 @@ -[multiple-targets.html] - [document.scrollingElement.scrollTop = 150] - expected: FAIL - - [document.scrollingElement.scrollTop = 10000] - expected: FAIL - - [document.scrollingElement.scrollTop = 0] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/multiple-thresholds.html.ini b/tests/wpt/meta/intersection-observer/multiple-thresholds.html.ini deleted file mode 100644 index 89a8f635fa1..00000000000 --- a/tests/wpt/meta/intersection-observer/multiple-thresholds.html.ini +++ /dev/null @@ -1,21 +0,0 @@ -[multiple-thresholds.html] - [document.scrollingElement.scrollTop = 120] - expected: FAIL - - [document.scrollingElement.scrollTop = 160] - expected: FAIL - - [document.scrollingElement.scrollTop = 200] - expected: FAIL - - [document.scrollingElement.scrollTop = 240] - expected: FAIL - - [document.scrollingElement.scrollTop = window.innerHeight + 140] - expected: FAIL - - [document.scrollingElement.scrollTop = window.innerHeight + 160] - expected: FAIL - - [document.scrollingElement.scrollTop = window.innerHeight + 200] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/observer-without-js-reference.html.ini b/tests/wpt/meta/intersection-observer/observer-without-js-reference.html.ini deleted file mode 100644 index 5edab7dcccc..00000000000 --- a/tests/wpt/meta/intersection-observer/observer-without-js-reference.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[observer-without-js-reference.html] - [document.scrollingElement.scrollTop = 300] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/remove-element.html.ini b/tests/wpt/meta/intersection-observer/remove-element.html.ini index 332f96fb092..75d0aa58251 100644 --- a/tests/wpt/meta/intersection-observer/remove-element.html.ini +++ b/tests/wpt/meta/intersection-observer/remove-element.html.ini @@ -5,8 +5,8 @@ [root.scrollTop = 150] expected: FAIL - [root.removeChild(target).] - expected: FAIL - [root.scrollTop = 150 after reinserting target.] expected: FAIL + + [root.insertBefore(target, trailingSpace).] + expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/root-margin-root-element.html.ini b/tests/wpt/meta/intersection-observer/root-margin-root-element.html.ini index 5c69cfd2345..b0a9c166e38 100644 --- a/tests/wpt/meta/intersection-observer/root-margin-root-element.html.ini +++ b/tests/wpt/meta/intersection-observer/root-margin-root-element.html.ini @@ -5,9 +5,6 @@ [root.scrollTop = 50, putting target into root margin] expected: FAIL - [document.scrollingElement.scrollTop = 0.] - expected: FAIL - [root.scrollTop = 0] expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/root-margin.html.ini b/tests/wpt/meta/intersection-observer/root-margin.html.ini deleted file mode 100644 index 788b5f1704b..00000000000 --- a/tests/wpt/meta/intersection-observer/root-margin.html.ini +++ /dev/null @@ -1,9 +0,0 @@ -[root-margin.html] - [document.scrollingElement.scrollLeft = 100] - expected: FAIL - - [document.scrollingElement.scrollTop = document.documentElement.clientHeight + 200] - expected: FAIL - - [document.scrollingElement.scrollTop = document.documentElement.clientHeight + 300] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/same-document-no-root.html.ini b/tests/wpt/meta/intersection-observer/same-document-no-root.html.ini deleted file mode 100644 index 06e8519b1e8..00000000000 --- a/tests/wpt/meta/intersection-observer/same-document-no-root.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[same-document-no-root.html] - [document.scrollingElement.scrollTop = 300] - expected: FAIL - - [document.scrollingElement.scrollTop = 100] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/same-document-root.html.ini b/tests/wpt/meta/intersection-observer/same-document-root.html.ini index 85bac42f7c5..f34112f4cd0 100644 --- a/tests/wpt/meta/intersection-observer/same-document-root.html.ini +++ b/tests/wpt/meta/intersection-observer/same-document-root.html.ini @@ -5,9 +5,6 @@ [root.scrollTop = 150 with root scrolled into view.] expected: FAIL - [document.scrollingElement.scrollTop = 0.] - expected: FAIL - [root.scrollTop = 0] expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/same-document-with-document-root.html.ini b/tests/wpt/meta/intersection-observer/same-document-with-document-root.html.ini deleted file mode 100644 index 2875cd435bf..00000000000 --- a/tests/wpt/meta/intersection-observer/same-document-with-document-root.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[same-document-with-document-root.html] - [document.scrollingElement.scrollTop = 300] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/same-document-zero-size-target.html.ini b/tests/wpt/meta/intersection-observer/same-document-zero-size-target.html.ini deleted file mode 100644 index 6a06e9f9894..00000000000 --- a/tests/wpt/meta/intersection-observer/same-document-zero-size-target.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[same-document-zero-size-target.html] - [document.scrollingElement.scrollTop = 300] - expected: FAIL - - [document.scrollingElement.scrollTop = 100] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/text-target.html.ini b/tests/wpt/meta/intersection-observer/text-target.html.ini deleted file mode 100644 index f9386c6734a..00000000000 --- a/tests/wpt/meta/intersection-observer/text-target.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[text-target.html] - [document.scrollingElement.scrollTop = 300] - expected: FAIL - - [document.scrollingElement.scrollTop = 100] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/unclipped-root.html.ini b/tests/wpt/meta/intersection-observer/unclipped-root.html.ini deleted file mode 100644 index 42277a94da4..00000000000 --- a/tests/wpt/meta/intersection-observer/unclipped-root.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[unclipped-root.html] - [First rAF.] - expected: FAIL - - [target.style.transform = 'translateY(195px)'] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/visibility-hidden.html.ini b/tests/wpt/meta/intersection-observer/visibility-hidden.html.ini deleted file mode 100644 index 63cf719796e..00000000000 --- a/tests/wpt/meta/intersection-observer/visibility-hidden.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[visibility-hidden.html] - [document.scrollingElement.scrollTop = 300] - expected: FAIL diff --git a/tests/wpt/tests/css/cssom-view/getBoundingClientRect-scroll.html b/tests/wpt/tests/css/cssom-view/getBoundingClientRect-scroll.html new file mode 100644 index 00000000000..4bcfe5e3de7 --- /dev/null +++ b/tests/wpt/tests/css/cssom-view/getBoundingClientRect-scroll.html @@ -0,0 +1,130 @@ + +getBoundingClientRect for a element inside scroll container + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + \ No newline at end of file