Commit a7fce186 authored by dslomov's avatar dslomov Committed by Commit bot

[destructuring] Parse binding patterns in formal parameters.

R=arv@chromium.org,wingo@igalia.com,caitpotter88@gmail.com
LOG=N
BUG=v8:811

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

Cr-Commit-Position: refs/heads/master@{#29029}
parent 6e5b9ffe
......@@ -1183,13 +1183,19 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
scope->set_start_position(shared_info->start_position());
ExpressionClassifier formals_classifier;
bool has_rest = false;
if (Check(Token::LPAREN)) {
// '(' StrictFormalParameters ')'
ParseFormalParameterList(scope, &has_rest, &formals_classifier, &ok);
if (ok) ok = Check(Token::RPAREN);
} else {
// BindingIdentifier
ParseFormalParameter(scope, has_rest, &formals_classifier, &ok);
{
// Parsing patterns as variable reference expression creates
// NewUnresolved references in current scope. Entrer arrow function
// scope for formal parameter parsing.
BlockState block_state(&scope_, scope);
if (Check(Token::LPAREN)) {
// '(' StrictFormalParameters ')'
ParseFormalParameterList(scope, &has_rest, &formals_classifier, &ok);
if (ok) ok = Check(Token::RPAREN);
} else {
// BindingIdentifier
ParseFormalParameter(scope, has_rest, &formals_classifier, &ok);
}
}
if (ok) {
......@@ -3805,7 +3811,10 @@ void ParserTraits::ParseArrowFunctionFormalParameters(
expr = expr->AsSpread()->expression();
}
DCHECK(expr->IsVariableProxy());
if (!expr->IsVariableProxy()) {
// TODO(dslomov): support pattern desugaring
return;
}
DCHECK(!expr->AsVariableProxy()->is_this());
const AstRawString* raw_name = expr->AsVariableProxy()->raw_name();
......@@ -3818,7 +3827,7 @@ void ParserTraits::ParseArrowFunctionFormalParameters(
parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
ExpressionClassifier classifier;
DeclareFormalParameter(scope, raw_name, &classifier, *has_rest);
DeclareFormalParameter(scope, expr, &classifier, *has_rest);
if (!duplicate_loc->IsValid()) {
*duplicate_loc = classifier.duplicate_formal_parameter_error().location;
}
......
......@@ -754,7 +754,7 @@ class ParserTraits {
V8_INLINE Scope* NewScope(Scope* parent_scope, ScopeType scope_type,
FunctionKind kind = kNormalFunction);
V8_INLINE void DeclareFormalParameter(Scope* scope, const AstRawString* name,
V8_INLINE void DeclareFormalParameter(Scope* scope, Expression* name,
ExpressionClassifier* classifier,
bool is_rest);
void ParseArrowFunctionFormalParameters(Scope* scope, Expression* params,
......@@ -1270,11 +1270,16 @@ Expression* ParserTraits::SpreadCallNew(
}
void ParserTraits::DeclareFormalParameter(Scope* scope,
const AstRawString* name,
void ParserTraits::DeclareFormalParameter(Scope* scope, Expression* pattern,
ExpressionClassifier* classifier,
bool is_rest) {
bool is_duplicate = false;
if (!pattern->IsVariableProxy()) {
// TODO(dslomov): implement.
DCHECK(parser_->allow_harmony_destructuring());
return;
}
auto name = pattern->AsVariableProxy()->raw_name();
Variable* var = scope->DeclareParameter(name, VAR, is_rest, &is_duplicate);
if (is_sloppy(scope->language_mode())) {
// TODO(sigurds) Mark every parameter as maybe assigned. This is a
......
......@@ -549,7 +549,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
ValidateBindingPattern(&pattern_classifier, CHECK_OK);
if (!FLAG_harmony_destructuring && !pattern.IsIdentifier()) {
if (!allow_harmony_destructuring() && !pattern.IsIdentifier()) {
ReportUnexpectedToken(next);
*ok = false;
return Statement::Default();
......
......@@ -555,7 +555,7 @@ class ParserBase : public Traits {
ExpressionT expr, bool* ok) {
if (classifier->is_valid_binding_pattern()) {
// A simple arrow formal parameter: IDENTIFIER => BODY.
if (!this->IsIdentifier(expr)) {
if (!allow_harmony_destructuring() && !this->IsIdentifier(expr)) {
Traits::ReportMessageAt(scanner()->location(),
MessageTemplate::kUnexpectedToken,
Token::String(scanner()->current_token()));
......@@ -1555,7 +1555,7 @@ class PreParserTraits {
return !tag.IsNoTemplateTag();
}
void DeclareFormalParameter(Scope* scope, PreParserIdentifier param,
void DeclareFormalParameter(Scope* scope, PreParserExpression pattern,
ExpressionClassifier* classifier, bool is_rest) {}
void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {}
......@@ -3487,10 +3487,21 @@ void ParserBase<Traits>::ParseFormalParameter(Scope* scope, bool is_rest,
bool* ok) {
// FormalParameter[Yield,GeneratorParameter] :
// BindingElement[?Yield, ?GeneratorParameter]
IdentifierT name = ParseAndClassifyIdentifier(classifier, ok);
Token::Value next = peek();
ExpressionT pattern = ParsePrimaryExpression(classifier, ok);
if (!*ok) return;
ValidateBindingPattern(classifier, ok);
if (!*ok) return;
Traits::DeclareFormalParameter(scope, name, classifier, is_rest);
if (!allow_harmony_destructuring() && !Traits::IsIdentifier(pattern)) {
ReportUnexpectedToken(next);
*ok = false;
return;
}
Traits::DeclareFormalParameter(scope, pattern, classifier, is_rest);
}
......
......@@ -6380,11 +6380,17 @@ TEST(StrongModeFreeVariablesNotDeclared) {
TEST(DestructuringPositiveTests) {
i::FLAG_harmony_destructuring = true;
i::FLAG_harmony_arrow_functions = true;
i::FLAG_harmony_computed_property_names = true;
const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
{"var ", " = {};"},
{"'use strict'; const ", " = {};"},
{"function f(", ") {}"},
{"function f(argument1, ", ") {}"},
{"var f = (", ") => {};"},
{"var f = ", " => {};"},
{"var f = (argument1,", ") => {};"},
{NULL, NULL}};
// clang-format off
......@@ -6424,9 +6430,9 @@ TEST(DestructuringPositiveTests) {
"[a,,...rest]",
NULL};
// clang-format on
static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals,
kAllowHarmonyComputedPropertyNames,
kAllowHarmonyDestructuring};
static const ParserFlag always_flags[] = {
kAllowHarmonyObjectLiterals, kAllowHarmonyComputedPropertyNames,
kAllowHarmonyArrowFunctions, kAllowHarmonyDestructuring};
RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
arraysize(always_flags));
}
......@@ -6434,15 +6440,21 @@ TEST(DestructuringPositiveTests) {
TEST(DestructuringNegativeTests) {
i::FLAG_harmony_destructuring = true;
i::FLAG_harmony_arrow_functions = true;
i::FLAG_harmony_computed_property_names = true;
static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals,
kAllowHarmonyComputedPropertyNames,
kAllowHarmonyDestructuring};
static const ParserFlag always_flags[] = {
kAllowHarmonyObjectLiterals, kAllowHarmonyComputedPropertyNames,
kAllowHarmonyArrowFunctions, kAllowHarmonyDestructuring};
{ // All modes.
const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
{"var ", " = {};"},
{"'use strict'; const ", " = {};"},
{"function f(", ") {}"},
{"function f(argument1, ", ") {}"},
{"var f = (", ") => {};"},
{"var f = ", " => {};"},
{"var f = (argument1,", ") => {};"},
{NULL, NULL}};
// clang-format off
......@@ -6475,7 +6487,6 @@ TEST(DestructuringNegativeTests) {
"a >>> a",
"function a() {}",
"a`bcd`",
"x => x",
"this",
"null",
"true",
......@@ -6483,7 +6494,6 @@ TEST(DestructuringNegativeTests) {
"1",
"'abc'",
"class {}",
"() => x",
"{+2 : x}",
"{-2 : x}",
"var",
......@@ -6509,11 +6519,34 @@ TEST(DestructuringNegativeTests) {
arraysize(always_flags));
}
{ // Strict mode.
{ // All modes.
const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
{"var ", " = {};"},
{"'use strict'; const ", " = {};"},
{"function f(", ") {}"},
{"function f(argument1, ", ") {}"},
{"var f = (", ") => {};"},
{"var f = (argument1,", ") => {};"},
{NULL, NULL}};
// clang-format off
const char* data[] = {
"x => x",
"() => x",
NULL};
// clang-format on
RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
arraysize(always_flags));
}
{ // Strict mode.
const char* context_data[][2] = {
{"'use strict'; let ", " = {};"},
{"'use strict'; const ", " = {};"},
{"'use strict'; function f(", ") {}"},
{"'use strict'; function f(argument1, ", ") {}"},
{NULL, NULL}};
// clang-format off
const char* data[] = {
"[eval]",
......
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