1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! The pseudo-classes and pseudo-elements supported by the style system.
use matching::{common_style_affecting_attributes, CommonStyleAffectingAttributeMode};
use selectors::Element;
use selectors::parser::{AttrSelector, SelectorImpl};
pub type AttrValue = <TheSelectorImpl as SelectorImpl>::AttrValue;
#[cfg(feature = "servo")]
pub use servo::selector_parser::*;
#[cfg(feature = "gecko")]
pub use gecko::selector_parser::*;
#[cfg(feature = "servo")]
pub use servo::selector_parser::ServoSelectorImpl as TheSelectorImpl;
#[cfg(feature = "gecko")]
pub use gecko::selector_parser::GeckoSelectorImpl as TheSelectorImpl;
#[cfg(feature = "servo")]
pub use servo::selector_parser::ServoElementSnapshot as Snapshot;
#[cfg(feature = "gecko")]
pub use gecko::snapshot::GeckoElementSnapshot as Snapshot;
#[cfg(feature = "servo")]
pub use servo::restyle_damage::ServoRestyleDamage as RestyleDamage;
#[cfg(feature = "gecko")]
pub use gecko::restyle_damage::GeckoRestyleDamage as RestyleDamage;
/// This function determines if a pseudo-element is eagerly cascaded or not.
///
/// Eagerly cascaded pseudo-elements are "normal" pseudo-elements (i.e.
/// `::before` and `::after`). They inherit styles normally as another
/// selector would do, and they're part of the cascade.
///
/// Lazy pseudo-elements are affected by selector matching, but they're only
/// computed when needed, and not before. They're useful for general
/// pseudo-elements that are not very common.
///
/// Note that in Servo lazy pseudo-elements are restricted to a subset of
/// selectors, so you can't use it for public pseudo-elements. This is not the
/// case with Gecko though.
///
/// Precomputed ones skip the cascade process entirely, mostly as an
/// optimisation since they are private pseudo-elements (like
/// `::-servo-details-content`).
///
/// This pseudo-elements are resolved on the fly using *only* global rules
/// (rules of the form `*|*`), and applying them to the parent style.
///
/// If you're implementing a public selector that the end-user might customize,
/// then you probably need to make it eager.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PseudoElementCascadeType {
Eager,
Lazy,
Precomputed,
}
impl PseudoElementCascadeType {
#[inline]
pub fn is_eager(&self) -> bool {
*self == PseudoElementCascadeType::Eager
}
#[inline]
pub fn is_lazy(&self) -> bool {
*self == PseudoElementCascadeType::Lazy
}
#[inline]
pub fn is_precomputed(&self) -> bool {
*self == PseudoElementCascadeType::Precomputed
}
}
pub trait ElementExt: Element<Impl=TheSelectorImpl> {
fn is_link(&self) -> bool;
}
impl TheSelectorImpl {
#[inline]
pub fn each_eagerly_cascaded_pseudo_element<F>(mut fun: F)
where F: FnMut(PseudoElement)
{
Self::each_pseudo_element(|pseudo| {
if Self::pseudo_element_cascade_type(&pseudo).is_eager() {
fun(pseudo)
}
})
}
#[inline]
pub fn each_precomputed_pseudo_element<F>(mut fun: F)
where F: FnMut(PseudoElement)
{
Self::each_pseudo_element(|pseudo| {
if Self::pseudo_element_cascade_type(&pseudo).is_precomputed() {
fun(pseudo)
}
})
}
}
pub fn attr_exists_selector_is_shareable(attr_selector: &AttrSelector<TheSelectorImpl>) -> bool {
// NB(pcwalton): If you update this, remember to update the corresponding list in
// `can_share_style_with()` as well.
common_style_affecting_attributes().iter().any(|common_attr_info| {
common_attr_info.attr_name == attr_selector.name && match common_attr_info.mode {
CommonStyleAffectingAttributeMode::IsPresent(_) => true,
CommonStyleAffectingAttributeMode::IsEqual(..) => false,
}
})
}
pub fn attr_equals_selector_is_shareable(attr_selector: &AttrSelector<TheSelectorImpl>,
value: &AttrValue) -> bool {
// FIXME(pcwalton): Remove once we start actually supporting RTL text. This is in
// here because the UA style otherwise disables all style sharing completely.
// FIXME(SimonSapin): should this be the attribute *name* rather than value?
atom!("dir") == *value ||
common_style_affecting_attributes().iter().any(|common_attr_info| {
common_attr_info.attr_name == attr_selector.name && match common_attr_info.mode {
CommonStyleAffectingAttributeMode::IsEqual(ref target_value, _) => {
*target_value == *value
}
CommonStyleAffectingAttributeMode::IsPresent(_) => false,
}
})
}
|