Bug 1254335 - Remove invalid assertion; r=jorendorff, a=ritu
authorMorgan Phillips <winter2718@gmail.com>
Wed, 09 Mar 2016 01:57:38 -0800
changeset 323988 9799515f95fc182eded016c1cc37dcd3f9b3dea2
parent 323987 bde325bf8319b06851a45f875fd028c41100137a
child 323989 d994d0a380df51d31987b1317de5b6e8d7ecc0f8
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff, ritu
bugs1254335
milestone47.0a2
Bug 1254335 - Remove invalid assertion; r=jorendorff, a=ritu The underlying intent of the assertion was to guarantee that pending errors wouldn't be overwritten. This patch makes that intent more clear while addressing the fact that the original assertion was not necessarily true.
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -3941,27 +3941,32 @@ Parser<ParseHandler>::AutoPushStmtInfoPC
 template <typename ParseHandler>
 Parser<ParseHandler>::PossibleError::PossibleError(Parser<ParseHandler>& parser)
                                                    : parser_(parser)
 {
     state_ = ErrorState::None;
 }
 
 template <typename ParseHandler>
-void
+bool
 Parser<ParseHandler>::PossibleError::setPending(ParseReportKind kind, unsigned errorNumber,
                                                 bool strict)
 {
+    if (hasError())
+        return false;
+
     // If we report an error later, we'll do it from the position where we set
     // the state to pending.
     offset_      = parser_.pos().begin;
     reportKind_  = kind;
     strict_      = strict;
     errorNumber_ = errorNumber;
     state_       = ErrorState::Pending;
+
+    return true;
 }
 
 template <typename ParseHandler>
 void
 Parser<ParseHandler>::PossibleError::setResolved()
 {
     state_ = ErrorState::None;
 }
@@ -3973,19 +3978,18 @@ Parser<ParseHandler>::PossibleError::has
     return state_ == ErrorState::Pending;
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::PossibleError::checkForExprErrors()
 {
     bool err = hasError();
-    if (err) {
+    if (err)
         parser_.reportWithOffset(reportKind_, strict_, offset_, errorNumber_);
-    }
     return !err;
 }
 
 template <typename ParseHandler>
 void
 Parser<ParseHandler>::PossibleError::transferErrorTo(PossibleError* other)
 {
     if (other) {
@@ -7825,17 +7829,16 @@ Parser<ParseHandler>::checkAndMarkAsAssi
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandling,
                                  TripledotHandling tripledotHandling,
                                  PossibleError* possibleError,
                                  InvokedPrediction invoked)
 {
     JS_CHECK_RECURSION(context, return null());
-    MOZ_ASSERT(!possibleError->hasError());
 
     // It's very common at this point to have a "detectably simple" expression,
     // i.e. a name/number/string token followed by one of the following tokens
     // that obviously isn't part of an expression: , ; : ) ] }
     //
     // (In Parsemark this happens 81.4% of the time;  in code with large
     // numeric arrays, such as some Kraken benchmarks, it happens more often.)
     //
@@ -9307,18 +9310,23 @@ Parser<ParseHandler>::objectLiteral(Yiel
                 return null();
 
             if (!seenCoverInitializedName) {
                 seenCoverInitializedName = true;
                 // "shorthand default" or "CoverInitializedName" syntax is only
                 // valid in the case of destructuring. Here we set a pending error so
                 // that later in the parse, once we've determined whether or not we're
                 // destructuring, the error can be reported or ignored appropriately.
-                if (possibleError)
-                    possibleError->setPending(ParseError, JSMSG_BAD_PROP_ID, false);
+                if (possibleError &&
+                    !possibleError->setPending(ParseError, JSMSG_BAD_PROP_ID, false)) {
+
+                    // Report any previously pending error.
+                    possibleError->checkForExprErrors();
+                    return null();
+                }
             }
 
         } else {
             // FIXME: Implement ES6 function "name" property semantics
             // (bug 883377).
             RootedPropertyName funName(context);
             switch (propType) {
               case PropertyType::Getter:
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -457,18 +457,19 @@ class Parser : private JS::AutoGCRooter,
         unsigned errorNumber_;
         ParseReportKind reportKind_;
         Parser<ParseHandler>& parser_;
         bool strict_;
 
         public:
           explicit PossibleError(Parser<ParseHandler>& parser);
 
-          // Set a pending error.
-          void setPending(ParseReportKind kind, unsigned errorNumber, bool strict);
+          // Set a pending error. Only a single error may be set per instance.
+          // Returns true on success or false on failure.
+          bool setPending(ParseReportKind kind, unsigned errorNumber, bool strict);
 
           // Resolve any pending error.
           void setResolved();
 
           // Return true if an error is pending without reporting
           bool hasError();
 
           // If there is a pending error report it and return false, otherwise return
--- a/js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js
+++ b/js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js
@@ -14,16 +14,17 @@ const SYNTAX_ERROR_STMTS = [
     "({x=1, y={z={1}}})",
     "({x=1} = {y=1});",
     "({x: y={z=1}}={})",
     "({x=1}),",
     "({z=1}={}, {w=2}, {e=3})=>{};",
     "({z={x=1}})=>{};",
     "({x = ({y=1}) => y})",
     "(({x=1})) => x",
+    "({e=[]}==(;",
     // declarations
     "let o = {x=1};",
     "var j = {x=1};",
     "var j = {x={y=1}}={};",
     "const z = {x=1};",
     "const z = {x={y=1}}={};",
     "const {x=1};",
     "const {x={y=33}}={};",