diff options
author | cathiechen <cathiechen@igalia.com> | 2024-03-22 16:02:01 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-22 15:02:01 +0000 |
commit | cb275e086c215b6da741c7918cd9683a134eb24f (patch) | |
tree | 173f32008068d06f27b3d1a8af1a855dfa6174da /components/script/dom/abstractrange.rs | |
parent | bae77671f85481503ab563c20ed488cf883436fa (diff) | |
download | servo-cb275e086c215b6da741c7918cd9683a134eb24f.tar.gz servo-cb275e086c215b6da741c7918cd9683a134eb24f.zip |
Implement StaticRange (#31809)
* Add DOM interface for AbstractRange
* Add DOM interface for StaticRange
* Update WPT tests for StaticRange-constructor.html
* Fix formatting
* Add AbstractRange & StaticRange in interfaces.html
* rebased the code and fixed the failures
Signed-off-by: Cathie Chen <cathiechen@igalia.com>
* update the expected result in idlharness.window.js.ini file
* Addressed the code review comments
* updae the test result of legacy layout
---------
Signed-off-by: Cathie Chen <cathiechen@igalia.com>
Co-authored-by: Nipun Garg <nipung271@gmail.com>
Diffstat (limited to 'components/script/dom/abstractrange.rs')
-rw-r--r-- | components/script/dom/abstractrange.rs | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/components/script/dom/abstractrange.rs b/components/script/dom/abstractrange.rs new file mode 100644 index 00000000000..a39b67b1807 --- /dev/null +++ b/components/script/dom/abstractrange.rs @@ -0,0 +1,177 @@ +/* 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/. */ + +use std::cell::Cell; +use std::cmp::{Ord, Ordering, PartialEq, PartialOrd}; + +use deny_public_fields::DenyPublicFields; +use dom_struct::dom_struct; + +use crate::dom::bindings::codegen::Bindings::AbstractRangeBinding::AbstractRangeMethods; +use crate::dom::bindings::codegen::Bindings::NodeBinding::{NodeConstants, NodeMethods}; +use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::root::{DomRoot, MutDom}; +use crate::dom::document::Document; +use crate::dom::node::{Node, ShadowIncluding}; + +#[dom_struct] +pub struct AbstractRange { + reflector_: Reflector, + start: BoundaryPoint, + end: BoundaryPoint, +} + +impl AbstractRange { + pub fn new_inherited( + start_container: &Node, + start_offset: u32, + end_container: &Node, + end_offset: u32, + ) -> AbstractRange { + AbstractRange { + reflector_: Reflector::new(), + start: BoundaryPoint::new(start_container, start_offset), + end: BoundaryPoint::new(end_container, end_offset), + } + } + + pub fn new( + document: &Document, + start_container: &Node, + start_offset: u32, + end_container: &Node, + end_offset: u32, + ) -> DomRoot<AbstractRange> { + let abstractrange = reflect_dom_object( + Box::new(AbstractRange::new_inherited( + start_container, + start_offset, + end_container, + end_offset, + )), + document.window(), + ); + abstractrange + } + + pub fn start(&self) -> &BoundaryPoint { + &self.start + } + + pub fn end(&self) -> &BoundaryPoint { + &self.end + } +} + +impl AbstractRangeMethods for AbstractRange { + /// <https://dom.spec.whatwg.org/#dom-range-startcontainer> + fn StartContainer(&self) -> DomRoot<Node> { + self.start.node.get() + } + + /// <https://dom.spec.whatwg.org/#dom-range-startoffset> + fn StartOffset(&self) -> u32 { + self.start.offset.get() + } + + /// <https://dom.spec.whatwg.org/#dom-range-endcontainer> + fn EndContainer(&self) -> DomRoot<Node> { + self.end.node.get() + } + + /// <https://dom.spec.whatwg.org/#dom-range-endoffset> + fn EndOffset(&self) -> u32 { + self.end.offset.get() + } + + /// <https://dom.spec.whatwg.org/#dom-range-collapsed> + fn Collapsed(&self) -> bool { + self.start == self.end + } +} + +#[derive(DenyPublicFields, JSTraceable, MallocSizeOf)] +#[crown::unrooted_must_root_lint::must_root] +pub struct BoundaryPoint { + node: MutDom<Node>, + offset: Cell<u32>, +} + +impl BoundaryPoint { + fn new(node: &Node, offset: u32) -> BoundaryPoint { + debug_assert!(!node.is_doctype()); + BoundaryPoint { + node: MutDom::new(node), + offset: Cell::new(offset), + } + } + + pub fn set(&self, node: &Node, offset: u32) { + self.node.set(node); + self.set_offset(offset); + } + + pub fn set_offset(&self, offset: u32) { + self.offset.set(offset); + } + + pub fn node(&self) -> &MutDom<Node> { + &self.node + } +} + +#[allow(crown::unrooted_must_root)] +impl PartialOrd for BoundaryPoint { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + bp_position( + &self.node.get(), + self.offset.get(), + &other.node.get(), + other.offset.get(), + ) + } +} + +#[allow(crown::unrooted_must_root)] +impl PartialEq for BoundaryPoint { + fn eq(&self, other: &Self) -> bool { + self.node.get() == other.node.get() && self.offset.get() == other.offset.get() + } +} + +/// <https://dom.spec.whatwg.org/#concept-range-bp-position> +pub fn bp_position(a_node: &Node, a_offset: u32, b_node: &Node, b_offset: u32) -> Option<Ordering> { + if a_node as *const Node == b_node as *const Node { + // Step 1. + return Some(a_offset.cmp(&b_offset)); + } + let position = b_node.CompareDocumentPosition(a_node); + if position & NodeConstants::DOCUMENT_POSITION_DISCONNECTED != 0 { + // No order is defined for nodes not in the same tree. + None + } else if position & NodeConstants::DOCUMENT_POSITION_FOLLOWING != 0 { + // Step 2. + match bp_position(b_node, b_offset, a_node, a_offset).unwrap() { + Ordering::Less => Some(Ordering::Greater), + Ordering::Greater => Some(Ordering::Less), + Ordering::Equal => unreachable!(), + } + } else if position & NodeConstants::DOCUMENT_POSITION_CONTAINS != 0 { + // Step 3-1, 3-2. + let mut b_ancestors = b_node.inclusive_ancestors(ShadowIncluding::No); + let child = b_ancestors + .find(|child| &*child.GetParentNode().unwrap() == a_node) + .unwrap(); + // Step 3-3. + if child.index() < a_offset { + Some(Ordering::Greater) + } else { + // Step 4. + Some(Ordering::Less) + } + } else { + // Step 4. + Some(Ordering::Less) + } +} |