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

Unified Diff: src/parser.cc

Issue 1127063003: [es6] implement default parameters via desugaring (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: arv's comments 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') | src/preparser.h » ('J')
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 5e3db128ada4d98a13861b6fcd4bfa37551fdf57..8b68a1dbad498467268702ac7645d6a4300f7a68 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -876,6 +876,7 @@ Parser::Parser(ParseInfo* info)
set_allow_harmony_rest_params(FLAG_harmony_rest_parameters);
set_allow_harmony_spreadcalls(FLAG_harmony_spreadcalls);
set_allow_harmony_destructuring(FLAG_harmony_destructuring);
+ set_allow_harmony_optional_params(FLAG_harmony_optional_params);
set_allow_strong_mode(FLAG_strong_mode);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) {
@@ -1139,13 +1140,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,
wingo 2015/05/11 15:00:48 nit: would be easier to read with named variables
caitp (gmail) 2015/05/11 15:34:24 Acknowledged.
+ &ok);
}
if (ok) {
@@ -2069,6 +2075,11 @@ Variable* Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
}
+void Parser::ShadowParametersForExpressions(Scope* scope) {
+ scope->ShadowParametersForExpressions();
+}
+
+
// Language extension which is only enabled for source files loaded
// through the API's extension mechanism. A native function
// declaration is resolved by looking up the function through a
@@ -3527,6 +3538,109 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
}
+ZoneList<Statement*>* Parser::DesugarInitializeParameters(
+ Scope* scope, bool has_initializers, ZoneList<Expression*>* initializers) {
+ DCHECK(scope->is_function_scope());
+
+ if (has_initializers) {
+ // If hasParameterExpressions for the function is true, each parameter is
wingo 2015/05/11 15:00:48 has_initializers I guess? I know hasParameterExpr
caitp (gmail) 2015/05/11 15:34:24 HasParameterExpressions is also true for Object bi
+ // desugared as follows:
+ //
+ // SingleNameBinding :
+ // let <name> = %_Arguments(<index>);
+ // SingleNameBinding Initializer
+ // let <name> = IS_UNDEFINED(%_Arguments(<index>)) ? <initializer>
+ // : %_Arguments(<index>);
+ //
+ // TODO(caitp, dslomov): support BindingPatterns & rest parameters
+ //
+
+ ShadowParametersForExpressions(scope);
+ ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(0, zone());
+ 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);
+ bool ok = true;
+ proxy = factory()->NewVariableProxy(Declare(declaration, true, &ok), pos);
+ DCHECK(ok);
wingo 2015/05/11 15:00:48 Seems that Declare can only fail for a var redecla
caitp (gmail) 2015/05/11 15:34:24 Acknowledged.
+ 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);
+ }
+ }
+ return body;
+ } else {
+ // If hasParameterExpressions is false, remove the unnecessary parameter
+ // block scopes.
+ ZoneList<Scope*>* scopes = scope->inner_scopes();
+ for (int i = 0; i < scopes->length(); ++i) {
+ Scope* scope = scopes->at(i);
+ DCHECK(scope->is_block_scope());
+ scope->FinalizeBlockScope();
+ }
+ return nullptr;
+ }
+}
+
+
Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
bool* ok) {
// ForStatement ::
@@ -3937,7 +4051,8 @@ void ParserTraits::DeclareArrowFunctionParameters(
parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
bool is_rest = false;
- bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest);
+ int pos = expr->position();
+ bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest, pos);
if (is_duplicate) {
// Arrow function parameter lists are parsed as StrictFormalParameters,
@@ -4067,8 +4182,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
Expect(Token::LPAREN, CHECK_OK);
int start_position = scanner()->location().beg_pos;
scope_->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;
@@ -4169,8 +4288,21 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
}
}
if (!is_lazily_parsed) {
- body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
- kind, CHECK_OK);
+ body = DesugarInitializeParameters(scope, has_initializers, initializers);
+ if (has_initializers) {
+ // TODO(caitp): Function body scope must be a declaration scope
+ Scope* function_body_scope = NewScope(scope, BLOCK_SCOPE);
+ function_body_scope->set_start_position(scope->start_position());
+ function_body_scope->SetScopeName(function_name);
+ BlockState function_body_state(&scope_, function_body_scope);
+ ZoneList<Statement*>* inner_body = ParseEagerFunctionBody(
+ function_name, pos, fvar, fvar_init_op, kind, CHECK_OK);
+ scope->set_end_position(function_body_scope->end_position());
+ body->AddAll(*inner_body, zone());
+ } 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();
@@ -4421,6 +4553,8 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
allow_harmony_spreadcalls());
reusable_preparser_->set_allow_harmony_destructuring(
allow_harmony_destructuring());
+ reusable_preparser_->set_allow_harmony_optional_params(
+ allow_harmony_optional_params());
reusable_preparser_->set_allow_strong_mode(allow_strong_mode());
}
PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | src/preparser.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698