Bug 773296 - Part 5: Map variables on a Declaration to nsRuleData. r=dbaron
authorCameron McCormack <cam@mcc.id.au>
Thu, 12 Dec 2013 13:09:41 +1100
changeset 160055 8eae39ddcb7734f710ff2252a213f4d0dbe482aa
parent 160054 6d1b73fffa7708f5ba0289c3b878b5ce9ca75323
child 160056 65d7e8f8497875b8618f6e1b6c9af03aa1550cba
push idunknown
push userunknown
push dateunknown
reviewersdbaron
bugs773296
milestone29.0a1
Bug 773296 - Part 5: Map variables on a Declaration to nsRuleData. r=dbaron This adds a CSSVariableDeclarations object to nsRuleData and adds a MapRuleInfoInto function to CSSVariableDeclarations so the can copy variable declarations into a nsRuleData's object. We call that from Declaration::Map{Normal,Important}RuleInfoInto. We make HasImportantData return true if we have important variables but no important non-custom properties on a declaration, since that is used to determine whether we have a rule node for important declarations. This means MapImportantRuleInfoInto can no longer assume that mImportantData is non-null.
layout/style/CSSVariableDeclarations.cpp
layout/style/CSSVariableDeclarations.h
layout/style/Declaration.h
layout/style/nsRuleData.h
--- a/layout/style/CSSVariableDeclarations.cpp
+++ b/layout/style/CSSVariableDeclarations.cpp
@@ -1,15 +1,19 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+/* CSS Custom Property assignments for a Declaration at a given priority */
+
 #include "CSSVariableDeclarations.h"
 
+#include "nsRuleData.h"
+
 // These two special string values are used to represent specified values of
 // 'initial' and 'inherit'.  (Note that neither is a valid variable value.)
 #define INITIAL_VALUE "!"
 #define INHERIT_VALUE ";"
 
 namespace mozilla {
 
 CSSVariableDeclarations::CSSVariableDeclarations()
@@ -28,16 +32,20 @@ CSSVariableDeclarations::~CSSVariableDec
 {
   MOZ_COUNT_DTOR(CSSVariableDeclarations);
 }
 #endif
 
 CSSVariableDeclarations&
 CSSVariableDeclarations::operator=(const CSSVariableDeclarations& aOther)
 {
+  if (this == &aOther) {
+    return *this;
+  }
+
   mVariables.Clear();
   CopyVariablesFrom(aOther);
   return *this;
 }
 
 /* static */ PLDHashOperator
 CSSVariableDeclarations::EnumerateVariableForCopy(const nsAString& aName,
                                                   nsString aValue,
@@ -105,16 +113,45 @@ CSSVariableDeclarations::PutInherit(cons
 }
 
 void
 CSSVariableDeclarations::Remove(const nsAString& aName)
 {
   mVariables.Remove(aName);
 }
 
+/* static */ PLDHashOperator
+CSSVariableDeclarations::EnumerateVariableForMapRuleInfoInto(
+                                                         const nsAString& aName,
+                                                         nsString aValue,
+                                                         void* aData)
+{
+  nsDataHashtable<nsStringHashKey, nsString>* variables =
+    static_cast<nsDataHashtable<nsStringHashKey, nsString>*>(aData);
+  if (!variables->Contains(aName)) {
+    variables->Put(aName, aValue);
+  }
+  return PL_DHASH_NEXT;
+}
+
+void
+CSSVariableDeclarations::MapRuleInfoInto(nsRuleData* aRuleData)
+{
+  if (!(aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Variables))) {
+    return;
+  }
+
+  if (!aRuleData->mVariables) {
+    aRuleData->mVariables = new CSSVariableDeclarations(*this);
+  } else {
+    mVariables.EnumerateRead(EnumerateVariableForMapRuleInfoInto,
+                             aRuleData->mVariables.get());
+  }
+}
+
 static size_t
 SizeOfTableEntry(const nsAString& aKey,
                  const nsString& aValue,
                  MallocSizeOf aMallocSizeOf,
                  void* aUserArg)
 {
   size_t n = 0;
   n += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
--- a/layout/style/CSSVariableDeclarations.h
+++ b/layout/style/CSSVariableDeclarations.h
@@ -5,16 +5,18 @@
 
 /* CSS Custom Property assignments for a Declaration at a given priority */
 
 #ifndef mozilla_CSSVariableDeclarations_h
 #define mozilla_CSSVariableDeclarations_h
 
 #include "nsDataHashtable.h"
 
+class nsRuleData;
+
 namespace mozilla {
 
 class CSSVariableDeclarations
 {
 public:
   CSSVariableDeclarations();
   CSSVariableDeclarations(const CSSVariableDeclarations& aOther);
 #ifdef DEBUG
@@ -91,25 +93,35 @@ public:
    */
   void Remove(const nsAString& aName);
 
   /**
    * Returns the number of entries in this set of variable declarations.
    */
   uint32_t Count() const { return mVariables.Count(); }
 
+  /**
+   * Copies each variable value from this object into aRuleData, unless that
+   * variable already exists on aRuleData.
+   */
+  void MapRuleInfoInto(nsRuleData* aRuleData);
+
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 private:
   /**
    * Adds all the variable declarations from aOther into this object.
    */
   void CopyVariablesFrom(const CSSVariableDeclarations& aOther);
   static PLDHashOperator EnumerateVariableForCopy(const nsAString& aName,
                                                   nsString aValue,
                                                   void* aData);
+  static PLDHashOperator
+    EnumerateVariableForMapRuleInfoInto(const nsAString& aName,
+                                        nsString aValue,
+                                        void* aData);
 
   nsDataHashtable<nsStringHashKey, nsString> mVariables;
 };
 
 } // namespace mozilla
 
 #endif
--- a/layout/style/Declaration.h
+++ b/layout/style/Declaration.h
@@ -59,17 +59,19 @@ public:
   void ValueAppended(nsCSSProperty aProperty);
 
   void RemoveProperty(nsCSSProperty aProperty);
 
   bool HasProperty(nsCSSProperty aProperty) const;
 
   void GetValue(nsCSSProperty aProperty, nsAString& aValue) const;
 
-  bool HasImportantData() const { return mImportantData != nullptr; }
+  bool HasImportantData() const {
+    return mImportantData || mImportantVariables;
+  }
   bool GetValueIsImportant(nsCSSProperty aProperty) const;
   bool GetValueIsImportant(const nsAString& aProperty) const;
 
   /**
    * Adds a custom property declaration to this object.
    *
    * @param aName The variable name (i.e., without the "var-" prefix).
    * @param aType The type of value the variable has.
@@ -161,21 +163,30 @@ public:
 
   /**
    * Do what |nsIStyleRule::MapRuleInfoInto| needs to do for a style
    * rule using this declaration for storage.
    */
   void MapNormalRuleInfoInto(nsRuleData *aRuleData) const {
     NS_ABORT_IF_FALSE(mData, "called while expanded");
     mData->MapRuleInfoInto(aRuleData);
+    if (mVariables) {
+      mVariables->MapRuleInfoInto(aRuleData);
+    }
   }
   void MapImportantRuleInfoInto(nsRuleData *aRuleData) const {
     NS_ABORT_IF_FALSE(mData, "called while expanded");
-    NS_ABORT_IF_FALSE(mImportantData, "must have important data");
-    mImportantData->MapRuleInfoInto(aRuleData);
+    NS_ABORT_IF_FALSE(mImportantData || mImportantVariables,
+                      "must have important data or variables");
+    if (mImportantData) {
+      mImportantData->MapRuleInfoInto(aRuleData);
+    }
+    if (mImportantVariables) {
+      mImportantVariables->MapRuleInfoInto(aRuleData);
+    }
   }
 
   /**
    * Attempt to replace the value for |aProperty| stored in this
    * declaration with the matching value from |aFromBlock|.
    * This method may only be called on a mutable declaration.
    * It will fail (returning false) if |aProperty| is shorthand,
    * is not already in this declaration, or does not have the indicated
--- a/layout/style/nsRuleData.h
+++ b/layout/style/nsRuleData.h
@@ -6,16 +6,17 @@
 /*
  * temporary (expanded) representation of property-value pairs used to
  * hold data from matched rules during style data computation.
  */
 
 #ifndef nsRuleData_h_
 #define nsRuleData_h_
 
+#include "mozilla/CSSVariableDeclarations.h"
 #include "nsCSSProps.h"
 #include "nsCSSValue.h"
 #include "nsStyleStructFwd.h"
 
 class nsPresContext;
 class nsStyleContext;
 struct nsRuleData;
 
@@ -39,16 +40,18 @@ struct nsRuleData
   // nsCSSProps::PropertyIndexInStruct(prop).  The only place we gather
   // more than one style struct's data at a time is
   // nsRuleNode::HasAuthorSpecifiedRules; therefore some code that we
   // know is not called from HasAuthorSpecifiedRules assumes that the
   // mValueOffsets for the one struct in mSIDs is zero.
   nsCSSValue* const mValueStorage; // our user owns this array
   size_t mValueOffsets[nsStyleStructID_Length];
 
+  nsAutoPtr<mozilla::CSSVariableDeclarations> mVariables;
+
   nsRuleData(uint32_t aSIDs, nsCSSValue* aValueStorage,
              nsPresContext* aContext, nsStyleContext* aStyleContext);
 
 #ifdef DEBUG
   ~nsRuleData();
 #else
   ~nsRuleData() {}
 #endif