mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-20 03:13:09 +09:00
Issue #1593 - Part 1: Import William Chen's patches w/o selector implementation, fixed up.
This commit is contained in:
parent
ecdf4bfb29
commit
7472bc02be
10 changed files with 273 additions and 32 deletions
|
|
@ -48,6 +48,7 @@
|
|||
#include "nsCSSRules.h"
|
||||
#include "nsStyleSet.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "nsNthIndexCache.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
|
|
@ -1342,9 +1343,17 @@ struct NodeMatchContext {
|
|||
// mForStyling is false, we have to assume we don't know.)
|
||||
const bool mIsRelevantLink;
|
||||
|
||||
NodeMatchContext(EventStates aStateMask, bool aIsRelevantLink)
|
||||
// If the node should be considered featureless (as specified in
|
||||
// selectors 4), then mIsFeature should be set to true to prevent
|
||||
// matching unless the selector is a special pseudo class or pseudo
|
||||
// element that matches featureless elements.
|
||||
const bool mIsFeatureless;
|
||||
|
||||
NodeMatchContext(EventStates aStateMask, bool aIsRelevantLink,
|
||||
bool aIsFeatureless = false)
|
||||
: mStateMask(aStateMask)
|
||||
, mIsRelevantLink(aIsRelevantLink)
|
||||
, mIsFeatureless(aIsFeatureless)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
@ -1631,6 +1640,11 @@ StateSelectorMatches(Element* aElement,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool AnySelectorInArgListMatches(Element* aElement,
|
||||
nsPseudoClassList* aList,
|
||||
NodeMatchContext& aNodeMatchContext,
|
||||
TreeMatchContext& aTreeMatchContext);
|
||||
|
||||
static bool
|
||||
StateSelectorMatches(Element* aElement,
|
||||
nsCSSSelector* aSelector,
|
||||
|
|
@ -1652,6 +1666,17 @@ StateSelectorMatches(Element* aElement,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Returns whether aSelector can match featureless elements.
|
||||
static bool CanMatchFeaturelessElement(nsCSSSelector* aSelector)
|
||||
{
|
||||
if (aSelector->HasFeatureSelectors()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// |aDependence| has two functions:
|
||||
// * when non-null, it indicates that we're processing a negation,
|
||||
// which is done only when SelectorMatches calls itself recursively
|
||||
|
|
@ -1672,6 +1697,11 @@ static bool SelectorMatches(Element* aElement,
|
|||
"is false since we don't know how to set it correctly in "
|
||||
"Has(Attribute|State)DependentStyle");
|
||||
|
||||
if (aNodeMatchContext.mIsFeatureless &&
|
||||
!CanMatchFeaturelessElement(aSelector)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// namespace/tag match
|
||||
// optimization : bail out early if we can
|
||||
if ((kNameSpaceID_Unknown != aSelector->mNameSpace &&
|
||||
|
|
@ -1870,18 +1900,9 @@ static bool SelectorMatches(Element* aElement,
|
|||
|
||||
case CSSPseudoClassType::any:
|
||||
{
|
||||
nsCSSSelectorList *l;
|
||||
for (l = pseudoClass->u.mSelectors; l; l = l->mNext) {
|
||||
nsCSSSelector *s = l->mSelectors;
|
||||
MOZ_ASSERT(!s->mNext && !s->IsPseudoElement(),
|
||||
"parser failed");
|
||||
if (SelectorMatches(
|
||||
aElement, s, aNodeMatchContext, aTreeMatchContext,
|
||||
SelectorMatchesFlags::IS_PSEUDO_CLASS_ARGUMENT)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!l) {
|
||||
if (!AnySelectorInArgListMatches(aElement, pseudoClass,
|
||||
aNodeMatchContext,
|
||||
aTreeMatchContext)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -2263,6 +2284,26 @@ static bool SelectorMatches(Element* aElement,
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool AnySelectorInArgListMatches(Element* aElement,
|
||||
nsPseudoClassList* aList,
|
||||
NodeMatchContext& aNodeMatchContext,
|
||||
TreeMatchContext& aTreeMatchContext)
|
||||
{
|
||||
nsCSSSelectorList *l;
|
||||
for (l = aList->u.mSelectors; l; l = l->mNext) {
|
||||
nsCSSSelector *s = l->mSelectors;
|
||||
MOZ_ASSERT(!s->mNext && !s->IsPseudoElement(),
|
||||
"parser failed");
|
||||
if (SelectorMatches(
|
||||
aElement, s, aNodeMatchContext, aTreeMatchContext,
|
||||
SelectorMatchesFlags::IS_PSEUDO_CLASS_ARGUMENT)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return !!l;
|
||||
}
|
||||
|
||||
#undef STATE_CHECK
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
@ -2352,7 +2393,9 @@ SelectorMatchesTree(Element* aPrevElement,
|
|||
MOZ_ASSERT(!aSelector || !aSelector->IsPseudoElement());
|
||||
nsCSSSelector* selector = aSelector;
|
||||
Element* prevElement = aPrevElement;
|
||||
bool crossedShadowRootBoundary = false;
|
||||
while (selector) { // check compound selectors
|
||||
bool contentIsFeatureless = false;
|
||||
NS_ASSERTION(!selector->mNext ||
|
||||
selector->mNext->mOperator != char16_t(0),
|
||||
"compound selector without combinator");
|
||||
|
|
@ -2383,6 +2426,20 @@ SelectorMatchesTree(Element* aPrevElement,
|
|||
// to test against is the parent
|
||||
else {
|
||||
nsIContent *content = prevElement->GetParent();
|
||||
|
||||
// In the shadow tree, the shadow host behaves as if it
|
||||
// is a featureless parent of top-level elements of the shadow
|
||||
// tree. Only cross shadow root boundary when the selector is the
|
||||
// left most selector because ancestors of the host are not in
|
||||
// the selector match list.
|
||||
ShadowRoot* shadowRoot = content ?
|
||||
ShadowRoot::FromNode(content) : nullptr;
|
||||
if (shadowRoot && !selector->mNext && !crossedShadowRootBoundary) {
|
||||
content = shadowRoot->GetHost();
|
||||
crossedShadowRootBoundary = true;
|
||||
contentIsFeatureless = true;
|
||||
}
|
||||
|
||||
// GetParent could return a document fragment; we only want
|
||||
// element parents.
|
||||
if (content && content->IsElement()) {
|
||||
|
|
@ -2434,7 +2491,8 @@ SelectorMatchesTree(Element* aPrevElement,
|
|||
}
|
||||
const bool isRelevantLink = (aFlags & eLookForRelevantLink) &&
|
||||
nsCSSRuleProcessor::IsLink(element);
|
||||
NodeMatchContext nodeContext(EventStates(), isRelevantLink);
|
||||
|
||||
NodeMatchContext nodeContext(EventStates(), isRelevantLink, contentIsFeatureless);
|
||||
if (isRelevantLink) {
|
||||
// If we find an ancestor of the matched node that is a link
|
||||
// during the matching process, then it's the relevant link (see
|
||||
|
|
@ -2504,6 +2562,20 @@ void ContentEnumFunc(const RuleValue& value, nsCSSSelector* aSelector,
|
|||
// We won't match; nothing else to do here
|
||||
return;
|
||||
}
|
||||
// If mOnlyMatchHostPseudo is set, then we only want to match against
|
||||
// selectors that contain a :host-context pseudo class.
|
||||
if (data->mTreeMatchContext.mOnlyMatchHostPseudo) {
|
||||
nsCSSSelector* selector = aSelector;
|
||||
while (selector && selector->mNext != nullptr) {
|
||||
selector = selector->mNext;
|
||||
}
|
||||
|
||||
bool seenHostPseudo = false;
|
||||
|
||||
if (!seenHostPseudo) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!data->mTreeMatchContext.SetStyleScopeForSelectorMatching(data->mElement,
|
||||
data->mScope)) {
|
||||
// The selector is for a rule in a scoped style sheet, and the subject
|
||||
|
|
@ -2563,7 +2635,8 @@ nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData)
|
|||
|
||||
if (cascade) {
|
||||
NodeMatchContext nodeContext(EventStates(),
|
||||
nsCSSRuleProcessor::IsLink(aData->mElement));
|
||||
nsCSSRuleProcessor::IsLink(aData->mElement),
|
||||
aData->mElementIsFeatureless);
|
||||
cascade->mRuleHash.EnumerateAllRules(aData->mElement, aData, nodeContext);
|
||||
}
|
||||
}
|
||||
|
|
@ -2847,6 +2920,24 @@ AttributeEnumFunc(nsCSSSelector* aSelector,
|
|||
nsRestyleHint possibleChange =
|
||||
RestyleHintForSelectorWithAttributeChange(aData->change,
|
||||
aSelector, aRightmostSelector);
|
||||
// If mOnlyMatchHostPseudo is set, then we only want to match against
|
||||
// selectors that contain a :host-context pseudo class.
|
||||
if (data->mTreeMatchContext.mOnlyMatchHostPseudo) {
|
||||
nsCSSSelector* selector = aSelector;
|
||||
while (selector && selector->mNext != nullptr) {
|
||||
selector = selector->mNext;
|
||||
}
|
||||
|
||||
bool seenHostPseudo = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!seenHostPseudo) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If, ignoring eRestyle_SomeDescendants, enumData->change already includes
|
||||
// all the bits of possibleChange, don't bother calling SelectorMatches, since
|
||||
|
|
@ -3318,7 +3409,7 @@ AddSelector(RuleCascadeData* aCascade,
|
|||
}
|
||||
}
|
||||
|
||||
// Recur through any :-moz-any selectors
|
||||
// Recur through any :-moz-any or :host-context selectors
|
||||
for (nsPseudoClassList* pseudoClass = negation->mPseudoClassList;
|
||||
pseudoClass; pseudoClass = pseudoClass->mNext) {
|
||||
if (pseudoClass->mType == CSSPseudoClassType::any) {
|
||||
|
|
@ -3970,6 +4061,7 @@ TreeMatchContext::InitAncestors(Element *aElement)
|
|||
for (uint32_t i = ancestors.Length(); i-- != 0; ) {
|
||||
mAncestorFilter.PushAncestor(ancestors[i]);
|
||||
PushStyleScope(ancestors[i]);
|
||||
PushShadowHost(ancestors[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue