--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -578,16 +578,23 @@ SERVO_BINDING_FUNC(Servo_ResolveStyle, S
RawGeckoElementBorrowed element,
RawServoStyleSetBorrowed set)
SERVO_BINDING_FUNC(Servo_ResolvePseudoStyle, ServoStyleContextStrong,
RawGeckoElementBorrowed element,
mozilla::CSSPseudoElementType pseudo_type,
bool is_probe,
ServoStyleContextBorrowedOrNull inherited_style,
RawServoStyleSetBorrowed set)
+SERVO_BINDING_FUNC(Servo_ComputedValues_ResolveXULTreePseudoStyle,
+ ServoStyleContextStrong,
+ RawGeckoElementBorrowed element,
+ nsAtom* pseudo_tag,
+ ServoStyleContextBorrowed inherited_style,
+ const mozilla::AtomArray* input_word,
+ 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,
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -4,16 +4,17 @@
* 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/. */
#ifndef mozilla_ServoBindings_h
#define mozilla_ServoBindings_h
#include <stdint.h>
+#include "mozilla/AtomArray.h"
#include "mozilla/ServoTypes.h"
#include "mozilla/ServoBindingTypes.h"
#include "mozilla/ServoElementSnapshot.h"
#include "mozilla/css/SheetParsingMode.h"
#include "mozilla/css/URLMatchingFunction.h"
#include "mozilla/EffectCompositor.h"
#include "mozilla/ComputedTimingFunction.h"
#include "nsChangeHint.h"
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -137,16 +137,17 @@ whitelist-vars = [
"kNameSpaceID_.*",
"kGenericFont_.*",
"kPresContext_.*",
]
whitelist-types = [
"RawGecko.*",
"mozilla::AnimationPropertySegment",
"mozilla::AnonymousCounterStyle",
+ "mozilla::AtomArray",
"mozilla::ComputedTiming",
"mozilla::ComputedTimingFunction",
"mozilla::ComputedTimingFunction::BeforeFlag",
"mozilla::SeenPtrs",
"mozilla::ServoElementSnapshot.*",
"mozilla::ServoStyleContext",
"mozilla::ServoStyleSheetInner",
"mozilla::ServoStyleSetSizes",
@@ -385,16 +386,17 @@ raw-lines = [
whitelist-functions = ["Servo_.*", "Gecko_.*"]
structs-types = [
"mozilla::css::GridTemplateAreasValue",
"mozilla::css::ErrorReporter",
"mozilla::css::ImageValue",
"mozilla::css::URLValue",
"mozilla::css::URLValueData",
"mozilla::AnonymousCounterStyle",
+ "mozilla::AtomArray",
"mozilla::MallocSizeOf",
"mozilla::OriginFlags",
"mozilla::UniquePtr",
"ServoRawOffsetArc",
"nsIContent",
"nsIDocument",
"nsIDocument_DocumentTheme",
"RawGeckoAnimationPropertySegment",
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -696,16 +696,37 @@ ServoStyleSet::ResolveNonInheritingAnony
MOZ_CRASH();
}
#endif
cache = computedValues;
return computedValues.forget();
}
+#ifdef MOZ_XUL
+already_AddRefed<ServoStyleContext>
+ServoStyleSet::ResolveXULTreePseudoStyle(dom::Element* aParentElement,
+ nsICSSAnonBoxPseudo* aPseudoTag,
+ ServoStyleContext* aParentContext,
+ const AtomArray& aInputWord)
+{
+ MOZ_ASSERT(nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag));
+ MOZ_ASSERT(aParentContext);
+ MOZ_ASSERT(!StylistNeedsUpdate());
+
+ return Servo_ComputedValues_ResolveXULTreePseudoStyle(
+ aParentElement,
+ aPseudoTag,
+ aParentContext,
+ &aInputWord,
+ mRawSet.get()
+ ).Consume();
+}
+#endif
+
// manage the set of style sheets in the style set
nsresult
ServoStyleSet::AppendStyleSheet(SheetType aType,
ServoStyleSheet* aSheet)
{
MOZ_ASSERT(aSheet);
MOZ_ASSERT(aSheet->IsApplicable());
MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -2,16 +2,17 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_ServoStyleSet_h
#define mozilla_ServoStyleSet_h
+#include "mozilla/AtomArray.h"
#include "mozilla/EffectCompositor.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/EventStates.h"
#include "mozilla/PostTraversalTask.h"
#include "mozilla/ServoBindingTypes.h"
#include "mozilla/ServoElementSnapshot.h"
#include "mozilla/ServoUtils.h"
#include "mozilla/StyleSheetInlines.h"
@@ -234,16 +235,24 @@ public:
ServoStyleContext* aParentContext);
// Get a style context for an anonymous box that does not inherit style from
// anything. aPseudoTag is the pseudo-tag to use and must be non-null. It
// must be an anon box, and must be a non-inheriting one.
already_AddRefed<ServoStyleContext>
ResolveNonInheritingAnonymousBoxStyle(nsAtom* aPseudoTag);
+#ifdef MOZ_XUL
+ already_AddRefed<ServoStyleContext>
+ ResolveXULTreePseudoStyle(dom::Element* aParentElement,
+ nsICSSAnonBoxPseudo* aPseudoTag,
+ ServoStyleContext* aParentContext,
+ const AtomArray& aInputWord);
+#endif
+
// manage the set of style sheets in the style set
nsresult AppendStyleSheet(SheetType aType, ServoStyleSheet* aSheet);
nsresult PrependStyleSheet(SheetType aType, ServoStyleSheet* aSheet);
nsresult RemoveStyleSheet(SheetType aType, ServoStyleSheet* aSheet);
nsresult ReplaceSheets(SheetType aType,
const nsTArray<RefPtr<ServoStyleSheet>>& aNewSheets);
nsresult InsertStyleSheetBefore(SheetType aType,
ServoStyleSheet* aNewSheet,
--- a/layout/style/StyleSetHandle.h
+++ b/layout/style/StyleSetHandle.h
@@ -2,16 +2,17 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_StyleSetHandle_h
#define mozilla_StyleSetHandle_h
+#include "mozilla/AtomArray.h"
#include "mozilla/EventStates.h"
#include "mozilla/RefPtr.h"
#include "mozilla/ServoTypes.h"
#include "mozilla/SheetType.h"
#include "mozilla/StyleBackendType.h"
#include "mozilla/StyleSheet.h"
#include "nsChangeHint.h"
#include "nsCSSPseudoElements.h"
@@ -24,16 +25,17 @@ namespace dom {
class Element;
class ShadowRoot;
} // namespace dom
} // namespace mozilla
class nsBindingManager;
class nsCSSCounterStyleRule;
struct nsFontFaceRuleContainer;
class nsAtom;
+class nsICSSAnonBoxPseudo;
class nsIContent;
class nsIDocument;
class nsStyleContext;
class nsStyleSet;
class nsPresContext;
class gfxFontFeatureValueSet;
struct TreeMatchContext;
@@ -139,16 +141,23 @@ public:
mozilla::CSSPseudoElementType aType,
nsStyleContext* aParentContext,
dom::Element* aPseudoElement);
inline already_AddRefed<nsStyleContext>
ResolveInheritingAnonymousBoxStyle(nsAtom* aPseudoTag,
nsStyleContext* aParentContext);
inline already_AddRefed<nsStyleContext>
ResolveNonInheritingAnonymousBoxStyle(nsAtom* aPseudoTag);
+#ifdef MOZ_XUL
+ inline already_AddRefed<nsStyleContext>
+ ResolveXULTreePseudoStyle(dom::Element* aParentElement,
+ nsICSSAnonBoxPseudo* aPseudoTag,
+ nsStyleContext* aParentContext,
+ const AtomArray& aInputWord);
+#endif
inline nsresult AppendStyleSheet(SheetType aType, StyleSheet* aSheet);
inline nsresult PrependStyleSheet(SheetType aType, StyleSheet* aSheet);
inline nsresult RemoveStyleSheet(SheetType aType, StyleSheet* aSheet);
inline nsresult ReplaceSheets(SheetType aType,
const nsTArray<RefPtr<StyleSheet>>& aNewSheets);
inline nsresult InsertStyleSheetBefore(SheetType aType,
StyleSheet* aNewSheet,
StyleSheet* aReferenceSheet);
--- a/layout/style/StyleSetHandleInlines.h
+++ b/layout/style/StyleSetHandleInlines.h
@@ -147,16 +147,28 @@ StyleSetHandle::Ptr::ResolveInheritingAn
}
already_AddRefed<nsStyleContext>
StyleSetHandle::Ptr::ResolveNonInheritingAnonymousBoxStyle(nsAtom* aPseudoTag)
{
FORWARD(ResolveNonInheritingAnonymousBoxStyle, (aPseudoTag));
}
+#ifdef MOZ_XUL
+already_AddRefed<nsStyleContext>
+StyleSetHandle::Ptr::ResolveXULTreePseudoStyle(dom::Element* aParentElement,
+ nsICSSAnonBoxPseudo* aPseudoTag,
+ nsStyleContext* aParentContext,
+ const AtomArray& aInputWord)
+{
+ FORWARD_WITH_PARENT(ResolveXULTreePseudoStyle, aParentContext,
+ (aParentElement, aPseudoTag, parent, aInputWord));
+}
+#endif
+
// manage the set of style sheets in the style set
nsresult
StyleSetHandle::Ptr::AppendStyleSheet(SheetType aType, StyleSheet* aSheet)
{
FORWARD_CONCRETE(AppendStyleSheet, (aType, aSheet->AsGecko()),
(aType, aSheet->AsServo()));
}
--- a/layout/xul/tree/nsTreeStyleCache.cpp
+++ b/layout/xul/tree/nsTreeStyleCache.cpp
@@ -74,27 +74,19 @@ nsTreeStyleCache::GetStyleContext(nsPres
// We're in a final state.
// Look up our style context for this state.
nsStyleContext* result = nullptr;
if (mCache) {
result = mCache->GetWeak(currState);
}
if (!result) {
// We missed the cache. Resolve this pseudo-style.
- // XXXheycam ServoStyleSets do not support XUL tree styles.
- RefPtr<nsStyleContext> newResult;
- if (aPresContext->StyleSet()->IsServo()) {
- NS_ERROR("stylo: ServoStyleSets should not support XUL tree styles yet");
- newResult = aPresContext->StyleSet()->
- ResolveStyleForPlaceholder();
- } else {
- newResult = aPresContext->StyleSet()->AsGecko()->
- ResolveXULTreePseudoStyle(aContent->AsElement(), aPseudoElement,
- aContext->AsGecko(), aInputWord);
- }
+ RefPtr<nsStyleContext> newResult = aPresContext->StyleSet()->
+ ResolveXULTreePseudoStyle(aContent->AsElement(),
+ aPseudoElement, aContext, aInputWord);
// Put the style context in our table, transferring the owning reference to the table.
if (!mCache) {
mCache = new StyleContextCache();
}
result = newResult.get();
mCache->Put(currState, newResult.forget());
}
--- a/servo/components/script_layout_interface/wrapper_traits.rs
+++ b/servo/components/script_layout_interface/wrapper_traits.rs
@@ -403,17 +403,18 @@ pub trait ThreadSafeLayoutElement: Clone
context.stylist
.lazily_compute_pseudo_element_style(
&context.guards,
unsafe { &self.unsafe_get() },
&style_pseudo,
RuleInclusion::All,
data.styles.primary(),
/* is_probe = */ false,
- &ServoMetricsProvider)
+ &ServoMetricsProvider,
+ /* matching_func = */ None)
.unwrap()
.clone()
}
}
}
}
}
--- a/servo/components/selectors/context.rs
+++ b/servo/components/selectors/context.rs
@@ -104,16 +104,20 @@ where
/// When this is None, :scope will match the root element.
///
/// See https://drafts.csswg.org/selectors-4/#scope-pseudo
pub scope_element: Option<OpaqueElement>,
/// The current nesting level of selectors that we're matching.
pub nesting_level: usize,
+ /// An optional hook function for checking whether a pseudo-element
+ /// should match when matching_mode is ForStatelessPseudoElement.
+ pub pseudo_element_matching_fn: Option<&'a Fn(&Impl::PseudoElement) -> bool>,
+
quirks_mode: QuirksMode,
classes_and_ids_case_sensitivity: CaseSensitivity,
_impl: ::std::marker::PhantomData<Impl>,
}
impl<'a, Impl> MatchingContext<'a, Impl>
where
Impl: SelectorImpl,
@@ -147,16 +151,17 @@ where
bloom_filter,
visited_handling,
nth_index_cache,
quirks_mode,
relevant_link_found: false,
classes_and_ids_case_sensitivity: quirks_mode.classes_and_ids_case_sensitivity(),
scope_element: None,
nesting_level: 0,
+ pseudo_element_matching_fn: None,
_impl: ::std::marker::PhantomData,
}
}
/// The quirks mode of the document.
#[inline]
pub fn quirks_mode(&self) -> QuirksMode {
self.quirks_mode
--- a/servo/components/selectors/matching.rs
+++ b/servo/components/selectors/matching.rs
@@ -382,19 +382,30 @@ where
E: Element,
F: FnMut(&E, ElementSelectorFlags),
{
// If this is the special pseudo-element mode, consume the ::pseudo-element
// before proceeding, since the caller has already handled that part.
if context.nesting_level == 0 &&
context.matching_mode == MatchingMode::ForStatelessPseudoElement {
// Consume the pseudo.
- let pseudo = iter.next().unwrap();
- debug_assert!(matches!(*pseudo, Component::PseudoElement(..)),
- "Used MatchingMode::ForStatelessPseudoElement in a non-pseudo selector");
+ match *iter.next().unwrap() {
+ Component::PseudoElement(ref pseudo) => {
+ if let Some(ref f) = context.pseudo_element_matching_fn {
+ if !f(pseudo) {
+ return false;
+ }
+ }
+ }
+ _ => {
+ debug_assert!(false,
+ "Used MatchingMode::ForStatelessPseudoElement \
+ in a non-pseudo selector");
+ }
+ }
// The only other parser-allowed Component in this sequence is a state
// class. We just don't match in that case.
if let Some(s) = iter.next() {
debug_assert!(matches!(*s, Component::NonTSPseudoClass(..)),
"Someone messed up pseudo-element parsing");
return false;
}
--- a/servo/components/style/gecko/generated/bindings.rs
+++ b/servo/components/style/gecko/generated/bindings.rs
@@ -10,16 +10,17 @@ pub type ServoStyleContextBorrowedOrNull
pub type ServoComputedDataBorrowed<'a> = &'a ServoComputedData;
pub type RawServoAnimationValueTableBorrowed<'a> = &'a ();
use gecko_bindings::structs::mozilla::css::GridTemplateAreasValue;
use gecko_bindings::structs::mozilla::css::ErrorReporter;
use gecko_bindings::structs::mozilla::css::ImageValue;
use gecko_bindings::structs::mozilla::css::URLValue;
use gecko_bindings::structs::mozilla::css::URLValueData;
use gecko_bindings::structs::mozilla::AnonymousCounterStyle;
+use gecko_bindings::structs::mozilla::AtomArray;
use gecko_bindings::structs::mozilla::MallocSizeOf;
use gecko_bindings::structs::mozilla::OriginFlags;
use gecko_bindings::structs::mozilla::UniquePtr;
use gecko_bindings::structs::ServoRawOffsetArc;
use gecko_bindings::structs::nsIContent;
use gecko_bindings::structs::nsIDocument;
use gecko_bindings::structs::nsIDocument_DocumentTheme;
use gecko_bindings::structs::RawGeckoAnimationPropertySegment;
@@ -2941,16 +2942,29 @@ extern "C" {
pseudo_type: CSSPseudoElementType,
is_probe: bool,
inherited_style:
ServoStyleContextBorrowedOrNull,
set: RawServoStyleSetBorrowed)
-> ServoStyleContextStrong;
}
extern "C" {
+ pub fn Servo_ComputedValues_ResolveXULTreePseudoStyle(element:
+ RawGeckoElementBorrowed,
+ pseudo_tag:
+ *mut nsAtom,
+ inherited_style:
+ ServoStyleContextBorrowed,
+ input_word:
+ *const AtomArray,
+ set:
+ RawServoStyleSetBorrowed)
+ -> ServoStyleContextStrong;
+}
+extern "C" {
pub fn Servo_SetExplicitStyle(element: RawGeckoElementBorrowed,
primary_style: ServoStyleContextBorrowed);
}
extern "C" {
pub fn Servo_HasAuthorSpecifiedRules(style: ServoStyleContextBorrowed,
element: RawGeckoElementBorrowed,
pseudo_type: CSSPseudoElementType,
rule_type_mask: u32,
--- a/servo/components/style/gecko/generated/pseudo_element_definition.rs
+++ b/servo/components/style/gecko/generated/pseudo_element_definition.rs
@@ -1321,16 +1321,58 @@ impl PseudoElement {
return Some(PseudoElement::MozSVGForeignContent);
}
if atom == &atom!(":-moz-svg-text") {
return Some(PseudoElement::MozSVGText);
}
None
}
+ /// Construct a tree pseudo-element from atom and args.
+ #[inline]
+ pub fn from_tree_pseudo_atom(atom: &Atom, args: Box<[Atom]>) -> Option<Self> {
+ if atom == &atom!(":-moz-tree-column") {
+ return Some(PseudoElement::MozTreeColumn(args));
+ }
+ if atom == &atom!(":-moz-tree-row") {
+ return Some(PseudoElement::MozTreeRow(args));
+ }
+ if atom == &atom!(":-moz-tree-separator") {
+ return Some(PseudoElement::MozTreeSeparator(args));
+ }
+ if atom == &atom!(":-moz-tree-cell") {
+ return Some(PseudoElement::MozTreeCell(args));
+ }
+ if atom == &atom!(":-moz-tree-indentation") {
+ return Some(PseudoElement::MozTreeIndentation(args));
+ }
+ if atom == &atom!(":-moz-tree-line") {
+ return Some(PseudoElement::MozTreeLine(args));
+ }
+ if atom == &atom!(":-moz-tree-twisty") {
+ return Some(PseudoElement::MozTreeTwisty(args));
+ }
+ if atom == &atom!(":-moz-tree-image") {
+ return Some(PseudoElement::MozTreeImage(args));
+ }
+ if atom == &atom!(":-moz-tree-cell-text") {
+ return Some(PseudoElement::MozTreeCellText(args));
+ }
+ if atom == &atom!(":-moz-tree-checkbox") {
+ return Some(PseudoElement::MozTreeCheckbox(args));
+ }
+ if atom == &atom!(":-moz-tree-progressmeter") {
+ return Some(PseudoElement::MozTreeProgressmeter(args));
+ }
+ if atom == &atom!(":-moz-tree-drop-feedback") {
+ return Some(PseudoElement::MozTreeDropFeedback(args));
+ }
+ None
+ }
+
/// Constructs an atom from a string of text, and whether we're in a
/// user-agent stylesheet.
///
/// If we're not in a user-agent stylesheet, we will never parse anonymous
/// box pseudo-elements.
///
/// Returns `None` if the pseudo-element is not recognised.
#[inline]
--- a/servo/components/style/gecko/generated/structs.rs
+++ b/servo/components/style/gecko/generated/structs.rs
@@ -4170,16 +4170,17 @@ pub mod root {
#[derive(Debug, Copy, Clone)]
pub struct SupportsWeakPtr {
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ShortcutKeyCandidate {
_unused: [u8; 0],
}
+ pub type AtomArray = root::nsTArray<root::RefPtr<root::nsAtom>>;
/// EventStates is the class used to represent the event states of nsIContent
/// instances. These states are calculated by IntrinsicState() and
/// ContentStatesChanged() has to be called when one of them changes thus
/// informing the layout/style engine of the change.
/// Event states are associated with pseudo-classes.
#[repr(C)]
#[derive(Debug, Copy)]
pub struct EventStates {
@@ -22380,18 +22381,16 @@ pub mod root {
"Alignment of field: " , stringify ! ( nsAttrName ) , "::"
, stringify ! ( mBits ) ));
}
#[repr(C)]
#[derive(Debug)]
pub struct nsAttrValue {
pub mBits: usize,
}
- pub type nsAttrValue_AtomArray =
- root::nsTArray<root::RefPtr<root::nsAtom>>;
pub const nsAttrValue_ValueType_eSVGTypesBegin:
root::nsAttrValue_ValueType =
nsAttrValue_ValueType::eSVGAngle;
pub const nsAttrValue_ValueType_eSVGTypesEnd: root::nsAttrValue_ValueType
=
nsAttrValue_ValueType::eSVGViewBox;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
--- a/servo/components/style/gecko/pseudo_element_definition.mako.rs
+++ b/servo/components/style/gecko/pseudo_element_definition.mako.rs
@@ -198,16 +198,29 @@ impl PseudoElement {
if atom == &atom!("${pseudo.value}") {
return Some(${pseudo_element_variant(pseudo)});
}
% endif
% endfor
None
}
+ /// Construct a tree pseudo-element from atom and args.
+ #[inline]
+ pub fn from_tree_pseudo_atom(atom: &Atom, args: Box<[Atom]>) -> Option<Self> {
+ % for pseudo in PSEUDOS:
+ % if pseudo.is_tree_pseudo_element():
+ if atom == &atom!("${pseudo.value}") {
+ return Some(PseudoElement::${pseudo.capitalized()}(args));
+ }
+ % endif
+ % endfor
+ None
+ }
+
/// Constructs an atom from a string of text, and whether we're in a
/// user-agent stylesheet.
///
/// If we're not in a user-agent stylesheet, we will never parse anonymous
/// box pseudo-elements.
///
/// Returns `None` if the pseudo-element is not recognised.
#[inline]
--- a/servo/components/style/stylist.rs
+++ b/servo/components/style/stylist.rs
@@ -812,23 +812,31 @@ impl Stylist {
pub fn lazily_compute_pseudo_element_style<E>(
&self,
guards: &StylesheetGuards,
element: &E,
pseudo: &PseudoElement,
rule_inclusion: RuleInclusion,
parent_style: &ComputedValues,
is_probe: bool,
- font_metrics: &FontMetricsProvider
+ font_metrics: &FontMetricsProvider,
+ matching_fn: Option<&Fn(&PseudoElement) -> bool>,
) -> Option<Arc<ComputedValues>>
where
E: TElement,
{
let cascade_inputs =
- self.lazy_pseudo_rules(guards, element, pseudo, is_probe, rule_inclusion);
+ self.lazy_pseudo_rules(
+ guards,
+ element,
+ pseudo,
+ is_probe,
+ rule_inclusion,
+ matching_fn
+ );
self.compute_pseudo_element_style_with_inputs(
&cascade_inputs,
pseudo,
guards,
parent_style,
font_metrics,
)
}
@@ -972,17 +980,18 @@ impl Stylist {
/// See the documentation on lazy pseudo-elements in
/// docs/components/style.md
pub fn lazy_pseudo_rules<E>(
&self,
guards: &StylesheetGuards,
element: &E,
pseudo: &PseudoElement,
is_probe: bool,
- rule_inclusion: RuleInclusion
+ rule_inclusion: RuleInclusion,
+ matching_fn: Option<&Fn(&PseudoElement) -> bool>,
) -> CascadeInputs
where
E: TElement
{
let pseudo = pseudo.canonical();
debug_assert!(pseudo.is_lazy());
// Apply the selector flags. We should be in sequential mode
@@ -1019,16 +1028,17 @@ impl Stylist {
let mut declarations = ApplicableDeclarationList::new();
let mut matching_context =
MatchingContext::new(
MatchingMode::ForStatelessPseudoElement,
None,
None,
self.quirks_mode,
);
+ matching_context.pseudo_element_matching_fn = matching_fn;
self.push_applicable_declarations(
element,
Some(&pseudo),
None,
None,
AnimationRules(None, None),
rule_inclusion,
@@ -1055,16 +1065,17 @@ impl Stylist {
let mut matching_context =
MatchingContext::new_for_visited(
MatchingMode::ForStatelessPseudoElement,
None,
None,
VisitedHandlingMode::RelevantLinkVisited,
self.quirks_mode,
);
+ matching_context.pseudo_element_matching_fn = matching_fn;
self.push_applicable_declarations(
element,
Some(&pseudo),
None,
None,
AnimationRules(None, None),
rule_inclusion,
@@ -1282,16 +1293,17 @@ impl Stylist {
// NOTE(emilio): This is needed because the XBL stylist may
// think it has a different quirks mode than the document.
let mut matching_context = MatchingContext::new(
context.matching_mode,
context.bloom_filter,
context.nth_index_cache.as_mut().map(|s| &mut **s),
stylist.quirks_mode,
);
+ matching_context.pseudo_element_matching_fn = context.pseudo_element_matching_fn;
map.get_all_matching_rules(
element,
&rule_hash_target,
applicable_declarations,
&mut matching_context,
stylist.quirks_mode,
flags_setter,
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -79,16 +79,17 @@ use style::gecko_bindings::bindings::nsT
use style::gecko_bindings::bindings::nsTimingFunctionBorrowedMut;
use style::gecko_bindings::structs;
use style::gecko_bindings::structs::{CSSPseudoElementType, CompositeOperation};
use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
use style::gecko_bindings::structs::{RawServoStyleRule, ServoStyleContextStrong, RustString};
use style::gecko_bindings::structs::{ServoStyleSheet, SheetParsingMode, nsAtom, nsCSSPropertyID};
use style::gecko_bindings::structs::{nsCSSFontFaceRule, nsCSSCounterStyleRule};
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint, PropertyValuePair};
+use style::gecko_bindings::structs::AtomArray;
use style::gecko_bindings::structs::IterationCompositeOperation;
use style::gecko_bindings::structs::MallocSizeOf as GeckoMallocSizeOf;
use style::gecko_bindings::structs::OriginFlags;
use style::gecko_bindings::structs::OriginFlags_Author;
use style::gecko_bindings::structs::OriginFlags_User;
use style::gecko_bindings::structs::OriginFlags_UserAgent;
use style::gecko_bindings::structs::RawGeckoGfxMatrix4x4;
use style::gecko_bindings::structs::RawGeckoPresContextOwned;
@@ -121,17 +122,17 @@ use style::properties::{SKIP_ROOT_AND_IT
use style::properties::PROHIBIT_DISPLAY_CONTENTS;
use style::properties::animated_properties::AnimationValue;
use style::properties::animated_properties::compare_property_priority;
use style::properties::parse_one_declaration_into;
use style::rule_cache::RuleCacheConditions;
use style::rule_tree::{CascadeLevel, StrongRuleNode, StyleSource};
use style::selector_parser::{PseudoElementCascadeType, SelectorImpl};
use style::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked};
-use style::string_cache::Atom;
+use style::string_cache::{Atom, WeakAtom};
use style::style_adjuster::StyleAdjuster;
use style::stylesheets::{CssRule, CssRules, CssRuleType, CssRulesHelpers, DocumentRule};
use style::stylesheets::{FontFeatureValuesRule, ImportRule, KeyframesRule, MediaRule};
use style::stylesheets::{NamespaceRule, Origin, OriginSet, PageRule, StyleRule};
use style::stylesheets::{StylesheetContents, SupportsRule};
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue};
use style::stylesheets::supports_rule::parse_condition_or_declaration;
@@ -1906,27 +1907,88 @@ pub extern "C" fn Servo_ResolvePseudoSty
&guard,
element,
&pseudo,
RuleInclusion::All,
&data.styles,
inherited_style,
&*doc_data,
is_probe,
+ /* matching_func = */ None,
);
match style {
Some(s) => s.into(),
None => {
debug_assert!(is_probe);
Strong::null()
}
}
}
+fn debug_atom_array(atoms: &AtomArray) -> String {
+ let mut result = String::from("[");
+ for atom in atoms.iter() {
+ if atom.mRawPtr.is_null() {
+ result += "(null), ";
+ } else {
+ let atom = unsafe { WeakAtom::new(atom.mRawPtr) };
+ write!(result, "{}, ", atom).unwrap();
+ }
+ }
+ result.push(']');
+ result
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_ComputedValues_ResolveXULTreePseudoStyle(
+ element: RawGeckoElementBorrowed,
+ pseudo_tag: *mut nsAtom,
+ inherited_style: ServoStyleContextBorrowed,
+ input_word: *const AtomArray,
+ raw_data: RawServoStyleSetBorrowed
+) -> ServoStyleContextStrong {
+ let element = GeckoElement(element);
+ let data = element.borrow_data()
+ .expect("Calling ResolveXULTreePseudoStyle on unstyled element?");
+
+ let pseudo = unsafe {
+ Atom::with(pseudo_tag, |atom| {
+ PseudoElement::from_tree_pseudo_atom(atom, Box::new([]))
+ }).expect("ResolveXULTreePseudoStyle with a non-tree pseudo?")
+ };
+ let input_word = unsafe { input_word.as_ref().unwrap() };
+
+ let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
+
+ debug!("ResolveXULTreePseudoStyle: {:?} {:?} {}",
+ element, pseudo, debug_atom_array(input_word));
+
+ let matching_fn = |pseudo: &PseudoElement| {
+ let args = pseudo.tree_pseudo_args().expect("Not a tree pseudo-element?");
+ args.iter().all(|atom| {
+ input_word.iter().any(|item| atom.as_ptr() == item.mRawPtr)
+ })
+ };
+
+ let global_style_data = &*GLOBAL_STYLE_DATA;
+ let guard = global_style_data.shared_lock.read();
+ get_pseudo_style(
+ &guard,
+ element,
+ &pseudo,
+ RuleInclusion::All,
+ &data.styles,
+ Some(inherited_style),
+ &*doc_data,
+ /* is_probe = */ false,
+ Some(&matching_fn),
+ ).unwrap().into()
+}
+
#[no_mangle]
pub extern "C" fn Servo_SetExplicitStyle(element: RawGeckoElementBorrowed,
style: ServoStyleContextBorrowed)
{
let element = GeckoElement(element);
debug!("Servo_SetExplicitStyle: {:?}", element);
// 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.
@@ -1960,16 +2022,17 @@ fn get_pseudo_style(
guard: &SharedRwLockReadGuard,
element: GeckoElement,
pseudo: &PseudoElement,
rule_inclusion: RuleInclusion,
styles: &ElementStyles,
inherited_styles: Option<&ComputedValues>,
doc_data: &PerDocumentStyleDataImpl,
is_probe: bool,
+ matching_func: Option<&Fn(&PseudoElement) -> bool>,
) -> Option<Arc<ComputedValues>> {
let style = match pseudo.cascade_type() {
PseudoElementCascadeType::Eager => {
match *pseudo {
PseudoElement::FirstLetter => {
styles.pseudos.get(&pseudo).and_then(|pseudo_styles| {
// inherited_styles can be None when doing lazy resolution
// (e.g. for computed style) or when probing. In that case
@@ -2033,16 +2096,17 @@ fn get_pseudo_style(
.lazily_compute_pseudo_element_style(
&guards,
&element,
&pseudo,
rule_inclusion,
base,
is_probe,
&metrics,
+ matching_func,
)
},
};
if is_probe {
return style;
}
@@ -3264,16 +3328,17 @@ pub extern "C" fn Servo_ResolveStyleLazi
&guard,
element,
pseudo,
rule_inclusion,
styles,
/* inherited_styles = */ None,
&*data,
is_probe,
+ /* matching_func = */ None,
)
}
None => Some(styles.primary().clone()),
}
};
let is_before_or_after = pseudo.as_ref().map_or(false, |p| p.is_before_or_after());