Bug 807336 - Suppress CSS property parse errors inside failing @supports rules. r=dbaron
authorCameron McCormack <cam@mcc.id.au>
Tue, 06 Nov 2012 13:59:25 +1100
changeset 125974 a1864cbae86c1ef0d1368dd1838d2e940f4b6420
parent 125973 948ae77e36d6f12e65b46037636349e26ceeb38a
child 125975 46ab2a002a9bfd3d4617651065e51b96e014f35c
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs807336
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 807336 - Suppress CSS property parse errors inside failing @supports rules. r=dbaron
layout/style/nsCSSParser.cpp
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -228,16 +228,22 @@ public:
                                    nsIURI* aURL, // for error reporting
                                    uint32_t aLineNumber, // for error reporting
                                    InfallibleTArray<float>& aSelectorList);
 
 protected:
   class nsAutoParseCompoundProperty;
   friend class nsAutoParseCompoundProperty;
 
+  class nsAutoParseCompoundProperty;
+  friend class nsAutoParseCompoundProperty;
+
+  class nsAutoSuppressErrors;
+  friend class nsAutoSuppressErrors;
+
   void AppendRule(css::Rule* aRule);
   friend void AppendRuleToSheet(css::Rule*, void*); // calls AppendRule
 
   /**
    * This helper class automatically calls SetParsingCompoundProperty in its
    * constructor and takes care of resetting it to false in its destructor.
    */
   class nsAutoParseCompoundProperty {
@@ -253,16 +259,68 @@ protected:
       ~nsAutoParseCompoundProperty()
       {
         mParser->SetParsingCompoundProperty(false);
       }
     private:
       CSSParserImpl* mParser;
   };
 
+  /**
+   * This helper class conditionally sets mInFailingSupportsRule to
+   * true if aCondition = false, and resets it to its original value in its
+   * destructor.  If we are already somewhere within a failing @supports
+   * rule, passing in aCondition = true does not change mInFailingSupportsRule.
+   */
+  class nsAutoFailingSupportsRule {
+    public:
+      nsAutoFailingSupportsRule(CSSParserImpl* aParser,
+                                bool aCondition)
+        : mParser(aParser),
+          mOriginalValue(aParser->mInFailingSupportsRule)
+      {
+        if (!aCondition) {
+          mParser->mInFailingSupportsRule = true;
+        }
+      }
+
+      ~nsAutoFailingSupportsRule()
+      {
+        mParser->mInFailingSupportsRule = mOriginalValue;
+      }
+
+    private:
+      CSSParserImpl* mParser;
+      bool mOriginalValue;
+  };
+
+  /**
+   * Auto class to set aParser->mSuppressErrors to the specified value
+   * and restore it to its original value later.
+   */
+  class nsAutoSuppressErrors {
+    public:
+      nsAutoSuppressErrors(CSSParserImpl* aParser,
+                           bool aSuppressErrors)
+        : mParser(aParser),
+          mOriginalValue(aParser->mSuppressErrors)
+      {
+        mParser->mSuppressErrors = aSuppressErrors;
+      }
+
+      ~nsAutoSuppressErrors()
+      {
+        mParser->mSuppressErrors = mOriginalValue;
+      }
+
+    private:
+      CSSParserImpl* mParser;
+      bool mOriginalValue;
+  };
+
   // the caller must hold on to aString until parsing is done
   void InitScanner(nsCSSScanner& aScanner,
                    css::ErrorReporter& aReporter,
                    nsIURI* aSheetURI, nsIURI* aBaseURI,
                    nsIPrincipal* aSheetPrincipal);
   void ReleaseScanner(void);
   bool IsSVGMode() const {
     return mScanner->IsSVGMode();
@@ -684,16 +742,25 @@ protected:
   // True for parsing media lists for HTML attributes, where we have to
   // ignore CSS comments.
   bool mHTMLMediaMode : 1;
 
   // This flag is set when parsing a non-box shorthand; it's used to not apply
   // some quirks during shorthand parsing
   bool          mParsingCompoundProperty : 1;
 
+  // True if we are somewhere within a @supports rule whose condition is
+  // false.
+  bool mInFailingSupportsRule : 1;
+
+  // True if we will suppress all parse errors (except unexpected EOFs).
+  // This is used to prevent errors for declarations inside a failing
+  // @supports rule.
+  bool mSuppressErrors : 1;
+
   // Stack of rule groups; used for @media and such.
   InfallibleTArray<nsRefPtr<css::GroupRule> > mGroupStack;
 
   // During the parsing of a property (which may be a shorthand), the data
   // are stored in |mTempData|.  (It is needed to ensure that parser
   // errors cause the data to be ignored, and to ensure that a
   // non-'!important' declaration does not override an '!important'
   // one.)
@@ -714,26 +781,26 @@ static void AppendRuleToArray(css::Rule*
 
 static void AppendRuleToSheet(css::Rule* aRule, void* aParser)
 {
   CSSParserImpl* parser = (CSSParserImpl*) aParser;
   parser->AppendRule(aRule);
 }
 
 #define REPORT_UNEXPECTED(msg_) \
-  mReporter->ReportUnexpected(#msg_)
+  { if (!mSuppressErrors) mReporter->ReportUnexpected(#msg_); }
 
 #define REPORT_UNEXPECTED_P(msg_, param_) \
-  mReporter->ReportUnexpected(#msg_, param_)
+  { if (!mSuppressErrors) mReporter->ReportUnexpected(#msg_, param_); }
 
 #define REPORT_UNEXPECTED_TOKEN(msg_) \
-  mReporter->ReportUnexpected(#msg_, mToken)
+  { if (!mSuppressErrors) mReporter->ReportUnexpected(#msg_, mToken); }
 
 #define REPORT_UNEXPECTED_TOKEN_CHAR(msg_, ch_) \
-  mReporter->ReportUnexpected(#msg_, mToken, ch_)
+  { if (!mSuppressErrors) mReporter->ReportUnexpected(#msg_, mToken, ch_); }
 
 #define REPORT_UNEXPECTED_EOF(lf_) \
   mReporter->ReportUnexpectedEOF(#lf_)
 
 #define REPORT_UNEXPECTED_EOF_CHAR(ch_) \
   mReporter->ReportUnexpectedEOF(ch_)
 
 #define OUTPUT_ERROR() \
@@ -751,16 +818,18 @@ CSSParserImpl::CSSParserImpl()
     mNameSpaceMap(nullptr),
     mHavePushBack(false),
     mNavQuirkMode(false),
     mHashlessColorQuirk(false),
     mUnitlessLengthQuirk(false),
     mUnsafeRulesEnabled(false),
     mHTMLMediaMode(false),
     mParsingCompoundProperty(false),
+    mInFailingSupportsRule(false),
+    mSuppressErrors(false),
     mNextFree(nullptr)
 {
 }
 
 CSSParserImpl::~CSSParserImpl()
 {
   mData.AssertInitialState();
   mTempData.AssertInitialState();
@@ -2370,16 +2439,20 @@ CSSParserImpl::ParseSupportsRule(RuleApp
   // Remove the "{" that would follow the condition.
   if (condition.Length() != 0) {
     condition.Truncate(condition.Length() - 1);
   }
 
   // Remove spaces from the start and end of the recorded supports condition.
   condition.Trim(" ", true, true, false);
 
+  // Record whether we are in a failing @supports, so that property parse
+  // errors don't get reported.
+  nsAutoFailingSupportsRule failing(this, conditionMet);
+
   nsRefPtr<css::GroupRule> rule = new CSSSupportsRule(conditionMet, condition);
   return ParseGroupRule(rule, aAppendFunc, aProcessData);
 }
 
 // supports_condition
 //   : supports_condition_in_parens supports_condition_terms
 //   | supports_condition_negation
 //   ;
@@ -4304,16 +4377,20 @@ CSSParserImpl::ParseDeclaration(css::Dec
       REPORT_UNEXPECTED(PEDeclSkipped);
       OUTPUT_ERROR();
     }
     // Not a declaration...
     UngetToken();
     return false;
   }
 
+  // Don't report property parse errors if we're inside a failing @supports
+  // rule.
+  nsAutoSuppressErrors suppressErrors(this, mInFailingSupportsRule);
+
   // Map property name to its ID and then parse the property
   nsCSSProperty propID = nsCSSProps::LookupProperty(propertyName,
                                                     nsCSSProps::eEnabled);
   if (eCSSProperty_UNKNOWN == propID ||
      (aContext == eCSSContext_Page &&
       !nsCSSProps::PropHasFlags(propID, CSS_PROPERTY_APPLIES_TO_PAGE_RULE))) { // unknown property
     if (!NonMozillaVendorIdentifier(propertyName)) {
       REPORT_UNEXPECTED_P(PEUnknownProperty, propertyName);