diff --git a/js/src/builtin/intl/NumberFormat.cpp b/js/src/builtin/intl/NumberFormat.cpp index 4fc08a0920..1fe6b8299f 100644 --- a/js/src/builtin/intl/NumberFormat.cpp +++ b/js/src/builtin/intl/NumberFormat.cpp @@ -839,7 +839,7 @@ intl_FormatNumberToParts(JSContext* cx, UNumberFormat* nf, double x, MutableHand partIndex++; } while (true); - MOZ_ASSERT(lastEndIndex == chars.length(), + MOZ_ASSERT(lastEndIndex == overallResult->length(), "result array must partition the entire string"); result.setObject(*partsArray); diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 0d031e9cac..bb2e40d8cb 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -764,7 +764,8 @@ protected: bool aIsNegated, nsIAtom** aPseudoElement, nsAtomList** aPseudoElementArgs, - CSSPseudoElementType* aPseudoElementType); + CSSPseudoElementType* aPseudoElementType, + bool aDisallowCombinators); nsSelectorParsingStatus ParseAttributeSelector(int32_t& aDataMask, nsCSSSelector& aSelector); @@ -781,7 +782,7 @@ protected: nsSelectorParsingStatus ParsePseudoClassWithSelectorListArg(nsCSSSelector& aSelector, CSSPseudoClassType aType, - bool aIsForgiving); + bool aDisallowCombinators); nsSelectorParsingStatus ParseNegatedSimpleSelector(int32_t& aDataMask, nsCSSSelector& aSelector); @@ -790,12 +791,15 @@ protected: // aStopChar. Otherwise, it's done when we hit EOF. bool ParseSelectorList(nsCSSSelectorList*& aListHead, char16_t aStopChar, - bool aIsForgiving); + bool aIsForgiving, + bool aDisallowCombinators); bool ParseSelectorGroup(nsCSSSelectorList*& aListHead, - bool aIsForgiving); + bool aIsForgiving, + bool aDisallowCombinators); bool ParseSelector(nsCSSSelectorList* aList, char16_t aPrevCombinator, - bool aIsForgiving); + bool aIsForgiving, + bool aDisallowCombinators); enum { eParseDeclaration_InBraces = 1 << 0, @@ -2334,7 +2338,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), false); + bool success = ParseSelectorList(*aSelectorList, char16_t(0), false, 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 @@ -5416,7 +5420,7 @@ CSSParserImpl::ParseRuleSet(RuleAppendFunc aAppendFunc, void* aData, nsCSSSelectorList* slist = nullptr; uint32_t linenum, colnum; if (!GetNextTokenLocation(true, &linenum, &colnum) || - !ParseSelectorList(slist, char16_t('{'), false)) { + !ParseSelectorList(slist, char16_t('{'), false, false)) { REPORT_UNEXPECTED(PEBadSelectorRSIgnored); OUTPUT_ERROR(); SkipRuleSet(aInsideBraces); @@ -5453,10 +5457,11 @@ CSSParserImpl::ParseRuleSet(RuleAppendFunc aAppendFunc, void* aData, bool CSSParserImpl::ParseSelectorList(nsCSSSelectorList*& aListHead, char16_t aStopChar, - bool aIsForgiving) + bool aIsForgiving, + bool aDisallowCombinators) { nsCSSSelectorList* list = nullptr; - if (! ParseSelectorGroup(list, aIsForgiving)) { + if (! ParseSelectorGroup(list, aIsForgiving, aDisallowCombinators)) { if (aIsForgiving) { // Initialize to an empty list if the first selector group was invalid // and we're a forgiving selector list. @@ -5487,7 +5492,7 @@ CSSParserImpl::ParseSelectorList(nsCSSSelectorList*& aListHead, if (',' == tk->mSymbol) { nsCSSSelectorList* newList = nullptr; // Another selector group must follow - if (! ParseSelectorGroup(newList, aIsForgiving)) { + if (! ParseSelectorGroup(newList, aIsForgiving, aDisallowCombinators)) { // Ignore invalid selectors if we're a forgiving selector list. if (aIsForgiving) { continue; @@ -5535,13 +5540,13 @@ static bool IsUniversalSelector(const nsCSSSelector& aSelector) } bool -CSSParserImpl::ParseSelectorGroup(nsCSSSelectorList*& aList, bool aIsForgiving) +CSSParserImpl::ParseSelectorGroup(nsCSSSelectorList*& aList, bool aIsForgiving, bool aDisallowCombinators) { char16_t combinator = 0; nsAutoPtr list(new nsCSSSelectorList()); for (;;) { - if (!ParseSelector(list, combinator, aIsForgiving)) { + if (!ParseSelector(list, combinator, aIsForgiving, aDisallowCombinators)) { return false; } @@ -5576,6 +5581,10 @@ CSSParserImpl::ParseSelectorGroup(nsCSSSelectorList*& aList, bool aIsForgiving) REPORT_UNEXPECTED_TOKEN(PESelectorListExtra); return false; } + + if (aIsForgiving && aDisallowCombinators) { + return false; + } } aList = list.forget(); @@ -6000,7 +6009,8 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask, bool aIsNegated, nsIAtom** aPseudoElement, nsAtomList** aPseudoElementArgs, - CSSPseudoElementType* aPseudoElementType) + CSSPseudoElementType* aPseudoElementType, + bool aDisallowCombinators) { NS_ASSERTION(aIsNegated || (aPseudoElement && aPseudoElementArgs), "expected location to store pseudo element"); @@ -6174,11 +6184,9 @@ 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, - isForgiving); + aDisallowCombinators); } if (eSelectorParsingStatus_Continue != parsingStatus) { if (eSelectorParsingStatus_Error == parsingStatus) { @@ -6310,7 +6318,8 @@ CSSParserImpl::ParseNegatedSimpleSelector(int32_t& aDataMask, } else if (mToken.IsSymbol(':')) { // :pseudo parsingStatus = ParsePseudoSelector(aDataMask, *newSel, true, - nullptr, nullptr, nullptr); + nullptr, nullptr, nullptr, + false); } else if (mToken.IsSymbol('[')) { // [attribute parsingStatus = ParseAttributeSelector(aDataMask, *newSel); @@ -6553,28 +6562,39 @@ CSSParserImpl::ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector, CSSParserImpl::nsSelectorParsingStatus CSSParserImpl::ParsePseudoClassWithSelectorListArg(nsCSSSelector& aSelector, CSSPseudoClassType aType, - bool aIsForgiving) + bool aDisallowCombinators) { + bool isForgiving = + nsCSSPseudoClasses::HasForgivingSelectorListArg(aType); + bool isSingleSelector = + nsCSSPseudoClasses::HasSingleSelectorArg(aType); + + if (isSingleSelector && !aDisallowCombinators) { + aDisallowCombinators = true; + } + nsAutoPtr slist; - if (! ParseSelectorList(*getter_Transfers(slist), char16_t(')'), aIsForgiving)) { + if (! ParseSelectorList(*getter_Transfers(slist), + char16_t(')'), + isForgiving, + aDisallowCombinators)) { return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')') } - if (nsCSSPseudoClasses::HasSingleSelectorArg(aType) && - slist->mNext) { + if (isSingleSelector && slist->mNext) { return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')') } for (nsCSSSelectorList *l = slist; l; l = l->mNext) { nsCSSSelector *s = l->mSelectors; if (s == nullptr) { - MOZ_ASSERT(aIsForgiving, + MOZ_ASSERT(isForgiving, "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()) { + if ((!isForgiving && s->mNext) || s->IsPseudoElement()) { return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')') } } @@ -6599,7 +6619,8 @@ CSSParserImpl::ParsePseudoClassWithSelectorListArg(nsCSSSelector& aSelector, bool CSSParserImpl::ParseSelector(nsCSSSelectorList* aList, char16_t aPrevCombinator, - bool aIsForgiving) + bool aIsForgiving, + bool aDisallowCombinators) { if (! GetToken(true)) { REPORT_UNEXPECTED_EOF(PESelectorEOF); @@ -6620,7 +6641,8 @@ CSSParserImpl::ParseSelector(nsCSSSelectorList* aList, parsingStatus = ParsePseudoSelector(dataMask, *selector, false, getter_AddRefs(pseudoElement), getter_Transfers(pseudoElementArgs), - &pseudoElementType); + &pseudoElementType, + aDisallowCombinators); if (pseudoElement && pseudoElementType != CSSPseudoElementType::AnonBox) { // Pseudo-elements other than anonymous boxes are represented with diff --git a/layout/style/nsCSSPseudoClasses.cpp b/layout/style/nsCSSPseudoClasses.cpp index 928326e399..23517ef52c 100644 --- a/layout/style/nsCSSPseudoClasses.cpp +++ b/layout/style/nsCSSPseudoClasses.cpp @@ -109,6 +109,30 @@ nsCSSPseudoClasses::HasSingleSelectorArg(Type aType) aType == Type::hostContext; } +bool +nsCSSPseudoClasses::HasForgivingSelectorListArg(Type aType) +{ + return aType == Type::is || + aType == Type::matches || + aType == Type::any || + aType == Type::where; +} + +bool +nsCSSPseudoClasses::HasSelectorListArg(Type aType) +{ + return HasForgivingSelectorListArg(aType) || + aType == Type::mozAny || + aType == Type::host || + aType == Type::hostContext; +} + +bool +nsCSSPseudoClasses::HasOptionalSelectorListArg(Type aType) +{ + return aType == Type::host; +} + void nsCSSPseudoClasses::PseudoTypeToString(Type aType, nsAString& aString) { diff --git a/layout/style/nsCSSPseudoClasses.h b/layout/style/nsCSSPseudoClasses.h index 76fcef3f78..99c05b019f 100644 --- a/layout/style/nsCSSPseudoClasses.h +++ b/layout/style/nsCSSPseudoClasses.h @@ -59,21 +59,9 @@ public: 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 HasForgivingSelectorListArg(aType) || - aType == Type::mozAny || - aType == Type::host || - aType == Type::hostContext; - } - static bool HasOptionalSelectorListArg(Type aType) { - return aType == Type::host; - } + static bool HasForgivingSelectorListArg(Type aType); + static bool HasSelectorListArg(Type aType); + static bool HasOptionalSelectorListArg(Type aType); static bool IsUserActionPseudoClass(Type aType); // Should only be used on types other than Count and NotPseudoClass diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index de4ee0fc3b..73209a951a 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -2713,7 +2713,8 @@ static bool SelectorListMatches(Element* aElement, aNodeMatchContext, aTreeMatchContext, SelectorMatchesFlags::IS_PSEUDO_CLASS_ARGUMENT, - aIsForgiving); + aIsForgiving, + aPreventComplexSelectors); } static inline