зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #19790 - style: Work from multiple bugs (from emilio:fix-all-the-bugs); r=heycam,xidorn
Bug: 1429846,1429248,1430608,1409672 Reviewed-by: xidorn,heycam Source-Repo: https://github.com/servo/servo Source-Revision: 7d685d4baa0b107e3dd95eeba8076bfb9e07ba0e --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 3a5287b8cba06111d931ce0d4c9ac8b346bed8c0
This commit is contained in:
Родитель
817545f74a
Коммит
3b5da0d9e2
|
@ -31,7 +31,7 @@ use std::fmt;
|
|||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::ops::Deref;
|
||||
use stylist::{StyleRuleCascadeData, Stylist};
|
||||
use stylist::{CascadeData, Stylist};
|
||||
use traversal_flags::TraversalFlags;
|
||||
|
||||
/// 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
|
||||
where
|
||||
Self: 'a,
|
||||
F: FnMut(AtomicRef<'a, StyleRuleCascadeData>, QuirksMode),
|
||||
F: FnMut(AtomicRef<'a, CascadeData>, QuirksMode),
|
||||
{
|
||||
let cut_off_inheritance = self.each_xbl_stylist(|stylist| {
|
||||
let quirks_mode = stylist.quirks_mode();
|
||||
f(
|
||||
AtomicRef::map(stylist, |stylist| stylist.normal_author_cascade_data()),
|
||||
AtomicRef::map(stylist, |stylist| stylist.author_cascade_data()),
|
||||
quirks_mode,
|
||||
)
|
||||
});
|
||||
|
@ -786,12 +786,10 @@ pub trait TElement
|
|||
while let Some(slot) = current {
|
||||
slot.each_xbl_stylist(|stylist| {
|
||||
let quirks_mode = stylist.quirks_mode();
|
||||
if stylist.slotted_author_cascade_data().is_some() {
|
||||
f(
|
||||
AtomicRef::map(stylist, |stylist| stylist.slotted_author_cascade_data().unwrap()),
|
||||
quirks_mode,
|
||||
)
|
||||
}
|
||||
f(
|
||||
AtomicRef::map(stylist, |stylist| stylist.author_cascade_data()),
|
||||
quirks_mode,
|
||||
)
|
||||
});
|
||||
|
||||
current = slot.assigned_slot();
|
||||
|
|
|
@ -2216,8 +2216,6 @@ cfg_if! {
|
|||
pub static nsGkAtoms_prefix: *mut nsStaticAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms7preloadE"]
|
||||
pub static nsGkAtoms_preload: *mut nsStaticAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms11prerenderedE"]
|
||||
pub static nsGkAtoms_prerendered: *mut nsStaticAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms15mozpresentationE"]
|
||||
pub static nsGkAtoms_mozpresentation: *mut nsStaticAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms8preserveE"]
|
||||
|
@ -7391,8 +7389,6 @@ cfg_if! {
|
|||
pub static nsGkAtoms_prefix: *mut nsStaticAtom;
|
||||
#[link_name = "?preload@nsGkAtoms@@2PEAVnsStaticAtom@@EA"]
|
||||
pub static nsGkAtoms_preload: *mut nsStaticAtom;
|
||||
#[link_name = "?prerendered@nsGkAtoms@@2PEAVnsStaticAtom@@EA"]
|
||||
pub static nsGkAtoms_prerendered: *mut nsStaticAtom;
|
||||
#[link_name = "?mozpresentation@nsGkAtoms@@2PEAVnsStaticAtom@@EA"]
|
||||
pub static nsGkAtoms_mozpresentation: *mut nsStaticAtom;
|
||||
#[link_name = "?preserve@nsGkAtoms@@2PEAVnsStaticAtom@@EA"]
|
||||
|
@ -12566,8 +12562,6 @@ cfg_if! {
|
|||
pub static nsGkAtoms_prefix: *mut nsStaticAtom;
|
||||
#[link_name = "\x01?preload@nsGkAtoms@@2PAVnsStaticAtom@@A"]
|
||||
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"]
|
||||
pub static nsGkAtoms_mozpresentation: *mut nsStaticAtom;
|
||||
#[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 _) } }};
|
||||
("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 _) } }};
|
||||
("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") =>
|
||||
{{ #[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") =>
|
||||
|
|
|
@ -501,8 +501,6 @@ extern "C" {
|
|||
pub fn Servo_SourceSizeList_Drop ( ptr : RawServoSourceSizeListOwned , ) ;
|
||||
} extern "C" {
|
||||
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" {
|
||||
pub fn Gecko_IsSignificantChild ( node : RawGeckoNodeBorrowed , text_is_significant : bool , whitespace_is_significant : bool , ) -> bool ;
|
||||
} 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 ;
|
||||
} extern "C" {
|
||||
pub fn Gecko_GetElementSnapshot ( table : * const ServoElementSnapshotTable , element : RawGeckoElementBorrowed , ) -> * const ServoElementSnapshot ;
|
||||
} extern "C" {
|
||||
pub fn Gecko_DropElementSnapshot ( snapshot : ServoElementSnapshotOwned , ) ;
|
||||
} extern "C" {
|
||||
pub fn Gecko_HaveSeenPtr ( table : * mut SeenPtrs , ptr : * const :: std :: os :: raw :: c_void , ) -> bool ;
|
||||
} extern "C" {
|
||||
|
@ -977,8 +973,6 @@ extern "C" {
|
|||
pub fn Gecko_IsDocumentBody ( element : RawGeckoElementBorrowed , ) -> bool ;
|
||||
} extern "C" {
|
||||
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" {
|
||||
pub fn Gecko_AddPropertyToSet ( arg1 : nsCSSPropertyIDSetBorrowedMut , arg2 : nsCSSPropertyID , ) ;
|
||||
} extern "C" {
|
||||
|
@ -1157,6 +1151,8 @@ extern "C" {
|
|||
pub fn Servo_Element_IsDisplayNone ( element : RawGeckoElementBorrowed , ) -> bool ;
|
||||
} extern "C" {
|
||||
pub fn Servo_Element_IsPrimaryStyleReusedViaRuleNode ( element : RawGeckoElementBorrowed , ) -> bool ;
|
||||
} extern "C" {
|
||||
pub fn Servo_InvalidateStyleForDocStateChanges ( root : RawGeckoElementBorrowed , sets : * const nsTArray < RawServoStyleSetBorrowed > , aStatesChanged : u64 , ) ;
|
||||
} 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 ;
|
||||
} extern "C" {
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -684,9 +684,11 @@ impl Expression {
|
|||
pub fn matches(&self, device: &Device, quirks_mode: QuirksMode) -> bool {
|
||||
let mut css_value = nsCSSValue::null();
|
||||
unsafe {
|
||||
(self.feature.mGetter.unwrap())(device.pres_context,
|
||||
self.feature,
|
||||
&mut css_value)
|
||||
(self.feature.mGetter.unwrap())(
|
||||
device.pres_context().mDocument.raw::<structs::nsIDocument>(),
|
||||
self.feature,
|
||||
&mut 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::state_and_attributes;
|
||||
use selectors::matching::{MatchingContext, MatchingMode, QuirksMode, VisitedHandlingMode};
|
||||
use stylist::StyleRuleCascadeData;
|
||||
use stylist::CascadeData;
|
||||
|
||||
/// A struct holding the members necessary to invalidate document state
|
||||
/// selectors.
|
||||
|
@ -30,20 +30,20 @@ impl Default for InvalidationMatchingData {
|
|||
|
||||
/// An invalidation processor for style changes due to state and attribute
|
||||
/// 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
|
||||
// binding along with the document data, or just apply the XBL stuff to the
|
||||
// bound subtrees.
|
||||
rules: &'a StyleRuleCascadeData,
|
||||
rules: I,
|
||||
matching_context: MatchingContext<'a, E::Impl>,
|
||||
document_states_changed: DocumentState,
|
||||
}
|
||||
|
||||
impl<'a, E: TElement> DocumentStateInvalidationProcessor<'a, E> {
|
||||
impl<'a, E: TElement, I> DocumentStateInvalidationProcessor<'a, E, I> {
|
||||
/// Creates a new DocumentStateInvalidationProcessor.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
rules: &'a StyleRuleCascadeData,
|
||||
rules: I,
|
||||
document_states_changed: DocumentState,
|
||||
quirks_mode: QuirksMode,
|
||||
) -> 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(
|
||||
&mut self,
|
||||
_element: E,
|
||||
|
@ -71,14 +75,15 @@ impl<'a, E: TElement> InvalidationProcessor<'a, E> for DocumentStateInvalidation
|
|||
_descendant_invalidations: &mut DescendantInvalidationLists<'a>,
|
||||
_sibling_invalidations: &mut InvalidationVector<'a>,
|
||||
) -> 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 {
|
||||
if !dependency.state.intersects(self.document_states_changed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for dependency in &map.document_state_selectors {
|
||||
if !dependency.state.intersects(self.document_states_changed) {
|
||||
continue;
|
||||
self_invalidations.push(Invalidation::new(&dependency.selector, 0));
|
||||
}
|
||||
|
||||
self_invalidations.push(Invalidation::new(&dependency.selector, 0));
|
||||
}
|
||||
|
||||
false
|
||||
|
|
|
@ -534,6 +534,20 @@ where
|
|||
|
||||
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() {
|
||||
any_descendant |=
|
||||
self.invalidate_dom_descendants_of(anon_content, invalidations);
|
||||
|
|
|
@ -24,7 +24,7 @@ use selectors::matching::{MatchingContext, MatchingMode, VisitedHandlingMode};
|
|||
use selectors::matching::matches_selector;
|
||||
use smallvec::SmallVec;
|
||||
use stylesheets::origin::{Origin, OriginSet};
|
||||
use stylist::StyleRuleCascadeData;
|
||||
use stylist::CascadeData;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum VisitedDependent {
|
||||
|
@ -57,7 +57,7 @@ where
|
|||
/// changes.
|
||||
pub struct StateAndAttrInvalidationProcessor<'a, 'b: 'a, E: TElement> {
|
||||
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,
|
||||
element: E,
|
||||
data: &'a mut ElementData,
|
||||
|
@ -68,7 +68,7 @@ impl<'a, 'b: 'a, E: TElement> StateAndAttrInvalidationProcessor<'a, 'b, E> {
|
|||
/// Creates a new StateAndAttrInvalidationProcessor.
|
||||
pub fn new(
|
||||
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,
|
||||
element: E,
|
||||
data: &'a mut ElementData,
|
||||
|
@ -255,11 +255,11 @@ where
|
|||
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()) {
|
||||
collector.collect_dependencies_in_invalidation_map(cascade_data.invalidation_map());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for &(ref data, quirks_mode) in self.shadow_rule_datas {
|
||||
// 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
|
||||
/// 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,
|
||||
${" | ".join([("LonghandId::" + p.camel_case)
|
||||
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
|
||||
// user style sheet.
|
||||
if ignore_colors &&
|
||||
longhand_id.is_ignored_when_document_colors_disabled() &&
|
||||
!matches!(cascade_level,
|
||||
CascadeLevel::UANormal |
|
||||
CascadeLevel::UserNormal |
|
||||
CascadeLevel::UserImportant |
|
||||
CascadeLevel::UAImportant) {
|
||||
longhand_id.is_ignored_when_document_colors_disabled(
|
||||
cascade_level,
|
||||
context.builder.pseudo
|
||||
)
|
||||
{
|
||||
let non_transparent_background = match *declaration {
|
||||
PropertyDeclaration::BackgroundColor(ref color) => {
|
||||
// Treat background-color a bit differently. If the specified
|
||||
|
|
|
@ -188,7 +188,8 @@ struct DocumentCascadeData {
|
|||
per_origin: PerOrigin<()>,
|
||||
}
|
||||
|
||||
struct DocumentCascadeDataIter<'a> {
|
||||
/// An iterator over the cascade data of a given document.
|
||||
pub struct DocumentCascadeDataIter<'a> {
|
||||
iter: PerOriginIter<'a, ()>,
|
||||
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.
|
||||
#[inline]
|
||||
pub fn iter_extra_data_origins(&self) -> ExtraStyleDataIterator {
|
||||
|
@ -466,30 +479,22 @@ impl Stylist {
|
|||
/// Returns the number of revalidation_selectors.
|
||||
pub fn num_revalidation_selectors(&self) -> usize {
|
||||
self.cascade_data.iter_origins()
|
||||
.map(|(data, _)| {
|
||||
data.normal_rule_data.selectors_for_cache_revalidation.len() +
|
||||
data.slotted_rule_data.as_ref().map_or(0, |d| {
|
||||
d.selectors_for_cache_revalidation.len()
|
||||
})
|
||||
}).sum()
|
||||
.map(|(data, _)| data.selectors_for_cache_revalidation.len())
|
||||
.sum()
|
||||
}
|
||||
|
||||
/// Returns the number of entries in invalidation maps.
|
||||
pub fn num_invalidations(&self) -> usize {
|
||||
self.cascade_data.iter_origins()
|
||||
.map(|(data, _)| {
|
||||
data.normal_rule_data.invalidation_map.len() +
|
||||
data.slotted_rule_data.as_ref().map_or(0, |d| d.invalidation_map.len())
|
||||
}).sum()
|
||||
.map(|(data, _)| data.invalidation_map.len())
|
||||
.sum()
|
||||
}
|
||||
|
||||
/// Returns whether the given DocumentState bit is relied upon by a selector
|
||||
/// of some rule.
|
||||
pub fn has_document_state_dependency(&self, state: DocumentState) -> bool {
|
||||
self.cascade_data.iter_origins()
|
||||
.any(|(d, _)| {
|
||||
d.normal_rule_data.has_document_state_dependency(state)
|
||||
})
|
||||
.any(|(d, _)| d.document_state_dependencies.intersects(state))
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// condition is true.
|
||||
pub fn any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool
|
||||
where
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -636,8 +631,8 @@ impl Stylist {
|
|||
return maybe;
|
||||
}
|
||||
|
||||
f(&self.cascade_data.author.normal_rule_data, self.quirks_mode()) ||
|
||||
f(&self.cascade_data.user.normal_rule_data, self.quirks_mode())
|
||||
f(&self.cascade_data.author, self.quirks_mode()) ||
|
||||
f(&self.cascade_data.user, self.quirks_mode())
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// 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.
|
||||
let mut results = SmallBitVec::new();
|
||||
for (data, _) in self.cascade_data.iter_origins() {
|
||||
data.normal_rule_data.selectors_for_cache_revalidation.lookup(
|
||||
data.selectors_for_cache_revalidation.lookup(
|
||||
element,
|
||||
self.quirks_mode,
|
||||
|selector_and_hashes| {
|
||||
|
@ -1918,7 +1901,7 @@ impl ElementAndPseudoRules {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn borrow_for_pseudo(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
||||
fn rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
||||
match pseudo {
|
||||
Some(pseudo) => self.pseudos_map.get(&pseudo.canonical()).map(|p| &**p),
|
||||
None => Some(&self.element_map),
|
||||
|
@ -1938,12 +1921,26 @@ impl ElementAndPseudoRules {
|
|||
}
|
||||
}
|
||||
|
||||
/// Cascade data generated from style rules.
|
||||
#[derive(Debug)]
|
||||
/// 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))]
|
||||
pub struct StyleRuleCascadeData {
|
||||
/// The actual style rules.
|
||||
rules: ElementAndPseudoRules,
|
||||
#[derive(Debug)]
|
||||
pub struct CascadeData {
|
||||
/// 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.
|
||||
invalidation_map: InvalidationMap,
|
||||
|
@ -1985,142 +1982,6 @@ pub struct StyleRuleCascadeData {
|
|||
/// tree-structural state like child index and pseudos).
|
||||
#[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
|
||||
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
|
||||
/// by name.
|
||||
|
@ -2146,8 +2007,15 @@ struct CascadeData {
|
|||
impl CascadeData {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
normal_rule_data: StyleRuleCascadeData::new(),
|
||||
slotted_rule_data: None,
|
||||
normal_rules: ElementAndPseudoRules::default(),
|
||||
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(),
|
||||
extra_data: ExtraStyleData::default(),
|
||||
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]
|
||||
fn normal_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
||||
self.normal_rule_data.rules(pseudo)
|
||||
self.normal_rules.rules(pseudo)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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`.
|
||||
|
@ -2270,19 +2163,43 @@ impl CascadeData {
|
|||
self.rules_source_order
|
||||
);
|
||||
|
||||
let style_rule_cascade_data = if selector.is_slotted() {
|
||||
self.slotted_rule_data.get_or_insert_with(|| {
|
||||
Box::new(StyleRuleCascadeData::new())
|
||||
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
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
let rules = if selector.is_slotted() {
|
||||
self.slotted_rules.get_or_insert_with(|| {
|
||||
Box::new(Default::default())
|
||||
})
|
||||
} else {
|
||||
&mut self.normal_rule_data
|
||||
&mut self.normal_rules
|
||||
};
|
||||
|
||||
style_rule_cascade_data.insert(
|
||||
rules.insert(
|
||||
rule,
|
||||
pseudo_element,
|
||||
quirks_mode,
|
||||
rebuild_kind,
|
||||
)?;
|
||||
}
|
||||
self.rules_source_order += 1;
|
||||
|
@ -2435,9 +2352,9 @@ impl CascadeData {
|
|||
|
||||
/// Clears the cascade data, but not the invalidation data.
|
||||
fn clear_cascade_data(&mut self) {
|
||||
self.normal_rule_data.clear_cascade_data();
|
||||
if let Some(ref mut slotted_rule_data) = self.slotted_rule_data {
|
||||
slotted_rule_data.clear_cascade_data();
|
||||
self.normal_rules.clear();
|
||||
if let Some(ref mut slotted_rules) = self.slotted_rules {
|
||||
slotted_rules.clear();
|
||||
}
|
||||
self.animations.clear();
|
||||
self.extra_data.clear();
|
||||
|
@ -2448,20 +2365,25 @@ impl CascadeData {
|
|||
|
||||
fn clear(&mut self) {
|
||||
self.clear_cascade_data();
|
||||
self.normal_rule_data.clear();
|
||||
if let Some(ref mut slotted_rule_data) = self.slotted_rule_data {
|
||||
slotted_rule_data.clear();
|
||||
}
|
||||
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();
|
||||
self.effective_media_query_results.clear();
|
||||
}
|
||||
|
||||
/// Measures heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
|
||||
self.normal_rule_data.add_size_of(ops, sizes);
|
||||
if let Some(ref slotted_rules) = self.slotted_rule_data {
|
||||
self.normal_rules.add_size_of(ops, sizes);
|
||||
if let Some(ref slotted_rules) = self.slotted_rules {
|
||||
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.effective_media_query_results.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::matching::{MatchingContext, MatchingMode, matches_selector};
|
||||
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
|
||||
use smallvec::SmallVec;
|
||||
use std::cell::RefCell;
|
||||
use std::env;
|
||||
use std::fmt::Write;
|
||||
|
@ -1774,7 +1775,6 @@ pub unsafe extern "C" fn Servo_SelectorList_QueryAll(
|
|||
content_list: *mut structs::nsSimpleContentList,
|
||||
may_use_invalidation: bool,
|
||||
) {
|
||||
use smallvec::SmallVec;
|
||||
use std::borrow::Borrow;
|
||||
use style::dom_apis::{self, MayUseInvalidation, QueryAll};
|
||||
|
||||
|
@ -2391,10 +2391,10 @@ pub extern "C" fn Servo_ComputedValues_EqualCustomProperties(
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(values: ServoStyleContextBorrowed,
|
||||
rules: RawGeckoServoStyleRuleListBorrowedMut) {
|
||||
use smallvec::SmallVec;
|
||||
|
||||
pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(
|
||||
values: ServoStyleContextBorrowed,
|
||||
rules: RawGeckoServoStyleRuleListBorrowedMut,
|
||||
) {
|
||||
let rule_node = match values.rules {
|
||||
Some(ref r) => r,
|
||||
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]
|
||||
pub extern "C" fn Servo_ParseCounterStyleDescriptor(
|
||||
descriptor: nsCSSCounterDesc,
|
||||
|
|
Загрузка…
Ссылка в новой задаче