[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: Adam Klein <adamk@chromium.org> Reviewed-by: Caitlin Potter <caitp@igalia.com> Cr-Commit-Position: refs/heads/master@{#45116}
This commit is contained in:
parent
6545911f30
commit
c299fee21c
@ -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
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
*%(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
|
||||
|
@ -1,4 +1,4 @@
|
||||
*%(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
|
||||
|
8
test/message/async-arrow-invalid-rest-2.js
Normal file
8
test/message/async-arrow-invalid-rest-2.js
Normal file
@ -0,0 +1,8 @@
|
||||
// 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);
|
4
test/message/async-arrow-invalid-rest-2.out
Normal file
4
test/message/async-arrow-invalid-rest-2.out
Normal file
@ -0,0 +1,4 @@
|
||||
*%(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
|
8
test/message/async-arrow-invalid-rest.js
Normal file
8
test/message/async-arrow-invalid-rest.js
Normal file
@ -0,0 +1,8 @@
|
||||
// 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);
|
4
test/message/async-arrow-invalid-rest.out
Normal file
4
test/message/async-arrow-invalid-rest.out
Normal file
@ -0,0 +1,4 @@
|
||||
*%(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
|
7
test/message/async-arrow-param-after-rest.js
Normal file
7
test/message/async-arrow-param-after-rest.js
Normal file
@ -0,0 +1,7 @@
|
||||
// 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
|
5
test/message/async-arrow-param-after-rest.out
Normal file
5
test/message/async-arrow-param-after-rest.out
Normal file
@ -0,0 +1,5 @@
|
||||
*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter
|
||||
async (...x, y) => 10
|
||||
^
|
||||
SyntaxError: Rest parameter must be last formal parameter
|
||||
|
7
test/message/function-param-after-rest.js
Normal file
7
test/message/function-param-after-rest.js
Normal file
@ -0,0 +1,7 @@
|
||||
// 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) { }
|
5
test/message/function-param-after-rest.out
Normal file
5
test/message/function-param-after-rest.out
Normal file
@ -0,0 +1,5 @@
|
||||
*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter
|
||||
function f(...x, y) { }
|
||||
^
|
||||
SyntaxError: Rest parameter must be last formal parameter
|
||||
|
Loading…
Reference in New Issue
Block a user