Backed out changeset b6d6ee031d40 (bug 611388)
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 31 Oct 2014 13:12:25 +0100
changeset 213395 2e29118fecea4e8c447b4d9ff7ac0e8e0c403c88
parent 213394 566edf2a7ad3974cf20144e88323afd1f5327532
child 213396 73fd8303deaba1bdc4ba099b9493c8540ea8e884
push id27748
push userryanvm@gmail.com
push dateFri, 31 Oct 2014 20:14:33 +0000
treeherdermozilla-central@12ac66e2c016 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs611388
milestone36.0a1
backs outb6d6ee031d401b351c7216a5e8256119edf0e1e7
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
Backed out changeset b6d6ee031d40 (bug 611388)
js/src/jsreflect.cpp
js/src/jsreflect.h
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -1728,17 +1728,17 @@ class ASTSerializer
     bool leftAssociate(ParseNode *pn, MutableHandleValue dst);
     bool functionArgs(ParseNode *pn, ParseNode *pnargs, ParseNode *pndestruct, ParseNode *pnbody,
                       NodeVector &args, NodeVector &defaults, MutableHandleValue rest);
 
     bool sourceElement(ParseNode *pn, MutableHandleValue dst);
 
     bool declaration(ParseNode *pn, MutableHandleValue dst);
     bool variableDeclaration(ParseNode *pn, bool let, MutableHandleValue dst);
-    bool variableDeclarator(ParseNode *pn, MutableHandleValue dst);
+    bool variableDeclarator(ParseNode *pn, VarDeclKind *pkind, MutableHandleValue dst);
     bool let(ParseNode *pn, bool expr, MutableHandleValue dst);
     bool importDeclaration(ParseNode *pn, MutableHandleValue dst);
     bool importSpecifier(ParseNode *pn, MutableHandleValue dst);
     bool exportDeclaration(ParseNode *pn, MutableHandleValue dst);
     bool exportSpecifier(ParseNode *pn, MutableHandleValue dst);
 
     bool optStatement(ParseNode *pn, MutableHandleValue dst) {
         if (!pn) {
@@ -1780,19 +1780,19 @@ class ASTSerializer
         }
         return identifier(atom, pos, dst);
     }
 
     bool identifier(HandleAtom atom, TokenPos *pos, MutableHandleValue dst);
     bool identifier(ParseNode *pn, MutableHandleValue dst);
     bool literal(ParseNode *pn, MutableHandleValue dst);
 
-    bool pattern(ParseNode *pn, MutableHandleValue dst);
-    bool arrayPattern(ParseNode *pn, MutableHandleValue dst);
-    bool objectPattern(ParseNode *pn, MutableHandleValue dst);
+    bool pattern(ParseNode *pn, VarDeclKind *pkind, MutableHandleValue dst);
+    bool arrayPattern(ParseNode *pn, VarDeclKind *pkind, MutableHandleValue dst);
+    bool objectPattern(ParseNode *pn, VarDeclKind *pkind, MutableHandleValue dst);
 
     bool function(ParseNode *pn, ASTType type, MutableHandleValue dst);
     bool functionArgsAndBody(ParseNode *pn, NodeVector &args, NodeVector &defaults,
                              MutableHandleValue body, MutableHandleValue rest);
     bool functionBody(ParseNode *pn, TokenPos *pos, MutableHandleValue dst);
 
     bool comprehensionBlock(ParseNode *pn, MutableHandleValue dst);
     bool comprehension(ParseNode *pn, MutableHandleValue dst);
@@ -2018,32 +2018,33 @@ ASTSerializer::declaration(ParseNode *pn
     }
 }
 
 bool
 ASTSerializer::variableDeclaration(ParseNode *pn, bool let, MutableHandleValue dst)
 {
     MOZ_ASSERT(let ? pn->isKind(PNK_LET) : (pn->isKind(PNK_VAR) || pn->isKind(PNK_CONST)));
 
-    VarDeclKind kind = let ? VARDECL_LET : pn->isKind(PNK_VAR) ? VARDECL_VAR : VARDECL_CONST;
+    /* Later updated to VARDECL_CONST if we find a PND_CONST declarator. */
+    VarDeclKind kind = let ? VARDECL_LET : VARDECL_VAR;
 
     NodeVector dtors(cx);
     if (!dtors.reserve(pn->pn_count))
         return false;
     for (ParseNode *next = pn->pn_head; next; next = next->pn_next) {
         RootedValue child(cx);
-        if (!variableDeclarator(next, &child))
+        if (!variableDeclarator(next, &kind, &child))
             return false;
         dtors.infallibleAppend(child);
     }
     return builder.variableDeclaration(dtors, kind, &pn->pn_pos, dst);
 }
 
 bool
-ASTSerializer::variableDeclarator(ParseNode *pn, MutableHandleValue dst)
+ASTSerializer::variableDeclarator(ParseNode *pn, VarDeclKind *pkind, MutableHandleValue dst)
 {
     ParseNode *pnleft;
     ParseNode *pnright;
 
     if (pn->isKind(PNK_NAME)) {
         pnleft = pn;
         pnright = pn->isUsed() ? nullptr : pn->pn_expr;
         MOZ_ASSERT_IF(pnright, pn->pn_pos.encloses(pnright->pn_pos));
@@ -2054,17 +2055,17 @@ ASTSerializer::variableDeclarator(ParseN
         MOZ_ASSERT(pn->pn_pos.encloses(pnright->pn_pos));
     } else {
         /* This happens for a destructuring declarator in a for-in/of loop. */
         pnleft = pn;
         pnright = nullptr;
     }
 
     RootedValue left(cx), right(cx);
-    return pattern(pnleft, &left) &&
+    return pattern(pnleft, pkind, &left) &&
            optExpression(pnright, &right) &&
            builder.variableDeclarator(left, right, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::let(ParseNode *pn, bool expr, MutableHandleValue dst)
 {
     MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
@@ -2075,20 +2076,25 @@ ASTSerializer::let(ParseNode *pn, bool e
 
     ParseNode *letBody = pn->pn_right;
     LOCAL_ASSERT(letBody->isKind(PNK_LEXICALSCOPE));
 
     NodeVector dtors(cx);
     if (!dtors.reserve(letHead->pn_count))
         return false;
 
+    VarDeclKind kind = VARDECL_LET_HEAD;
+
     for (ParseNode *next = letHead->pn_head; next; next = next->pn_next) {
         RootedValue child(cx);
-
-        if (!variableDeclarator(next, &child))
+        /*
+         * Unlike in |variableDeclaration|, this does not update |kind|; since let-heads do
+         * not contain const declarations, declarators should never have PND_CONST set.
+         */
+        if (!variableDeclarator(next, &kind, &child))
             return false;
         dtors.infallibleAppend(child);
     }
 
     RootedValue v(cx);
     return expr
            ? expression(letBody->pn_expr, &v) &&
              builder.letExpression(dtors, v, &pn->pn_pos, dst)
@@ -2249,17 +2255,17 @@ bool
 ASTSerializer::catchClause(ParseNode *pn, bool *isGuarded, MutableHandleValue dst)
 {
     MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid1->pn_pos));
     MOZ_ASSERT_IF(pn->pn_kid2, pn->pn_pos.encloses(pn->pn_kid2->pn_pos));
     MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid3->pn_pos));
 
     RootedValue var(cx), guard(cx), body(cx);
 
-    if (!pattern(pn->pn_kid1, &var) ||
+    if (!pattern(pn->pn_kid1, nullptr, &var) ||
         !optExpression(pn->pn_kid2, &guard)) {
         return false;
     }
 
     *isGuarded = !guard.isMagic(JS_SERIALIZE_NO_NODE);
 
     return statement(pn->pn_kid3, &body) &&
            builder.catchClause(var, guard, body, &pn->pn_pos, dst);
@@ -2437,27 +2443,27 @@ ASTSerializer::statement(ParseNode *pn, 
 
         RootedValue stmt(cx);
         if (!statement(pn->pn_right, &stmt))
             return false;
 
         if (head->isKind(PNK_FORIN)) {
             RootedValue var(cx);
             return (!head->pn_kid1
-                    ? pattern(head->pn_kid2, &var)
+                    ? pattern(head->pn_kid2, nullptr, &var)
                     : head->pn_kid1->isKind(PNK_LEXICALSCOPE)
                     ? variableDeclaration(head->pn_kid1->pn_expr, true, &var)
                     : variableDeclaration(head->pn_kid1, false, &var)) &&
                 forIn(pn, head, var, stmt, dst);
         }
 
         if (head->isKind(PNK_FOROF)) {
             RootedValue var(cx);
             return (!head->pn_kid1
-                    ? pattern(head->pn_kid2, &var)
+                    ? pattern(head->pn_kid2, nullptr, &var)
                     : head->pn_kid1->isKind(PNK_LEXICALSCOPE)
                     ? variableDeclaration(head->pn_kid1->pn_expr, true, &var)
                     : variableDeclaration(head->pn_kid1, false, &var)) &&
                 forOf(pn, head, var, stmt, dst);
         }
 
         RootedValue init(cx), test(cx), update(cx);
 
@@ -2580,17 +2586,17 @@ ASTSerializer::comprehensionBlock(ParseN
     ParseNode *in = pn->pn_left;
 
     LOCAL_ASSERT(in && (in->isKind(PNK_FORIN) || in->isKind(PNK_FOROF)));
 
     bool isForEach = in->isKind(PNK_FORIN) && (pn->pn_iflags & JSITER_FOREACH);
     bool isForOf = in->isKind(PNK_FOROF);
 
     RootedValue patt(cx), src(cx);
-    return pattern(in->pn_kid2, &patt) &&
+    return pattern(in->pn_kid2, nullptr, &patt) &&
            expression(in->pn_kid3, &src) &&
            builder.comprehensionBlock(patt, src, isForEach, isForOf, &in->pn_pos, dst);
 }
 
 bool
 ASTSerializer::comprehension(ParseNode *pn, MutableHandleValue dst)
 {
     // There are two array comprehension flavors.
@@ -2751,17 +2757,17 @@ ASTSerializer::expression(ParseNode *pn,
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
 
         AssignmentOperator op = aop(pn->getOp());
         LOCAL_ASSERT(op > AOP_ERR && op < AOP_LIMIT);
 
         RootedValue lhs(cx), rhs(cx);
-        return pattern(pn->pn_left, &lhs) &&
+        return pattern(pn->pn_left, nullptr, &lhs) &&
                expression(pn->pn_right, &rhs) &&
                builder.assignmentExpression(op, lhs, rhs, &pn->pn_pos, dst);
       }
 
       case PNK_ADD:
       case PNK_SUB:
       case PNK_STRICTEQ:
       case PNK_EQ:
@@ -3111,48 +3117,48 @@ ASTSerializer::literal(ParseNode *pn, Mu
       default:
         LOCAL_NOT_REACHED("unexpected literal type");
     }
 
     return builder.literal(val, &pn->pn_pos, dst);
 }
 
 bool
-ASTSerializer::arrayPattern(ParseNode *pn, MutableHandleValue dst)
+ASTSerializer::arrayPattern(ParseNode *pn, VarDeclKind *pkind, MutableHandleValue dst)
 {
     MOZ_ASSERT(pn->isKind(PNK_ARRAY));
 
     NodeVector elts(cx);
     if (!elts.reserve(pn->pn_count))
         return false;
 
     for (ParseNode *next = pn->pn_head; next; next = next->pn_next) {
         if (next->isKind(PNK_ELISION)) {
             elts.infallibleAppend(NullValue());
         } else if (next->isKind(PNK_SPREAD)) {
             RootedValue target(cx);
             RootedValue spread(cx);
-            if (!pattern(next->pn_kid, &target))
+            if (!pattern(next->pn_kid, pkind, &target))
                 return false;
             if(!builder.spreadExpression(target, &next->pn_pos, &spread))
                 return false;
             elts.infallibleAppend(spread);
         } else {
             RootedValue patt(cx);
-            if (!pattern(next, &patt))
+            if (!pattern(next, pkind, &patt))
                 return false;
             elts.infallibleAppend(patt);
         }
     }
 
     return builder.arrayPattern(elts, &pn->pn_pos, dst);
 }
 
 bool
-ASTSerializer::objectPattern(ParseNode *pn, MutableHandleValue dst)
+ASTSerializer::objectPattern(ParseNode *pn, VarDeclKind *pkind, MutableHandleValue dst)
 {
     MOZ_ASSERT(pn->isKind(PNK_OBJECT));
 
     NodeVector elts(cx);
     if (!elts.reserve(pn->pn_count))
         return false;
 
     for (ParseNode *propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
@@ -3167,39 +3173,44 @@ ASTSerializer::objectPattern(ParseNode *
             target = propdef->pn_kid;
         } else {
             if (!propertyName(propdef->pn_left, &key))
                 return false;
             target = propdef->pn_right;
         }
 
         RootedValue patt(cx), prop(cx);
-        if (!pattern(target, &patt) ||
+        if (!pattern(target, pkind, &patt) ||
             !builder.propertyPattern(key, patt, propdef->isKind(PNK_SHORTHAND), &propdef->pn_pos,
                                      &prop))
         {
             return false;
         }
 
         elts.infallibleAppend(prop);
     }
 
     return builder.objectPattern(elts, &pn->pn_pos, dst);
 }
 
 bool
-ASTSerializer::pattern(ParseNode *pn, MutableHandleValue dst)
+ASTSerializer::pattern(ParseNode *pn, VarDeclKind *pkind, MutableHandleValue dst)
 {
     JS_CHECK_RECURSION(cx, return false);
     switch (pn->getKind()) {
       case PNK_OBJECT:
-        return objectPattern(pn, dst);
+        return objectPattern(pn, pkind, dst);
 
       case PNK_ARRAY:
-        return arrayPattern(pn, dst);
+        return arrayPattern(pn, pkind, dst);
+
+      case PNK_NAME:
+        if (pkind && (pn->pn_dflags & PND_CONST))
+            *pkind = VARDECL_CONST;
+        /* FALL THROUGH */
 
       default:
         return expression(pn, dst);
     }
 }
 
 bool
 ASTSerializer::identifier(HandleAtom atom, TokenPos *pos, MutableHandleValue dst)
@@ -3332,17 +3343,17 @@ ASTSerializer::functionArgs(ParseNode *p
      * argsbody sequence (which ends with the body node), or 2) a
      * destructuring initialization at the beginning of the body. Loop
      * |arg| through the argsbody and |destruct| through the initial
      * destructuring assignments, stopping only when we've exhausted
      * both.
      */
     while ((arg && arg != pnbody) || destruct) {
         if (destruct && destruct->pn_right->frameSlot() == i) {
-            if (!pattern(destruct->pn_left, &node) || !args.append(node))
+            if (!pattern(destruct->pn_left, nullptr, &node) || !args.append(node))
                 return false;
             destruct = destruct->pn_next;
         } else if (arg && arg != pnbody) {
             /*
              * We don't check that arg->frameSlot() == i since we
              * can't call that method if the arg def has been turned
              * into a use, e.g.:
              *
--- a/js/src/jsreflect.h
+++ b/js/src/jsreflect.h
@@ -68,16 +68,17 @@ enum UnaryOperator {
     UNOP_LIMIT
 };
 
 enum VarDeclKind {
     VARDECL_ERR = -1,
     VARDECL_VAR = 0,
     VARDECL_CONST,
     VARDECL_LET,
+    VARDECL_LET_HEAD,
     VARDECL_LIMIT
 };
 
 enum PropKind {
     PROP_ERR = -1,
     PROP_INIT = 0,
     PROP_GETTER,
     PROP_SETTER,