diff --git a/layout/inspector/inCSSValueSearch.cpp b/layout/inspector/inCSSValueSearch.cpp index 5897e1b542..82697508ed 100644 --- a/layout/inspector/inCSSValueSearch.cpp +++ b/layout/inspector/inCSSValueSearch.cpp @@ -18,6 +18,8 @@ #include "nsIDOMCSSImportRule.h" #include "nsIDOMCSSMediaRule.h" #include "nsIDOMCSSSupportsRule.h" +#include "nsIDOMCSSLayerBlockRule.h" +#include "nsIDOMCSSLayerStatementRule.h" #include "nsIDOMCSSRule.h" #include "nsIURI.h" #include "nsIDocument.h" @@ -322,6 +324,12 @@ inCSSValueSearch::SearchRuleList(nsIDOMCSSRuleList* aRuleList, nsIURI* aBaseURL) supportsRule->GetCssRules(getter_AddRefs(childRules)); SearchRuleList(childRules, aBaseURL); } break; + case nsIDOMCSSRule::LAYER_BLOCK_RULE: { + nsCOMPtr layerBlockRule = do_QueryInterface(rule); + nsCOMPtr childRules; + layerBlockRule->GetCssRules(getter_AddRefs(childRules)); + SearchRuleList(childRules, aBaseURL); + } break; default: // XXX handle nsIDOMCSSRule::PAGE_RULE if we ever support it break; diff --git a/layout/style/CSSStyleSheet.cpp b/layout/style/CSSStyleSheet.cpp index 1307864c9d..1ed14259db 100644 --- a/layout/style/CSSStyleSheet.cpp +++ b/layout/style/CSSStyleSheet.cpp @@ -1896,6 +1896,8 @@ CSSStyleSheet::InsertRuleIntoGroup(const nsAString & aRule, case css::Rule::COUNTER_STYLE_RULE: case css::Rule::DOCUMENT_RULE: case css::Rule::SUPPORTS_RULE: + case css::Rule::LAYER_BLOCK_RULE: + case css::Rule::LAYER_STATEMENT_RULE: // these types are OK to insert into a group break; case css::Rule::CHARSET_RULE: diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 72b105ca3f..1603e66353 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -68,6 +68,7 @@ static bool sWebkitDevicePixelRatioEnabled; static bool sMozGradientsEnabled; static bool sControlCharVisibility; static bool sLegacyNegationPseudoClassEnabled; +static bool sCascadeLayersEnabled; const uint32_t nsCSSProps::kParserVariantTable[eCSSProperty_COUNT_no_shorthands] = { @@ -753,6 +754,8 @@ protected: nsCSSValue& aValue); bool ParseCounterRange(nsCSSValuePair& aPair); + bool ParseLayerRule(RuleAppendFunc aAppendFunc, void* aProcessData); + /** * Parses the current input stream for a CSS token stream value and resolves * any variable references using the variables in aVariables. @@ -3453,6 +3456,11 @@ CSSParserImpl::ParseAtRule(RuleAppendFunc aAppendFunc, parseFunc = &CSSParserImpl::ParseSupportsRule; newSection = eCSSSection_General; + } else if (mToken.mIdent.LowerCaseEqualsLiteral("layer") && + sCascadeLayersEnabled) { + parseFunc = &CSSParserImpl::ParseLayerRule; + newSection = eCSSSection_General; + } else if (mToken.mIdent.LowerCaseEqualsLiteral("counter-style")) { parseFunc = &CSSParserImpl::ParseCounterStyleRule; newSection = eCSSSection_General; @@ -4935,6 +4943,82 @@ CSSParserImpl::ParseSupportsConditionTermsAfterOperator( } } +bool +CSSParserImpl::ParseLayerRule(RuleAppendFunc aAppendFunc, void* aProcessData) +{ + nsString layerName; + + uint32_t linenum, colnum; + if (!GetNextTokenLocation(true, &linenum, &colnum)) { + return false; + } + + nsCSSToken* tk = &mToken; + if (!GetToken(true)) { + return false; + } + + // Parse the layer name or name list if we aren't immediately + // followed by a "{", which indicates an anonymous layer. + if (tk->mType == eCSSToken_Ident) { + nsTArray* nameList = new nsTArray(); + nameList->AppendElement(tk->mIdent); + + bool parsing = true; + bool expectIdent = false; + while (parsing) { + if (!GetToken(true)) { + return false; + } + + switch (tk->mType) { + case eCSSToken_Symbol: { + if (',' == tk->mSymbol) { + if (expectIdent) { + return false; + } + expectIdent = true; + continue; + } else if (';' == tk->mSymbol) { + if (expectIdent) { + return false; + } + RefPtr rule = + new CSSLayerStatementRule(*nameList, linenum, colnum); + return true; + } else if ('{' == tk->mSymbol) { + if (expectIdent) { + return false; + } + uint32_t nameListLength = nameList->Length(); + if (nameListLength == 0 || nameListLength > 1) { + return false; + } + layerName.Assign(nameList->ElementAt(0)); + UngetToken(); + parsing = false; + break; + } + } + case eCSSToken_Ident: { + nameList->AppendElement(tk->mIdent); + expectIdent = false; + break; + } + default: { + return false; + } + } + } + } else if (tk->mType == eCSSToken_Symbol && '{' != tk->mSymbol) { + return false; + } + + RefPtr rule = + new CSSLayerBlockRule(layerName, linenum, colnum); + return ParseGroupRule(rule, aAppendFunc, aProcessData); +} + bool CSSParserImpl::ParseCounterStyleRule(RuleAppendFunc aAppendFunc, void* aData) { @@ -18185,6 +18269,8 @@ nsCSSParser::Startup() "layout.css.control-characters.visible"); Preferences::AddBoolVarCache(&sLegacyNegationPseudoClassEnabled, "layout.css.legacy-negation-pseudo.enabled"); + Preferences::AddBoolVarCache(&sCascadeLayersEnabled, + "layout.css.cascade-layers.enabled"); } nsCSSParser::nsCSSParser(mozilla::css::Loader* aLoader, diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index ff3661c73d..0a9c55fc17 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -3932,7 +3932,8 @@ GatherDocRuleEnumFunc(css::Rule* aRule, void* aData) "mMustGatherDocumentRules is true"); if (css::Rule::MEDIA_RULE == type || - css::Rule::SUPPORTS_RULE == type) { + css::Rule::SUPPORTS_RULE == type || + css::Rule::LAYER_BLOCK_RULE == type) { css::GroupRule* groupRule = static_cast(aRule); if (!groupRule->EnumerateRulesForwards(GatherDocRuleEnumFunc, aData)) { return false; @@ -4011,7 +4012,8 @@ CascadeRuleEnumFunc(css::Rule* aRule, void* aData) } } else if (css::Rule::MEDIA_RULE == type || - css::Rule::SUPPORTS_RULE == type) { + css::Rule::SUPPORTS_RULE == type || + css::Rule::LAYER_BLOCK_RULE == type) { css::GroupRule* groupRule = static_cast(aRule); const bool use = groupRule->UseForPresentation(data->mPresContext, data->mCacheKey);