Reviewers: adamk,
Description:
[es6] Correct length for functions with default parameters
[email protected]
BUG=v8:2160
LOG=N
Please review this at https://codereview.chromium.org/1311163002/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+43, -27 lines):
M src/parser.h
M src/scopes.h
M src/scopes.cc
M test/mjsunit/harmony/default-parameters.js
M test/mjsunit/harmony/destructuring.js
Index: src/parser.h
diff --git a/src/parser.h b/src/parser.h
index
355778b042d3368b3f340cc58f08a357bc7879a4..8713d1b331cd6b2d48771a11c1a8951cb964b0d2
100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -1341,8 +1341,9 @@ void ParserTraits::DeclareFormalParameter(
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);
+ Variable* var = scope->DeclareParameter(
+ name, mode, parameter.initializer != nullptr, parameter.is_rest,
+ &is_duplicate);
if (is_duplicate) {
classifier->RecordDuplicateFormalParameterError(
parser_->scanner()->location());
Index: src/scopes.cc
diff --git a/src/scopes.cc b/src/scopes.cc
index
9a6e3aae6da4d72b705970990826e3fd78308f90..8c99044e72b57a659ad49953331d04e129d62dac
100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -180,6 +180,7 @@ void Scope::SetDefaults(ScopeType scope_type, Scope*
outer_scope,
num_global_slots_ = 0;
num_modules_ = 0;
module_var_ = NULL;
+ arity_ = 0;
has_simple_parameters_ = true;
rest_parameter_ = NULL;
rest_index_ = -1;
@@ -465,10 +466,12 @@ Variable* Scope::Lookup(const AstRawString* name) {
}
-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);
@@ -479,6 +482,9 @@ Variable* Scope::DeclareParameter(const AstRawString*
name, VariableMode mode,
// 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;
Index: src/scopes.h
diff --git a/src/scopes.h b/src/scopes.h
index
4990fab994574a9fb9fbb27814ba93faf3ad5c86..28cc742eb25ac0c1a2a9247784e653aca5e50588
100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -128,8 +128,9 @@ class Scope: public ZoneObject {
// 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.
@@ -365,16 +366,8 @@ class Scope: public ZoneObject {
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(); }
@@ -632,6 +625,7 @@ class Scope: public ZoneObject {
Variable* module_var_;
// Info about the parameter list of a function.
+ int arity_;
bool has_simple_parameters_;
Variable* rest_parameter_;
int rest_index_;
Index: test/mjsunit/harmony/default-parameters.js
diff --git a/test/mjsunit/harmony/default-parameters.js
b/test/mjsunit/harmony/default-parameters.js
index
3be5916d9bf5553265889489f2b143b51cdc2928..0d87b0371217876779656f6a32568c065cecd365
100644
--- a/test/mjsunit/harmony/default-parameters.js
+++ b/test/mjsunit/harmony/default-parameters.js
@@ -418,15 +418,14 @@
(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);
})();
Index: test/mjsunit/harmony/destructuring.js
diff --git a/test/mjsunit/harmony/destructuring.js
b/test/mjsunit/harmony/destructuring.js
index
69e144b26fd2a190cc233ef70c49f6eb12f04234..84eeb893f0a08aeb9f3191a275952e21c48a9bba
100644
--- a/test/mjsunit/harmony/destructuring.js
+++ b/test/mjsunit/harmony/destructuring.js
@@ -953,3 +953,19 @@
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);
+})();
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.