Bug 1416337 - Split FunctionSyntaxKind's Expression initializer into AssignmentExpression and PrimaryExpression flavors (even if for the moment only the latter is ever used or generated). r=arai
authorJeff Walden <jwalden@mit.edu>
Thu, 23 Nov 2017 12:52:24 -0500
changeset 438040 113bb57a4a4b49b74c3323a50764fb4e57e52c06
parent 438039 7a366209edc107847f5454b9f55914c1a252b878
child 438041 0bcec4cc47cfd03d2f142b9a05600664531f10c6
push id117
push userfmarier@mozilla.com
push dateTue, 28 Nov 2017 20:17:16 +0000
reviewersarai
bugs1416337
milestone59.0a1
Bug 1416337 - Split FunctionSyntaxKind's Expression initializer into AssignmentExpression and PrimaryExpression flavors (even if for the moment only the latter is ever used or generated). r=arai
js/src/frontend/ParseNode.h
js/src/frontend/Parser.cpp
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -1410,29 +1410,52 @@ AccessorTypeToJSOp(AccessorType atype)
         return JSOP_INITPROP_SETTER;
       default:
         MOZ_CRASH("unexpected accessor type");
     }
 }
 
 enum FunctionSyntaxKind
 {
-    Expression,
+    // A non-arrow function expression that is a PrimaryExpression and *also* a
+    // complete AssignmentExpression.  For example, in
+    //
+    //   var x = (function y() {});
+    //
+    // |y| is such a function expression.
+    AssignmentExpression,
+
+    // A non-arrow function expression that is a PrimaryExpression but *not* a
+    // complete AssignmentExpression.  For example, in
+    //
+    //   var x = (1 + function y() {});
+    //
+    // |y| is such a function expression.
+    PrimaryExpression,
+
+    // A named function appearing as a Statement.
     Statement,
+
     Arrow,
     Method,
     ClassConstructor,
     DerivedClassConstructor,
     Getter,
     GetterNoExpressionClosure,
     Setter,
     SetterNoExpressionClosure
 };
 
 static inline bool
+IsFunctionExpression(FunctionSyntaxKind kind)
+{
+    return kind == AssignmentExpression || kind == PrimaryExpression;
+}
+
+static inline bool
 IsConstructorKind(FunctionSyntaxKind kind)
 {
     return kind == ClassConstructor || kind == DerivedClassConstructor;
 }
 
 static inline bool
 IsGetterKind(FunctionSyntaxKind kind)
 {
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -2783,17 +2783,18 @@ ParserBase::newFunction(HandleAtom atom,
     RootedFunction fun(context);
 
     gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
     JSFunction::Flags flags;
 #ifdef DEBUG
     bool isGlobalSelfHostedBuiltin = false;
 #endif
     switch (kind) {
-      case Expression:
+      case AssignmentExpression:
+      case PrimaryExpression:
         flags = (generatorKind == GeneratorKind::NotGenerator &&
                  asyncKind == FunctionAsyncKind::SyncFunction
                  ? JSFunction::INTERPRETED_LAMBDA
                  : JSFunction::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC);
         break;
       case Arrow:
         flags = JSFunction::INTERPRETED_LAMBDA_ARROW;
         allocKind = gc::AllocKind::FUNCTION_EXTENDED;
@@ -3761,25 +3762,27 @@ Parser<ParseHandler, CharT>::functionFor
     {
         AutoAwaitIsKeyword<Parser> awaitIsKeyword(this, bodyAwaitHandling);
         body = functionBody(inHandling, bodyYieldHandling, kind, bodyType);
         if (!body)
             return false;
     }
 
     // Revalidate the function name when we transitioned to strict mode.
-    if ((kind == Statement || kind == Expression) && fun->explicitName()
-        && !inheritedStrict && pc->sc()->strict())
+    if ((kind == Statement || IsFunctionExpression(kind)) &&
+        fun->explicitName() &&
+        !inheritedStrict &&
+        pc->sc()->strict())
     {
         MOZ_ASSERT(pc->sc()->hasExplicitUseStrict(),
                    "strict mode should only change when a 'use strict' directive is present");
 
         PropertyName* propertyName = fun->explicitName()->asPropertyName();
         YieldHandling nameYieldHandling;
-        if (kind == Expression) {
+        if (IsFunctionExpression(kind)) {
             // Named lambda has binding inside it.
             nameYieldHandling = bodyYieldHandling;
         } else {
             // Otherwise YieldHandling cannot be checked at this point
             // because of different context.
             // It should already be checked before this point.
             nameYieldHandling = YieldIsName;
         }
@@ -3943,17 +3946,21 @@ Parser<ParseHandler, CharT>::functionExp
 
     Node pn = handler.newFunctionExpression(pos());
     if (!pn)
         return null();
 
     if (invoked)
         pn = handler.setLikelyIIFE(pn);
 
-    return functionDefinition(pn, toStringStart, InAllowed, yieldHandling, name, Expression,
+    // This is PrimaryExpression for now because the parser hasn't been changed
+    // to use AssignmentExpression yet.
+    FunctionSyntaxKind kind = PrimaryExpression;
+
+    return functionDefinition(pn, toStringStart, InAllowed, yieldHandling, name, kind,
                               generatorKind, asyncKind);
 }
 
 /*
  * Return true if this node, known to be an unparenthesized string literal,
  * could be the string of a directive in a Directive Prologue. Directive
  * strings never contain escape sequences or line continuations.
  * isEscapeFreeStringLiteral, below, checks whether the node itself could be