Bug 1401825 - Support pseudo-element properly in nsPresContext::HasAuthorSpecifiedRules. r?emilio
MozReview-Commit-ID: Iugvr9DYm2E
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -2248,26 +2248,39 @@ nsPresContext::HasAuthorSpecifiedRules(c
if (auto* geckoStyleContext = aFrame->StyleContext()->GetAsGecko()) {
return
nsRuleNode::HasAuthorSpecifiedRules(geckoStyleContext,
aRuleTypeMask,
UseDocumentColors());
}
Element* elem = aFrame->GetContent()->AsElement();
- MOZ_ASSERT(elem->GetPseudoElementType() ==
- aFrame->StyleContext()->GetPseudoType());
- if (elem->HasServoData()) {
- return Servo_HasAuthorSpecifiedRules(elem,
- aRuleTypeMask,
- UseDocumentColors());
- } else {
+ // We need to handle non-generated content pseudos too, so we use
+ // the parent of generated content pseudo to be consistent.
+ if (elem->GetPseudoElementType() != CSSPseudoElementType::NotPseudo) {
+ MOZ_ASSERT(elem->GetParent(), "Pseudo element has no parent element?");
+ elem = elem->GetParent()->AsElement();
+ }
+ if (MOZ_UNLIKELY(!elem->HasServoData())) {
// Probably shouldn't happen, but does. See bug 1387953
return false;
}
+
+ nsStyleContext* styleContext = aFrame->StyleContext();
+ CSSPseudoElementType pseudoType = styleContext->GetPseudoType();
+ // Anonymous boxes are more complicated, and we just assume that they
+ // cannot have any author-specified rules here.
+ if (pseudoType == CSSPseudoElementType::InheritingAnonBox ||
+ pseudoType == CSSPseudoElementType::NonInheritingAnonBox) {
+ return false;
+ }
+ return Servo_HasAuthorSpecifiedRules(styleContext->AsServo(),
+ elem, pseudoType,
+ aRuleTypeMask,
+ UseDocumentColors());
}
gfxUserFontSet*
nsPresContext::GetUserFontSet(bool aFlushUserFontSet)
{
return mDocument->GetUserFontSet(aFlushUserFontSet);
}
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -582,17 +582,19 @@ SERVO_BINDING_FUNC(Servo_ResolvePseudoSt
mozilla::CSSPseudoElementType pseudo_type,
bool is_probe,
ServoStyleContextBorrowedOrNull inherited_style,
RawServoStyleSetBorrowed set)
SERVO_BINDING_FUNC(Servo_SetExplicitStyle, void,
RawGeckoElementBorrowed element,
ServoStyleContextBorrowed primary_style)
SERVO_BINDING_FUNC(Servo_HasAuthorSpecifiedRules, bool,
+ ServoStyleContextBorrowed style,
RawGeckoElementBorrowed element,
+ mozilla::CSSPseudoElementType pseudo_type,
uint32_t rule_type_mask,
bool author_colors_allowed)
// Resolves style for an element or pseudo-element without processing pending
// restyles first. The Element and its ancestors may be unstyled, have pending
// restyles, or be in a display:none subtree. Styles are cached when possible,
// though caching is not possible within display:none subtrees, and the styles
// may be invalidated by already-scheduled restyles.
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/1401825.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<style>
+::-moz-list-bullet {
+ -moz-appearance: button;
+}
+</style>
+<li></li>
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -225,16 +225,17 @@ load 1400035.html
load 1400325.html
load 1400926.html
load 1400936-1.html
load 1400936-2.html
load 1401256.html
load 1401692.html
load 1401706.html
load 1401801.html
+load 1401825.html
load 1402218-1.html
load 1402366.html
load 1402419.html
load 1402472.html
load 1403028.html
load 1403433.html
load 1403465.html
load 1403592.html
--- a/servo/components/style/gecko/generated/bindings.rs
+++ b/servo/components/style/gecko/generated/bindings.rs
@@ -2939,17 +2939,19 @@ extern "C" {
set: RawServoStyleSetBorrowed)
-> ServoStyleContextStrong;
}
extern "C" {
pub fn Servo_SetExplicitStyle(element: RawGeckoElementBorrowed,
primary_style: ServoStyleContextBorrowed);
}
extern "C" {
- pub fn Servo_HasAuthorSpecifiedRules(element: RawGeckoElementBorrowed,
+ pub fn Servo_HasAuthorSpecifiedRules(style: ServoStyleContextBorrowed,
+ element: RawGeckoElementBorrowed,
+ pseudo_type: CSSPseudoElementType,
rule_type_mask: u32,
author_colors_allowed: bool) -> bool;
}
extern "C" {
pub fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
pseudo_type: CSSPseudoElementType,
rule_inclusion: StyleRuleInclusion,
snapshots:
--- a/servo/components/style/rule_tree/mod.rs
+++ b/servo/components/style/rule_tree/mod.rs
@@ -2,16 +2,18 @@
* 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/. */
#![allow(unsafe_code)]
//! The rule tree.
use applicable_declarations::ApplicableDeclarationList;
+#[cfg(feature = "gecko")]
+use gecko::selector_parser::PseudoElement;
#[cfg(feature = "servo")]
use heapsize::HeapSizeOf;
#[cfg(feature = "gecko")]
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use properties::{Importance, LonghandIdSet, PropertyDeclarationBlock};
use servo_arc::{Arc, ArcBorrow, NonZeroPtrMut};
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
use smallvec::SmallVec;
@@ -1072,16 +1074,17 @@ impl StrongRuleNode {
/// Implementation of `nsRuleNode::HasAuthorSpecifiedRules` for Servo rule
/// nodes.
///
/// Returns true if any properties specified by `rule_type_mask` was set by
/// an author rule.
#[cfg(feature = "gecko")]
pub fn has_author_specified_rules<E>(&self,
mut element: E,
+ mut pseudo: Option<PseudoElement>,
guards: &StylesheetGuards,
rule_type_mask: u32,
author_colors_allowed: bool)
-> bool
where E: ::dom::TElement
{
use gecko_bindings::structs::{NS_AUTHOR_SPECIFIED_BACKGROUND, NS_AUTHOR_SPECIFIED_BORDER};
use gecko_bindings::structs::{NS_AUTHOR_SPECIFIED_PADDING, NS_AUTHOR_SPECIFIED_TEXT_SHADOW};
@@ -1286,24 +1289,30 @@ impl StrongRuleNode {
}
}
}
}
if !have_explicit_ua_inherit { break }
// Continue to the parent element and search for the inherited properties.
- element = match element.inheritance_parent() {
- Some(parent) => parent,
- None => break
- };
+ if let Some(pseudo) = pseudo.take() {
+ if pseudo.inherits_from_default_values() {
+ break;
+ }
+ } else {
+ element = match element.inheritance_parent() {
+ Some(parent) => parent,
+ None => break
+ };
- let parent_data = element.mutate_data().unwrap();
- let parent_rule_node = parent_data.styles.primary().rules().clone();
- element_rule_node = Cow::Owned(parent_rule_node);
+ let parent_data = element.mutate_data().unwrap();
+ let parent_rule_node = parent_data.styles.primary().rules().clone();
+ element_rule_node = Cow::Owned(parent_rule_node);
+ }
properties = inherited_properties;
}
false
}
/// Returns true if there is either animation or transition level rule.
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1858,36 +1858,34 @@ pub extern "C" fn Servo_SetExplicitStyle
// We only support this API for initial styling. There's no reason it couldn't
// work for other things, we just haven't had a reason to do so.
debug_assert!(element.get_data().is_none());
let mut data = unsafe { element.ensure_data() };
data.styles.primary = Some(unsafe { ArcBorrow::from_ref(style) }.clone_arc());
}
#[no_mangle]
-pub extern "C" fn Servo_HasAuthorSpecifiedRules(element: RawGeckoElementBorrowed,
+pub extern "C" fn Servo_HasAuthorSpecifiedRules(style: ServoStyleContextBorrowed,
+ element: RawGeckoElementBorrowed,
+ pseudo_type: CSSPseudoElementType,
rule_type_mask: u32,
author_colors_allowed: bool)
-> bool
{
let element = GeckoElement(element);
-
- let data =
- element.borrow_data()
- .expect("calling Servo_HasAuthorSpecifiedRules on an unstyled element");
-
- let primary_style = data.styles.primary();
+ let pseudo = PseudoElement::from_pseudo_type(pseudo_type);
let guard = (*GLOBAL_STYLE_DATA).shared_lock.read();
let guards = StylesheetGuards::same(&guard);
- primary_style.rules().has_author_specified_rules(element,
- &guards,
- rule_type_mask,
- author_colors_allowed)
+ style.rules().has_author_specified_rules(element,
+ pseudo,
+ &guards,
+ rule_type_mask,
+ author_colors_allowed)
}
fn get_pseudo_style(
guard: &SharedRwLockReadGuard,
element: GeckoElement,
pseudo: &PseudoElement,
rule_inclusion: RuleInclusion,
styles: &ElementStyles,