From 030592649ec9140719d877df5367e9d08f2fcabf Mon Sep 17 00:00:00 2001 From: Kyle Zentner Date: Thu, 4 Jun 2015 16:38:00 +0200 Subject: [PATCH] Bug 1170173 - Parse CSS 'contain' property. r=dholbert --- ...ser_ruleview_completion-new-property_02.js | 2 +- layout/style/nsCSSKeywordList.h | 3 ++ layout/style/nsCSSParser.cpp | 26 ++++++++++++ layout/style/nsCSSPropList.h | 12 ++++++ layout/style/nsCSSProps.cpp | 9 +++++ layout/style/nsCSSProps.h | 1 + layout/style/nsCSSValue.cpp | 14 +++++++ layout/style/nsComputedDOMStyle.cpp | 25 ++++++++++++ layout/style/nsComputedDOMStyle.h | 1 + layout/style/nsComputedDOMStylePropertyList.h | 1 + layout/style/nsRuleNode.cpp | 6 +++ layout/style/nsStyleConsts.h | 13 ++++++ layout/style/nsStyleStruct.cpp | 3 ++ layout/style/nsStyleStruct.h | 1 + layout/style/test/property_database.js | 40 +++++++++++++++++++ modules/libpref/init/all.js | 3 ++ testing/profiles/prefs_general.js | 3 ++ 17 files changed, 162 insertions(+), 1 deletion(-) diff --git a/browser/devtools/styleinspector/test/browser_ruleview_completion-new-property_02.js b/browser/devtools/styleinspector/test/browser_ruleview_completion-new-property_02.js index f26eaec168c..0cb9b08bc85 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_completion-new-property_02.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_completion-new-property_02.js @@ -25,7 +25,7 @@ let testData = [ ["VK_TAB", {shiftKey: true}, "display", -1, 0], ["VK_BACK_SPACE", {}, "", -1, 0], ["c", {}, "caption-side", 0, 10], - ["o", {}, "color", 0, 6], + ["o", {}, "color", 0, 7], ["VK_TAB", {}, "none", -1, 0], ["r", {}, "rebeccapurple", 0, 6], ["VK_DOWN", {}, "red", 1, 6], diff --git a/layout/style/nsCSSKeywordList.h b/layout/style/nsCSSKeywordList.h index 6e8967797c9..a24b32c4446 100644 --- a/layout/style/nsCSSKeywordList.h +++ b/layout/style/nsCSSKeywordList.h @@ -330,6 +330,7 @@ CSS_KEY(korean-hanja-informal, korean_hanja_informal) CSS_KEY(landscape, landscape) CSS_KEY(large, large) CSS_KEY(larger, larger) +CSS_KEY(layout, layout) CSS_KEY(left, left) CSS_KEY(lighten, lighten) CSS_KEY(lighter, lighter) @@ -399,6 +400,7 @@ CSS_KEY(outside, outside) CSS_KEY(over, over) CSS_KEY(overlay, overlay) CSS_KEY(overline, overline) +CSS_KEY(paint, paint) CSS_KEY(padding-box, padding_box) CSS_KEY(painted, painted) CSS_KEY(pan-x, pan_x) @@ -509,6 +511,7 @@ CSS_KEY(sticky, sticky) CSS_KEY(stretch, stretch) CSS_KEY(stretch-to-fit, stretch_to_fit) CSS_KEY(stretched, stretched) +CSS_KEY(strict, strict) CSS_KEY(stroke, stroke) CSS_KEY(stroke-box, stroke_box) CSS_KEY(style, style) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 3c6c86872a5..04d3b5cc7d3 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -887,6 +887,7 @@ protected: // for 'clip' and '-moz-image-region' bool ParseRect(nsCSSProperty aPropID); bool ParseColumns(); + bool ParseContain(nsCSSValue& aValue); bool ParseContent(); bool ParseCounterData(nsCSSProperty aPropID); bool ParseCursor(); @@ -10290,6 +10291,8 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue, return ParseTextOverflow(aValue); case eCSSProperty_touch_action: return ParseTouchAction(aValue); + case eCSSProperty_contain: + return ParseContain(aValue); default: MOZ_ASSERT(false, "should not reach here"); return false; @@ -12397,6 +12400,29 @@ CSSParserImpl::ParseFontVariantEastAsian(nsCSSValue& aValue) maskEastAsian); } +bool +CSSParserImpl::ParseContain(nsCSSValue& aValue) +{ + if (ParseVariant(aValue, VARIANT_INHERIT | VARIANT_NONE, nullptr)) { + return true; + } + static const int32_t maskContain[] = { MASK_END_VALUE }; + if (!ParseBitmaskValues(aValue, nsCSSProps::kContainKTable, maskContain)) { + return false; + } + if (aValue.GetIntValue() & NS_STYLE_CONTAIN_STRICT) { + if (aValue.GetIntValue() != NS_STYLE_CONTAIN_STRICT) { + // Disallow any other keywords in combination with 'strict'. + return false; + } + // Strict implies layout, style, and paint. + // However, for serialization purposes, we keep the strict bit around. + aValue.SetIntValue(NS_STYLE_CONTAIN_STRICT | + NS_STYLE_CONTAIN_ALL_BITS, eCSSUnit_Enumerated); + } + return true; +} + static const int32_t maskLigatures[] = { NS_FONT_VARIANT_LIGATURES_COMMON_MASK, NS_FONT_VARIANT_LIGATURES_DISCRETIONARY_MASK, diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index 1ae06f85f99..c85cb772694 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -1487,6 +1487,18 @@ CSS_PROP_COLUMN( kBorderWidthKTable, CSS_PROP_NO_OFFSET, eStyleAnimType_Custom) +CSS_PROP_DISPLAY( + contain, + contain, + Contain, + CSS_PROPERTY_PARSE_VALUE | + CSS_PROPERTY_VALUE_PARSER_FUNCTION, + "layout.css.contain.enabled", + // Does not affect parsing, but is needed for tab completion in devtools: + VARIANT_HK | VARIANT_NONE, + kContainKTable, + CSS_PROP_NO_OFFSET, + eStyleAnimType_None) CSS_PROP_CONTENT( content, content, diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index 5e97f82bea9..270ffe24cbe 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -1469,6 +1469,15 @@ const KTableValue nsCSSProps::kMathDisplayKTable[] = { eCSSKeyword_UNKNOWN,-1 }; +const KTableValue nsCSSProps::kContainKTable[] = { + eCSSKeyword_none, NS_STYLE_CONTAIN_NONE, + eCSSKeyword_strict, NS_STYLE_CONTAIN_STRICT, + eCSSKeyword_layout, NS_STYLE_CONTAIN_LAYOUT, + eCSSKeyword_style, NS_STYLE_CONTAIN_STYLE, + eCSSKeyword_paint, NS_STYLE_CONTAIN_PAINT, + eCSSKeyword_UNKNOWN,-1 +}; + const KTableValue nsCSSProps::kContextOpacityKTable[] = { eCSSKeyword_context_fill_opacity, NS_STYLE_CONTEXT_FILL_OPACITY, eCSSKeyword_context_stroke_opacity, NS_STYLE_CONTEXT_STROKE_OPACITY, diff --git a/layout/style/nsCSSProps.h b/layout/style/nsCSSProps.h index 3674586a0dc..e8e9a83dfd5 100644 --- a/layout/style/nsCSSProps.h +++ b/layout/style/nsCSSProps.h @@ -648,6 +648,7 @@ public: static const KTableValue kMaskTypeKTable[]; static const KTableValue kMathVariantKTable[]; static const KTableValue kMathDisplayKTable[]; + static const KTableValue kContainKTable[]; static const KTableValue kContextOpacityKTable[]; static const KTableValue kContextPatternKTable[]; static const KTableValue kObjectFitKTable[]; diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index e15faeeeb8d..12442f4c14b 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -1292,6 +1292,20 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult, aResult); break; + case eCSSProperty_contain: + if (intValue & NS_STYLE_CONTAIN_STRICT) { + NS_ASSERTION(intValue == (NS_STYLE_CONTAIN_STRICT | NS_STYLE_CONTAIN_ALL_BITS), + "contain: strict should imply contain: layout style paint"); + // Only output strict. + intValue = NS_STYLE_CONTAIN_STRICT; + } + nsStyleUtil::AppendBitmaskCSSValue(aProperty, + intValue, + NS_STYLE_CONTAIN_STRICT, + NS_STYLE_CONTAIN_PAINT, + aResult); + break; + default: const nsAFlatCString& name = nsCSSProps::LookupPropertyValue(aProperty, intValue); AppendASCIItoUTF16(name, aResult); diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 4829f464b51..f835e89f7a4 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -4005,6 +4005,31 @@ nsComputedDOMStyle::DoGetDisplay() return val; } +CSSValue* +nsComputedDOMStyle::DoGetContain() +{ + nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue; + + int32_t mask = StyleDisplay()->mContain; + + if (mask == 0) { + val->SetIdent(eCSSKeyword_none); + } else if (mask & NS_STYLE_CONTAIN_STRICT) { + NS_ASSERTION(mask == (NS_STYLE_CONTAIN_STRICT | NS_STYLE_CONTAIN_ALL_BITS), + "contain: strict should imply contain: layout style paint"); + val->SetIdent(eCSSKeyword_strict); + } else { + nsAutoString valueStr; + + nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_contain, + mask, NS_STYLE_CONTAIN_LAYOUT, + NS_STYLE_CONTAIN_PAINT, valueStr); + val->SetString(valueStr); + } + + return val; +} + CSSValue* nsComputedDOMStyle::DoGetPosition() { diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index a351ebc24a3..4a84e57ae8a 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -392,6 +392,7 @@ private: mozilla::dom::CSSValue* DoGetClear(); mozilla::dom::CSSValue* DoGetFloat(); mozilla::dom::CSSValue* DoGetDisplay(); + mozilla::dom::CSSValue* DoGetContain(); mozilla::dom::CSSValue* DoGetPosition(); mozilla::dom::CSSValue* DoGetClip(); mozilla::dom::CSSValue* DoGetImageOrientation(); diff --git a/layout/style/nsComputedDOMStylePropertyList.h b/layout/style/nsComputedDOMStylePropertyList.h index 0914b141246..e652813d755 100644 --- a/layout/style/nsComputedDOMStylePropertyList.h +++ b/layout/style/nsComputedDOMStylePropertyList.h @@ -102,6 +102,7 @@ COMPUTED_STYLE_PROP(caption_side, CaptionSide) COMPUTED_STYLE_PROP(clear, Clear) COMPUTED_STYLE_PROP(clip, Clip) COMPUTED_STYLE_PROP(color, Color) +COMPUTED_STYLE_PROP(contain, Contain) COMPUTED_STYLE_PROP(content, Content) COMPUTED_STYLE_PROP(counter_increment, CounterIncrement) COMPUTED_STYLE_PROP(counter_reset, CounterReset) diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 65bb9efc95a..cb46ba4871a 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -5266,6 +5266,12 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct, parentDisplay->mDisplay, NS_STYLE_DISPLAY_INLINE, 0, 0, 0, 0); + // contain: none, enum, inherit, initial + SetDiscrete(*aRuleData->ValueForContain(), display->mContain, canStoreInRuleTree, + SETDSC_ENUMERATED | SETDSC_NONE | SETDSC_UNSET_INITIAL, + parentDisplay->mContain, + NS_STYLE_CONTAIN_NONE, 0, NS_STYLE_CONTAIN_NONE, 0, 0); + // mix-blend-mode: enum, inherit, initial SetDiscrete(*aRuleData->ValueForMixBlendMode(), display->mMixBlendMode, canStoreInRuleTree, diff --git a/layout/style/nsStyleConsts.h b/layout/style/nsStyleConsts.h index a9f326ce1f2..d191de12c71 100644 --- a/layout/style/nsStyleConsts.h +++ b/layout/style/nsStyleConsts.h @@ -444,6 +444,19 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) { #define NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER 37 #define NS_STYLE_DISPLAY_CONTENTS 38 +// See nsStyleDisplay +// If these are re-ordered, nsComputedDOMStyle::DoGetContain() and +// nsCSSValue::AppendToString() must be updated. +#define NS_STYLE_CONTAIN_NONE 0 +#define NS_STYLE_CONTAIN_STRICT 0x1 +#define NS_STYLE_CONTAIN_LAYOUT 0x2 +#define NS_STYLE_CONTAIN_STYLE 0x4 +#define NS_STYLE_CONTAIN_PAINT 0x8 +// NS_STYLE_CONTAIN_ALL_BITS does not correspond to a keyword. +#define NS_STYLE_CONTAIN_ALL_BITS (NS_STYLE_CONTAIN_LAYOUT | \ + NS_STYLE_CONTAIN_STYLE | \ + NS_STYLE_CONTAIN_PAINT) + // See nsStylePosition #define NS_STYLE_ALIGN_CONTENT_FLEX_START 0 #define NS_STYLE_ALIGN_CONTENT_FLEX_END 1 diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 29abb3ec762..30751e3f0fb 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -2582,6 +2582,7 @@ nsStyleDisplay::nsStyleDisplay() mAppearance = NS_THEME_NONE; mDisplay = NS_STYLE_DISPLAY_INLINE; mOriginalDisplay = mDisplay; + mContain = NS_STYLE_CONTAIN_NONE; mPosition = NS_STYLE_POSITION_STATIC; mFloats = NS_STYLE_FLOAT_NONE; mOriginalFloats = mFloats; @@ -2647,6 +2648,7 @@ nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource) , mOpacity(aSource.mOpacity) , mDisplay(aSource.mDisplay) , mOriginalDisplay(aSource.mOriginalDisplay) + , mContain(aSource.mContain) , mAppearance(aSource.mAppearance) , mPosition(aSource.mPosition) , mFloats(aSource.mFloats) @@ -2710,6 +2712,7 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const if (!EqualURIs(mBinding, aOther.mBinding) || mPosition != aOther.mPosition || mDisplay != aOther.mDisplay + || mContain != aOther.mContain || (mFloats == NS_STYLE_FLOAT_NONE) != (aOther.mFloats == NS_STYLE_FLOAT_NONE) || mOverflowX != aOther.mOverflowX || mOverflowY != aOther.mOverflowY diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 7740a16e113..981a967d4c8 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -2069,6 +2069,7 @@ struct nsStyleDisplay { uint8_t mOriginalDisplay; // [reset] saved mDisplay for position:absolute/fixed // and float:left/right; otherwise equal // to mDisplay + uint8_t mContain; // [reset] see nsStyleConsts.h NS_STYLE_CONTAIN_* uint8_t mAppearance; // [reset] uint8_t mPosition; // [reset] see nsStyleConsts.h uint8_t mFloats; // [reset] see nsStyleConsts.h NS_STYLE_FLOAT_* diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index bc3628e8503..31278f009cb 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -6159,6 +6159,46 @@ if (SpecialPowers.getBoolPref("layout.css.display-contents.enabled")) { gCSSProperties["display"].other_values.push("contents"); } +if (SpecialPowers.getBoolPref("layout.css.contain.enabled")) { + gCSSProperties["contain"] = { + domProp: "contain", + inherited: false, + type: CSS_TYPE_LONGHAND, + initial_values: [ "none" ], + other_values: [ + "strict", + "layout", + "style", + "layout style", + "style layout", + "paint", + "layout paint", + "paint layout", + "style paint", + "paint style", + "layout style paint", + "layout paint style", + "style paint layout", + "paint style layout", + ], + invalid_values: [ + "none strict", + "strict layout", + "strict layout style", + "layout strict", + "layout style strict", + "layout style paint strict", + "paint strict", + "style strict", + "paint paint", + "strict strict", + "auto", + "10px", + "0", + ] + }; +} + if (SpecialPowers.getBoolPref("layout.css.image-orientation.enabled")) { gCSSProperties["image-orientation"] = { domProp: "imageOrientation", diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index aef811bc8f1..03a86a17601 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2259,6 +2259,9 @@ pref("layout.css.overflow-clip-box.enabled", false); // Is support for CSS grid enabled? pref("layout.css.grid.enabled", false); +// Is support for CSS contain enabled? +pref("layout.css.contain.enabled", false); + // Is support for CSS Ruby enabled? // // When this pref is removed, make sure that the pref callback registration diff --git a/testing/profiles/prefs_general.js b/testing/profiles/prefs_general.js index 92fcf6316a2..1c172e67dcc 100644 --- a/testing/profiles/prefs_general.js +++ b/testing/profiles/prefs_general.js @@ -148,6 +148,9 @@ user_pref("layout.css.report_errors", true); // Enable CSS Grid for testing user_pref("layout.css.grid.enabled", true); +// Enable CSS 'contain' for testing +user_pref("layout.css.contain.enabled", true); + // Enable CSS object-fit & object-position for testing user_pref("layout.css.object-fit-and-position.enabled", true);