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. * Indicates the type of function currently being parsed.
*/ */
private enum FunctionFlavor { private enum FunctionFlavor {
NORMAL, GENERATOR, ASYNC; NORMAL, GENERATOR, ASYNCHRONOUS;
} }


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


function = builder.build(getTreeLocation(partial.start)); 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))); .setFunctionBody(new EmptyStatementTree(getTreeLocation(partial.start)));
eatPossibleImplicitSemiColon(); eatPossibleImplicitSemiColon();
} else { } else {
parseFunctionTail(builder, /* isGenerator */ false); parseFunctionTail(builder, FunctionFlavor.ASYNCHRONOUS);
} }


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


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


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

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;
functionContextStack.addLast(functionFlavor); functionContextStack.addLast(functionFlavor);
builder builder
.setGenerator(isGenerator) .setGenerator(functionFlavor == FunctionFlavor.GENERATOR)
.setGenerics(maybeParseGenericTypes()) .setGenerics(maybeParseGenericTypes())
.setFormalParameterList(parseFormalParameterList(ParamContext.IMPLEMENTATION)) .setFormalParameterList(parseFormalParameterList(ParamContext.IMPLEMENTATION))
.setReturnType(maybeParseColonType()) .setReturnType(maybeParseColonType())
Expand Down Expand Up @@ -1218,7 +1210,7 @@ private ParseTree parseFunctionDeclaration() {


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


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


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


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


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


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


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


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


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


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


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


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


private ParseTree parseAwaitExpression() { private ParseTree parseAwaitExpression() {
SourcePosition start = getTreeStartLocation(); SourcePosition start = getTreeStartLocation();
if (functionContextStack.isEmpty()
|| functionContextStack.peekLast() != FunctionFlavor.ASYNCHRONOUS) {
reportError("'await' used in a non-async function context");
}
eatPredefinedString(AWAIT); eatPredefinedString(AWAIT);
ParseTree expression = parseUnaryExpression(); ParseTree expression = parseUnaryExpression();
return new AwaitExpressionTree(getTreeLocation(start), expression); 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 '=>'"); 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() { public void testAsyncFunction() {
String asyncFunctionExpressionSource = "f = async function() {};"; String asyncFunctionExpressionSource = "f = async function() {};";
String asyncFunctionDeclarationSource = "async function f() {}"; String asyncFunctionDeclarationSource = "async function f() {}";
Expand Down

0 comments on commit ce5b2aa

Please sign in to comment.