diff --git a/src/parser.cc b/src/parser.cc index 0a18cd9954..5ecda894c1 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -4077,7 +4077,11 @@ void ParserTraits::ParseArrowFunctionFormalParameters( parser_->scope_, parameters->scope); } - AddFormalParameter(parameters, expr, initializer, is_rest); + // TODO(adamk): params_loc.end_pos is not the correct initializer position, + // but it should be conservative enough to trigger hole checks for variables + // referenced in the initializer (if any). + AddFormalParameter(parameters, expr, initializer, params_loc.end_pos, + is_rest); } @@ -4539,7 +4543,15 @@ Block* Parser::BuildParameterInitializationBlock( descriptor.is_const = false; descriptor.needs_init = true; descriptor.declaration_pos = parameter.pattern->position(); + // The position that will be used by the AssignmentExpression + // which copies from the temp parameter to the pattern. + // + // TODO(adamk): Should this be RelocInfo::kNoPosition, since + // it's just copying from a temp var to the real param var? descriptor.initialization_pos = parameter.pattern->position(); + // The initializer position which will end up in, + // Variable::initializer_position(), used for hole check elimination. + int initializer_position = parameter.pattern->position(); Expression* initial_value = factory()->NewVariableProxy(parameters.scope->parameter(i)); if (parameter.initializer != nullptr) { @@ -4554,6 +4566,7 @@ Block* Parser::BuildParameterInitializationBlock( condition, parameter.initializer, initial_value, RelocInfo::kNoPosition); descriptor.initialization_pos = parameter.initializer->position(); + initializer_position = parameter.initializer_end_position; } else if (parameter.is_rest) { // $rest = []; // for (var $argument_index = $rest_index; @@ -4565,7 +4578,6 @@ Block* Parser::BuildParameterInitializationBlock( DCHECK(parameter.pattern->IsVariableProxy()); DCHECK_EQ(i, parameters.params.length() - 1); - int pos = parameter.pattern->position(); Variable* temp_var = parameters.scope->parameter(i); auto empty_values = new (zone()) ZoneList(0, zone()); auto empty_array = factory()->NewArrayLiteral( @@ -4629,8 +4641,6 @@ Block* Parser::BuildParameterInitializationBlock( zone()); init_block->statements()->Add(loop, zone()); - - descriptor.initialization_pos = pos; } Scope* param_scope = scope_; @@ -4649,7 +4659,7 @@ Block* Parser::BuildParameterInitializationBlock( { BlockState block_state(&scope_, param_scope); DeclarationParsingResult::Declaration decl( - parameter.pattern, parameter.pattern->position(), initial_value); + parameter.pattern, initializer_position, initial_value); PatternRewriter::DeclareAndInitializeVariables(param_block, &descriptor, &decl, nullptr, CHECK_OK); } diff --git a/src/parser.h b/src/parser.h index 2bb24a15bd..c912c8f020 100644 --- a/src/parser.h +++ b/src/parser.h @@ -551,12 +551,17 @@ class SingletonLogger; struct ParserFormalParameters : FormalParametersBase { struct Parameter { Parameter(const AstRawString* name, Expression* pattern, - Expression* initializer, bool is_rest) - : name(name), pattern(pattern), initializer(initializer), + Expression* initializer, int initializer_end_position, + bool is_rest) + : name(name), + pattern(pattern), + initializer(initializer), + initializer_end_position(initializer_end_position), is_rest(is_rest) {} const AstRawString* name; Expression* pattern; Expression* initializer; + int initializer_end_position; bool is_rest; bool is_simple() const { return pattern->IsVariableProxy() && initializer == nullptr && !is_rest; @@ -793,9 +798,10 @@ class ParserTraits { V8_INLINE Scope* NewScope(Scope* parent_scope, ScopeType scope_type, FunctionKind kind = kNormalFunction); - V8_INLINE void AddFormalParameter( - ParserFormalParameters* parameters, Expression* pattern, - Expression* initializer, bool is_rest); + V8_INLINE void AddFormalParameter(ParserFormalParameters* parameters, + Expression* pattern, + Expression* initializer, + int initializer_end_position, bool is_rest); V8_INLINE void DeclareFormalParameter( Scope* scope, const ParserFormalParameters::Parameter& parameter, ExpressionClassifier* classifier); @@ -1337,9 +1343,11 @@ Expression* ParserTraits::SpreadCallNew( } -void ParserTraits::AddFormalParameter( - ParserFormalParameters* parameters, - Expression* pattern, Expression* initializer, bool is_rest) { +void ParserTraits::AddFormalParameter(ParserFormalParameters* parameters, + Expression* pattern, + Expression* initializer, + int initializer_end_position, + bool is_rest) { bool is_simple = !is_rest && pattern->IsVariableProxy() && initializer == nullptr; DCHECK(parser_->allow_harmony_destructuring_bind() || @@ -1349,7 +1357,8 @@ void ParserTraits::AddFormalParameter( ? pattern->AsVariableProxy()->raw_name() : parser_->ast_value_factory()->empty_string(); parameters->params.Add( - ParserFormalParameters::Parameter(name, pattern, initializer, is_rest), + ParserFormalParameters::Parameter(name, pattern, initializer, + initializer_end_position, is_rest), parameters->scope->zone()); } diff --git a/src/preparser.h b/src/preparser.h index e36c6bce0d..4a4f1c8831 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -1708,9 +1708,10 @@ class PreParserTraits { return !tag.IsNoTemplateTag(); } - void AddFormalParameter( - PreParserFormalParameters* parameters, PreParserExpression pattern, - PreParserExpression initializer, bool is_rest) { + void AddFormalParameter(PreParserFormalParameters* parameters, + PreParserExpression pattern, + PreParserExpression initializer, + int initializer_end_position, bool is_rest) { ++parameters->arity; } void DeclareFormalParameter(Scope* scope, PreParserIdentifier parameter, @@ -3839,7 +3840,8 @@ void ParserBase::ParseFormalParameter( classifier->RecordNonSimpleParameter(); } - Traits::AddFormalParameter(parameters, pattern, initializer, is_rest); + Traits::AddFormalParameter(parameters, pattern, initializer, + scanner()->location().end_pos, is_rest); } diff --git a/test/message/default-parameter-tdz-arrow.js b/test/message/default-parameter-tdz-arrow.js new file mode 100644 index 0000000000..cad091f8ac --- /dev/null +++ b/test/message/default-parameter-tdz-arrow.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-default-parameters + +((a=-a) => { })(); diff --git a/test/message/default-parameter-tdz-arrow.out b/test/message/default-parameter-tdz-arrow.out new file mode 100644 index 0000000000..7d5f894ef5 --- /dev/null +++ b/test/message/default-parameter-tdz-arrow.out @@ -0,0 +1,6 @@ +*%(basename)s:7: ReferenceError: a is not defined +((a=-a) => { })(); + ^ +ReferenceError: a is not defined + at *%(basename)s:7:6 + at *%(basename)s:7:16 diff --git a/test/message/default-parameter-tdz.js b/test/message/default-parameter-tdz.js new file mode 100644 index 0000000000..ff2a400e09 --- /dev/null +++ b/test/message/default-parameter-tdz.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-default-parameters + +(function(a=+a) { })(); diff --git a/test/message/default-parameter-tdz.out b/test/message/default-parameter-tdz.out new file mode 100644 index 0000000000..8a6d56abae --- /dev/null +++ b/test/message/default-parameter-tdz.out @@ -0,0 +1,6 @@ +*%(basename)s:7: ReferenceError: a is not defined +(function(a=+a) { })(); + ^ +ReferenceError: a is not defined + at *%(basename)s:7:14 + at *%(basename)s:7:21