[parser] report SyntaxError if rest parameter used in Setter MethodDefinition

BUG=v8:4107, v8:2159
LOG=N
R=arv@chromium.org

Review URL: https://codereview.chromium.org/1141223002

Cr-Commit-Position: refs/heads/master@{#28454}
This commit is contained in:
caitpotter88 2015-05-18 08:52:57 -07:00 committed by Commit bot
parent 5bd4f9dd5a
commit e160e6debb
11 changed files with 81 additions and 9 deletions

View File

@ -320,6 +320,8 @@ class CallSite {
T(NoCatchOrFinally, "Missing catch or finally after try") \ T(NoCatchOrFinally, "Missing catch or finally after try") \
T(NotIsvar, "builtin %%IS_VAR: not a variable") \ T(NotIsvar, "builtin %%IS_VAR: not a variable") \
T(ParamAfterRest, "Rest parameter must be last formal parameter") \ T(ParamAfterRest, "Rest parameter must be last formal parameter") \
T(BadSetterRestParameter, \
"Setter function argument must not be a rest parameter") \
T(ParenthesisInArgString, "Function arg string contains parenthesis") \ T(ParenthesisInArgString, "Function arg string contains parenthesis") \
T(SingleFunctionLiteral, "Single function literal required") \ T(SingleFunctionLiteral, "Single function literal required") \
T(SloppyLexical, \ T(SloppyLexical, \

View File

@ -3892,8 +3892,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
Expect(Token::RPAREN, CHECK_OK); Expect(Token::RPAREN, CHECK_OK);
int formals_end_position = scanner()->location().end_pos; int formals_end_position = scanner()->location().end_pos;
CheckArityRestrictions(num_parameters, arity_restriction, start_position, CheckArityRestrictions(num_parameters, arity_restriction, has_rest,
formals_end_position, CHECK_OK); start_position, formals_end_position, CHECK_OK);
Expect(Token::LBRACE, CHECK_OK); Expect(Token::LBRACE, CHECK_OK);

View File

@ -1034,21 +1034,21 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
&factory); &factory);
ExpressionClassifier formals_classifier; ExpressionClassifier formals_classifier;
bool is_rest = false; bool has_rest = false;
Expect(Token::LPAREN, CHECK_OK); Expect(Token::LPAREN, CHECK_OK);
int start_position = scanner()->location().beg_pos; int start_position = scanner()->location().beg_pos;
function_scope->set_start_position(start_position); function_scope->set_start_position(start_position);
int num_parameters; int num_parameters;
{ {
DuplicateFinder duplicate_finder(scanner()->unicode_cache()); DuplicateFinder duplicate_finder(scanner()->unicode_cache());
num_parameters = ParseFormalParameterList(&duplicate_finder, &is_rest, num_parameters = ParseFormalParameterList(&duplicate_finder, &has_rest,
&formals_classifier, CHECK_OK); &formals_classifier, CHECK_OK);
} }
Expect(Token::RPAREN, CHECK_OK); Expect(Token::RPAREN, CHECK_OK);
int formals_end_position = scanner()->location().end_pos; int formals_end_position = scanner()->location().end_pos;
CheckArityRestrictions(num_parameters, arity_restriction, start_position, CheckArityRestrictions(num_parameters, arity_restriction, has_rest,
formals_end_position, CHECK_OK); start_position, formals_end_position, CHECK_OK);
// See Parser::ParseFunctionLiteral for more information about lazy parsing // See Parser::ParseFunctionLiteral for more information about lazy parsing
// and lazy compilation. // and lazy compilation.
@ -1068,7 +1068,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
// function, since the function can declare itself strict. // function, since the function can declare itself strict.
CheckFunctionName(language_mode(), kind, function_name, CheckFunctionName(language_mode(), kind, function_name,
name_is_strict_reserved, function_name_location, CHECK_OK); name_is_strict_reserved, function_name_location, CHECK_OK);
const bool strict_formal_parameters = is_rest || IsConciseMethod(kind); const bool strict_formal_parameters = has_rest || IsConciseMethod(kind);
const bool allow_duplicate_parameters = const bool allow_duplicate_parameters =
is_sloppy(language_mode()) && !strict_formal_parameters; is_sloppy(language_mode()) && !strict_formal_parameters;
ValidateFormalParameters(&formals_classifier, language_mode(), ValidateFormalParameters(&formals_classifier, language_mode(),

View File

@ -893,7 +893,7 @@ class ParserBase : public Traits {
ExpressionClassifier* classifier, bool* ok); ExpressionClassifier* classifier, bool* ok);
void CheckArityRestrictions( void CheckArityRestrictions(
int param_count, FunctionLiteral::ArityRestriction arity_restriction, int param_count, FunctionLiteral::ArityRestriction arity_restriction,
int formals_start_pos, int formals_end_pos, bool* ok); bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok);
// Checks if the expression is a valid reference expression (e.g., on the // Checks if the expression is a valid reference expression (e.g., on the
// left-hand side of assignments). Although ruled out by ECMA as early errors, // left-hand side of assignments). Although ruled out by ECMA as early errors,
@ -3657,7 +3657,7 @@ int ParserBase<Traits>::ParseFormalParameterList(
template <class Traits> template <class Traits>
void ParserBase<Traits>::CheckArityRestrictions( void ParserBase<Traits>::CheckArityRestrictions(
int param_count, FunctionLiteral::ArityRestriction arity_restriction, int param_count, FunctionLiteral::ArityRestriction arity_restriction,
int formals_start_pos, int formals_end_pos, bool* ok) { bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok) {
switch (arity_restriction) { switch (arity_restriction) {
case FunctionLiteral::GETTER_ARITY: case FunctionLiteral::GETTER_ARITY:
if (param_count != 0) { if (param_count != 0) {
@ -3672,6 +3672,11 @@ void ParserBase<Traits>::CheckArityRestrictions(
MessageTemplate::kBadSetterArity); MessageTemplate::kBadSetterArity);
*ok = false; *ok = false;
} }
if (has_rest) {
ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos),
MessageTemplate::kBadSetterRestParameter);
*ok = false;
}
break; break;
default: default:
break; break;

View File

@ -5109,6 +5109,24 @@ TEST(ParseRestParametersErrors) {
} }
TEST(RestParameterInSetterMethodError) {
const char* context_data[][2] = {
{"'use strict';({ set prop(", ") {} }).prop = 1;"},
{"'use strict';(class { static set prop(", ") {} }).prop = 1;"},
{"'use strict';(new (class { set prop(", ") {} })).prop = 1;"},
{"({ set prop(", ") {} }).prop = 1;"},
{"(class { static set prop(", ") {} }).prop = 1;"},
{"(new (class { set prop(", ") {} })).prop = 1;"},
{nullptr, nullptr}};
const char* data[] = {"...a", "...arguments", "...eval", nullptr};
static const ParserFlag always_flags[] = {
kAllowHarmonyRestParameters, kAllowHarmonyClasses, kAllowHarmonySloppy};
RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
arraysize(always_flags));
}
TEST(RestParametersEvalArguments) { TEST(RestParametersEvalArguments) {
const char* strict_context_data[][2] = const char* strict_context_data[][2] =
{{"'use strict';(function(", {{"'use strict';(function(",

View File

@ -0,0 +1,12 @@
// Copyright 2015 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.
//
// Flags: --harmony-rest-parameters --harmony-classes
'use strict';
var _bad = "setting this should fail!";
class C {
get bad() { return _bad; }
set bad(...args) { _bad = args[0]; }
}

View File

@ -0,0 +1,4 @@
*%(basename)s:11: SyntaxError: Setter function argument must not be a rest parameter
set bad(...args) { _bad = args[0]; }
^^^^^^^^^
SyntaxError: Setter function argument must not be a rest parameter

View File

@ -0,0 +1,11 @@
// Copyright 2015 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.
//
// Flags: --harmony-rest-parameters
var _bad = "this should fail!";
({
get bad() { return _bad; },
set bad(...args) { _bad = args[0]; }
});

View File

@ -0,0 +1,4 @@
*%(basename)s:10: SyntaxError: Setter function argument must not be a rest parameter
set bad(...args) { _bad = args[0]; }
^^^^^^^^^
SyntaxError: Setter function argument must not be a rest parameter

View File

@ -0,0 +1,12 @@
// Copyright 2015 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.
//
// Flags: --harmony-rest-parameters
'use strict';
var _bad = "this should fail!";
({
get bad() { return _bad; },
set bad(...args) { _bad = args[0]; }
});

View File

@ -0,0 +1,4 @@
*%(basename)s:11: SyntaxError: Setter function argument must not be a rest parameter
set bad(...args) { _bad = args[0]; }
^^^^^^^^^
SyntaxError: Setter function argument must not be a rest parameter