Commit c299fee2 authored by Daniel Ehrenberg's avatar Daniel Ehrenberg Committed by Commit Bot

[parser] Fix parse errors for async arrow function edge cases

New test262 tests bring up a couple cases with async arrow functions
that V8 didn't seem to handle properly; this patch makes those cases
errors:
- async (...x,) => y -- Rest parameter must be last formal parameter
- async (...x = z) => y -- No default value for rest parameter
- async (...x, y) => z -- Rest parameter must be last formal parameter

Bug: v8:4483, v8:5051
Change-Id: I024d9ba0c854e8e5e75283df2ee53127b1be090d
Reviewed-on: https://chromium-review.googlesource.com/496057
Commit-Queue: Daniel Ehrenberg <littledan@chromium.org>
Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Reviewed-by: 's avatarCaitlin Potter <caitp@igalia.com>
Cr-Commit-Position: refs/heads/master@{#45116}
parent 6545911f
......@@ -608,6 +608,8 @@ class ErrorUtils : public AllStatic {
T(ArgStringTerminatesParametersEarly, \
"Arg string terminates parameters early") \
T(UnexpectedEndOfArgString, "Unexpected end of arg string") \
T(RestDefaultInitializer, \
"Rest parameter may not have a default initializer") \
T(RuntimeWrongNumArgs, "Runtime function given wrong number of arguments") \
T(SuperNotCalled, \
"Must call super constructor in derived class before accessing 'this' or " \
......
......@@ -1972,6 +1972,11 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN, bool* ok) {
int ellipsis_pos = position();
int pattern_pos = peek_position();
ExpressionT pattern = ParsePrimaryExpression(CHECK_OK);
if (peek() == Token::ASSIGN) {
ReportMessage(MessageTemplate::kRestDefaultInitializer);
*ok = false;
return result;
}
ValidateBindingPattern(CHECK_OK);
right = factory()->NewSpread(pattern, ellipsis_pos, pattern_pos);
} else {
......@@ -2715,6 +2720,10 @@ typename ParserBase<Impl>::ExpressionListT ParserBase<Impl>::ParseArguments(
spread_arg.beg_pos = start_pos;
spread_arg.end_pos = peek_position();
}
if (argument->IsAssignment()) {
classifier()->RecordAsyncArrowFormalParametersError(
scanner()->location(), MessageTemplate::kRestDefaultInitializer);
}
argument = factory()->NewSpread(argument, start_pos, expr_pos);
}
result->Add(argument, zone_);
......@@ -2727,6 +2736,10 @@ typename ParserBase<Impl>::ExpressionListT ParserBase<Impl>::ParseArguments(
done = (peek() != Token::COMMA);
if (!done) {
Next();
if (argument->IsSpread()) {
classifier()->RecordAsyncArrowFormalParametersError(
scanner()->location(), MessageTemplate::kParamAfterRest);
}
if (allow_harmony_trailing_commas() && peek() == Token::RPAREN) {
// allow trailing comma
done = true;
......@@ -3657,7 +3670,12 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters,
}
ExpressionT initializer = impl()->EmptyExpression();
if (!is_rest && Check(Token::ASSIGN)) {
if (Check(Token::ASSIGN)) {
if (is_rest) {
ReportMessage(MessageTemplate::kRestDefaultInitializer);
*ok = false;
return;
}
ExpressionClassifier init_classifier(this);
initializer = ParseAssignmentExpression(true, CHECK_OK_CUSTOM(Void));
impl()->RewriteNonPattern(CHECK_OK_CUSTOM(Void));
......
......@@ -4262,6 +4262,7 @@ TEST(ErrorsArrowFunctions) {
"(c, a.b) => {}",
"(a['b'], c) => {}",
"(c, a['b']) => {}",
"(...a = b) => b",
// crbug.com/582626
"(...rest - a) => b",
......@@ -8989,6 +8990,10 @@ TEST(AsyncAwaitErrors) {
// v8:5148 assert that errors are still thrown for calls that may have been
// async functions
"async({ foo33 = 1 })",
"async(...a = b) => b",
"async(...a,) => b",
"async(...a, b) => b",
NULL
};
......
*%(basename)s:7: SyntaxError: Unexpected token =
*%(basename)s:7: SyntaxError: Rest parameter may not have a default initializer
var f = (a, ...x = 10) => x;
^
SyntaxError: Unexpected token =
^
SyntaxError: Rest parameter may not have a default initializer
*%(basename)s:7: SyntaxError: Unexpected token =
*%(basename)s:7: SyntaxError: Rest parameter may not have a default initializer
var f = (...x = 10) => x;
^
SyntaxError: Unexpected token =
^
SyntaxError: Rest parameter may not have a default initializer
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
//
var f = async (a, ...x = 10) => x;
f(1, 2, 3, 4, 5);
*%(basename)s:7: SyntaxError: Rest parameter may not have a default initializer
var f = async (a, ...x = 10) => x;
^^
SyntaxError: Rest parameter may not have a default initializer
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
//
var f = async (...x = 10) => x;
f(1, 2, 3, 4, 5);
*%(basename)s:7: SyntaxError: Rest parameter may not have a default initializer
var f = async (...x = 10) => x;
^^
SyntaxError: Rest parameter may not have a default initializer
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
//
async (...x, y) => 10
*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter
async (...x, y) => 10
^
SyntaxError: Rest parameter must be last formal parameter
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
//
function f(...x, y) { }
*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter
function f(...x, y) { }
^
SyntaxError: Rest parameter must be last formal parameter
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment