mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-07 18:04:46 +00:00
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:
parent
39eee0a002
commit
c84288a36d
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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(
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,2 +0,0 @@
|
||||
[highlight-currentcolor-root-implicit-default-002.html]
|
||||
expected: FAIL
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user