diff --git a/src/messages.h b/src/messages.h index 15a3d67b7a..bfc78c738d 100644 --- a/src/messages.h +++ b/src/messages.h @@ -320,6 +320,8 @@ class CallSite { T(NoCatchOrFinally, "Missing catch or finally after try") \ T(NotIsvar, "builtin %%IS_VAR: not a variable") \ 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(SingleFunctionLiteral, "Single function literal required") \ T(SloppyLexical, \ diff --git a/src/parser.cc b/src/parser.cc index 7d7f6a6269..0f63d0bad5 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -3892,8 +3892,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( Expect(Token::RPAREN, CHECK_OK); int formals_end_position = scanner()->location().end_pos; - CheckArityRestrictions(num_parameters, arity_restriction, start_position, - formals_end_position, CHECK_OK); + CheckArityRestrictions(num_parameters, arity_restriction, has_rest, + start_position, formals_end_position, CHECK_OK); Expect(Token::LBRACE, CHECK_OK); diff --git a/src/preparser.cc b/src/preparser.cc index 75e5d2eda0..3dca827c92 100644 --- a/src/preparser.cc +++ b/src/preparser.cc @@ -1034,21 +1034,21 @@ PreParser::Expression PreParser::ParseFunctionLiteral( &factory); ExpressionClassifier formals_classifier; - bool is_rest = false; + bool has_rest = false; Expect(Token::LPAREN, CHECK_OK); int start_position = scanner()->location().beg_pos; function_scope->set_start_position(start_position); int num_parameters; { DuplicateFinder duplicate_finder(scanner()->unicode_cache()); - num_parameters = ParseFormalParameterList(&duplicate_finder, &is_rest, + num_parameters = ParseFormalParameterList(&duplicate_finder, &has_rest, &formals_classifier, CHECK_OK); } Expect(Token::RPAREN, CHECK_OK); int formals_end_position = scanner()->location().end_pos; - CheckArityRestrictions(num_parameters, arity_restriction, start_position, - formals_end_position, CHECK_OK); + CheckArityRestrictions(num_parameters, arity_restriction, has_rest, + start_position, formals_end_position, CHECK_OK); // See Parser::ParseFunctionLiteral for more information about lazy parsing // and lazy compilation. @@ -1068,7 +1068,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral( // function, since the function can declare itself strict. CheckFunctionName(language_mode(), kind, function_name, 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 = is_sloppy(language_mode()) && !strict_formal_parameters; ValidateFormalParameters(&formals_classifier, language_mode(), diff --git a/src/preparser.h b/src/preparser.h index 0163a33a81..9e8b63d21b 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -893,7 +893,7 @@ class ParserBase : public Traits { ExpressionClassifier* classifier, bool* ok); void CheckArityRestrictions( 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 // left-hand side of assignments). Although ruled out by ECMA as early errors, @@ -3657,7 +3657,7 @@ int ParserBase<Traits>::ParseFormalParameterList( template <class Traits> void ParserBase<Traits>::CheckArityRestrictions( 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) { case FunctionLiteral::GETTER_ARITY: if (param_count != 0) { @@ -3672,6 +3672,11 @@ void ParserBase<Traits>::CheckArityRestrictions( MessageTemplate::kBadSetterArity); *ok = false; } + if (has_rest) { + ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos), + MessageTemplate::kBadSetterRestParameter); + *ok = false; + } break; default: break; diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc index 2f96ec45f0..afe638d54e 100644 --- a/test/cctest/test-parsing.cc +++ b/test/cctest/test-parsing.cc @@ -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) { const char* strict_context_data[][2] = {{"'use strict';(function(", diff --git a/test/message/rest-param-class-setter-strict.js b/test/message/rest-param-class-setter-strict.js new file mode 100644 index 0000000000..d37edb6f3f --- /dev/null +++ b/test/message/rest-param-class-setter-strict.js @@ -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]; } +} diff --git a/test/message/rest-param-class-setter-strict.out b/test/message/rest-param-class-setter-strict.out new file mode 100644 index 0000000000..3296a0f2c8 --- /dev/null +++ b/test/message/rest-param-class-setter-strict.out @@ -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 diff --git a/test/message/rest-param-object-setter-sloppy.js b/test/message/rest-param-object-setter-sloppy.js new file mode 100644 index 0000000000..08c03298dc --- /dev/null +++ b/test/message/rest-param-object-setter-sloppy.js @@ -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]; } +}); diff --git a/test/message/rest-param-object-setter-sloppy.out b/test/message/rest-param-object-setter-sloppy.out new file mode 100644 index 0000000000..9400a2a9ce --- /dev/null +++ b/test/message/rest-param-object-setter-sloppy.out @@ -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 diff --git a/test/message/rest-param-object-setter-strict.js b/test/message/rest-param-object-setter-strict.js new file mode 100644 index 0000000000..e3a8f604e6 --- /dev/null +++ b/test/message/rest-param-object-setter-strict.js @@ -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]; } +}); diff --git a/test/message/rest-param-object-setter-strict.out b/test/message/rest-param-object-setter-strict.out new file mode 100644 index 0000000000..3296a0f2c8 --- /dev/null +++ b/test/message/rest-param-object-setter-strict.out @@ -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