mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Move stylesheets related code to DocumentOrShadowRoot
This commit is contained in:
parent
d2e1a3ab33
commit
0d6bd24245
6 changed files with 208 additions and 193 deletions
|
@ -39,6 +39,7 @@ use crate::dom::bindings::utils::WindowProxyHandler;
|
||||||
use crate::dom::document::PendingRestyle;
|
use crate::dom::document::PendingRestyle;
|
||||||
use crate::dom::htmlimageelement::SourceSet;
|
use crate::dom::htmlimageelement::SourceSet;
|
||||||
use crate::dom::htmlmediaelement::{HTMLMediaElementFetchContext, MediaFrameRenderer};
|
use crate::dom::htmlmediaelement::{HTMLMediaElementFetchContext, MediaFrameRenderer};
|
||||||
|
use crate::dom::stylesheetlist::StyleSheetListOwner;
|
||||||
use crate::task::TaskBox;
|
use crate::task::TaskBox;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use canvas_traits::canvas::{
|
use canvas_traits::canvas::{
|
||||||
|
@ -497,6 +498,7 @@ unsafe_no_jsmanaged_fields!(HTMLMediaElementFetchContext);
|
||||||
unsafe_no_jsmanaged_fields!(Rotation3D<f64>, Transform2D<f32>, Transform3D<f64>);
|
unsafe_no_jsmanaged_fields!(Rotation3D<f64>, Transform2D<f32>, Transform3D<f64>);
|
||||||
unsafe_no_jsmanaged_fields!(Point2D<f32>, Vector2D<f32>, Rect<Au>);
|
unsafe_no_jsmanaged_fields!(Point2D<f32>, Vector2D<f32>, Rect<Au>);
|
||||||
unsafe_no_jsmanaged_fields!(Rect<f32>, RigidTransform3D<f64>);
|
unsafe_no_jsmanaged_fields!(Rect<f32>, RigidTransform3D<f64>);
|
||||||
|
unsafe_no_jsmanaged_fields!(StyleSheetListOwner);
|
||||||
|
|
||||||
unsafe impl<'a> JSTraceable for &'a str {
|
unsafe impl<'a> JSTraceable for &'a str {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -43,7 +43,7 @@ use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||||
use crate::dom::customelementregistry::CustomElementDefinition;
|
use crate::dom::customelementregistry::CustomElementDefinition;
|
||||||
use crate::dom::customevent::CustomEvent;
|
use crate::dom::customevent::CustomEvent;
|
||||||
use crate::dom::documentfragment::DocumentFragment;
|
use crate::dom::documentfragment::DocumentFragment;
|
||||||
use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, DocumentOrShadowRootImpl};
|
use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, StyleSheetInDocument};
|
||||||
use crate::dom::documenttype::DocumentType;
|
use crate::dom::documenttype::DocumentType;
|
||||||
use crate::dom::domimplementation::DOMImplementation;
|
use crate::dom::domimplementation::DOMImplementation;
|
||||||
use crate::dom::element::CustomElementCreationMode;
|
use crate::dom::element::CustomElementCreationMode;
|
||||||
|
@ -68,7 +68,6 @@ use crate::dom::htmlheadelement::HTMLHeadElement;
|
||||||
use crate::dom::htmlhtmlelement::HTMLHtmlElement;
|
use crate::dom::htmlhtmlelement::HTMLHtmlElement;
|
||||||
use crate::dom::htmliframeelement::HTMLIFrameElement;
|
use crate::dom::htmliframeelement::HTMLIFrameElement;
|
||||||
use crate::dom::htmlimageelement::HTMLImageElement;
|
use crate::dom::htmlimageelement::HTMLImageElement;
|
||||||
use crate::dom::htmlmetaelement::HTMLMetaElement;
|
|
||||||
use crate::dom::htmlscriptelement::{HTMLScriptElement, ScriptResult};
|
use crate::dom::htmlscriptelement::{HTMLScriptElement, ScriptResult};
|
||||||
use crate::dom::htmltitleelement::HTMLTitleElement;
|
use crate::dom::htmltitleelement::HTMLTitleElement;
|
||||||
use crate::dom::keyboardevent::KeyboardEvent;
|
use crate::dom::keyboardevent::KeyboardEvent;
|
||||||
|
@ -89,7 +88,7 @@ use crate::dom::range::Range;
|
||||||
use crate::dom::servoparser::ServoParser;
|
use crate::dom::servoparser::ServoParser;
|
||||||
use crate::dom::shadowroot::ShadowRoot;
|
use crate::dom::shadowroot::ShadowRoot;
|
||||||
use crate::dom::storageevent::StorageEvent;
|
use crate::dom::storageevent::StorageEvent;
|
||||||
use crate::dom::stylesheetlist::StyleSheetList;
|
use crate::dom::stylesheetlist::{StyleSheetList, StyleSheetListOwner};
|
||||||
use crate::dom::text::Text;
|
use crate::dom::text::Text;
|
||||||
use crate::dom::touch::Touch;
|
use crate::dom::touch::Touch;
|
||||||
use crate::dom::touchevent::TouchEvent;
|
use crate::dom::touchevent::TouchEvent;
|
||||||
|
@ -145,7 +144,6 @@ use std::cell::{Cell, Ref, RefMut};
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
use std::collections::{HashMap, HashSet, VecDeque};
|
use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::fmt;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -153,12 +151,12 @@ use std::time::{Duration, Instant};
|
||||||
use style::attr::AttrValue;
|
use style::attr::AttrValue;
|
||||||
use style::context::QuirksMode;
|
use style::context::QuirksMode;
|
||||||
use style::invalidation::element::restyle_hints::RestyleHint;
|
use style::invalidation::element::restyle_hints::RestyleHint;
|
||||||
use style::media_queries::{Device, MediaList, MediaType};
|
use style::media_queries::{Device, MediaType};
|
||||||
use style::selector_parser::{RestyleDamage, Snapshot};
|
use style::selector_parser::{RestyleDamage, Snapshot};
|
||||||
use style::shared_lock::{SharedRwLock as StyleSharedRwLock, SharedRwLockReadGuard};
|
use style::shared_lock::SharedRwLock as StyleSharedRwLock;
|
||||||
use style::str::{split_html_space_chars, str_join};
|
use style::str::{split_html_space_chars, str_join};
|
||||||
use style::stylesheet_set::DocumentStylesheetSet;
|
use style::stylesheet_set::DocumentStylesheetSet;
|
||||||
use style::stylesheets::{CssRule, Origin, OriginSet, Stylesheet};
|
use style::stylesheets::Stylesheet;
|
||||||
use url::percent_encoding::percent_decode;
|
use url::percent_encoding::percent_decode;
|
||||||
use url::Host;
|
use url::Host;
|
||||||
|
|
||||||
|
@ -221,53 +219,11 @@ impl PendingRestyle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
|
||||||
#[must_root]
|
|
||||||
struct StyleSheetInDocument {
|
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
|
||||||
sheet: Arc<Stylesheet>,
|
|
||||||
owner: Dom<Element>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for StyleSheetInDocument {
|
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
self.sheet.fmt(formatter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for StyleSheetInDocument {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
Arc::ptr_eq(&self.sheet, &other.sheet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::style::stylesheets::StylesheetInDocument for StyleSheetInDocument {
|
|
||||||
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin {
|
|
||||||
self.sheet.origin(guard)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode {
|
|
||||||
self.sheet.quirks_mode(guard)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn enabled(&self) -> bool {
|
|
||||||
self.sheet.enabled()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
|
||||||
self.sheet.media(guard)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
|
||||||
self.sheet.rules(guard)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <https://dom.spec.whatwg.org/#document>
|
/// <https://dom.spec.whatwg.org/#document>
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct Document {
|
pub struct Document {
|
||||||
node: Node,
|
node: Node,
|
||||||
document_or_shadow_root: DocumentOrShadowRootImpl,
|
document_or_shadow_root: DocumentOrShadowRoot,
|
||||||
window: Dom<Window>,
|
window: Dom<Window>,
|
||||||
implementation: MutNullableDom<DOMImplementation>,
|
implementation: MutNullableDom<DOMImplementation>,
|
||||||
#[ignore_malloc_size_of = "type from external crate"]
|
#[ignore_malloc_size_of = "type from external crate"]
|
||||||
|
@ -618,7 +574,7 @@ impl Document {
|
||||||
// FIXME: This should check the dirty bit on the document,
|
// FIXME: This should check the dirty bit on the document,
|
||||||
// not the document element. Needs some layout changes to make
|
// not the document element. Needs some layout changes to make
|
||||||
// that workable.
|
// that workable.
|
||||||
self.stylesheets.borrow().has_changed() ||
|
self.document_or_shadow_root.stylesheets_have_changed() ||
|
||||||
self.GetDocumentElement().map_or(false, |root| {
|
self.GetDocumentElement().map_or(false, |root| {
|
||||||
root.upcast::<Node>().has_dirty_descendants() ||
|
root.upcast::<Node>().has_dirty_descendants() ||
|
||||||
!self.pending_restyles.borrow().is_empty() ||
|
!self.pending_restyles.borrow().is_empty() ||
|
||||||
|
@ -1580,7 +1536,7 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invalidate_stylesheets(&self) {
|
pub fn invalidate_stylesheets(&self) {
|
||||||
self.stylesheets.borrow_mut().force_dirty(OriginSet::all());
|
self.document_or_shadow_root.invalidate_stylesheets();
|
||||||
|
|
||||||
// Mark the document element dirty so a reflow will be performed.
|
// Mark the document element dirty so a reflow will be performed.
|
||||||
//
|
//
|
||||||
|
@ -2627,7 +2583,7 @@ impl Document {
|
||||||
let has_browsing_context = has_browsing_context == HasBrowsingContext::Yes;
|
let has_browsing_context = has_browsing_context == HasBrowsingContext::Yes;
|
||||||
Document {
|
Document {
|
||||||
node: Node::new_document_node(),
|
node: Node::new_document_node(),
|
||||||
document_or_shadow_root: DocumentOrShadowRootImpl::new(window),
|
document_or_shadow_root: DocumentOrShadowRoot::new(window),
|
||||||
window: Dom::from_ref(window),
|
window: Dom::from_ref(window),
|
||||||
has_browsing_context,
|
has_browsing_context,
|
||||||
implementation: Default::default(),
|
implementation: Default::default(),
|
||||||
|
@ -2865,9 +2821,9 @@ impl Document {
|
||||||
// and normal stylesheets additions / removals, because in the last case
|
// and normal stylesheets additions / removals, because in the last case
|
||||||
// the layout thread already has that information and we could avoid
|
// the layout thread already has that information and we could avoid
|
||||||
// dirtying the whole thing.
|
// dirtying the whole thing.
|
||||||
let mut stylesheets = self.stylesheets.borrow_mut();
|
let have_changed = self.document_or_shadow_root.stylesheets_have_changed();
|
||||||
let have_changed = stylesheets.has_changed();
|
self.document_or_shadow_root
|
||||||
stylesheets.flush_without_invalidation();
|
.flush_stylesheets_without_invalidation();
|
||||||
have_changed
|
have_changed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2885,90 +2841,21 @@ impl Document {
|
||||||
/// Remove a stylesheet owned by `owner` from the list of document sheets.
|
/// Remove a stylesheet owned by `owner` from the list of document sheets.
|
||||||
#[allow(unrooted_must_root)] // Owner needs to be rooted already necessarily.
|
#[allow(unrooted_must_root)] // Owner needs to be rooted already necessarily.
|
||||||
pub fn remove_stylesheet(&self, owner: &Element, s: &Arc<Stylesheet>) {
|
pub fn remove_stylesheet(&self, owner: &Element, s: &Arc<Stylesheet>) {
|
||||||
self.window()
|
self.document_or_shadow_root.remove_stylesheet(owner, s)
|
||||||
.layout_chan()
|
|
||||||
.send(Msg::RemoveStylesheet(s.clone()))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let guard = s.shared_lock.read();
|
|
||||||
|
|
||||||
// FIXME(emilio): Would be nice to remove the clone, etc.
|
|
||||||
self.stylesheets.borrow_mut().remove_stylesheet(
|
|
||||||
None,
|
|
||||||
StyleSheetInDocument {
|
|
||||||
sheet: s.clone(),
|
|
||||||
owner: Dom::from_ref(owner),
|
|
||||||
},
|
|
||||||
&guard,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a stylesheet owned by `owner` to the list of document sheets, in the
|
/// Add a stylesheet owned by `owner` to the list of document sheets, in the
|
||||||
/// correct tree position.
|
/// correct tree position.
|
||||||
#[allow(unrooted_must_root)] // Owner needs to be rooted already necessarily.
|
#[allow(unrooted_must_root)] // Owner needs to be rooted already necessarily.
|
||||||
pub fn add_stylesheet(&self, owner: &Element, sheet: Arc<Stylesheet>) {
|
pub fn add_stylesheet(&self, owner: &Element, sheet: Arc<Stylesheet>) {
|
||||||
// FIXME(emilio): It'd be nice to unify more code between the elements
|
self.document_or_shadow_root
|
||||||
// that own stylesheets, but StylesheetOwner is more about loading
|
.add_stylesheet(owner, sheet, self.style_shared_lock());
|
||||||
// them...
|
|
||||||
debug_assert!(
|
|
||||||
owner.as_stylesheet_owner().is_some() || owner.is::<HTMLMetaElement>(),
|
|
||||||
"Wat"
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut stylesheets = self.stylesheets.borrow_mut();
|
|
||||||
let insertion_point = stylesheets
|
|
||||||
.iter()
|
|
||||||
.map(|(sheet, _origin)| sheet)
|
|
||||||
.find(|sheet_in_doc| {
|
|
||||||
owner
|
|
||||||
.upcast::<Node>()
|
|
||||||
.is_before(sheet_in_doc.owner.upcast())
|
|
||||||
})
|
|
||||||
.cloned();
|
|
||||||
|
|
||||||
self.window()
|
|
||||||
.layout_chan()
|
|
||||||
.send(Msg::AddStylesheet(
|
|
||||||
sheet.clone(),
|
|
||||||
insertion_point.as_ref().map(|s| s.sheet.clone()),
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let sheet = StyleSheetInDocument {
|
|
||||||
sheet,
|
|
||||||
owner: Dom::from_ref(owner),
|
|
||||||
};
|
|
||||||
|
|
||||||
let lock = self.style_shared_lock();
|
|
||||||
let guard = lock.read();
|
|
||||||
|
|
||||||
match insertion_point {
|
|
||||||
Some(ip) => {
|
|
||||||
stylesheets.insert_stylesheet_before(None, sheet, ip, &guard);
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
stylesheets.append_stylesheet(None, sheet, &guard);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the number of document stylesheets.
|
|
||||||
pub fn stylesheet_count(&self) -> usize {
|
|
||||||
self.stylesheets.borrow().len()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn salvageable(&self) -> bool {
|
pub fn salvageable(&self) -> bool {
|
||||||
self.salvageable.get()
|
self.salvageable.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stylesheet_at(&self, index: usize) -> Option<DomRoot<CSSStyleSheet>> {
|
|
||||||
let stylesheets = self.stylesheets.borrow();
|
|
||||||
|
|
||||||
stylesheets
|
|
||||||
.get(Origin::Author, index)
|
|
||||||
.and_then(|s| s.owner.upcast::<Node>().get_cssom_stylesheet())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document>
|
/// <https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document>
|
||||||
pub fn appropriate_template_contents_owner_document(&self) -> DomRoot<Document> {
|
pub fn appropriate_template_contents_owner_document(&self) -> DomRoot<Document> {
|
||||||
self.appropriate_template_contents_owner_document
|
self.appropriate_template_contents_owner_document
|
||||||
|
@ -3290,12 +3177,8 @@ impl ProfilerMetadataFactory for Document {
|
||||||
impl DocumentMethods for Document {
|
impl DocumentMethods for Document {
|
||||||
// https://drafts.csswg.org/cssom/#dom-document-stylesheets
|
// https://drafts.csswg.org/cssom/#dom-document-stylesheets
|
||||||
fn StyleSheets(&self) -> DomRoot<StyleSheetList> {
|
fn StyleSheets(&self) -> DomRoot<StyleSheetList> {
|
||||||
self.stylesheet_list.or_init(|| {
|
self.stylesheet_list
|
||||||
StyleSheetList::new(
|
.or_init(|| StyleSheetList::new(&self.window, Box::new(Dom::from_ref(self))))
|
||||||
&self.window,
|
|
||||||
DocumentOrShadowRoot::Document(Dom::from_ref(self)),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-document-implementation
|
// https://dom.spec.whatwg.org/#dom-document-implementation
|
||||||
|
@ -4678,3 +4561,13 @@ impl PendingScript {
|
||||||
.map(|result| (DomRoot::from_ref(&*self.element), result))
|
.map(|result| (DomRoot::from_ref(&*self.element), result))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StyleSheetListOwner for Dom<Document> {
|
||||||
|
fn stylesheet_count(&self) -> usize {
|
||||||
|
self.document_or_shadow_root.stylesheet_count()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stylesheet_at(&self, index: usize) -> Option<DomRoot<CSSStyleSheet>> {
|
||||||
|
self.document_or_shadow_root.stylesheet_at(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,65 +2,86 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeBinding::NodeMethods;
|
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeBinding::NodeMethods;
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::num::Finite;
|
use crate::dom::bindings::num::Finite;
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::cssstylesheet::CSSStyleSheet;
|
use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||||
use crate::dom::document::Document;
|
|
||||||
use crate::dom::element::Element;
|
use crate::dom::element::Element;
|
||||||
use crate::dom::htmlelement::HTMLElement;
|
use crate::dom::htmlelement::HTMLElement;
|
||||||
use crate::dom::node;
|
use crate::dom::htmlmetaelement::HTMLMetaElement;
|
||||||
use crate::dom::shadowroot::ShadowRoot;
|
use crate::dom::node::{self, Node};
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use euclid::Point2D;
|
use euclid::Point2D;
|
||||||
use js::jsapi::JS_GetRuntime;
|
use js::jsapi::JS_GetRuntime;
|
||||||
use script_layout_interface::message::{NodesFromPointQueryType, QueryMsg};
|
use script_layout_interface::message::{Msg, NodesFromPointQueryType, QueryMsg};
|
||||||
use script_traits::UntrustedNodeAddress;
|
use script_traits::UntrustedNodeAddress;
|
||||||
|
use servo_arc::Arc;
|
||||||
|
use std::fmt;
|
||||||
|
use style::context::QuirksMode;
|
||||||
|
use style::media_queries::MediaList;
|
||||||
|
use style::shared_lock::{SharedRwLock as StyleSharedRwLock, SharedRwLockReadGuard};
|
||||||
|
use style::stylesheet_set::DocumentStylesheetSet;
|
||||||
|
use style::stylesheets::{CssRule, Origin, OriginSet, Stylesheet};
|
||||||
|
|
||||||
macro_rules! proxy_call(
|
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
||||||
($fn_name:ident, $return_type:ty) => (
|
|
||||||
pub fn $fn_name(&self) -> $return_type {
|
|
||||||
match self {
|
|
||||||
DocumentOrShadowRoot::Document(doc) => doc.$fn_name(),
|
|
||||||
DocumentOrShadowRoot::ShadowRoot(root) => root.$fn_name(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
($fn_name:ident, $arg1:ident, $arg1_type:ty, $return_type:ty) => (
|
|
||||||
pub fn $fn_name(&self, $arg1: $arg1_type) -> $return_type {
|
|
||||||
match self {
|
|
||||||
DocumentOrShadowRoot::Document(doc) => doc.$fn_name($arg1),
|
|
||||||
DocumentOrShadowRoot::ShadowRoot(root) => root.$fn_name($arg1),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
);
|
|
||||||
|
|
||||||
#[must_root]
|
#[must_root]
|
||||||
#[derive(JSTraceable, MallocSizeOf)]
|
pub struct StyleSheetInDocument {
|
||||||
pub enum DocumentOrShadowRoot {
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
Document(Dom<Document>),
|
sheet: Arc<Stylesheet>,
|
||||||
ShadowRoot(Dom<ShadowRoot>),
|
owner: Dom<Element>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DocumentOrShadowRoot {
|
impl fmt::Debug for StyleSheetInDocument {
|
||||||
proxy_call!(stylesheet_count, usize);
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
proxy_call!(stylesheet_at, index, usize, Option<DomRoot<CSSStyleSheet>>);
|
self.sheet.fmt(formatter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for StyleSheetInDocument {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
Arc::ptr_eq(&self.sheet, &other.sheet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::style::stylesheets::StylesheetInDocument for StyleSheetInDocument {
|
||||||
|
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin {
|
||||||
|
self.sheet.origin(guard)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode {
|
||||||
|
self.sheet.quirks_mode(guard)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enabled(&self) -> bool {
|
||||||
|
self.sheet.enabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
||||||
|
self.sheet.media(guard)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||||
|
self.sheet.rules(guard)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/webcomponents/spec/shadow/#extensions-to-the-documentorshadowroot-mixin
|
// https://w3c.github.io/webcomponents/spec/shadow/#extensions-to-the-documentorshadowroot-mixin
|
||||||
#[must_root]
|
#[must_root]
|
||||||
#[derive(JSTraceable, MallocSizeOf)]
|
#[derive(JSTraceable, MallocSizeOf)]
|
||||||
pub struct DocumentOrShadowRootImpl {
|
pub struct DocumentOrShadowRoot {
|
||||||
window: Dom<Window>,
|
window: Dom<Window>,
|
||||||
|
/// List of stylesheets associated with nodes in this document or shadow root.
|
||||||
|
/// |None| if the list needs to be refreshed.
|
||||||
|
stylesheets: DomRefCell<DocumentStylesheetSet<StyleSheetInDocument>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DocumentOrShadowRootImpl {
|
impl DocumentOrShadowRoot {
|
||||||
pub fn new(window: &Window) -> Self {
|
pub fn new(window: &Window) -> Self {
|
||||||
Self {
|
Self {
|
||||||
window: Dom::from_ref(window),
|
window: Dom::from_ref(window),
|
||||||
|
stylesheets: DomRefCell::new(DocumentStylesheetSet::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,4 +206,102 @@ impl DocumentOrShadowRootImpl {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn stylesheet_count(&self) -> usize {
|
||||||
|
self.stylesheets.borrow().len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stylesheet_at(&self, index: usize) -> Option<DomRoot<CSSStyleSheet>> {
|
||||||
|
let stylesheets = self.stylesheets.borrow();
|
||||||
|
|
||||||
|
stylesheets
|
||||||
|
.get(Origin::Author, index)
|
||||||
|
.and_then(|s| s.owner.upcast::<Node>().get_cssom_stylesheet())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stylesheets_have_changed(&self) -> bool {
|
||||||
|
self.stylesheets.borrow().has_changed()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invalidate_stylesheets(&self) {
|
||||||
|
self.stylesheets.borrow_mut().force_dirty(OriginSet::all());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flush_stylesheets_without_invalidation(&self) {
|
||||||
|
self.stylesheets.borrow_mut().flush_without_invalidation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove a stylesheet owned by `owner` from the list of document sheets.
|
||||||
|
#[allow(unrooted_must_root)] // Owner needs to be rooted already necessarily.
|
||||||
|
pub fn remove_stylesheet(&self, owner: &Element, s: &Arc<Stylesheet>) {
|
||||||
|
self.window
|
||||||
|
.layout_chan()
|
||||||
|
.send(Msg::RemoveStylesheet(s.clone()))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let guard = s.shared_lock.read();
|
||||||
|
|
||||||
|
// FIXME(emilio): Would be nice to remove the clone, etc.
|
||||||
|
self.stylesheets.borrow_mut().remove_stylesheet(
|
||||||
|
None,
|
||||||
|
StyleSheetInDocument {
|
||||||
|
sheet: s.clone(),
|
||||||
|
owner: Dom::from_ref(owner),
|
||||||
|
},
|
||||||
|
&guard,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a stylesheet owned by `owner` to the list of document sheets, in the
|
||||||
|
/// correct tree position.
|
||||||
|
#[allow(unrooted_must_root)] // Owner needs to be rooted already necessarily.
|
||||||
|
pub fn add_stylesheet(
|
||||||
|
&self,
|
||||||
|
owner: &Element,
|
||||||
|
sheet: Arc<Stylesheet>,
|
||||||
|
style_shared_lock: &StyleSharedRwLock,
|
||||||
|
) {
|
||||||
|
// FIXME(emilio): It'd be nice to unify more code between the elements
|
||||||
|
// that own stylesheets, but StylesheetOwner is more about loading
|
||||||
|
// them...
|
||||||
|
debug_assert!(
|
||||||
|
owner.as_stylesheet_owner().is_some() || owner.is::<HTMLMetaElement>(),
|
||||||
|
"Wat"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut stylesheets = self.stylesheets.borrow_mut();
|
||||||
|
let insertion_point = stylesheets
|
||||||
|
.iter()
|
||||||
|
.map(|(sheet, _origin)| sheet)
|
||||||
|
.find(|sheet_in_doc| {
|
||||||
|
owner
|
||||||
|
.upcast::<Node>()
|
||||||
|
.is_before(sheet_in_doc.owner.upcast())
|
||||||
|
})
|
||||||
|
.cloned();
|
||||||
|
|
||||||
|
self.window
|
||||||
|
.layout_chan()
|
||||||
|
.send(Msg::AddStylesheet(
|
||||||
|
sheet.clone(),
|
||||||
|
insertion_point.as_ref().map(|s| s.sheet.clone()),
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let sheet = StyleSheetInDocument {
|
||||||
|
sheet,
|
||||||
|
owner: Dom::from_ref(owner),
|
||||||
|
};
|
||||||
|
|
||||||
|
let guard = style_shared_lock.read();
|
||||||
|
|
||||||
|
match insertion_point {
|
||||||
|
Some(ip) => {
|
||||||
|
stylesheets.insert_stylesheet_before(None, sheet, ip, &guard);
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
stylesheets.append_stylesheet(None, sheet, &guard);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ use crate::dom::node::{NodeDamage, NodeFlags, UnbindContext};
|
||||||
use crate::dom::nodelist::NodeList;
|
use crate::dom::nodelist::NodeList;
|
||||||
use crate::dom::promise::Promise;
|
use crate::dom::promise::Promise;
|
||||||
use crate::dom::servoparser::ServoParser;
|
use crate::dom::servoparser::ServoParser;
|
||||||
use crate::dom::shadowroot::{LayoutShadowRootHelpers, ShadowRoot};
|
use crate::dom::shadowroot::ShadowRoot;
|
||||||
use crate::dom::text::Text;
|
use crate::dom::text::Text;
|
||||||
use crate::dom::validation::Validatable;
|
use crate::dom::validation::Validatable;
|
||||||
use crate::dom::virtualmethods::{vtable_for, VirtualMethods};
|
use crate::dom::virtualmethods::{vtable_for, VirtualMethods};
|
||||||
|
|
|
@ -11,10 +11,10 @@ use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
|
||||||
use crate::dom::cssstylesheet::CSSStyleSheet;
|
use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||||
use crate::dom::document::Document;
|
use crate::dom::document::Document;
|
||||||
use crate::dom::documentfragment::DocumentFragment;
|
use crate::dom::documentfragment::DocumentFragment;
|
||||||
use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, DocumentOrShadowRootImpl};
|
use crate::dom::documentorshadowroot::DocumentOrShadowRoot;
|
||||||
use crate::dom::element::Element;
|
use crate::dom::element::Element;
|
||||||
use crate::dom::node::{Node, NodeFlags};
|
use crate::dom::node::{Node, NodeFlags};
|
||||||
use crate::dom::stylesheetlist::StyleSheetList;
|
use crate::dom::stylesheetlist::{StyleSheetList, StyleSheetListOwner};
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ use dom_struct::dom_struct;
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct ShadowRoot {
|
pub struct ShadowRoot {
|
||||||
document_fragment: DocumentFragment,
|
document_fragment: DocumentFragment,
|
||||||
document_or_shadow_root: DocumentOrShadowRootImpl,
|
document_or_shadow_root: DocumentOrShadowRoot,
|
||||||
document: Dom<Document>,
|
document: Dom<Document>,
|
||||||
host: Dom<Element>,
|
host: Dom<Element>,
|
||||||
stylesheet_list: MutNullableDom<StyleSheetList>,
|
stylesheet_list: MutNullableDom<StyleSheetList>,
|
||||||
|
@ -38,7 +38,7 @@ impl ShadowRoot {
|
||||||
.set_flag(NodeFlags::IS_IN_SHADOW_TREE, true);
|
.set_flag(NodeFlags::IS_IN_SHADOW_TREE, true);
|
||||||
ShadowRoot {
|
ShadowRoot {
|
||||||
document_fragment,
|
document_fragment,
|
||||||
document_or_shadow_root: DocumentOrShadowRootImpl::new(document.window()),
|
document_or_shadow_root: DocumentOrShadowRoot::new(document.window()),
|
||||||
document: Dom::from_ref(document),
|
document: Dom::from_ref(document),
|
||||||
host: Dom::from_ref(host),
|
host: Dom::from_ref(host),
|
||||||
stylesheet_list: MutNullableDom::new(None),
|
stylesheet_list: MutNullableDom::new(None),
|
||||||
|
@ -58,16 +58,6 @@ impl ShadowRoot {
|
||||||
//XXX get retargeted focused element
|
//XXX get retargeted focused element
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stylesheet_count(&self) -> usize {
|
|
||||||
//XXX handle shadowroot stylesheets
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stylesheet_at(&self, _index: usize) -> Option<DomRoot<CSSStyleSheet>> {
|
|
||||||
//XXX handle shadowroot stylesheets
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShadowRootMethods for ShadowRoot {
|
impl ShadowRootMethods for ShadowRoot {
|
||||||
|
@ -113,12 +103,8 @@ impl ShadowRootMethods for ShadowRoot {
|
||||||
|
|
||||||
// https://drafts.csswg.org/cssom/#dom-document-stylesheets
|
// https://drafts.csswg.org/cssom/#dom-document-stylesheets
|
||||||
fn StyleSheets(&self) -> DomRoot<StyleSheetList> {
|
fn StyleSheets(&self) -> DomRoot<StyleSheetList> {
|
||||||
self.stylesheet_list.or_init(|| {
|
self.stylesheet_list
|
||||||
StyleSheetList::new(
|
.or_init(|| StyleSheetList::new(&self.window, Box::new(Dom::from_ref(self))))
|
||||||
&self.window,
|
|
||||||
DocumentOrShadowRoot::ShadowRoot(Dom::from_ref(self)),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,3 +120,13 @@ impl LayoutShadowRootHelpers for LayoutDom<ShadowRoot> {
|
||||||
(*self.unsafe_get()).host.to_layout()
|
(*self.unsafe_get()).host.to_layout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StyleSheetListOwner for Dom<ShadowRoot> {
|
||||||
|
fn stylesheet_count(&self) -> usize {
|
||||||
|
self.document_or_shadow_root.stylesheet_count()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stylesheet_at(&self, index: usize) -> Option<DomRoot<CSSStyleSheet>> {
|
||||||
|
self.document_or_shadow_root.stylesheet_at(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,20 +6,25 @@ use crate::dom::bindings::codegen::Bindings::StyleSheetListBinding;
|
||||||
use crate::dom::bindings::codegen::Bindings::StyleSheetListBinding::StyleSheetListMethods;
|
use crate::dom::bindings::codegen::Bindings::StyleSheetListBinding::StyleSheetListMethods;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::documentorshadowroot::DocumentOrShadowRoot;
|
use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||||
use crate::dom::stylesheet::StyleSheet;
|
use crate::dom::stylesheet::StyleSheet;
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
|
||||||
|
pub trait StyleSheetListOwner {
|
||||||
|
fn stylesheet_count(&self) -> usize;
|
||||||
|
fn stylesheet_at(&self, index: usize) -> Option<DomRoot<CSSStyleSheet>>;
|
||||||
|
}
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct StyleSheetList {
|
pub struct StyleSheetList {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
document_or_shadow_root: DocumentOrShadowRoot,
|
#[ignore_malloc_size_of = "trait object"]
|
||||||
|
document_or_shadow_root: Box<StyleSheetListOwner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StyleSheetList {
|
impl StyleSheetList {
|
||||||
#[allow(unrooted_must_root)]
|
fn new_inherited(doc_or_sr: Box<StyleSheetListOwner>) -> StyleSheetList {
|
||||||
fn new_inherited(doc_or_sr: DocumentOrShadowRoot) -> StyleSheetList {
|
|
||||||
StyleSheetList {
|
StyleSheetList {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
document_or_shadow_root: doc_or_sr,
|
document_or_shadow_root: doc_or_sr,
|
||||||
|
@ -27,7 +32,7 @@ impl StyleSheetList {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
pub fn new(window: &Window, doc_or_sr: DocumentOrShadowRoot) -> DomRoot<StyleSheetList> {
|
pub fn new(window: &Window, doc_or_sr: Box<StyleSheetListOwner>) -> DomRoot<StyleSheetList> {
|
||||||
reflect_dom_object(
|
reflect_dom_object(
|
||||||
Box::new(StyleSheetList::new_inherited(doc_or_sr)),
|
Box::new(StyleSheetList::new_inherited(doc_or_sr)),
|
||||||
window,
|
window,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue