mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Add support for :dir(ltr/rtl) CSS selector, layout/style part. Bug 562159, r=bz
This commit is contained in:
parent
4a67200814
commit
1c6ba0a43d
@ -248,6 +248,10 @@ private:
|
|||||||
#define NS_EVENT_STATE_VULNERABLE_NO_UPDATE NS_DEFINE_EVENT_STATE_MACRO(41)
|
#define NS_EVENT_STATE_VULNERABLE_NO_UPDATE NS_DEFINE_EVENT_STATE_MACRO(41)
|
||||||
// Platform does not support plugin content (some mobile platforms)
|
// Platform does not support plugin content (some mobile platforms)
|
||||||
#define NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM NS_DEFINE_EVENT_STATE_MACRO(42)
|
#define NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM NS_DEFINE_EVENT_STATE_MACRO(42)
|
||||||
|
// Element is ltr (for :dir pseudo-class)
|
||||||
|
#define NS_EVENT_STATE_LTR NS_DEFINE_EVENT_STATE_MACRO(43)
|
||||||
|
// Element is rtl (for :dir pseudo-class)
|
||||||
|
#define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(44)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: do not go over 63 without updating nsEventStates::InternalType!
|
* NOTE: do not go over 63 without updating nsEventStates::InternalType!
|
||||||
|
@ -49,6 +49,7 @@ public:
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
|
NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
|
||||||
"Unexpected namespace");
|
"Unexpected namespace");
|
||||||
|
AddStatesSilently(NS_EVENT_STATE_LTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Typesafe, non-refcounting cast from nsIContent. Cheaper than QI. **/
|
/** Typesafe, non-refcounting cast from nsIContent. Cheaper than QI. **/
|
||||||
|
@ -114,6 +114,7 @@ PEMQExpectedFeatureValue=Found invalid value for media feature.
|
|||||||
PEBadFontBlockStart=Expected '{' to begin @font-face rule but found '%1$S'.
|
PEBadFontBlockStart=Expected '{' to begin @font-face rule but found '%1$S'.
|
||||||
PEBadFontBlockEnd=Expected '}' to end @font-face rule but found '%1$S'.
|
PEBadFontBlockEnd=Expected '}' to end @font-face rule but found '%1$S'.
|
||||||
PEAnonBoxNotAlone=Did not expect anonymous box.
|
PEAnonBoxNotAlone=Did not expect anonymous box.
|
||||||
|
PEBadDirValue=Expected 'ltr' or 'rtl' in direction selector but found '%1$S'.
|
||||||
PESupportsConditionStartEOF='not' or '('
|
PESupportsConditionStartEOF='not' or '('
|
||||||
PESupportsConditionInParensStartEOF='not', '(' or identifier
|
PESupportsConditionInParensStartEOF='not', '(' or identifier
|
||||||
PESupportsConditionNotEOF='not'
|
PESupportsConditionNotEOF='not'
|
||||||
|
@ -3595,10 +3595,12 @@ CSSParserImpl::ParsePseudoClassWithIdentArg(nsCSSSelector& aSelector,
|
|||||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||||
}
|
}
|
||||||
|
|
||||||
// -moz-locale-dir can only have values of 'ltr' or 'rtl'.
|
// -moz-locale-dir and :dir can only have values of 'ltr' or 'rtl'.
|
||||||
if (aType == nsCSSPseudoClasses::ePseudoClass_mozLocaleDir) {
|
if (aType == nsCSSPseudoClasses::ePseudoClass_mozLocaleDir ||
|
||||||
|
aType == nsCSSPseudoClasses::ePseudoClass_dir) {
|
||||||
if (!mToken.mIdent.EqualsLiteral("ltr") &&
|
if (!mToken.mIdent.EqualsLiteral("ltr") &&
|
||||||
!mToken.mIdent.EqualsLiteral("rtl")) {
|
!mToken.mIdent.EqualsLiteral("rtl")) {
|
||||||
|
REPORT_UNEXPECTED_TOKEN(PEBadDirValue);
|
||||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,27 +9,45 @@
|
|||||||
* This file contains the list of nsIAtoms and their values for CSS
|
* This file contains the list of nsIAtoms and their values for CSS
|
||||||
* pseudo-classes. It is designed to be used as inline input to
|
* pseudo-classes. It is designed to be used as inline input to
|
||||||
* nsCSSPseudoClasses.cpp *only* through the magic of C preprocessing.
|
* nsCSSPseudoClasses.cpp *only* through the magic of C preprocessing.
|
||||||
* All entries must be enclosed in the macros CSS_PSEUDO_CLASS or
|
* All entries must be enclosed in the macros CSS_PSEUDO_CLASS,
|
||||||
* CSS_STATE_PSEUDO_CLASS which will have cruel and unusual things
|
* CSS_STATE_DEPENDENT_PSEUDO_CLASS, or CSS_STATE_PSEUDO_CLASS which
|
||||||
* done to it. The entries should be kept in some sort of logical
|
* will have cruel and unusual things done to them. The entries should
|
||||||
* order. The first argument to CSS_PSEUDO_CLASS is the C++
|
* be kept in some sort of logical order. The first argument to
|
||||||
* identifier of the atom. The second argument is the string value of
|
* CSS_PSEUDO_CLASS is the C++ identifier of the atom. The second
|
||||||
* the atom. CSS_STATE_PSEUDO_CLASS also takes the name of the state
|
* argument is the string value of the atom.
|
||||||
* bits that the class corresponds to. Only one of the bits needs to
|
* CSS_STATE_DEPENDENT_PSEUDO_CLASS and CSS_STATE_PSEUDO_CLASS also take
|
||||||
* match for the pseudo-class to match. If CSS_STATE_PSEUDO_CLASS is
|
* the name of the state bits that the class corresponds to. Only one
|
||||||
* not defined, it'll be automatically defined to CSS_PSEUDO_CLASS.
|
* of the bits needs to match for a CSS_STATE_PSEUDO_CLASS to match;
|
||||||
|
* CSS_STATE_DEPENDENT_PSEUDO_CLASS matching depends on a customized per-class
|
||||||
|
* algorithm which should be defined in SelectorMatches() in
|
||||||
|
* nsCSSRuleProcessor.cpp.
|
||||||
|
*
|
||||||
|
* If CSS_STATE_PSEUDO_CLASS is not defined, it'll be automatically
|
||||||
|
* defined to CSS_STATE_DEPENDENT_PSEUDO_CLASS;
|
||||||
|
* if CSS_STATE_DEPENDENT_PSEUDO_CLASS is not defined, it'll be
|
||||||
|
* automatically defined to CSS_PSEUDO_CLASS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// OUTPUT_CLASS=nsCSSPseudoClasses
|
// OUTPUT_CLASS=nsCSSPseudoClasses
|
||||||
// MACRO_NAME=CSS_PSEUDO_CLASS
|
// MACRO_NAME=CSS_PSEUDO_CLASS
|
||||||
|
|
||||||
|
#ifdef DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||||
|
#error "CSS_STATE_DEPENDENT_PSEUDO_CLASS shouldn't be defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||||
|
#define CSS_STATE_DEPENDENT_PSEUDO_CLASS(_name, _value, _bit) \
|
||||||
|
CSS_PSEUDO_CLASS(_name, _value)
|
||||||
|
#define DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEFINED_CSS_STATE_PSEUDO_CLASS
|
#ifdef DEFINED_CSS_STATE_PSEUDO_CLASS
|
||||||
#error "This shouldn't be defined"
|
#error "CSS_STATE_PSEUDO_CLASS shouldn't be defined"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CSS_STATE_PSEUDO_CLASS
|
#ifndef CSS_STATE_PSEUDO_CLASS
|
||||||
#define CSS_STATE_PSEUDO_CLASS(_name, _value, _bit) \
|
#define CSS_STATE_PSEUDO_CLASS(_name, _value, _bit) \
|
||||||
CSS_PSEUDO_CLASS(_name, _value)
|
CSS_STATE_DEPENDENT_PSEUDO_CLASS(_name, _value, _bit)
|
||||||
#define DEFINED_CSS_STATE_PSEUDO_CLASS
|
#define DEFINED_CSS_STATE_PSEUDO_CLASS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -90,6 +108,11 @@ CSS_PSEUDO_CLASS(mozTableBorderNonzero, ":-moz-table-border-nonzero")
|
|||||||
// it doesn't actually get directly matched on in SelectorMatches.
|
// it doesn't actually get directly matched on in SelectorMatches.
|
||||||
CSS_PSEUDO_CLASS(notPseudo, ":not")
|
CSS_PSEUDO_CLASS(notPseudo, ":not")
|
||||||
|
|
||||||
|
// :dir(ltr) and :dir(rtl) match elements whose resolved directionality
|
||||||
|
// in the markup language is ltr or rtl respectively
|
||||||
|
CSS_STATE_DEPENDENT_PSEUDO_CLASS(dir, ":dir",
|
||||||
|
NS_EVENT_STATE_LTR | NS_EVENT_STATE_RTL)
|
||||||
|
|
||||||
CSS_STATE_PSEUDO_CLASS(link, ":link", NS_EVENT_STATE_UNVISITED)
|
CSS_STATE_PSEUDO_CLASS(link, ":link", NS_EVENT_STATE_UNVISITED)
|
||||||
// what matches :link or :visited
|
// what matches :link or :visited
|
||||||
CSS_STATE_PSEUDO_CLASS(mozAnyLink, ":-moz-any-link",
|
CSS_STATE_PSEUDO_CLASS(mozAnyLink, ":-moz-any-link",
|
||||||
@ -178,3 +201,8 @@ CSS_STATE_PSEUDO_CLASS(mozMeterSubSubOptimum, ":-moz-meter-sub-sub-optimum",
|
|||||||
#undef DEFINED_CSS_STATE_PSEUDO_CLASS
|
#undef DEFINED_CSS_STATE_PSEUDO_CLASS
|
||||||
#undef CSS_STATE_PSEUDO_CLASS
|
#undef CSS_STATE_PSEUDO_CLASS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||||
|
#undef DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||||
|
#undef CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||||
|
#endif
|
||||||
|
@ -42,7 +42,8 @@ nsCSSPseudoClasses::HasStringArg(Type aType)
|
|||||||
return aType == ePseudoClass_lang ||
|
return aType == ePseudoClass_lang ||
|
||||||
aType == ePseudoClass_mozEmptyExceptChildrenWithLocalname ||
|
aType == ePseudoClass_mozEmptyExceptChildrenWithLocalname ||
|
||||||
aType == ePseudoClass_mozSystemMetric ||
|
aType == ePseudoClass_mozSystemMetric ||
|
||||||
aType == ePseudoClass_mozLocaleDir;
|
aType == ePseudoClass_mozLocaleDir ||
|
||||||
|
aType == ePseudoClass_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -1308,7 +1308,7 @@ struct NodeMatchContext {
|
|||||||
// event-state-dependent selector for any value of that event state.
|
// event-state-dependent selector for any value of that event state.
|
||||||
// So mStateMask contains the states that should NOT be tested.
|
// So mStateMask contains the states that should NOT be tested.
|
||||||
//
|
//
|
||||||
// NOTE: For |aStateMask| to work correctly, it's important that any
|
// NOTE: For |mStateMask| to work correctly, it's important that any
|
||||||
// change that changes multiple state bits include all those state
|
// change that changes multiple state bits include all those state
|
||||||
// bits in the notification. Otherwise, if multiple states change but
|
// bits in the notification. Otherwise, if multiple states change but
|
||||||
// we do separate notifications then we might determine the style is
|
// we do separate notifications then we might determine the style is
|
||||||
@ -1533,7 +1533,21 @@ checkGenericEmptyMatches(Element* aElement,
|
|||||||
return (child == nullptr);
|
return (child == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// An array of the states that are relevant for various pseudoclasses.
|
// Arrays of the states that are relevant for various pseudoclasses.
|
||||||
|
static const nsEventStates sPseudoClassStateDependences[] = {
|
||||||
|
#define CSS_PSEUDO_CLASS(_name, _value) \
|
||||||
|
nsEventStates(),
|
||||||
|
#define CSS_STATE_DEPENDENT_PSEUDO_CLASS(_name, _value, _states) \
|
||||||
|
_states,
|
||||||
|
#include "nsCSSPseudoClassList.h"
|
||||||
|
#undef CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||||
|
#undef CSS_PSEUDO_CLASS
|
||||||
|
// Add more entries for our fake values to make sure we can't
|
||||||
|
// index out of bounds into this array no matter what.
|
||||||
|
nsEventStates(),
|
||||||
|
nsEventStates()
|
||||||
|
};
|
||||||
|
|
||||||
static const nsEventStates sPseudoClassStates[] = {
|
static const nsEventStates sPseudoClassStates[] = {
|
||||||
#define CSS_PSEUDO_CLASS(_name, _value) \
|
#define CSS_PSEUDO_CLASS(_name, _value) \
|
||||||
nsEventStates(),
|
nsEventStates(),
|
||||||
@ -1556,7 +1570,7 @@ MOZ_STATIC_ASSERT(NS_ARRAY_LENGTH(sPseudoClassStates) ==
|
|||||||
// * when non-null, it indicates that we're processing a negation,
|
// * when non-null, it indicates that we're processing a negation,
|
||||||
// which is done only when SelectorMatches calls itself recursively
|
// which is done only when SelectorMatches calls itself recursively
|
||||||
// * what it points to should be set to true whenever a test is skipped
|
// * what it points to should be set to true whenever a test is skipped
|
||||||
// because of aStateMask
|
// because of aNodeMatchContent.mStateMask
|
||||||
static bool SelectorMatches(Element* aElement,
|
static bool SelectorMatches(Element* aElement,
|
||||||
nsCSSSelector* aSelector,
|
nsCSSSelector* aSelector,
|
||||||
NodeMatchContext& aNodeMatchContext,
|
NodeMatchContext& aNodeMatchContext,
|
||||||
@ -1997,6 +2011,38 @@ static bool SelectorMatches(Element* aElement,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case nsCSSPseudoClasses::ePseudoClass_dir:
|
||||||
|
{
|
||||||
|
if (aDependence) {
|
||||||
|
nsEventStates states
|
||||||
|
= sPseudoClassStateDependences[pseudoClass->mType];
|
||||||
|
if (aNodeMatchContext.mStateMask.HasAtLeastOneOfStates(states)) {
|
||||||
|
*aDependence = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we only had to consider HTML, directionality would be exclusively
|
||||||
|
// LTR or RTL, and this could be just
|
||||||
|
//
|
||||||
|
// if (dirString.EqualsLiteral("rtl") !=
|
||||||
|
// aElement->StyleState().HasState(NS_EVENT_STATE_RTL)
|
||||||
|
//
|
||||||
|
// However, in markup languages where there is no direction attribute
|
||||||
|
// we have to consider the possibility that neither dir(rtl) nor
|
||||||
|
// dir(ltr) matches.
|
||||||
|
nsEventStates state = aElement->StyleState();
|
||||||
|
bool elementIsRTL = state.HasState(NS_EVENT_STATE_RTL);
|
||||||
|
bool elementIsLTR = state.HasState(NS_EVENT_STATE_LTR);
|
||||||
|
nsDependentString dirString(pseudoClass->u.mString);
|
||||||
|
|
||||||
|
if ((dirString.EqualsLiteral("rtl") && !elementIsRTL) ||
|
||||||
|
(dirString.EqualsLiteral("ltr") && !elementIsLTR)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
NS_ABORT_IF_FALSE(false, "How did that happen?");
|
NS_ABORT_IF_FALSE(false, "How did that happen?");
|
||||||
}
|
}
|
||||||
@ -2128,10 +2174,10 @@ static bool SelectorMatches(Element* aElement,
|
|||||||
bool dependence = false;
|
bool dependence = false;
|
||||||
result = !SelectorMatches(aElement, negation, aNodeMatchContext,
|
result = !SelectorMatches(aElement, negation, aNodeMatchContext,
|
||||||
aTreeMatchContext, &dependence);
|
aTreeMatchContext, &dependence);
|
||||||
// If the selector does match due to the dependence on aStateMask,
|
// If the selector does match due to the dependence on
|
||||||
// then we want to keep result true so that the final result of
|
// aNodeMatchContext.mStateMask, then we want to keep result true
|
||||||
// SelectorMatches is true. Doing so tells StateEnumFunc that
|
// so that the final result of SelectorMatches is true. Doing so
|
||||||
// there is a dependence on the state.
|
// tells StateEnumFunc that there is a dependence on the state.
|
||||||
result = result || dependence;
|
result = result || dependence;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2665,7 +2711,7 @@ nsEventStates ComputeSelectorStateDependence(nsCSSSelector& aSelector)
|
|||||||
if (pseudoClass->mType >= nsCSSPseudoClasses::ePseudoClass_Count) {
|
if (pseudoClass->mType >= nsCSSPseudoClasses::ePseudoClass_Count) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
states |= sPseudoClassStates[pseudoClass->mType];
|
states |= sPseudoClassStateDependences[pseudoClass->mType];
|
||||||
}
|
}
|
||||||
return states;
|
return states;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user