From becd09758531acbf029f5cc2cbffba8f4c2985ef Mon Sep 17 00:00:00 2001 From: Steven Novaryo <65610990+stevennovaryo@users.noreply.github.com> Date: Thu, 13 Feb 2025 15:47:29 +0800 Subject: [PATCH] dom: IntersectionObserver initialization (#35314) * Add internal slot definition Signed-off-by: stevennovaryo * Add initialization for new IntersectionObserver Signed-off-by: stevennovaryo * Move observer initialization Signed-off-by: stevennovaryo * Update WPT tests Signed-off-by: stevennovaryo * Make a copy of style IntersectionObserverRootMargin Signed-off-by: stevennovaryo * Move initialization to account for rooted expression Signed-off-by: stevennovaryo * Fix some fields typing Signed-off-by: stevennovaryo * Impl rest of IntersectionObserver interface Signed-off-by: stevennovaryo * Fix tidy issue Signed-off-by: stevennovaryo * Apply types logic and tidy fix from suggestions Signed-off-by: stevennovaryo * Add allow unrooted for add registration to element Signed-off-by: stevennovaryo --------- Signed-off-by: stevennovaryo --- components/script/dom/document.rs | 3 + components/script/dom/element.rs | 45 +++ components/script/dom/intersectionobserver.rs | 313 +++++++++++++++++- .../dom/intersectionobserverrootmargin.rs | 84 +++++ components/script/dom/mod.rs | 1 + components/script/dom/raredata.rs | 6 + .../script_bindings/codegen/Bindings.conf | 4 + .../webidls/IntersectionObserver.webidl | 2 +- .../idlharness.window.js.ini | 3 - .../observer-attributes.html.ini | 21 -- .../observer-exceptions.html.ini | 21 -- 11 files changed, 439 insertions(+), 64 deletions(-) create mode 100644 components/script/dom/intersectionobserverrootmargin.rs delete mode 100644 tests/wpt/meta/intersection-observer/idlharness.window.js.ini delete mode 100644 tests/wpt/meta/intersection-observer/observer-attributes.html.ini delete mode 100644 tests/wpt/meta/intersection-observer/observer-exceptions.html.ini diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index ff691ec52dc..be6ee41e599 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -515,6 +515,8 @@ pub(crate) struct Document { /// #[no_trace] inherited_insecure_requests_policy: Cell>, + /// + intersection_observer_task_queued: Cell, } #[allow(non_snake_case)] @@ -3744,6 +3746,7 @@ impl Document { status_code, is_initial_about_blank: Cell::new(is_initial_about_blank), inherited_insecure_requests_policy: Cell::new(inherited_insecure_requests_policy), + intersection_observer_task_queued: Cell::new(false), } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 66e977bf2b5..9783b65b9ce 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -64,6 +64,7 @@ use xml5ever::serialize::TraversalScope::{ use super::customelementregistry::is_valid_custom_element_name; use super::htmltablecolelement::{HTMLTableColElement, HTMLTableColElementLayoutHelpers}; +use super::intersectionobserver::{IntersectionObserver, IntersectionObserverRegistration}; use crate::dom::activation::Activatable; use crate::dom::attr::{Attr, AttrHelpersForLayout}; use crate::dom::bindings::cell::{ref_filter_map, DomRefCell, Ref, RefMut}; @@ -613,6 +614,50 @@ impl Element { Some(node) => node.is::(), } } + + /// Return all IntersectionObserverRegistration for this element. + /// Lazily initialize the raredata if it does not exist. + pub(crate) fn registered_intersection_observers_mut( + &self, + ) -> RefMut> { + RefMut::map(self.ensure_rare_data(), |rare_data| { + &mut rare_data.registered_intersection_observers + }) + } + + pub(crate) fn registered_intersection_observers( + &self, + ) -> Option>> { + let rare_data: Ref<_> = self.rare_data.borrow(); + + if rare_data.is_none() { + return None; + } + Some(Ref::map(rare_data, |rare_data| { + &rare_data + .as_ref() + .unwrap() + .registered_intersection_observers + })) + } + + /// Add a new IntersectionObserverRegistration to the element. + #[cfg_attr(crown, allow(crown::unrooted_must_root))] + pub(crate) fn add_intersection_observer_registration( + &self, + registration: IntersectionObserverRegistration, + ) { + self.ensure_rare_data() + .registered_intersection_observers + .push(registration); + } + + /// Removes a certain IntersectionObserver. + pub(crate) fn remove_intersection_observer(&self, observer: &IntersectionObserver) { + self.ensure_rare_data() + .registered_intersection_observers + .retain(|reg_obs| *reg_obs.observer != *observer) + } } /// diff --git a/components/script/dom/intersectionobserver.rs b/components/script/dom/intersectionobserver.rs index 9077c4e1a87..73a9b2bed27 100644 --- a/components/script/dom/intersectionobserver.rs +++ b/components/script/dom/intersectionobserver.rs @@ -2,23 +2,44 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use std::cell::{Cell, RefCell}; use std::rc::Rc; +use base::cross_process_instant::CrossProcessInstant; +use cssparser::{Parser, ParserInput}; use dom_struct::dom_struct; use js::rust::{HandleObject, MutableHandleValue}; +use style::context::QuirksMode; +use style::parser::{Parse, ParserContext}; +use style::stylesheets::{CssRuleType, Origin}; +use style_traits::{ParsingMode, ToCss}; +use url::Url; use super::bindings::codegen::Bindings::IntersectionObserverBinding::{ IntersectionObserverCallback, IntersectionObserverMethods, }; -use super::bindings::codegen::UnionTypes::ElementOrDocument; -use super::types::{Element, IntersectionObserverEntry}; +use super::intersectionobserverentry::IntersectionObserverEntry; +use super::intersectionobserverrootmargin::IntersectionObserverRootMargin; +use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::IntersectionObserverBinding::IntersectionObserverInit; +use crate::dom::bindings::codegen::UnionTypes::{DoubleOrDoubleSequence, ElementOrDocument}; +use crate::dom::bindings::error::Error; +use crate::dom::bindings::import::module::Fallible; +use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, Reflector}; -use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::DOMString; +use crate::dom::bindings::utils::to_frozen_array; +use crate::dom::element::Element; use crate::dom::window::Window; use crate::script_runtime::{CanGc, JSContext}; +/// > The intersection root for an IntersectionObserver is the value of its root attribute if the attribute is non-null; +/// > otherwise, it is the top-level browsing context’s document node, referred to as the implicit root. +/// +/// +pub type IntersectionRoot = Option; + /// The Intersection Observer interface /// /// > The IntersectionObserver interface can be used to observe changes in the intersection @@ -29,33 +50,226 @@ use crate::script_runtime::{CanGc, JSContext}; pub(crate) struct IntersectionObserver { reflector_: Reflector, + /// > The root provided to the IntersectionObserver constructor, or null if none was provided. + /// + root: IntersectionRoot, + /// > This callback will be invoked when there are changes to a target’s intersection /// > with the intersection root, as per the processing model. /// #[ignore_malloc_size_of = "Rc are hard"] callback: Rc, + + /// + queued_entries: DomRefCell>>, + + /// + observation_targets: DomRefCell>>, + + /// + #[no_trace] + #[ignore_malloc_size_of = "Defined in style"] + root_margin: RefCell, + + /// + #[no_trace] + #[ignore_malloc_size_of = "Defined in style"] + scroll_margin: RefCell, + + /// + thresholds: RefCell>>, + + /// + delay: Cell, + + /// + track_visibility: Cell, } impl IntersectionObserver { pub(crate) fn new_inherited( callback: Rc, - _init: &IntersectionObserverInit, + root: IntersectionRoot, + root_margin: IntersectionObserverRootMargin, + scroll_margin: IntersectionObserverRootMargin, ) -> Self { Self { reflector_: Reflector::new(), + root, callback, + queued_entries: Default::default(), + observation_targets: Default::default(), + root_margin: RefCell::new(root_margin), + scroll_margin: RefCell::new(scroll_margin), + thresholds: Default::default(), + delay: Default::default(), + track_visibility: Default::default(), } } + /// fn new( window: &Window, proto: Option, callback: Rc, init: &IntersectionObserverInit, can_gc: CanGc, - ) -> DomRoot { - let observer = Box::new(Self::new_inherited(callback, init)); - reflect_dom_object_with_proto(observer, window, proto, can_gc) + ) -> Fallible> { + // Step 3. + // > Attempt to parse a margin from options.rootMargin. If a list is returned, + // > set this’s internal [[rootMargin]] slot to that. Otherwise, throw a SyntaxError exception. + let root_margin = if let Ok(margin) = parse_a_margin(init.rootMargin.as_ref()) { + margin + } else { + return Err(Error::Syntax); + }; + + // Step 4. + // > Attempt to parse a margin from options.scrollMargin. If a list is returned, + // > set this’s internal [[scrollMargin]] slot to that. Otherwise, throw a SyntaxError exception. + let scroll_margin = if let Ok(margin) = parse_a_margin(init.scrollMargin.as_ref()) { + margin + } else { + return Err(Error::Syntax); + }; + + // Step 1 and step 2, 3, 4 setter + // > 1. Let this be a new IntersectionObserver object + // > 2. Set this’s internal [[callback]] slot to callback. + // > 3. ... set this’s internal [[rootMargin]] slot to that. + // > 4. ,.. set this’s internal [[scrollMargin]] slot to that. + // + // Owned root is also passed to the constructor. + let observer = reflect_dom_object_with_proto( + Box::new(Self::new_inherited( + callback, + init.root.clone(), + root_margin, + scroll_margin, + )), + window, + proto, + can_gc, + ); + + // Step 5-13 + observer.init_observer(init)?; + + Ok(observer) + } + + /// Step 5-13 of + fn init_observer(&self, init: &IntersectionObserverInit) -> Fallible<()> { + // Step 5 + // > Let thresholds be a list equal to options.threshold. + // + // Non-sequence value should be converted into Vec. + // Default value of thresholds is [0]. + let mut thresholds = match &init.threshold { + Some(DoubleOrDoubleSequence::Double(num)) => vec![*num], + Some(DoubleOrDoubleSequence::DoubleSequence(sequence)) => sequence.clone(), + None => vec![Finite::wrap(0.)], + }; + + // Step 6 + // > If any value in thresholds is less than 0.0 or greater than 1.0, throw a RangeError exception. + for num in &thresholds { + if **num < 0.0 || **num > 1.0 { + return Err(Error::Range( + "Value in thresholds should not be less than 0.0 or greater than 1.0" + .to_owned(), + )); + } + } + + // Step 7 + // > Sort thresholds in ascending order. + thresholds.sort_by(|lhs, rhs| lhs.partial_cmp(&**rhs).unwrap()); + + // Step 8 + // > If thresholds is empty, append 0 to thresholds. + if thresholds.is_empty() { + thresholds.push(Finite::wrap(0.)); + } + + // Step 9 + // > The thresholds attribute getter will return this sorted thresholds list. + // + // Set this’s internal [[thresholds]] slot to the sorted thresholds list + // and getter will return the internal [[thresholds]] slot. + self.thresholds.replace(thresholds); + + // Step 10 + // > Let delay be the value of options.delay. + // + // Default value of delay is 0. + let mut delay = init.delay.unwrap_or(0); + + // Step 11 + // > If options.trackVisibility is true and delay is less than 100, set delay to 100. + if init.trackVisibility { + delay = delay.max(100); + } + + // Step 12 + // > Set this’s internal [[delay]] slot to options.delay to delay. + self.delay.set(delay); + + // Step 13 + // > Set this’s internal [[trackVisibility]] slot to options.trackVisibility. + self.track_visibility.set(init.trackVisibility); + + Ok(()) + } + + /// + fn observe_target_element(&self, target: &Element) { + // Step 1 + // > If target is in observer’s internal [[ObservationTargets]] slot, return. + let is_present = self + .observation_targets + .borrow() + .iter() + .any(|element| &**element == target); + if is_present { + return; + } + + // Step 2 + // > Let intersectionObserverRegistration be an IntersectionObserverRegistration record with + // > an observer property set to observer, a previousThresholdIndex property set to -1, + // > a previousIsIntersecting property set to false, and a previousIsVisible property set to false. + // Step 3 + // > Append intersectionObserverRegistration to target’s internal [[RegisteredIntersectionObservers]] slot. + target.add_intersection_observer_registration(IntersectionObserverRegistration { + observer: Dom::from_ref(self), + previous_threshold_index: Cell::new(-1), + previous_is_intersecting: Cell::new(false), + last_update_time: Cell::new(CrossProcessInstant::epoch()), + previous_is_visible: Cell::new(false), + }); + + // Step 4 + // > Add target to observer’s internal [[ObservationTargets]] slot. + self.observation_targets + .borrow_mut() + .push(Dom::from_ref(target)); + } + + /// + fn unobserve_target_element(&self, target: &Element) { + // Step 1 + // > Remove the IntersectionObserverRegistration record whose observer property is equal to + // > this from target’s internal [[RegisteredIntersectionObservers]] slot, if present. + target + .registered_intersection_observers_mut() + .retain(|registration| &*registration.observer != self); + + // Step 2 + // > Remove target from this’s internal [[ObservationTargets]] slot, if present + self.observation_targets + .borrow_mut() + .retain(|element| &**element != target); } } @@ -64,7 +278,7 @@ impl IntersectionObserverMethods for IntersectionObserver /// /// fn GetRoot(&self) -> Option { - None + self.root.clone() } /// > Offsets applied to the root intersection rectangle, effectively growing or @@ -74,7 +288,7 @@ impl IntersectionObserverMethods for IntersectionObserver /// /// fn RootMargin(&self) -> DOMString { - DOMString::new() + DOMString::from_string(self.root_margin.borrow().to_css_string()) } /// > Offsets are applied to scrollports on the path from intersection root to target, @@ -82,7 +296,7 @@ impl IntersectionObserverMethods for IntersectionObserver /// /// fn ScrollMargin(&self) -> DOMString { - DOMString::new() + DOMString::from_string(self.scroll_margin.borrow().to_css_string()) } /// > A list of thresholds, sorted in increasing numeric order, where each threshold @@ -92,39 +306,59 @@ impl IntersectionObserverMethods for IntersectionObserver /// > constructor, or the sequence is empty, the value of this attribute will be `[0]`. /// /// - fn Thresholds(&self, _context: JSContext, _retval: MutableHandleValue) {} + fn Thresholds(&self, context: JSContext, retval: MutableHandleValue) { + to_frozen_array(&self.thresholds.borrow(), context, retval); + } /// > A number indicating the minimum delay in milliseconds between notifications from /// > this observer for a given target. /// /// fn Delay(&self) -> i32 { - 0 + self.delay.get() } /// > A boolean indicating whether this IntersectionObserver will track changes in a target’s visibility. /// /// fn TrackVisibility(&self) -> bool { - false + self.track_visibility.get() } /// > Run the observe a target Element algorithm, providing this and target. /// /// - fn Observe(&self, _target: &Element) {} + fn Observe(&self, target: &Element) { + self.observe_target_element(target); + } /// > Run the unobserve a target Element algorithm, providing this and target. /// /// - fn Unobserve(&self, _target: &Element) {} + fn Unobserve(&self, target: &Element) { + self.unobserve_target_element(target); + } /// - fn Disconnect(&self) {} + fn Disconnect(&self) { + // > For each target in this’s internal [[ObservationTargets]] slot: + self.observation_targets.borrow().iter().for_each(|target| { + // > 1. Remove the IntersectionObserverRegistration record whose observer property is equal to + // > this from target’s internal [[RegisteredIntersectionObservers]] slot. + target.remove_intersection_observer(self); + }); + // > 2. Remove target from this’s internal [[ObservationTargets]] slot. + self.observation_targets.borrow_mut().clear(); + } /// fn TakeRecords(&self) -> Vec> { - vec![] + // Step 1-3. + self.queued_entries + .take() + .iter() + .map(|entry| entry.as_rooted()) + .collect() } /// @@ -134,7 +368,50 @@ impl IntersectionObserverMethods for IntersectionObserver can_gc: CanGc, callback: Rc, init: &IntersectionObserverInit, - ) -> DomRoot { + ) -> Fallible> { Self::new(window, proto, callback, init, can_gc) } } + +/// +#[derive(JSTraceable, MallocSizeOf)] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +pub(crate) struct IntersectionObserverRegistration { + pub(crate) observer: Dom, + previous_threshold_index: Cell, + previous_is_intersecting: Cell, + #[no_trace] + last_update_time: Cell, + previous_is_visible: Cell, +} + +/// +fn parse_a_margin(value: Option<&DOMString>) -> Result { + // && + // + // > ... defaulting to "0px". + let value = match value { + Some(str) => str.str(), + _ => "0px", + }; + + // Create necessary style ParserContext and utilize stylo's IntersectionObserverRootMargin + let mut input = ParserInput::new(value); + let mut parser = Parser::new(&mut input); + + let url = Url::parse("about:blank").unwrap().into(); + let context = ParserContext::new( + Origin::Author, + &url, + Some(CssRuleType::Style), + ParsingMode::DEFAULT, + QuirksMode::NoQuirks, + /* namespaces = */ Default::default(), + None, + None, + ); + + parser + .parse_entirely(|p| IntersectionObserverRootMargin::parse(&context, p)) + .map_err(|_| ()) +} diff --git a/components/script/dom/intersectionobserverrootmargin.rs b/components/script/dom/intersectionobserverrootmargin.rs new file mode 100644 index 00000000000..edde6c0e363 --- /dev/null +++ b/components/script/dom/intersectionobserverrootmargin.rs @@ -0,0 +1,84 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! Copy of Stylo Gecko's [`style::values::specified::gecko::IntersectionObserverRootMargin`] implementation. +//! TODO: expose the object to servo as well in Stylo + +use std::fmt; + +use cssparser::{match_ignore_ascii_case, Parser, Token}; +use style::parser::{Parse, ParserContext}; +use style::values::computed::{self, Length, LengthPercentage}; +use style::values::generics::rect::Rect; +use style_traits::values::SequenceWriter; +use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; + +fn parse_pixel_or_percent<'i>( + _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 Rect); + +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(Rect::all( + LengthPercentage::zero(), + ))); + } + let rect = Rect::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) + } +} diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 69e5ceb2b77..ec5f9a8c9a6 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -422,6 +422,7 @@ 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; diff --git a/components/script/dom/raredata.rs b/components/script/dom/raredata.rs index ac830a8e362..9e866bf5f43 100644 --- a/components/script/dom/raredata.rs +++ b/components/script/dom/raredata.rs @@ -13,6 +13,7 @@ use crate::dom::customelementregistry::{ }; use crate::dom::elementinternals::ElementInternals; use crate::dom::htmlslotelement::SlottableData; +use crate::dom::intersectionobserver::IntersectionObserverRegistration; use crate::dom::mutationobserver::RegisteredObserver; use crate::dom::node::UniqueId; use crate::dom::shadowroot::ShadowRoot; @@ -58,4 +59,9 @@ pub(crate) struct ElementRareData { pub(crate) client_rect: Option>>, /// pub(crate) element_internals: Option>, + + /// + /// > Element objects have an internal [[RegisteredIntersectionObservers]] slot, + /// > which is initialized to an empty list. This list holds IntersectionObserverRegistration records, which have: + pub(crate) registered_intersection_observers: Vec, } diff --git a/components/script_bindings/codegen/Bindings.conf b/components/script_bindings/codegen/Bindings.conf index 492a20e1e1f..df27a32a06c 100644 --- a/components/script_bindings/codegen/Bindings.conf +++ b/components/script_bindings/codegen/Bindings.conf @@ -608,6 +608,10 @@ Unions = { 'derives': ['Clone'] }, +'ElementOrDocument': { + 'derives': ['Clone', 'MallocSizeOf'] +}, + 'HTMLCanvasElementOrOffscreenCanvas': { 'derives': ['Clone', 'MallocSizeOf'] }, diff --git a/components/script_bindings/webidls/IntersectionObserver.webidl b/components/script_bindings/webidls/IntersectionObserver.webidl index 9607864408e..a5becc147fa 100644 --- a/components/script_bindings/webidls/IntersectionObserver.webidl +++ b/components/script_bindings/webidls/IntersectionObserver.webidl @@ -18,7 +18,7 @@ dictionary IntersectionObserverInit { [Pref="dom_intersection_observer_enabled", Exposed=(Window)] interface IntersectionObserver { - constructor(IntersectionObserverCallback callback, optional IntersectionObserverInit options = {}); + [Throws] constructor(IntersectionObserverCallback callback, optional IntersectionObserverInit options = {}); readonly attribute (Element or Document)? root; readonly attribute DOMString rootMargin; readonly attribute DOMString scrollMargin; diff --git a/tests/wpt/meta/intersection-observer/idlharness.window.js.ini b/tests/wpt/meta/intersection-observer/idlharness.window.js.ini deleted file mode 100644 index ea20d78b758..00000000000 --- a/tests/wpt/meta/intersection-observer/idlharness.window.js.ini +++ /dev/null @@ -1,3 +0,0 @@ -[idlharness.window.html] - [IntersectionObserver interface: observer must inherit property "thresholds" with the proper type] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/observer-attributes.html.ini b/tests/wpt/meta/intersection-observer/observer-attributes.html.ini deleted file mode 100644 index bc8e7d27082..00000000000 --- a/tests/wpt/meta/intersection-observer/observer-attributes.html.ini +++ /dev/null @@ -1,21 +0,0 @@ -[observer-attributes.html] - [observer.thresholds] - expected: FAIL - - [observer.rootMargin] - expected: FAIL - - [empty observer.thresholds] - expected: FAIL - - [whitespace observer.rootMargin] - expected: FAIL - - [set observer.root] - expected: FAIL - - [set observer.thresholds] - expected: FAIL - - [set observer.rootMargin] - expected: FAIL diff --git a/tests/wpt/meta/intersection-observer/observer-exceptions.html.ini b/tests/wpt/meta/intersection-observer/observer-exceptions.html.ini deleted file mode 100644 index 6fb4a44467f..00000000000 --- a/tests/wpt/meta/intersection-observer/observer-exceptions.html.ini +++ /dev/null @@ -1,21 +0,0 @@ -[observer-exceptions.html] - [IntersectionObserver constructor with { threshold: [1.1\] }] - expected: FAIL - - [IntersectionObserver constructor with { rootMargin: "1" }] - expected: FAIL - - [IntersectionObserver constructor with { rootMargin: "2em" }] - expected: FAIL - - [IntersectionObserver constructor with { rootMargin: "auto" }] - expected: FAIL - - [IntersectionObserver constructor with { rootMargin: "calc(1px + 2px)" }] - expected: FAIL - - [IntersectionObserver constructor with { rootMargin: "1px !important" }] - expected: FAIL - - [IntersectionObserver constructor with { rootMargin: "1px 1px 1px 1px 1px" }] - expected: FAIL