mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 16:28:38 +09:00
Merge remote-tracking branch 'origin/tracking' into custom
This commit is contained in:
commit
a52c44343e
16 changed files with 359 additions and 179 deletions
|
|
@ -3438,9 +3438,9 @@ Element::Closest(const nsAString& aSelector, ErrorResult& aResult)
|
|||
matchingContext.AddScopeElement(this);
|
||||
for (nsINode* node = this; node; node = node->GetParentNode()) {
|
||||
if (node->IsElement() &&
|
||||
nsCSSRuleProcessor::SelectorListMatches(node->AsElement(),
|
||||
matchingContext,
|
||||
selectorList)) {
|
||||
nsCSSRuleProcessor::RestrictedSelectorListMatches(node->AsElement(),
|
||||
matchingContext,
|
||||
selectorList)) {
|
||||
return node->AsElement();
|
||||
}
|
||||
}
|
||||
|
|
@ -3464,8 +3464,9 @@ Element::Matches(const nsAString& aSelector, ErrorResult& aError)
|
|||
TreeMatchContext::eNeverMatchVisited);
|
||||
matchingContext.SetHasSpecifiedScope();
|
||||
matchingContext.AddScopeElement(this);
|
||||
return nsCSSRuleProcessor::SelectorListMatches(this, matchingContext,
|
||||
selectorList);
|
||||
return nsCSSRuleProcessor::RestrictedSelectorListMatches(this,
|
||||
matchingContext,
|
||||
selectorList);
|
||||
}
|
||||
|
||||
static const nsAttrValue::EnumTable kCORSAttributeTable[] = {
|
||||
|
|
|
|||
|
|
@ -2879,9 +2879,9 @@ FindMatchingElementsWithId(const nsAString& aId, nsINode* aRoot,
|
|||
// We have an element with the right id and it's a strict descendant
|
||||
// of aRoot. Make sure it really matches the selector.
|
||||
if (!aMatchInfo ||
|
||||
nsCSSRuleProcessor::SelectorListMatches(element,
|
||||
aMatchInfo->mMatchContext,
|
||||
aMatchInfo->mSelectorList)) {
|
||||
nsCSSRuleProcessor::RestrictedSelectorListMatches(element,
|
||||
aMatchInfo->mMatchContext,
|
||||
aMatchInfo->mSelectorList)) {
|
||||
aList.AppendElement(element);
|
||||
if (onlyFirstMatch) {
|
||||
return;
|
||||
|
|
@ -2932,9 +2932,9 @@ FindMatchingElements(nsINode* aRoot, nsCSSSelectorList* aSelectorList, T &aList,
|
|||
cur;
|
||||
cur = cur->GetNextNode(aRoot)) {
|
||||
if (cur->IsElement() &&
|
||||
nsCSSRuleProcessor::SelectorListMatches(cur->AsElement(),
|
||||
matchingContext,
|
||||
aSelectorList)) {
|
||||
nsCSSRuleProcessor::RestrictedSelectorListMatches(cur->AsElement(),
|
||||
matchingContext,
|
||||
aSelectorList)) {
|
||||
if (onlyFirstMatch) {
|
||||
aList.AppendElement(cur->AsElement());
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1740,6 +1740,10 @@ private:
|
|||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
if (pubKey->keyType != rsaKey) {
|
||||
return NS_ERROR_DOM_DATA_ERR;
|
||||
}
|
||||
|
||||
// Extract relevant information from the public key
|
||||
mModulusLength = 8 * pubKey->u.rsa.modulus.len;
|
||||
if (!mPublicExponent.Assign(&pubKey->u.rsa.publicExponent)) {
|
||||
|
|
@ -1873,6 +1877,10 @@ private:
|
|||
}
|
||||
|
||||
if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI)) {
|
||||
if (pubKey->keyType != ecKey) {
|
||||
return NS_ERROR_DOM_DATA_ERR;
|
||||
}
|
||||
|
||||
if (!CheckEncodedECParameters(&pubKey->u.ec.DEREncodedParams)) {
|
||||
return NS_ERROR_DOM_OPERATION_ERR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -557,34 +557,30 @@ FindErrorInstanceOrPrototype(JSContext* cx, HandleObject obj, MutableHandleObjec
|
|||
// (new NYI).stack
|
||||
// to continue returning stacks that are useless, but at least don't throw.
|
||||
|
||||
RootedObject target(cx, CheckedUnwrap(obj));
|
||||
if (!target) {
|
||||
JS_ReportErrorASCII(cx, "Permission denied to access object");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject proto(cx);
|
||||
while (!IsErrorProtoKey(StandardProtoKeyOrNull(target))) {
|
||||
if (!GetPrototype(cx, target, &proto))
|
||||
return false;
|
||||
|
||||
if (!proto) {
|
||||
// We walked the whole prototype chain and did not find an Error
|
||||
// object.
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
|
||||
js_Error_str, "(get stack)", obj->getClass()->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
target = CheckedUnwrap(proto);
|
||||
RootedObject curr(cx, obj);
|
||||
RootedObject target(cx);
|
||||
do {
|
||||
target = CheckedUnwrap(curr);
|
||||
if (!target) {
|
||||
JS_ReportErrorASCII(cx, "Permission denied to access object");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsErrorProtoKey(StandardProtoKeyOrNull(target))) {
|
||||
result.set(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
result.set(target);
|
||||
return true;
|
||||
if (!GetPrototype(cx, target, &curr)) {
|
||||
return false;
|
||||
}
|
||||
} while (curr);
|
||||
|
||||
// We walked the whole prototype chain and did not find an Error
|
||||
// object.
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
|
||||
js_Error_str, "(get stack)", obj->getClass()->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ inDOMUtils::SelectorMatchesElement(nsIDOMElement* aElement,
|
|||
}
|
||||
|
||||
// We have a matching pseudo element, now remove it so we can compare
|
||||
// directly against |element| when proceeding into SelectorListMatches.
|
||||
// directly against |element| when proceeding into RestrictedSelectorListMatches.
|
||||
// It's OK to do this - we just cloned sel and nothing else is using it.
|
||||
sel->RemoveRightmostSelector();
|
||||
}
|
||||
|
|
@ -476,8 +476,9 @@ inDOMUtils::SelectorMatchesElement(nsIDOMElement* aElement,
|
|||
nsRuleWalker::eRelevantLinkUnvisited,
|
||||
element->OwnerDoc(),
|
||||
TreeMatchContext::eNeverMatchVisited);
|
||||
*aMatches = nsCSSRuleProcessor::SelectorListMatches(element, matchingContext,
|
||||
sel);
|
||||
*aMatches = nsCSSRuleProcessor::RestrictedSelectorListMatches(element,
|
||||
matchingContext,
|
||||
sel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -149,11 +149,11 @@ nsPseudoClassList::nsPseudoClassList(CSSPseudoClassType aType,
|
|||
mNext(nullptr)
|
||||
{
|
||||
NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(aType) ||
|
||||
nsCSSPseudoClasses::HasOptionalSelectorListArg(aType),
|
||||
nsCSSPseudoClasses::HasOptionalSelectorListArg(aType),
|
||||
"unexpected pseudo-class");
|
||||
NS_ASSERTION(aSelectorList, "selector list expected");
|
||||
MOZ_COUNT_CTOR(nsPseudoClassList);
|
||||
u.mSelectors = aSelectorList;
|
||||
u.mSelectorList = aSelectorList;
|
||||
}
|
||||
|
||||
nsPseudoClassList*
|
||||
|
|
@ -170,7 +170,7 @@ nsPseudoClassList::Clone(bool aDeep) const
|
|||
NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(mType),
|
||||
"unexpected pseudo-class");
|
||||
// This constructor adopts its selector list argument.
|
||||
result = new nsPseudoClassList(mType, u.mSelectors->Clone());
|
||||
result = new nsPseudoClassList(mType, u.mSelectorList->Clone());
|
||||
}
|
||||
|
||||
if (aDeep)
|
||||
|
|
@ -199,7 +199,7 @@ nsPseudoClassList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) cons
|
|||
} else {
|
||||
NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(p->mType),
|
||||
"unexpected pseudo-class");
|
||||
n += p->u.mSelectors->SizeOfIncludingThis(aMallocSizeOf);
|
||||
n += p->u.mSelectorList->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
p = p->mNext;
|
||||
}
|
||||
|
|
@ -210,7 +210,7 @@ nsPseudoClassList::~nsPseudoClassList(void)
|
|||
{
|
||||
MOZ_COUNT_DTOR(nsPseudoClassList);
|
||||
if (nsCSSPseudoClasses::HasSelectorListArg(mType)) {
|
||||
delete u.mSelectors;
|
||||
delete u.mSelectorList;
|
||||
} else if (u.mMemory) {
|
||||
free(u.mMemory);
|
||||
}
|
||||
|
|
@ -537,14 +537,35 @@ int32_t nsCSSSelector::CalcWeightWithoutNegations() const
|
|||
weight += 0x000100;
|
||||
list = list->mNext;
|
||||
}
|
||||
// FIXME (bug 561154): This is incorrect for :-moz-any(), which isn't
|
||||
// really a pseudo-class. In order to handle :-moz-any() correctly,
|
||||
// we need to compute specificity after we match, based on which
|
||||
// option we matched with (and thus also need to try the
|
||||
// highest-specificity options first).
|
||||
nsPseudoClassList *plist = mPseudoClassList;
|
||||
while (nullptr != plist) {
|
||||
weight += 0x000100;
|
||||
int pseudoClassWeight = 0x000100;
|
||||
// XXX(franklindm): Check for correctness.
|
||||
if (nsCSSPseudoClasses::HasSelectorListArg(plist->mType) &&
|
||||
plist->mType != CSSPseudoClassType::mozAny) {
|
||||
// The specificity of :host() and :host-context is that of a
|
||||
// pseudo-class, plus the specificity of its argument.
|
||||
if (plist->mType != CSSPseudoClassType::host &&
|
||||
plist->mType != CSSPseudoClassType::hostContext) {
|
||||
pseudoClassWeight = 0;
|
||||
}
|
||||
// The specificity of the :where() pseudo-class is always zero.
|
||||
if (plist->mType != CSSPseudoClassType::where) {
|
||||
// The specificity of the :is() pseudo-class is replaced by the
|
||||
// specificity of its most specific argument.
|
||||
nsCSSSelectorList* slist = plist->u.mSelectorList;
|
||||
while (slist) {
|
||||
int currentWeight = slist->mSelectors ?
|
||||
slist->mWeight :
|
||||
0;
|
||||
if (currentWeight > pseudoClassWeight) {
|
||||
pseudoClassWeight = currentWeight;
|
||||
}
|
||||
slist = slist->mNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
weight += pseudoClassWeight;
|
||||
plist = plist->mNext;
|
||||
}
|
||||
nsAttrSelector* attr = mAttrList;
|
||||
|
|
@ -927,7 +948,7 @@ nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations
|
|||
NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(list->mType),
|
||||
"unexpected pseudo-class");
|
||||
nsString tmp;
|
||||
list->u.mSelectors->ToString(tmp, aSheet);
|
||||
list->u.mSelectorList->ToString(tmp, aSheet);
|
||||
aString.Append(tmp);
|
||||
}
|
||||
aString.Append(char16_t(')'));
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public:
|
|||
void* mMemory; // mString and mNumbers use moz_xmalloc/free
|
||||
char16_t* mString;
|
||||
int32_t* mNumbers;
|
||||
nsCSSSelectorList* mSelectors;
|
||||
nsCSSSelectorList* mSelectorList;
|
||||
} u;
|
||||
CSSPseudoClassType mType;
|
||||
nsPseudoClassList* mNext;
|
||||
|
|
|
|||
|
|
@ -780,7 +780,8 @@ protected:
|
|||
CSSPseudoClassType aType);
|
||||
|
||||
nsSelectorParsingStatus ParsePseudoClassWithSelectorListArg(nsCSSSelector& aSelector,
|
||||
CSSPseudoClassType aType);
|
||||
CSSPseudoClassType aType,
|
||||
bool aIsForgiving);
|
||||
|
||||
nsSelectorParsingStatus ParseNegatedSimpleSelector(int32_t& aDataMask,
|
||||
nsCSSSelector& aSelector);
|
||||
|
|
@ -788,9 +789,13 @@ protected:
|
|||
// If aStopChar is non-zero, the selector list is done when we hit
|
||||
// aStopChar. Otherwise, it's done when we hit EOF.
|
||||
bool ParseSelectorList(nsCSSSelectorList*& aListHead,
|
||||
char16_t aStopChar);
|
||||
bool ParseSelectorGroup(nsCSSSelectorList*& aListHead);
|
||||
bool ParseSelector(nsCSSSelectorList* aList, char16_t aPrevCombinator);
|
||||
char16_t aStopChar,
|
||||
bool aIsForgiving);
|
||||
bool ParseSelectorGroup(nsCSSSelectorList*& aListHead,
|
||||
bool aIsForgiving);
|
||||
bool ParseSelector(nsCSSSelectorList* aList,
|
||||
char16_t aPrevCombinator,
|
||||
bool aIsForgiving);
|
||||
|
||||
enum {
|
||||
eParseDeclaration_InBraces = 1 << 0,
|
||||
|
|
@ -2329,7 +2334,7 @@ CSSParserImpl::ParseSelectorString(const nsSubstring& aSelectorString,
|
|||
css::ErrorReporter reporter(scanner, mSheet, mChildLoader, aURI);
|
||||
InitScanner(scanner, reporter, aURI, aURI, nullptr);
|
||||
|
||||
bool success = ParseSelectorList(*aSelectorList, char16_t(0));
|
||||
bool success = ParseSelectorList(*aSelectorList, char16_t(0), false);
|
||||
|
||||
// We deliberately do not call OUTPUT_ERROR here, because all our
|
||||
// callers map a failure return to a JS exception, and if that JS
|
||||
|
|
@ -5411,7 +5416,7 @@ CSSParserImpl::ParseRuleSet(RuleAppendFunc aAppendFunc, void* aData,
|
|||
nsCSSSelectorList* slist = nullptr;
|
||||
uint32_t linenum, colnum;
|
||||
if (!GetNextTokenLocation(true, &linenum, &colnum) ||
|
||||
!ParseSelectorList(slist, char16_t('{'))) {
|
||||
!ParseSelectorList(slist, char16_t('{'), false)) {
|
||||
REPORT_UNEXPECTED(PEBadSelectorRSIgnored);
|
||||
OUTPUT_ERROR();
|
||||
SkipRuleSet(aInsideBraces);
|
||||
|
|
@ -5447,13 +5452,20 @@ CSSParserImpl::ParseRuleSet(RuleAppendFunc aAppendFunc, void* aData,
|
|||
|
||||
bool
|
||||
CSSParserImpl::ParseSelectorList(nsCSSSelectorList*& aListHead,
|
||||
char16_t aStopChar)
|
||||
char16_t aStopChar,
|
||||
bool aIsForgiving)
|
||||
{
|
||||
nsCSSSelectorList* list = nullptr;
|
||||
if (! ParseSelectorGroup(list)) {
|
||||
// must have at least one selector group
|
||||
aListHead = nullptr;
|
||||
return false;
|
||||
if (! ParseSelectorGroup(list, aIsForgiving)) {
|
||||
if (aIsForgiving) {
|
||||
// Initialize to an empty list if the first selector group was invalid
|
||||
// and we're a forgiving selector list.
|
||||
list = new nsCSSSelectorList();
|
||||
} else {
|
||||
// must have at least one selector group
|
||||
aListHead = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(nullptr != list, "no selector list");
|
||||
aListHead = list;
|
||||
|
|
@ -5475,11 +5487,22 @@ CSSParserImpl::ParseSelectorList(nsCSSSelectorList*& aListHead,
|
|||
if (',' == tk->mSymbol) {
|
||||
nsCSSSelectorList* newList = nullptr;
|
||||
// Another selector group must follow
|
||||
if (! ParseSelectorGroup(newList)) {
|
||||
if (! ParseSelectorGroup(newList, aIsForgiving)) {
|
||||
// Ignore invalid selectors if we're a forgiving selector list.
|
||||
if (aIsForgiving) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// add new list to the end of the selector list
|
||||
list->mNext = newList;
|
||||
// Replace the list head if: it's empty and we're a forgiving selector
|
||||
// list. Otherwise, add the new list to the end of the selector list.
|
||||
if (aIsForgiving && !aListHead->mSelectors) {
|
||||
MOZ_ASSERT(newList->mSelectors,
|
||||
"replacing empty list head with an empty selector list?");
|
||||
aListHead = newList;
|
||||
} else {
|
||||
list->mNext = newList;
|
||||
}
|
||||
list = newList;
|
||||
continue;
|
||||
} else if (aStopChar == tk->mSymbol && aStopChar != char16_t(0)) {
|
||||
|
|
@ -5487,9 +5510,12 @@ CSSParserImpl::ParseSelectorList(nsCSSSelectorList*& aListHead,
|
|||
return true;
|
||||
}
|
||||
}
|
||||
REPORT_UNEXPECTED_TOKEN(PESelectorListExtra);
|
||||
UngetToken();
|
||||
break;
|
||||
|
||||
if (!aIsForgiving) {
|
||||
REPORT_UNEXPECTED_TOKEN(PESelectorListExtra);
|
||||
UngetToken();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete aListHead;
|
||||
|
|
@ -5509,13 +5535,13 @@ static bool IsUniversalSelector(const nsCSSSelector& aSelector)
|
|||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParseSelectorGroup(nsCSSSelectorList*& aList)
|
||||
CSSParserImpl::ParseSelectorGroup(nsCSSSelectorList*& aList, bool aIsForgiving)
|
||||
{
|
||||
char16_t combinator = 0;
|
||||
nsAutoPtr<nsCSSSelectorList> list(new nsCSSSelectorList());
|
||||
|
||||
for (;;) {
|
||||
if (!ParseSelector(list, combinator)) {
|
||||
if (!ParseSelector(list, combinator, aIsForgiving)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -6148,8 +6174,11 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask,
|
|||
else {
|
||||
MOZ_ASSERT(nsCSSPseudoClasses::HasSelectorListArg(pseudoClassType),
|
||||
"unexpected pseudo with function token");
|
||||
bool isForgiving =
|
||||
nsCSSPseudoClasses::HasForgivingSelectorListArg(pseudoClassType);
|
||||
parsingStatus = ParsePseudoClassWithSelectorListArg(aSelector,
|
||||
pseudoClassType);
|
||||
pseudoClassType,
|
||||
isForgiving);
|
||||
}
|
||||
if (eSelectorParsingStatus_Continue != parsingStatus) {
|
||||
if (eSelectorParsingStatus_Error == parsingStatus) {
|
||||
|
|
@ -6523,18 +6552,29 @@ CSSParserImpl::ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
|
|||
//
|
||||
CSSParserImpl::nsSelectorParsingStatus
|
||||
CSSParserImpl::ParsePseudoClassWithSelectorListArg(nsCSSSelector& aSelector,
|
||||
CSSPseudoClassType aType)
|
||||
CSSPseudoClassType aType,
|
||||
bool aIsForgiving)
|
||||
{
|
||||
nsAutoPtr<nsCSSSelectorList> slist;
|
||||
if (! ParseSelectorList(*getter_Transfers(slist), char16_t(')'))) {
|
||||
if (! ParseSelectorList(*getter_Transfers(slist), char16_t(')'), aIsForgiving)) {
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
|
||||
if (nsCSSPseudoClasses::HasSingleSelectorArg(aType) &&
|
||||
slist->mNext) {
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
|
||||
// Check that none of the selectors in the list have combinators or
|
||||
// pseudo-elements.
|
||||
for (nsCSSSelectorList *l = slist; l; l = l->mNext) {
|
||||
nsCSSSelector *s = l->mSelectors;
|
||||
if (s->mNext || s->IsPseudoElement()) {
|
||||
if (s == nullptr) {
|
||||
MOZ_ASSERT(aIsForgiving,
|
||||
"unexpected empty selector in unforgiving selector list");
|
||||
break;
|
||||
}
|
||||
// Check that none of the selectors in the list have combinators or
|
||||
// pseudo-elements.
|
||||
if ((!aIsForgiving && s->mNext) || s->IsPseudoElement()) {
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
}
|
||||
|
|
@ -6558,7 +6598,8 @@ CSSParserImpl::ParsePseudoClassWithSelectorListArg(nsCSSSelector& aSelector,
|
|||
*/
|
||||
bool
|
||||
CSSParserImpl::ParseSelector(nsCSSSelectorList* aList,
|
||||
char16_t aPrevCombinator)
|
||||
char16_t aPrevCombinator,
|
||||
bool aIsForgiving)
|
||||
{
|
||||
if (! GetToken(true)) {
|
||||
REPORT_UNEXPECTED_EOF(PESelectorEOF);
|
||||
|
|
@ -6632,6 +6673,12 @@ CSSParserImpl::ParseSelector(nsCSSSelectorList* aList,
|
|||
}
|
||||
|
||||
if (!dataMask) {
|
||||
// XXX(franklindm): We're effectively ignoring stray combinators
|
||||
// and empty selector groups here for forgiving selector lists.
|
||||
// It doesn't seem right, but this is how tainted browsers do it.
|
||||
if (aIsForgiving) {
|
||||
return false;
|
||||
}
|
||||
if (selector->mNext) {
|
||||
REPORT_UNEXPECTED(PESelectorGroupExtraCombinator);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -74,7 +74,11 @@ CSS_PSEUDO_CLASS(mozEmptyExceptChildrenWithLocalname, ":-moz-empty-except-childr
|
|||
CSS_PSEUDO_CLASS(lang, ":lang", 0, "")
|
||||
CSS_PSEUDO_CLASS(mozBoundElement, ":-moz-bound-element", 0, "")
|
||||
CSS_PSEUDO_CLASS(root, ":root", 0, "")
|
||||
CSS_PSEUDO_CLASS(any, ":-moz-any", 0, "")
|
||||
CSS_PSEUDO_CLASS(mozAny, ":-moz-any", 0, "")
|
||||
CSS_PSEUDO_CLASS(is, ":is", 0, "layout.css.is-where-pseudo.enabled")
|
||||
CSS_PSEUDO_CLASS(matches, ":matches", 0, "layout.css.is-where-pseudo.enabled")
|
||||
CSS_PSEUDO_CLASS(any, ":any", 0, "layout.css.is-where-pseudo.enabled")
|
||||
CSS_PSEUDO_CLASS(where, ":where", 0, "layout.css.is-where-pseudo.enabled")
|
||||
|
||||
CSS_PSEUDO_CLASS(firstChild, ":first-child", 0, "")
|
||||
CSS_PSEUDO_CLASS(firstNode, ":-moz-first-node", 0, "")
|
||||
|
|
|
|||
|
|
@ -102,6 +102,13 @@ nsCSSPseudoClasses::HasNthPairArg(Type aType)
|
|||
aType == Type::nthLastOfType;
|
||||
}
|
||||
|
||||
bool
|
||||
nsCSSPseudoClasses::HasSingleSelectorArg(Type aType)
|
||||
{
|
||||
return aType == Type::host ||
|
||||
aType == Type::hostContext;
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSPseudoClasses::PseudoTypeToString(Type aType, nsAString& aString)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -58,10 +58,18 @@ public:
|
|||
static Type GetPseudoType(nsIAtom* aAtom, EnabledState aEnabledState);
|
||||
static bool HasStringArg(Type aType);
|
||||
static bool HasNthPairArg(Type aType);
|
||||
static bool HasSingleSelectorArg(Type aType);
|
||||
static bool HasForgivingSelectorListArg(Type aType) {
|
||||
return aType == Type::is ||
|
||||
aType == Type::matches ||
|
||||
aType == Type::any ||
|
||||
aType == Type::where;
|
||||
}
|
||||
static bool HasSelectorListArg(Type aType) {
|
||||
return aType == Type::any ||
|
||||
aType == Type::host ||
|
||||
aType == Type::hostContext;
|
||||
return HasForgivingSelectorListArg(aType) ||
|
||||
aType == Type::mozAny ||
|
||||
aType == Type::host ||
|
||||
aType == Type::hostContext;
|
||||
}
|
||||
static bool HasOptionalSelectorListArg(Type aType) {
|
||||
return aType == Type::host;
|
||||
|
|
|
|||
|
|
@ -1337,8 +1337,8 @@ struct NodeMatchContext {
|
|||
// node being matched that is itself or an ancestor.)
|
||||
//
|
||||
// Always false when TreeMatchContext::mForStyling is false. (We
|
||||
// could figure it out for SelectorListMatches, but we're starting
|
||||
// from the middle of the selector list when doing
|
||||
// could figure it out for RestrictedSelectorListMatches, but we're
|
||||
// starting from the middle of the selector list when doing
|
||||
// Has{Attribute,State}DependentStyle, so we can't tell. So when
|
||||
// mForStyling is false, we have to assume we don't know.)
|
||||
const bool mIsRelevantLink;
|
||||
|
|
@ -1640,10 +1640,20 @@ StateSelectorMatches(Element* aElement,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool AnySelectorInArgListMatches(Element* aElement,
|
||||
nsPseudoClassList* aList,
|
||||
NodeMatchContext& aNodeMatchContext,
|
||||
TreeMatchContext& aTreeMatchContext);
|
||||
static bool SelectorListMatches(Element* aElement,
|
||||
nsCSSSelectorList* aList,
|
||||
NodeMatchContext& aNodeMatchContext,
|
||||
TreeMatchContext& aTreeMatchContext,
|
||||
SelectorMatchesFlags aSelectorFlags,
|
||||
bool aIsForgiving = false,
|
||||
bool aPreventComplexSelectors = false);
|
||||
|
||||
static bool SelectorListMatches(Element* aElement,
|
||||
nsPseudoClassList* aList,
|
||||
NodeMatchContext& aNodeMatchContext,
|
||||
TreeMatchContext& aTreeMatchContext,
|
||||
bool aIsForgiving = false,
|
||||
bool aPreventComplexSelectors = false);
|
||||
|
||||
static bool
|
||||
StateSelectorMatches(Element* aElement,
|
||||
|
|
@ -1907,11 +1917,32 @@ static bool SelectorMatches(Element* aElement,
|
|||
}
|
||||
break;
|
||||
|
||||
case CSSPseudoClassType::is:
|
||||
case CSSPseudoClassType::matches:
|
||||
case CSSPseudoClassType::any:
|
||||
case CSSPseudoClassType::where:
|
||||
{
|
||||
if (!AnySelectorInArgListMatches(aElement, pseudoClass,
|
||||
aNodeMatchContext,
|
||||
aTreeMatchContext)) {
|
||||
if (!SelectorListMatches(aElement,
|
||||
pseudoClass,
|
||||
aNodeMatchContext,
|
||||
aTreeMatchContext,
|
||||
true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CSSPseudoClassType::mozAny:
|
||||
{
|
||||
// XXX: For compatibility, we retain :-moz-any()'s original behavior,
|
||||
// which is to be unforgiving and reject complex selectors in
|
||||
// its selector list argument.
|
||||
if (!SelectorListMatches(aElement,
|
||||
pseudoClass,
|
||||
aNodeMatchContext,
|
||||
aTreeMatchContext,
|
||||
false,
|
||||
true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1929,20 +1960,23 @@ static bool SelectorMatches(Element* aElement,
|
|||
// selector.
|
||||
|
||||
// We match automatically if GetParent() and GetShadowRoot() have
|
||||
// the same result. Without special casing this ahead of all other
|
||||
// selector matching, it fails. Have not determined the cause.
|
||||
|
||||
if (aElement->GetParent() == aElement->GetShadowRoot()) {
|
||||
// the same result iff our selector list is empty. Without special
|
||||
// casing this ahead of all other selector matching, it fails.
|
||||
// Have not determined the cause.
|
||||
if (!pseudoClass->u.mSelectorList &&
|
||||
aElement->GetParent() == aElement->GetShadowRoot()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Match if any selector in the argument list matches.
|
||||
|
||||
// FIXME: What this effectively does is bypass the "featureless"
|
||||
// selector check under SelectorMatches.
|
||||
NodeMatchContext nodeContext(EventStates(),
|
||||
nsCSSRuleProcessor::IsLink(aElement));
|
||||
if (AnySelectorInArgListMatches(aElement, pseudoClass,
|
||||
nodeContext,
|
||||
aTreeMatchContext)) {
|
||||
aNodeMatchContext.mIsRelevantLink);
|
||||
if (SelectorListMatches(aElement,
|
||||
pseudoClass,
|
||||
nodeContext,
|
||||
aTreeMatchContext)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1981,9 +2015,10 @@ static bool SelectorMatches(Element* aElement,
|
|||
while (currentElement) {
|
||||
NodeMatchContext nodeContext(EventStates(),
|
||||
nsCSSRuleProcessor::IsLink(currentElement));
|
||||
if (AnySelectorInArgListMatches(currentElement, pseudoClass,
|
||||
nodeContext,
|
||||
aTreeMatchContext)) {
|
||||
if (SelectorListMatches(currentElement,
|
||||
pseudoClass,
|
||||
nodeContext,
|
||||
aTreeMatchContext)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -2373,26 +2408,6 @@ 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
|
||||
|
|
@ -2401,7 +2416,7 @@ HasPseudoClassSelectorArgsWithCombinators(nsCSSSelector* aSelector)
|
|||
{
|
||||
for (nsPseudoClassList* p = aSelector->mPseudoClassList; p; p = p->mNext) {
|
||||
if (nsCSSPseudoClasses::HasSelectorListArg(p->mType)) {
|
||||
for (nsCSSSelectorList* l = p->u.mSelectors; l; l = l->mNext) {
|
||||
for (nsCSSSelectorList* l = p->u.mSelectorList; l; l = l->mNext) {
|
||||
if (l->mSelectors->mNext) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2637,6 +2652,70 @@ SelectorMatchesTree(Element* aPrevElement,
|
|||
return true; // all the selectors matched.
|
||||
}
|
||||
|
||||
static bool SelectorListMatches(Element* aElement,
|
||||
nsCSSSelectorList* aList,
|
||||
NodeMatchContext& aNodeMatchContext,
|
||||
TreeMatchContext& aTreeMatchContext,
|
||||
SelectorMatchesFlags aSelectorFlags,
|
||||
bool aIsForgiving,
|
||||
bool aPreventComplexSelectors)
|
||||
{
|
||||
while (aList) {
|
||||
nsCSSSelector *selector = aList->mSelectors;
|
||||
// Forgiving selector lists are allowed to be empty, but they
|
||||
// don't match anything.
|
||||
if (!selector && aIsForgiving) {
|
||||
return false;
|
||||
}
|
||||
NS_ASSERTION(selector, "Should have *some* selectors");
|
||||
NS_ASSERTION(!selector->IsPseudoElement(), "Shouldn't have been called");
|
||||
if (aPreventComplexSelectors) {
|
||||
NS_ASSERTION(!selector->mNext, "Shouldn't have complex selectors");
|
||||
}
|
||||
if (SelectorMatches(aElement,
|
||||
selector,
|
||||
aNodeMatchContext,
|
||||
aTreeMatchContext,
|
||||
aSelectorFlags)) {
|
||||
nsCSSSelector* next = selector->mNext;
|
||||
SelectorMatchesTreeFlags selectorTreeFlags = SelectorMatchesTreeFlags(0);
|
||||
// Try to look for the closest ancestor link element if we're processing
|
||||
// the selector list argument of a pseudo-class.
|
||||
if (!aNodeMatchContext.mIsRelevantLink &&
|
||||
(aSelectorFlags & SelectorMatchesFlags::IS_PSEUDO_CLASS_ARGUMENT)) {
|
||||
selectorTreeFlags = eLookForRelevantLink;
|
||||
}
|
||||
|
||||
if (!next ||
|
||||
SelectorMatchesTree(aElement,
|
||||
next,
|
||||
aTreeMatchContext,
|
||||
selectorTreeFlags)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
aList = aList->mNext;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool SelectorListMatches(Element* aElement,
|
||||
nsPseudoClassList* aList,
|
||||
NodeMatchContext& aNodeMatchContext,
|
||||
TreeMatchContext& aTreeMatchContext,
|
||||
bool aIsForgiving,
|
||||
bool aPreventComplexSelectors)
|
||||
{
|
||||
return SelectorListMatches(aElement,
|
||||
aList->u.mSelectorList,
|
||||
aNodeMatchContext,
|
||||
aTreeMatchContext,
|
||||
SelectorMatchesFlags::IS_PSEUDO_CLASS_ARGUMENT,
|
||||
aIsForgiving);
|
||||
}
|
||||
|
||||
static inline
|
||||
void ContentEnumFunc(const RuleValue& value, nsCSSSelector* aSelector,
|
||||
ElementDependentRuleProcessorData* data, NodeMatchContext& nodeContext,
|
||||
|
|
@ -3517,13 +3596,11 @@ AddSelector(RuleCascadeData* aCascade,
|
|||
}
|
||||
}
|
||||
|
||||
// Recur through any :-moz-any or :host-context selectors
|
||||
// Recur through any pseudo-class that has a selector list argument.
|
||||
for (nsPseudoClassList* pseudoClass = negation->mPseudoClassList;
|
||||
pseudoClass; pseudoClass = pseudoClass->mNext) {
|
||||
if (pseudoClass->mType == CSSPseudoClassType::any ||
|
||||
pseudoClass->mType == CSSPseudoClassType::host ||
|
||||
pseudoClass->mType == CSSPseudoClassType::hostContext) {
|
||||
for (nsCSSSelectorList *l = pseudoClass->u.mSelectors; l; l = l->mNext) {
|
||||
if (nsCSSPseudoClasses::HasSelectorListArg(pseudoClass->mType)) {
|
||||
for (nsCSSSelectorList *l = pseudoClass->u.mSelectorList; l; l = l->mNext) {
|
||||
nsCSSSelector *s = l->mSelectors;
|
||||
if (!AddSelector(aCascade, aSelectorInTopLevel, s,
|
||||
aRightmostSelector)) {
|
||||
|
|
@ -4075,33 +4152,20 @@ nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
|
|||
}
|
||||
|
||||
/* static */ bool
|
||||
nsCSSRuleProcessor::SelectorListMatches(Element* aElement,
|
||||
TreeMatchContext& aTreeMatchContext,
|
||||
nsCSSSelectorList* aSelectorList)
|
||||
nsCSSRuleProcessor::RestrictedSelectorListMatches(Element* aElement,
|
||||
TreeMatchContext& aTreeMatchContext,
|
||||
nsCSSSelectorList* aSelectorList)
|
||||
{
|
||||
MOZ_ASSERT(!aTreeMatchContext.mForScopedStyle,
|
||||
"mCurrentStyleScope will need to be saved and restored after the "
|
||||
"SelectorMatchesTree call");
|
||||
|
||||
while (aSelectorList) {
|
||||
nsCSSSelector* sel = aSelectorList->mSelectors;
|
||||
NS_ASSERTION(sel, "Should have *some* selectors");
|
||||
NS_ASSERTION(!sel->IsPseudoElement(), "Shouldn't have been called");
|
||||
NodeMatchContext nodeContext(EventStates(), false);
|
||||
if (SelectorMatches(aElement, sel, nodeContext, aTreeMatchContext,
|
||||
SelectorMatchesFlags::NONE)) {
|
||||
nsCSSSelector* next = sel->mNext;
|
||||
if (!next ||
|
||||
SelectorMatchesTree(aElement, next, aTreeMatchContext,
|
||||
SelectorMatchesTreeFlags(0))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
aSelectorList = aSelectorList->mNext;
|
||||
}
|
||||
|
||||
return false;
|
||||
NodeMatchContext nodeContext(EventStates(), false);
|
||||
return SelectorListMatches(aElement,
|
||||
aSelectorList,
|
||||
nodeContext,
|
||||
aTreeMatchContext,
|
||||
SelectorMatchesFlags::NONE);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -92,9 +92,9 @@ public:
|
|||
* include any pseudo-element selectors. aSelectorList is allowed
|
||||
* to be null; in this case false will be returned.
|
||||
*/
|
||||
static bool SelectorListMatches(mozilla::dom::Element* aElement,
|
||||
TreeMatchContext& aTreeMatchContext,
|
||||
nsCSSSelectorList* aSelectorList);
|
||||
static bool RestrictedSelectorListMatches(mozilla::dom::Element* aElement,
|
||||
TreeMatchContext& aTreeMatchContext,
|
||||
nsCSSSelectorList* aSelectorList);
|
||||
|
||||
/*
|
||||
* Helper to get the content state for a content node. This may be
|
||||
|
|
|
|||
|
|
@ -1006,6 +1006,50 @@ EmailConfigWizard.prototype =
|
|||
this.validateManualEditComplete();
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether OAuth2 is supported by current incoming hostname.
|
||||
*/
|
||||
checkIncomingSupportsOAuth2 : function() {
|
||||
#ifdef MOZ_MAILNEWS_OAUTH2
|
||||
var config = this.getUserConfig();
|
||||
|
||||
// If the hostname supports OAuth2 and imap is enabled, enable OAuth2.
|
||||
let iDetails = OAuth2Providers.getHostnameDetails(config.incoming.hostname);
|
||||
gEmailWizardLogger.info("OAuth2 details for incoming hostname " +
|
||||
config.incoming.hostname + " is " + iDetails);
|
||||
e("in-authMethod-oauth2").hidden = !(iDetails && e("incoming_protocol").value == 1);
|
||||
if (!e("in-authMethod-oauth2").hidden) {
|
||||
config.oauthSettings = {};
|
||||
[config.oauthSettings.issuer, config.oauthSettings.scope] = iDetails;
|
||||
// oauthsettings are not stored nor changable in the user interface, so just
|
||||
// store them in the base configuration.
|
||||
this._currentConfig.oauthSettings = config.oauthSettings;
|
||||
}
|
||||
#endif
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether OAuth2 is supported by current outgoing hostname.
|
||||
*/
|
||||
checkOutgoingSupportsOAuth2 : function() {
|
||||
#ifdef MOZ_MAILNEWS_OAUTH2
|
||||
var config = this.getUserConfig();
|
||||
|
||||
// If the hostname supports OAuth2 and imap is enabled, enable OAuth2.
|
||||
let oDetails = OAuth2Providers.getHostnameDetails(config.outgoing.hostname);
|
||||
gEmailWizardLogger.info("OAuth2 details for outgoing hostname " +
|
||||
config.outgoing.hostname + " is " + oDetails);
|
||||
e("out-authMethod-oauth2").hidden = !oDetails;
|
||||
if (!e("out-authMethod-oauth2").hidden) {
|
||||
config.oauthSettings = {};
|
||||
[config.oauthSettings.issuer, config.oauthSettings.scope] = oDetails;
|
||||
// oauthsettings are not stored nor changable in the user interface, so just
|
||||
// store them in the base configuration.
|
||||
this._currentConfig.oauthSettings = config.oauthSettings;
|
||||
}
|
||||
#endif
|
||||
},
|
||||
|
||||
/**
|
||||
* Fills the manual edit textfields with the provided config.
|
||||
* @param config {AccountConfig} The config to present to user
|
||||
|
|
@ -1034,20 +1078,7 @@ EmailConfigWizard.prototype =
|
|||
}
|
||||
this.fillPortDropdown(config.incoming.type);
|
||||
|
||||
#ifdef MOZ_MAILNEWS_OAUTH2
|
||||
// If the hostname supports OAuth2 and imap is enabled, enable OAuth2.
|
||||
let iDetails = OAuth2Providers.getHostnameDetails(config.incoming.hostname);
|
||||
gEmailWizardLogger.info("OAuth2 details for incoming hostname " +
|
||||
config.incoming.hostname + " is " + iDetails);
|
||||
e("in-authMethod-oauth2").hidden = !(iDetails && e("incoming_protocol").value == 1);
|
||||
if (!e("in-authMethod-oauth2").hidden) {
|
||||
config.oauthSettings = {};
|
||||
[config.oauthSettings.issuer, config.oauthSettings.scope] = iDetails;
|
||||
// oauthsettings are not stored nor changable in the user interface, so just
|
||||
// store them in the base configuration.
|
||||
this._currentConfig.oauthSettings = config.oauthSettings;
|
||||
}
|
||||
#endif
|
||||
this.checkIncomingSupportsOAuth2();
|
||||
|
||||
// outgoing server
|
||||
e("outgoing_hostname").value = config.outgoing.hostname;
|
||||
|
|
@ -1065,20 +1096,7 @@ EmailConfigWizard.prototype =
|
|||
this.adjustOutgoingPortToSSLAndProtocol(config);
|
||||
}
|
||||
|
||||
#ifdef MOZ_MAILNEWS_OAUTH2
|
||||
// If the hostname supports OAuth2 and imap is enabled, enable OAuth2.
|
||||
let oDetails = OAuth2Providers.getHostnameDetails(config.outgoing.hostname);
|
||||
gEmailWizardLogger.info("OAuth2 details for outgoing hostname " +
|
||||
config.outgoing.hostname + " is " + oDetails);
|
||||
e("out-authMethod-oauth2").hidden = !oDetails;
|
||||
if (!e("out-authMethod-oauth2").hidden) {
|
||||
config.oauthSettings = {};
|
||||
[config.oauthSettings.issuer, config.oauthSettings.scope] = oDetails;
|
||||
// oauthsettings are not stored nor changable in the user interface, so just
|
||||
// store them in the base configuration.
|
||||
this._currentConfig.oauthSettings = config.oauthSettings;
|
||||
}
|
||||
#endif
|
||||
this.checkOutgoingSupportsOAuth2();
|
||||
|
||||
// populate fields even if existingServerKey, in case user changes back
|
||||
if (config.outgoing.existingServerKey) {
|
||||
|
|
|
|||
|
|
@ -276,6 +276,7 @@
|
|||
</menulist>
|
||||
<textbox id="incoming_hostname"
|
||||
oninput="gEmailConfigWizard.onInputHostname();"
|
||||
onblur="gEmailConfigWizard.checkIncomingSupportsOAuth2();"
|
||||
class="host uri-element"/>
|
||||
<menulist id="incoming_port"
|
||||
editable="true"
|
||||
|
|
@ -325,6 +326,7 @@
|
|||
editable="true"
|
||||
sizetopopup="none"
|
||||
oninput="gEmailConfigWizard.onInputHostname();"
|
||||
onblur="gEmailConfigWizard.checkOutgoingSupportsOAuth2();"
|
||||
oncommand="gEmailConfigWizard.onChangedOutgoingDropdown();"
|
||||
onpopupshowing="gEmailConfigWizard.onOpenOutgoingDropdown();"
|
||||
class="host uri-element">
|
||||
|
|
|
|||
|
|
@ -2558,6 +2558,9 @@ pref("layout.css.prefixes.webkit", true);
|
|||
// pref is set to false.)
|
||||
pref("layout.css.prefixes.device-pixel-ratio-webkit", false);
|
||||
|
||||
// Is support for the :is() and :where() selectors enabled?
|
||||
pref("layout.css.is-where-pseudo.enabled", true);
|
||||
|
||||
// Is support for the :scope selector enabled?
|
||||
pref("layout.css.scope-pseudo.enabled", true);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue