Repository: servo/servo
File: components/script/layout_dom/element.rs (Rust)

Code before:
    fn has_custom_state(&self, name: &AtomIdent) -> bool {
        let mut has_state = false;
        self.element
            .each_custom_state_for_layout(|state| has_state |= state == name);

        has_state
    }
}

/// A wrapper around elements that ensures layout can only
/// ever access safe properties and cannot race on elements.
#[derive(Clone, Copy, Debug)]
pub struct ServoThreadSafeLayoutElement<'dom> {
    /// The wrapped [`ServoLayoutElement`].
    pub(super) element: ServoLayoutElement<'dom>,

    /// The possibly nested [`PseudoElementChain`] for this element.
    pub(super) pseudo_element_chain: PseudoElementChain,
}

impl<'dom> ServoThreadSafeLayoutElement<'dom> {
    /// The shadow root this element is a host of.
    pub fn shadow_root(&self) -> Option<ServoShadowRoot<'dom>> {
        if !self.pseudo_element_chain.is_empty() {
            return None;
        }
        self.element
            .element
            .get_shadow_root_for_layout()
            .map(ServoShadowRoot::from_layout_js)
    }

    pub fn slotted_nodes(&self) -> &[ServoLayoutNode<'dom>] {
        self.element.slotted_nodes()
    }
}

impl<'dom> ThreadSafeLayoutElement<'dom> for ServoThreadSafeLayoutElement<'dom> {
    type ConcreteThreadSafeLayoutNode = ServoThreadSafeLayoutNode<'dom>;
    type ConcreteElement = ServoLayoutElement<'dom>;

    fn as_node(&self) -> ServoThreadSafeLayoutNode<'dom> {
        ServoThreadSafeLayoutNode {
            node: self.element.as_node(),
            pseudo_element_chain: self.pseudo_element_chain,
        }
    }

    fn pseudo_element_chain(&self) -> PseudoElementChain {
        self.pseudo_element_chain
    }

Review comment (suggestion):
The context for this change is https://github.com/servo/servo/blob/b2aa0ac859e2921e944bd970d0590c96424206dc/components/layout/formatting_contexts.rs#L93

There are various other methods in `ServoThreadSafeLayoutElement` and `ServoThreadSafeLayoutNone` which are ignoring the `pseudo_element_chain`, should be investigated in a follow-up.

Code after:
    fn has_custom_state(&self, name: &AtomIdent) -> bool {
        let mut has_state = false;
        self.element
            .each_custom_state_for_layout(|state| has_state |= state == name);

        has_state
    }
}

/// A wrapper around elements that ensures layout can only
/// ever access safe properties and cannot race on elements.
#[derive(Clone, Copy, Debug)]
pub struct ServoThreadSafeLayoutElement<'dom> {
    /// The wrapped [`ServoLayoutElement`].
    pub(super) element: ServoLayoutElement<'dom>,

    /// The possibly nested [`PseudoElementChain`] for this element.
    pub(super) pseudo_element_chain: PseudoElementChain,
}

impl<'dom> ServoThreadSafeLayoutElement<'dom> {
    /// The shadow root this element is a host of.
    pub fn shadow_root(&self) -> Option<ServoShadowRoot<'dom>> {
        self.element
            .element
            .get_shadow_root_for_layout()
            .map(ServoShadowRoot::from_layout_js)
    }

    pub fn slotted_nodes(&self) -> &[ServoLayoutNode<'dom>] {
        self.element.slotted_nodes()
    }
}

impl<'dom> ThreadSafeLayoutElement<'dom> for ServoThreadSafeLayoutElement<'dom> {
    type ConcreteThreadSafeLayoutNode = ServoThreadSafeLayoutNode<'dom>;
    type ConcreteElement = ServoLayoutElement<'dom>;

    fn as_node(&self) -> ServoThreadSafeLayoutNode<'dom> {
        ServoThreadSafeLayoutNode {
            node: self.element.as_node(),
            pseudo_element_chain: self.pseudo_element_chain,
        }
    }

    fn pseudo_element_chain(&self) -> PseudoElementChain {
        self.pseudo_element_chain
    }

    fn with_pseudo(&self, pseudo_element: PseudoElement) -> Option<Self> {
        if pseudo_element.is_eager() &&