Repository: servo/servo
File: components/script/dom/node.rs (Rust)

Code before:
    }
}

/// Iterate through `nodes` until we find a `Node` that is not in `not_in`
fn first_node_not_in<I>(mut nodes: I, not_in: &[NodeOrString]) -> Option<DomRoot<Node>>
where
    I: Iterator<Item = DomRoot<Node>>,
{
    nodes.find(|node| {
        not_in.iter().all(|n| match *n {
            NodeOrString::Node(ref n) => n != node,
            _ => true,
        })
    })
}

/// If the given untrusted node address represents a valid DOM node in the given runtime,
/// returns it.
#[expect(unsafe_code)]
pub(crate) unsafe fn from_untrusted_node_address(candidate: UntrustedNodeAddress) -> DomRoot<Node> {
    let node = unsafe { Node::from_untrusted_node_address(candidate) };
    DomRoot::from_ref(node)
}

#[expect(unsafe_code)]
pub(crate) trait LayoutNodeHelpers<'dom> {
    fn type_id_for_layout(self) -> NodeTypeId;

    fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
    fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
    fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
    fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
    fn prev_sibling_ref(self) -> Option<LayoutDom<'dom, Node>>;
    fn next_sibling_ref(self) -> Option<LayoutDom<'dom, Node>>;

    fn owner_doc_for_layout(self) -> LayoutDom<'dom, Document>;
    fn containing_shadow_root_for_layout(self) -> Option<LayoutDom<'dom, ShadowRoot>>;
    fn assigned_slot_for_layout(self) -> Option<LayoutDom<'dom, HTMLSlotElement>>;

    fn is_element_for_layout(&self) -> bool;
    fn is_text_node_for_layout(&self) -> bool;
    unsafe fn get_flag(self, flag: NodeFlags) -> bool;
    unsafe fn set_flag(self, flag: NodeFlags, value: bool);

    fn style_data(self) -> Option<&'dom StyleData>;
    fn layout_data(self) -> Option<&'dom GenericLayoutData>;

    /// Initialize the style data of this node.
    ///
    /// # Safety
    ///

Review comment (suggestion):
it might be beneficial to implement this in an iterative way with `.ancestors(ShadowIncluding::No)` instead of recursing here, to use less stack space.

But we can keep it like this for now.

Code after:
            .and_then(|rare_data| rare_data.implemented_pseudo_element)
    }

    /// <https://html.spec.whatwg.org/multipage/#editing-host>
    fn is_editing_host(&self) -> bool {
        self.downcast::<HTMLElement>()
            .is_some_and(HTMLElement::is_editing_host)
    }

    /// <https://w3c.github.io/editing/docs/execCommand/#editable>
    pub(crate) fn is_editable(&self) -> bool {
        // > Something is editable if it is a node; it is not an editing host;
        if self.is_editing_host() {
            return false;
        }
        // > it does not have a contenteditable attribute set to the false state;
        let html_element = self.downcast::<HTMLElement>();
        if html_element.is_some_and(|el| el.ContentEditable().str() == "false") {
            return false;
        }
        // > its parent is an editing host or editable;
        let Some(parent) = self.GetParentNode() else {
            return false;
        };
        if !parent.is_editable() && !parent.is_editing_host() {
            return false;
        }
        // > and either it is an HTML element, or it is an svg or math element, or it is not an Element and its parent is an HTML element.
        html_element.is_some() || parent.downcast::<HTMLElement>().is_some()
    }
}

/// Iterate through `nodes` until we find a `Node` that is not in `not_in`
fn first_node_not_in<I>(mut nodes: I, not_in: &[NodeOrString]) -> Option<DomRoot<Node>>
where
    I: Iterator<Item = DomRoot<Node>>,
{
    nodes.find(|node| {
        not_in.iter().all(|n| match *n {
            NodeOrString::Node(ref n) => n != node,
            _ => true,
        })
    })
}

/// If the given untrusted node address represents a valid DOM node in the given runtime,
/// returns it.
#[expect(unsafe_code)]
pub(crate) unsafe fn from_untrusted_node_address(candidate: UntrustedNodeAddress) -> DomRoot<Node> {
    let node = unsafe { Node::from_untrusted_node_address(candidate) };
    DomRoot::from_ref(node)