/* 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 selectors::matching::QuirksMode; use style::dom::{TDocument, TNode}; use style::shared_lock::{ SharedRwLock as StyleSharedRwLock, SharedRwLockReadGuard as StyleSharedRwLockReadGuard, }; use style::stylist::Stylist; use crate::dom::bindings::root::LayoutDom; use crate::dom::document::{Document, LayoutDocumentHelpers}; use crate::dom::node::{LayoutNodeHelpers, Node, NodeFlags}; use crate::layout_dom::{ServoLayoutElement, ServoLayoutNode, ServoShadowRoot}; // A wrapper around documents that ensures ayout can only ever access safe properties. #[derive(Clone, Copy)] pub struct ServoLayoutDocument<'dom> { /// The wrapped private DOM Document document: LayoutDom<'dom, Document>, } impl<'ld> ::style::dom::TDocument for ServoLayoutDocument<'ld> { type ConcreteNode = ServoLayoutNode<'ld>; fn as_node(&self) -> Self::ConcreteNode { ServoLayoutNode::from_layout_js(self.document.upcast()) } fn quirks_mode(&self) -> QuirksMode { self.document.quirks_mode() } fn is_html_document(&self) -> bool { self.document.is_html_document_for_layout() } fn shared_lock(&self) -> &StyleSharedRwLock { self.document.style_shared_lock() } } impl<'ld> ServoLayoutDocument<'ld> { pub fn root_element(&self) -> Option> { self.as_node() .dom_children() .flat_map(|n| n.as_element()) .next() } pub fn style_shared_lock(&self) -> &StyleSharedRwLock { self.document.style_shared_lock() } pub fn shadow_roots(&self) -> Vec { unsafe { self.document .shadow_roots() .iter() .map(|sr| { debug_assert!(sr.upcast::().get_flag(NodeFlags::IS_CONNECTED)); ServoShadowRoot::from_layout_js(*sr) }) .collect() } } pub fn flush_shadow_roots_stylesheets( &self, stylist: &mut Stylist, guard: &StyleSharedRwLockReadGuard, ) { unsafe { if !self.document.shadow_roots_styles_changed() { return; } self.document.flush_shadow_roots_stylesheets(); for shadow_root in self.shadow_roots() { shadow_root.flush_stylesheets(stylist, guard); } } } pub(crate) fn from_layout_js(document: LayoutDom<'ld, Document>) -> Self { ServoLayoutDocument { document } } }