Bug 774169, patch 3: Treat -moz-transform as a shorthand rather than an alias so the parsing function can know whether it is parsing a prefixed transform. r=bzbarsky
authorL. David Baron <dbaron@dbaron.org>
Tue, 18 Sep 2012 11:37:14 -0700
changeset 110996 110a5d25c8f2a24b5004afc17f5f51b5a7699916
parent 110995 775fef3dc66b6461e32442e53ae1c9c7c0d206e9
child 110997 125d2728927e5731e7418b6d7a953b42243c70d9
push idunknown
push userunknown
push dateunknown
reviewersbzbarsky
bugs774169
milestone18.0a1
Bug 774169, patch 3: Treat -moz-transform as a shorthand rather than an alias so the parsing function can know whether it is parsing a prefixed transform. r=bzbarsky
layout/style/Declaration.cpp
layout/style/nsCSSParser.cpp
layout/style/nsCSSPropAliasList.h
layout/style/nsCSSPropList.h
layout/style/nsCSSProps.cpp
layout/style/nsCSSProps.h
layout/style/nsComputedDOMStyle.cpp
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -813,16 +813,25 @@ Declaration::GetValue(nsCSSProperty aPro
       AppendValueToString(subprops[0], aValue);
       aValue.Append(PRUnichar(' '));
       AppendValueToString(subprops[1], aValue);
       aValue.Append(PRUnichar(' '));
       AppendValueToString(subprops[2], aValue);
       break;
     }
 #endif // MOZ_FLEXBOX
+    case eCSSProperty__moz_transform: {
+      // shorthands that are just aliases with different parsing rules
+      const nsCSSProperty* subprops =
+        nsCSSProps::SubpropertyEntryFor(aProperty);
+      NS_ABORT_IF_FALSE(subprops[1] == eCSSProperty_UNKNOWN,
+                        "must have exactly one subproperty");
+      AppendValueToString(subprops[0], aValue);
+      break;
+    }
     default:
       NS_ABORT_IF_FALSE(false, "no other shorthands");
       break;
   }
 }
 
 bool
 Declaration::GetValueIsImportant(const nsAString& aProperty) const
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -504,17 +504,17 @@ protected:
   bool ParseFamily(nsCSSValue& aValue);
   bool ParseFontFeatureSettings(nsCSSValue& aValue);
   bool ParseFontSrc(nsCSSValue& aValue);
   bool ParseFontSrcFormat(InfallibleTArray<nsCSSValue>& values);
   bool ParseFontRanges(nsCSSValue& aValue);
   bool ParseListStyle();
   bool ParseMargin();
   bool ParseMarks(nsCSSValue& aValue);
-  bool ParseTransform();
+  bool ParseTransform(bool aIsPrefixed);
   bool ParseOutline();
   bool ParseOverflow();
   bool ParsePadding();
   bool ParseQuotes();
   bool ParseSize();
   bool ParseTextDecoration();
   bool ParseTextDecorationLine(nsCSSValue& aValue);
   bool ParseTextOverflow(nsCSSValue& aValue);
@@ -6104,17 +6104,19 @@ CSSParserImpl::ParsePropertyByFunction(n
                                        NS_BOXPROP_SOURCE_LOGICAL);
   case eCSSProperty_quotes:
     return ParseQuotes();
   case eCSSProperty_size:
     return ParseSize();
   case eCSSProperty_text_decoration:
     return ParseTextDecoration();
   case eCSSProperty_transform:
-    return ParseTransform();
+    return ParseTransform(false);
+  case eCSSProperty__moz_transform:
+    return ParseTransform(true);
   case eCSSProperty_transform_origin:
     return ParseTransformOrigin(false);
   case eCSSProperty_perspective_origin:
     return ParseTransformOrigin(true);
   case eCSSProperty_transition:
     return ParseTransition();
   case eCSSProperty_animation:
     return ParseAnimation();
@@ -8570,17 +8572,17 @@ CSSParserImpl::ParseSingleTransform(nsCS
   }
 
   return ParseFunction(mToken.mIdent, variantMask, minElems, maxElems, aValue);
 }
 
 /* Parses a transform property list by continuously reading in properties
  * and constructing a matrix from it.
  */
-bool CSSParserImpl::ParseTransform()
+bool CSSParserImpl::ParseTransform(bool aIsPrefixed)
 {
   nsCSSValue value;
   if (ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE, nullptr)) {
     // 'inherit', 'initial', and 'none' must be alone
     if (!ExpectEndProperty()) {
       return false;
     }
   } else {
--- a/layout/style/nsCSSPropAliasList.h
+++ b/layout/style/nsCSSPropAliasList.h
@@ -30,17 +30,16 @@
   than needing the CSS_PROP_DOMPROP_PREFIXED(prop) macro).
 
   -. 'pref' is the name of a pref that controls whether the property
   is enabled.  The property is enabled if 'pref' is an empty string,
   or if the boolean property whose name is 'pref' is set to true.
 
  ******/
 
-CSS_PROP_ALIAS(-moz-transform, transform, MozTransform, "")
 CSS_PROP_ALIAS(-moz-transform-origin, transform_origin, MozTransformOrigin, "")
 CSS_PROP_ALIAS(-moz-perspective-origin, perspective_origin, MozPerspectiveOrigin, "")
 CSS_PROP_ALIAS(-moz-perspective, perspective, MozPerspective, "")
 CSS_PROP_ALIAS(-moz-transform-style, transform_style, MozTransformStyle, "")
 CSS_PROP_ALIAS(-moz-backface-visibility, backface_visibility, MozBackfaceVisibility, "")
 CSS_PROP_ALIAS(-moz-border-image, border_image, MozBorderImage, "")
 CSS_PROP_ALIAS(-moz-transition, transition, MozTransition, "")
 CSS_PROP_ALIAS(-moz-transition-delay, transition_delay, MozTransitionDelay, "")
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -3353,16 +3353,26 @@ CSS_PROP_SVGRESET(
     VectorEffect,
     CSS_PROPERTY_PARSE_VALUE,
     "",
     VARIANT_HK,
     kVectorEffectKTable,
     offsetof(nsStyleSVGReset, mVectorEffect),
     eStyleAnimType_EnumU8)
 
+// The shorthands below are essentially aliases, but they require different
+// parsing rules, and are therefore implemented as shorthands.
+CSS_PROP_SHORTHAND(
+    -moz-transform,
+    _moz_transform,
+    MozTransform,
+    CSS_PROPERTY_PARSE_FUNCTION |
+        CSS_PROPERTY_IS_ALIAS,
+    "")
+
 #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL
 // We have a few properties that are in style structs but are not stored
 // in style sheets (or nsCSS* structs).  Some fields in these property
 // definitions are bogus (e.g., they work for nsRuleData* offsets but
 // not nsCSS* offsets).  Callers that care about these bogus fields can
 // define CSS_PROP_STUB_NOT_CSS to define a replacement for these
 // entries.
 #ifdef CSS_PROP_STUB_NOT_CSS
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -214,16 +214,21 @@ nsCSSProps::BuildShorthandsContainingTab
 #ifdef DEBUG_SHORTHANDS_CONTAINING
     printf("Considering shorthand property '%s'.\n",
            nsCSSProps::GetStringValue(shorthand).get());
 #endif
     PropertyAndCount &subpropCountsEntry =
       subpropCounts[shorthand - eCSSProperty_COUNT_no_shorthands];
     subpropCountsEntry.property = shorthand;
     subpropCountsEntry.count = 0;
+    if (nsCSSProps::PropHasFlags(shorthand, CSS_PROPERTY_IS_ALIAS)) {
+      // Don't put shorthands that are acting as aliases in the
+      // shorthands-containing lists.
+      continue;
+    }
     for (const nsCSSProperty* subprops = SubpropertyEntryFor(shorthand);
          *subprops != eCSSProperty_UNKNOWN;
          ++subprops) {
       NS_ABORT_IF_FALSE(0 < *subprops &&
                         *subprops < eCSSProperty_COUNT_no_shorthands,
                         "subproperty must be a longhand");
       ++occurrenceCounts[*subprops];
       ++subpropCountsEntry.count;
@@ -274,16 +279,22 @@ nsCSSProps::BuildShorthandsContainingTab
                            *shorthandAndCountEnd = ArrayEnd(subpropCounts);
        shorthandAndCount < shorthandAndCountEnd;
        ++shorthandAndCount) {
 #ifdef DEBUG_SHORTHANDS_CONTAINING
     printf("Entering %u subprops for '%s'.\n",
            shorthandAndCount->count,
            nsCSSProps::GetStringValue(shorthandAndCount->property).get());
 #endif
+    if (nsCSSProps::PropHasFlags(shorthandAndCount->property,
+                                 CSS_PROPERTY_IS_ALIAS)) {
+      // Don't put shorthands that are acting as aliases in the
+      // shorthands-containing lists.
+      continue;
+    }
     for (const nsCSSProperty* subprops =
            SubpropertyEntryFor(shorthandAndCount->property);
          *subprops != eCSSProperty_UNKNOWN;
          ++subprops) {
       *(--gShorthandsContainingTable[*subprops]) = shorthandAndCount->property;
     }
   }
 
@@ -302,16 +313,21 @@ nsCSSProps::BuildShorthandsContainingTab
   }
 #endif
 
 #ifdef DEBUG
   // Verify that all values that should be are present.
   for (nsCSSProperty shorthand = eCSSProperty_COUNT_no_shorthands;
        shorthand < eCSSProperty_COUNT;
        shorthand = nsCSSProperty(shorthand + 1)) {
+    if (nsCSSProps::PropHasFlags(shorthand, CSS_PROPERTY_IS_ALIAS)) {
+      // Don't put shorthands that are acting as aliases in the
+      // shorthands-containing lists.
+      continue;
+    }
     for (const nsCSSProperty* subprops = SubpropertyEntryFor(shorthand);
          *subprops != eCSSProperty_UNKNOWN;
          ++subprops) {
       uint32_t count = 0;
       for (const nsCSSProperty *shcont = ShorthandsContaining(*subprops);
            *shcont != eCSSProperty_UNKNOWN;
            ++shcont) {
         if (*shcont == shorthand)
@@ -2238,16 +2254,23 @@ static const nsCSSProperty gBorderImageS
 
 static const nsCSSProperty gMarkerSubpropTable[] = {
   eCSSProperty_marker_start,
   eCSSProperty_marker_mid,
   eCSSProperty_marker_end,
   eCSSProperty_UNKNOWN
 };
 
+// Subproperty tables for shorthands that are just aliases with
+// different parsing rules.
+static const nsCSSProperty gMozTransformSubpropTable[] = {
+  eCSSProperty_transform,
+  eCSSProperty_UNKNOWN
+};
+
 const nsCSSProperty *const
 nsCSSProps::kSubpropertyTable[eCSSProperty_COUNT - eCSSProperty_COUNT_no_shorthands] = {
 #define CSS_PROP_DOMPROP_PREFIXED(prop_) prop_
 // 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
@@ -93,16 +93,19 @@ MOZ_STATIC_ASSERT((CSS_PROPERTY_PARSE_PR
 #define CSS_PROPERTY_VALUE_AT_LEAST_ONE           (2<<13)
 
 // Does this property suppor the hashless hex color quirk in quirks mode?
 #define CSS_PROPERTY_HASHLESS_COLOR_QUIRK         (1<<15)
 
 // Does this property suppor the unitless length quirk in quirks mode?
 #define CSS_PROPERTY_UNITLESS_LENGTH_QUIRK        (1<<16)
 
+// Is this property (which must be a shorthand) really an alias?
+#define CSS_PROPERTY_IS_ALIAS                     (1<<17)
+
 /**
  * Types of animatable values.
  */
 enum nsStyleAnimType {
   // requires a custom implementation in
   // nsStyleAnimation::ExtractComputedValue
   eStyleAnimType_Custom,
 
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -400,16 +400,28 @@ nsComputedDOMStyle::GetPropertyCSSValue(
 
   nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocumentWeak);
   NS_ENSURE_TRUE(document, NS_ERROR_NOT_AVAILABLE);
   document->FlushPendingLinkUpdates();
 
   nsCSSProperty prop = nsCSSProps::LookupProperty(aPropertyName,
                                                   nsCSSProps::eEnabled);
 
+  // We don't (for now, anyway, though it may make sense to change it
+  // for all aliases, including those in nsCSSPropAliasList) want
+  // aliases to be enumerable (via GetLength and IndexedGetter), so
+  // handle them here rather than adding entries to
+  // GetQueryablePropertyMap.
+  if (nsCSSProps::PropHasFlags(prop, CSS_PROPERTY_IS_ALIAS)) {
+    const nsCSSProperty* subprops = nsCSSProps::SubpropertyEntryFor(prop);
+    NS_ABORT_IF_FALSE(subprops[1] == eCSSProperty_UNKNOWN,
+                      "must have list of length 1");
+    prop = subprops[0];
+  }
+
   const ComputedStyleMapEntry* propEntry = nullptr;
   {
     uint32_t length = 0;
     const ComputedStyleMapEntry* propMap = GetQueryablePropertyMap(&length);
     for (uint32_t i = 0; i < length; ++i) {
       if (prop == propMap[i].mProperty) {
         propEntry = &propMap[i];
         break;