Commit 6dda11ff authored by rossberg's avatar rossberg Committed by Commit bot

[es6] Implement default parameters

Based on caitp's https://codereview.chromium.org/1127063003/

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

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

Cr-Commit-Position: refs/heads/master@{#30192}
parent 94ee6b1b
......@@ -1818,6 +1818,7 @@ EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_sloppy_function)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_sloppy_let)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_unicode_regexps)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_rest_parameters)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_default_parameters)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_reflect)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_spreadcalls)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_destructuring)
......@@ -1869,6 +1870,7 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_sloppy)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_sloppy_function)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_sloppy_let)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_rest_parameters)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_default_parameters)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_spreadcalls)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_destructuring)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_object)
......@@ -2545,6 +2547,7 @@ bool Genesis::InstallExperimentalNatives() {
static const char* harmony_sloppy_let_natives[] = {nullptr};
static const char* harmony_unicode_regexps_natives[] = {nullptr};
static const char* harmony_rest_parameters_natives[] = {nullptr};
static const char* harmony_default_parameters_natives[] = {nullptr};
static const char* harmony_reflect_natives[] = {"native harmony-reflect.js",
nullptr};
static const char* harmony_spreadcalls_natives[] = {
......
......@@ -194,6 +194,7 @@ DEFINE_BOOL(legacy_const, true, "legacy semantics for const in sloppy mode")
V(harmony_unicode_regexps, "harmony unicode regexps") \
V(harmony_reflect, "harmony Reflect API") \
V(harmony_destructuring, "harmony destructuring") \
V(harmony_default_parameters, "harmony default parameters") \
V(harmony_sharedarraybuffer, "harmony sharedarraybuffer") \
V(harmony_atomics, "harmony atomics") \
V(harmony_simd, "harmony simd")
......
......@@ -916,6 +916,7 @@ Parser::Parser(ParseInfo* info)
set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function);
set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let);
set_allow_harmony_rest_parameters(FLAG_harmony_rest_parameters);
set_allow_harmony_default_parameters(FLAG_harmony_default_parameters);
set_allow_harmony_spreadcalls(FLAG_harmony_spreadcalls);
set_allow_harmony_destructuring(FLAG_harmony_destructuring);
set_allow_harmony_spread_arrays(FLAG_harmony_spread_arrays);
......@@ -3910,7 +3911,19 @@ void ParserTraits::ParseArrowFunctionFormalParameters(
parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
}
AddFormalParameter(parameters, expr, is_rest);
Expression* initializer = nullptr;
if (!is_rest && parser_->allow_harmony_default_parameters() &&
parser_->Check(Token::ASSIGN)) {
ExpressionClassifier init_classifier;
initializer =
parser_->ParseAssignmentExpression(true, &init_classifier, ok);
if (!*ok) return;
parser_->ValidateExpression(&init_classifier, ok);
if (!*ok) return;
parameters->is_simple = false;
}
AddFormalParameter(parameters, expr, initializer, is_rest);
}
......@@ -4329,9 +4342,22 @@ Block* Parser::BuildParameterInitializationBlock(
descriptor.declaration_pos = parameter.pattern->position();
descriptor.initialization_pos = parameter.pattern->position();
descriptor.init_op = Token::INIT_LET;
Expression* initial_value =
factory()->NewVariableProxy(parameters.scope->parameter(i));
if (parameter.initializer != nullptr) {
// IS_UNDEFINED($param) ? initializer : $param
auto condition = factory()->NewCompareOperation(
Token::EQ_STRICT,
factory()->NewVariableProxy(parameters.scope->parameter(i)),
factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
RelocInfo::kNoPosition);
initial_value = factory()->NewConditional(
condition, parameter.initializer, initial_value,
RelocInfo::kNoPosition);
descriptor.initialization_pos = parameter.initializer->position();
}
DeclarationParsingResult::Declaration decl(
parameter.pattern, parameter.pattern->position(),
factory()->NewVariableProxy(parameters.scope->parameter(i)));
parameter.pattern, parameter.pattern->position(), initial_value);
PatternRewriter::DeclareAndInitializeVariables(init_block, &descriptor,
&decl, nullptr, CHECK_OK);
}
......@@ -4497,6 +4523,7 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
SET_ALLOW(harmony_sloppy);
SET_ALLOW(harmony_sloppy_let);
SET_ALLOW(harmony_rest_parameters);
SET_ALLOW(harmony_default_parameters);
SET_ALLOW(harmony_spreadcalls);
SET_ALLOW(harmony_destructuring);
SET_ALLOW(harmony_spread_arrays);
......
......@@ -541,10 +541,13 @@ class SingletonLogger;
struct ParserFormalParameters : FormalParametersBase {
struct Parameter {
Parameter(const AstRawString* name, Expression* pattern, bool is_rest)
: name(name), pattern(pattern), is_rest(is_rest) {}
Parameter(const AstRawString* name, Expression* pattern,
Expression* initializer, bool is_rest)
: name(name), pattern(pattern), initializer(initializer),
is_rest(is_rest) {}
const AstRawString* name;
Expression* pattern;
Expression* initializer;
bool is_rest;
};
......@@ -779,7 +782,8 @@ class ParserTraits {
FunctionKind kind = kNormalFunction);
V8_INLINE void AddFormalParameter(
ParserFormalParameters* parameters, Expression* pattern, bool is_rest);
ParserFormalParameters* parameters, Expression* pattern,
Expression* initializer, bool is_rest);
V8_INLINE void DeclareFormalParameter(
Scope* scope, const ParserFormalParameters::Parameter& parameter,
bool is_simple, ExpressionClassifier* classifier);
......@@ -1313,15 +1317,17 @@ Expression* ParserTraits::SpreadCallNew(
void ParserTraits::AddFormalParameter(
ParserFormalParameters* parameters, Expression* pattern, bool is_rest) {
bool is_simple = pattern->IsVariableProxy();
ParserFormalParameters* parameters,
Expression* pattern, Expression* initializer, bool is_rest) {
bool is_simple = pattern->IsVariableProxy() && initializer == nullptr;
DCHECK(parser_->allow_harmony_destructuring() ||
parser_->allow_harmony_rest_parameters() || is_simple);
parser_->allow_harmony_rest_parameters() ||
parser_->allow_harmony_default_parameters() || is_simple);
const AstRawString* name = is_simple
? pattern->AsVariableProxy()->raw_name()
: parser_->ast_value_factory()->empty_string();
parameters->params.Add(
ParserFormalParameters::Parameter(name, pattern, is_rest),
ParserFormalParameters::Parameter(name, pattern, initializer, is_rest),
parameters->scope->zone());
}
......
......@@ -111,6 +111,7 @@ class ParserBase : public Traits {
allow_harmony_sloppy_function_(false),
allow_harmony_sloppy_let_(false),
allow_harmony_rest_parameters_(false),
allow_harmony_default_parameters_(false),
allow_harmony_spreadcalls_(false),
allow_harmony_destructuring_(false),
allow_harmony_spread_arrays_(false),
......@@ -129,6 +130,7 @@ class ParserBase : public Traits {
ALLOW_ACCESSORS(harmony_sloppy_function);
ALLOW_ACCESSORS(harmony_sloppy_let);
ALLOW_ACCESSORS(harmony_rest_parameters);
ALLOW_ACCESSORS(harmony_default_parameters);
ALLOW_ACCESSORS(harmony_spreadcalls);
ALLOW_ACCESSORS(harmony_destructuring);
ALLOW_ACCESSORS(harmony_spread_arrays);
......@@ -805,6 +807,7 @@ class ParserBase : public Traits {
bool allow_harmony_sloppy_function_;
bool allow_harmony_sloppy_let_;
bool allow_harmony_rest_parameters_;
bool allow_harmony_default_parameters_;
bool allow_harmony_spreadcalls_;
bool allow_harmony_destructuring_;
bool allow_harmony_spread_arrays_;
......@@ -1637,7 +1640,7 @@ class PreParserTraits {
void AddFormalParameter(
PreParserFormalParameters* parameters, PreParserExpression pattern,
bool is_rest) {
PreParserExpression initializer, bool is_rest) {
++parameters->arity;
}
void DeclareFormalParameter(Scope* scope, PreParserIdentifier parameter,
......@@ -2873,7 +2876,7 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
return expression;
}
if (!allow_harmony_destructuring()) {
if (!(allow_harmony_destructuring() || allow_harmony_default_parameters())) {
BindingPatternUnexpectedToken(classifier);
}
......@@ -3638,22 +3641,26 @@ void ParserBase<Traits>::ParseFormalParameter(
ValidateBindingPattern(classifier, ok);
if (!*ok) return;
if (!allow_harmony_destructuring() && !Traits::IsIdentifier(pattern)) {
ReportUnexpectedToken(next);
*ok = false;
return;
if (!Traits::IsIdentifier(pattern)) {
if (is_rest || !allow_harmony_destructuring()) {
ReportUnexpectedToken(next);
*ok = false;
return;
}
parameters->is_simple = false;
}
if (parameters->is_simple) {
parameters->is_simple = !is_rest && Traits::IsIdentifier(pattern);
}
parameters->has_rest = is_rest;
if (is_rest && !Traits::IsIdentifier(pattern)) {
ReportUnexpectedToken(next);
*ok = false;
return;
ExpressionT initializer = Traits::EmptyExpression();
if (!is_rest && allow_harmony_default_parameters() && Check(Token::ASSIGN)) {
ExpressionClassifier init_classifier;
initializer = ParseAssignmentExpression(true, &init_classifier, ok);
if (!*ok) return;
ValidateExpression(&init_classifier, ok);
if (!*ok) return;
parameters->is_simple = false;
}
Traits::AddFormalParameter(parameters, pattern, is_rest);
Traits::AddFormalParameter(parameters, pattern, initializer, is_rest);
}
......@@ -3689,11 +3696,14 @@ void ParserBase<Traits>::ParseFormalParameterList(
if (!*ok) return;
} while (!parameters->has_rest && Check(Token::COMMA));
if (parameters->has_rest && peek() == Token::COMMA) {
ReportMessageAt(scanner()->peek_location(),
if (parameters->has_rest) {
parameters->is_simple = false;
if (peek() == Token::COMMA) {
ReportMessageAt(scanner()->peek_location(),
MessageTemplate::kParamAfterRest);
*ok = false;
return;
*ok = false;
return;
}
}
}
......
// 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: --expose-debug-as debug --harmony-default-parameters
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
listenerComplete = false;
breakPointCount = 0;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
breakPointCount++;
if (breakPointCount == 1) {
// Break point in initializer for parameter `a`, invoked by
// initializer for parameter `b`
assertEquals('default', exec_state.frame(1).evaluate('mode').value());
// initializer for `b` can't refer to `b`
assertThrows(function() {
exec_state.frame(1).evaluate('b').value();
}, ReferenceError);
assertThrows(function() {
exec_state.frame(1).evaluate('c');
}, ReferenceError);
} else if (breakPointCount == 2) {
// Break point in IIFE initializer for parameter `c`
assertEquals('modeFn', exec_state.frame(1).evaluate('a.name').value());
assertEquals('default', exec_state.frame(1).evaluate('b').value());
assertThrows(function() {
exec_state.frame(1).evaluate('c');
}, ReferenceError);
} else if (breakPointCount == 3) {
// Break point in function body --- `c` parameter is shadowed
assertEquals('modeFn', exec_state.frame(0).evaluate('a.name').value());
assertEquals('default', exec_state.frame(0).evaluate('b').value());
assertEquals('local', exec_state.frame(0).evaluate('d').value());
}
}
};
// Add the debug event listener.
Debug.setListener(listener);
function f(a = function modeFn(mode) { debugger; return mode; },
b = a("default"),
c = (function() { debugger; })()) {
var d = 'local';
debugger;
};
f();
// Make sure that the debug event listener vas invoked.
assertEquals(3, breakPointCount);
// 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-default-parameters --harmony-arrow-functions
// Flags: --harmony-rest-parameters
(function TestDefaults() {
function f1(x = 1) { return x }
assertEquals(1, f1());
assertEquals(1, f1(undefined));
assertEquals(2, f1(2));
assertEquals(null, f1(null));
function f2(x, y = x) { return x + y; }
assertEquals(8, f2(4));
assertEquals(8, f2(4, undefined));
assertEquals(6, f2(4, 2));
function f3(x = 1, y) { return x + y; }
assertEquals(8, f3(5, 3));
assertEquals(3, f3(undefined, 2));
assertEquals(6, f3(4, 2));
function f4(x = () => 1) { return x() }
assertEquals(1, f4());
assertEquals(1, f4(undefined));
assertEquals(2, f4(() => 2));
assertThrows(() => f4(null), TypeError);
function f5(x, y = () => x) { return x + y(); }
assertEquals(8, f5(4));
assertEquals(8, f5(4, undefined));
assertEquals(6, f5(4, () => 2));
function f6(x = {a: 1, m() { return 2 }}) { return x.a + x.m(); }
assertEquals(3, f6());
assertEquals(3, f6(undefined));
assertEquals(5, f6({a: 2, m() { return 3 }}));
var g1 = (x = 1) => { return x };
assertEquals(1, g1());
assertEquals(1, g1(undefined));
assertEquals(2, g1(2));
assertEquals(null, g1(null));
var g2 = (x, y = x) => { return x + y; };
assertEquals(8, g2(4));
assertEquals(8, g2(4, undefined));
assertEquals(6, g2(4, 2));
var g3 = (x = 1, y) => { return x + y; };
assertEquals(8, g3(5, 3));
assertEquals(3, g3(undefined, 2));
assertEquals(6, g3(4, 2));
var g4 = (x = () => 1) => { return x() };
assertEquals(1, g4());
assertEquals(1, g4(undefined));
assertEquals(2, g4(() => 2));
assertThrows(() => g4(null), TypeError);
var g5 = (x, y = () => x) => { return x + y(); };
assertEquals(8, g5(4));
assertEquals(8, g5(4, undefined));
assertEquals(6, g5(4, () => 2));
var g6 = (x = {a: 1, m() { return 2 }}) => { return x.a + x.m(); };
assertEquals(3, g6());
assertEquals(3, g6(undefined));
assertEquals(5, g6({a: 2, m() { return 3 }}));
}());
(function TestEvalInParameters() {
function f1(x = eval(0)) { return x }
assertEquals(0, f1());
function f2(x = () => eval(1)) { return x() }
assertEquals(1, f2());
})();
(function TestParameterScoping() {
// TODO(rossberg): Add checks for variable declarations in defaults.
var x = 1;
function f1(a = x) { var x = 2; return a; }
assertEquals(1, f1());
function f2(a = x) { function x() {}; return a; }
assertEquals(1, f2());
function f3(a = x) { 'use strict'; let x = 2; return a; }
assertEquals(1, f3());
function f4(a = x) { 'use strict'; const x = 2; return a; }
assertEquals(1, f4());
function f5(a = x) { 'use strict'; function x() {}; return a; }
assertEquals(1, f5());
function f6(a = eval("x")) { var x; return a; }
assertEquals(1, f6());
function f61(a = eval("x")) { 'use strict'; var x; return a; }
assertEquals(1, f61());
function f62(a = eval("'use strict'; x")) { var x; return a; }
assertEquals(1, f62());
function f7(a = function() { return x }) { var x; return a(); }
assertEquals(1, f7());
function f8(a = () => x) { var x; return a(); }
assertEquals(1, f8());
function f9(a = () => eval("x")) { var x; return a(); }
assertEquals(1, f9());
function f91(a = () => eval("x")) { 'use strict'; var x; return a(); }
assertEquals(1, f91());
function f92(a = () => { 'use strict'; return eval("x") }) { var x; return a(); }
assertEquals(1, f92());
function f93(a = () => eval("'use strict'; x")) { var x; return a(); }
assertEquals(1, f93());
var g1 = (a = x) => { var x = 2; return a; };
assertEquals(1, g1());
var g2 = (a = x) => { function x() {}; return a; };
assertEquals(1, g2());
var g3 = (a = x) => { 'use strict'; let x = 2; return a; };
assertEquals(1, g3());
var g4 = (a = x) => { 'use strict'; const x = 2; return a; };
assertEquals(1, g4());
var g5 = (a = x) => { 'use strict'; function x() {}; return a; };
assertEquals(1, g5());
var g6 = (a = eval("x")) => { var x; return a; };
assertEquals(1, g6());
var g61 = (a = eval("x")) => { 'use strict'; var x; return a; };
assertEquals(1, g61());
var g62 = (a = eval("'use strict'; x")) => { var x; return a; };
assertEquals(1, g62());
var g7 = (a = function() { return x }) => { var x; return a(); };
assertEquals(1, g7());
var g8 = (a = () => x) => { var x; return a(); };
assertEquals(1, g8());
var g9 = (a = () => eval("x")) => { var x; return a(); };
assertEquals(1, g9());
var g91 = (a = () => eval("x")) => { 'use strict'; var x; return a(); };
assertEquals(1, g91());
var g92 = (a = () => { 'use strict'; return eval("x") }) => { var x; return a(); };
assertEquals(1, g92());
var g93 = (a = () => eval("'use strict'; x")) => { var x; return a(); };
assertEquals(1, g93());
var f11 = function f(x = f) { var f; return x; }
assertSame(f11, f11());
var f12 = function f(x = f) { function f() {}; return x; }
assertSame(f12, f12());
var f13 = function f(x = f) { 'use strict'; let f; return x; }
assertSame(f13, f13());
var f14 = function f(x = f) { 'use strict'; const f = 0; return x; }
assertSame(f14, f14());
var f15 = function f(x = f) { 'use strict'; function f() {}; return x; }
assertSame(f15, f15());
var f16 = function f(f = 7, x = f) { return x; }
assertSame(7, f16());
var o1 = {f: function(x = this) { return x; }};
assertSame(o1, o1.f());
assertSame(1, o1.f(1));
})();
(function TestParameterTDZ() {
function f1(a = x, x) { return a }
assertThrows(() => f1(undefined, 4), ReferenceError);
assertEquals(4, f1(4, 5));
function f2(a = eval("x"), x) { return a }
assertThrows(() => f2(undefined, 4), ReferenceError);
assertEquals(4, f2(4, 5));
function f3(a = eval("x"), x) { 'use strict'; return a }
assertThrows(() => f3(undefined, 4), ReferenceError);
assertEquals(4, f3(4, 5));
function f4(a = eval("'use strict'; x"), x) { return a }
assertThrows(() => f4(undefined, 4), ReferenceError);
assertEquals(4, f4(4, 5));
function f5(a = () => x, x) { return a() }
assertEquals(4, f5(() => 4, 5));
function f6(a = () => eval("x"), x) { return a() }
assertEquals(4, f6(() => 4, 5));
function f7(a = () => eval("x"), x) { 'use strict'; return a() }
assertEquals(4, f7(() => 4, 5));
function f8(a = () => eval("'use strict'; x"), x) { return a() }
assertEquals(4, f8(() => 4, 5));
function f11(a = x, x = 2) { return a }
assertThrows(() => f11(), ReferenceError);
assertThrows(() => f11(undefined), ReferenceError);
assertThrows(() => f11(undefined, 4), ReferenceError);
assertEquals(4, f1(4, 5));
function f12(a = eval("x"), x = 2) { return a }
assertThrows(() => f12(), ReferenceError);
assertThrows(() => f12(undefined), ReferenceError);
assertThrows(() => f12(undefined, 4), ReferenceError);
assertEquals(4, f12(4, 5));
function f13(a = eval("x"), x = 2) { 'use strict'; return a }
assertThrows(() => f13(), ReferenceError);
assertThrows(() => f13(undefined), ReferenceError);
assertThrows(() => f13(undefined, 4), ReferenceError);
assertEquals(4, f13(4, 5));
function f14(a = eval("'use strict'; x"), x = 2) { return a }
assertThrows(() => f14(), ReferenceError);
assertThrows(() => f14(undefined), ReferenceError);
assertThrows(() => f14(undefined, 4), ReferenceError);
assertEquals(4, f14(4, 5));
function f34(x = function() { return a }, ...a) { return x()[0] }
assertEquals(4, f34(undefined, 4));
function f35(x = () => a, ...a) { return x()[0] }
assertEquals(4, f35(undefined, 4));
function f36(x = () => eval("a"), ...a) { return x()[0] }
assertEquals(4, f36(undefined, 4));
function f37(x = () => eval("a"), ...a) { 'use strict'; return x()[0] }
assertEquals(4, f37(undefined, 4));
function f38(x = () => { 'use strict'; return eval("a") }, ...a) { return x()[0] }
assertEquals(4, f38(undefined, 4));
function f39(x = () => eval("'use strict'; a"), ...a) { return x()[0] }
assertEquals(4, f39(undefined, 4));
var g34 = (x = function() { return a }, ...a) => { return x()[0] };
assertEquals(4, g34(undefined, 4));
var g35 = (x = () => a, ...a) => { return x()[0] };
assertEquals(4, g35(undefined, 4));
})();
(function TestArgumentsForNonSimpleParameters() {
function f1(x = 900) { arguments[0] = 1; return x }
assertEquals(9, f1(9));
assertEquals(900, f1());
function f2(x = 1001) { x = 2; return arguments[0] }
assertEquals(10, f2(10));
assertEquals(undefined, f2());
}());
(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);
})();
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --harmony-destructuring
// Flags: --harmony-arrow-functions --harmony-rest-parameters
// Flags: --harmony-destructuring --harmony-arrow-functions
// Flags: --harmony-default-parameters --harmony-rest-parameters
(function TestObjectLiteralPattern() {
var { x : x, y : y } = { x : 1, y : 2 };
......@@ -723,13 +723,14 @@
(function TestExpressionsInParameters() {
function f0(x = eval(0)) { return x }
assertEquals(0, f0());
function f1({a = eval(1)}) { return a }
assertEquals(1, f1({}));
function f2([x = eval(2)]) { return x }
assertEquals(2, f2([]));
function f3({[eval(7)]: x}) { return x }
assertEquals(3, f3({7: 3}));
// TODO(rossberg, caitp): Add tests for default parameters.
})();
......@@ -819,7 +820,7 @@
})();
(function TestParameterTDZ() {
(function TestParameterDestructuringTDZ() {
function f1({a = x}, x) { return a }
assertThrows(() => f1({}, 4), ReferenceError);
assertEquals(4, f1({a: 4}, 5));
......@@ -943,7 +944,6 @@
assertEquals(5, f7({a: 5}));
function f8(x, ...a) { a = []; return arguments[1] }
assertEquals(6, f8(5, 6));
// TODO(rossberg, caitp): Add cases for default parameters.
}());
......
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