aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/abstractrange.rs
diff options
context:
space:
mode:
authorcathiechen <cathiechen@igalia.com>2024-03-22 16:02:01 +0100
committerGitHub <noreply@github.com>2024-03-22 15:02:01 +0000
commitcb275e086c215b6da741c7918cd9683a134eb24f (patch)
tree173f32008068d06f27b3d1a8af1a855dfa6174da /components/script/dom/abstractrange.rs
parentbae77671f85481503ab563c20ed488cf883436fa (diff)
downloadservo-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.rs177
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)
+ }
+}