mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Invalidate and flush shadow tree stylesheets where needed
This commit is contained in:
parent
18c1b8f690
commit
519cc2c317
8 changed files with 115 additions and 25 deletions
|
@ -13,7 +13,7 @@ use crate::dom::bindings::root::{Dom, DomRoot};
|
|||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::cssrule::CSSRule;
|
||||
use crate::dom::element::Element;
|
||||
use crate::dom::node::{document_from_node, window_from_node, Node};
|
||||
use crate::dom::node::{document_from_node, shadow_root_from_node, window_from_node, Node};
|
||||
use crate::dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use servo_arc::Arc;
|
||||
|
@ -115,10 +115,16 @@ impl CSSStyleOwner {
|
|||
if changed {
|
||||
// If this is changed, see also
|
||||
// CSSStyleRule::SetSelectorText, which does the same thing.
|
||||
rule.global()
|
||||
.as_window()
|
||||
.Document()
|
||||
.invalidate_stylesheets();
|
||||
if let Some(shadow_root) =
|
||||
shadow_root_from_node(rule.parent_stylesheet().owner().upcast::<Node>())
|
||||
{
|
||||
shadow_root.invalidate_stylesheets();
|
||||
} else {
|
||||
rule.global()
|
||||
.as_window()
|
||||
.Document()
|
||||
.invalidate_stylesheets();
|
||||
}
|
||||
}
|
||||
result
|
||||
},
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::dom::bindings::str::DOMString;
|
|||
use crate::dom::cssrule::{CSSRule, SpecificCSSRule};
|
||||
use crate::dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration, CSSStyleOwner};
|
||||
use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||
use crate::dom::node::{shadow_root_from_node, Node};
|
||||
use crate::dom::window::Window;
|
||||
use cssparser::ToCss;
|
||||
use cssparser::{Parser as CssParser, ParserInput as CssParserInput};
|
||||
|
@ -118,12 +119,18 @@ impl CSSStyleRuleMethods for CSSStyleRule {
|
|||
let mut guard = self.cssrule.shared_lock().write();
|
||||
let stylerule = self.stylerule.write_with(&mut guard);
|
||||
mem::swap(&mut stylerule.selectors, &mut s);
|
||||
// It seems like we will want to avoid having to invalidate all
|
||||
// stylesheets eventually!
|
||||
self.global()
|
||||
.as_window()
|
||||
.Document()
|
||||
.invalidate_stylesheets();
|
||||
if let Some(shadow_root) =
|
||||
shadow_root_from_node(self.cssrule.parent_stylesheet().owner().upcast::<Node>())
|
||||
{
|
||||
shadow_root.invalidate_stylesheets();
|
||||
} else {
|
||||
// It seems like we will want to avoid having to invalidate all
|
||||
// stylesheets eventually!
|
||||
self.global()
|
||||
.as_window()
|
||||
.Document()
|
||||
.invalidate_stylesheets();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,13 @@ use crate::dom::bindings::codegen::Bindings::CSSStyleSheetBinding;
|
|||
use crate::dom::bindings::codegen::Bindings::CSSStyleSheetBinding::CSSStyleSheetMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::cssrulelist::{CSSRuleList, RulesSource};
|
||||
use crate::dom::element::Element;
|
||||
use crate::dom::node::{shadow_root_from_node, Node};
|
||||
use crate::dom::stylesheet::StyleSheet;
|
||||
use crate::dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
|
@ -64,6 +66,10 @@ impl CSSStyleSheet {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn owner(&self) -> DomRoot<Element> {
|
||||
DomRoot::from_ref(&*self.owner)
|
||||
}
|
||||
|
||||
fn rulelist(&self) -> DomRoot<CSSRuleList> {
|
||||
self.rulelist.or_init(|| {
|
||||
let rules = self.style_stylesheet.contents.rules.clone();
|
||||
|
@ -81,10 +87,14 @@ impl CSSStyleSheet {
|
|||
|
||||
pub fn set_disabled(&self, disabled: bool) {
|
||||
if self.style_stylesheet.set_disabled(disabled) {
|
||||
self.global()
|
||||
.as_window()
|
||||
.Document()
|
||||
.invalidate_stylesheets();
|
||||
if let Some(shadow_root) = shadow_root_from_node(self.owner.upcast::<Node>()) {
|
||||
shadow_root.invalidate_stylesheets();
|
||||
} else {
|
||||
self.global()
|
||||
.as_window()
|
||||
.Document()
|
||||
.invalidate_stylesheets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2430,6 +2430,7 @@ pub trait LayoutDocumentHelpers {
|
|||
unsafe fn will_paint(&self);
|
||||
unsafe fn quirks_mode(&self) -> QuirksMode;
|
||||
unsafe fn style_shared_lock(&self) -> &StyleSharedRwLock;
|
||||
unsafe fn shadow_roots(&self) -> Vec<LayoutDom<ShadowRoot>>;
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
@ -2474,6 +2475,16 @@ impl LayoutDocumentHelpers for LayoutDom<Document> {
|
|||
unsafe fn style_shared_lock(&self) -> &StyleSharedRwLock {
|
||||
(*self.unsafe_get()).style_shared_lock()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn shadow_roots(&self) -> Vec<LayoutDom<ShadowRoot>> {
|
||||
(*self.unsafe_get())
|
||||
.shadow_roots
|
||||
.borrow_for_layout()
|
||||
.iter()
|
||||
.map(|sr| sr.to_layout())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#is-a-registrable-domain-suffix-of-or-is-equal-to
|
||||
|
|
|
@ -14,13 +14,15 @@ use crate::dom::document::Document;
|
|||
use crate::dom::documentfragment::DocumentFragment;
|
||||
use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, StyleSheetInDocument};
|
||||
use crate::dom::element::Element;
|
||||
use crate::dom::node::{Node, NodeFlags};
|
||||
use crate::dom::node::{Node, NodeDamage, NodeFlags};
|
||||
use crate::dom::stylesheetlist::{StyleSheetList, StyleSheetListOwner};
|
||||
use crate::dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use selectors::context::QuirksMode;
|
||||
use servo_arc::Arc;
|
||||
use style::author_styles::AuthorStyles;
|
||||
use style::dom::TElement;
|
||||
use style::media_queries::Device;
|
||||
use style::shared_lock::SharedRwLockReadGuard;
|
||||
use style::stylesheets::Stylesheet;
|
||||
|
||||
|
@ -67,6 +69,14 @@ impl ShadowRoot {
|
|||
//XXX get retargeted focused element
|
||||
None
|
||||
}
|
||||
|
||||
pub fn invalidate_stylesheets(&self) {
|
||||
self.author_styles.borrow_mut().stylesheets.force_dirty();
|
||||
// Mark the host element dirty so a reflow will be performed.
|
||||
self.host
|
||||
.upcast::<Node>()
|
||||
.dirty(NodeDamage::NodeStyleDamaged);
|
||||
}
|
||||
}
|
||||
|
||||
impl ShadowRootMethods for ShadowRoot {
|
||||
|
@ -123,7 +133,12 @@ pub trait LayoutShadowRootHelpers {
|
|||
unsafe fn get_style_data_for_layout<'a, E: TElement>(
|
||||
&self,
|
||||
) -> &'a AuthorStyles<StyleSheetInDocument>;
|
||||
unsafe fn flush_stylesheets<E: TElement>(&self, guard: &SharedRwLockReadGuard);
|
||||
unsafe fn flush_stylesheets<E: TElement>(
|
||||
&self,
|
||||
device: &Device,
|
||||
quirks_mode: QuirksMode,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
);
|
||||
}
|
||||
|
||||
impl LayoutShadowRootHelpers for LayoutDom<ShadowRoot> {
|
||||
|
@ -143,10 +158,16 @@ impl LayoutShadowRootHelpers for LayoutDom<ShadowRoot> {
|
|||
|
||||
#[inline]
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn flush_stylesheets<E: TElement>(&self, guard: &SharedRwLockReadGuard) {
|
||||
let document = &(*self.unsafe_get()).document;
|
||||
unsafe fn flush_stylesheets<E: TElement>(
|
||||
&self,
|
||||
device: &Device,
|
||||
quirks_mode: QuirksMode,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
) {
|
||||
let mut author_styles = (*self.unsafe_get()).author_styles.borrow_mut_for_layout();
|
||||
author_styles.flush::<E>(&document.device(), document.quirks_mode(), guard);
|
||||
if author_styles.stylesheets.dirty() {
|
||||
author_styles.flush::<E>(device, quirks_mode, guard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,9 @@ use crate::dom::eventtarget::EventTarget;
|
|||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::htmlelement::HTMLElement;
|
||||
use crate::dom::htmllinkelement::{HTMLLinkElement, RequestGenerationId};
|
||||
use crate::dom::node::{document_from_node, window_from_node};
|
||||
use crate::dom::node::{document_from_node, shadow_root_from_node, window_from_node};
|
||||
use crate::dom::performanceresourcetiming::InitiatorType;
|
||||
use crate::dom::shadowroot::ShadowRoot;
|
||||
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||
use cssparser::SourceLocation;
|
||||
use encoding_rs::UTF_8;
|
||||
|
@ -81,6 +82,7 @@ pub struct StylesheetContext {
|
|||
data: Vec<u8>,
|
||||
/// The node document for elem when the load was initiated.
|
||||
document: Trusted<Document>,
|
||||
shadow_root: Option<Trusted<ShadowRoot>>,
|
||||
origin_clean: bool,
|
||||
/// A token which must match the generation id of the `HTMLLinkElement` for it to load the stylesheet.
|
||||
/// This is ignored for `HTMLStyleElement` and imports.
|
||||
|
@ -187,7 +189,11 @@ impl FetchResponseListener for StylesheetContext {
|
|||
},
|
||||
}
|
||||
|
||||
document.invalidate_stylesheets();
|
||||
if let Some(ref shadow_root) = self.shadow_root {
|
||||
shadow_root.root().invalidate_stylesheets();
|
||||
} else {
|
||||
document.invalidate_stylesheets();
|
||||
}
|
||||
|
||||
// FIXME: Revisit once consensus is reached at:
|
||||
// https://github.com/whatwg/html/issues/1142
|
||||
|
@ -264,6 +270,7 @@ impl<'a> StylesheetLoader<'a> {
|
|||
integrity_metadata: String,
|
||||
) {
|
||||
let document = document_from_node(self.elem);
|
||||
let shadow_root = shadow_root_from_node(self.elem).map(|sr| Trusted::new(&*sr));
|
||||
let gen = self
|
||||
.elem
|
||||
.downcast::<HTMLLinkElement>()
|
||||
|
@ -275,6 +282,7 @@ impl<'a> StylesheetLoader<'a> {
|
|||
metadata: None,
|
||||
data: vec![],
|
||||
document: Trusted::new(&*document),
|
||||
shadow_root,
|
||||
origin_clean: true,
|
||||
request_generation_id: gen,
|
||||
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue