Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Unified Diff: src/parser.cc

Issue 1104223002: [es6] implement optional parameters via desugaring (with scoping) (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add a debugger test Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index feed1e4b12fcef812309dfe4c4a7870fbcd41a13..f0641d4e84b40a06582c75d264df16b8944277f8 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1134,13 +1134,18 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
scope->set_start_position(shared_info->start_position());
FormalParameterErrorLocations error_locs;
bool has_rest = false;
+ bool has_initializers = false;
+ ZoneList<Expression*>* initializers =
+ new (zone()) ZoneList<Expression*>(0, zone());
if (Check(Token::LPAREN)) {
// '(' StrictFormalParameters ')'
- ParseFormalParameterList(scope, &error_locs, &has_rest, &ok);
+ ParseFormalParameterList(scope, &error_locs, initializers,
+ &has_initializers, &has_rest, &ok);
if (ok) ok = Check(Token::RPAREN);
} else {
// BindingIdentifier
- ParseFormalParameter(scope, &error_locs, has_rest, &ok);
+ ParseFormalParameter(scope, &error_locs, nullptr, nullptr, has_rest,
+ &ok);
}
if (ok) {
@@ -1925,7 +1930,8 @@ VariableProxy* Parser::NewUnresolved(const AstRawString* name,
}
-Variable* Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
+Variable* Parser::Declare(Declaration* declaration, bool resolve,
+ bool allow_redeclaration, bool* ok) {
VariableProxy* proxy = declaration->proxy();
DCHECK(proxy->raw_name() != NULL);
const AstRawString* name = proxy->raw_name();
@@ -1948,7 +1954,7 @@ Variable* Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
declaration_scope->is_script_scope()) {
// Declare the variable in the declaration scope.
var = declaration_scope->LookupLocal(name);
- if (var == NULL) {
+ if (var == NULL || allow_redeclaration) {
// Declare the name.
Variable::Kind kind = Variable::NORMAL;
int declaration_group_start = -1;
@@ -1960,9 +1966,16 @@ Variable* Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
declaration_group_start =
declaration->AsVariableDeclaration()->declaration_group_start();
}
- var = declaration_scope->DeclareLocal(
- name, mode, declaration->initialization(), kind, kNotAssigned,
- declaration_group_start);
+ if (var) {
+ DCHECK(declaration_scope->IsDeclaredParameter(name));
+ var = declaration_scope->RedeclareLocal(
+ name, mode, declaration->initialization(), kind, kNotAssigned,
+ declaration_group_start);
+ } else {
+ var = declaration_scope->DeclareLocal(
+ name, mode, declaration->initialization(), kind, kNotAssigned,
+ declaration_group_start);
+ }
} else if (IsLexicalVariableMode(mode) ||
IsLexicalVariableMode(var->mode()) ||
((mode == CONST_LEGACY || var->mode() == CONST_LEGACY) &&
@@ -3930,9 +3943,9 @@ void ParserTraits::DeclareArrowFunctionParameters(
// VariableProxy and recorded as unresolved in the scope. Here we undo that
// parse-time side-effect.
parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
-
+ int pos = expr->AsVariableProxy()->position();
bool is_rest = false;
- bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest);
+ bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest, pos);
if (is_duplicate) {
// Arrow function parameter lists are parsed as StrictFormalParameters,
@@ -3963,6 +3976,98 @@ void ParserTraits::ParseArrowFunctionFormalParameters(
}
+ZoneList<Statement*>* Parser::DesugarInitializeParameters(
+ Scope* scope, bool has_initializers, ZoneList<Expression*>* initializers) {
+ DCHECK(scope->is_function_scope());
+
+ ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(0, zone());
+ if (has_initializers) {
+ for (int i = 0; i < initializers->length(); ++i) {
+ Expression* initializer = initializers->at(i);
+
+ // Position of parameter VariableProxy, for hole-checking
+ int pos = scope->parameter_position(i);
+
+ // Lexically declare the initialized variable
+ static const VariableMode mode = LET;
+ VariableProxy* proxy =
+ NewUnresolved(scope->parameter(i)->raw_name(), mode);
+ VariableDeclaration* declaration = factory()->NewVariableDeclaration(
+ proxy, mode, scope, RelocInfo::kNoPosition);
+ // BRITTLE: this illegally redeclares the variable, be careful about this
+ proxy =
+ factory()->NewVariableProxy(Declare(declaration, true, true), pos);
+ proxy->var()->set_maybe_assigned();
+
+ const AstRawString* fn_name = ast_value_factory()->empty_string();
+ const Runtime::Function* arguments =
+ Runtime::FunctionForId(Runtime::kInlineArguments);
+ ZoneList<Expression*>* arguments_i0 =
+ new (zone()) ZoneList<Expression*>(0, zone());
+ arguments_i0->Add(factory()->NewSmiLiteral(i, RelocInfo::kNoPosition),
+ zone());
+
+ // TODO(caitp): ensure proper TDZ behaviour --- need hole-check for
+ // all parameter bindings, including ones without initializers
+ if (initializer) {
+ // IS_UNDEFINED(%_Arguments(i)) ? <initializer> : %_Arguments(i);
+ ZoneList<Expression*>* arguments_i1 =
+ new (zone()) ZoneList<Expression*>(0, zone());
+ arguments_i1->Add(factory()->NewSmiLiteral(i, RelocInfo::kNoPosition),
+ zone());
+
+ Expression* arg_or_default = factory()->NewConditional(
+ // condition:
+ factory()->NewCompareOperation(
+ Token::EQ_STRICT,
+ factory()->NewCallRuntime(fn_name, arguments, arguments_i0,
+ RelocInfo::kNoPosition),
+ factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition),
+ // if true:
+ initializer,
+ // if false:
+ factory()->NewCallRuntime(fn_name, arguments, arguments_i1,
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition);
+
+ Expression* assign = factory()->NewAssignment(
+ Token::INIT_LET, proxy, arg_or_default, RelocInfo::kNoPosition);
+
+ body->Add(
+ factory()->NewExpressionStatement(assign, RelocInfo::kNoPosition),
+ zone());
+ proxy->var()->set_initializer_position(initializer->position());
+ } else {
+ // let <name> = %_Arguments(i)
+ Expression* assign = factory()->NewAssignment(
+ Token::INIT_LET, proxy,
+ factory()->NewCallRuntime(fn_name, arguments, arguments_i0,
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition);
+ body->Add(
+ factory()->NewExpressionStatement(assign, RelocInfo::kNoPosition),
+ zone());
+ proxy->var()->set_initializer_position(pos);
+ }
+ }
+ } else {
+ // If hasParameterExpressions is false, remove the unnecessary parameter
+ // block scopes. The function body scope can't be safely removed at this
+ // point.
+ ZoneList<Scope*>* scopes = scope->inner_scopes();
+ for (int i = 0; i < scopes->length(); ++i) {
+ Scope* scope = scopes->at(i);
+ if (!scope->is_function_body_scope()) {
+ DCHECK(scope->is_block_scope());
+ scope->FinalizeBlockScope();
+ }
+ }
+ }
+ return body;
+}
+
+
FunctionLiteral* Parser::ParseFunctionLiteral(
const AstRawString* function_name, Scanner::Location function_name_location,
bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
@@ -4028,6 +4133,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
declaration_scope != original_declaration_scope)
? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
: NewScope(scope_, FUNCTION_SCOPE, kind);
+ Scope* function_body = NewScope(scope, FUNCTION_BODY_SCOPE);
+ DCHECK_EQ(scope->function_body(), function_body);
ZoneList<Statement*>* body = NULL;
int materialized_literal_count = -1;
int expected_property_count = -1;
@@ -4042,6 +4149,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
FunctionState function_state(&function_state_, &scope_, scope, kind,
&function_factory);
scope_->SetScopeName(function_name);
+ function_body->SetScopeName(function_name);
if (is_generator) {
// For generators, allocating variables in contexts is currently a win
@@ -4061,8 +4169,13 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
Expect(Token::LPAREN, CHECK_OK);
int start_position = scanner()->location().beg_pos;
scope_->set_start_position(start_position);
+ function_body->set_start_position(start_position);
+ ZoneList<Expression*>* initializers =
+ new (zone()) ZoneList<Expression*>(0, zone());
+ bool has_initializers = false;
num_parameters =
- ParseFormalParameterList(scope, &error_locs, &has_rest, CHECK_OK);
+ ParseFormalParameterList(scope, &error_locs, initializers,
+ &has_initializers, &has_rest, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
int formals_end_position = scanner()->location().end_pos;
@@ -4092,6 +4205,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
VariableProxy* proxy = factory()->NewVariableProxy(fvar);
VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
+ DCHECK(scope_->is_function_scope());
scope_->DeclareFunctionVar(fvar_declaration);
}
@@ -4133,26 +4247,47 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
!parenthesized_function_);
parenthesized_function_ = false; // The bit was set for this function only.
- if (is_lazily_parsed) {
- for (Scope* s = scope_->outer_scope();
- s != nullptr && (s != s->DeclarationScope()); s = s->outer_scope()) {
- s->ForceContextAllocation();
+ {
+ // Use the FUNCTION_BODY scope only if it's needed
+ // TODO(caitp): This is needed when ObjectBindingPatterns with
+ // computed property keys are used as well.
+ Scope* func_scope = has_initializers ? function_body : scope_;
+ if (func_scope != function_body) {
+ function_body->FinalizeBlockScope();
}
- SkipLazyFunctionBody(&materialized_literal_count,
- &expected_property_count, CHECK_OK);
- } else {
- body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
- kind, CHECK_OK);
- materialized_literal_count = function_state.materialized_literal_count();
- expected_property_count = function_state.expected_property_count();
- handler_count = function_state.handler_count();
-
- if (is_strong(language_mode()) && IsSubclassConstructor(kind)) {
- if (!function_state.super_location().IsValid()) {
- ReportMessageAt(function_name_location,
- "strong_super_call_missing", kReferenceError);
- *ok = false;
- return nullptr;
+
+ if (is_lazily_parsed) {
+ for (Scope* s = scope_->outer_scope();
+ s != nullptr && (s != s->DeclarationScope());
+ s = s->outer_scope()) {
+ s->ForceContextAllocation();
+ }
+ {
+ BlockState function_body_state(&scope_, func_scope);
+ SkipLazyFunctionBody(&materialized_literal_count,
+ &expected_property_count, CHECK_OK);
+ }
+ } else {
+ body =
+ DesugarInitializeParameters(scope, has_initializers, initializers);
+ {
+ BlockState function_body_state(&scope_, func_scope);
+ ZoneList<Statement*>* inner_body = ParseEagerFunctionBody(
+ function_name, pos, fvar, fvar_init_op, kind, CHECK_OK);
+ body->AddAll(*inner_body, zone());
+ }
+ materialized_literal_count =
+ function_state.materialized_literal_count();
+ expected_property_count = function_state.expected_property_count();
+ handler_count = function_state.handler_count();
+
+ if (is_strong(language_mode()) && IsSubclassConstructor(kind)) {
+ if (!function_state.super_location().IsValid()) {
+ ReportMessageAt(function_name_location, "strong_super_call_missing",
+ kReferenceError);
+ *ok = false;
+ return nullptr;
+ }
}
}
}
@@ -4244,6 +4379,10 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
return;
}
scope_->set_end_position(logger.end());
+ if (scope_->is_function_body_scope()) {
+ DCHECK(scope_->outer_scope()->is_function_scope());
+ scope_->outer_scope()->set_end_position(scanner()->location().end_pos);
+ }
Expect(Token::RBRACE, ok);
if (!*ok) {
return;
@@ -4352,6 +4491,10 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
Expect(Token::RBRACE, CHECK_OK);
scope_->set_end_position(scanner()->location().end_pos);
+ if (scope_->is_function_body_scope()) {
+ DCHECK(scope_->outer_scope()->is_function_scope());
+ scope_->outer_scope()->set_end_position(scanner()->location().end_pos);
+ }
return body;
}
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698