зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #17318 - stylo: Fix pseudo element matching for XBL stylesheets (Bug 1371577) (from aethanyc:fix-pseudo-xbl-stylesheet); r=emilio
This change is reviewed in https://bugzilla.mozilla.org/show_bug.cgi?id=1371577#c9 Source-Repo: https://github.com/servo/servo Source-Revision: 5dce166266d1f74e2ae88dbe52ca5ced75c2349b --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : c36859edd46fdd90296b4a89ba5dd9f8f9d9eb0c
This commit is contained in:
Родитель
219252fd4b
Коммит
4133c4eec0
|
@ -573,7 +573,8 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
|
||||||
|
|
||||||
/// Gets declarations from XBL bindings from the element. Only gecko element could have this.
|
/// Gets declarations from XBL bindings from the element. Only gecko element could have this.
|
||||||
fn get_declarations_from_xbl_bindings<V>(&self,
|
fn get_declarations_from_xbl_bindings<V>(&self,
|
||||||
_: &mut V)
|
_pseudo_element: Option<&PseudoElement>,
|
||||||
|
_applicable_declarations: &mut V)
|
||||||
-> bool
|
-> bool
|
||||||
where V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock> {
|
where V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock> {
|
||||||
false
|
false
|
||||||
|
|
|
@ -382,17 +382,19 @@ impl<'lb> GeckoXBLBinding<'lb> {
|
||||||
// Implements Gecko's nsXBLBinding::WalkRules().
|
// Implements Gecko's nsXBLBinding::WalkRules().
|
||||||
fn get_declarations_for<E, V>(&self,
|
fn get_declarations_for<E, V>(&self,
|
||||||
element: &E,
|
element: &E,
|
||||||
|
pseudo_element: Option<&PseudoElement>,
|
||||||
applicable_declarations: &mut V)
|
applicable_declarations: &mut V)
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock> {
|
V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock> {
|
||||||
if let Some(base_binding) = self.base_binding() {
|
if let Some(base_binding) = self.base_binding() {
|
||||||
base_binding.get_declarations_for(element, applicable_declarations);
|
base_binding.get_declarations_for(element, pseudo_element, applicable_declarations);
|
||||||
}
|
}
|
||||||
|
|
||||||
let raw_data = unsafe { bindings::Gecko_XBLBinding_GetRawServoStyleSet(self.0) };
|
let raw_data = unsafe { bindings::Gecko_XBLBinding_GetRawServoStyleSet(self.0) };
|
||||||
if let Some(raw_data) = raw_data {
|
if let Some(raw_data) = raw_data {
|
||||||
let data = PerDocumentStyleData::from_ffi(&*raw_data).borrow();
|
let data = PerDocumentStyleData::from_ffi(&*raw_data).borrow();
|
||||||
data.stylist.push_applicable_declarations_as_xbl_only_stylist(element,
|
data.stylist.push_applicable_declarations_as_xbl_only_stylist(element,
|
||||||
|
pseudo_element,
|
||||||
applicable_declarations);
|
applicable_declarations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -942,6 +944,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
// Implements Gecko's nsBindingManager::WalkRules(). Returns whether to cut off the
|
// Implements Gecko's nsBindingManager::WalkRules(). Returns whether to cut off the
|
||||||
// inheritance.
|
// inheritance.
|
||||||
fn get_declarations_from_xbl_bindings<V>(&self,
|
fn get_declarations_from_xbl_bindings<V>(&self,
|
||||||
|
pseudo_element: Option<&PseudoElement>,
|
||||||
applicable_declarations: &mut V)
|
applicable_declarations: &mut V)
|
||||||
-> bool
|
-> bool
|
||||||
where V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock> {
|
where V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock> {
|
||||||
|
@ -951,7 +954,9 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
|
|
||||||
while let Some(element) = current {
|
while let Some(element) = current {
|
||||||
if let Some(binding) = element.get_xbl_binding() {
|
if let Some(binding) = element.get_xbl_binding() {
|
||||||
binding.get_declarations_for(self, applicable_declarations);
|
binding.get_declarations_for(self,
|
||||||
|
pseudo_element,
|
||||||
|
applicable_declarations);
|
||||||
|
|
||||||
// If we're not looking at our original element, allow the binding to cut off
|
// If we're not looking at our original element, allow the binding to cut off
|
||||||
// style inheritance.
|
// style inheritance.
|
||||||
|
|
|
@ -933,10 +933,38 @@ impl Stylist {
|
||||||
self.quirks_mode = quirks_mode;
|
self.quirks_mode = quirks_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the correspond PerPseudoElementSelectorMap given PseudoElement.
|
||||||
|
fn get_map(&self,
|
||||||
|
pseudo_element: Option<&PseudoElement>) -> Option<&PerPseudoElementSelectorMap>
|
||||||
|
{
|
||||||
|
match pseudo_element {
|
||||||
|
Some(pseudo) => self.pseudos_map.get(pseudo),
|
||||||
|
None => Some(&self.element_map),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the rule hash target given an element.
|
||||||
|
fn rule_hash_target<E>(&self, element: E) -> E
|
||||||
|
where E: TElement
|
||||||
|
{
|
||||||
|
let is_implemented_pseudo =
|
||||||
|
element.implemented_pseudo_element().is_some();
|
||||||
|
|
||||||
|
// NB: This causes use to rule has pseudo selectors based on the
|
||||||
|
// properties of the originating element (which is fine, given the
|
||||||
|
// find_first_from_right usage).
|
||||||
|
if is_implemented_pseudo {
|
||||||
|
element.closest_non_native_anonymous_ancestor().unwrap()
|
||||||
|
} else {
|
||||||
|
element
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the applicable CSS declarations for the given element by
|
/// Returns the applicable CSS declarations for the given element by
|
||||||
/// treating us as an XBL stylesheet-only stylist.
|
/// treating us as an XBL stylesheet-only stylist.
|
||||||
pub fn push_applicable_declarations_as_xbl_only_stylist<E, V>(&self,
|
pub fn push_applicable_declarations_as_xbl_only_stylist<E, V>(&self,
|
||||||
element: &E,
|
element: &E,
|
||||||
|
pseudo_element: Option<&PseudoElement>,
|
||||||
applicable_declarations: &mut V)
|
applicable_declarations: &mut V)
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock>,
|
V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock>,
|
||||||
|
@ -945,13 +973,21 @@ impl Stylist {
|
||||||
MatchingContext::new(MatchingMode::Normal, None, self.quirks_mode);
|
MatchingContext::new(MatchingMode::Normal, None, self.quirks_mode);
|
||||||
let mut dummy_flag_setter = |_: &E, _: ElementSelectorFlags| {};
|
let mut dummy_flag_setter = |_: &E, _: ElementSelectorFlags| {};
|
||||||
|
|
||||||
self.element_map.author.get_all_matching_rules(element,
|
let map = match self.get_map(pseudo_element) {
|
||||||
element,
|
Some(map) => map,
|
||||||
applicable_declarations,
|
None => return,
|
||||||
&mut matching_context,
|
};
|
||||||
self.quirks_mode,
|
let rule_hash_target = self.rule_hash_target(*element);
|
||||||
&mut dummy_flag_setter,
|
|
||||||
CascadeLevel::XBL);
|
// nsXBLPrototypeResources::ComputeServoStyleSet() added XBL stylesheets under author
|
||||||
|
// (doc) level.
|
||||||
|
map.author.get_all_matching_rules(element,
|
||||||
|
&rule_hash_target,
|
||||||
|
applicable_declarations,
|
||||||
|
&mut matching_context,
|
||||||
|
self.quirks_mode,
|
||||||
|
&mut dummy_flag_setter,
|
||||||
|
CascadeLevel::XBL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the applicable CSS declarations for the given element.
|
/// Returns the applicable CSS declarations for the given element.
|
||||||
|
@ -983,22 +1019,11 @@ impl Stylist {
|
||||||
"Style attributes do not apply to pseudo-elements");
|
"Style attributes do not apply to pseudo-elements");
|
||||||
debug_assert!(pseudo_element.map_or(true, |p| !p.is_precomputed()));
|
debug_assert!(pseudo_element.map_or(true, |p| !p.is_precomputed()));
|
||||||
|
|
||||||
let map = match pseudo_element {
|
let map = match self.get_map(pseudo_element) {
|
||||||
Some(pseudo) => self.pseudos_map.get(pseudo).unwrap(),
|
Some(map) => map,
|
||||||
None => &self.element_map,
|
None => return,
|
||||||
};
|
|
||||||
|
|
||||||
let is_implemented_pseudo =
|
|
||||||
element.implemented_pseudo_element().is_some();
|
|
||||||
|
|
||||||
// NB: This causes use to rule has pseudo selectors based on the
|
|
||||||
// properties of the originating element (which is fine, given the
|
|
||||||
// find_first_from_right usage).
|
|
||||||
let rule_hash_target = if is_implemented_pseudo {
|
|
||||||
element.closest_non_native_anonymous_ancestor().unwrap()
|
|
||||||
} else {
|
|
||||||
*element
|
|
||||||
};
|
};
|
||||||
|
let rule_hash_target = self.rule_hash_target(*element);
|
||||||
|
|
||||||
debug!("Determining if style is shareable: pseudo: {}",
|
debug!("Determining if style is shareable: pseudo: {}",
|
||||||
pseudo_element.is_some());
|
pseudo_element.is_some());
|
||||||
|
@ -1060,7 +1085,8 @@ impl Stylist {
|
||||||
|
|
||||||
// Step 3b: XBL rules.
|
// Step 3b: XBL rules.
|
||||||
let cut_off_inheritance =
|
let cut_off_inheritance =
|
||||||
rule_hash_target.get_declarations_from_xbl_bindings(applicable_declarations);
|
rule_hash_target.get_declarations_from_xbl_bindings(pseudo_element,
|
||||||
|
applicable_declarations);
|
||||||
debug!("XBL: {:?}", context.relations);
|
debug!("XBL: {:?}", context.relations);
|
||||||
|
|
||||||
if rule_hash_target.matches_user_and_author_rules() && !only_default_rules {
|
if rule_hash_target.matches_user_and_author_rules() && !only_default_rules {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче