Bug 1301638 : Part 1 - Add pref control for CSS positioned mask props. draft
authorAstley Chen <aschen@mozilla.com>
Fri, 04 Nov 2016 15:21:03 +0800
changeset 433758 442f61c1063639ebcc2917caf01a5f1f92632a3f
parent 428476 215f9686117673a2c914ed207bc7da9bb8d741ad
child 433759 854000f8097e0ef101a601f188c3f7a53063e034
push id34640
push useraschen@mozilla.com
push dateFri, 04 Nov 2016 07:57:51 +0000
bugs1301638
milestone52.0a1
Bug 1301638 : Part 1 - Add pref control for CSS positioned mask props. MozReview-Commit-ID: DGT2TKKU9Bu
layout/inspector/inDOMUtils.cpp
layout/style/Declaration.cpp
layout/style/StyleAnimationValue.cpp
layout/style/nsCSSDataBlock.cpp
layout/style/nsCSSParser.cpp
layout/style/nsCSSPropAliasList.h
layout/style/nsCSSPropList.h
layout/style/nsCSSProps.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
layout/style/nsComputedDOMStylePropertyList.h
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/test/moz.build
layout/svg/nsSVGIntegrationUtils.cpp
modules/libpref/init/all.js
old-configure.in
--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -778,22 +778,20 @@ PropertySupportsVariant(nsCSSPropertyID 
       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_position_x:
       case eCSSProperty_background_position_y:
       case eCSSProperty_background_size:
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
       case eCSSProperty_mask_position:
       case eCSSProperty_mask_position_x:
       case eCSSProperty_mask_position_y:
       case eCSSProperty_mask_size:
-#endif
       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
@@ -248,21 +248,20 @@ AppendSingleImageLayerPositionValue(cons
     // Output 4-value form by adding the y edge.
     aValue.AppendLiteral("top ");
   }
   aPositionY.AppendToString(aTable[nsStyleImageLayers::positionY],
                             aValue, aSerialization);
 }
 
 void
-Declaration::GetImageLayerValue(
-                   nsCSSCompressedDataBlock *data,
-                   nsAString& aValue,
-                   nsCSSValue::Serialization aSerialization,
-                   const nsCSSPropertyID aTable[]) const
+Declaration::GetImageLayerValue(nsCSSCompressedDataBlock* data,
+                                nsAString& aValue,
+                                nsCSSValue::Serialization aSerialization,
+                                const nsCSSPropertyID aTable[]) const
 {
   // We know from our caller 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.)
@@ -408,21 +407,17 @@ Declaration::GetImageLayerValue(
         if (repeat || positionX || positionY || clip || origin || size ||
             attachment) {
           // Uneven length lists, so can't be serialized as shorthand.
           aValue.Truncate();
           return;
         }
       // This layer is an mask layer
       } else {
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
         MOZ_ASSERT(aTable == nsStyleImageLayers::kMaskLayerTable);
-#else
-        MOZ_ASSERT_UNREACHABLE("Should never get here when mask-as-shorthand is disable");
-#endif
         if (repeat || positionX || positionY || clip || origin || size ||
             composite || mode) {
           // Uneven length lists, so can't be serialized as shorthand.
           aValue.Truncate();
           return;
         }
       }
       break;
@@ -433,21 +428,17 @@ Declaration::GetImageLayerValue(
       if (!repeat || !positionX || !positionY || !clip || !origin || !size ||
           !attachment) {
         // Uneven length lists, so can't be serialized as shorthand.
         aValue.Truncate();
         return;
       }
     // This layer is an mask layer
     } else {
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
       MOZ_ASSERT(aTable == nsStyleImageLayers::kMaskLayerTable);
-#else
-      MOZ_ASSERT_UNREACHABLE("Should never get here when mask-as-shorthand is disable");
-#endif
       if (!repeat || !positionX || !positionY || !clip || !origin || !size ||
           !composite || !mode) {
         // Uneven length lists, so can't be serialized as shorthand.
         aValue.Truncate();
         return;
       }
     }
     aValue.Append(char16_t(','));
@@ -762,28 +753,26 @@ Declaration::GetValue(nsCSSPropertyID aP
                          nsStyleImageLayers::kBackgroundLayerTable);
       break;
     }
     case eCSSProperty_background_position: {
       GetImageLayerPositionValue(data, aValue, aSerialization,
                                  nsStyleImageLayers::kBackgroundLayerTable);
       break;
     }
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
     case eCSSProperty_mask: {
       GetImageLayerValue(data, aValue, aSerialization,
                          nsStyleImageLayers::kMaskLayerTable);
       break;
     }
     case eCSSProperty_mask_position: {
       GetImageLayerPositionValue(data, aValue, aSerialization,
                                  nsStyleImageLayers::kMaskLayerTable);
       break;
     }
-#endif
     case eCSSProperty_font: {
       // systemFont might not be present; other values are guaranteed to be
       // available based on the shorthand check at the beginning of the
       // function, as long as the prop is enabled
       const nsCSSValue *systemFont =
         data->ValueFor(eCSSProperty__x_system_font);
       const nsCSSValue *style =
         data->ValueFor(eCSSProperty_font_style);
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -4061,46 +4061,41 @@ StyleAnimationValue::ExtractComputedValu
             static_cast<const nsStyleBackground*>(styleStruct)->mImage;
           ExtractImageLayerPositionYList(layers, aComputedValue);
           break;
 
 
 
 
         }
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
         case eCSSProperty_mask_position_x: {
           const nsStyleImageLayers& layers =
             static_cast<const nsStyleSVGReset*>(styleStruct)->mMask;
           ExtractImageLayerPositionXList(layers, aComputedValue);
           break;
         }
         case eCSSProperty_mask_position_y: {
           const nsStyleImageLayers& layers =
             static_cast<const nsStyleSVGReset*>(styleStruct)->mMask;
           ExtractImageLayerPositionYList(layers, aComputedValue);
 
           break;
         }
-#endif
         case eCSSProperty_background_size: {
           const nsStyleImageLayers& layers =
             static_cast<const nsStyleBackground*>(styleStruct)->mImage;
           ExtractImageLayerSizePairList(layers, aComputedValue);
           break;
         }
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
         case eCSSProperty_mask_size: {
           const nsStyleImageLayers& layers =
             static_cast<const nsStyleSVGReset*>(styleStruct)->mMask;
           ExtractImageLayerSizePairList(layers, aComputedValue);
           break;
         }
-#endif
-
         case eCSSProperty_clip_path: {
           const nsStyleSVGReset* svgReset =
             static_cast<const nsStyleSVGReset*>(styleStruct);
           const StyleClipPath& clipPath = svgReset->mClipPath;
           const StyleShapeSourceType type = clipPath.GetType();
 
           if (type == StyleShapeSourceType::URL) {
             auto result = MakeUnique<nsCSSValue>();
--- a/layout/style/nsCSSDataBlock.cpp
+++ b/layout/style/nsCSSDataBlock.cpp
@@ -56,17 +56,16 @@ ShouldIgnoreColors(nsRuleData *aRuleData
 static void
 TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument,
                            nsStyleContext* aContext, nsCSSPropertyID aProperty,
                            bool aForTokenStream)
 {
   MOZ_ASSERT(aDocument);
 
   if (aValue.GetUnit() == eCSSUnit_URL) {
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
     // The 'mask-image' property accepts local reference URIs.
     // For example,
     //   mask-image: url(#mask_id); // refer to a SVG mask element, whose id is
     //                              // "mask_id", in the current document.
     // For such 'mask-image' values (pointing to an in-document element),
     // there is no need to trigger image download.
     if (aProperty == eCSSProperty_mask_image) {
       // Filter out all fragment URLs.
@@ -89,17 +88,17 @@ TryToStartImageLoadOnValue(const nsCSSVa
         nsIURI* docURI = aDocument->GetDocumentURI();
         bool isEqualExceptRef = false;
         nsresult  rv = imageURI->EqualsExceptRef(docURI, &isEqualExceptRef);
         if (NS_SUCCEEDED(rv) && isEqualExceptRef) {
           return;
         }
       }
     }
-#endif
+
     aValue.StartImageLoad(aDocument);
     if (aForTokenStream && aContext) {
       CSSVariableImageTable::Add(aContext, aProperty,
                                  aValue.GetImageStructValue());
     }
   }
   else if (aValue.GetUnit() == eCSSUnit_Image) {
     // If we already have a request, see if this document needs to clone it.
@@ -695,22 +694,31 @@ nsCSSExpandedDataBlock::TransferFromBloc
   }
 
   // We can pass CSSEnabledState::eIgnore (here, and in ClearProperty
   // above) rather than a value corresponding to whether we're parsing
   // a UA style sheet or certified app because we assert in nsCSSProps::
   // AddRefTable that shorthand properties available in these contexts
   // also have all of their subproperties available in these contexts.
   bool changed = false;
-  CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPropID, aEnabledState) {
-    changed |= DoTransferFromBlock(aFromBlock, *p,
+  if (!nsCSSProps::IsEnabled(eCSSProperty_mask_image) &&
+      aPropID == eCSSProperty_mask) {
+    changed |= DoTransferFromBlock(aFromBlock, eCSSProperty_mask_image,
                                    aIsImportant, aOverrideImportant,
                                    aMustCallValueAppended, aDeclaration,
                                    aSheetDocument);
+  } else {
+    CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPropID, aEnabledState) {
+      changed |= DoTransferFromBlock(aFromBlock, *p,
+                                     aIsImportant, aOverrideImportant,
+                                     aMustCallValueAppended, aDeclaration,
+                                     aSheetDocument);
+    }
   }
+
   return changed;
 }
 
 bool
 nsCSSExpandedDataBlock::DoTransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
                                             nsCSSPropertyID aPropID,
                                             bool aIsImportant,
                                             bool aOverrideImportant,
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -895,16 +895,17 @@ protected:
   bool ParseImageLayersItem(ImageLayersShorthandParseState& aState,
                             const nsCSSPropertyID aTable[]);
 
   bool ParseValueList(nsCSSPropertyID aPropID); // a single value prop-id
   bool ParseImageLayerRepeat(nsCSSPropertyID aPropID);
   bool ParseImageLayerRepeatValues(nsCSSValuePair& aValue);
   bool ParseImageLayerPosition(const nsCSSPropertyID aTable[]);
   bool ParseImageLayerPositionCoord(nsCSSPropertyID aPropID, bool aIsHorizontal);
+  bool ParseMaskAsLonghand();
 
   // 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
@@ -11807,30 +11808,31 @@ CSSParserImpl::ParsePropertyByFunction(n
   case eCSSProperty_stroke_dasharray:
     return ParseDasharray();
   case eCSSProperty_marker:
     return ParseMarker();
   case eCSSProperty_paint_order:
     return ParsePaintOrder();
   case eCSSProperty_scroll_snap_type:
     return ParseScrollSnapType();
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
   case eCSSProperty_mask:
+    if (!nsCSSProps::IsEnabled(eCSSProperty_mask_image)) {
+      return ParseMaskAsLonghand();
+    }
     return ParseImageLayers(nsStyleImageLayers::kMaskLayerTable);
   case eCSSProperty_mask_repeat:
     return ParseImageLayerRepeat(eCSSProperty_mask_repeat);
   case eCSSProperty_mask_position:
     return ParseImageLayerPosition(nsStyleImageLayers::kMaskLayerTable);
   case eCSSProperty_mask_position_x:
   case eCSSProperty_mask_position_y:
     return ParseImageLayerPositionCoord(aPropID,
                aPropID == eCSSProperty_mask_position_x);
   case eCSSProperty_mask_size:
     return ParseImageLayerSize(eCSSProperty_mask_size);
-#endif
   case eCSSProperty__webkit_text_stroke:
     return ParseWebkitTextStroke();
   case eCSSProperty_all:
     return ParseAll();
   default:
     MOZ_ASSERT(false, "should not be called");
     return false;
   }
@@ -12084,16 +12086,43 @@ BoxPositionMaskToCSSValue(int32_t aMask,
       val = NS_STYLE_IMAGELAYER_POSITION_BOTTOM;
     }
   }
 
   return nsCSSValue(val, eCSSUnit_Enumerated);
 }
 
 bool
+CSSParserImpl::ParseMaskAsLonghand()
+{
+  nsCSSValue image;
+
+  // Check first for inherit/initial/unset.
+  if (ParseSingleTokenVariant(image, VARIANT_INHERIT, nullptr)) {
+    AppendValue(eCSSProperty_mask_image, image);
+    return true;
+  }
+
+  nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
+  if (keyword != eCSSKeyword_none && mToken.mType != eCSSToken_URL) {
+    return false;
+  }
+
+  nsCSSValueList* imageList = image.SetListValue();
+  if (ParseSingleValueProperty(imageList->mValue, eCSSProperty_mask_image) !=
+        CSSParseResult::Ok) {
+    NS_NOTREACHED("should be able to parse");
+    return false;
+  }
+
+  AppendValue(eCSSProperty_mask_image, image);
+  return true;
+}
+
+bool
 CSSParserImpl::ParseImageLayers(const nsCSSPropertyID aTable[])
 {
   nsAutoParseCompoundProperty compound(this);
 
   // background-color can only be set once, so it's not a list.
   nsCSSValue color;
 
   // Check first for inherit/initial/unset.
@@ -17341,16 +17370,25 @@ CSSParserImpl::ParseAll()
 
   // It's unlikely we'll want to use 'all' from within a UA style sheet, so
   // instead of computing the correct EnabledState value we just expand out
   // to all content-visible properties.
   CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, eCSSProperty_all,
                                        CSSEnabledState::eForAllContent) {
     AppendValue(*p, value);
   }
+
+  // When pref layout.css.positioned-mask.enabled is false, mask-image property
+  // is used to keep the value of mask longhand property for backward
+  // compatibility. In such case, mask-image is in disabled state so that we
+  // need to take care of it particularly. 
+  if (!nsCSSProps::IsEnabled(eCSSProperty_mask_image)) {
+    AppendValue(eCSSProperty_mask_image, value);
+  }
+
   return true;
 }
 
 bool
 CSSParserImpl::ParseVariableDeclaration(CSSVariableDeclarations::Type* aType,
                                         nsString& aValue)
 {
   CSSVariableDeclarations::Type type;
--- a/layout/style/nsCSSPropAliasList.h
+++ b/layout/style/nsCSSPropAliasList.h
@@ -448,51 +448,49 @@ CSS_PROP_ALIAS(-webkit-align-content,
                WebkitAlignContent,
                WEBKIT_PREFIX_PREF)
 
 CSS_PROP_ALIAS(-webkit-user-select,
                user_select,
                WebkitUserSelect,
                WEBKIT_PREFIX_PREF)
 
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
 CSS_PROP_ALIAS(-webkit-mask,
                mask,
                WebkitMask,
-               WEBKIT_PREFIX_PREF)
+               "layout.css.positioned-mask.enabled")
 CSS_PROP_ALIAS(-webkit-mask-clip,
                mask_clip,
                WebkitMaskClip,
-               WEBKIT_PREFIX_PREF)
+               "layout.css.positioned-mask.enabled")
 CSS_PROP_ALIAS(-webkit-mask-composite,
                mask_composite,
                WebkitMaskComposite,
-               WEBKIT_PREFIX_PREF)
+               "layout.css.positioned-mask.enabled")
 CSS_PROP_ALIAS(-webkit-mask-image,
                mask_image,
                WebkitMaskImage,
-               WEBKIT_PREFIX_PREF)
+               "layout.css.positioned-mask.enabled")
 CSS_PROP_ALIAS(-webkit-mask-origin,
                mask_origin,
                WebkitMaskOrigin,
-               WEBKIT_PREFIX_PREF)
+               "layout.css.positioned-mask.enabled")
 CSS_PROP_ALIAS(-webkit-mask-position,
                mask_position,
                WebkitMaskPosition,
-               WEBKIT_PREFIX_PREF)
+               "layout.css.positioned-mask.enabled")
 CSS_PROP_ALIAS(-webkit-mask-position-x,
                mask_position_x,
                WebkitMaskPositionX,
-               WEBKIT_PREFIX_PREF)
+               "layout.css.positioned-mask.enabled")
 CSS_PROP_ALIAS(-webkit-mask-position-y,
                mask_position_y,
                WebkitMaskPositionY,
-               WEBKIT_PREFIX_PREF)
+               "layout.css.positioned-mask.enabled")
 CSS_PROP_ALIAS(-webkit-mask-repeat,
                mask_repeat,
                WebkitMaskRepeat,
-               WEBKIT_PREFIX_PREF)
+               "layout.css.positioned-mask.enabled")
 CSS_PROP_ALIAS(-webkit-mask-size,
                mask_size,
                WebkitMaskSize,
-               WEBKIT_PREFIX_PREF)
-#endif
+               "layout.css.positioned-mask.enabled")
 #undef WEBKIT_PREFIX_PREF
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -2640,148 +2640,134 @@ CSS_PROP_SVG(
     marker_start,
     MarkerStart,
     CSS_PROPERTY_PARSE_VALUE,
     "",
     VARIANT_HUO,
     nullptr,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
-#ifndef MOZ_ENABLE_MASK_AS_SHORTHAND
-CSS_PROP_SVGRESET(
-    mask,
-    mask,
-    Mask,
-    CSS_PROPERTY_PARSE_VALUE |
-      CSS_PROPERTY_CREATES_STACKING_CONTEXT,
-    "",
-    VARIANT_HUO,
-    nullptr,
-    CSS_PROP_NO_OFFSET,
-    eStyleAnimType_None)
-#else
 CSS_PROP_SHORTHAND(
     mask,
     mask,
     Mask,
     CSS_PROPERTY_PARSE_FUNCTION,
     "")
 CSS_PROP_SVGRESET(
     mask-clip,
     mask_clip,
     MaskClip,
     CSS_PROPERTY_PARSE_VALUE_LIST |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
-    "",
+    "layout.css.positioned-mask.enabled",
     VARIANT_KEYWORD, // used by list parsing
     kImageLayerOriginKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_SVGRESET(
     mask-composite,
     mask_composite,
     MaskComposite,
     CSS_PROPERTY_PARSE_VALUE_LIST |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
-    "",
+    "layout.css.positioned-mask.enabled",
     VARIANT_KEYWORD, // used by list parsing
     kImageLayerCompositeKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_SVGRESET(
     mask-image,
     mask_image,
     MaskImage,
     CSS_PROPERTY_PARSE_VALUE_LIST |
         CSS_PROPERTY_CREATES_STACKING_CONTEXT |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
         CSS_PROPERTY_START_IMAGE_LOADS,
-    "",
+    "layout.css.positioned-mask.enabled",
     VARIANT_IMAGE, // used by list parsing
     nullptr,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_SVGRESET(
     mask-mode,
     mask_mode,
     MaskMode,
     CSS_PROPERTY_PARSE_VALUE_LIST |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
-    "",
+    "layout.css.positioned-mask.enabled",
     VARIANT_KEYWORD, // used by list parsing
     kImageLayerModeKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_SVGRESET(
     mask-origin,
     mask_origin,
     MaskOrigin,
     CSS_PROPERTY_PARSE_VALUE_LIST |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
-    "",
+    "layout.css.positioned-mask.enabled",
     VARIANT_KEYWORD, // used by list parsing
     kImageLayerOriginKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_SHORTHAND(
     mask-position,
     mask_position,
     MaskPosition,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_UNITLESS_LENGTH_QUIRK,
-    "")
+    "layout.css.positioned-mask.enabled")
 CSS_PROP_SVGRESET(
     mask-position-x,
     mask_position_x,
     MaskPositionX,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
         CSS_PROPERTY_STORES_CALC,
-    "",
+    "layout.css.positioned-mask.enabled",
     0,
     kImageLayerPositionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
 CSS_PROP_SVGRESET(
     mask-position-y,
     mask_position_y,
     MaskPositionY,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
         CSS_PROPERTY_STORES_CALC,
-    "",
+    "layout.css.positioned-mask.enabled",
     0,
     kImageLayerPositionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
 CSS_PROP_SVGRESET(
     mask-repeat,
     mask_repeat,
     MaskRepeat,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
-    "",
+    "layout.css.positioned-mask.enabled",
     VARIANT_KEYWORD, // used by list parsing
     kImageLayerRepeatKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_SVGRESET(
     mask-size,
     mask_size,
     MaskSize,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
         CSS_PROPERTY_VALUE_NONNEGATIVE |
         CSS_PROPERTY_STORES_CALC,
-    "",
+    "layout.css.positioned-mask.enabled",
     0,
     kImageLayerSizeKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
-#endif // MOZ_ENABLE_MASK_AS_SHORTHAND
 CSS_PROP_SVGRESET(
     mask-type,
     mask_type,
     MaskType,
     CSS_PROPERTY_PARSE_VALUE,
     "",
     VARIANT_HK,
     kMaskTypeKTable,
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -2971,17 +2971,16 @@ static const nsCSSPropertyID gMozTransfo
   eCSSProperty_UNKNOWN
 };
 
 static const nsCSSPropertyID gScrollSnapTypeSubpropTable[] = {
   eCSSProperty_scroll_snap_type_x,
   eCSSProperty_scroll_snap_type_y,
   eCSSProperty_UNKNOWN
 };
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
 static const nsCSSPropertyID gMaskSubpropTable[] = {
   eCSSProperty_mask_image,
   eCSSProperty_mask_repeat,
   eCSSProperty_mask_position_x,
   eCSSProperty_mask_position_y,
   eCSSProperty_mask_clip,
   eCSSProperty_mask_origin,
   eCSSProperty_mask_size,
@@ -2989,17 +2988,17 @@ static const nsCSSPropertyID gMaskSubpro
   eCSSProperty_mask_mode,
   eCSSProperty_UNKNOWN
 };
 static const nsCSSPropertyID gMaskPositionSubpropTable[] = {
   eCSSProperty_mask_position_x,
   eCSSProperty_mask_position_y,
   eCSSProperty_UNKNOWN
 };
-#endif
+
 // FIXME: mask-border tables should be added when we implement
 // mask-border properties.
 
 const nsCSSPropertyID *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.
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -6151,17 +6151,16 @@ nsComputedDOMStyle::DoGetMask()
 
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
 
   SetValueToURLValue(firstLayer.mSourceURI, val);
 
   return val.forget();
 }
 
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetMaskClip()
 {
   return GetBackgroundList(&nsStyleImageLayers::Layer::mClip,
                            &nsStyleImageLayers::mClipCount,
                            StyleSVGReset()->mMask,
                            nsCSSProps::kImageLayerOriginKTable);
 }
@@ -6229,17 +6228,16 @@ nsComputedDOMStyle::DoGetMaskRepeat()
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetMaskSize()
 {
   const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
   return DoGetImageLayerSize(layers);
 }
-#endif
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetMaskType()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   val->SetIdent(
     nsCSSProps::ValueToKeywordEnum(StyleSVGReset()->mMaskType,
                                    nsCSSProps::kMaskTypeKTable));
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -302,28 +302,27 @@ private:
   already_AddRefed<CSSValue> DoGetBackgroundRepeat();
   already_AddRefed<CSSValue> DoGetBackgroundClip();
   already_AddRefed<CSSValue> DoGetBackgroundBlendMode();
   already_AddRefed<CSSValue> DoGetBackgroundOrigin();
   already_AddRefed<CSSValue> DoGetBackgroundSize();
 
   /* Mask properties */
   already_AddRefed<CSSValue> DoGetMask();
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
   already_AddRefed<CSSValue> DoGetMaskImage();
   already_AddRefed<CSSValue> DoGetMaskPosition();
   already_AddRefed<CSSValue> DoGetMaskPositionX();
   already_AddRefed<CSSValue> DoGetMaskPositionY();
   already_AddRefed<CSSValue> DoGetMaskRepeat();
   already_AddRefed<CSSValue> DoGetMaskClip();
   already_AddRefed<CSSValue> DoGetMaskOrigin();
   already_AddRefed<CSSValue> DoGetMaskSize();
   already_AddRefed<CSSValue> DoGetMaskMode();
   already_AddRefed<CSSValue> DoGetMaskComposite();
-#endif
+
   /* Padding properties */
   already_AddRefed<CSSValue> DoGetPaddingTop();
   already_AddRefed<CSSValue> DoGetPaddingBottom();
   already_AddRefed<CSSValue> DoGetPaddingLeft();
   already_AddRefed<CSSValue> DoGetPaddingRight();
 
   /* Table Properties */
   already_AddRefed<CSSValue> DoGetBorderCollapse();
--- a/layout/style/nsComputedDOMStylePropertyList.h
+++ b/layout/style/nsComputedDOMStylePropertyList.h
@@ -326,28 +326,26 @@ COMPUTED_STYLE_PROP(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)
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
 COMPUTED_STYLE_PROP(mask_clip,                     MaskClip)
 COMPUTED_STYLE_PROP(mask_composite,                MaskComposite)
 COMPUTED_STYLE_PROP(mask_image,                    MaskImage)
 COMPUTED_STYLE_PROP(mask_mode,                     MaskMode)
 COMPUTED_STYLE_PROP(mask_origin,                   MaskOrigin)
 COMPUTED_STYLE_PROP(mask_position,                 MaskPosition)
 COMPUTED_STYLE_PROP(mask_position_x,               MaskPositionX)
 COMPUTED_STYLE_PROP(mask_position_y,               MaskPositionY)
 COMPUTED_STYLE_PROP(mask_repeat,                   MaskRepeat)
 COMPUTED_STYLE_PROP(mask_size,                     MaskSize)
-#endif
 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)
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -9931,17 +9931,16 @@ nsRuleNode::ComputeSVGResetData(void* aS
   // mask-type: enum, inherit, initial
   SetValue(*aRuleData->ValueForMaskType(),
            svgReset->mMaskType,
            conditions,
            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
            parentSVGReset->mMaskType,
            NS_STYLE_MASK_TYPE_LUMINANCE);
 
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
   uint32_t maxItemCount = 1;
   bool rebuild = false;
 
   // mask-image: none | <url> | <image-list> | <element-reference>  | <gradient>
   nsStyleImage initialImage;
   SetImageLayerList(aContext, *aRuleData->ValueForMaskImage(),
                     svgReset->mMask.mLayers,
                     parentSVGReset->mMask.mLayers,
@@ -10041,31 +10040,16 @@ nsRuleNode::ComputeSVGResetData(void* aS
                     &nsStyleImageLayers::Layer::mComposite,
                     uint8_t(NS_STYLE_MASK_COMPOSITE_ADD),
                     parentSVGReset->mMask.mCompositeCount,
                     svgReset->mMask.mCompositeCount, maxItemCount, rebuild, conditions);
 
   if (rebuild) {
     FillAllBackgroundLists(svgReset->mMask, maxItemCount);
   }
-#else
-  // mask: none | <url>
-  const nsCSSValue* maskValue = aRuleData->ValueForMask();
-  if (eCSSUnit_URL == maskValue->GetUnit()) {
-    svgReset->mMask.mLayers[0].mSourceURI.SetValue(maskValue);
-  } else if (eCSSUnit_None == maskValue->GetUnit() ||
-             eCSSUnit_Initial == maskValue->GetUnit() ||
-             eCSSUnit_Unset == maskValue->GetUnit()) {
-    svgReset->mMask.mLayers[0].mSourceURI.SetNull();
-  } else if (eCSSUnit_Inherit == maskValue->GetUnit()) {
-    conditions.SetUncacheable();
-    svgReset->mMask.mLayers[0].mSourceURI =
-      parentSVGReset->mMask.mLayers[0].mSourceURI;
-  }
-#endif
 
   COMPUTE_END_RESET(SVGReset, svgReset)
 }
 
 const void*
 nsRuleNode::ComputeVariablesData(void* aStartStruct,
                                  const nsRuleData* aRuleData,
                                  nsStyleContext* aContext,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2475,32 +2475,30 @@ const nsCSSPropertyID nsStyleImageLayers
   eCSSProperty_background_clip,           // clip
   eCSSProperty_background_origin,         // origin
   eCSSProperty_background_size,           // size
   eCSSProperty_background_attachment,     // attachment
   eCSSProperty_UNKNOWN,                   // maskMode
   eCSSProperty_UNKNOWN                    // composite
 };
 
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
 const nsCSSPropertyID nsStyleImageLayers::kMaskLayerTable[] = {
   eCSSProperty_mask,                      // shorthand
   eCSSProperty_UNKNOWN,                   // color
   eCSSProperty_mask_image,                // image
   eCSSProperty_mask_repeat,               // repeat
   eCSSProperty_mask_position_x,           // positionX
   eCSSProperty_mask_position_y,           // positionY
   eCSSProperty_mask_clip,                 // clip
   eCSSProperty_mask_origin,               // origin
   eCSSProperty_mask_size,                 // size
   eCSSProperty_UNKNOWN,                   // attachment
   eCSSProperty_mask_mode,                 // maskMode
   eCSSProperty_mask_composite             // composite
 };
-#endif
 
 nsStyleImageLayers::nsStyleImageLayers(nsStyleImageLayers::LayerType aType)
   : mAttachmentCount(1)
   , mClipCount(1)
   , mOriginCount(1)
   , mRepeatCount(1)
   , mPositionXCount(1)
   , mPositionYCount(1)
--- a/layout/style/test/moz.build
+++ b/layout/style/test/moz.build
@@ -108,18 +108,16 @@ TEST_HARNESS_FILES.testing.mochitest.tes
     '/layout/reftests/svg/as-image/lime100x100.svg',
     '/layout/reftests/svg/as-image/svg-image-visited-1-helper.svg',
     '/layout/reftests/svg/as-image/svg-image-visited-2-helper.svg',
     '/layout/reftests/svg/pseudo-classes-02-ref.svg',
     '/layout/reftests/svg/pseudo-classes-02.svg',
 ]
 
 DEFINES['MOZILLA_INTERNAL_API'] = True
-if CONFIG['MOZ_ENABLE_MASK_AS_SHORTHAND']:
-   HOST_DEFINES['MOZ_ENABLE_MASK_AS_SHORTHAND'] = True
 
 if CONFIG['COMPILE_ENVIRONMENT']:
     GENERATED_FILES += ['css_properties.js']
     GENERATED_FILES['css_properties.js'].script = 'gen-css-properties.py'
     GENERATED_FILES['css_properties.js'].inputs = [
         'css_properties_like_longhand.js',
         '!host_ListCSSProperties%s' % CONFIG['HOST_BIN_SUFFIX'],
     ]
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -709,35 +709,27 @@ nsSVGIntegrationUtils::PaintMaskAndClipP
   nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
 
   bool isTrivialClip = clipPathFrame ? clipPathFrame->IsTrivial() : true;
 
   gfxMatrix cssPxToDevPxMatrix = GetCSSPxToDevPxMatrix(frame);
   const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
   nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
 
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
   // For a HTML doc:
   //   According to css-masking spec, always create a mask surface when we
   //   have any item in maskFrame even if all of those items are
   //   non-resolvable <mask-sources> or <images>, we still need to create a
   //   transparent black mask layer under this condition.
   // For a SVG doc:
   //   SVG 1.1 say that  if we fail to resolve a mask, we should draw the
   //   object unmasked.
   bool shouldGenerateMaskLayer = hasSVGLayout
                                  ? maskFrames.Length() == 1 && maskFrames[0]
                                  : maskFrames.Length() > 0;
-#else
-  // Since we do not support image mask so far, we should treat any
-  // unresolvable mask as no mask. Otherwise, any object with a valid image
-  // mask, e.g. url("xxx.png"), will become invisible just because we can not
-  // handle image mask correctly. (See bug 1294171)
-  bool shouldGenerateMaskLayer = maskFrames.Length() == 1 && maskFrames[0];
-#endif
 
   bool shouldGenerateClipMaskLayer = clipPathFrame && !isTrivialClip;
   bool shouldApplyClipPath = clipPathFrame && isTrivialClip;
   bool shouldApplyBasicShape = !clipPathFrame && svgReset->HasClipPath();
   MOZ_ASSERT_IF(shouldGenerateClipMaskLayer,
                 !shouldApplyClipPath && !shouldApplyBasicShape);
 
   nsPoint offsetToBoundingBox;
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2454,16 +2454,24 @@ pref("layout.css.dpi", -1);
 // automatically based on user settings for the platform (e.g., "UI scale factor"
 // on Mac). A positive value is used as-is. This effectively controls the size
 // of a CSS "px". This is only used for windows on the screen, not for printing.
 pref("layout.css.devPixelsPerPx", "-1.0");
 
 // Is support for CSS initial-letter property enabled?
 pref("layout.css.initial-letter.enabled", false);
 
+// Is support for CSS positioned mask enabled?
+// Enabled by default for nightly and aurora channels
+#ifdef RELEASE_OR_BETA
+pref("layout.css.positioned-mask.enabled", false);
+#else
+pref("layout.css.positioned-mask.enabled", true);
+#endif
+
 // Is support for mix-blend-mode enabled?
 pref("layout.css.mix-blend-mode.enabled", true);
 
 // Is support for isolation enabled?
 pref("layout.css.isolation.enabled", true);
 
 // Is support for CSS Filters enabled?
 pref("layout.css.filters.enabled", true);
--- a/old-configure.in
+++ b/old-configure.in
@@ -5911,32 +5911,16 @@ dnl ====================================
 if test -z "$GNU_CC" -a "$OS_ARCH" = "WINNT"; then
     PREPROCESS_OPTION="-P -Fi"
 else
     PREPROCESS_OPTION="-E -o "
 fi
 
 AC_SUBST(PREPROCESS_OPTION)
 
-dnl ========================================================
-dnl mask as shorthand property
-dnl ========================================================
-
-# The control structure code will be removed as soon as the feature is stable
-# Refer to bug 1281101 for more details.
-
-# Enable mask-as-shorthand property by default for nightly and aurora channels
-if test -z "$RELEASE_OR_BETA"; then
-  dnl mask as shorthand property enabled
-  MOZ_ENABLE_MASK_AS_SHORTHAND=1
-  AC_DEFINE(MOZ_ENABLE_MASK_AS_SHORTHAND)
-fi
-
-AC_SUBST(MOZ_ENABLE_MASK_AS_SHORTHAND)
-
 # Avoid using obsolete NSPR features
 AC_DEFINE(NO_NSPR_10_SUPPORT)
 
 # Don't build NSS libpkix
 NSS_DISABLE_LIBPKIX=1
 AC_SUBST(NSS_DISABLE_LIBPKIX)
 
 MOZ_CREATE_CONFIG_STATUS()