mirror of
https://github.com/servo/servo.git
synced 2025-08-07 22:45:34 +01:00
Auto merge of #19790 - emilio:fix-all-the-bugs, r=heycam,xidorn
style: Work from multiple bugs. Bug: 1429846,1429248,1430608,1409672 Reviewed-by: xidorn,heycam <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19790) <!-- Reviewable:end -->
This commit is contained in:
commit
7d685d4baa
11 changed files with 249 additions and 258 deletions
|
@ -31,7 +31,7 @@ use std::fmt;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use stylist::{StyleRuleCascadeData, Stylist};
|
use stylist::{CascadeData, Stylist};
|
||||||
use traversal_flags::TraversalFlags;
|
use traversal_flags::TraversalFlags;
|
||||||
|
|
||||||
/// An opaque handle to a node, which, unlike UnsafeNode, cannot be transformed
|
/// An opaque handle to a node, which, unlike UnsafeNode, cannot be transformed
|
||||||
|
@ -772,12 +772,12 @@ pub trait TElement
|
||||||
fn each_applicable_non_document_style_rule_data<'a, F>(&self, mut f: F) -> bool
|
fn each_applicable_non_document_style_rule_data<'a, F>(&self, mut f: F) -> bool
|
||||||
where
|
where
|
||||||
Self: 'a,
|
Self: 'a,
|
||||||
F: FnMut(AtomicRef<'a, StyleRuleCascadeData>, QuirksMode),
|
F: FnMut(AtomicRef<'a, CascadeData>, QuirksMode),
|
||||||
{
|
{
|
||||||
let cut_off_inheritance = self.each_xbl_stylist(|stylist| {
|
let cut_off_inheritance = self.each_xbl_stylist(|stylist| {
|
||||||
let quirks_mode = stylist.quirks_mode();
|
let quirks_mode = stylist.quirks_mode();
|
||||||
f(
|
f(
|
||||||
AtomicRef::map(stylist, |stylist| stylist.normal_author_cascade_data()),
|
AtomicRef::map(stylist, |stylist| stylist.author_cascade_data()),
|
||||||
quirks_mode,
|
quirks_mode,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -786,12 +786,10 @@ pub trait TElement
|
||||||
while let Some(slot) = current {
|
while let Some(slot) = current {
|
||||||
slot.each_xbl_stylist(|stylist| {
|
slot.each_xbl_stylist(|stylist| {
|
||||||
let quirks_mode = stylist.quirks_mode();
|
let quirks_mode = stylist.quirks_mode();
|
||||||
if stylist.slotted_author_cascade_data().is_some() {
|
|
||||||
f(
|
f(
|
||||||
AtomicRef::map(stylist, |stylist| stylist.slotted_author_cascade_data().unwrap()),
|
AtomicRef::map(stylist, |stylist| stylist.author_cascade_data()),
|
||||||
quirks_mode,
|
quirks_mode,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
current = slot.assigned_slot();
|
current = slot.assigned_slot();
|
||||||
|
|
|
@ -2216,8 +2216,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms_prefix: *mut nsStaticAtom;
|
pub static nsGkAtoms_prefix: *mut nsStaticAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms7preloadE"]
|
#[link_name = "_ZN9nsGkAtoms7preloadE"]
|
||||||
pub static nsGkAtoms_preload: *mut nsStaticAtom;
|
pub static nsGkAtoms_preload: *mut nsStaticAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms11prerenderedE"]
|
|
||||||
pub static nsGkAtoms_prerendered: *mut nsStaticAtom;
|
|
||||||
#[link_name = "_ZN9nsGkAtoms15mozpresentationE"]
|
#[link_name = "_ZN9nsGkAtoms15mozpresentationE"]
|
||||||
pub static nsGkAtoms_mozpresentation: *mut nsStaticAtom;
|
pub static nsGkAtoms_mozpresentation: *mut nsStaticAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms8preserveE"]
|
#[link_name = "_ZN9nsGkAtoms8preserveE"]
|
||||||
|
@ -7391,8 +7389,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms_prefix: *mut nsStaticAtom;
|
pub static nsGkAtoms_prefix: *mut nsStaticAtom;
|
||||||
#[link_name = "?preload@nsGkAtoms@@2PEAVnsStaticAtom@@EA"]
|
#[link_name = "?preload@nsGkAtoms@@2PEAVnsStaticAtom@@EA"]
|
||||||
pub static nsGkAtoms_preload: *mut nsStaticAtom;
|
pub static nsGkAtoms_preload: *mut nsStaticAtom;
|
||||||
#[link_name = "?prerendered@nsGkAtoms@@2PEAVnsStaticAtom@@EA"]
|
|
||||||
pub static nsGkAtoms_prerendered: *mut nsStaticAtom;
|
|
||||||
#[link_name = "?mozpresentation@nsGkAtoms@@2PEAVnsStaticAtom@@EA"]
|
#[link_name = "?mozpresentation@nsGkAtoms@@2PEAVnsStaticAtom@@EA"]
|
||||||
pub static nsGkAtoms_mozpresentation: *mut nsStaticAtom;
|
pub static nsGkAtoms_mozpresentation: *mut nsStaticAtom;
|
||||||
#[link_name = "?preserve@nsGkAtoms@@2PEAVnsStaticAtom@@EA"]
|
#[link_name = "?preserve@nsGkAtoms@@2PEAVnsStaticAtom@@EA"]
|
||||||
|
@ -12566,8 +12562,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms_prefix: *mut nsStaticAtom;
|
pub static nsGkAtoms_prefix: *mut nsStaticAtom;
|
||||||
#[link_name = "\x01?preload@nsGkAtoms@@2PAVnsStaticAtom@@A"]
|
#[link_name = "\x01?preload@nsGkAtoms@@2PAVnsStaticAtom@@A"]
|
||||||
pub static nsGkAtoms_preload: *mut nsStaticAtom;
|
pub static nsGkAtoms_preload: *mut nsStaticAtom;
|
||||||
#[link_name = "\x01?prerendered@nsGkAtoms@@2PAVnsStaticAtom@@A"]
|
|
||||||
pub static nsGkAtoms_prerendered: *mut nsStaticAtom;
|
|
||||||
#[link_name = "\x01?mozpresentation@nsGkAtoms@@2PAVnsStaticAtom@@A"]
|
#[link_name = "\x01?mozpresentation@nsGkAtoms@@2PAVnsStaticAtom@@A"]
|
||||||
pub static nsGkAtoms_mozpresentation: *mut nsStaticAtom;
|
pub static nsGkAtoms_mozpresentation: *mut nsStaticAtom;
|
||||||
#[link_name = "\x01?preserve@nsGkAtoms@@2PAVnsStaticAtom@@A"]
|
#[link_name = "\x01?preserve@nsGkAtoms@@2PAVnsStaticAtom@@A"]
|
||||||
|
@ -17744,8 +17738,6 @@ macro_rules! atom {
|
||||||
{{ #[allow(unsafe_code)] #[allow(unused_unsafe)]unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_prefix as *mut _) } }};
|
{{ #[allow(unsafe_code)] #[allow(unused_unsafe)]unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_prefix as *mut _) } }};
|
||||||
("preload") =>
|
("preload") =>
|
||||||
{{ #[allow(unsafe_code)] #[allow(unused_unsafe)]unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_preload as *mut _) } }};
|
{{ #[allow(unsafe_code)] #[allow(unused_unsafe)]unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_preload as *mut _) } }};
|
||||||
("prerendered") =>
|
|
||||||
{{ #[allow(unsafe_code)] #[allow(unused_unsafe)]unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_prerendered as *mut _) } }};
|
|
||||||
("mozpresentation") =>
|
("mozpresentation") =>
|
||||||
{{ #[allow(unsafe_code)] #[allow(unused_unsafe)]unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_mozpresentation as *mut _) } }};
|
{{ #[allow(unsafe_code)] #[allow(unused_unsafe)]unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_mozpresentation as *mut _) } }};
|
||||||
("preserve") =>
|
("preserve") =>
|
||||||
|
|
|
@ -501,8 +501,6 @@ extern "C" {
|
||||||
pub fn Servo_SourceSizeList_Drop ( ptr : RawServoSourceSizeListOwned , ) ;
|
pub fn Servo_SourceSizeList_Drop ( ptr : RawServoSourceSizeListOwned , ) ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Gecko_RecordTraversalStatistics ( total : u32 , parallel : u32 , total_t : u32 , parallel_t : u32 , total_s : u32 , parallel_s : u32 , ) ;
|
pub fn Gecko_RecordTraversalStatistics ( total : u32 , parallel : u32 , total_t : u32 , parallel_t : u32 , total_s : u32 , parallel_s : u32 , ) ;
|
||||||
} extern "C" {
|
|
||||||
pub fn Gecko_IsInDocument ( node : RawGeckoNodeBorrowed , ) -> bool ;
|
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Gecko_IsSignificantChild ( node : RawGeckoNodeBorrowed , text_is_significant : bool , whitespace_is_significant : bool , ) -> bool ;
|
pub fn Gecko_IsSignificantChild ( node : RawGeckoNodeBorrowed , text_is_significant : bool , whitespace_is_significant : bool , ) -> bool ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
|
@ -753,8 +751,6 @@ extern "C" {
|
||||||
pub fn Gecko_CalcStyleDifference ( old_style : ServoStyleContextBorrowed , new_style : ServoStyleContextBorrowed , any_style_changed : * mut bool , reset_only_changed : * mut bool , ) -> u32 ;
|
pub fn Gecko_CalcStyleDifference ( old_style : ServoStyleContextBorrowed , new_style : ServoStyleContextBorrowed , any_style_changed : * mut bool , reset_only_changed : * mut bool , ) -> u32 ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Gecko_GetElementSnapshot ( table : * const ServoElementSnapshotTable , element : RawGeckoElementBorrowed , ) -> * const ServoElementSnapshot ;
|
pub fn Gecko_GetElementSnapshot ( table : * const ServoElementSnapshotTable , element : RawGeckoElementBorrowed , ) -> * const ServoElementSnapshot ;
|
||||||
} extern "C" {
|
|
||||||
pub fn Gecko_DropElementSnapshot ( snapshot : ServoElementSnapshotOwned , ) ;
|
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Gecko_HaveSeenPtr ( table : * mut SeenPtrs , ptr : * const :: std :: os :: raw :: c_void , ) -> bool ;
|
pub fn Gecko_HaveSeenPtr ( table : * mut SeenPtrs , ptr : * const :: std :: os :: raw :: c_void , ) -> bool ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
|
@ -977,8 +973,6 @@ extern "C" {
|
||||||
pub fn Gecko_IsDocumentBody ( element : RawGeckoElementBorrowed , ) -> bool ;
|
pub fn Gecko_IsDocumentBody ( element : RawGeckoElementBorrowed , ) -> bool ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Gecko_GetLookAndFeelSystemColor ( color_id : i32 , pres_context : RawGeckoPresContextBorrowed , ) -> nscolor ;
|
pub fn Gecko_GetLookAndFeelSystemColor ( color_id : i32 , pres_context : RawGeckoPresContextBorrowed , ) -> nscolor ;
|
||||||
} extern "C" {
|
|
||||||
pub fn Gecko_MatchStringArgPseudo ( element : RawGeckoElementBorrowed , type_ : CSSPseudoClassType , ident : * const u16 , ) -> bool ;
|
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Gecko_AddPropertyToSet ( arg1 : nsCSSPropertyIDSetBorrowedMut , arg2 : nsCSSPropertyID , ) ;
|
pub fn Gecko_AddPropertyToSet ( arg1 : nsCSSPropertyIDSetBorrowedMut , arg2 : nsCSSPropertyID , ) ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
|
@ -1157,6 +1151,8 @@ extern "C" {
|
||||||
pub fn Servo_Element_IsDisplayNone ( element : RawGeckoElementBorrowed , ) -> bool ;
|
pub fn Servo_Element_IsDisplayNone ( element : RawGeckoElementBorrowed , ) -> bool ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Servo_Element_IsPrimaryStyleReusedViaRuleNode ( element : RawGeckoElementBorrowed , ) -> bool ;
|
pub fn Servo_Element_IsPrimaryStyleReusedViaRuleNode ( element : RawGeckoElementBorrowed , ) -> bool ;
|
||||||
|
} extern "C" {
|
||||||
|
pub fn Servo_InvalidateStyleForDocStateChanges ( root : RawGeckoElementBorrowed , sets : * const nsTArray < RawServoStyleSetBorrowed > , aStatesChanged : u64 , ) ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Servo_StyleSheet_FromUTF8Bytes ( loader : * mut Loader , gecko_stylesheet : * mut ServoStyleSheet , data : * const u8 , data_len : usize , parsing_mode : SheetParsingMode , extra_data : * mut RawGeckoURLExtraData , line_number_offset : u32 , quirks_mode : nsCompatibility , reusable_sheets : * mut LoaderReusableStyleSheets , ) -> RawServoStyleSheetContentsStrong ;
|
pub fn Servo_StyleSheet_FromUTF8Bytes ( loader : * mut Loader , gecko_stylesheet : * mut ServoStyleSheet , data : * const u8 , data_len : usize , parsing_mode : SheetParsingMode , extra_data : * mut RawGeckoURLExtraData , line_number_offset : u32 , quirks_mode : nsCompatibility , reusable_sheets : * mut LoaderReusableStyleSheets , ) -> RawServoStyleSheetContentsStrong ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -684,9 +684,11 @@ impl Expression {
|
||||||
pub fn matches(&self, device: &Device, quirks_mode: QuirksMode) -> bool {
|
pub fn matches(&self, device: &Device, quirks_mode: QuirksMode) -> bool {
|
||||||
let mut css_value = nsCSSValue::null();
|
let mut css_value = nsCSSValue::null();
|
||||||
unsafe {
|
unsafe {
|
||||||
(self.feature.mGetter.unwrap())(device.pres_context,
|
(self.feature.mGetter.unwrap())(
|
||||||
|
device.pres_context().mDocument.raw::<structs::nsIDocument>(),
|
||||||
self.feature,
|
self.feature,
|
||||||
&mut css_value)
|
&mut css_value,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let value = match MediaExpressionValue::from_css_value(self, &css_value) {
|
let value = match MediaExpressionValue::from_css_value(self, &css_value) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ use invalidation::element::invalidator::{DescendantInvalidationLists, Invalidati
|
||||||
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor};
|
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor};
|
||||||
use invalidation::element::state_and_attributes;
|
use invalidation::element::state_and_attributes;
|
||||||
use selectors::matching::{MatchingContext, MatchingMode, QuirksMode, VisitedHandlingMode};
|
use selectors::matching::{MatchingContext, MatchingMode, QuirksMode, VisitedHandlingMode};
|
||||||
use stylist::StyleRuleCascadeData;
|
use stylist::CascadeData;
|
||||||
|
|
||||||
/// A struct holding the members necessary to invalidate document state
|
/// A struct holding the members necessary to invalidate document state
|
||||||
/// selectors.
|
/// selectors.
|
||||||
|
@ -30,20 +30,20 @@ impl Default for InvalidationMatchingData {
|
||||||
|
|
||||||
/// An invalidation processor for style changes due to state and attribute
|
/// An invalidation processor for style changes due to state and attribute
|
||||||
/// changes.
|
/// changes.
|
||||||
pub struct DocumentStateInvalidationProcessor<'a, E: TElement> {
|
pub struct DocumentStateInvalidationProcessor<'a, E: TElement, I> {
|
||||||
// TODO(emilio): We might want to just run everything for every possible
|
// TODO(emilio): We might want to just run everything for every possible
|
||||||
// binding along with the document data, or just apply the XBL stuff to the
|
// binding along with the document data, or just apply the XBL stuff to the
|
||||||
// bound subtrees.
|
// bound subtrees.
|
||||||
rules: &'a StyleRuleCascadeData,
|
rules: I,
|
||||||
matching_context: MatchingContext<'a, E::Impl>,
|
matching_context: MatchingContext<'a, E::Impl>,
|
||||||
document_states_changed: DocumentState,
|
document_states_changed: DocumentState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E: TElement> DocumentStateInvalidationProcessor<'a, E> {
|
impl<'a, E: TElement, I> DocumentStateInvalidationProcessor<'a, E, I> {
|
||||||
/// Creates a new DocumentStateInvalidationProcessor.
|
/// Creates a new DocumentStateInvalidationProcessor.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
rules: &'a StyleRuleCascadeData,
|
rules: I,
|
||||||
document_states_changed: DocumentState,
|
document_states_changed: DocumentState,
|
||||||
quirks_mode: QuirksMode,
|
quirks_mode: QuirksMode,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -63,7 +63,11 @@ impl<'a, E: TElement> DocumentStateInvalidationProcessor<'a, E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E: TElement> InvalidationProcessor<'a, E> for DocumentStateInvalidationProcessor<'a, E> {
|
impl<'a, E, I> InvalidationProcessor<'a, E> for DocumentStateInvalidationProcessor<'a, E, I>
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
I: Iterator<Item = &'a CascadeData>,
|
||||||
|
{
|
||||||
fn collect_invalidations(
|
fn collect_invalidations(
|
||||||
&mut self,
|
&mut self,
|
||||||
_element: E,
|
_element: E,
|
||||||
|
@ -71,8 +75,8 @@ impl<'a, E: TElement> InvalidationProcessor<'a, E> for DocumentStateInvalidation
|
||||||
_descendant_invalidations: &mut DescendantInvalidationLists<'a>,
|
_descendant_invalidations: &mut DescendantInvalidationLists<'a>,
|
||||||
_sibling_invalidations: &mut InvalidationVector<'a>,
|
_sibling_invalidations: &mut InvalidationVector<'a>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let map = self.rules.invalidation_map();
|
for cascade_data in &mut self.rules {
|
||||||
|
let map = cascade_data.invalidation_map();
|
||||||
for dependency in &map.document_state_selectors {
|
for dependency in &map.document_state_selectors {
|
||||||
if !dependency.state.intersects(self.document_states_changed) {
|
if !dependency.state.intersects(self.document_states_changed) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -80,6 +84,7 @@ impl<'a, E: TElement> InvalidationProcessor<'a, E> for DocumentStateInvalidation
|
||||||
|
|
||||||
self_invalidations.push(Invalidation::new(&dependency.selector, 0));
|
self_invalidations.push(Invalidation::new(&dependency.selector, 0));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
|
@ -534,6 +534,20 @@ where
|
||||||
|
|
||||||
let mut any_descendant = false;
|
let mut any_descendant = false;
|
||||||
|
|
||||||
|
// NOTE(emilio): This should not be needed for Shadow DOM for normal
|
||||||
|
// element state / attribute invalidations (it's needed for XBL though,
|
||||||
|
// due to the weird way the anon content there works (it doesn't block
|
||||||
|
// combinators)).
|
||||||
|
//
|
||||||
|
// However, it's needed as of right now for document state invalidation,
|
||||||
|
// were we rely on iterating every element that ends up in the composed
|
||||||
|
// doc.
|
||||||
|
//
|
||||||
|
// Also, we could avoid having that special-case for document state
|
||||||
|
// invalidations if we invalidate for document state changes per
|
||||||
|
// subtree, though that's kind of annoying because we need to invalidate
|
||||||
|
// the shadow host subtree (to handle :host and ::slotted), and the
|
||||||
|
// actual shadow tree (to handle all other rules in the ShadowRoot).
|
||||||
if let Some(anon_content) = self.element.xbl_binding_anonymous_content() {
|
if let Some(anon_content) = self.element.xbl_binding_anonymous_content() {
|
||||||
any_descendant |=
|
any_descendant |=
|
||||||
self.invalidate_dom_descendants_of(anon_content, invalidations);
|
self.invalidate_dom_descendants_of(anon_content, invalidations);
|
||||||
|
|
|
@ -24,7 +24,7 @@ use selectors::matching::{MatchingContext, MatchingMode, VisitedHandlingMode};
|
||||||
use selectors::matching::matches_selector;
|
use selectors::matching::matches_selector;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use stylesheets::origin::{Origin, OriginSet};
|
use stylesheets::origin::{Origin, OriginSet};
|
||||||
use stylist::StyleRuleCascadeData;
|
use stylist::CascadeData;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum VisitedDependent {
|
enum VisitedDependent {
|
||||||
|
@ -57,7 +57,7 @@ where
|
||||||
/// changes.
|
/// changes.
|
||||||
pub struct StateAndAttrInvalidationProcessor<'a, 'b: 'a, E: TElement> {
|
pub struct StateAndAttrInvalidationProcessor<'a, 'b: 'a, E: TElement> {
|
||||||
shared_context: &'a SharedStyleContext<'b>,
|
shared_context: &'a SharedStyleContext<'b>,
|
||||||
shadow_rule_datas: &'a [(AtomicRef<'b, StyleRuleCascadeData>, QuirksMode)],
|
shadow_rule_datas: &'a [(AtomicRef<'b, CascadeData>, QuirksMode)],
|
||||||
cut_off_inheritance: bool,
|
cut_off_inheritance: bool,
|
||||||
element: E,
|
element: E,
|
||||||
data: &'a mut ElementData,
|
data: &'a mut ElementData,
|
||||||
|
@ -68,7 +68,7 @@ impl<'a, 'b: 'a, E: TElement> StateAndAttrInvalidationProcessor<'a, 'b, E> {
|
||||||
/// Creates a new StateAndAttrInvalidationProcessor.
|
/// Creates a new StateAndAttrInvalidationProcessor.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
shared_context: &'a SharedStyleContext<'b>,
|
shared_context: &'a SharedStyleContext<'b>,
|
||||||
shadow_rule_datas: &'a [(AtomicRef<'b, StyleRuleCascadeData>, QuirksMode)],
|
shadow_rule_datas: &'a [(AtomicRef<'b, CascadeData>, QuirksMode)],
|
||||||
cut_off_inheritance: bool,
|
cut_off_inheritance: bool,
|
||||||
element: E,
|
element: E,
|
||||||
data: &'a mut ElementData,
|
data: &'a mut ElementData,
|
||||||
|
@ -255,11 +255,11 @@ where
|
||||||
OriginSet::all()
|
OriginSet::all()
|
||||||
};
|
};
|
||||||
|
|
||||||
self.shared_context.stylist.each_normal_rule_cascade_data(|cascade_data, origin| {
|
for (cascade_data, origin) in self.shared_context.stylist.iter_origins() {
|
||||||
if document_origins.contains(origin.into()) {
|
if document_origins.contains(origin.into()) {
|
||||||
collector.collect_dependencies_in_invalidation_map(cascade_data.invalidation_map());
|
collector.collect_dependencies_in_invalidation_map(cascade_data.invalidation_map());
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
for &(ref data, quirks_mode) in self.shadow_rule_datas {
|
for &(ref data, quirks_mode) in self.shadow_rule_datas {
|
||||||
// FIXME(emilio): Replace with assert / remove when we figure
|
// FIXME(emilio): Replace with assert / remove when we figure
|
||||||
|
|
|
@ -680,7 +680,36 @@ impl LonghandId {
|
||||||
|
|
||||||
/// Returns true if the property is one that is ignored when document
|
/// Returns true if the property is one that is ignored when document
|
||||||
/// colors are disabled.
|
/// colors are disabled.
|
||||||
fn is_ignored_when_document_colors_disabled(&self) -> bool {
|
fn is_ignored_when_document_colors_disabled(
|
||||||
|
&self,
|
||||||
|
cascade_level: CascadeLevel,
|
||||||
|
pseudo: Option<<&PseudoElement>,
|
||||||
|
) -> bool {
|
||||||
|
let is_ua_or_user_rule = matches!(
|
||||||
|
cascade_level,
|
||||||
|
CascadeLevel::UANormal |
|
||||||
|
CascadeLevel::UserNormal |
|
||||||
|
CascadeLevel::UserImportant |
|
||||||
|
CascadeLevel::UAImportant
|
||||||
|
);
|
||||||
|
|
||||||
|
if is_ua_or_user_rule {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_style_attribute = matches!(
|
||||||
|
cascade_level,
|
||||||
|
CascadeLevel::StyleAttributeNormal |
|
||||||
|
CascadeLevel::StyleAttributeImportant
|
||||||
|
);
|
||||||
|
// Don't override colors on pseudo-element's style attributes. The
|
||||||
|
// background-color on ::-moz-color-swatch is an example. Those are set
|
||||||
|
// as an author style (via the style attribute), but it's pretty
|
||||||
|
// important for it to show up for obvious reasons :)
|
||||||
|
if pseudo.is_some() && is_style_attribute {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
matches!(*self,
|
matches!(*self,
|
||||||
${" | ".join([("LonghandId::" + p.camel_case)
|
${" | ".join([("LonghandId::" + p.camel_case)
|
||||||
for p in data.longhands if p.ignored_when_colors_disabled])}
|
for p in data.longhands if p.ignored_when_colors_disabled])}
|
||||||
|
@ -3383,12 +3412,11 @@ where
|
||||||
// marked as ignored in that mode, unless they come from a UA or
|
// marked as ignored in that mode, unless they come from a UA or
|
||||||
// user style sheet.
|
// user style sheet.
|
||||||
if ignore_colors &&
|
if ignore_colors &&
|
||||||
longhand_id.is_ignored_when_document_colors_disabled() &&
|
longhand_id.is_ignored_when_document_colors_disabled(
|
||||||
!matches!(cascade_level,
|
cascade_level,
|
||||||
CascadeLevel::UANormal |
|
context.builder.pseudo
|
||||||
CascadeLevel::UserNormal |
|
)
|
||||||
CascadeLevel::UserImportant |
|
{
|
||||||
CascadeLevel::UAImportant) {
|
|
||||||
let non_transparent_background = match *declaration {
|
let non_transparent_background = match *declaration {
|
||||||
PropertyDeclaration::BackgroundColor(ref color) => {
|
PropertyDeclaration::BackgroundColor(ref color) => {
|
||||||
// Treat background-color a bit differently. If the specified
|
// Treat background-color a bit differently. If the specified
|
||||||
|
|
|
@ -188,7 +188,8 @@ struct DocumentCascadeData {
|
||||||
per_origin: PerOrigin<()>,
|
per_origin: PerOrigin<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DocumentCascadeDataIter<'a> {
|
/// An iterator over the cascade data of a given document.
|
||||||
|
pub struct DocumentCascadeDataIter<'a> {
|
||||||
iter: PerOriginIter<'a, ()>,
|
iter: PerOriginIter<'a, ()>,
|
||||||
cascade_data: &'a DocumentCascadeData,
|
cascade_data: &'a DocumentCascadeData,
|
||||||
}
|
}
|
||||||
|
@ -436,6 +437,18 @@ impl Stylist {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the cascade data for the author level.
|
||||||
|
#[inline]
|
||||||
|
pub fn author_cascade_data(&self) -> &CascadeData {
|
||||||
|
&self.cascade_data.author
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate through all the cascade datas from the document.
|
||||||
|
#[inline]
|
||||||
|
pub fn iter_origins(&self) -> DocumentCascadeDataIter {
|
||||||
|
self.cascade_data.iter_origins()
|
||||||
|
}
|
||||||
|
|
||||||
/// Iterate over the extra data in origin order.
|
/// Iterate over the extra data in origin order.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn iter_extra_data_origins(&self) -> ExtraStyleDataIterator {
|
pub fn iter_extra_data_origins(&self) -> ExtraStyleDataIterator {
|
||||||
|
@ -466,30 +479,22 @@ impl Stylist {
|
||||||
/// Returns the number of revalidation_selectors.
|
/// Returns the number of revalidation_selectors.
|
||||||
pub fn num_revalidation_selectors(&self) -> usize {
|
pub fn num_revalidation_selectors(&self) -> usize {
|
||||||
self.cascade_data.iter_origins()
|
self.cascade_data.iter_origins()
|
||||||
.map(|(data, _)| {
|
.map(|(data, _)| data.selectors_for_cache_revalidation.len())
|
||||||
data.normal_rule_data.selectors_for_cache_revalidation.len() +
|
.sum()
|
||||||
data.slotted_rule_data.as_ref().map_or(0, |d| {
|
|
||||||
d.selectors_for_cache_revalidation.len()
|
|
||||||
})
|
|
||||||
}).sum()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of entries in invalidation maps.
|
/// Returns the number of entries in invalidation maps.
|
||||||
pub fn num_invalidations(&self) -> usize {
|
pub fn num_invalidations(&self) -> usize {
|
||||||
self.cascade_data.iter_origins()
|
self.cascade_data.iter_origins()
|
||||||
.map(|(data, _)| {
|
.map(|(data, _)| data.invalidation_map.len())
|
||||||
data.normal_rule_data.invalidation_map.len() +
|
.sum()
|
||||||
data.slotted_rule_data.as_ref().map_or(0, |d| d.invalidation_map.len())
|
|
||||||
}).sum()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the given DocumentState bit is relied upon by a selector
|
/// Returns whether the given DocumentState bit is relied upon by a selector
|
||||||
/// of some rule.
|
/// of some rule.
|
||||||
pub fn has_document_state_dependency(&self, state: DocumentState) -> bool {
|
pub fn has_document_state_dependency(&self, state: DocumentState) -> bool {
|
||||||
self.cascade_data.iter_origins()
|
self.cascade_data.iter_origins()
|
||||||
.any(|(d, _)| {
|
.any(|(d, _)| d.document_state_dependencies.intersects(state))
|
||||||
d.normal_rule_data.has_document_state_dependency(state)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flush the list of stylesheets if they changed, ensuring the stylist is
|
/// Flush the list of stylesheets if they changed, ensuring the stylist is
|
||||||
|
@ -605,24 +610,14 @@ impl Stylist {
|
||||||
self.stylesheets.remove_stylesheet(Some(&self.device), sheet, guard)
|
self.stylesheets.remove_stylesheet(Some(&self.device), sheet, guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes `f` on each of the normal rule cascade datas in this styleset.
|
|
||||||
pub fn each_normal_rule_cascade_data<'a, F>(&'a self, mut f: F)
|
|
||||||
where
|
|
||||||
F: FnMut(&'a StyleRuleCascadeData, Origin),
|
|
||||||
{
|
|
||||||
for (data, origin) in self.cascade_data.iter_origins() {
|
|
||||||
f(&data.normal_rule_data, origin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns whether for any of the applicable style rule data a given
|
/// Returns whether for any of the applicable style rule data a given
|
||||||
/// condition is true.
|
/// condition is true.
|
||||||
pub fn any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool
|
pub fn any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool
|
||||||
where
|
where
|
||||||
E: TElement,
|
E: TElement,
|
||||||
F: FnMut(&StyleRuleCascadeData, QuirksMode) -> bool,
|
F: FnMut(&CascadeData, QuirksMode) -> bool,
|
||||||
{
|
{
|
||||||
if f(&self.cascade_data.user_agent.cascade_data.normal_rule_data, self.quirks_mode()) {
|
if f(&self.cascade_data.user_agent.cascade_data, self.quirks_mode()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,8 +631,8 @@ impl Stylist {
|
||||||
return maybe;
|
return maybe;
|
||||||
}
|
}
|
||||||
|
|
||||||
f(&self.cascade_data.author.normal_rule_data, self.quirks_mode()) ||
|
f(&self.cascade_data.author, self.quirks_mode()) ||
|
||||||
f(&self.cascade_data.user.normal_rule_data, self.quirks_mode())
|
f(&self.cascade_data.user, self.quirks_mode())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the style for a given "precomputed" pseudo-element, taking the
|
/// Computes the style for a given "precomputed" pseudo-element, taking the
|
||||||
|
@ -1446,18 +1441,6 @@ impl Stylist {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the cascade data for the normal rules.
|
|
||||||
#[inline]
|
|
||||||
pub fn normal_author_cascade_data(&self) -> &StyleRuleCascadeData {
|
|
||||||
&self.cascade_data.author.normal_rule_data
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the cascade data for the slotted rules in this scope, if any.
|
|
||||||
#[inline]
|
|
||||||
pub fn slotted_author_cascade_data(&self) -> Option<&StyleRuleCascadeData> {
|
|
||||||
self.cascade_data.author.slotted_rule_data.as_ref().map(|d| &**d)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the registered `@keyframes` animation for the specified name.
|
/// Returns the registered `@keyframes` animation for the specified name.
|
||||||
///
|
///
|
||||||
/// FIXME(emilio): This needs to account for the element rules.
|
/// FIXME(emilio): This needs to account for the element rules.
|
||||||
|
@ -1498,7 +1481,7 @@ impl Stylist {
|
||||||
// this in the caller by asserting that the bitvecs are same-length.
|
// this in the caller by asserting that the bitvecs are same-length.
|
||||||
let mut results = SmallBitVec::new();
|
let mut results = SmallBitVec::new();
|
||||||
for (data, _) in self.cascade_data.iter_origins() {
|
for (data, _) in self.cascade_data.iter_origins() {
|
||||||
data.normal_rule_data.selectors_for_cache_revalidation.lookup(
|
data.selectors_for_cache_revalidation.lookup(
|
||||||
element,
|
element,
|
||||||
self.quirks_mode,
|
self.quirks_mode,
|
||||||
|selector_and_hashes| {
|
|selector_and_hashes| {
|
||||||
|
@ -1918,7 +1901,7 @@ impl ElementAndPseudoRules {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn borrow_for_pseudo(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
fn rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
||||||
match pseudo {
|
match pseudo {
|
||||||
Some(pseudo) => self.pseudos_map.get(&pseudo.canonical()).map(|p| &**p),
|
Some(pseudo) => self.pseudos_map.get(&pseudo.canonical()).map(|p| &**p),
|
||||||
None => Some(&self.element_map),
|
None => Some(&self.element_map),
|
||||||
|
@ -1938,12 +1921,26 @@ impl ElementAndPseudoRules {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cascade data generated from style rules.
|
/// Data resulting from performing the CSS cascade that is specific to a given
|
||||||
#[derive(Debug)]
|
/// origin.
|
||||||
|
///
|
||||||
|
/// FIXME(emilio): Consider renaming and splitting in `CascadeData` and
|
||||||
|
/// `InvalidationData`? That'd make `clear_cascade_data()` clearer.
|
||||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
||||||
pub struct StyleRuleCascadeData {
|
#[derive(Debug)]
|
||||||
/// The actual style rules.
|
pub struct CascadeData {
|
||||||
rules: ElementAndPseudoRules,
|
/// The data coming from normal style rules that apply to elements at this
|
||||||
|
/// cascade level.
|
||||||
|
normal_rules: ElementAndPseudoRules,
|
||||||
|
|
||||||
|
/// The data coming from ::slotted() pseudo-element rules.
|
||||||
|
///
|
||||||
|
/// We need to store them separately because an element needs to match
|
||||||
|
/// ::slotted() pseudo-element rules in different shadow roots.
|
||||||
|
///
|
||||||
|
/// In particular, we need to go through all the style data in all the
|
||||||
|
/// containing style scopes starting from the closest assigned slot.
|
||||||
|
slotted_rules: Option<Box<ElementAndPseudoRules>>,
|
||||||
|
|
||||||
/// The invalidation map for these rules.
|
/// The invalidation map for these rules.
|
||||||
invalidation_map: InvalidationMap,
|
invalidation_map: InvalidationMap,
|
||||||
|
@ -1985,142 +1982,6 @@ pub struct StyleRuleCascadeData {
|
||||||
/// tree-structural state like child index and pseudos).
|
/// tree-structural state like child index and pseudos).
|
||||||
#[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
|
#[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
|
||||||
selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
|
selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
|
||||||
}
|
|
||||||
|
|
||||||
impl StyleRuleCascadeData {
|
|
||||||
#[inline(always)]
|
|
||||||
fn insert(
|
|
||||||
&mut self,
|
|
||||||
rule: Rule,
|
|
||||||
pseudo_element: Option<&PseudoElement>,
|
|
||||||
quirks_mode: QuirksMode,
|
|
||||||
rebuild_kind: SheetRebuildKind,
|
|
||||||
) -> Result<(), FailedAllocationError> {
|
|
||||||
if rebuild_kind.should_rebuild_invalidation() {
|
|
||||||
self.invalidation_map.note_selector(&rule.selector, quirks_mode)?;
|
|
||||||
let mut visitor = StylistSelectorVisitor {
|
|
||||||
needs_revalidation: false,
|
|
||||||
passed_rightmost_selector: false,
|
|
||||||
attribute_dependencies: &mut self.attribute_dependencies,
|
|
||||||
style_attribute_dependency: &mut self.style_attribute_dependency,
|
|
||||||
state_dependencies: &mut self.state_dependencies,
|
|
||||||
document_state_dependencies: &mut self.document_state_dependencies,
|
|
||||||
mapped_ids: &mut self.mapped_ids,
|
|
||||||
};
|
|
||||||
|
|
||||||
rule.selector.visit(&mut visitor);
|
|
||||||
|
|
||||||
if visitor.needs_revalidation {
|
|
||||||
self.selectors_for_cache_revalidation.insert(
|
|
||||||
RevalidationSelectorAndHashes::new(
|
|
||||||
rule.selector.clone(),
|
|
||||||
rule.hashes.clone(),
|
|
||||||
),
|
|
||||||
quirks_mode
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.rules.insert(rule, pseudo_element, quirks_mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the invalidation map.
|
|
||||||
#[inline]
|
|
||||||
pub fn invalidation_map(&self) -> &InvalidationMap {
|
|
||||||
&self.invalidation_map
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
|
|
||||||
self.rules.add_size_of(ops, sizes);
|
|
||||||
sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
|
|
||||||
sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear_cascade_data(&mut self) {
|
|
||||||
self.rules.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear(&mut self) {
|
|
||||||
self.clear_cascade_data();
|
|
||||||
self.invalidation_map.clear();
|
|
||||||
self.attribute_dependencies.clear();
|
|
||||||
self.style_attribute_dependency = false;
|
|
||||||
self.state_dependencies = ElementState::empty();
|
|
||||||
self.document_state_dependencies = DocumentState::empty();
|
|
||||||
self.mapped_ids.clear();
|
|
||||||
self.selectors_for_cache_revalidation.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns whether the given attribute might appear in an attribute
|
|
||||||
/// selector of some rule.
|
|
||||||
#[inline]
|
|
||||||
pub fn might_have_attribute_dependency(
|
|
||||||
&self,
|
|
||||||
local_name: &LocalName,
|
|
||||||
) -> bool {
|
|
||||||
if *local_name == local_name!("style") {
|
|
||||||
return self.style_attribute_dependency
|
|
||||||
}
|
|
||||||
|
|
||||||
self.attribute_dependencies.might_contain_hash(local_name.get_hash())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns whether the given ElementState bit is relied upon by a selector
|
|
||||||
/// of some rule.
|
|
||||||
#[inline]
|
|
||||||
pub fn has_state_dependency(&self, state: ElementState) -> bool {
|
|
||||||
self.state_dependencies.intersects(state)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns whether the given DocumentState bit is relied upon by a selector
|
|
||||||
/// of some rule in the stylist.
|
|
||||||
#[inline]
|
|
||||||
fn has_document_state_dependency(&self, state: DocumentState) -> bool {
|
|
||||||
self.document_state_dependencies.intersects(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StyleRuleCascadeData {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
rules: ElementAndPseudoRules::default(),
|
|
||||||
invalidation_map: InvalidationMap::new(),
|
|
||||||
attribute_dependencies: NonCountingBloomFilter::new(),
|
|
||||||
style_attribute_dependency: false,
|
|
||||||
state_dependencies: ElementState::empty(),
|
|
||||||
document_state_dependencies: DocumentState::empty(),
|
|
||||||
mapped_ids: NonCountingBloomFilter::new(),
|
|
||||||
selectors_for_cache_revalidation: SelectorMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
|
||||||
self.rules.borrow_for_pseudo(pseudo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Data resulting from performing the CSS cascade that is specific to a given
|
|
||||||
/// origin.
|
|
||||||
///
|
|
||||||
/// FIXME(emilio): Consider renaming and splitting in `CascadeData` and
|
|
||||||
/// `InvalidationData`? That'd make `clear_cascade_data()` clearer.
|
|
||||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct CascadeData {
|
|
||||||
/// The data coming from normal style rules that apply to elements at this
|
|
||||||
/// cascade level.
|
|
||||||
normal_rule_data: StyleRuleCascadeData,
|
|
||||||
|
|
||||||
/// The data coming from ::slotted() pseudo-element rules.
|
|
||||||
///
|
|
||||||
/// We need to store them separately because an element needs to match
|
|
||||||
/// ::slotted() pseudo-element rules in different shadow roots.
|
|
||||||
///
|
|
||||||
/// In particular, we need to go through all the style data in all the
|
|
||||||
/// containing style scopes starting from the closest assigned slot.
|
|
||||||
slotted_rule_data: Option<Box<StyleRuleCascadeData>>,
|
|
||||||
|
|
||||||
/// A map with all the animations at this `CascadeData`'s origin, indexed
|
/// A map with all the animations at this `CascadeData`'s origin, indexed
|
||||||
/// by name.
|
/// by name.
|
||||||
|
@ -2146,8 +2007,15 @@ struct CascadeData {
|
||||||
impl CascadeData {
|
impl CascadeData {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
normal_rule_data: StyleRuleCascadeData::new(),
|
normal_rules: ElementAndPseudoRules::default(),
|
||||||
slotted_rule_data: None,
|
slotted_rules: None,
|
||||||
|
invalidation_map: InvalidationMap::new(),
|
||||||
|
attribute_dependencies: NonCountingBloomFilter::new(),
|
||||||
|
style_attribute_dependency: false,
|
||||||
|
state_dependencies: ElementState::empty(),
|
||||||
|
document_state_dependencies: DocumentState::empty(),
|
||||||
|
mapped_ids: NonCountingBloomFilter::new(),
|
||||||
|
selectors_for_cache_revalidation: SelectorMap::new(),
|
||||||
animations: Default::default(),
|
animations: Default::default(),
|
||||||
extra_data: ExtraStyleData::default(),
|
extra_data: ExtraStyleData::default(),
|
||||||
effective_media_query_results: EffectiveMediaQueryResults::new(),
|
effective_media_query_results: EffectiveMediaQueryResults::new(),
|
||||||
|
@ -2157,14 +2025,39 @@ impl CascadeData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the invalidation map.
|
||||||
|
pub fn invalidation_map(&self) -> &InvalidationMap {
|
||||||
|
&self.invalidation_map
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether the given ElementState bit is relied upon by a selector
|
||||||
|
/// of some rule.
|
||||||
|
#[inline]
|
||||||
|
pub fn has_state_dependency(&self, state: ElementState) -> bool {
|
||||||
|
self.state_dependencies.intersects(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether the given attribute might appear in an attribute
|
||||||
|
/// selector of some rule.
|
||||||
|
#[inline]
|
||||||
|
pub fn might_have_attribute_dependency(
|
||||||
|
&self,
|
||||||
|
local_name: &LocalName,
|
||||||
|
) -> bool {
|
||||||
|
if *local_name == local_name!("style") {
|
||||||
|
return self.style_attribute_dependency
|
||||||
|
}
|
||||||
|
|
||||||
|
self.attribute_dependencies.might_contain_hash(local_name.get_hash())
|
||||||
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn normal_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
fn normal_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
||||||
self.normal_rule_data.rules(pseudo)
|
self.normal_rules.rules(pseudo)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn slotted_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
fn slotted_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
||||||
self.slotted_rule_data.as_ref().and_then(|d| d.rules(pseudo))
|
self.slotted_rules.as_ref().and_then(|d| d.rules(pseudo))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collects all the applicable media query results into `results`.
|
/// Collects all the applicable media query results into `results`.
|
||||||
|
@ -2270,19 +2163,43 @@ impl CascadeData {
|
||||||
self.rules_source_order
|
self.rules_source_order
|
||||||
);
|
);
|
||||||
|
|
||||||
let style_rule_cascade_data = if selector.is_slotted() {
|
if rebuild_kind.should_rebuild_invalidation() {
|
||||||
self.slotted_rule_data.get_or_insert_with(|| {
|
self.invalidation_map.note_selector(&rule.selector, quirks_mode)?;
|
||||||
Box::new(StyleRuleCascadeData::new())
|
let mut visitor = StylistSelectorVisitor {
|
||||||
})
|
needs_revalidation: false,
|
||||||
} else {
|
passed_rightmost_selector: false,
|
||||||
&mut self.normal_rule_data
|
attribute_dependencies: &mut self.attribute_dependencies,
|
||||||
|
style_attribute_dependency: &mut self.style_attribute_dependency,
|
||||||
|
state_dependencies: &mut self.state_dependencies,
|
||||||
|
document_state_dependencies: &mut self.document_state_dependencies,
|
||||||
|
mapped_ids: &mut self.mapped_ids,
|
||||||
};
|
};
|
||||||
|
|
||||||
style_rule_cascade_data.insert(
|
rule.selector.visit(&mut visitor);
|
||||||
|
|
||||||
|
if visitor.needs_revalidation {
|
||||||
|
self.selectors_for_cache_revalidation.insert(
|
||||||
|
RevalidationSelectorAndHashes::new(
|
||||||
|
rule.selector.clone(),
|
||||||
|
rule.hashes.clone(),
|
||||||
|
),
|
||||||
|
quirks_mode
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let rules = if selector.is_slotted() {
|
||||||
|
self.slotted_rules.get_or_insert_with(|| {
|
||||||
|
Box::new(Default::default())
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
&mut self.normal_rules
|
||||||
|
};
|
||||||
|
|
||||||
|
rules.insert(
|
||||||
rule,
|
rule,
|
||||||
pseudo_element,
|
pseudo_element,
|
||||||
quirks_mode,
|
quirks_mode,
|
||||||
rebuild_kind,
|
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
self.rules_source_order += 1;
|
self.rules_source_order += 1;
|
||||||
|
@ -2435,9 +2352,9 @@ impl CascadeData {
|
||||||
|
|
||||||
/// Clears the cascade data, but not the invalidation data.
|
/// Clears the cascade data, but not the invalidation data.
|
||||||
fn clear_cascade_data(&mut self) {
|
fn clear_cascade_data(&mut self) {
|
||||||
self.normal_rule_data.clear_cascade_data();
|
self.normal_rules.clear();
|
||||||
if let Some(ref mut slotted_rule_data) = self.slotted_rule_data {
|
if let Some(ref mut slotted_rules) = self.slotted_rules {
|
||||||
slotted_rule_data.clear_cascade_data();
|
slotted_rules.clear();
|
||||||
}
|
}
|
||||||
self.animations.clear();
|
self.animations.clear();
|
||||||
self.extra_data.clear();
|
self.extra_data.clear();
|
||||||
|
@ -2448,20 +2365,25 @@ impl CascadeData {
|
||||||
|
|
||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
self.clear_cascade_data();
|
self.clear_cascade_data();
|
||||||
self.normal_rule_data.clear();
|
self.invalidation_map.clear();
|
||||||
if let Some(ref mut slotted_rule_data) = self.slotted_rule_data {
|
self.attribute_dependencies.clear();
|
||||||
slotted_rule_data.clear();
|
self.style_attribute_dependency = false;
|
||||||
}
|
self.state_dependencies = ElementState::empty();
|
||||||
|
self.document_state_dependencies = DocumentState::empty();
|
||||||
|
self.mapped_ids.clear();
|
||||||
|
self.selectors_for_cache_revalidation.clear();
|
||||||
self.effective_media_query_results.clear();
|
self.effective_media_query_results.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Measures heap usage.
|
/// Measures heap usage.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
|
fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
|
||||||
self.normal_rule_data.add_size_of(ops, sizes);
|
self.normal_rules.add_size_of(ops, sizes);
|
||||||
if let Some(ref slotted_rules) = self.slotted_rule_data {
|
if let Some(ref slotted_rules) = self.slotted_rules {
|
||||||
slotted_rules.add_size_of(ops, sizes);
|
slotted_rules.add_size_of(ops, sizes);
|
||||||
}
|
}
|
||||||
|
sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
|
||||||
|
sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
|
||||||
sizes.mOther += self.animations.size_of(ops);
|
sizes.mOther += self.animations.size_of(ops);
|
||||||
sizes.mOther += self.effective_media_query_results.size_of(ops);
|
sizes.mOther += self.effective_media_query_results.size_of(ops);
|
||||||
sizes.mOther += self.extra_data.size_of(ops);
|
sizes.mOther += self.extra_data.size_of(ops);
|
||||||
|
|
|
@ -9,6 +9,7 @@ use malloc_size_of::MallocSizeOfOps;
|
||||||
use selectors::{Element, NthIndexCache};
|
use selectors::{Element, NthIndexCache};
|
||||||
use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
|
use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
|
||||||
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
|
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
@ -1774,7 +1775,6 @@ pub unsafe extern "C" fn Servo_SelectorList_QueryAll(
|
||||||
content_list: *mut structs::nsSimpleContentList,
|
content_list: *mut structs::nsSimpleContentList,
|
||||||
may_use_invalidation: bool,
|
may_use_invalidation: bool,
|
||||||
) {
|
) {
|
||||||
use smallvec::SmallVec;
|
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use style::dom_apis::{self, MayUseInvalidation, QueryAll};
|
use style::dom_apis::{self, MayUseInvalidation, QueryAll};
|
||||||
|
|
||||||
|
@ -2391,10 +2391,10 @@ pub extern "C" fn Servo_ComputedValues_EqualCustomProperties(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(values: ServoStyleContextBorrowed,
|
pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(
|
||||||
rules: RawGeckoServoStyleRuleListBorrowedMut) {
|
values: ServoStyleContextBorrowed,
|
||||||
use smallvec::SmallVec;
|
rules: RawGeckoServoStyleRuleListBorrowedMut,
|
||||||
|
) {
|
||||||
let rule_node = match values.rules {
|
let rule_node = match values.rules {
|
||||||
Some(ref r) => r,
|
Some(ref r) => r,
|
||||||
None => return,
|
None => return,
|
||||||
|
@ -4930,6 +4930,40 @@ pub extern "C" fn Servo_ParseCounterStyleName(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Servo_InvalidateStyleForDocStateChanges(
|
||||||
|
root: RawGeckoElementBorrowed,
|
||||||
|
raw_style_sets: *const nsTArray<RawServoStyleSetBorrowed>,
|
||||||
|
states_changed: u64,
|
||||||
|
) {
|
||||||
|
use style::invalidation::element::document_state::DocumentStateInvalidationProcessor;
|
||||||
|
use style::invalidation::element::invalidator::TreeStyleInvalidator;
|
||||||
|
|
||||||
|
let mut borrows = SmallVec::<[_; 20]>::with_capacity((*raw_style_sets).len());
|
||||||
|
for style_set in &**raw_style_sets {
|
||||||
|
borrows.push(PerDocumentStyleData::from_ffi(*style_set).borrow());
|
||||||
|
}
|
||||||
|
let root = GeckoElement(root);
|
||||||
|
let mut processor = DocumentStateInvalidationProcessor::new(
|
||||||
|
borrows.iter().flat_map(|b| b.stylist.iter_origins().map(|(data, _origin)| data)),
|
||||||
|
DocumentState::from_bits_truncate(states_changed),
|
||||||
|
root.as_node().owner_doc().quirks_mode(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = TreeStyleInvalidator::new(
|
||||||
|
root,
|
||||||
|
/* stack_limit_checker = */ None,
|
||||||
|
&mut processor,
|
||||||
|
).invalidate();
|
||||||
|
|
||||||
|
debug_assert!(!result.has_invalidated_siblings(), "How in the world?");
|
||||||
|
if result.has_invalidated_descendants() {
|
||||||
|
bindings::Gecko_NoteDirtySubtreeForInvalidation(root.0);
|
||||||
|
} else if result.has_invalidated_self() {
|
||||||
|
bindings::Gecko_NoteDirtyElement(root.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_ParseCounterStyleDescriptor(
|
pub extern "C" fn Servo_ParseCounterStyleDescriptor(
|
||||||
descriptor: nsCSSCounterDesc,
|
descriptor: nsCSSCounterDesc,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue