Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix await identifiers in property names #249

Merged
merged 3 commits into from May 14, 2019
Merged
Changes from 2 commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -41,6 +41,7 @@
String UNEXPECTED_RESERVED_WORD = "Unexpected reserved word";
String UNEXPECTED_TEMPLATE = "Unexpected template";
String UNEXPECTED_EOS = "Unexpected end of input";
String UNEXPECTED_REST_PARAMETERS_INITIALIZATION = "Rest parameter may not have a default initializer";
String NEWLINE_AFTER_THROW = "Illegal newline after throw";
String NEWLINE_AFTER_ARROW_PARAMS = "Illegal newline after arrow parameters";
String UNTERMINATED_REGEXP = "Invalid regular expression: missing /";
@@ -551,6 +551,11 @@ protected FormalParameters parseParams() throws JsError {
while (!this.eof()) {
if (this.eat(TokenType.ELLIPSIS)) {
rest = parseBindingTarget();
if (this.match(TokenType.ASSIGN)) {

This comment has been minimized.

Copy link
@bakkot

bakkot May 3, 2019

Contributor

Whitespace

throw this.createError(ErrorMessages.UNEXPECTED_REST_PARAMETERS_INITIALIZATION);
} else if (this.match(TokenType.COMMA)) {
throw this.createUnexpected(this.lookahead);
}
break;
}
items.add(this.parseParam());
@@ -1589,7 +1594,11 @@ protected Expression parseNumericLiteral() throws JsError {
Maybe<Binding> rest = Maybe.empty();
Maybe<SpreadElementExpression> lastArgument = arguments.maybeLast();
if (lastArgument.isJust() && lastArgument.fromJust() instanceof SpreadElement) {
rest = Maybe.of(this.targetToBinding(this.transformDestructuring(((SpreadElement) lastArgument.fromJust()).expression)));
BindingBindingWithDefault binding = this.targetToBindingPossiblyWithDefault(this.transformDestructuringWithDefault(((SpreadElement) lastArgument.fromJust()).expression));
if (binding instanceof BindingWithDefault) {
throw this.createError(ErrorMessages.UNEXPECTED_REST_PARAMETERS_INITIALIZATION);
}
rest = Maybe.of((Binding) binding);
arguments = arguments.take(arguments.length - 1);
}
// evil java hack
@@ -2188,16 +2197,31 @@ protected BindingBindingWithDefault targetToBindingPossiblyWithDefault(@Nonnull
this.isBindingElement = this.isAssignmentTarget = false;
return Either.left(keyOrMethod.right().fromJust());
} else if (keyOrMethod.isLeft()) {
if (token.type == TokenType.AWAIT && this.firstAwaitLocation == null) {
this.firstAwaitLocation = this.getLocation();
}
PropertyName propName = keyOrMethod.left().fromJust();
if (propName instanceof StaticPropertyName) {
StaticPropertyName staticPropertyName = (StaticPropertyName) propName;
if (this.eat(TokenType.ASSIGN)) {
if (this.allowYieldExpression && token.type == TokenType.YIELD) {
throw this.createError(ErrorMessages.INVALID_TOKEN_CONTEXT, "yield");
}
if (this.allowAwaitExpression && token.type == TokenType.AWAIT) {
throw this.createError(ErrorMessages.INVALID_TOKEN_CONTEXT, "await");
}
Expression init = this.isolateCoverGrammar(this::parseAssignmentExpression).left().fromJust();
this.firstExprError = this.createErrorWithLocation(startLocation, ErrorMessages.ILLEGAL_PROPERTY);
AssignmentTargetPropertyIdentifier toReturn = new AssignmentTargetPropertyIdentifier(this.transformDestructuring(staticPropertyName), Maybe.of(init));
return Either.right(this.finishNode(startState, toReturn));
}
if (!this.match(TokenType.COLON)) {
if (this.allowYieldExpression && token.type == TokenType.YIELD) {
throw this.createError(ErrorMessages.INVALID_TOKEN_CONTEXT, "yield");
}
if (this.allowAwaitExpression && token.type == TokenType.AWAIT) {
throw this.createError(ErrorMessages.INVALID_TOKEN_CONTEXT, "await");
}
if (token.type != TokenType.IDENTIFIER && token.type != TokenType.YIELD && token.type != TokenType.LET && token.type != TokenType.ASYNC && token.type != TokenType.AWAIT) {
throw this.createUnexpected(token);
}
@@ -2299,8 +2323,7 @@ protected BindingBindingWithDefault targetToBindingPossiblyWithDefault(@Nonnull
if (isGenerator && this.match(TokenType.COLON)) {
throw this.createUnexpected(this.lookahead);
}

return Either.left(name);
return Either.left(name);
}

protected boolean lookaheadPropertyName() {
@@ -2354,7 +2377,7 @@ protected boolean lookaheadPropertyName() {
@Nonnull
protected String parseIdentifierName() throws JsError {
if (isIdentifierName(this.lookahead.type.klass)) {
return this.lex().toString();
return this.lex().toString();
} else {
throw this.createUnexpected(this.lookahead);
}
@@ -182,5 +182,7 @@ public void testObjectExpression() throws JsError {
ImmutableList.of(Maybe.of(new ObjectBinding(ImmutableList.of(new BindingPropertyIdentifier(
new BindingIdentifier("b"), Maybe.of(new LiteralNumericExpression(0.0))))))), Maybe.empty()),
new FunctionBody(ImmutableList.empty(), ImmutableList.empty())))));

testScriptFailure("(function* (){return {yield = 5} = {}})", 30, "\"yield\" may not be used as an identifier in this context");
}
}
@@ -30,6 +30,6 @@ public void testYieldGeneratorExpression() throws JsError {

testScriptFailure("function *a(){yield\n*a}", 2, 0, 20, "Unexpected token \"*\"");
testScriptFailure("function *a(){yield*}", 20, "Unexpected token \"}\"");
testScriptFailure("function *a(){({yield} = {})}", 23, "Unexpected token \"yield\"");
testScriptFailure("function *a(){({yield} = {})}", 21, "\"yield\" may not be used as an identifier in this context");
}
}
@@ -131,5 +131,9 @@ public void testAsyncFailure() {
testScriptFailure("async (a = (await) => {}) => {}", 12, "Async arrow parameters may not contain \"await\"");
testScriptFailure("async (a = aw\\u{61}it => {}) => {}", 11, "Async arrow parameters may not contain \"await\"");
testScriptFailure("async (a = (b = await (0)) => {}) => {}", 16, "Async arrow parameters may not contain \"await\"");
testScriptFailure("async ({await}) => 1", 13,"Async arrow parameters may not contain \"await\"");
This conversation was marked as resolved by bakkot

This comment has been minimized.

Copy link
@bakkot

bakkot May 3, 2019

Contributor

Should add similar tests for yield, since this PR is adding those cases.

This comment has been minimized.

Copy link
@bakkot

bakkot May 3, 2019

Contributor

I guess the only missing ones are function *a({yield}){} and function *a({yield = 0}){}.

testScriptFailure("async function x({await}) { return 1 }", 23,"Unexpected token \"}\"");
testScriptFailure("async function f() { return {await}; }", 34,"\"await\" may not be used as an identifier in this context");
testScriptFailure("async function f() { return {await = 0} = {}; }", 37,"\"await\" may not be used as an identifier in this context");
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.