| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index 7de35fe5d465fbadf3c29fd79a616458f4f8fa18..79b2bdb399deaf3191441b7e78e741f4840fb1e8 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -373,10 +373,12 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
|
| handler_count = function_state.handler_count();
|
| }
|
|
|
| + ZoneList<Expression*>* default_values =
|
| + new (zone()) ZoneList<Expression*>(0, zone());
|
| FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
|
| name, ast_value_factory(), function_scope, body,
|
| materialized_literal_count, expected_property_count, handler_count,
|
| - parameter_count, FunctionLiteral::kNoDuplicateParameters,
|
| + parameter_count, default_values, FunctionLiteral::kNoDuplicateParameters,
|
| FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction,
|
| FunctionLiteral::kNotParenthesized, kind, pos);
|
|
|
| @@ -1039,11 +1041,13 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info, Scope** scope,
|
| }
|
|
|
| if (ok) {
|
| + ZoneList<Expression*>* default_values =
|
| + new (zone()) ZoneList<Expression*>(0, zone());
|
| result = factory()->NewFunctionLiteral(
|
| ast_value_factory()->empty_string(), ast_value_factory(), scope_,
|
| body, function_state.materialized_literal_count(),
|
| function_state.expected_property_count(),
|
| - function_state.handler_count(), 0,
|
| + function_state.handler_count(), 0, default_values,
|
| FunctionLiteral::kNoDuplicateParameters,
|
| FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval,
|
| FunctionLiteral::kNotParenthesized, FunctionKind::kNormalFunction, 0);
|
| @@ -3837,12 +3841,19 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| // nested function, and hoisting works normally relative to that.
|
| Scope* declaration_scope = scope_->DeclarationScope();
|
| Scope* original_declaration_scope = original_scope_->DeclarationScope();
|
| - Scope* scope = function_type == FunctionLiteral::DECLARATION &&
|
| + Scope* env_scope = function_type == FunctionLiteral::DECLARATION &&
|
| is_sloppy(language_mode()) &&
|
| (original_scope_ == original_declaration_scope ||
|
| declaration_scope != original_declaration_scope)
|
| - ? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
|
| - : NewScope(scope_, FUNCTION_SCOPE, kind);
|
| + ? declaration_scope
|
| + : scope_;
|
| + // A separate Environment Record is needed to ensure that closures created by
|
| + // expressions in the formal parameter list do not have visibility of
|
| + // declarations in the function body.
|
| + Scope* param_expressions_scope = NewScope(env_scope, BLOCK_SCOPE);
|
| +
|
| + Scope* scope = NewScope(env_scope, FUNCTION_SCOPE, kind);
|
| +
|
| ZoneList<Statement*>* body = NULL;
|
| int materialized_literal_count = -1;
|
| int expected_property_count = -1;
|
| @@ -3852,12 +3863,17 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_
|
| ? FunctionLiteral::kIsParenthesized
|
| : FunctionLiteral::kNotParenthesized;
|
| +
|
| + ZoneList<Expression*>* param_initializers =
|
| + new (zone()) ZoneList<Expression*>(0, zone());
|
| +
|
| // Parse function body.
|
| {
|
| AstNodeFactory function_factory(ast_value_factory());
|
| FunctionState function_state(&function_state_, &scope_, scope, kind,
|
| &function_factory);
|
| scope_->SetScopeName(function_name);
|
| + param_expressions_scope->SetParameterExpressionsScopeFor(scope_);
|
|
|
| if (is_generator) {
|
| // For generators, allocating variables in contexts is currently a win
|
| @@ -3894,9 +3910,14 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| arity_restriction != FunctionLiteral::SETTER_ARITY);
|
| while (!done) {
|
| bool is_strict_reserved = false;
|
| - is_rest = peek() == Token::ELLIPSIS && allow_harmony_rest_params();
|
| - if (is_rest) {
|
| + int rest_pos;
|
| +
|
| + ParameterKind kind = NormalParameter;
|
| +
|
| + if (peek() == Token::ELLIPSIS && allow_harmony_rest_params()) {
|
| Consume(Token::ELLIPSIS);
|
| + rest_pos = position();
|
| + kind = RestParameter;
|
| }
|
|
|
| const AstRawString* param_name =
|
| @@ -3918,7 +3939,30 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| dupe_loc = scanner()->location();
|
| }
|
|
|
| - Variable* var = scope_->DeclareParameter(param_name, VAR, is_rest);
|
| +
|
| + if (peek() == Token::ASSIGN) {
|
| + // Default parameters:
|
| + Consume(Token::ASSIGN);
|
| + static const bool accept_IN = true;
|
| + Expression* defaultValue = nullptr;
|
| + {
|
| + // Evaluate parameter initializations within context of separate scope
|
| + BlockState state(&scope_, param_expressions_scope);
|
| + defaultValue = ParseAssignmentExpression(accept_IN, CHECK_OK);
|
| + }
|
| + if (kind == RestParameter) {
|
| + ReportMessageAt(
|
| + Scanner::Location(rest_pos, scanner()->location().end_pos),
|
| + "rest_param_default");
|
| + *ok = false;
|
| + return nullptr;
|
| + }
|
| + kind = OptionalParameter;
|
| + param_initializers->Add(defaultValue, zone());
|
| + }
|
| +
|
| + Variable* var = scope_->DeclareParameter(param_name, VAR, kind);
|
| +
|
| if (is_sloppy(scope->language_mode())) {
|
| // TODO(sigurds) Mark every parameter as maybe assigned. This is a
|
| // conservative approximation necessary to account for parameters
|
| @@ -4050,7 +4094,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
|
| function_name, ast_value_factory(), scope, body,
|
| materialized_literal_count, expected_property_count, handler_count,
|
| - num_parameters, duplicate_parameters, function_type,
|
| + num_parameters, param_initializers, duplicate_parameters, function_type,
|
| FunctionLiteral::kIsFunction, parenthesized, kind, pos);
|
| function_literal->set_function_token_position(function_token_pos);
|
|
|
|
|