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

Unified Diff: src/parser.cc

Issue 1308123007: [es6] conditionally ignore TDZ semantics for formals (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 3 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
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();
}

Powered by Google App Engine
This is Rietveld 408576698