| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index 07f842a119b06e9c83fb3ad647e990a1d1cedb0c..202a98ff971b44407c6dfac23e87b33fbe4a3a6c 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -2042,6 +2042,16 @@ Variable* Parser::Declare(Declaration* declaration,
|
| IsLexicalVariableMode(mode)))) {
|
| // Declare the variable in the declaration scope.
|
| var = declaration_scope->LookupLocal(name);
|
| + bool redeclared_parameter =
|
| + var != nullptr &&
|
| + declaration_kind == DeclarationDescriptor::PARAMETER &&
|
| + (is_strict(language_mode()) ||
|
| + !declaration_scope->has_simple_parameters());
|
| + if (redeclared_parameter && var->is_arguments()) {
|
| + var = nullptr;
|
| + redeclared_parameter = false;
|
| + }
|
| +
|
| if (var == NULL) {
|
| // Declare the name.
|
| Variable::Kind kind = Variable::NORMAL;
|
| @@ -2060,7 +2070,8 @@ Variable* Parser::Declare(Declaration* declaration,
|
| } else if (IsLexicalVariableMode(mode) ||
|
| IsLexicalVariableMode(var->mode()) ||
|
| ((mode == CONST_LEGACY || var->mode() == CONST_LEGACY) &&
|
| - !declaration_scope->is_script_scope())) {
|
| + !declaration_scope->is_script_scope()) ||
|
| + redeclared_parameter) {
|
| // The name was declared in this scope before; check for conflicting
|
| // re-declarations. We have a conflict if either of the declarations is
|
| // not a var (in script scope, we also have to ignore legacy const for
|
| @@ -2075,7 +2086,8 @@ Variable* Parser::Declare(Declaration* declaration,
|
| // because the var declaration is hoisted to the function scope where 'x'
|
| // is already bound.
|
| DCHECK(IsDeclaredVariableMode(var->mode()));
|
| - if (is_strict(language_mode()) || allow_harmony_sloppy()) {
|
| + if (is_strict(language_mode()) || allow_harmony_sloppy() ||
|
| + redeclared_parameter) {
|
| // In harmony we treat re-declarations as early errors. See
|
| // ES5 16 for a definition of early errors.
|
| if (declaration_kind == DeclarationDescriptor::NORMAL) {
|
| @@ -4388,6 +4400,14 @@ Block* Parser::BuildParameterInitializationBlock(
|
| const ParserFormalParameters& parameters, bool* ok) {
|
| DCHECK(!parameters.is_simple);
|
| DCHECK(scope_->is_function_scope());
|
| + VariableMode parameter_mode = VAR;
|
| + Token::Value init_op = Token::INIT_VAR;
|
| +
|
| + if (parameters.contains_expressions) {
|
| + parameter_mode = LET;
|
| + init_op = Token::INIT_LET;
|
| + }
|
| +
|
| Block* init_block =
|
| factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
|
| for (int i = 0; i < parameters.params.length(); ++i) {
|
| @@ -4398,12 +4418,12 @@ Block* Parser::BuildParameterInitializationBlock(
|
| descriptor.declaration_scope = scope_;
|
| descriptor.scope = scope_;
|
| descriptor.hoist_scope = nullptr;
|
| - descriptor.mode = LET;
|
| + descriptor.mode = parameter_mode;
|
| descriptor.is_const = false;
|
| descriptor.needs_init = true;
|
| descriptor.declaration_pos = parameter.pattern->position();
|
| descriptor.initialization_pos = parameter.pattern->position();
|
| - descriptor.init_op = Token::INIT_LET;
|
| + descriptor.init_op = init_op;
|
| Expression* initial_value =
|
| factory()->NewVariableProxy(parameters.scope->parameter(i));
|
| if (parameter.initializer != nullptr) {
|
| @@ -4419,11 +4439,14 @@ Block* Parser::BuildParameterInitializationBlock(
|
| RelocInfo::kNoPosition);
|
| descriptor.initialization_pos = parameter.initializer->position();
|
| } else if (parameter.is_rest) {
|
| + // var $arguments_length = %_ArgumentsLength()
|
| // $rest = [];
|
| // for (var $argument_index = $rest_index;
|
| // $argument_index < %_ArgumentsLength();
|
| // ++$argument_index) {
|
| - // %AppendElement($rest, %_Arguments($argument_index));
|
| + // /* TODO: use CreateDataProperty($rest, $argument_index - $rest_index,
|
| + // %_Arguments($argument_index)) */
|
| + // $rest[$argument_index - $rest_index] = $_Arguments($argument_index)
|
| // }
|
| // let <param> = $rest;
|
| DCHECK(parameter.pattern->IsVariableProxy());
|
| @@ -4431,6 +4454,18 @@ Block* Parser::BuildParameterInitializationBlock(
|
|
|
| int pos = parameter.pattern->position();
|
| Variable* temp_var = parameters.scope->parameter(i);
|
| + Variable* arguments_length =
|
| + parameters.scope->NewTemporary(ast_value_factory()->empty_string());
|
| +
|
| + // var $arguments_length = %_ArgumentsLength();
|
| + auto empty_arguments = new (zone()) ZoneList<Expression*>(0, zone());
|
| + auto init_arguments_length = factory()->NewAssignment(
|
| + Token::INIT_VAR, factory()->NewVariableProxy(arguments_length),
|
| + factory()->NewCallRuntime(Runtime::kInlineArgumentsLength,
|
| + empty_arguments, RelocInfo::kNoPosition),
|
| + RelocInfo::kNoPosition);
|
| +
|
| + // $rest = Array($arguments_length && $arguments_length - 1);
|
| auto empty_values = new (zone()) ZoneList<Expression*>(0, zone());
|
| auto empty_array = factory()->NewArrayLiteral(
|
| empty_values, parameters.rest_array_literal_index,
|
| @@ -4440,9 +4475,10 @@ Block* Parser::BuildParameterInitializationBlock(
|
| Token::INIT_VAR, factory()->NewVariableProxy(temp_var), empty_array,
|
| RelocInfo::kNoPosition);
|
|
|
| +
|
| auto loop = factory()->NewForStatement(NULL, RelocInfo::kNoPosition);
|
|
|
| - auto argument_index =
|
| + Variable* argument_index =
|
| parameters.scope->NewTemporary(ast_value_factory()->empty_string());
|
| auto init = factory()->NewExpressionStatement(
|
| factory()->NewAssignment(
|
| @@ -4451,13 +4487,10 @@ Block* Parser::BuildParameterInitializationBlock(
|
| RelocInfo::kNoPosition),
|
| RelocInfo::kNoPosition);
|
|
|
| - auto empty_arguments = new (zone()) ZoneList<Expression*>(0, zone());
|
| -
|
| // $arguments_index < arguments.length
|
| auto cond = factory()->NewCompareOperation(
|
| Token::LT, factory()->NewVariableProxy(argument_index),
|
| - factory()->NewCallRuntime(Runtime::kInlineArgumentsLength,
|
| - empty_arguments, RelocInfo::kNoPosition),
|
| + factory()->NewVariableProxy(arguments_length),
|
| RelocInfo::kNoPosition);
|
|
|
| // ++argument_index
|
| @@ -4471,24 +4504,29 @@ Block* Parser::BuildParameterInitializationBlock(
|
| auto arguments_args = new (zone()) ZoneList<Expression*>(1, zone());
|
| arguments_args->Add(factory()->NewVariableProxy(argument_index), zone());
|
|
|
| - // %AppendElement($rest, %_Arguments($arguments_index))
|
| - auto append_element_args = new (zone()) ZoneList<Expression*>(2, zone());
|
| -
|
| - append_element_args->Add(factory()->NewVariableProxy(temp_var), zone());
|
| - append_element_args->Add(
|
| - factory()->NewCallRuntime(Runtime::kInlineArguments, arguments_args,
|
| - RelocInfo::kNoPosition),
|
| - zone());
|
| -
|
| + // $rest[ $arguments_index - $rest_index ] = %_Arguments($arguments_index)
|
| auto body = factory()->NewExpressionStatement(
|
| - factory()->NewCallRuntime(Runtime::kAppendElement,
|
| - append_element_args,
|
| - RelocInfo::kNoPosition),
|
| + factory()->NewAssignment(
|
| + Token::ASSIGN,
|
| + factory()->NewProperty(
|
| + factory()->NewVariableProxy(temp_var),
|
| + factory()->NewBinaryOperation(
|
| + Token::SUB, factory()->NewVariableProxy(argument_index),
|
| + factory()->NewSmiLiteral(i, RelocInfo::kNoPosition),
|
| + RelocInfo::kNoPosition),
|
| + RelocInfo::kNoPosition),
|
| + factory()->NewCallRuntime(Runtime::kInlineArguments,
|
| + arguments_args, RelocInfo::kNoPosition),
|
| + RelocInfo::kNoPosition),
|
| RelocInfo::kNoPosition);
|
|
|
| loop->Initialize(init, cond, next, body);
|
|
|
| init_block->AddStatement(
|
| + factory()->NewExpressionStatement(init_arguments_length,
|
| + RelocInfo::kNoPosition),
|
| + zone());
|
| + init_block->AddStatement(
|
| factory()->NewExpressionStatement(init_array, RelocInfo::kNoPosition),
|
| zone());
|
|
|
| @@ -4560,13 +4598,17 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
|
| ZoneList<Statement*>* body = result;
|
| Scope* inner_scope = scope_;
|
| Block* inner_block = nullptr;
|
| - if (!parameters.is_simple) {
|
| + if (parameters.contains_expressions) {
|
| inner_scope = NewScope(scope_, BLOCK_SCOPE);
|
| inner_scope->set_is_declaration_scope();
|
| inner_scope->set_start_position(scanner()->location().beg_pos);
|
| inner_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
|
| inner_block->set_scope(inner_scope);
|
| body = inner_block->statements();
|
| + } else if (!parameters.is_simple) {
|
| + Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
|
| + DCHECK_NOT_NULL(init_block);
|
| + result->Add(init_block, zone());
|
| }
|
|
|
| {
|
| @@ -4615,9 +4657,11 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
|
| Expect(Token::RBRACE, CHECK_OK);
|
| scope_->set_end_position(scanner()->location().end_pos);
|
|
|
| - if (!parameters.is_simple) {
|
| + if (parameters.contains_expressions) {
|
| DCHECK_NOT_NULL(inner_scope);
|
| DCHECK_EQ(body, inner_block->statements());
|
| +
|
| + DCHECK_NE(scope_, inner_scope);
|
| scope_->SetLanguageMode(inner_scope->language_mode());
|
| Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
|
| DCHECK_NOT_NULL(init_block);
|
| @@ -4696,7 +4740,7 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
|
| }
|
| PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
|
| language_mode(), function_state_->kind(), scope_->has_simple_parameters(),
|
| - logger, bookmark);
|
| + scope_->has_parameter_expressions(), logger, bookmark);
|
| if (pre_parse_timer_ != NULL) {
|
| pre_parse_timer_->Stop();
|
| }
|
|
|