auto name = is_simple || parameter.is_rest
? parameter.name : parser_->ast_value_factory()->empty_string();
auto mode = is_simple || parameter.is_rest ? VAR : TEMPORARY;
- Variable* var =
- scope->DeclareParameter(name, mode, parameter.is_rest, &is_duplicate);
+ bool is_optional = parameter.initializer != nullptr;
+ Variable* var = scope->DeclareParameter(
+ name, mode, is_optional, parameter.is_rest, &is_duplicate);
if (is_duplicate) {
classifier->RecordDuplicateFormalParameterError(
parser_->scanner()->location());
num_global_slots_ = 0;
num_modules_ = 0;
module_var_ = NULL;
+ arity_ = 0;
has_simple_parameters_ = true;
rest_parameter_ = NULL;
rest_index_ = -1;
}
-Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode,
- bool is_rest, bool* is_duplicate) {
+Variable* Scope::DeclareParameter(
+ const AstRawString* name, VariableMode mode,
+ bool is_optional, bool is_rest, bool* is_duplicate) {
DCHECK(!already_resolved());
DCHECK(is_function_scope());
+ DCHECK(!is_optional || !is_rest);
Variable* var;
if (mode == TEMPORARY) {
var = NewTemporary(name);
// TODO(wingo): Avoid O(n^2) check.
*is_duplicate = IsDeclaredParameter(name);
}
+ if (!is_optional && !is_rest && arity_ == params_.length()) {
+ ++arity_;
+ }
if (is_rest) {
DCHECK_NULL(rest_parameter_);
rest_parameter_ = var;
// Declare a parameter in this scope. When there are duplicated
// parameters the rightmost one 'wins'. However, the implementation
// expects all parameters to be declared and from left to right.
- Variable* DeclareParameter(const AstRawString* name, VariableMode mode,
- bool is_rest, bool* is_duplicate);
+ Variable* DeclareParameter(
+ const AstRawString* name, VariableMode mode,
+ bool is_optional, bool is_rest, bool* is_duplicate);
// Declare a local variable in this scope. If the variable has been
// declared before, the previously declared variable is returned.
return params_[index];
}
- // Returns the default function arity --- does not include rest parameters.
- int default_function_length() const {
- int count = params_.length();
- if (rest_index_ >= 0) {
- DCHECK(count > 0);
- DCHECK(is_function_scope());
- --count;
- }
- return count;
- }
+ // Returns the default function arity excluding default or rest parameters.
+ int default_function_length() const { return arity_; }
int num_parameters() const { return params_.length(); }
Variable* module_var_;
// Info about the parameter list of a function.
+ int arity_;
bool has_simple_parameters_;
Variable* rest_parameter_;
int rest_index_;
(function TestFunctionLength() {
- // TODO(rossberg): Fix arity.
- // assertEquals(0, (function(x = 1) {}).length);
- // assertEquals(0, (function(x = 1, ...a) {}).length);
- // assertEquals(1, (function(x, y = 1) {}).length);
- // assertEquals(1, (function(x, y = 1, ...a) {}).length);
- // assertEquals(2, (function(x, y, z = 1) {}).length);
- // assertEquals(2, (function(x, y, z = 1, ...a) {}).length);
- // assertEquals(1, (function(x, y = 1, z) {}).length);
- // assertEquals(1, (function(x, y = 1, z, ...a) {}).length);
- // assertEquals(1, (function(x, y = 1, z, v = 2) {}).length);
- // assertEquals(1, (function(x, y = 1, z, v = 2, ...a) {}).length);
+ assertEquals(0, (function(x = 1) {}).length);
+ assertEquals(0, (function(x = 1, ...a) {}).length);
+ assertEquals(1, (function(x, y = 1) {}).length);
+ assertEquals(1, (function(x, y = 1, ...a) {}).length);
+ assertEquals(2, (function(x, y, z = 1) {}).length);
+ assertEquals(2, (function(x, y, z = 1, ...a) {}).length);
+ assertEquals(1, (function(x, y = 1, z) {}).length);
+ assertEquals(1, (function(x, y = 1, z, ...a) {}).length);
+ assertEquals(1, (function(x, y = 1, z, v = 2) {}).length);
+ assertEquals(1, (function(x, y = 1, z, v = 2, ...a) {}).length);
})();
assertThrows("'use strict'; let x = {}; for (let [x, y] in {x});", ReferenceError);
assertThrows("'use strict'; let x = {}; for (let [y, x] in {x});", ReferenceError);
}());
+
+
+(function TestFunctionLength() {
+ assertEquals(1, (function({}) {}).length);
+ assertEquals(1, (function([]) {}).length);
+ assertEquals(1, (function({x}) {}).length);
+ assertEquals(1, (function({}, ...a) {}).length);
+ assertEquals(1, (function({x}, {y} = {}) {}).length);
+ assertEquals(1, (function({x}, {y} = {}, ...a) {}).length);
+ assertEquals(2, (function(x, {y}, {z} = {}) {}).length);
+ assertEquals(2, (function({x}, {}, {z} = {}, ...a) {}).length);
+ assertEquals(1, (function(x, {y} = {}, {z}) {}).length);
+ assertEquals(1, (function({x}, {y} = {}, {z}, ...a) {}).length);
+ assertEquals(1, (function(x, {y} = {}, {z}, {v} = {}) {}).length);
+ assertEquals(1, (function({x}, {y} = {}, {z}, {v} = {}, ...a) {}).length);
+})();