Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 3b537d237532747898d75b5b2bb9ecc4465b79d5..e36004f334fcd919f85b12c41f17dbee310fdf42 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -873,6 +873,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) { |
@@ -1134,13 +1135,20 @@ 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); |
+ Expression** initializer_ptr = nullptr; |
+ bool** has_initializer_ptr = nullptr; |
+ ParseFormalParameter(scope, &error_locs, initializer_ptr, |
+ has_initializer_ptr, has_rest, &ok); |
} |
if (ok) { |
@@ -2064,6 +2072,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 |
@@ -3522,6 +3535,112 @@ 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 |
+ // 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; |
+ |
+ // All formal parameters have been removed from the scope VariableMap, |
+ // and so Declare() should not be able to fail. |
+ proxy = factory()->NewVariableProxy(Declare(declaration, true, &ok), pos); |
+ DCHECK(ok); |
+ proxy->var()->set_maybe_assigned(); |
rossberg
2015/05/12 14:04:53
Why is this set?
rossberg
2015/05/20 07:41:47
Ping
caitp (gmail)
2015/05/20 11:29:38
Maybe it's not needed, but it reads like it does t
rossberg
2015/05/20 12:33:55
Ah, note that these are initialisations, not assig
|
+ |
+ 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 |
rossberg
2015/05/12 14:04:53
Nit: this comment seems obsolete
|
+ // 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 :: |
@@ -3932,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, |
@@ -4062,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; |
@@ -4164,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()); |
rossberg
2015/05/12 14:04:53
Shouldn't this create a block statement instead?
caitp (gmail)
2015/05/12 14:34:17
Is this for the extra bailout id? I have mostly be
rossberg
2015/05/20 07:41:47
The scope chain needs to be in sync with the conte
|
+ } 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(); |
@@ -4416,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( |