Bug 1185106 - Part 7.1: Support async method in Parser. r=efaust,jwalden,till draft
authorMariusz Kierski <mkierski@mozilla.com>
Sun, 28 Aug 2016 23:58:28 +0900
changeset 430935 6e45a99167d49c4529de2590e651c6e5ed279a36
parent 430934 604969949219386e333fcc3f8f5520ab6c47ad3a
child 430936 2a8aeb60861d4b187d34e31bb97bfc614a0182f3
push id33945
push userarai_a@mac.com
push dateFri, 28 Oct 2016 11:34:02 +0000
reviewersefaust, jwalden, till
bugs1185106
milestone52.0a1
Bug 1185106 - Part 7.1: Support async method in Parser. r=efaust,jwalden,till MozReview-Commit-ID: IqaY6IwRiHr
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -6398,16 +6398,17 @@ JSOpFromPropertyType(PropertyType propTy
       case PropertyType::GetterNoExpressionClosure:
         return JSOP_INITPROP_GETTER;
       case PropertyType::Setter:
       case PropertyType::SetterNoExpressionClosure:
         return JSOP_INITPROP_SETTER;
       case PropertyType::Normal:
       case PropertyType::Method:
       case PropertyType::GeneratorMethod:
+      case PropertyType::AsyncMethod:
       case PropertyType::Constructor:
       case PropertyType::DerivedConstructor:
         return JSOP_INITPROP;
       default:
         MOZ_CRASH("unexpected property type");
     }
 }
 
@@ -6419,32 +6420,44 @@ FunctionSyntaxKindFromPropertyType(Prope
         return Getter;
       case PropertyType::GetterNoExpressionClosure:
         return GetterNoExpressionClosure;
       case PropertyType::Setter:
         return Setter;
       case PropertyType::SetterNoExpressionClosure:
         return SetterNoExpressionClosure;
       case PropertyType::Method:
-        return Method;
       case PropertyType::GeneratorMethod:
+      case PropertyType::AsyncMethod:
         return Method;
       case PropertyType::Constructor:
         return ClassConstructor;
       case PropertyType::DerivedConstructor:
         return DerivedClassConstructor;
       default:
         MOZ_CRASH("unexpected property type");
     }
 }
 
 static GeneratorKind
 GeneratorKindFromPropertyType(PropertyType propType)
 {
-    return propType == PropertyType::GeneratorMethod ? StarGenerator : NotGenerator;
+    if (propType == PropertyType::GeneratorMethod)
+        return StarGenerator;
+    if (propType == PropertyType::AsyncMethod)
+        return StarGenerator;
+    return NotGenerator;
+}
+
+static FunctionAsyncKind
+AsyncKindFromPropertyType(PropertyType propType)
+{
+    if (propType == PropertyType::AsyncMethod)
+        return AsyncFunction;
+    return SyncFunction;
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling,
                                       ClassContext classContext,
                                       DefaultHandling defaultHandling)
 {
@@ -6548,16 +6561,17 @@ Parser<ParseHandler>::classDefinition(Yi
 
         PropertyType propType;
         Node propName = propertyName(yieldHandling, classMethods, &propType, &propAtom);
         if (!propName)
             return null();
 
         if (propType != PropertyType::Getter && propType != PropertyType::Setter &&
             propType != PropertyType::Method && propType != PropertyType::GeneratorMethod &&
+            propType != PropertyType::AsyncMethod &&
             propType != PropertyType::Constructor && propType != PropertyType::DerivedConstructor)
         {
             report(ParseError, false, null(), JSMSG_BAD_METHOD_DEF);
             return null();
         }
 
         if (propType == PropertyType::Getter)
             propType = PropertyType::GetterNoExpressionClosure;
@@ -8737,22 +8751,41 @@ Parser<ParseHandler>::propertyName(Yield
 {
     TokenKind ltok;
     if (!tokenStream.getToken(&ltok, TokenStream::KeywordIsName))
         return null();
 
     MOZ_ASSERT(ltok != TOK_RC, "caller should have handled TOK_RC");
 
     bool isGenerator = false;
+    bool isAsync = false;
     if (ltok == TOK_MUL) {
         isGenerator = true;
         if (!tokenStream.getToken(&ltok, TokenStream::KeywordIsName))
             return null();
     }
 
+    if (ltok == TOK_NAME && tokenStream.currentName() == context->names().async) {
+        TokenKind tt;
+        if (!tokenStream.getToken(&tt, TokenStream::KeywordIsName))
+            return null();
+        if (tt != TOK_LP && tt != TOK_COLON) {
+            isAsync = true;
+            ltok = tt;
+        } else {
+            tokenStream.ungetToken();
+            tokenStream.addModifierException(TokenStream::NoneIsKeywordIsName);
+        }
+    }
+
+    if (isAsync && isGenerator) {
+        report(ParseError, false, null(), JSMSG_ASYNC_GENERATOR);
+        return null();
+    }
+
     propAtom.set(nullptr);
     Node propName;
     switch (ltok) {
       case TOK_NUMBER:
         propAtom.set(DoubleToAtom(context, tokenStream.currentToken().number()));
         if (!propAtom.get())
             return null();
         propName = newNumber(tokenStream.currentToken());
@@ -8764,17 +8797,17 @@ Parser<ParseHandler>::propertyName(Yield
         propName = computedPropertyName(yieldHandling, propList);
         if (!propName)
             return null();
         break;
 
       case TOK_NAME: {
         propAtom.set(tokenStream.currentName());
         // Do not look for accessor syntax on generators
-        if (isGenerator ||
+        if (isGenerator || isAsync ||
             !(propAtom.get() == context->names().get ||
               propAtom.get() == context->names().set))
         {
             propName = handler.newObjectLiteralPropertyName(propAtom, pos());
             if (!propName)
                 return null();
             break;
         }
@@ -8883,17 +8916,22 @@ Parser<ParseHandler>::propertyName(Yield
         *propType = tt == TOK_ASSIGN ?
                           PropertyType::CoverInitializedName :
                           PropertyType::Shorthand;
         return propName;
     }
 
     if (tt == TOK_LP) {
         tokenStream.ungetToken();
-        *propType = isGenerator ? PropertyType::GeneratorMethod : PropertyType::Method;
+        if (isGenerator)
+            *propType = PropertyType::GeneratorMethod;
+        else if (isAsync)
+            *propType = PropertyType::AsyncMethod;
+        else
+            *propType = PropertyType::Method;
         return propName;
     }
 
     report(ParseError, false, null(), JSMSG_COLON_AFTER_ID);
     return null();
 }
 
 template <typename ParseHandler>
@@ -9115,18 +9153,19 @@ Parser<ParseHandler>::objectLiteral(Yiel
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::methodDefinition(PropertyType propType, HandleAtom funName)
 {
     FunctionSyntaxKind kind = FunctionSyntaxKindFromPropertyType(propType);
     GeneratorKind generatorKind = GeneratorKindFromPropertyType(propType);
-    YieldHandling yieldHandling = GetYieldHandling(generatorKind, SyncFunction);
-    return functionDefinition(InAllowed, yieldHandling, funName, kind, generatorKind, SyncFunction);
+    FunctionAsyncKind asyncKind = AsyncKindFromPropertyType(propType);
+    YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind);
+    return functionDefinition(InAllowed, yieldHandling, funName, kind, generatorKind, asyncKind);
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::tryNewTarget(Node &newTarget)
 {
     MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_NEW));
 
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -562,16 +562,17 @@ enum class PropertyType {
     Shorthand,
     CoverInitializedName,
     Getter,
     GetterNoExpressionClosure,
     Setter,
     SetterNoExpressionClosure,
     Method,
     GeneratorMethod,
+    AsyncMethod,
     Constructor,
     DerivedConstructor
 };
 
 // Specify a value for an ES6 grammar parametrization.  We have no enum for
 // [Return] because its behavior is exactly equivalent to checking whether
 // we're in a function box -- easier and simpler than passing an extra
 // parameter everywhere.