Bug 1593415 - add test and refine reflection for nullish coalescing r=jorendorff
authoryulia <ystartsev@mozilla.com>
Wed, 13 Nov 2019 11:21:14 +0000
changeset 502241 b35b1431e4e2abcb9a4369c8fe2aa17a9321fdb1
parent 502240 c80cebff64aa82b4da9238b249a3b68dbb4a353d
child 502242 14a04a7ccab4071b62f36bffc60362a790a40618
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1593415
milestone72.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 1593415 - add test and refine reflection for nullish coalescing r=jorendorff Differential Revision: https://phabricator.services.mozilla.com/D52690
js/src/builtin/ReflectParse.cpp
js/src/tests/non262/reflect-parse/expression.js
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -631,17 +631,17 @@ class NodeBuilder {
 
   MOZ_MUST_USE bool assignmentExpression(AssignmentOperator op, HandleValue lhs,
                                          HandleValue rhs, TokenPos* pos,
                                          MutableHandleValue dst);
 
   MOZ_MUST_USE bool updateExpression(HandleValue expr, bool incr, bool prefix,
                                      TokenPos* pos, MutableHandleValue dst);
 
-  MOZ_MUST_USE bool logicalExpression(bool lor, HandleValue left,
+  MOZ_MUST_USE bool logicalExpression(ParseNodeKind pnk, HandleValue left,
                                       HandleValue right, TokenPos* pos,
                                       MutableHandleValue dst);
 
   MOZ_MUST_USE bool conditionalExpression(HandleValue test, HandleValue cons,
                                           HandleValue alt, TokenPos* pos,
                                           MutableHandleValue dst);
 
   MOZ_MUST_USE bool sequenceExpression(NodeVector& elts, TokenPos* pos,
@@ -1100,22 +1100,38 @@ bool NodeBuilder::updateExpression(Handl
   if (!cb.isNull()) {
     return callback(cb, expr, opName, prefixVal, pos, dst);
   }
 
   return newNode(AST_UPDATE_EXPR, pos, "operator", opName, "argument", expr,
                  "prefix", prefixVal, dst);
 }
 
-bool NodeBuilder::logicalExpression(bool lor, HandleValue left,
+bool NodeBuilder::logicalExpression(ParseNodeKind pnk, HandleValue left,
                                     HandleValue right, TokenPos* pos,
                                     MutableHandleValue dst) {
   RootedValue opName(cx);
-  if (!atomValue(lor ? "||" : "&&", &opName)) {
-    return false;
+  switch (pnk) {
+    case ParseNodeKind::OrExpr:
+      if (!atomValue("||", &opName)) {
+        return false;
+      }
+      break;
+    case ParseNodeKind::CoalesceExpr:
+      if (!atomValue("??", &opName)) {
+        return false;
+      }
+      break;
+    case ParseNodeKind::AndExpr:
+      if (!atomValue("&&", &opName)) {
+        return false;
+      }
+      break;
+    default:
+      MOZ_CRASH("Unexpected ParseNodeKind: Must be `Or`, `And`, or `Coalesce`");
   }
 
   RootedValue cb(cx, callbacks[AST_LOGICAL_EXPR]);
   if (!cb.isNull()) {
     return callback(cb, opName, left, right, pos, dst);
   }
 
   return newNode(AST_LOGICAL_EXPR, pos, "operator", opName, "left", left,
@@ -2563,35 +2579,36 @@ bool ASTSerializer::classField(ClassFiel
   }
   return propertyName(&classField->name(), &key) &&
          builder.classField(key, val, &classField->pn_pos, dst);
 }
 
 bool ASTSerializer::leftAssociate(ListNode* node, MutableHandleValue dst) {
   MOZ_ASSERT(!node->empty());
 
-  ParseNodeKind kind = node->getKind();
-  bool lor = kind == ParseNodeKind::OrExpr;
-  bool logop = lor || kind == ParseNodeKind::AndExpr;
+  ParseNodeKind pnk = node->getKind();
+  bool lor = pnk == ParseNodeKind::OrExpr;
+  bool coalesce = pnk == ParseNodeKind::CoalesceExpr;
+  bool logop = lor || coalesce || pnk == ParseNodeKind::AndExpr;
 
   ParseNode* head = node->head();
   RootedValue left(cx);
   if (!expression(head, &left)) {
     return false;
   }
   for (ParseNode* next : node->contentsFrom(head->pn_next)) {
     RootedValue right(cx);
     if (!expression(next, &right)) {
       return false;
     }
 
     TokenPos subpos(node->pn_pos.begin, next->pn_pos.end);
 
     if (logop) {
-      if (!builder.logicalExpression(lor, left, right, &subpos, &left)) {
+      if (!builder.logicalExpression(pnk, left, right, &subpos, &left)) {
         return false;
       }
     } else {
       BinaryOperator op = binop(node->getKind());
       LOCAL_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT);
 
       if (!builder.binaryExpression(op, left, right, &subpos, &left)) {
         return false;
--- a/js/src/tests/non262/reflect-parse/expression.js
+++ b/js/src/tests/non262/reflect-parse/expression.js
@@ -84,16 +84,17 @@ assertExpr("(x >>= y)", aExpr(">>=", ide
 assertExpr("(x >>>= y)", aExpr(">>>=", ident("x"), ident("y")));
 assertExpr("(x |= y)", aExpr("|=", ident("x"), ident("y")));
 assertExpr("(x ^= y)", aExpr("^=", ident("x"), ident("y")));
 assertExpr("(x &= y)", aExpr("&=", ident("x"), ident("y")));
 
 // Conditional expressions
 assertExpr("(x || y)", logExpr("||", ident("x"), ident("y")));
 assertExpr("(x && y)", logExpr("&&", ident("x"), ident("y")));
+assertExpr("(x ?? y)", logExpr("??", ident("x"), ident("y")));
 assertExpr("(w || x || y || z)", logExpr("||", logExpr("||", logExpr("||", ident("w"), ident("x")), ident("y")), ident("z")))
 assertExpr("(x ? y : z)", condExpr(ident("x"), ident("y"), ident("z")));
 
 // Sequence expressions
 assertExpr("(x,y)", seqExpr([ident("x"),ident("y")]))
 assertExpr("(x,y,z)", seqExpr([ident("x"),ident("y"),ident("z")]))
 assertExpr("(a,b,c,d,e,f,g)", seqExpr([ident("a"),ident("b"),ident("c"),ident("d"),ident("e"),ident("f"),ident("g")]));