Commit 4273f66e authored by rossberg's avatar rossberg Committed by Commit bot

[es6] Implement proper TDZ for parameters

Previously, examples like (({a = x}, x) => {})({}, 0) did not throw a ReferenceError like they should. This CL

- Splits up DeclareFormalParameters such that the formals can be recorded first and declared later.

- Declaration then takes the complete parameter list into account. If it is not simple, temporaries are introduced for all parameters.

- BuildParameterInitializationBlock desugars all parameters from non-simple lists into let-bindings.

- Refactored Pre/ParserFormalParameters, so that the arity information is no longer duplicated in Parser.

- Rest is currently handled specially, until rest-via-destructuring has landed.

R=adamk@chromium.org, littledan@chromium.org
BUG=v8:811
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#30025}
parent 41fad8db
...@@ -1203,6 +1203,11 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info, ...@@ -1203,6 +1203,11 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
// BindingIdentifier // BindingIdentifier
const bool is_rest = false; const bool is_rest = false;
ParseFormalParameter(is_rest, &formals, &formals_classifier, &ok); ParseFormalParameter(is_rest, &formals, &formals_classifier, &ok);
if (ok) {
DeclareFormalParameter(
formals.scope, formals.at(0), formals.is_simple,
&formals_classifier);
}
} }
} }
...@@ -2223,10 +2228,7 @@ Statement* Parser::ParseFunctionDeclaration( ...@@ -2223,10 +2228,7 @@ Statement* Parser::ParseFunctionDeclaration(
is_strong(language_mode()) is_strong(language_mode())
? CONST ? CONST
: (is_strict(language_mode()) || allow_harmony_sloppy()) && : (is_strict(language_mode()) || allow_harmony_sloppy()) &&
!(scope_->is_script_scope() || scope_->is_eval_scope() || !scope_->is_declaration_scope() ? LET : VAR;
scope_->is_function_scope())
? LET
: VAR;
VariableProxy* proxy = NewUnresolved(name, mode); VariableProxy* proxy = NewUnresolved(name, mode);
Declaration* declaration = Declaration* declaration =
factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos); factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
...@@ -3854,7 +3856,7 @@ void ParserTraits::ParseArrowFunctionFormalParameters( ...@@ -3854,7 +3856,7 @@ void ParserTraits::ParseArrowFunctionFormalParameters(
ParserFormalParameters* parameters, Expression* expr, ParserFormalParameters* parameters, Expression* expr,
const Scanner::Location& params_loc, const Scanner::Location& params_loc,
Scanner::Location* duplicate_loc, bool* ok) { Scanner::Location* duplicate_loc, bool* ok) {
if (parameters->arity >= Code::kMaxArguments) { if (parameters->Arity() >= Code::kMaxArguments) {
ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList); ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
*ok = false; *ok = false;
return; return;
...@@ -3908,11 +3910,26 @@ void ParserTraits::ParseArrowFunctionFormalParameters( ...@@ -3908,11 +3910,26 @@ void ParserTraits::ParseArrowFunctionFormalParameters(
parser_->scope_->RemoveUnresolved(expr->AsVariableProxy()); parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
} }
++parameters->arity; AddFormalParameter(parameters, expr, is_rest);
ExpressionClassifier classifier; }
DeclareFormalParameter(parameters, expr, is_rest, &classifier);
if (!duplicate_loc->IsValid()) {
*duplicate_loc = classifier.duplicate_formal_parameter_error().location; void ParserTraits::ParseArrowFunctionFormalParameterList(
ParserFormalParameters* parameters, Expression* expr,
const Scanner::Location& params_loc,
Scanner::Location* duplicate_loc, bool* ok) {
ParseArrowFunctionFormalParameters(parameters, expr, params_loc,
duplicate_loc, ok);
if (!*ok) return;
for (int i = 0; i < parameters->Arity(); ++i) {
auto parameter = parameters->at(i);
ExpressionClassifier classifier;
DeclareFormalParameter(
parameters->scope, parameter, parameters->is_simple, &classifier);
if (!duplicate_loc->IsValid()) {
*duplicate_loc = classifier.duplicate_formal_parameter_error().location;
}
} }
} }
...@@ -4032,8 +4049,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( ...@@ -4032,8 +4049,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
scope_->set_start_position(start_position); scope_->set_start_position(start_position);
ParserFormalParameters formals(scope); ParserFormalParameters formals(scope);
ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK);
arity = formals.arity; arity = formals.Arity();
DCHECK(arity == formals.params.length());
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;
...@@ -4299,7 +4315,8 @@ Block* Parser::BuildParameterInitializationBlock( ...@@ -4299,7 +4315,8 @@ Block* Parser::BuildParameterInitializationBlock(
factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
for (int i = 0; i < parameters.params.length(); ++i) { for (int i = 0; i < parameters.params.length(); ++i) {
auto parameter = parameters.params[i]; auto parameter = parameters.params[i];
if (parameter.pattern == nullptr) continue; // TODO(caitp,rossberg): Remove special handling for rest once desugared.
if (parameter.is_rest) break;
DeclarationDescriptor descriptor; DeclarationDescriptor descriptor;
descriptor.declaration_kind = DeclarationDescriptor::PARAMETER; descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
descriptor.parser = this; descriptor.parser = this;
......
...@@ -539,7 +539,7 @@ class Parser; ...@@ -539,7 +539,7 @@ class Parser;
class SingletonLogger; class SingletonLogger;
struct ParserFormalParameters : public PreParserFormalParameters { struct ParserFormalParameters : FormalParametersBase {
struct Parameter { struct Parameter {
Parameter(const AstRawString* name, Expression* pattern, bool is_rest) Parameter(const AstRawString* name, Expression* pattern, bool is_rest)
: name(name), pattern(pattern), is_rest(is_rest) {} : name(name), pattern(pattern), is_rest(is_rest) {}
...@@ -549,15 +549,11 @@ struct ParserFormalParameters : public PreParserFormalParameters { ...@@ -549,15 +549,11 @@ struct ParserFormalParameters : public PreParserFormalParameters {
}; };
explicit ParserFormalParameters(Scope* scope) explicit ParserFormalParameters(Scope* scope)
: PreParserFormalParameters(scope), params(4, scope->zone()) {} : FormalParametersBase(scope), params(4, scope->zone()) {}
ZoneList<Parameter> params; ZoneList<Parameter> params;
void AddParameter( int Arity() const { return params.length(); }
const AstRawString* name, Expression* pattern, bool is_rest) { const Parameter& at(int i) const { return params[i]; }
params.Add(Parameter(name, pattern, is_rest), scope->zone());
DCHECK_EQ(arity, params.length());
}
}; };
...@@ -782,13 +778,19 @@ class ParserTraits { ...@@ -782,13 +778,19 @@ class ParserTraits {
V8_INLINE Scope* NewScope(Scope* parent_scope, ScopeType scope_type, V8_INLINE Scope* NewScope(Scope* parent_scope, ScopeType scope_type,
FunctionKind kind = kNormalFunction); FunctionKind kind = kNormalFunction);
V8_INLINE void AddFormalParameter(
ParserFormalParameters* parameters, Expression* pattern, bool is_rest);
V8_INLINE void DeclareFormalParameter( V8_INLINE void DeclareFormalParameter(
ParserFormalParameters* parameters, Expression* pattern, bool is_rest, Scope* scope, const ParserFormalParameters::Parameter& parameter,
ExpressionClassifier* classifier); bool is_simple, ExpressionClassifier* classifier);
void ParseArrowFunctionFormalParameters( void ParseArrowFunctionFormalParameters(
ParserFormalParameters* parameters, Expression* params, ParserFormalParameters* parameters, Expression* params,
const Scanner::Location& params_loc, const Scanner::Location& params_loc,
Scanner::Location* duplicate_loc, bool* ok); Scanner::Location* duplicate_loc, bool* ok);
void ParseArrowFunctionFormalParameterList(
ParserFormalParameters* parameters, Expression* params,
const Scanner::Location& params_loc,
Scanner::Location* duplicate_loc, bool* ok);
void ReindexLiterals(const ParserFormalParameters& parameters); void ReindexLiterals(const ParserFormalParameters& parameters);
...@@ -1310,25 +1312,35 @@ Expression* ParserTraits::SpreadCallNew( ...@@ -1310,25 +1312,35 @@ Expression* ParserTraits::SpreadCallNew(
} }
void ParserTraits::DeclareFormalParameter( void ParserTraits::AddFormalParameter(
ParserFormalParameters* parameters, Expression* pattern, bool is_rest, ParserFormalParameters* parameters, Expression* pattern, bool is_rest) {
ExpressionClassifier* classifier) {
bool is_duplicate = false;
bool is_simple = pattern->IsVariableProxy(); bool is_simple = pattern->IsVariableProxy();
DCHECK(parser_->allow_harmony_destructuring() || is_simple); DCHECK(parser_->allow_harmony_destructuring() ||
parser_->allow_harmony_rest_parameters() || is_simple);
const AstRawString* name = is_simple const AstRawString* name = is_simple
? pattern->AsVariableProxy()->raw_name() ? pattern->AsVariableProxy()->raw_name()
: parser_->ast_value_factory()->empty_string(); : parser_->ast_value_factory()->empty_string();
VariableMode mode = is_simple ? VAR : TEMPORARY; parameters->params.Add(
ParserFormalParameters::Parameter(name, pattern, is_rest),
parameters->scope->zone());
}
void ParserTraits::DeclareFormalParameter(
Scope* scope, const ParserFormalParameters::Parameter& parameter,
bool is_simple, ExpressionClassifier* classifier) {
bool is_duplicate = false;
// TODO(caitp): Remove special handling for rest once desugaring is in.
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 = Variable* var =
parameters->scope->DeclareParameter(name, mode, is_rest, &is_duplicate); scope->DeclareParameter(name, mode, parameter.is_rest, &is_duplicate);
parameters->AddParameter(name, is_simple ? nullptr : pattern, is_rest);
if (is_duplicate) { if (is_duplicate) {
classifier->RecordDuplicateFormalParameterError( classifier->RecordDuplicateFormalParameterError(
parser_->scanner()->location()); parser_->scanner()->location());
} }
if (is_sloppy(parameters->scope->language_mode())) { if (is_sloppy(scope->language_mode())) {
// TODO(sigurds) Mark every parameter as maybe assigned. This is a // TODO(sigurds) Mark every parameter as maybe assigned. This is a
// conservative approximation necessary to account for parameters // conservative approximation necessary to account for parameters
// that are assigned via the arguments array. // that are assigned via the arguments array.
......
...@@ -27,6 +27,15 @@ enum FunctionNameValidity { ...@@ -27,6 +27,15 @@ enum FunctionNameValidity {
}; };
struct FormalParametersBase {
explicit FormalParametersBase(Scope* scope) : scope(scope) {}
Scope* scope;
bool has_rest = false;
bool is_simple = true;
int materialized_literals_count = 0;
};
// Common base class shared between parser and pre-parser. Traits encapsulate // Common base class shared between parser and pre-parser. Traits encapsulate
// the differences between Parser and PreParser: // the differences between Parser and PreParser:
...@@ -1312,18 +1321,13 @@ class PreParserFactory { ...@@ -1312,18 +1321,13 @@ class PreParserFactory {
}; };
struct PreParserFormalParameters { struct PreParserFormalParameters : FormalParametersBase {
explicit PreParserFormalParameters(Scope* scope) explicit PreParserFormalParameters(Scope* scope)
: scope(scope), : FormalParametersBase(scope) {}
arity(0), int arity = 0;
has_rest(false),
is_simple(true), int Arity() const { return arity; }
materialized_literals_count(0) {} PreParserIdentifier at(int i) { return PreParserIdentifier(); } // Dummy
Scope* scope;
int arity;
bool has_rest;
bool is_simple;
int materialized_literals_count;
}; };
...@@ -1606,7 +1610,7 @@ class PreParserTraits { ...@@ -1606,7 +1610,7 @@ class PreParserTraits {
const PreParserFormalParameters& parameters, FunctionKind kind, const PreParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok); FunctionLiteral::FunctionType function_type, bool* ok);
V8_INLINE void ParseArrowFunctionFormalParameters( V8_INLINE void ParseArrowFunctionFormalParameterList(
PreParserFormalParameters* parameters, PreParserFormalParameters* parameters,
PreParserExpression expression, const Scanner::Location& params_loc, PreParserExpression expression, const Scanner::Location& params_loc,
Scanner::Location* duplicate_loc, bool* ok); Scanner::Location* duplicate_loc, bool* ok);
...@@ -1637,8 +1641,13 @@ class PreParserTraits { ...@@ -1637,8 +1641,13 @@ class PreParserTraits {
return !tag.IsNoTemplateTag(); return !tag.IsNoTemplateTag();
} }
void DeclareFormalParameter(PreParserFormalParameters* parameters, void AddFormalParameter(
PreParserExpression pattern, bool is_rest, PreParserFormalParameters* parameters, PreParserExpression pattern,
bool is_rest) {
++parameters->arity;
}
void DeclareFormalParameter(Scope* scope, PreParserIdentifier parameter,
bool is_simple,
ExpressionClassifier* classifier) {} ExpressionClassifier* classifier) {}
void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {} void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {}
...@@ -1835,7 +1844,7 @@ PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function, ...@@ -1835,7 +1844,7 @@ PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function,
} }
void PreParserTraits::ParseArrowFunctionFormalParameters( void PreParserTraits::ParseArrowFunctionFormalParameterList(
PreParserFormalParameters* parameters, PreParserFormalParameters* parameters,
PreParserExpression params, const Scanner::Location& params_loc, PreParserExpression params, const Scanner::Location& params_loc,
Scanner::Location* duplicate_loc, bool* ok) { Scanner::Location* duplicate_loc, bool* ok) {
...@@ -2280,12 +2289,15 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, ...@@ -2280,12 +2289,15 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
// (...x) => y // (...x) => y
Scope* scope = Scope* scope =
this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction); this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
FormalParametersT parameters(scope); FormalParametersT formals(scope);
scope->set_start_position(beg_pos); scope->set_start_position(beg_pos);
ExpressionClassifier args_classifier; ExpressionClassifier formals_classifier;
const bool is_rest = true; const bool is_rest = true;
this->ParseFormalParameter(is_rest, &parameters, &args_classifier, this->ParseFormalParameter(is_rest, &formals, &formals_classifier,
CHECK_OK); CHECK_OK);
Traits::DeclareFormalParameter(
formals.scope, formals.at(0), formals.is_simple,
&formals_classifier);
if (peek() == Token::COMMA) { if (peek() == Token::COMMA) {
ReportMessageAt(scanner()->peek_location(), ReportMessageAt(scanner()->peek_location(),
MessageTemplate::kParamAfterRest); MessageTemplate::kParamAfterRest);
...@@ -2293,7 +2305,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, ...@@ -2293,7 +2305,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
return this->EmptyExpression(); return this->EmptyExpression();
} }
Expect(Token::RPAREN, CHECK_OK); Expect(Token::RPAREN, CHECK_OK);
result = this->ParseArrowFunctionLiteral(parameters, args_classifier, result = this->ParseArrowFunctionLiteral(formals, formals_classifier,
CHECK_OK); CHECK_OK);
} else { } else {
// Heuristically try to detect immediately called functions before // Heuristically try to detect immediately called functions before
...@@ -2845,8 +2857,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, ...@@ -2845,8 +2857,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
scope->set_start_position(lhs_location.beg_pos); scope->set_start_position(lhs_location.beg_pos);
Scanner::Location duplicate_loc = Scanner::Location::invalid(); Scanner::Location duplicate_loc = Scanner::Location::invalid();
this->ParseArrowFunctionFormalParameters(&parameters, expression, loc, this->ParseArrowFunctionFormalParameterList(&parameters, expression, loc,
&duplicate_loc, CHECK_OK); &duplicate_loc, CHECK_OK);
if (duplicate_loc.IsValid()) { if (duplicate_loc.IsValid()) {
arrow_formals_classifier.RecordDuplicateFormalParameterError( arrow_formals_classifier.RecordDuplicateFormalParameterError(
duplicate_loc); duplicate_loc);
...@@ -3647,8 +3659,7 @@ void ParserBase<Traits>::ParseFormalParameter( ...@@ -3647,8 +3659,7 @@ void ParserBase<Traits>::ParseFormalParameter(
*ok = false; *ok = false;
return; return;
} }
++parameters->arity; Traits::AddFormalParameter(parameters, pattern, is_rest);
Traits::DeclareFormalParameter(parameters, pattern, is_rest, classifier);
} }
...@@ -3669,11 +3680,11 @@ void ParserBase<Traits>::ParseFormalParameterList( ...@@ -3669,11 +3680,11 @@ void ParserBase<Traits>::ParseFormalParameterList(
// FormalsList[?Yield, ?GeneratorParameter] , // FormalsList[?Yield, ?GeneratorParameter] ,
// FormalParameter[?Yield,?GeneratorParameter] // FormalParameter[?Yield,?GeneratorParameter]
DCHECK_EQ(0, parameters->arity); DCHECK_EQ(0, parameters->Arity());
if (peek() != Token::RPAREN) { if (peek() != Token::RPAREN) {
do { do {
if (parameters->arity > Code::kMaxArguments) { if (parameters->Arity() > Code::kMaxArguments) {
ReportMessage(MessageTemplate::kTooManyParameters); ReportMessage(MessageTemplate::kTooManyParameters);
*ok = false; *ok = false;
return; return;
...@@ -3687,8 +3698,15 @@ void ParserBase<Traits>::ParseFormalParameterList( ...@@ -3687,8 +3698,15 @@ void ParserBase<Traits>::ParseFormalParameterList(
ReportMessageAt(scanner()->peek_location(), ReportMessageAt(scanner()->peek_location(),
MessageTemplate::kParamAfterRest); MessageTemplate::kParamAfterRest);
*ok = false; *ok = false;
return;
} }
} }
for (int i = 0; i < parameters->Arity(); ++i) {
auto parameter = parameters->at(i);
Traits::DeclareFormalParameter(
parameters->scope, parameter, parameters->is_simple, classifier);
}
} }
......
...@@ -806,16 +806,70 @@ ...@@ -806,16 +806,70 @@
assertEquals(1, g20({a: 1, b: 2})); assertEquals(1, g20({a: 1, b: 2}));
// var g21 = ({[eval('y')]: x}) => { var y = 'b'; return x; }; // var g21 = ({[eval('y')]: x}) => { var y = 'b'; return x; };
// assertEquals(1, g21({a: 1, b: 2})); // assertEquals(1, g21({a: 1, b: 2}));
})();
(function TestParameterTDZ() {
function f1({a = x}, x) { return a }
assertThrows(() => f1({}, 4), ReferenceError);
assertEquals(4, f1({a: 4}, 5));
// TODO(rossberg): eval in default expressions is not working yet.
// function f2({a = eval("x")}, x) { return a }
// assertThrows(() => f2({}, 4), ReferenceError);
// assertEquals(4, f2({a: 4}, 5));
// function f3({a = eval("x")}, x) { 'use strict'; return a }
// assertThrows(() => f3({}, 4), ReferenceError);
// assertEquals(4, f3({a: 4}, 5));
// function f4({a = eval("'use strict'; x")}, x) { return a }
// assertThrows(() => f4({}, 4), ReferenceError);
// assertEquals(4, f4({a: 4}, 5));
function f5({a = () => x}, x) { return a() }
assertEquals(4, f5({a: () => 4}, 5));
// TODO(rossberg): eval in default expressions is not working yet.
// function f6({a = () => eval("x")}, x) { return a() }
// assertEquals(4, f6({a: () => 4}, 5));
// function f7({a = () => eval("x")}, x) { 'use strict'; return a() }
// assertEquals(4, f7({a: () => 4}, 5));
// function f8({a = () => eval("'use strict'; x")}, x) { return a() }
// assertEquals(4, f8({a: () => 4}, 5));
function f11({a = b}, {b}) { return a }
assertThrows(() => f11({}, {b: 4}), ReferenceError);
assertEquals(4, f11({a: 4}, {b: 5}));
// function f12({a = eval("b")}, {b}) { return a }
// assertThrows(() => f12({}, {b: 4}), ReferenceError);
// assertEquals(4, f12({a: 4}, {b: 5}));
// function f13({a = eval("b")}, {b}) { 'use strict'; return a }
// assertThrows(() => f13({}, {b: 4}), ReferenceError);
// assertEquals(4, f13({a: 4}, {b: 5}));
// function f14({a = eval("'use strict'; b")}, {b}) { return a }
// assertThrows(() => f14({}, {b: 4}), ReferenceError);
// assertEquals(4, f14({a: 4}, {b: 5}));
function f15({a = () => b}, {b}) { return a() }
assertEquals(4, f15({a: () => 4}, {b: 5}));
// function f16({a = () => eval("b")}, {b}) { return a() }
// assertEquals(4, f16({a: () => 4}, {b: 5}));
// function f17({a = () => eval("b")}, {b}) { 'use strict'; return a() }
// assertEquals(4, f17({a: () => 4}, {b: 5}));
// function f18({a = () => eval("'use strict'; b")}, {b}) { return a() }
// assertEquals(4, f18({a: () => 4}, {b: 5}));
// TODO(caitp): TDZ for rest parameters is not working yet. // TODO(caitp): TDZ for rest parameters is not working yet.
// function f30({x = a}, ...a) {} // function f30({x = a}, ...a) { return x[0] }
// assertThrows(() => f30({}), ReferenceError); // assertThrows(() => f30({}), ReferenceError);
// function f31({x = eval("a")}, ...a) {} // assertEquals(4, f30({a: [4]}, 5));
// function f31({x = eval("a")}, ...a) { return x[0] }
// assertThrows(() => f31({}), ReferenceError); // assertThrows(() => f31({}), ReferenceError);
// function f32({x = eval("a")}, ...a) { 'use strict'; } // assertEquals(4, f31({a: [4]}, 5));
// function f32({x = eval("a")}, ...a) { 'use strict'; return x[0] }
// assertThrows(() => f32({}), ReferenceError); // assertThrows(() => f32({}), ReferenceError);
// function f33({x = eval("'use strict'; a")}, ...a) {} // assertEquals(4, f32({a: [4]}, 5));
// function f33({x = eval("'use strict'; a")}, ...a) { return x[0] }
// assertThrows(() => f33({}), ReferenceError); // assertThrows(() => f33({}), ReferenceError);
// assertEquals(4, f33({a: [4]}, 5));
function f34({x = function() { return a }}, ...a) { return x()[0] } function f34({x = function() { return a }}, ...a) { return x()[0] }
assertEquals(4, f34({}, 4)); assertEquals(4, f34({}, 4));
function f35({x = () => a}, ...a) { return x()[0] } function f35({x = () => a}, ...a) { return x()[0] }
......
...@@ -436,6 +436,9 @@ ...@@ -436,6 +436,9 @@
'language/computed-property-names/class/static/method-symbol': [FAIL, FAIL_SLOPPY], 'language/computed-property-names/class/static/method-symbol': [FAIL, FAIL_SLOPPY],
'language/computed-property-names/class/static/method-string': [FAIL, FAIL_SLOPPY], 'language/computed-property-names/class/static/method-string': [FAIL, FAIL_SLOPPY],
# This should work as soon as rest parameters are re-implemented via desaguring.
'language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-rest': [PASS, FAIL],
# https://code.google.com/p/v8/issues/detail?id=2160 # https://code.google.com/p/v8/issues/detail?id=2160
'language/expressions/arrow-function/syntax/arrowparameters-cover-initialize-1': [FAIL], 'language/expressions/arrow-function/syntax/arrowparameters-cover-initialize-1': [FAIL],
'language/expressions/arrow-function/syntax/arrowparameters-cover-initialize-2': [FAIL], 'language/expressions/arrow-function/syntax/arrowparameters-cover-initialize-2': [FAIL],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment