diff --git a/components/script/dom/intersectionobserver.rs b/components/script/dom/intersectionobserver.rs index 172e83d58d7..ab56c061fa3 100644 --- a/components/script/dom/intersectionobserver.rs +++ b/components/script/dom/intersectionobserver.rs @@ -10,11 +10,12 @@ use app_units::Au; use base::cross_process_instant::CrossProcessInstant; use cssparser::{Parser, ParserInput}; use dom_struct::dom_struct; -use euclid::default::{Rect, Size2D}; +use euclid::default::{Rect, SideOffsets2D, Size2D}; use js::rust::{HandleObject, MutableHandleValue}; use style::context::QuirksMode; use style::parser::{Parse, ParserContext}; use style::stylesheets::{CssRuleType, Origin}; +use style::values::specified::intersection_observer::IntersectionObserverMargin; use style_traits::{ParsingMode, ToCss}; use url::Url; @@ -36,7 +37,6 @@ use crate::dom::document::Document; use crate::dom::domrectreadonly::DOMRectReadOnly; use crate::dom::element::Element; use crate::dom::intersectionobserverentry::IntersectionObserverEntry; -use crate::dom::intersectionobserverrootmargin::IntersectionObserverRootMargin; use crate::dom::node::{Node, NodeTraits}; use crate::dom::window::Window; use crate::script_runtime::{CanGc, JSContext}; @@ -82,12 +82,12 @@ pub(crate) struct IntersectionObserver { /// #[no_trace] #[ignore_malloc_size_of = "Defined in style"] - root_margin: RefCell, + root_margin: RefCell, /// #[no_trace] #[ignore_malloc_size_of = "Defined in style"] - scroll_margin: RefCell, + scroll_margin: RefCell, /// thresholds: RefCell>>, @@ -104,8 +104,8 @@ impl IntersectionObserver { window: &Window, callback: Rc, root: IntersectionRoot, - root_margin: IntersectionObserverRootMargin, - scroll_margin: IntersectionObserverRootMargin, + root_margin: IntersectionObserverMargin, + scroll_margin: IntersectionObserverMargin, ) -> Self { Self { reflector_: Reflector::new(), @@ -462,10 +462,7 @@ impl IntersectionObserver { // > the width of the undilated rectangle. // TODO(stevennovaryo): add check for same-origin-domain intersection_rectangle.map(|intersection_rectangle| { - let margin = self - .root_margin - .borrow() - .resolve_percentages_with_basis(intersection_rectangle); + let margin = self.resolve_percentages_with_basis(intersection_rectangle); intersection_rectangle.outer_rect(margin) }) } @@ -661,6 +658,16 @@ impl IntersectionObserver { .set(intersection_output.is_visible); } } + + fn resolve_percentages_with_basis(&self, containing_block: Rect) -> SideOffsets2D { + let inner = &self.root_margin.borrow().0; + SideOffsets2D::new( + inner.0.to_used_value(containing_block.height()), + inner.1.to_used_value(containing_block.width()), + inner.2.to_used_value(containing_block.height()), + inner.3.to_used_value(containing_block.width()), + ) + } } impl IntersectionObserverMethods for IntersectionObserver { @@ -799,7 +806,7 @@ impl IntersectionObserverRegistration { } /// -fn parse_a_margin(value: Option<&DOMString>) -> Result { +fn parse_a_margin(value: Option<&DOMString>) -> Result { // && // // > ... defaulting to "0px". @@ -808,7 +815,7 @@ fn parse_a_margin(value: Option<&DOMString>) -> Result "0px", }; - // Create necessary style ParserContext and utilize stylo's IntersectionObserverRootMargin + // Create necessary style ParserContext and utilize stylo's IntersectionObserverMargin let mut input = ParserInput::new(value); let mut parser = Parser::new(&mut input); @@ -825,7 +832,7 @@ fn parse_a_margin(value: Option<&DOMString>) -> Result( - _context: &ParserContext, - input: &mut Parser<'i, '_>, -) -> Result> { - let location = input.current_source_location(); - let token = input.next()?; - let value = match *token { - Token::Dimension { - value, ref unit, .. - } => { - match_ignore_ascii_case! { unit, - "px" => Ok(LengthPercentage::new_length(Length::new(value))), - _ => Err(()), - } - }, - Token::Percentage { unit_value, .. } => Ok(LengthPercentage::new_percent( - computed::Percentage(unit_value), - )), - _ => Err(()), - }; - value.map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError)) -} - -/// The value of an IntersectionObserver's rootMargin property. -/// -/// Only bare px or percentage values are allowed. Other length units and -/// calc() values are not allowed. -/// -/// -#[repr(transparent)] -pub struct IntersectionObserverRootMargin(pub StyleRect); - -impl Parse for IntersectionObserverRootMargin { - fn parse<'i>( - context: &ParserContext, - input: &mut Parser<'i, '_>, - ) -> Result> { - use style::Zero; - if input.is_exhausted() { - // If there are zero elements in tokens, set tokens to ["0px"]. - return Ok(IntersectionObserverRootMargin(StyleRect::all( - LengthPercentage::zero(), - ))); - } - let rect = StyleRect::parse_with(context, input, parse_pixel_or_percent)?; - Ok(IntersectionObserverRootMargin(rect)) - } -} - -// Strictly speaking this is not ToCss. It's serializing for DOM. But -// we can just reuse the infrastructure of this. -// -// -impl ToCss for IntersectionObserverRootMargin { - fn to_css(&self, dest: &mut CssWriter) -> fmt::Result - where - W: fmt::Write, - { - // We cannot use the ToCss impl of Rect, because that would - // merge items when they are equal. We want to list them all. - let mut writer = SequenceWriter::new(dest, " "); - let rect = &self.0; - writer.item(&rect.0)?; - writer.item(&rect.1)?; - writer.item(&rect.2)?; - writer.item(&rect.3) - } -} - -// TODO(stevennovaryo): move this to the wrapper later -impl IntersectionObserverRootMargin { - // Resolve to used values. - pub(crate) fn resolve_percentages_with_basis( - &self, - containing_block: Rect, - ) -> SideOffsets2D { - let inner = &self.0; - SideOffsets2D::new( - inner.0.to_used_value(containing_block.height()), - inner.1.to_used_value(containing_block.width()), - inner.2.to_used_value(containing_block.height()), - inner.3.to_used_value(containing_block.width()), - ) - } -} diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index ec9c1733b29..0267a820120 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -438,7 +438,6 @@ pub(crate) mod imagedata; pub(crate) mod inputevent; pub(crate) mod intersectionobserver; pub(crate) mod intersectionobserverentry; -pub(crate) mod intersectionobserverrootmargin; pub(crate) mod keyboardevent; pub(crate) mod location; pub(crate) mod mediadeviceinfo;