Skip to content

Commit

Permalink
Only recognize await expressions within async functions.
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=148824854
  • Loading branch information
brad4d committed Mar 2, 2017
1 parent 3a7464d commit ce5b2aa
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 27 deletions.
48 changes: 21 additions & 27 deletions src/com/google/javascript/jscomp/parsing/parser/Parser.java
Expand Up @@ -178,7 +178,7 @@ public class Parser {
* Indicates the type of function currently being parsed.
*/
private enum FunctionFlavor {
NORMAL, GENERATOR, ASYNC;
NORMAL, GENERATOR, ASYNCHRONOUS;
}

private final Scanner scanner;
Expand Down Expand Up @@ -919,7 +919,7 @@ private ParseTree parseClassMemberDeclaration(PartialClassElement partial) {
.setName(name)
.setStatic(partial.isStatic)
.setAccess(accessOnFunction);
parseFunctionTail(builder, isGenerator);
parseFunctionTail(builder, isGenerator ? FunctionFlavor.GENERATOR : FunctionFlavor.NORMAL);

function = builder.build(getTreeLocation(partial.start));
}
Expand Down Expand Up @@ -981,7 +981,7 @@ private ParseTree parseAsyncMethod(PartialClassElement partial) {
.setFunctionBody(new EmptyStatementTree(getTreeLocation(partial.start)));
eatPossibleImplicitSemiColon();
} else {
parseFunctionTail(builder, /* isGenerator */ false);
parseFunctionTail(builder, FunctionFlavor.ASYNCHRONOUS);
}

return builder.build(getTreeLocation(name.getStart()));
Expand All @@ -995,7 +995,7 @@ private ParseTree parseAsyncMethod(PartialClassElement partial) {
FunctionDeclarationTree.builder(FunctionDeclarationTree.Kind.EXPRESSION)
.setAsync(true)
.setStatic(partial.isStatic);
parseFunctionTail(builder, /* isGenerator */ false);
parseFunctionTail(builder, FunctionFlavor.ASYNCHRONOUS);

ParseTree function = builder.build(getTreeLocation(nameExpr.getStart()));
return new ComputedPropertyMethodTree(
Expand Down Expand Up @@ -1043,19 +1043,11 @@ private FunctionDeclarationTree parseAmbientFunctionDeclaration(
return builder.build(getTreeLocation(start));
}

private void parseFunctionTail(FunctionDeclarationTree.Builder builder) {
parseFunctionTail(builder, /* isGenerator */ false);
}

private void parseGeneratorFunctionTail(FunctionDeclarationTree.Builder builder) {
parseFunctionTail(builder, /* isGenerator */ true);
}

private void parseFunctionTail(FunctionDeclarationTree.Builder builder, boolean isGenerator) {
FunctionFlavor functionFlavor = isGenerator ? FunctionFlavor.GENERATOR : FunctionFlavor.NORMAL;
private void parseFunctionTail(
FunctionDeclarationTree.Builder builder, FunctionFlavor functionFlavor) {
functionContextStack.addLast(functionFlavor);
builder
.setGenerator(isGenerator)
.setGenerator(functionFlavor == FunctionFlavor.GENERATOR)
.setGenerics(maybeParseGenericTypes())
.setFormalParameterList(parseFormalParameterList(ParamContext.IMPLEMENTATION))
.setReturnType(maybeParseColonType())
Expand Down Expand Up @@ -1218,7 +1210,7 @@ private ParseTree parseFunctionDeclaration() {

FunctionDeclarationTree.Builder builder =
FunctionDeclarationTree.builder(FunctionDeclarationTree.Kind.DECLARATION).setName(eatId());
parseFunctionTail(builder, isGenerator);
parseFunctionTail(builder, isGenerator ? FunctionFlavor.GENERATOR : FunctionFlavor.NORMAL);
return builder.build(getTreeLocation(start));
}

Expand All @@ -1230,7 +1222,7 @@ private ParseTree parseFunctionExpression() {
FunctionDeclarationTree.Builder builder =
FunctionDeclarationTree.builder(FunctionDeclarationTree.Kind.EXPRESSION)
.setName(eatIdOpt());
parseFunctionTail(builder, isGenerator);
parseFunctionTail(builder, isGenerator ? FunctionFlavor.GENERATOR : FunctionFlavor.NORMAL);

return builder.build(getTreeLocation(start));
}
Expand All @@ -1251,7 +1243,7 @@ private ParseTree parseAsyncFunctionDeclaration() {
.setName(eatId())
.setAsync(true);

parseFunctionTail(builder);
parseFunctionTail(builder, FunctionFlavor.ASYNCHRONOUS);
return builder.build(getTreeLocation(start));
}

Expand All @@ -1271,7 +1263,7 @@ private ParseTree parseAsyncFunctionExpression() {
.setName(eatIdOpt())
.setAsync(true);

parseFunctionTail(builder);
parseFunctionTail(builder, FunctionFlavor.ASYNCHRONOUS);
return builder.build(getTreeLocation(start));
}

Expand Down Expand Up @@ -2487,7 +2479,7 @@ private ParseTree parsePropertyAssignment() {
} else {
FunctionDeclarationTree.Builder builder =
FunctionDeclarationTree.builder(FunctionDeclarationTree.Kind.EXPRESSION);
parseFunctionTail(builder);
parseFunctionTail(builder, FunctionFlavor.NORMAL);
ParseTree value = builder.build(getTreeLocation(start));
return new ComputedPropertyMethodTree(
getTreeLocation(start), null, name, value);
Expand All @@ -2513,7 +2505,7 @@ private ParseTree parsePropertyAssignmentGenerator() {
FunctionDeclarationTree.Builder builder =
FunctionDeclarationTree.builder(FunctionDeclarationTree.Kind.EXPRESSION);

parseGeneratorFunctionTail(builder);
parseFunctionTail(builder, FunctionFlavor.GENERATOR);
ParseTree value = builder.build(getTreeLocation(start));
return new ComputedPropertyMethodTree(getTreeLocation(start), null, name, value);
}
Expand Down Expand Up @@ -2882,7 +2874,7 @@ private ParseTree completeArrowFunctionParseAtArrow(
reportError("No newline allowed before '=>'");
}
eat(TokenType.ARROW);
ParseTree arrowFunctionBody = parseArrowFunctionBody(expressionIn);
ParseTree arrowFunctionBody = parseArrowFunctionBody(expressionIn, FunctionFlavor.NORMAL);

FunctionDeclarationTree.Builder builder =
FunctionDeclarationTree.builder(FunctionDeclarationTree.Kind.ARROW)
Expand Down Expand Up @@ -2959,7 +2951,7 @@ private ParseTree parseAsyncArrowFunction(Expression expressionIn) {
reportError("No newline allowed before '=>'");
}
eat(TokenType.ARROW);
ParseTree arrowFunctionBody = parseArrowFunctionBody(expressionIn);
ParseTree arrowFunctionBody = parseArrowFunctionBody(expressionIn, FunctionFlavor.ASYNCHRONOUS);

FunctionDeclarationTree.Builder builder =
FunctionDeclarationTree.builder(FunctionDeclarationTree.Kind.ARROW)
Expand All @@ -2969,8 +2961,8 @@ private ParseTree parseAsyncArrowFunction(Expression expressionIn) {
return builder.build(getTreeLocation(start));
}

private ParseTree parseArrowFunctionBody(Expression expressionIn) {
functionContextStack.addLast(FunctionFlavor.NORMAL);
private ParseTree parseArrowFunctionBody(Expression expressionIn, FunctionFlavor functionFlavor) {
functionContextStack.addLast(functionFlavor);
ParseTree arrowFunctionBody;
if (peek(TokenType.OPEN_CURLY)) {
arrowFunctionBody = parseFunctionBody();
Expand Down Expand Up @@ -3316,13 +3308,15 @@ private boolean peekUnaryOperator() {
private static final String AWAIT = "await";

private boolean peekAwaitExpression() {
// TODO(bradfordcsmith): This should be handled such that it's treated as special only within an
// async function.
return peekPredefinedString(AWAIT);
}

private ParseTree parseAwaitExpression() {
SourcePosition start = getTreeStartLocation();
if (functionContextStack.isEmpty()
|| functionContextStack.peekLast() != FunctionFlavor.ASYNCHRONOUS) {
reportError("'await' used in a non-async function context");
}
eatPredefinedString(AWAIT);
ParseTree expression = parseUnaryExpression();
return new AwaitExpressionTree(getTreeLocation(start), expression);
Expand Down
6 changes: 6 additions & 0 deletions test/com/google/javascript/jscomp/parsing/ParserTest.java
Expand Up @@ -2959,6 +2959,12 @@ public void testArrowInvalid1() {
parseError("f( (x,y)\n=>2)", "No newline allowed before '=>'");
}

public void testInvalidAwait() {
parseError("await 15;", "'await' used in a non-async function context");
parseError(
"function f() { return await 5; }", "'await' used in a non-async function context");
}

public void testAsyncFunction() {
String asyncFunctionExpressionSource = "f = async function() {};";
String asyncFunctionDeclarationSource = "async function f() {}";
Expand Down

0 comments on commit ce5b2aa

Please sign in to comment.