Bug 1838262, part 2: Implemented getComputedStyle() for custom highlight api. r=emilio

This patch introduces functional pseudo parameters, i.e. `::highlight(foo)`,
for `getComputedStyle()`. This required adapting the parse algorithm (`nsCSSPseudoElements::ParsePseudoElement()`) and forwarding the functional pseudo parameter into the style engine.

Differential Revision: https://phabricator.services.mozilla.com/D183773
This commit is contained in:
Jan-Niklas Jaeschke 2023-07-31 13:47:54 +00:00
parent 39eee0a002
commit c84288a36d
23 changed files with 218 additions and 145 deletions

View File

@ -2531,7 +2531,7 @@ static void UpdateBackdropIfNeeded(nsIFrame* aFrame, ServoStyleSet& aStyleSet,
PseudoStyleType::backdrop);
RefPtr<ComputedStyle> newStyle = aStyleSet.ResolvePseudoElementStyle(
*aFrame->GetContent()->AsElement(), PseudoStyleType::backdrop,
*aFrame->GetContent()->AsElement(), PseudoStyleType::backdrop, nullptr,
aFrame->Style());
// NOTE(emilio): We can't use the changes handled for the owner of the
@ -2578,7 +2578,8 @@ static void UpdateOneAdditionalComputedStyle(nsIFrame* aFrame, uint32_t aIndex,
RefPtr<ComputedStyle> newStyle =
aRestyleState.StyleSet().ResolvePseudoElementStyle(
*aFrame->GetContent()->AsElement(), pseudoType, aFrame->Style());
*aFrame->GetContent()->AsElement(), pseudoType, nullptr,
aFrame->Style());
uint32_t equalStructs; // Not used, actually.
nsChangeHint childHint =
@ -2786,7 +2787,8 @@ bool RestyleManager::ProcessPostTraversal(Element* aElement,
!nsLayoutUtils::GetMarkerPseudo(aElement)) {
RefPtr<ComputedStyle> pseudoStyle =
aRestyleState.StyleSet().ProbePseudoElementStyle(
*aElement, PseudoStyleType::marker, upToDateStyleIfRestyled);
*aElement, PseudoStyleType::marker, nullptr,
upToDateStyleIfRestyled);
if (pseudoStyle) {
changeHint |= nsChangeHint_ReconstructFrame;
}

View File

@ -1078,7 +1078,7 @@ void nsFrameConstructorState::ConstructBackdropFrameFor(nsIContent* aContent,
RefPtr<ComputedStyle> style =
mPresShell->StyleSet()->ResolvePseudoElementStyle(
*aContent->AsElement(), PseudoStyleType::backdrop,
*aContent->AsElement(), PseudoStyleType::backdrop, nullptr,
/* aParentStyle */ nullptr);
MOZ_ASSERT(style->StyleDisplay()->mTopLayer == StyleTopLayer::Top);
nsContainerFrame* parentFrame =
@ -1848,7 +1848,7 @@ void nsCSSFrameConstructor::CreateGeneratedContentItem(
// |ProbePseudoElementStyle| checks the relevant properties for the pseudo.
// It only returns a non-null value if the pseudo should exist.
RefPtr<ComputedStyle> pseudoStyle = styleSet->ProbePseudoElementStyle(
aOriginatingElement, aPseudoElement, &aStyle);
aOriginatingElement, aPseudoElement, nullptr, &aStyle);
if (!pseudoStyle) {
return;
}
@ -8568,7 +8568,8 @@ already_AddRefed<ComputedStyle> nsCSSFrameConstructor::GetFirstLetterStyle(
nsIContent* aContent, ComputedStyle* aComputedStyle) {
if (aContent) {
return mPresShell->StyleSet()->ResolvePseudoElementStyle(
*aContent->AsElement(), PseudoStyleType::firstLetter, aComputedStyle);
*aContent->AsElement(), PseudoStyleType::firstLetter, nullptr,
aComputedStyle);
}
return nullptr;
}
@ -8577,7 +8578,8 @@ already_AddRefed<ComputedStyle> nsCSSFrameConstructor::GetFirstLineStyle(
nsIContent* aContent, ComputedStyle* aComputedStyle) {
if (aContent) {
return mPresShell->StyleSet()->ResolvePseudoElementStyle(
*aContent->AsElement(), PseudoStyleType::firstLine, aComputedStyle);
*aContent->AsElement(), PseudoStyleType::firstLine, nullptr,
aComputedStyle);
}
return nullptr;
}

View File

@ -1608,7 +1608,7 @@ bool nsLayoutUtils::HasPseudoStyle(nsIContent* aContent,
RefPtr<ComputedStyle> pseudoContext;
if (aContent) {
pseudoContext = aPresContext->StyleSet()->ProbePseudoElementStyle(
*aContent->AsElement(), aPseudoElement, aComputedStyle);
*aContent->AsElement(), aPseudoElement, nullptr, aComputedStyle);
}
return pseudoContext != nullptr;
}

View File

@ -194,7 +194,7 @@ void nsButtonFrameRenderer::ReResolveStyles(nsPresContext* aPresContext) {
// get styles assigned to -moz-focus-inner (ie dotted border on Windows)
mInnerFocusStyle = styleSet->ProbePseudoElementStyle(
*mFrame->GetContent()->AsElement(), PseudoStyleType::mozFocusInner,
mFrame->Style());
nullptr, mFrame->Style());
}
ComputedStyle* nsButtonFrameRenderer::GetComputedStyle(int32_t aIndex) const {

View File

@ -6203,7 +6203,8 @@ void nsBlockFrame::UpdateFirstLetterStyle(ServoRestyleState& aRestyleState) {
ComputedStyle* parentStyle = styleParent->Style();
RefPtr<ComputedStyle> firstLetterStyle =
aRestyleState.StyleSet().ResolvePseudoElementStyle(
*mContent->AsElement(), PseudoStyleType::firstLetter, parentStyle);
*mContent->AsElement(), PseudoStyleType::firstLetter, nullptr,
parentStyle);
// Note that we don't need to worry about changehints for the continuation
// styles: those will be handled by the styleParent already.
RefPtr<ComputedStyle> continuationStyle =
@ -8113,7 +8114,8 @@ void nsBlockFrame::UpdatePseudoElementStyles(ServoRestyleState& aRestyleState) {
ComputedStyle* parentStyle = styleParent->Style();
RefPtr<ComputedStyle> firstLineStyle =
aRestyleState.StyleSet().ResolvePseudoElementStyle(
*mContent->AsElement(), PseudoStyleType::firstLine, parentStyle);
*mContent->AsElement(), PseudoStyleType::firstLine, nullptr,
parentStyle);
// FIXME(bz): Can we make first-line continuations be non-inheriting anon
// boxes?
@ -8313,6 +8315,6 @@ int32_t nsBlockFrame::GetDepth() const {
already_AddRefed<ComputedStyle> nsBlockFrame::GetFirstLetterStyle(
nsPresContext* aPresContext) {
return aPresContext->StyleSet()->ProbePseudoElementStyle(
*mContent->AsElement(), PseudoStyleType::firstLetter, Style());
*mContent->AsElement(), PseudoStyleType::firstLetter, nullptr, Style());
}
#endif

View File

@ -2399,7 +2399,7 @@ already_AddRefed<ComputedStyle> nsIFrame::ComputeSelectionStyle(
}
RefPtr<ComputedStyle> pseudoStyle =
PresContext()->StyleSet()->ProbePseudoElementStyle(
*element, PseudoStyleType::selection, Style());
*element, PseudoStyleType::selection, nullptr, Style());
if (!pseudoStyle) {
return nullptr;
}

View File

@ -56,7 +56,8 @@ namespace mozilla {
namespace dom {
static already_AddRefed<const ComputedStyle> GetCleanComputedStyleForElement(
dom::Element* aElement, PseudoStyleType aPseudo) {
dom::Element* aElement, PseudoStyleType aPseudo,
nsAtom* aFunctionalPseudoParameter) {
MOZ_ASSERT(aElement);
Document* doc = aElement->GetComposedDoc();
@ -76,7 +77,8 @@ static already_AddRefed<const ComputedStyle> GetCleanComputedStyleForElement(
presContext->EnsureSafeToHandOutCSSRules();
return nsComputedDOMStyle::GetComputedStyle(aElement, aPseudo);
return nsComputedDOMStyle::GetComputedStyle(aElement, aPseudo,
aFunctionalPseudoParameter);
}
/* static */
@ -227,14 +229,15 @@ void InspectorUtils::GetCSSStyleRules(GlobalObject& aGlobalObject,
const nsAString& aPseudo,
bool aIncludeVisitedStyle,
nsTArray<RefPtr<CSSStyleRule>>& aResult) {
Maybe<PseudoStyleType> type = nsCSSPseudoElements::GetPseudoType(
aPseudo, CSSEnabledState::ForAllContent);
auto [type, functionalPseudoParameter] =
nsCSSPseudoElements::ParsePseudoElement(aPseudo,
CSSEnabledState::ForAllContent);
if (!type) {
return;
}
RefPtr<const ComputedStyle> computedStyle =
GetCleanComputedStyleForElement(&aElement, *type);
RefPtr<const ComputedStyle> computedStyle = GetCleanComputedStyleForElement(
&aElement, *type, functionalPseudoParameter);
if (!computedStyle) {
// This can fail for elements that are not in the document or
// if the document they're in doesn't have a presshell. Bail out.

View File

@ -451,13 +451,17 @@ static inline bool LazyPseudoIsCacheable(PseudoStyleType aType,
already_AddRefed<ComputedStyle> ServoStyleSet::ResolvePseudoElementStyle(
const Element& aOriginatingElement, PseudoStyleType aType,
ComputedStyle* aParentStyle, IsProbe aIsProbe) {
nsAtom* aFunctionalPseudoParameter, ComputedStyle* aParentStyle,
IsProbe aIsProbe) {
// Runs from frame construction, this should have clean styles already, except
// with non-lazy FC...
UpdateStylistIfNeeded();
MOZ_ASSERT(PseudoStyle::IsPseudoElement(aType));
// caching is done using `aType` only, therefore results would be wrong for
// pseudos with functional parameters (e.g. `::highlight(foo)`).
const bool cacheable =
!aFunctionalPseudoParameter &&
LazyPseudoIsCacheable(aType, aOriginatingElement, aParentStyle);
RefPtr<ComputedStyle> style =
cacheable ? aParentStyle->GetCachedLazyPseudoStyle(aType) : nullptr;
@ -469,9 +473,9 @@ already_AddRefed<ComputedStyle> ServoStyleSet::ResolvePseudoElementStyle(
//
// There are callers which do pass the wrong parent style and it would
// assert (like ComputeSelectionStyle()). That's messy!
style = Servo_ResolvePseudoStyle(&aOriginatingElement, aType, isProbe,
isProbe ? nullptr : aParentStyle,
mRawData.get())
style = Servo_ResolvePseudoStyle(
&aOriginatingElement, aType, aFunctionalPseudoParameter,
isProbe, isProbe ? nullptr : aParentStyle, mRawData.get())
.Consume();
if (!style) {
MOZ_ASSERT(isProbe);
@ -1213,7 +1217,7 @@ void ServoStyleSet::ClearNonInheritingComputedStyles() {
already_AddRefed<ComputedStyle> ServoStyleSet::ResolveStyleLazily(
const Element& aElement, PseudoStyleType aPseudoType,
StyleRuleInclusion aRuleInclusion) {
nsAtom* aFunctionalPseudoParameter, StyleRuleInclusion aRuleInclusion) {
PreTraverseSync();
MOZ_ASSERT(!StylistNeedsUpdate());
@ -1257,7 +1261,8 @@ already_AddRefed<ComputedStyle> ServoStyleSet::ResolveStyleLazily(
pc->PresShell()->DidInitialize();
return Servo_ResolveStyleLazily(
elementForStyleResolution, pseudoTypeForStyleResolution,
aRuleInclusion, &restyleManager->Snapshots(),
aFunctionalPseudoParameter, aRuleInclusion,
&restyleManager->Snapshots(),
restyleManager->GetUndisplayedRestyleGeneration(), canUseCache,
mRawData.get())
.Consume();

View File

@ -216,12 +216,14 @@ class ServoStyleSet {
// If IsProbe is No, then the style is guaranteed to be non-null.
already_AddRefed<ComputedStyle> ResolvePseudoElementStyle(
const dom::Element& aOriginatingElement, PseudoStyleType,
ComputedStyle* aParentStyle, IsProbe = IsProbe::No);
nsAtom* aFunctionalPseudoParameter, ComputedStyle* aParentStyle,
IsProbe = IsProbe::No);
already_AddRefed<ComputedStyle> ProbePseudoElementStyle(
const dom::Element& aOriginatingElement, PseudoStyleType aType,
ComputedStyle* aParentStyle) {
return ResolvePseudoElementStyle(aOriginatingElement, aType, aParentStyle,
nsAtom* aFunctionalPseudoParameter, ComputedStyle* aParentStyle) {
return ResolvePseudoElementStyle(aOriginatingElement, aType,
aFunctionalPseudoParameter, aParentStyle,
IsProbe::Yes);
}
@ -243,6 +245,7 @@ class ServoStyleSet {
// unstyled.)
already_AddRefed<ComputedStyle> ResolveStyleLazily(
const dom::Element&, PseudoStyleType = PseudoStyleType::NotPseudo,
nsAtom* aFunctionalPseudoParameter = nullptr,
StyleRuleInclusion = StyleRuleInclusion::All);
// Get a ComputedStyle for an anonymous box. The pseudo type must be an

View File

@ -14,6 +14,7 @@
#include "nsDOMString.h"
#include "nsGkAtomConsts.h"
#include "nsStaticAtomUtils.h"
#include "nsStringFwd.h"
using namespace mozilla;
@ -38,20 +39,20 @@ nsAtom* nsCSSPseudoElements::GetPseudoAtom(Type aType) {
}
/* static */
Maybe<PseudoStyleType> nsCSSPseudoElements::GetPseudoType(
const nsAString& aPseudoElement, CSSEnabledState aEnabledState) {
std::tuple<mozilla::Maybe<PseudoStyleType>, RefPtr<nsAtom>>
nsCSSPseudoElements::ParsePseudoElement(const nsAString& aPseudoElement,
CSSEnabledState aEnabledState) {
if (DOMStringIsNull(aPseudoElement) || aPseudoElement.IsEmpty()) {
return Some(PseudoStyleType::NotPseudo);
return {Some(PseudoStyleType::NotPseudo), nullptr};
}
if (aPseudoElement.First() != char16_t(':')) {
return Nothing();
return {};
}
// deal with two-colon forms of aPseudoElt
nsAString::const_iterator start, end;
aPseudoElement.BeginReading(start);
aPseudoElement.EndReading(end);
const char16_t* start = aPseudoElement.BeginReading();
const char16_t* end = aPseudoElement.EndReading();
NS_ASSERTION(start != end, "aPseudoElement is not empty!");
++start;
bool haveTwoColons = true;
@ -59,20 +60,56 @@ Maybe<PseudoStyleType> nsCSSPseudoElements::GetPseudoType(
--start;
haveTwoColons = false;
}
// XXX jjaschke: this parsing algorithm should be replaced by the css parser
// for correct handling of all edge cases. See Bug 1845712.
const int32_t parameterPosition = aPseudoElement.FindChar('(');
const bool hasParameter = parameterPosition != kNotFound;
if (hasParameter) {
end = start + parameterPosition - 1;
}
RefPtr<nsAtom> pseudo = NS_Atomize(Substring(start, end));
MOZ_ASSERT(pseudo);
Maybe<uint32_t> index = nsStaticAtomUtils::Lookup(pseudo, GetAtomBase(),
kAtomCount_PseudoElements);
if (index.isNothing()) {
return Nothing();
return {};
}
auto type = static_cast<Type>(*index);
RefPtr<nsAtom> functionalPseudoParameter;
if (hasParameter) {
if (type != PseudoStyleType::highlight) {
return {};
}
functionalPseudoParameter =
[&aPseudoElement, parameterPosition]() -> already_AddRefed<nsAtom> {
const char16_t* start = aPseudoElement.BeginReading();
const char16_t* end = aPseudoElement.EndReading();
start += parameterPosition + 1;
--end;
if (*end != ')') {
return nullptr;
}
return NS_Atomize(Substring(start, end));
}();
}
if (!haveTwoColons &&
!PseudoElementHasFlags(type, CSS_PSEUDO_ELEMENT_IS_CSS2)) {
return Nothing();
return {};
}
return IsEnabled(type, aEnabledState) ? Some(type) : Nothing();
if (IsEnabled(type, aEnabledState)) {
return {Some(type), functionalPseudoParameter};
}
return {};
}
/* static */
mozilla::Maybe<PseudoStyleType> nsCSSPseudoElements::GetPseudoType(
const nsAString& aPseudoElement, CSSEnabledState aEnabledState) {
auto [pseudoType, _] = ParsePseudoElement(aPseudoElement, aEnabledState);
return pseudoType;
}
/* static */

View File

@ -81,6 +81,14 @@ class nsCSSPseudoElements {
#include "nsCSSPseudoElementList.h"
#undef CSS_PSEUDO_ELEMENT
// Returns an empty tuple for a syntactically invalid pseudo-element, and
// NotPseudo for the empty / null string.
// The second element of the tuple (functional pseudo parameter) is currently
// only used for `::highlight()` pseudos and is `nullptr` otherwise.
static std::tuple<mozilla::Maybe<Type>, RefPtr<nsAtom>> ParsePseudoElement(
const nsAString& aPseudoElement,
EnabledState = EnabledState::ForAllContent);
// Returns Nothing() for a syntactically invalid pseudo-element, and NotPseudo
// for the empty / null string.
static mozilla::Maybe<Type> GetPseudoType(

View File

@ -71,8 +71,9 @@ using namespace mozilla::dom;
already_AddRefed<nsComputedDOMStyle> NS_NewComputedDOMStyle(
dom::Element* aElement, const nsAString& aPseudoElt, Document* aDocument,
nsComputedDOMStyle::StyleType aStyleType, mozilla::ErrorResult&) {
Maybe<PseudoStyleType> pseudo = nsCSSPseudoElements::GetPseudoType(
aPseudoElt, CSSEnabledState::ForAllContent);
auto [pseudo, functionalPseudoParameter] =
nsCSSPseudoElements::ParsePseudoElement(aPseudoElt,
CSSEnabledState::ForAllContent);
auto returnEmpty = nsComputedDOMStyle::AlwaysReturnEmptyStyle::No;
if (!pseudo) {
if (!aPseudoElt.IsEmpty() && aPseudoElt.First() == u':') {
@ -80,8 +81,9 @@ already_AddRefed<nsComputedDOMStyle> NS_NewComputedDOMStyle(
}
pseudo.emplace(PseudoStyleType::NotPseudo);
}
RefPtr<nsComputedDOMStyle> computedStyle = new nsComputedDOMStyle(
aElement, *pseudo, aDocument, aStyleType, returnEmpty);
RefPtr<nsComputedDOMStyle> computedStyle =
new nsComputedDOMStyle(aElement, *pseudo, functionalPseudoParameter,
aDocument, aStyleType, returnEmpty);
return computedStyle.forget();
}
@ -317,6 +319,7 @@ void ComputedStyleMap::Update() {
nsComputedDOMStyle::nsComputedDOMStyle(dom::Element* aElement,
PseudoStyleType aPseudo,
nsAtom* aFunctionalPseudoParameter,
Document* aDocument,
StyleType aStyleType,
AlwaysReturnEmptyStyle aAlwaysEmpty)
@ -325,6 +328,7 @@ nsComputedDOMStyle::nsComputedDOMStyle(dom::Element* aElement,
mInnerFrame(nullptr),
mPresShell(nullptr),
mPseudo(aPseudo),
mFunctionalPseudoParameter(aFunctionalPseudoParameter),
mStyleType(aStyleType),
mAlwaysReturnEmpty(aAlwaysEmpty) {
MOZ_ASSERT(aElement);
@ -496,11 +500,13 @@ void nsComputedDOMStyle::GetPropertyValue(
/* static */
already_AddRefed<const ComputedStyle> nsComputedDOMStyle::GetComputedStyle(
Element* aElement, PseudoStyleType aPseudo, StyleType aStyleType) {
Element* aElement, PseudoStyleType aPseudo,
nsAtom* aFunctionalPseudoParameter, StyleType aStyleType) {
if (Document* doc = aElement->GetComposedDoc()) {
doc->FlushPendingNotifications(FlushType::Style);
}
return GetComputedStyleNoFlush(aElement, aPseudo, aStyleType);
return GetComputedStyleNoFlush(aElement, aPseudo, aFunctionalPseudoParameter,
aStyleType);
}
/**
@ -537,10 +543,10 @@ static bool IsInFlatTree(const Element& aElement) {
}
already_AddRefed<const ComputedStyle>
nsComputedDOMStyle::DoGetComputedStyleNoFlush(const Element* aElement,
PseudoStyleType aPseudo,
PresShell* aPresShell,
StyleType aStyleType) {
nsComputedDOMStyle::DoGetComputedStyleNoFlush(
const Element* aElement, PseudoStyleType aPseudo,
nsAtom* aFunctionalPseudoParameter, PresShell* aPresShell,
StyleType aStyleType) {
MOZ_ASSERT(aElement, "NULL element");
// If the content has a pres shell, we must use it. Otherwise we'd
@ -592,16 +598,17 @@ nsComputedDOMStyle::DoGetComputedStyleNoFlush(const Element* aElement,
StyleRuleInclusion rules = aStyleType == StyleType::DefaultOnly
? StyleRuleInclusion::DefaultOnly
: StyleRuleInclusion::All;
RefPtr<ComputedStyle> result =
styleSet->ResolveStyleLazily(*aElement, aPseudo, rules);
RefPtr<ComputedStyle> result = styleSet->ResolveStyleLazily(
*aElement, aPseudo, aFunctionalPseudoParameter, rules);
return result.forget();
}
already_AddRefed<const ComputedStyle>
nsComputedDOMStyle::GetUnanimatedComputedStyleNoFlush(Element* aElement,
PseudoStyleType aPseudo) {
nsComputedDOMStyle::GetUnanimatedComputedStyleNoFlush(
Element* aElement, PseudoStyleType aPseudo,
nsAtom* aFunctionalPseudoParameter) {
RefPtr<const ComputedStyle> style =
GetComputedStyleNoFlush(aElement, aPseudo);
GetComputedStyleNoFlush(aElement, aPseudo, aFunctionalPseudoParameter);
if (!style) {
return nullptr;
}
@ -1102,7 +1109,7 @@ void nsComputedDOMStyle::UpdateCurrentStyleSources(nsCSSPropertyID aPropID) {
// Need to resolve a style.
RefPtr<const ComputedStyle> resolvedComputedStyle =
DoGetComputedStyleNoFlush(
mElement, mPseudo,
mElement, mPseudo, mFunctionalPseudoParameter,
presShellForContent ? presShellForContent : mPresShell, mStyleType);
if (!resolvedComputedStyle) {
ClearComputedStyle();

View File

@ -88,7 +88,8 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
// In some cases, for legacy reasons, we forcefully return an empty style.
enum class AlwaysReturnEmptyStyle : bool { No, Yes };
nsComputedDOMStyle(Element*, PseudoStyleType, Document*, StyleType,
nsComputedDOMStyle(Element*, PseudoStyleType,
nsAtom* aFunctionalPseudoParameter, Document*, StyleType,
AlwaysReturnEmptyStyle = AlwaysReturnEmptyStyle::No);
nsINode* GetAssociatedNode() const override { return mElement; }
@ -96,20 +97,22 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
static already_AddRefed<const ComputedStyle> GetComputedStyle(
Element* aElement, PseudoStyleType = PseudoStyleType::NotPseudo,
StyleType = StyleType::All);
nsAtom* aFunctionalPseudoParameter = nullptr, StyleType = StyleType::All);
static already_AddRefed<const ComputedStyle> GetComputedStyleNoFlush(
const Element* aElement,
PseudoStyleType aPseudo = PseudoStyleType::NotPseudo,
nsAtom* aFunctionalPseudoParameter = nullptr,
StyleType aStyleType = StyleType::All) {
return DoGetComputedStyleNoFlush(
aElement, aPseudo, nsContentUtils::GetPresShellForContent(aElement),
aStyleType);
aElement, aPseudo, aFunctionalPseudoParameter,
nsContentUtils::GetPresShellForContent(aElement), aStyleType);
}
static already_AddRefed<const ComputedStyle>
GetUnanimatedComputedStyleNoFlush(
Element*, PseudoStyleType = PseudoStyleType::NotPseudo);
Element*, PseudoStyleType = PseudoStyleType::NotPseudo,
nsAtom* aFunctionalPseudoParameter = nullptr);
// Helper for nsDOMWindowUtils::GetVisitedDependentComputedStyle
void SetExposeVisitedStyle(bool aExpose) {
@ -168,7 +171,8 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
void SetFrameComputedStyle(ComputedStyle* aStyle, uint64_t aGeneration);
static already_AddRefed<const ComputedStyle> DoGetComputedStyleNoFlush(
const Element*, PseudoStyleType, mozilla::PresShell*, StyleType);
const Element*, PseudoStyleType, nsAtom* aFunctionalPseudoParameter,
mozilla::PresShell*, StyleType);
#define STYLE_STRUCT(name_) \
const nsStyle##name_* Style##name_() { \
@ -355,6 +359,7 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
mozilla::PresShell* mPresShell;
PseudoStyleType mPseudo;
RefPtr<nsAtom> mFunctionalPseudoParameter;
/* The kind of styles we should be returning. */
StyleType mStyleType;

View File

@ -130,15 +130,22 @@ impl PseudoElement {
/// Construct a pseudo-element from a `PseudoStyleType`.
#[inline]
pub fn from_pseudo_type(type_: PseudoStyleType) -> Option<Self> {
pub fn from_pseudo_type(type_: PseudoStyleType, functional_pseudo_parameter: Option<AtomIdent>) -> Option<Self> {
match type_ {
% for pseudo in PSEUDOS:
% if pseudo.is_simple_pseudo_element():
PseudoStyleType::${pseudo.pseudo_ident} => {
debug_assert!(functional_pseudo_parameter.is_none());
Some(${pseudo_element_variant(pseudo)})
},
% endif
% endfor
PseudoStyleType::highlight => {
match functional_pseudo_parameter {
Some(p) => Some(PseudoElement::Highlight(p)),
None => None
}
}
_ => None,
}
}

View File

@ -1306,7 +1306,7 @@ impl<'le> TElement for GeckoElement<'le> {
return None;
}
PseudoElement::from_pseudo_type(unsafe { bindings::Gecko_GetImplementedPseudo(self.0) })
PseudoElement::from_pseudo_type(unsafe { bindings::Gecko_GetImplementedPseudo(self.0) }, None)
}
#[inline]

View File

@ -118,7 +118,7 @@ impl ComputedValues {
if !self.is_pseudo_style() {
return None;
}
PseudoElement::from_pseudo_type(self.0.mPseudoType)
PseudoElement::from_pseudo_type(self.0.mPseudoType, None)
}
#[inline]

View File

@ -2470,7 +2470,7 @@ pub extern "C" fn Servo_StyleRule_SelectorMatchesElement(
let selectors = desugared_selector_list(rules);
let Some(selector) = selectors.0.get(index as usize) else { return false };
let mut matching_mode = MatchingMode::Normal;
match PseudoElement::from_pseudo_type(pseudo_type) {
match PseudoElement::from_pseudo_type(pseudo_type, None) {
Some(pseudo) => {
// We need to make sure that the requested pseudo element type
// matches the selector pseudo element type before proceeding.
@ -3903,7 +3903,7 @@ pub unsafe extern "C" fn Servo_ComputedValues_GetForAnonymousBox(
pseudo: PseudoStyleType,
raw_data: &PerDocumentStyleData,
) -> Strong<ComputedValues> {
let pseudo = PseudoElement::from_pseudo_type(pseudo).unwrap();
let pseudo = PseudoElement::from_pseudo_type(pseudo, None).unwrap();
debug_assert!(pseudo.is_anon_box());
debug_assert_ne!(pseudo, PseudoElement::PageContent);
let global_style_data = &*GLOBAL_STYLE_DATA;
@ -3924,10 +3924,23 @@ pub unsafe extern "C" fn Servo_ComputedValues_GetForAnonymousBox(
.into()
}
fn get_functional_pseudo_parameter_atom(
functional_pseudo_parameter: *mut nsAtom,
) -> Option<AtomIdent> {
if functional_pseudo_parameter.is_null() {
None
} else {
Some(AtomIdent::new(unsafe {
Atom::from_raw(functional_pseudo_parameter)
}))
}
}
#[no_mangle]
pub extern "C" fn Servo_ResolvePseudoStyle(
element: &RawGeckoElement,
pseudo_type: PseudoStyleType,
functional_pseudo_parameter: *mut nsAtom,
is_probe: bool,
inherited_style: Option<&ComputedValues>,
raw_data: &PerDocumentStyleData,
@ -3938,7 +3951,10 @@ pub extern "C" fn Servo_ResolvePseudoStyle(
debug!(
"Servo_ResolvePseudoStyle: {:?} {:?}, is_probe: {}",
element,
PseudoElement::from_pseudo_type(pseudo_type),
PseudoElement::from_pseudo_type(
pseudo_type,
get_functional_pseudo_parameter_atom(functional_pseudo_parameter)
),
is_probe
);
@ -3963,21 +3979,26 @@ pub extern "C" fn Servo_ResolvePseudoStyle(
},
};
let pseudo = PseudoElement::from_pseudo_type(pseudo_type)
.expect("ResolvePseudoStyle with a non-pseudo?");
let pseudo_element = PseudoElement::from_pseudo_type(
pseudo_type,
get_functional_pseudo_parameter_atom(functional_pseudo_parameter),
)
.expect("ResolvePseudoStyle with a non-pseudo?");
let matching_fn = |pseudo: &PseudoElement| *pseudo == pseudo_element;
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let style = get_pseudo_style(
&guard,
element,
&pseudo,
&pseudo_element,
RuleInclusion::All,
&data.styles,
inherited_style,
&doc_data.stylist,
is_probe,
/* matching_func = */ None,
/* matching_func = */ if pseudo_element.is_highlight() {Some(&matching_fn)} else {None},
);
match style {
@ -4211,7 +4232,7 @@ pub unsafe extern "C" fn Servo_ComputedValues_Inherit(
let data = raw_data.borrow();
let for_text = target == structs::InheritTarget::Text;
let pseudo = PseudoElement::from_pseudo_type(pseudo).unwrap();
let pseudo = PseudoElement::from_pseudo_type(pseudo, None).unwrap();
debug_assert!(pseudo.is_anon_box());
let mut style =
@ -5823,6 +5844,7 @@ pub extern "C" fn Servo_ResolveStyle(element: &RawGeckoElement) -> Strong<Comput
pub extern "C" fn Servo_ResolveStyleLazily(
element: &RawGeckoElement,
pseudo_type: PseudoStyleType,
functional_pseudo_parameter: *mut nsAtom,
rule_inclusion: StyleRuleInclusion,
snapshots: *const ServoElementSnapshotTable,
cache_generation: u64,
@ -5837,7 +5859,15 @@ pub extern "C" fn Servo_ResolveStyleLazily(
let mut data = raw_data.borrow_mut();
let data = &mut *data;
let rule_inclusion = RuleInclusion::from(rule_inclusion);
let pseudo = PseudoElement::from_pseudo_type(pseudo_type);
let pseudo_element = PseudoElement::from_pseudo_type(
pseudo_type,
get_functional_pseudo_parameter_atom(functional_pseudo_parameter),
);
let matching_fn = |pseudo: &PseudoElement| match pseudo_element {
Some(ref p) => *pseudo == *p,
_ => false,
};
if cache_generation != data.undisplayed_style_cache_generation {
data.undisplayed_style_cache.clear();
@ -5846,7 +5876,7 @@ pub extern "C" fn Servo_ResolveStyleLazily(
let stylist = &data.stylist;
let finish = |styles: &ElementStyles, is_probe: bool| -> Option<Arc<ComputedValues>> {
match pseudo {
match pseudo_element {
Some(ref pseudo) => {
get_pseudo_style(
&guard,
@ -5857,14 +5887,20 @@ pub extern "C" fn Servo_ResolveStyleLazily(
/* inherited_styles = */ None,
&stylist,
is_probe,
/* matching_func = */ None,
if pseudo.is_highlight() {
Some(&matching_fn)
} else {
None
},
)
},
None => Some(styles.primary().clone()),
}
};
let is_before_or_after = pseudo.as_ref().map_or(false, |p| p.is_before_or_after());
let is_before_or_after = pseudo_element
.as_ref()
.map_or(false, |p| p.is_before_or_after());
// In the common case we already have the style. Check that before setting
// up all the computation machinery.
@ -5883,7 +5919,7 @@ pub extern "C" fn Servo_ResolveStyleLazily(
if let Some(result) = styles {
return result.into();
}
if pseudo.is_none() && can_use_cache {
if pseudo_element.is_none() && can_use_cache {
if let Some(style) = data.undisplayed_style_cache.get(&element.opaque()) {
return style.clone().into();
}
@ -5908,7 +5944,7 @@ pub extern "C" fn Servo_ResolveStyleLazily(
&mut context,
element,
rule_inclusion,
pseudo.as_ref(),
pseudo_element.as_ref(),
if can_use_cache {
Some(&mut data.undisplayed_style_cache)
} else {
@ -6052,7 +6088,7 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(
) {
let data = raw_data.borrow();
let element = GeckoElement(element);
let pseudo = PseudoElement::from_pseudo_type(pseudo_type);
let pseudo = PseudoElement::from_pseudo_type(pseudo_type, None);
let parent_element = if pseudo.is_none() {
element.inheritance_parent()
} else {

View File

@ -1,30 +1,30 @@
[highlight-pseudo-computed.html]
[getComputedStyle() for ::highlight(foo)]
expected: FAIL
[Different getComputedStyle() for ::highlight(bar) and same element]
expected: FAIL
[getComputedStyle() for ::highlight(foo): should be element's default]
expected: FAIL
[getComputedStyle() for ::highlight(foo)) should be element's default]
expected: FAIL
[getComputedStyle() for ::highlight(foo)( should be element's default]
expected: FAIL
[getComputedStyle() for ::highlight(foo)(foo) should be element's default]
expected: FAIL
[getComputedStyle() for ::highlight(foo)() should be element's default]
expected: FAIL
[getComputedStyle() for :::highlight(foo) should be element's default]
expected: FAIL
[getComputedStyle() for ::highlight(foo). should be element's default]
[getComputedStyle() for ::highlight(foo): should not return a style.]
expected: FAIL
[getComputedStyle() for ::highlight(foo,bar) should be element's default]
[getComputedStyle() for ::highlight(foo)) should not return a style.]
expected: FAIL
[getComputedStyle() for ::highlight(foo)( should not return a style.]
expected: FAIL
[getComputedStyle() for ::highlight should not return a style.]
expected: FAIL
[getComputedStyle() for ::highlight(foo)(foo) should not return a style.]
expected: FAIL
[getComputedStyle() for ::highlight(foo)() should not return a style.]
expected: FAIL
[getComputedStyle() for ::highlight(foo). should not return a style.]
expected: FAIL
[getComputedStyle() for ::highlight(foo,bar) should not return a style.]
expected: FAIL
[getComputedStyle() for ::highlight(foo bar) should not return a style.]
expected: FAIL

View File

@ -18,9 +18,3 @@
[getComputedStyle() for ::grammar-error at #target2]
expected: FAIL
[getComputedStyle() for ::highlight(foo) at #target1]
expected: FAIL
[getComputedStyle() for ::highlight(foo) at #target2]
expected: FAIL

View File

@ -18,9 +18,3 @@
[getComputedStyle() for ::grammar-error at #target2]
expected: FAIL
[getComputedStyle() for ::highlight(foo) at #target1]
expected: FAIL
[getComputedStyle() for ::highlight(foo) at #target2]
expected: FAIL

View File

@ -1,2 +0,0 @@
[highlight-currentcolor-root-implicit-default-002.html]
expected: FAIL

View File

@ -94,29 +94,5 @@
[getComputedStyle() for ::grammar-error. should be element's default]
expected: FAIL
[getComputedStyle() for ::highlight(foo)]
expected: FAIL
[getComputedStyle() for ::highlight(foo): should be element's default]
expected: FAIL
[getComputedStyle() for ::highlight(foo)) should be element's default]
expected: FAIL
[getComputedStyle() for ::highlight(foo)( should be element's default]
expected: FAIL
[getComputedStyle() for ::highlight(foo)(foo) should be element's default]
expected: FAIL
[getComputedStyle() for ::highlight(foo)() should be element's default]
expected: FAIL
[getComputedStyle() for :::highlight(foo) should be element's default]
expected: FAIL
[getComputedStyle() for ::highlight(foo). should be element's default]
expected: FAIL
[Different getComputedStyle() for ::highlight(bar) and same element]
expected: FAIL

View File

@ -18,9 +18,3 @@
[getComputedStyle() for ::grammar-error at #target2]
expected: FAIL
[getComputedStyle() for ::highlight(foo) at #target1]
expected: FAIL
[getComputedStyle() for ::highlight(foo) at #target2]
expected: FAIL