Bug 686281 - CSS Mask prop. draft
authorCJKu <cku@mozilla.com>
Thu, 05 Nov 2015 23:37:37 +0800
changeset 306866 de0abcd8bd14296589e39cec28ac40188d862ce6
parent 306865 61dcc13d0848230382d5c85cdcf6721a05ee37c6
child 306867 fe77abdd9067643465f82186fdcb7d72bb612650
push id7204
push usercku@mozilla.com
push dateThu, 05 Nov 2015 15:38:26 +0000
bugs686281
milestone45.0a1
Bug 686281 - CSS Mask prop.
layout/inspector/inDOMUtils.cpp
layout/style/Declaration.cpp
layout/style/nsCSSKeywordList.h
layout/style/nsCSSParser.cpp
layout/style/nsCSSPropList.h
layout/style/nsCSSProps.cpp
layout/style/nsCSSProps.h
layout/style/nsCSSValue.cpp
layout/style/nsComputedDOMStylePropertyList.h
--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -760,16 +760,18 @@ PropertySupportsVariant(nsCSSProperty aP
         break;
 
       case eCSSProperty_border_top_left_radius:
       case eCSSProperty_border_top_right_radius:
       case eCSSProperty_border_bottom_left_radius:
       case eCSSProperty_border_bottom_right_radius:
       case eCSSProperty_background_position:
       case eCSSProperty_background_size:
+      case eCSSProperty_mask_position:
+      case eCSSProperty_mask_size:
       case eCSSProperty_grid_auto_columns:
       case eCSSProperty_grid_auto_rows:
       case eCSSProperty_grid_template_columns:
       case eCSSProperty_grid_template_rows:
       case eCSSProperty_object_position:
       case eCSSProperty_scroll_snap_coordinate:
       case eCSSProperty_scroll_snap_destination:
       case eCSSProperty_transform_origin:
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -388,16 +388,134 @@ Declaration::GetValue(nsCSSProperty aPro
           // Don't output a third value when it's -moz-use-text-color.
           !(isMozUseTextColor ||
             (aValue.Append(char16_t(' ')),
              AppendValueToString(subprops[2], aValue, aSerialization)))) {
         aValue.Truncate();
       }
       break;
     }
+    case eCSSProperty_mask: {
+      const nsCSSValueList *image =
+        data->ValueFor(eCSSProperty_mask_image)->
+        GetListValue();
+      const nsCSSValuePairList *repeat =
+        data->ValueFor(eCSSProperty_mask_repeat)->
+        GetPairListValue();
+      const nsCSSValueList *position =
+        data->ValueFor(eCSSProperty_mask_position)->
+        GetListValue();
+      const nsCSSValueList *clip =
+        data->ValueFor(eCSSProperty_mask_clip)->
+        GetListValue();
+      const nsCSSValueList *origin =
+        data->ValueFor(eCSSProperty_mask_origin)->
+        GetListValue();
+      const nsCSSValuePairList *size =
+        data->ValueFor(eCSSProperty_mask_size)->
+        GetPairListValue();
+      const nsCSSValueList *composite =
+        data->ValueFor(eCSSProperty_mask_composite)->
+        GetListValue();
+      const nsCSSValueList *mode =
+        data->ValueFor(eCSSProperty_mask_mode)->
+        GetListValue();
+      for (;;) {
+        image->mValue.AppendToString(eCSSProperty_mask_image, aValue,
+                                     aSerialization);
+
+        aValue.Append(char16_t(' '));
+        repeat->mXValue.AppendToString(eCSSProperty_mask_repeat, aValue,
+                                       aSerialization);
+        if (repeat->mYValue.GetUnit() != eCSSUnit_Null) {
+          repeat->mYValue.AppendToString(eCSSProperty_mask_repeat, aValue,
+                                         aSerialization);
+        }
+
+        aValue.Append(char16_t(' '));
+        position->mValue.AppendToString(eCSSProperty_mask_position,
+                                        aValue, aSerialization);
+
+        if (size->mXValue.GetUnit() != eCSSUnit_Auto ||
+            size->mYValue.GetUnit() != eCSSUnit_Auto) {
+          aValue.Append(char16_t(' '));
+          aValue.Append(char16_t('/'));
+          aValue.Append(char16_t(' '));
+          size->mXValue.AppendToString(eCSSProperty_mask_size, aValue,
+                                       aSerialization);
+          aValue.Append(char16_t(' '));
+          size->mYValue.AppendToString(eCSSProperty_mask_size, aValue,
+                                       aSerialization);
+        }
+
+        MOZ_ASSERT(clip->mValue.GetUnit() == eCSSUnit_Enumerated &&
+                   origin->mValue.GetUnit() == eCSSUnit_Enumerated,
+                   "should not have inherit/initial within list");
+
+        if (clip->mValue.GetIntValue() != NS_STYLE_LAYER_CLIP_BORDER ||
+            origin->mValue.GetIntValue() != NS_STYLE_LAYER_ORIGIN_PADDING) {
+          MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
+                       eCSSProperty_mask_origin] ==
+                     nsCSSProps::kLayerOriginKTable);
+          MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
+                       eCSSProperty_mask_clip] ==
+                     nsCSSProps::kLayerOriginKTable);
+          static_assert(NS_STYLE_LAYER_CLIP_BORDER ==
+                        NS_STYLE_LAYER_ORIGIN_BORDER &&
+                        NS_STYLE_LAYER_CLIP_PADDING ==
+                        NS_STYLE_LAYER_ORIGIN_PADDING &&
+                        NS_STYLE_LAYER_CLIP_CONTENT ==
+                        NS_STYLE_LAYER_ORIGIN_CONTENT,
+                        "mask-clip and mask-origin style constants must agree");
+          aValue.Append(char16_t(' '));
+          origin->mValue.AppendToString(eCSSProperty_mask_origin, aValue,
+                                        aSerialization);
+
+          if (clip->mValue != origin->mValue) {
+            aValue.Append(char16_t(' '));
+            clip->mValue.AppendToString(eCSSProperty_mask_clip, aValue,
+                                        aSerialization);
+          }
+        }
+
+        aValue.Append(char16_t(' '));
+        composite->mValue.AppendToString(eCSSProperty_mask_composite,
+                                          aValue, aSerialization);
+
+        aValue.Append(char16_t(' '));
+        mode->mValue.AppendToString(eCSSProperty_mask_mode,
+                                    aValue, aSerialization);
+
+        image = image->mNext;
+        repeat = repeat->mNext;
+        position = position->mNext;
+        clip = clip->mNext;
+        origin = origin->mNext;
+        size = size->mNext;
+        composite = composite->mNext;
+        mode = mode->mNext;
+
+        if (!image) {
+          if (repeat || position || clip || origin || size) {
+            // Uneven length lists, so can't be serialized as shorthand.
+            aValue.Truncate();
+            return;
+          }
+          break;
+        }
+        if (!repeat || !position || !clip || !origin || !size) {
+          // Uneven length lists, so can't be serialized as shorthand.
+          aValue.Truncate();
+          return;
+        }
+        aValue.Append(char16_t(','));
+        aValue.Append(char16_t(' '));
+      }
+      break;
+    }
     case eCSSProperty_background: {
       // We know from above that all subproperties were specified.
       // However, we still can't represent that in the shorthand unless
       // they're all lists of the same length.  So if they're different
       // lengths, we need to bail out.
       // We also need to bail out if an item has background-clip and
       // background-origin that are different and not the default
       // values.  (We omit them if they're both default.)
@@ -437,50 +555,51 @@ Declaration::GetValue(nsCSSProperty aPro
                                        aSerialization);
         if (repeat->mYValue.GetUnit() != eCSSUnit_Null) {
           repeat->mYValue.AppendToString(eCSSProperty_background_repeat, aValue,
                                          aSerialization);
         }
         aValue.Append(char16_t(' '));
         attachment->mValue.AppendToString(eCSSProperty_background_attachment,
                                           aValue, aSerialization);
+
         aValue.Append(char16_t(' '));
         position->mValue.AppendToString(eCSSProperty_background_position,
                                         aValue, aSerialization);
-        
+
         if (size->mXValue.GetUnit() != eCSSUnit_Auto ||
             size->mYValue.GetUnit() != eCSSUnit_Auto) {
           aValue.Append(char16_t(' '));
           aValue.Append(char16_t('/'));
           aValue.Append(char16_t(' '));
           size->mXValue.AppendToString(eCSSProperty_background_size, aValue,
                                        aSerialization);
           aValue.Append(char16_t(' '));
           size->mYValue.AppendToString(eCSSProperty_background_size, aValue,
                                        aSerialization);
         }
 
         MOZ_ASSERT(clip->mValue.GetUnit() == eCSSUnit_Enumerated &&
                    origin->mValue.GetUnit() == eCSSUnit_Enumerated,
                    "should not have inherit/initial within list");
 
-        if (clip->mValue.GetIntValue() != NS_STYLE_BG_CLIP_BORDER ||
-            origin->mValue.GetIntValue() != NS_STYLE_BG_ORIGIN_PADDING) {
+        if (clip->mValue.GetIntValue() != NS_STYLE_LAYER_CLIP_BORDER ||
+            origin->mValue.GetIntValue() != NS_STYLE_LAYER_ORIGIN_PADDING) {
           MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
                        eCSSProperty_background_origin] ==
-                     nsCSSProps::kBackgroundOriginKTable);
+                     nsCSSProps::kLayerOriginKTable);
           MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
                        eCSSProperty_background_clip] ==
-                     nsCSSProps::kBackgroundOriginKTable);
-          static_assert(NS_STYLE_BG_CLIP_BORDER ==
-                        NS_STYLE_BG_ORIGIN_BORDER &&
-                        NS_STYLE_BG_CLIP_PADDING ==
-                        NS_STYLE_BG_ORIGIN_PADDING &&
-                        NS_STYLE_BG_CLIP_CONTENT ==
-                        NS_STYLE_BG_ORIGIN_CONTENT,
+                     nsCSSProps::kLayerOriginKTable);
+          static_assert(NS_STYLE_LAYER_CLIP_BORDER ==
+                        NS_STYLE_LAYER_ORIGIN_BORDER &&
+                        NS_STYLE_LAYER_CLIP_PADDING ==
+                        NS_STYLE_LAYER_ORIGIN_PADDING &&
+                        NS_STYLE_LAYER_CLIP_CONTENT ==
+                        NS_STYLE_LAYER_ORIGIN_CONTENT,
                         "bg-clip and bg-origin style constants must agree");
           aValue.Append(char16_t(' '));
           origin->mValue.AppendToString(eCSSProperty_background_origin, aValue,
                                         aSerialization);
 
           if (clip->mValue != origin->mValue) {
             aValue.Append(char16_t(' '));
             clip->mValue.AppendToString(eCSSProperty_background_clip, aValue,
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -753,8 +753,12 @@ CSS_KEY(reset-size, reset_size)
 //CSS_KEY(start, start)
 CSS_KEY(srgb, srgb)
 CSS_KEY(symbolic, symbolic)
 CSS_KEY(symbols, symbols)
 CSS_KEY(text-after-edge, text_after_edge)
 CSS_KEY(text-before-edge, text_before_edge)
 CSS_KEY(use-script, use_script)
 CSS_KEY(-moz-crisp-edges, _moz_crisp_edges)
+CSS_KEY(add, add)
+CSS_KEY(subtract, subtract)
+CSS_KEY(intersect, intersect)
+CSS_KEY(exclude, exclude)
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -805,56 +805,62 @@ protected:
   PriorityParsingStatus ParsePriority();
 
 #ifdef MOZ_XUL
   bool ParseTreePseudoElement(nsAtomList **aPseudoElementArgs);
 #endif
 
   // Property specific parsing routines
   bool ParseBackground();
-
-  struct BackgroundParseState {
+  bool ParseMask();
+
+  struct StyleLayersParseState {
     nsCSSValue&  mColor;
     nsCSSValueList* mImage;
     nsCSSValuePairList* mRepeat;
     nsCSSValueList* mAttachment;
     nsCSSValueList* mClip;
     nsCSSValueList* mOrigin;
     nsCSSValueList* mPosition;
     nsCSSValuePairList* mSize;
-    BackgroundParseState(
+    nsCSSValueList* mComposite;
+    nsCSSValueList* mMode;
+    StyleLayersParseState(
         nsCSSValue& aColor, nsCSSValueList* aImage, nsCSSValuePairList* aRepeat,
         nsCSSValueList* aAttachment, nsCSSValueList* aClip,
         nsCSSValueList* aOrigin, nsCSSValueList* aPosition,
-        nsCSSValuePairList* aSize) :
+        nsCSSValuePairList* aSize, nsCSSValueList* aComposite,
+        nsCSSValueList* aMode) :
         mColor(aColor), mImage(aImage), mRepeat(aRepeat),
         mAttachment(aAttachment), mClip(aClip), mOrigin(aOrigin),
-        mPosition(aPosition), mSize(aSize) {};
+        mPosition(aPosition), mSize(aSize), mComposite(aComposite),
+        mMode(aMode) {};
   };
 
-  bool IsFunctionTokenValidForBackgroundImage(const nsCSSToken& aToken) const;
-  bool ParseBackgroundItem(BackgroundParseState& aState);
+  bool IsFunctionTokenValidForStyleLayerImage(const nsCSSToken& aToken) const;
+  bool ParseBackgroundItem(StyleLayersParseState& aState);
+  bool ParseMaskItem(StyleLayersParseState& aState);
 
   bool ParseValueList(nsCSSProperty aPropID); // a single value prop-id
-  bool ParseBackgroundRepeat();
-  bool ParseBackgroundRepeatValues(nsCSSValuePair& aValue);
-  bool ParseBackgroundPosition();
+  bool ParseLayerRepeat(nsCSSProperty aPropID);
+  bool ParseLayerRepeatValues(nsCSSValuePair& aValue);
+  bool ParseLayerPosition(nsCSSProperty aPropID);
 
   // ParseBoxPositionValues parses the CSS 2.1 background-position syntax,
   // which is still used by some properties. See ParsePositionValue
   // for the css3-background syntax.
   bool ParseBoxPositionValues(nsCSSValuePair& aOut, bool aAcceptsInherit,
                               bool aAllowExplicitCenter = true); // deprecated
 
   // ParsePositionValue parses a CSS <position> value, which is used by
   // the 'background-position' property.
   bool ParsePositionValue(nsCSSValue& aOut);
 
-  bool ParseBackgroundSize();
-  bool ParseBackgroundSizeValues(nsCSSValuePair& aOut);
+  bool ParseLayerSize(nsCSSProperty aPropID);
+  bool ParseLayerSizeValues(nsCSSValuePair& aOut);
   bool ParseBorderColor();
   bool ParseBorderColors(nsCSSProperty aProperty);
   void SetBorderImageInitialValues();
   bool ParseBorderImageRepeat(bool aAcceptsInherit);
   // If ParseBorderImageSlice returns false, aConsumedTokens indicates
   // whether or not any tokens were consumed (in other words, was the property
   // in error or just not present).  If ParseBorderImageSlice returns true
   // aConsumedTokens is always true.
@@ -9546,23 +9552,23 @@ CSSParserImpl::ParseColorStop(nsCSSValue
 // ParseBoxPositionValues()'s "aAllowExplicitCenter" parameter, before you
 // call this function.)
 static bool
 IsBoxPositionStrictlyEdgeKeywords(nsCSSValuePair& aPosition)
 {
   const nsCSSValue& xValue = aPosition.mXValue;
   const nsCSSValue& yValue = aPosition.mYValue;
   return (xValue.GetUnit() == eCSSUnit_Enumerated &&
-          (xValue.GetIntValue() & (NS_STYLE_BG_POSITION_LEFT |
-                                   NS_STYLE_BG_POSITION_CENTER |
-                                   NS_STYLE_BG_POSITION_RIGHT)) &&
+          (xValue.GetIntValue() & (NS_STYLE_LAYER_POSITION_LEFT |
+                                   NS_STYLE_LAYER_POSITION_CENTER |
+                                   NS_STYLE_LAYER_POSITION_RIGHT)) &&
           yValue.GetUnit() == eCSSUnit_Enumerated &&
-          (yValue.GetIntValue() & (NS_STYLE_BG_POSITION_TOP |
-                                   NS_STYLE_BG_POSITION_CENTER |
-                                   NS_STYLE_BG_POSITION_BOTTOM)));
+          (yValue.GetIntValue() & (NS_STYLE_LAYER_POSITION_TOP |
+                                   NS_STYLE_LAYER_POSITION_CENTER |
+                                   NS_STYLE_LAYER_POSITION_BOTTOM)));
 }
 
 // <gradient>
 //    : linear-gradient( <linear-gradient-line>? <color-stops> ')'
 //    | radial-gradient( <radial-gradient-line>? <color-stops> ')'
 //
 // <linear-gradient-line> : [ to [left | right] || [top | bottom] ] ,
 //                        | <legacy-gradient-line>
@@ -9881,17 +9887,17 @@ CSSParserImpl::IsLegacyGradientLine(cons
     // this is a color
     break;
 
   case eCSSToken_Ident: {
     // This is only a gradient line if it's a box position keyword.
     nsCSSKeyword kw = nsCSSKeywords::LookupKeyword(aId);
     int32_t junk;
     if (kw != eCSSKeyword_UNKNOWN &&
-        nsCSSProps::FindKeyword(kw, nsCSSProps::kBackgroundPositionKTable,
+        nsCSSProps::FindKeyword(kw, nsCSSProps::kLayerPositionKTable,
                                 junk)) {
       haveGradientLine = true;
     }
     break;
   }
 
   default:
     // error
@@ -10510,21 +10516,21 @@ CSSParserImpl::ParseProperty(nsCSSProper
 
 bool
 CSSParserImpl::ParsePropertyByFunction(nsCSSProperty aPropID)
 {
   switch (aPropID) {  // handle shorthand or multiple properties
   case eCSSProperty_background:
     return ParseBackground();
   case eCSSProperty_background_repeat:
-    return ParseBackgroundRepeat();
+    return ParseLayerRepeat(eCSSProperty_background_repeat);
   case eCSSProperty_background_position:
-    return ParseBackgroundPosition();
+    return ParseLayerPosition(eCSSProperty_background_position);
   case eCSSProperty_background_size:
-    return ParseBackgroundSize();
+    return ParseLayerSize(eCSSProperty_background_size);
   case eCSSProperty_border:
     return ParseBorderSide(kBorderTopIDs, true);
   case eCSSProperty_border_color:
     return ParseBorderColor();
   case eCSSProperty_border_spacing:
     return ParseBorderSpacing();
   case eCSSProperty_border_style:
     return ParseBorderStyle();
@@ -10684,30 +10690,38 @@ CSSParserImpl::ParsePropertyByFunction(n
   case eCSSProperty_marker:
     return ParseMarker();
   case eCSSProperty_paint_order:
     return ParsePaintOrder();
   case eCSSProperty_clip_path:
     return ParseClipPath();
   case eCSSProperty_scroll_snap_type:
     return ParseScrollSnapType();
+  case eCSSProperty_mask:
+    return ParseMask();
+  case eCSSProperty_mask_repeat:
+    return ParseLayerRepeat(eCSSProperty_mask_repeat);
+  case eCSSProperty_mask_position:
+    return ParseLayerPosition(eCSSProperty_mask_position);
+  case eCSSProperty_mask_size:
+    return ParseLayerSize(eCSSProperty_mask_size);
   case eCSSProperty_all:
     return ParseAll();
   default:
     MOZ_ASSERT(false, "should not be called");
     return false;
   }
 }
 
 // Bits used in determining which background position info we have
-#define BG_CENTER  NS_STYLE_BG_POSITION_CENTER
-#define BG_TOP     NS_STYLE_BG_POSITION_TOP
-#define BG_BOTTOM  NS_STYLE_BG_POSITION_BOTTOM
-#define BG_LEFT    NS_STYLE_BG_POSITION_LEFT
-#define BG_RIGHT   NS_STYLE_BG_POSITION_RIGHT
+#define BG_CENTER  NS_STYLE_LAYER_POSITION_CENTER
+#define BG_TOP     NS_STYLE_LAYER_POSITION_TOP
+#define BG_BOTTOM  NS_STYLE_LAYER_POSITION_BOTTOM
+#define BG_LEFT    NS_STYLE_LAYER_POSITION_LEFT
+#define BG_RIGHT   NS_STYLE_LAYER_POSITION_RIGHT
 #define BG_CTB    (BG_CENTER | BG_TOP | BG_BOTTOM)
 #define BG_TB     (BG_TOP | BG_BOTTOM)
 #define BG_CLR    (BG_CENTER | BG_LEFT | BG_RIGHT)
 #define BG_LR     (BG_LEFT | BG_RIGHT)
 
 CSSParseResult
 CSSParserImpl::ParseBoxProperty(nsCSSValue& aValue,
                                 nsCSSProperty aPropID)
@@ -10911,31 +10925,31 @@ CSSParserImpl::ParseFontDescriptorValue(
   // explicitly do NOT have a default case to let the compiler
   // help find missing descriptors
   return false;
 }
 
 static nsCSSValue
 BoxPositionMaskToCSSValue(int32_t aMask, bool isX)
 {
-  int32_t val = NS_STYLE_BG_POSITION_CENTER;
+  int32_t val = NS_STYLE_LAYER_POSITION_CENTER;
   if (isX) {
     if (aMask & BG_LEFT) {
-      val = NS_STYLE_BG_POSITION_LEFT;
+      val = NS_STYLE_LAYER_POSITION_LEFT;
     }
     else if (aMask & BG_RIGHT) {
-      val = NS_STYLE_BG_POSITION_RIGHT;
+      val = NS_STYLE_LAYER_POSITION_RIGHT;
     }
   }
   else {
     if (aMask & BG_TOP) {
-      val = NS_STYLE_BG_POSITION_TOP;
+      val = NS_STYLE_LAYER_POSITION_TOP;
     }
     else if (aMask & BG_BOTTOM) {
-      val = NS_STYLE_BG_POSITION_BOTTOM;
+      val = NS_STYLE_LAYER_POSITION_BOTTOM;
     }
   }
 
   return nsCSSValue(val, eCSSUnit_Enumerated);
 }
 
 bool
 CSSParserImpl::ParseBackground()
@@ -10951,22 +10965,23 @@ CSSParserImpl::ParseBackground()
     for (const nsCSSProperty* subprops =
            nsCSSProps::SubpropertyEntryFor(eCSSProperty_background);
          *subprops != eCSSProperty_UNKNOWN; ++subprops) {
       AppendValue(*subprops, color);
     }
     return true;
   }
 
-  nsCSSValue image, repeat, attachment, clip, origin, position, size;
-  BackgroundParseState state(color, image.SetListValue(), 
-                             repeat.SetPairListValue(),
-                             attachment.SetListValue(), clip.SetListValue(),
-                             origin.SetListValue(), position.SetListValue(),
-                             size.SetPairListValue());
+  nsCSSValue image, repeat, attachment, clip, origin, position, size, composite, mode;
+  StyleLayersParseState state(color, image.SetListValue(),
+                              repeat.SetPairListValue(),
+                              attachment.SetListValue(), clip.SetListValue(),
+                              origin.SetListValue(), position.SetListValue(),
+                              size.SetPairListValue(), composite.SetListValue(),
+                              mode.SetListValue());
 
   for (;;) {
     if (!ParseBackgroundItem(state)) {
       return false;
     }
     // If we saw a color, this must be the last item.
     if (color.GetUnit() != eCSSUnit_Null) {
       break;
@@ -11003,20 +11018,73 @@ CSSParserImpl::ParseBackground()
   AppendValue(eCSSProperty_background_clip,       clip);
   AppendValue(eCSSProperty_background_origin,     origin);
   AppendValue(eCSSProperty_background_position,   position);
   AppendValue(eCSSProperty_background_size,       size);
   AppendValue(eCSSProperty_background_color,      color);
   return true;
 }
 
+bool
+CSSParserImpl::ParseMask()
+{
+  nsAutoParseCompoundProperty compound(this);
+
+  nsCSSValue color;
+  nsCSSValue image, repeat, attachment, clip, origin, position, size, composite, mode;
+  StyleLayersParseState state(color, image.SetListValue(),
+                             repeat.SetPairListValue(),
+                             attachment.SetListValue(), clip.SetListValue(),
+                             origin.SetListValue(), position.SetListValue(),
+                             size.SetPairListValue(), composite.SetListValue(),
+                             mode.SetListValue());
+
+  for (;;) {
+    if (!ParseMaskItem(state)) {
+      return false;
+    }
+    // If there's a comma, expect another item.
+    if (!ExpectSymbol(',', true)) {
+      break;
+    }
+    // Chain another entry on all the lists.
+    state.mImage->mNext = new nsCSSValueList;
+    state.mImage = state.mImage->mNext;
+    state.mRepeat->mNext = new nsCSSValuePairList;
+    state.mRepeat = state.mRepeat->mNext;
+    state.mClip->mNext = new nsCSSValueList;
+    state.mClip = state.mClip->mNext;
+    state.mOrigin->mNext = new nsCSSValueList;
+    state.mOrigin = state.mOrigin->mNext;
+    state.mPosition->mNext = new nsCSSValueList;
+    state.mPosition = state.mPosition->mNext;
+    state.mSize->mNext = new nsCSSValuePairList;
+    state.mSize = state.mSize->mNext;
+    state.mComposite->mNext = new nsCSSValueList;
+    state.mComposite = state.mComposite->mNext;
+    state.mMode->mNext = new nsCSSValueList;
+    state.mMode = state.mMode->mNext;
+  }
+
+  AppendValue(eCSSProperty_mask_image,      image);
+  AppendValue(eCSSProperty_mask_repeat,     repeat);
+  AppendValue(eCSSProperty_mask_clip,       clip);
+  AppendValue(eCSSProperty_mask_origin,     origin);
+  AppendValue(eCSSProperty_mask_position,   position);
+  AppendValue(eCSSProperty_mask_size,       size);
+  AppendValue(eCSSProperty_mask_composite,  composite);
+  AppendValue(eCSSProperty_mask_mode,       mode);
+
+  return true;
+}
+
 // Helper for ParseBackgroundItem. Returns true if the passed-in nsCSSToken is
 // a function which is accepted for background-image.
 bool
-CSSParserImpl::IsFunctionTokenValidForBackgroundImage(
+CSSParserImpl::IsFunctionTokenValidForStyleLayerImage(
   const nsCSSToken& aToken) const
 {
   MOZ_ASSERT(aToken.mType == eCSSToken_Function,
              "Should only be called for function-typed tokens");
 
   const nsAString& funcName = aToken.mIdent;
 
   return funcName.LowerCaseEqualsLiteral("linear-gradient") ||
@@ -11034,30 +11102,30 @@ CSSParserImpl::IsFunctionTokenValidForBa
       funcName.LowerCaseEqualsLiteral("-webkit-linear-gradient") ||
       funcName.LowerCaseEqualsLiteral("-webkit-radial-gradient") ||
       funcName.LowerCaseEqualsLiteral("-webkit-repeating-linear-gradient") ||
       funcName.LowerCaseEqualsLiteral("-webkit-repeating-radial-gradient")));
 }
 
 // Parse one item of the background shorthand property.
 bool
-CSSParserImpl::ParseBackgroundItem(CSSParserImpl::BackgroundParseState& aState)
+CSSParserImpl::ParseBackgroundItem(CSSParserImpl::StyleLayersParseState& aState)
 
 {
   // Fill in the values that the shorthand will set if we don't find
   // other values.
   aState.mImage->mValue.SetNoneValue();
-  aState.mRepeat->mXValue.SetIntValue(NS_STYLE_BG_REPEAT_REPEAT,
+  aState.mRepeat->mXValue.SetIntValue(NS_STYLE_LAYER_REPEAT_REPEAT,
                                       eCSSUnit_Enumerated);
   aState.mRepeat->mYValue.Reset();
-  aState.mAttachment->mValue.SetIntValue(NS_STYLE_BG_ATTACHMENT_SCROLL,
+  aState.mAttachment->mValue.SetIntValue(NS_STYLE_LAYER_ATTACHMENT_SCROLL,
                                          eCSSUnit_Enumerated);
-  aState.mClip->mValue.SetIntValue(NS_STYLE_BG_CLIP_BORDER,
+  aState.mClip->mValue.SetIntValue(NS_STYLE_LAYER_CLIP_BORDER,
                                    eCSSUnit_Enumerated);
-  aState.mOrigin->mValue.SetIntValue(NS_STYLE_BG_ORIGIN_PADDING,
+  aState.mOrigin->mValue.SetIntValue(NS_STYLE_LAYER_ORIGIN_PADDING,
                                      eCSSUnit_Enumerated);
   RefPtr<nsCSSValue::Array> positionArr = nsCSSValue::Array::Create(4);
   aState.mPosition->mValue.SetArrayValue(positionArr, eCSSUnit_Array);
   positionArr->Item(1).SetPercentValue(0.0f);
   positionArr->Item(3).SetPercentValue(0.0f);
   aState.mSize->mXValue.SetAutoValue();
   aState.mSize->mYValue.SetAutoValue();
 
@@ -11091,82 +11159,82 @@ CSSParserImpl::ParseBackgroundItem(CSSPa
         haveImage = true;
         if (ParseSingleValueProperty(aState.mImage->mValue,
                                      eCSSProperty_background_image) !=
             CSSParseResult::Ok) {
           NS_NOTREACHED("should be able to parse");
           return false;
         }
       } else if (nsCSSProps::FindKeyword(keyword,
-                   nsCSSProps::kBackgroundAttachmentKTable, dummy)) {
+                   nsCSSProps::kLayerAttachmentKTable, dummy)) {
         if (haveAttach)
           return false;
         haveAttach = true;
         if (ParseSingleValueProperty(aState.mAttachment->mValue,
                                      eCSSProperty_background_attachment) !=
             CSSParseResult::Ok) {
           NS_NOTREACHED("should be able to parse");
           return false;
         }
       } else if (nsCSSProps::FindKeyword(keyword,
-                   nsCSSProps::kBackgroundRepeatKTable, dummy)) {
+                   nsCSSProps::kLayerRepeatKTable, dummy)) {
         if (haveRepeat)
           return false;
         haveRepeat = true;
         nsCSSValuePair scratch;
-        if (!ParseBackgroundRepeatValues(scratch)) {
+        if (!ParseLayerRepeatValues(scratch)) {
           NS_NOTREACHED("should be able to parse");
           return false;
         }
         aState.mRepeat->mXValue = scratch.mXValue;
         aState.mRepeat->mYValue = scratch.mYValue;
       } else if (nsCSSProps::FindKeyword(keyword,
-                   nsCSSProps::kBackgroundPositionKTable, dummy)) {
+                   nsCSSProps::kLayerPositionKTable, dummy)) {
         if (havePositionAndSize)
           return false;
         havePositionAndSize = true;
         if (!ParsePositionValue(aState.mPosition->mValue)) {
           return false;
         }
         if (ExpectSymbol('/', true)) {
           nsCSSValuePair scratch;
-          if (!ParseBackgroundSizeValues(scratch)) {
+          if (!ParseLayerSizeValues(scratch)) {
             return false;
           }
           aState.mSize->mXValue = scratch.mXValue;
           aState.mSize->mYValue = scratch.mYValue;
         }
       } else if (nsCSSProps::FindKeyword(keyword,
-                   nsCSSProps::kBackgroundOriginKTable, dummy)) {
+                   nsCSSProps::kLayerOriginKTable, dummy)) {
         if (haveOrigin)
           return false;
         haveOrigin = true;
         if (ParseSingleValueProperty(aState.mOrigin->mValue,
                                      eCSSProperty_background_origin) !=
             CSSParseResult::Ok) {
           NS_NOTREACHED("should be able to parse");
           return false;
         }
 
         // The spec allows a second box value (for background-clip),
         // immediately following the first one (for background-origin).
 
         // 'background-clip' and 'background-origin' use the same keyword table
         MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
                      eCSSProperty_background_origin] ==
-                   nsCSSProps::kBackgroundOriginKTable);
+                   nsCSSProps::kLayerOriginKTable);
         MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
                      eCSSProperty_background_clip] ==
-                   nsCSSProps::kBackgroundOriginKTable);
-        static_assert(NS_STYLE_BG_CLIP_BORDER ==
-                      NS_STYLE_BG_ORIGIN_BORDER &&
-                      NS_STYLE_BG_CLIP_PADDING ==
-                      NS_STYLE_BG_ORIGIN_PADDING &&
-                      NS_STYLE_BG_CLIP_CONTENT ==
-                      NS_STYLE_BG_ORIGIN_CONTENT,
+                   nsCSSProps::kLayerOriginKTable);
+        static_assert(NS_STYLE_LAYER_CLIP_BORDER ==
+                      NS_STYLE_LAYER_ORIGIN_BORDER &&
+                      NS_STYLE_LAYER_CLIP_PADDING ==
+                      NS_STYLE_LAYER_ORIGIN_PADDING &&
+                      NS_STYLE_LAYER_CLIP_CONTENT ==
+                      NS_STYLE_LAYER_ORIGIN_CONTENT,
                       "bg-clip and bg-origin style constants must agree");
 
         CSSParseResult result =
           ParseSingleValueProperty(aState.mClip->mValue,
                                    eCSSProperty_background_clip);
         MOZ_ASSERT(result != CSSParseResult::Error,
                    "how can failing to parse a single background-clip value "
                    "consume tokens?");
@@ -11183,17 +11251,17 @@ CSSParserImpl::ParseBackgroundItem(CSSPa
         if (ParseSingleValueProperty(aState.mColor,
                                      eCSSProperty_background_color) !=
             CSSParseResult::Ok) {
           return false;
         }
       }
     } else if (tt == eCSSToken_URL ||
                (tt == eCSSToken_Function &&
-                IsFunctionTokenValidForBackgroundImage(mToken))) {
+                IsFunctionTokenValidForStyleLayerImage(mToken))) {
       if (haveImage)
         return false;
       haveImage = true;
       if (ParseSingleValueProperty(aState.mImage->mValue,
                                    eCSSProperty_background_image) !=
           CSSParseResult::Ok) {
         return false;
       }
@@ -11206,17 +11274,17 @@ CSSParserImpl::ParseBackgroundItem(CSSPa
       if (havePositionAndSize)
         return false;
       havePositionAndSize = true;
       if (!ParsePositionValue(aState.mPosition->mValue)) {
         return false;
       }
       if (ExpectSymbol('/', true)) {
         nsCSSValuePair scratch;
-        if (!ParseBackgroundSizeValues(scratch)) {
+        if (!ParseLayerSizeValues(scratch)) {
           return false;
         }
         aState.mSize->mXValue = scratch.mXValue;
         aState.mSize->mYValue = scratch.mYValue;
       }
     } else {
       if (haveColor)
         return false;
@@ -11230,18 +11298,207 @@ CSSParserImpl::ParseBackgroundItem(CSSPa
       }
     }
     haveSomething = true;
   }
 
   return haveSomething;
 }
 
+bool
+CSSParserImpl::ParseMaskItem(CSSParserImpl::StyleLayersParseState& aState)
+{
+  // Fill in the values that the shorthand will set if we don't find
+  // other values.
+  aState.mImage->mValue.SetNoneValue();
+  aState.mRepeat->mXValue.SetIntValue(NS_STYLE_LAYER_REPEAT_REPEAT,
+                                      eCSSUnit_Enumerated);
+  aState.mRepeat->mYValue.Reset();
+  aState.mClip->mValue.SetIntValue(NS_STYLE_LAYER_CLIP_BORDER,
+                                   eCSSUnit_Enumerated);
+  aState.mOrigin->mValue.SetIntValue(NS_STYLE_LAYER_ORIGIN_PADDING,
+                                     eCSSUnit_Enumerated);
+  RefPtr<nsCSSValue::Array> positionArr = nsCSSValue::Array::Create(4);
+  aState.mPosition->mValue.SetArrayValue(positionArr, eCSSUnit_Array);
+  positionArr->Item(1).SetPercentValue(0.0f);
+  positionArr->Item(3).SetPercentValue(0.0f);
+  aState.mSize->mXValue.SetAutoValue();
+  aState.mSize->mYValue.SetAutoValue();
+  aState.mComposite->mValue.SetIntValue(NS_STYLE_COMPOSITE_ADD,
+                                        eCSSUnit_Enumerated);
+  aState.mMode->mValue.SetIntValue(NS_STYLE_LAYER_MODE_AUTO,
+                                   eCSSUnit_Enumerated);
+  bool haveImage = false,
+       haveRepeat = false,
+       havePositionAndSize = false,
+       haveOrigin = false,
+       haveComposite = false,
+       haveMode = false,
+       haveSomething = false;
+
+  while (GetToken(true)) {
+    nsCSSTokenType tt = mToken.mType;
+    UngetToken(); // ...but we'll still cheat and use mToken
+    if (tt == eCSSToken_Symbol) {
+      // ExpectEndProperty only looks for symbols, and nothing else will
+      // show up as one.
+      break;
+    }
+
+    if (tt == eCSSToken_Ident) {
+      nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
+      int32_t dummy;
+      if (keyword == eCSSKeyword_inherit ||
+          keyword == eCSSKeyword_initial ||
+          keyword == eCSSKeyword_unset) {
+        return false;
+      } else if (keyword == eCSSKeyword_none) {
+        if (haveImage)
+          return false;
+        haveImage = true;
+        if (ParseSingleValueProperty(aState.mImage->mValue,
+                                     eCSSProperty_mask_image) !=
+            CSSParseResult::Ok) {
+          NS_NOTREACHED("should be able to parse");
+          return false;
+        }
+      } else if (nsCSSProps::FindKeyword(keyword,
+                   nsCSSProps::kLayerRepeatKTable, dummy)) {
+        if (haveRepeat)
+          return false;
+        haveRepeat = true;
+        nsCSSValuePair scratch;
+        if (!ParseLayerRepeatValues(scratch)) {
+          NS_NOTREACHED("should be able to parse");
+          return false;
+        }
+        aState.mRepeat->mXValue = scratch.mXValue;
+        aState.mRepeat->mYValue = scratch.mYValue;
+      } else if (nsCSSProps::FindKeyword(keyword,
+                   nsCSSProps::kLayerPositionKTable, dummy)) {
+        if (havePositionAndSize)
+          return false;
+        havePositionAndSize = true;
+        if (!ParsePositionValue(aState.mPosition->mValue)) {
+          return false;
+        }
+        if (ExpectSymbol('/', true)) {
+          nsCSSValuePair scratch;
+          if (!ParseLayerSizeValues(scratch)) {
+            return false;
+          }
+          aState.mSize->mXValue = scratch.mXValue;
+          aState.mSize->mYValue = scratch.mYValue;
+        }
+      } else if (nsCSSProps::FindKeyword(keyword,
+                   nsCSSProps::kLayerOriginKTable, dummy)) {
+        if (haveOrigin)
+          return false;
+        haveOrigin = true;
+        if (ParseSingleValueProperty(aState.mOrigin->mValue,
+                                     eCSSProperty_mask_origin) !=
+            CSSParseResult::Ok) {
+          NS_NOTREACHED("should be able to parse");
+          return false;
+        }
+
+        // The spec allows a second box value (for mask-clip),
+        // immediately following the first one (for mask-origin).
+
+        // 'mask-clip' and 'mask-origin' use the same keyword table
+        MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
+                     eCSSProperty_mask_origin] ==
+                   nsCSSProps::kLayerOriginKTable);
+        MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
+                     eCSSProperty_mask_clip] ==
+                   nsCSSProps::kLayerOriginKTable);
+        static_assert(NS_STYLE_LAYER_CLIP_BORDER ==
+                      NS_STYLE_LAYER_ORIGIN_BORDER &&
+                      NS_STYLE_LAYER_CLIP_PADDING ==
+                      NS_STYLE_LAYER_ORIGIN_PADDING &&
+                      NS_STYLE_LAYER_CLIP_CONTENT ==
+                      NS_STYLE_LAYER_ORIGIN_CONTENT,
+                      "mask-clip and mask-origin style constants must agree");
+
+        CSSParseResult result =
+          ParseSingleValueProperty(aState.mClip->mValue,
+                                   eCSSProperty_mask_clip);
+        MOZ_ASSERT(result != CSSParseResult::Error,
+                   "how can failing to parse a single mask-clip value "
+                   "consume tokens?");
+        if (result == CSSParseResult::NotFound) {
+          // When exactly one <box> value is set, it is used for both
+          // 'mask-origin' and 'mask-clip'.
+          // See assertions above showing these values are compatible.
+          aState.mClip->mValue = aState.mOrigin->mValue;
+        }
+      } else if (nsCSSProps::FindKeyword(keyword,
+                   nsCSSProps::kLayerCompositeKTable, dummy)) {
+        if (haveComposite)
+          return false;
+        haveComposite = true;
+        if (ParseSingleValueProperty(aState.mComposite->mValue,
+                                     eCSSProperty_mask_composite) !=
+            CSSParseResult::Ok) {
+          NS_NOTREACHED("should be able to parse");
+          return false;
+        }
+      } else if (nsCSSProps::FindKeyword(keyword,
+                   nsCSSProps::kLayerModeKTable, dummy)) {
+        if (haveMode)
+          return false;
+        haveMode = true;
+        if (ParseSingleValueProperty(aState.mMode->mValue,
+                                     eCSSProperty_mask_mode) !=
+            CSSParseResult::Ok) {
+          NS_NOTREACHED("should be able to parse");
+          return false;
+        }
+      }
+    } else if (tt == eCSSToken_URL ||
+               (tt == eCSSToken_Function &&
+                IsFunctionTokenValidForStyleLayerImage(mToken))) {
+      if (haveImage)
+        return false;
+      haveImage = true;
+      if (ParseSingleValueProperty(aState.mImage->mValue,
+                                   eCSSProperty_mask_image) !=
+          CSSParseResult::Ok) {
+        return false;
+      }
+    } else if (tt == eCSSToken_Dimension ||
+               tt == eCSSToken_Number ||
+               tt == eCSSToken_Percentage ||
+               (tt == eCSSToken_Function &&
+                (mToken.mIdent.LowerCaseEqualsLiteral("calc") ||
+                 mToken.mIdent.LowerCaseEqualsLiteral("-moz-calc")))) {
+      if (havePositionAndSize)
+        return false;
+      havePositionAndSize = true;
+      if (!ParsePositionValue(aState.mPosition->mValue)) {
+        return false;
+      }
+      if (ExpectSymbol('/', true)) {
+        nsCSSValuePair scratch;
+        if (!ParseLayerSizeValues(scratch)) {
+          return false;
+        }
+        aState.mSize->mXValue = scratch.mXValue;
+        aState.mSize->mYValue = scratch.mYValue;
+      }
+    }
+
+    haveSomething = true;
+  }
+
+  return haveSomething;
+}
+
 // This function is very similar to ParseScrollSnapCoordinate,
-// ParseBackgroundPosition, and ParseBackgroundSize.
+// ParseLayerPosition, and ParseBackgroundSize.
 bool
 CSSParserImpl::ParseValueList(nsCSSProperty aPropID)
 {
   // aPropID is a single value prop-id
   nsCSSValue value;
   // 'initial', 'inherit' and 'unset' stand alone, no list permitted.
   if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
     nsCSSValueList* item = value.SetListValue();
@@ -11257,70 +11514,70 @@ CSSParserImpl::ParseValueList(nsCSSPrope
       item = item->mNext;
     }
   }
   AppendValue(aPropID, value);
   return true;
 }
 
 bool
-CSSParserImpl::ParseBackgroundRepeat()
+CSSParserImpl::ParseLayerRepeat(nsCSSProperty aPropID)
 {
   nsCSSValue value;
   // 'initial', 'inherit' and 'unset' stand alone, no list permitted.
   if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
     nsCSSValuePair valuePair;
-    if (!ParseBackgroundRepeatValues(valuePair)) {
+    if (!ParseLayerRepeatValues(valuePair)) {
       return false;
     }
     nsCSSValuePairList* item = value.SetPairListValue();
     for (;;) {
       item->mXValue = valuePair.mXValue;
       item->mYValue = valuePair.mYValue;
       if (!ExpectSymbol(',', true)) {
         break;
       }
-      if (!ParseBackgroundRepeatValues(valuePair)) {
+      if (!ParseLayerRepeatValues(valuePair)) {
         return false;
       }
       item->mNext = new nsCSSValuePairList;
       item = item->mNext;
     }
   }
 
-  AppendValue(eCSSProperty_background_repeat, value);
-  return true;
-}
-
-bool
-CSSParserImpl::ParseBackgroundRepeatValues(nsCSSValuePair& aValue) 
+  AppendValue(aPropID, value);
+  return true;
+}
+
+bool
+CSSParserImpl::ParseLayerRepeatValues(nsCSSValuePair& aValue)
 {
   nsCSSValue& xValue = aValue.mXValue;
   nsCSSValue& yValue = aValue.mYValue;
-  
-  if (ParseEnum(xValue, nsCSSProps::kBackgroundRepeatKTable)) {
+
+  if (ParseEnum(xValue, nsCSSProps::kLayerRepeatKTable)) {
     int32_t value = xValue.GetIntValue();
     // For single values set yValue as eCSSUnit_Null.
-    if (value == NS_STYLE_BG_REPEAT_REPEAT_X ||
-        value == NS_STYLE_BG_REPEAT_REPEAT_Y ||
-        !ParseEnum(yValue, nsCSSProps::kBackgroundRepeatPartKTable)) {
+    if (value == NS_STYLE_LAYER_REPEAT_REPEAT_X ||
+        value == NS_STYLE_LAYER_REPEAT_REPEAT_Y ||
+        !ParseEnum(yValue, nsCSSProps::kLayerRepeatPartKTable)) {
       // the caller will fail cases like "repeat-x no-repeat"
       // by expecting a list separator or an end property.
       yValue.Reset();
     }
     return true;
   }
   
   return false;
 }
 
-// This function is very similar to ParseScrollSnapCoordinate,
-// ParseBackgroundList, and ParseBackgroundSize.
-bool
-CSSParserImpl::ParseBackgroundPosition()
+// This function is very similar to ParseScrollSnapCoordinate
+// and ParseBackgroundSize.
+bool
+CSSParserImpl::ParseLayerPosition(nsCSSProperty aPropID)
 {
   nsCSSValue value;
   // 'initial', 'inherit' and 'unset' stand alone, no list permitted.
   if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
     nsCSSValue itemValue;
     if (!ParsePositionValue(itemValue)) {
       return false;
     }
@@ -11332,17 +11589,17 @@ CSSParserImpl::ParseBackgroundPosition()
       }
       if (!ParsePositionValue(itemValue)) {
         return false;
       }
       item->mNext = new nsCSSValueList;
       item = item->mNext;
     }
   }
-  AppendValue(eCSSProperty_background_position, value);
+  AppendValue(aPropID, value);
   return true;
 }
 
 /**
  * BoxPositionMaskToCSSValue and ParseBoxPositionValues are used
  * for parsing the CSS 2.1 background-position syntax (which has at
  * most two values).  (Compare to the css3-background syntax which
  * takes up to four values.)  Some current CSS specifications that
@@ -11382,17 +11639,17 @@ bool CSSParserImpl::ParseBoxPositionValu
     result = ParseVariant(yValue, VARIANT_LP | VARIANT_CALC, nullptr);
     if (result == CSSParseResult::Error) {
       return false;
     } else if (result == CSSParseResult::Ok) {
       // We have two numbers
       return true;
     }
 
-    if (ParseEnum(yValue, nsCSSProps::kBackgroundPositionKTable)) {
+    if (ParseEnum(yValue, nsCSSProps::kLayerPositionKTable)) {
       int32_t yVal = yValue.GetIntValue();
       if (!(yVal & BG_CTB)) {
         // The second keyword can only be 'center', 'top', or 'bottom'
         return false;
       }
       yValue = BoxPositionMaskToCSSValue(yVal, false);
       return true;
     }
@@ -11405,20 +11662,20 @@ bool CSSParserImpl::ParseBoxPositionValu
 
   // Now try keywords. We do this manually to allow for the first
   // appearance of "center" to apply to the either the x or y
   // position (it's ambiguous so we have to disambiguate). Each
   // allowed keyword value is assigned it's own bit. We don't allow
   // any duplicate keywords other than center. We try to get two
   // keywords but it's okay if there is only one.
   int32_t mask = 0;
-  if (ParseEnum(xValue, nsCSSProps::kBackgroundPositionKTable)) {
+  if (ParseEnum(xValue, nsCSSProps::kLayerPositionKTable)) {
     int32_t bit = xValue.GetIntValue();
     mask |= bit;
-    if (ParseEnum(xValue, nsCSSProps::kBackgroundPositionKTable)) {
+    if (ParseEnum(xValue, nsCSSProps::kLayerPositionKTable)) {
       bit = xValue.GetIntValue();
       if (mask & (bit & ~BG_CENTER)) {
         // Only the 'center' keyword can be duplicated.
         return false;
       }
       mask |= bit;
     }
     else {
@@ -11466,17 +11723,17 @@ CSSParserImpl::ParsePositionValue(nsCSSV
              &yEdge   = value->Item(2),
              &yOffset = value->Item(3);
 
   // Parse all the values into the array.
   uint32_t valueCount = 0;
   for (int32_t i = 0; i < 4; i++) {
     CSSParseResult result =
       ParseVariant(value->Item(i), VARIANT_LPCALC | VARIANT_KEYWORD,
-                   nsCSSProps::kBackgroundPositionKTable);
+                   nsCSSProps::kLayerPositionKTable);
     if (result == CSSParseResult::Error) {
       return false;
     } else if (result == CSSParseResult::NotFound) {
       break;
     }
     ++valueCount;
   }
 
@@ -11579,17 +11836,17 @@ CSSParserImpl::ParsePositionValue(nsCSSV
       // "If only one value is specified, the second value is assumed to be
       // center."
       if (eCSSUnit_Enumerated == value->Item(0).GetUnit()) {
         xOffset.Reset();
       } else {
         value->Item(1) = value->Item(0); // move xOffset to correct position
         xEdge.Reset();
       }
-      yEdge.SetIntValue(NS_STYLE_BG_POSITION_CENTER, eCSSUnit_Enumerated);
+      yEdge.SetIntValue(NS_STYLE_LAYER_POSITION_CENTER, eCSSUnit_Enumerated);
       yOffset.Reset();
       break;
     default:
       return false;
   }
 
   // For compatibility with CSS2.1 code the edges can be unspecified.
   // Unspecified edges are recorded as nullptr.
@@ -11626,57 +11883,57 @@ CSSParserImpl::ParsePositionValue(nsCSSV
     yEdge = swapEdge;
     yOffset = swapOffset;
   }
 
   return true;
 }
 
 // This function is very similar to ParseScrollSnapCoordinate,
-// ParseBackgroundList, and ParseBackgroundPosition.
-bool
-CSSParserImpl::ParseBackgroundSize()
+// and ParseLayerPosition.
+bool
+CSSParserImpl::ParseLayerSize(nsCSSProperty aPropID)
 {
   nsCSSValue value;
   // 'initial', 'inherit' and 'unset' stand alone, no list permitted.
   if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
     nsCSSValuePair valuePair;
-    if (!ParseBackgroundSizeValues(valuePair)) {
+    if (!ParseLayerSizeValues(valuePair)) {
       return false;
     }
     nsCSSValuePairList* item = value.SetPairListValue();
     for (;;) {
       item->mXValue = valuePair.mXValue;
       item->mYValue = valuePair.mYValue;
       if (!ExpectSymbol(',', true)) {
         break;
       }
-      if (!ParseBackgroundSizeValues(valuePair)) {
+      if (!ParseLayerSizeValues(valuePair)) {
         return false;
       }
       item->mNext = new nsCSSValuePairList;
       item = item->mNext;
     }
   }
-  AppendValue(eCSSProperty_background_size, value);
+  AppendValue(aPropID, value);
   return true;
 }
 
 /**
  * Parses two values that correspond to lengths for the background-size
  * property.  These can be one or two lengths (or the 'auto' keyword) or
  * percentages corresponding to the element's dimensions or the single keywords
  * 'contain' or 'cover'.  'initial', 'inherit' and 'unset' must be handled by
  * the caller if desired.
  *
  * @param aOut The nsCSSValuePair in which to place the result.
  * @return Whether or not the operation succeeded.
  */
 #define BG_SIZE_VARIANT (VARIANT_LP | VARIANT_AUTO | VARIANT_CALC)
-bool CSSParserImpl::ParseBackgroundSizeValues(nsCSSValuePair &aOut)
+bool CSSParserImpl::ParseLayerSizeValues(nsCSSValuePair &aOut)
 {
   // First try a percentage or a length value
   nsCSSValue &xValue = aOut.mXValue,
              &yValue = aOut.mYValue;
   CSSParseResult result =
     ParseNonNegativeVariant(xValue, BG_SIZE_VARIANT, nullptr);
   if (result == CSSParseResult::Error) {
     return false;
@@ -11693,21 +11950,22 @@ bool CSSParserImpl::ParseBackgroundSizeV
 
     // If only one percentage or length value is given, it sets the
     // horizontal size only, and the vertical size will be as if by 'auto'.
     yValue.SetAutoValue();
     return true;
   }
 
   // Now address 'contain' and 'cover'.
-  if (!ParseEnum(xValue, nsCSSProps::kBackgroundSizeKTable))
+  if (!ParseEnum(xValue, nsCSSProps::kLayerSizeKTable))
     return false;
   yValue.Reset();
   return true;
 }
+
 #undef BG_SIZE_VARIANT
 
 bool
 CSSParserImpl::ParseBorderColor()
 {
   return ParseBoxProperties(kBorderColorIDs);
 }
 
@@ -15841,18 +16099,17 @@ CSSParserImpl::ParseScrollSnapDestinatio
   nsCSSValue itemValue;
   if (!ParsePositionValue(aValue)) {
     REPORT_UNEXPECTED_TOKEN(PEExpectedPosition);
     return false;
   }
   return true;
 }
 
-// This function is very similar to ParseBackgroundPosition, ParseBackgroundList
-// and ParseBackgroundSize.
+// This function is very similar to ParseLayerPosition, and ParseLayerSize.
 bool
 CSSParserImpl::ParseScrollSnapCoordinate(nsCSSValue& aValue)
 {
   if (ParseSingleTokenVariant(aValue, VARIANT_INHERIT | VARIANT_NONE,
                               nullptr)) {
     return true;
   }
   nsCSSValue itemValue;
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -532,30 +532,30 @@ CSS_PROP_BACKGROUND(
     background_attachment,
     BackgroundAttachment,
     CSS_PROPERTY_PARSE_VALUE_LIST |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
     "",
     VARIANT_KEYWORD, // used by list parsing
-    kBackgroundAttachmentKTable,
+    kLayerAttachmentKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_BACKGROUND(
     background-clip,
     background_clip,
     BackgroundClip,
     CSS_PROPERTY_PARSE_VALUE_LIST |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
     "",
     VARIANT_KEYWORD, // used by list parsing
-    kBackgroundOriginKTable,
+    kLayerOriginKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_BACKGROUND(
     background-color,
     background_color,
     BackgroundColor,
     CSS_PROPERTY_PARSE_VALUE |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
@@ -600,60 +600,60 @@ CSS_PROP_BACKGROUND(
     background_origin,
     BackgroundOrigin,
     CSS_PROPERTY_PARSE_VALUE_LIST |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
     "",
     VARIANT_KEYWORD, // used by list parsing
-    kBackgroundOriginKTable,
+    kLayerOriginKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_BACKGROUND(
     background-position,
     background_position,
     BackgroundPosition,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
         CSS_PROPERTY_UNITLESS_LENGTH_QUIRK |
         CSS_PROPERTY_STORES_CALC,
     "",
     0,
-    kBackgroundPositionKTable,
+    kLayerPositionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
 CSS_PROP_BACKGROUND(
     background-repeat,
     background_repeat,
     BackgroundRepeat,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
     "",
     VARIANT_KEYWORD, // used by list parsing
-    kBackgroundRepeatKTable,
+    kLayerRepeatKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_BACKGROUND(
     background-size,
     background_size,
     BackgroundSize,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
         CSS_PROPERTY_VALUE_NONNEGATIVE |
         CSS_PROPERTY_STORES_CALC,
     "",
     0,
-    kBackgroundSizeKTable,
+    kLayerSizeKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
 CSS_PROP_DISPLAY(
     -moz-binding,
     binding,
     CSS_PROP_DOMPROP_PREFIXED(Binding),
     CSS_PROPERTY_PARSE_VALUE,
     "",
@@ -2597,17 +2597,17 @@ CSS_PROP_POSITION(
     object-position,
     object_position,
     ObjectPosition,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_STORES_CALC |
         CSS_PROPERTY_ENABLED_IN_UA_SHEETS,
     "layout.css.object-fit-and-position.enabled",
     0,
-    kBackgroundPositionKTable,
+    kLayerPositionKTable,
     offsetof(nsStylePosition, mObjectPosition),
     eStyleAnimType_Custom)
 CSS_PROP_LOGICAL(
     offset-block-end,
     offset_block_end,
     OffsetBlockEnd,
     CSS_PROPERTY_PARSE_VALUE |
         CSS_PROPERTY_STORES_CALC |
@@ -3078,29 +3078,29 @@ CSS_PROP_DISPLAY(
     scroll_snap_coordinate,
     ScrollSnapCoordinate,
     CSS_PROPERTY_PARSE_VALUE |
         CSS_PROPERTY_VALUE_PARSER_FUNCTION |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
         CSS_PROPERTY_STORES_CALC,
     "layout.css.scroll-snap.enabled",
     0,
-    kBackgroundPositionKTable,
+    kLayerPositionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_DISPLAY(
     scroll-snap-destination,
     scroll_snap_destination,
     ScrollSnapDestination,
     CSS_PROPERTY_PARSE_VALUE |
         CSS_PROPERTY_VALUE_PARSER_FUNCTION |
         CSS_PROPERTY_STORES_CALC,
     "layout.css.scroll-snap.enabled",
     0,
-    kBackgroundPositionKTable,
+    kLayerPositionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_DISPLAY(
     scroll-snap-points-x,
     scroll_snap_points_x,
     ScrollSnapPointsX,
     CSS_PROPERTY_PARSE_VALUE |
         CSS_PROPERTY_VALUE_PARSER_FUNCTION |
@@ -3336,29 +3336,29 @@ CSS_PROP_DISPLAY(
     transform-origin,
     transform_origin,
     TransformOrigin,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_STORES_CALC |
         CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH,
     "",
     0,
-    kBackgroundPositionKTable,
+    kLayerPositionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
 CSS_PROP_DISPLAY(
     perspective-origin,
     perspective_origin,
     PerspectiveOrigin,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_STORES_CALC |
         CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH,
     "",
     0,
-    kBackgroundPositionKTable,
+    kLayerPositionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
 CSS_PROP_DISPLAY(
     perspective,
     perspective,
     Perspective,
     CSS_PROPERTY_PARSE_VALUE |
         CSS_PROPERTY_CREATES_STACKING_CONTEXT,
@@ -3976,28 +3976,137 @@ CSS_PROP_SVG(
     marker_start,
     MarkerStart,
     CSS_PROPERTY_PARSE_VALUE,
     "",
     VARIANT_HUO,
     nullptr,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
-CSS_PROP_SVGRESET(
+CSS_PROP_SHORTHAND(
     mask,
     mask,
     Mask,
-    CSS_PROPERTY_PARSE_VALUE |
-        CSS_PROPERTY_CREATES_STACKING_CONTEXT,
-    "",
-    VARIANT_HUO,
+    CSS_PROPERTY_PARSE_FUNCTION,
+    "")
+CSS_PROP_SVGRESET(
+    mask-image,
+    mask_image,
+    MaskImage,
+    CSS_PROPERTY_PARSE_VALUE_LIST |
+        CSS_PROPERTY_CREATES_STACKING_CONTEXT |
+        CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
+        CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
+        CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
+        CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED |
+        CSS_PROPERTY_START_IMAGE_LOADS,
+    "",
+    VARIANT_IMAGE,
     nullptr,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_SVGRESET(
+    mask-repeat,
+    mask_repeat,
+    MaskRepeat,
+    CSS_PROPERTY_PARSE_FUNCTION |
+        CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
+        CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
+        CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
+    "",
+    VARIANT_KEYWORD, // used by list parsing
+    kLayerRepeatKTable,
+    CSS_PROP_NO_OFFSET,
+    eStyleAnimType_None)
+CSS_PROP_SVGRESET(
+    mask-origin,
+    mask_origin,
+    MaskOrigin,
+    CSS_PROPERTY_PARSE_VALUE_LIST |
+        CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
+        CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
+        CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
+    "",
+    VARIANT_KEYWORD, // used by list parsing
+    kLayerOriginKTable,
+    CSS_PROP_NO_OFFSET,
+    eStyleAnimType_None)
+CSS_PROP_SVGRESET(
+    mask-clip,
+    mask_clip,
+    MaskClip,
+    CSS_PROPERTY_PARSE_VALUE_LIST |
+        CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
+        CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
+        CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
+    "",
+    VARIANT_KEYWORD, // used by list parsing
+    kLayerOriginKTable,
+    CSS_PROP_NO_OFFSET,
+    eStyleAnimType_None)
+// TBD
+// Copy from background-position, which animation type is eStyleAnimType_Custom
+// Need to do something in StyleAnimationValue::ExtractComputedValue.
+CSS_PROP_SVGRESET(
+    mask-position,
+    mask_position,
+    MaskPosition,
+    CSS_PROPERTY_PARSE_FUNCTION |
+        CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
+        CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
+        CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
+        CSS_PROPERTY_UNITLESS_LENGTH_QUIRK |
+        CSS_PROPERTY_STORES_CALC,
+    "",
+    0,
+    kLayerPositionKTable,
+    CSS_PROP_NO_OFFSET,
+    eStyleAnimType_Custom)
+CSS_PROP_SVGRESET(
+    mask-size,
+    mask_size,
+    MaskSize,
+    CSS_PROPERTY_PARSE_FUNCTION |
+        CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
+        CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
+        CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
+        CSS_PROPERTY_VALUE_NONNEGATIVE |
+        CSS_PROPERTY_STORES_CALC,
+    "",
+    0,
+    kLayerSizeKTable,
+    CSS_PROP_NO_OFFSET,
+    eStyleAnimType_Custom)
+CSS_PROP_SVGRESET(
+    mask-mode,
+    mask_mode,
+    MaskMode,
+    CSS_PROPERTY_PARSE_VALUE_LIST |
+        CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
+        CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
+        CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
+    "",
+    VARIANT_KEYWORD, // used by list parsing
+    kLayerModeKTable,
+    CSS_PROP_NO_OFFSET,
+    eStyleAnimType_None)
+CSS_PROP_SVGRESET(
+    mask-composite,
+    mask_composite,
+    MaskComposite,
+    CSS_PROPERTY_PARSE_VALUE_LIST |
+        CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
+        CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
+        CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
+    "",
+    VARIANT_KEYWORD, // used by list parsing
+    kLayerCompositeKTable,
+    CSS_PROP_NO_OFFSET,
+    eStyleAnimType_None)
+CSS_PROP_SVGRESET(
     mask-type,
     mask_type,
     MaskType,
     CSS_PROPERTY_PARSE_VALUE,
     "layout.css.masking.enabled",
     VARIANT_HK,
     kMaskTypeKTable,
     offsetof(nsStyleSVGReset, mMaskType),
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -857,63 +857,77 @@ const KTableValue nsCSSProps::kBackfaceV
 };
 
 const KTableValue nsCSSProps::kTransformStyleKTable[] = {
   eCSSKeyword_flat, NS_STYLE_TRANSFORM_STYLE_FLAT,
   eCSSKeyword_preserve_3d, NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D,
   eCSSKeyword_UNKNOWN,-1
 };
 
-const KTableValue nsCSSProps::kBackgroundAttachmentKTable[] = {
-  eCSSKeyword_fixed, NS_STYLE_BG_ATTACHMENT_FIXED,
-  eCSSKeyword_scroll, NS_STYLE_BG_ATTACHMENT_SCROLL,
-  eCSSKeyword_local, NS_STYLE_BG_ATTACHMENT_LOCAL,
+const KTableValue nsCSSProps::kLayerAttachmentKTable[] = {
+  eCSSKeyword_fixed, NS_STYLE_LAYER_ATTACHMENT_FIXED,
+  eCSSKeyword_scroll, NS_STYLE_LAYER_ATTACHMENT_SCROLL,
+  eCSSKeyword_local, NS_STYLE_LAYER_ATTACHMENT_LOCAL,
   eCSSKeyword_UNKNOWN,-1
 };
 
-static_assert(NS_STYLE_BG_CLIP_BORDER == NS_STYLE_BG_ORIGIN_BORDER &&
-              NS_STYLE_BG_CLIP_PADDING == NS_STYLE_BG_ORIGIN_PADDING &&
-              NS_STYLE_BG_CLIP_CONTENT == NS_STYLE_BG_ORIGIN_CONTENT,
+static_assert(NS_STYLE_LAYER_CLIP_BORDER == NS_STYLE_LAYER_ORIGIN_BORDER &&
+              NS_STYLE_LAYER_CLIP_PADDING == NS_STYLE_LAYER_ORIGIN_PADDING &&
+              NS_STYLE_LAYER_CLIP_CONTENT == NS_STYLE_LAYER_ORIGIN_CONTENT,
               "bg-clip and bg-origin style constants must agree");
-const KTableValue nsCSSProps::kBackgroundOriginKTable[] = {
-  eCSSKeyword_border_box, NS_STYLE_BG_ORIGIN_BORDER,
-  eCSSKeyword_padding_box, NS_STYLE_BG_ORIGIN_PADDING,
-  eCSSKeyword_content_box, NS_STYLE_BG_ORIGIN_CONTENT,
+const KTableValue nsCSSProps::kLayerOriginKTable[] = {
+  eCSSKeyword_border_box, NS_STYLE_LAYER_ORIGIN_BORDER,
+  eCSSKeyword_padding_box, NS_STYLE_LAYER_ORIGIN_PADDING,
+  eCSSKeyword_content_box, NS_STYLE_LAYER_ORIGIN_CONTENT,
   eCSSKeyword_UNKNOWN,-1
 };
 
 // Note: Don't change this table unless you update
 // parseBackgroundPosition!
 
-const KTableValue nsCSSProps::kBackgroundPositionKTable[] = {
-  eCSSKeyword_center, NS_STYLE_BG_POSITION_CENTER,
-  eCSSKeyword_top, NS_STYLE_BG_POSITION_TOP,
-  eCSSKeyword_bottom, NS_STYLE_BG_POSITION_BOTTOM,
-  eCSSKeyword_left, NS_STYLE_BG_POSITION_LEFT,
-  eCSSKeyword_right, NS_STYLE_BG_POSITION_RIGHT,
+const KTableValue nsCSSProps::kLayerPositionKTable[] = {
+  eCSSKeyword_center, NS_STYLE_LAYER_POSITION_CENTER,
+  eCSSKeyword_top, NS_STYLE_LAYER_POSITION_TOP,
+  eCSSKeyword_bottom, NS_STYLE_LAYER_POSITION_BOTTOM,
+  eCSSKeyword_left, NS_STYLE_LAYER_POSITION_LEFT,
+  eCSSKeyword_right, NS_STYLE_LAYER_POSITION_RIGHT,
+  eCSSKeyword_UNKNOWN,-1
+};
+
+const KTableValue nsCSSProps::kLayerRepeatKTable[] = {
+  eCSSKeyword_no_repeat,  NS_STYLE_LAYER_REPEAT_NO_REPEAT,
+  eCSSKeyword_repeat,     NS_STYLE_LAYER_REPEAT_REPEAT,
+  eCSSKeyword_repeat_x,   NS_STYLE_LAYER_REPEAT_REPEAT_X,
+  eCSSKeyword_repeat_y,   NS_STYLE_LAYER_REPEAT_REPEAT_Y,
   eCSSKeyword_UNKNOWN,-1
 };
 
-const KTableValue nsCSSProps::kBackgroundRepeatKTable[] = {
-  eCSSKeyword_no_repeat,  NS_STYLE_BG_REPEAT_NO_REPEAT,
-  eCSSKeyword_repeat,     NS_STYLE_BG_REPEAT_REPEAT,
-  eCSSKeyword_repeat_x,   NS_STYLE_BG_REPEAT_REPEAT_X,
-  eCSSKeyword_repeat_y,   NS_STYLE_BG_REPEAT_REPEAT_Y,
+const KTableValue nsCSSProps::kLayerRepeatPartKTable[] = {
+  eCSSKeyword_no_repeat,  NS_STYLE_LAYER_REPEAT_NO_REPEAT,
+  eCSSKeyword_repeat,     NS_STYLE_LAYER_REPEAT_REPEAT,
+  eCSSKeyword_UNKNOWN,-1
+};
+
+const KTableValue nsCSSProps::kLayerSizeKTable[] = {
+  eCSSKeyword_contain, NS_STYLE_LAYER_SIZE_CONTAIN,
+  eCSSKeyword_cover,   NS_STYLE_LAYER_SIZE_COVER,
   eCSSKeyword_UNKNOWN,-1
 };
 
-const KTableValue nsCSSProps::kBackgroundRepeatPartKTable[] = {
-  eCSSKeyword_no_repeat,  NS_STYLE_BG_REPEAT_NO_REPEAT,
-  eCSSKeyword_repeat,     NS_STYLE_BG_REPEAT_REPEAT,
+const KTableValue nsCSSProps::kLayerModeKTable[] = {
+  eCSSKeyword_alpha, NS_STYLE_LAYER_MODE_ALPHA,
+  eCSSKeyword_luminance, NS_STYLE_LAYER_MODE_LUMINANCE,
+  eCSSKeyword_auto, NS_STYLE_LAYER_MODE_AUTO,
   eCSSKeyword_UNKNOWN,-1
 };
 
-const KTableValue nsCSSProps::kBackgroundSizeKTable[] = {
-  eCSSKeyword_contain, NS_STYLE_BG_SIZE_CONTAIN,
-  eCSSKeyword_cover,   NS_STYLE_BG_SIZE_COVER,
+const KTableValue nsCSSProps::kLayerCompositeKTable[] = {
+  eCSSKeyword_subtract, NS_STYLE_COMPOSITE_SUBTRACT,
+  eCSSKeyword_intersect, NS_STYLE_COMPOSITE_INTERSECT,
+  eCSSKeyword_exclude, NS_STYLE_COMPOSITE_EXCLUDE,
   eCSSKeyword_UNKNOWN,-1
 };
 
 const KTableValue nsCSSProps::kBlendModeKTable[] = {
     eCSSKeyword_normal,      NS_STYLE_BLEND_NORMAL,
     eCSSKeyword_multiply,    NS_STYLE_BLEND_MULTIPLY,
     eCSSKeyword_screen,      NS_STYLE_BLEND_SCREEN,
     eCSSKeyword_overlay,     NS_STYLE_BLEND_OVERLAY,
@@ -2173,16 +2187,18 @@ const KTableValue nsCSSProps::kImageRend
 };
 
 const KTableValue nsCSSProps::kMaskTypeKTable[] = {
   eCSSKeyword_luminance, NS_STYLE_MASK_TYPE_LUMINANCE,
   eCSSKeyword_alpha, NS_STYLE_MASK_TYPE_ALPHA,
   eCSSKeyword_UNKNOWN, -1
 };
 
+
+
 const KTableValue nsCSSProps::kShapeRenderingKTable[] = {
   eCSSKeyword_auto, NS_STYLE_SHAPE_RENDERING_AUTO,
   eCSSKeyword_optimizespeed, NS_STYLE_SHAPE_RENDERING_OPTIMIZESPEED,
   eCSSKeyword_crispedges, NS_STYLE_SHAPE_RENDERING_CRISPEDGES,
   eCSSKeyword_geometricprecision, NS_STYLE_SHAPE_RENDERING_GEOMETRICPRECISION,
   eCSSKeyword_UNKNOWN, -1
 };
 
@@ -2775,16 +2791,27 @@ static const nsCSSProperty gMozTransform
 };
 
 static const nsCSSProperty gScrollSnapTypeSubpropTable[] = {
   eCSSProperty_scroll_snap_type_x,
   eCSSProperty_scroll_snap_type_y,
   eCSSProperty_UNKNOWN
 };
 
+static const nsCSSProperty gMaskSubpropTable[] = {
+  eCSSProperty_mask_image,
+  eCSSProperty_mask_repeat,
+  eCSSProperty_mask_position,
+  eCSSProperty_mask_clip,
+  eCSSProperty_mask_origin,
+  eCSSProperty_mask_size,
+  eCSSProperty_mask_composite,
+  eCSSProperty_mask_mode,
+  eCSSProperty_UNKNOWN
+};
 const nsCSSProperty *const
 nsCSSProps::kSubpropertyTable[eCSSProperty_COUNT - eCSSProperty_COUNT_no_shorthands] = {
 #define CSS_PROP_PUBLIC_OR_PRIVATE(publicname_, privatename_) privatename_
 // Need an extra level of macro nesting to force expansion of method_
 // params before they get pasted.
 #define NSCSSPROPS_INNER_MACRO(method_) g##method_##SubpropTable,
 #define CSS_PROP_SHORTHAND(name_, id_, method_, flags_, pref_) \
   NSCSSPROPS_INNER_MACRO(method_)
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -631,22 +631,24 @@ public:
   static const KTableValue kAnimationFillModeKTable[];
   static const KTableValue kAnimationIterationCountKTable[];
   static const KTableValue kAnimationPlayStateKTable[];
   static const KTableValue kAnimationTimingFunctionKTable[];
   static const KTableValue kAppearanceKTable[];
   static const KTableValue kAzimuthKTable[];
   static const KTableValue kBackfaceVisibilityKTable[];
   static const KTableValue kTransformStyleKTable[];
-  static const KTableValue kBackgroundAttachmentKTable[];
-  static const KTableValue kBackgroundOriginKTable[];
-  static const KTableValue kBackgroundPositionKTable[];
-  static const KTableValue kBackgroundRepeatKTable[];
-  static const KTableValue kBackgroundRepeatPartKTable[];
-  static const KTableValue kBackgroundSizeKTable[];
+  static const KTableValue kLayerAttachmentKTable[];
+  static const KTableValue kLayerOriginKTable[];
+  static const KTableValue kLayerPositionKTable[];
+  static const KTableValue kLayerRepeatKTable[];
+  static const KTableValue kLayerRepeatPartKTable[];
+  static const KTableValue kLayerSizeKTable[];
+  static const KTableValue kLayerCompositeKTable[];
+  static const KTableValue kLayerModeKTable[];
   static const KTableValue kBlendModeKTable[];
   static const KTableValue kBorderCollapseKTable[];
   static const KTableValue kBorderColorKTable[];
   static const KTableValue kBorderImageRepeatKTable[];
   static const KTableValue kBorderImageSliceKTable[];
   static const KTableValue kBorderStyleKTable[];
   static const KTableValue kBorderWidthKTable[];
   static const KTableValue kBoxAlignKTable[];
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -1489,22 +1489,22 @@ nsCSSValue::AppendToString(nsCSSProperty
     if (!gradient->mIsRadial && !gradient->mIsLegacySyntax) {
       if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None ||
           gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None) {
         MOZ_ASSERT(gradient->mAngle.GetUnit() == eCSSUnit_None);
         MOZ_ASSERT(gradient->mBgPos.mXValue.GetUnit() == eCSSUnit_Enumerated &&
                    gradient->mBgPos.mYValue.GetUnit() == eCSSUnit_Enumerated,
                    "unexpected unit");
         aResult.AppendLiteral("to");
-        if (!(gradient->mBgPos.mXValue.GetIntValue() & NS_STYLE_BG_POSITION_CENTER)) {
+        if (!(gradient->mBgPos.mXValue.GetIntValue() & NS_STYLE_LAYER_POSITION_CENTER)) {
           aResult.Append(' ');
           gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position,
                                                   aResult, aSerialization);
         }
-        if (!(gradient->mBgPos.mYValue.GetIntValue() & NS_STYLE_BG_POSITION_CENTER)) {
+        if (!(gradient->mBgPos.mYValue.GetIntValue() & NS_STYLE_LAYER_POSITION_CENTER)) {
           aResult.Append(' ');
           gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position,
                                                   aResult, aSerialization);
         }
         needSep = true;
       } else if (gradient->mAngle.GetUnit() != eCSSUnit_None) {
         gradient->mAngle.AppendToString(aProperty, aResult, aSerialization);
         needSep = true;
--- a/layout/style/nsComputedDOMStylePropertyList.h
+++ b/layout/style/nsComputedDOMStylePropertyList.h
@@ -57,16 +57,25 @@ COMPUTED_STYLE_PROP(background_attachmen
 COMPUTED_STYLE_PROP(background_blend_mode,         BackgroundBlendMode)
 COMPUTED_STYLE_PROP(background_clip,               BackgroundClip)
 COMPUTED_STYLE_PROP(background_color,              BackgroundColor)
 COMPUTED_STYLE_PROP(background_image,              BackgroundImage)
 COMPUTED_STYLE_PROP(background_origin,             BackgroundOrigin)
 COMPUTED_STYLE_PROP(background_position,           BackgroundPosition)
 COMPUTED_STYLE_PROP(background_repeat,             BackgroundRepeat)
 COMPUTED_STYLE_PROP(background_size,               BackgroundSize)
+///// COMPUTED_STYLE_PROP(mask,                    Mask)
+COMPUTED_STYLE_PROP(mask_clip,                     MaskClip)
+COMPUTED_STYLE_PROP(mask_image,                    MaskImage)
+COMPUTED_STYLE_PROP(mask_origin,                   MaskOrigin)
+COMPUTED_STYLE_PROP(mask_position,                 MaskPosition)
+COMPUTED_STYLE_PROP(mask_repeat,                   MaskRepeat)
+COMPUTED_STYLE_PROP(mask_size,                     MaskSize)
+COMPUTED_STYLE_PROP(mask_mode,                     MaskMode)
+COMPUTED_STYLE_PROP(mask_composite,                MaskComposite)
 //// COMPUTED_STYLE_PROP(border,                   Border)
 //// COMPUTED_STYLE_PROP(border_bottom,            BorderBottom)
 COMPUTED_STYLE_PROP(border_bottom_color,           BorderBottomColor)
 COMPUTED_STYLE_PROP(border_bottom_left_radius,     BorderBottomLeftRadius)
 COMPUTED_STYLE_PROP(border_bottom_right_radius,    BorderBottomRightRadius)
 COMPUTED_STYLE_PROP(border_bottom_style,           BorderBottomStyle)
 COMPUTED_STYLE_PROP(border_bottom_width,           BorderBottomWidth)
 COMPUTED_STYLE_PROP(border_collapse,               BorderCollapse)
@@ -306,17 +315,16 @@ COMPUTED_STYLE_PROP(fill_rule,          
 COMPUTED_STYLE_PROP(filter,                        Filter)
 COMPUTED_STYLE_PROP(flood_color,                   FloodColor)
 COMPUTED_STYLE_PROP(flood_opacity,                 FloodOpacity)
 COMPUTED_STYLE_PROP(image_rendering,               ImageRendering)
 COMPUTED_STYLE_PROP(lighting_color,                LightingColor)
 COMPUTED_STYLE_PROP(marker_end,                    MarkerEnd)
 COMPUTED_STYLE_PROP(marker_mid,                    MarkerMid)
 COMPUTED_STYLE_PROP(marker_start,                  MarkerStart)
-COMPUTED_STYLE_PROP(mask,                          Mask)
 COMPUTED_STYLE_PROP(mask_type,                     MaskType)
 COMPUTED_STYLE_PROP(paint_order,                   PaintOrder)
 COMPUTED_STYLE_PROP(shape_rendering,               ShapeRendering)
 COMPUTED_STYLE_PROP(stop_color,                    StopColor)
 COMPUTED_STYLE_PROP(stop_opacity,                  StopOpacity)
 COMPUTED_STYLE_PROP(stroke,                        Stroke)
 COMPUTED_STYLE_PROP(stroke_dasharray,              StrokeDasharray)
 COMPUTED_STYLE_PROP(stroke_dashoffset,             StrokeDashoffset)