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

Side by Side Diff: src/parsing/parser.cc

Issue 2520883002: [parser] Fix scopes in rewriting of for-of and destructuring assignments. (Closed)
Patch Set: Remove debug print from test. Created 4 years 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 unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/parsing/parser.h" 5 #include "src/parsing/parser.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/ast/ast-expression-rewriter.h" 10 #include "src/ast/ast-expression-rewriter.h"
(...skipping 4291 matching lines...) Expand 10 before | Expand all | Expand 10 after
4302 const auto& assignments = 4302 const auto& assignments =
4303 function_state_->destructuring_assignments_to_rewrite(); 4303 function_state_->destructuring_assignments_to_rewrite();
4304 for (int i = assignments.length() - 1; i >= 0; --i) { 4304 for (int i = assignments.length() - 1; i >= 0; --i) {
4305 // Rewrite list in reverse, so that nested assignment patterns are rewritten 4305 // Rewrite list in reverse, so that nested assignment patterns are rewritten
4306 // correctly. 4306 // correctly.
4307 const DestructuringAssignment& pair = assignments.at(i); 4307 const DestructuringAssignment& pair = assignments.at(i);
4308 RewritableExpression* to_rewrite = 4308 RewritableExpression* to_rewrite =
4309 pair.assignment->AsRewritableExpression(); 4309 pair.assignment->AsRewritableExpression();
4310 DCHECK_NOT_NULL(to_rewrite); 4310 DCHECK_NOT_NULL(to_rewrite);
4311 if (!to_rewrite->is_rewritten()) { 4311 if (!to_rewrite->is_rewritten()) {
4312 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, 4312 // Since this function is called at the end of parsing the program,
4313 pair.scope); 4313 // pair.scope may already have been removed by FinalizeBlockScope in the
4314 // meantime. In that case, use the first outer non-removed scope.
4315 Scope* scope = pair.scope;
4316 while (scope != nullptr && scope->HasBeenRemoved()) {
Toon Verwaest 2016/11/23 12:20:45 Move to helper function as mentioned before.
4317 scope = scope->outer_scope();
4318 }
4319 DCHECK_NOT_NULL(scope);
4320
4321 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope);
4314 } 4322 }
4315 } 4323 }
4316 } 4324 }
4317 4325
4318 Expression* Parser::RewriteExponentiation(Expression* left, Expression* right, 4326 Expression* Parser::RewriteExponentiation(Expression* left, Expression* right,
4319 int pos) { 4327 int pos) {
4320 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); 4328 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
4321 args->Add(left, zone()); 4329 args->Add(left, zone());
4322 args->Add(right, zone()); 4330 args->Add(right, zone());
4323 return factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos); 4331 return factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
4738 Expression* condition = factory()->NewCompareOperation( 4746 Expression* condition = factory()->NewCompareOperation(
4739 Token::EQ, factory()->NewVariableProxy(var_throw), 4747 Token::EQ, factory()->NewVariableProxy(var_throw),
4740 factory()->NewNullLiteral(nopos), nopos); 4748 factory()->NewNullLiteral(nopos), nopos);
4741 Expression* call = 4749 Expression* call =
4742 NewThrowTypeError(MessageTemplate::kThrowMethodMissing, 4750 NewThrowTypeError(MessageTemplate::kThrowMethodMissing,
4743 ast_value_factory()->empty_string(), nopos); 4751 ast_value_factory()->empty_string(), nopos);
4744 Statement* throw_call = factory()->NewExpressionStatement(call, nopos); 4752 Statement* throw_call = factory()->NewExpressionStatement(call, nopos);
4745 4753
4746 Block* then = factory()->NewBlock(nullptr, 4 + 1, false, nopos); 4754 Block* then = factory()->NewBlock(nullptr, 4 + 1, false, nopos);
4747 BuildIteratorCloseForCompletion( 4755 BuildIteratorCloseForCompletion(
4748 then->statements(), var_iterator, 4756 scope(), then->statements(), var_iterator,
4749 factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos)); 4757 factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos));
4750 then->statements()->Add(throw_call, zone()); 4758 then->statements()->Add(throw_call, zone());
4751 check_throw = factory()->NewIfStatement( 4759 check_throw = factory()->NewIfStatement(
4752 condition, then, factory()->NewEmptyStatement(nopos), nopos); 4760 condition, then, factory()->NewEmptyStatement(nopos), nopos);
4753 } 4761 }
4754 4762
4755 // output = %_Call(iteratorThrow, iterator, input); 4763 // output = %_Call(iteratorThrow, iterator, input);
4756 Statement* call_throw; 4764 Statement* call_throw;
4757 { 4765 {
4758 auto args = new (zone()) ZoneList<Expression*>(3, zone()); 4766 auto args = new (zone()) ZoneList<Expression*>(3, zone());
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
5106 is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call, 5114 is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call,
5107 nopos); 5115 nopos);
5108 } 5116 }
5109 5117
5110 statements->Add(get_return, zone()); 5118 statements->Add(get_return, zone());
5111 statements->Add(check_return, zone()); 5119 statements->Add(check_return, zone());
5112 statements->Add(call_return, zone()); 5120 statements->Add(call_return, zone());
5113 statements->Add(validate_output, zone()); 5121 statements->Add(validate_output, zone());
5114 } 5122 }
5115 5123
5116 void Parser::FinalizeIteratorUse(Variable* completion, Expression* condition, 5124 void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion,
5117 Variable* iter, Block* iterator_use, 5125 Expression* condition, Variable* iter,
5118 Block* target) { 5126 Block* iterator_use, Block* target) {
5119 // 5127 //
5120 // This function adds two statements to [target], corresponding to the 5128 // This function adds two statements to [target], corresponding to the
5121 // following code: 5129 // following code:
5122 // 5130 //
5123 // completion = kNormalCompletion; 5131 // completion = kNormalCompletion;
5124 // try { 5132 // try {
5125 // try { 5133 // try {
5126 // iterator_use 5134 // iterator_use
5127 // } catch(e) { 5135 // } catch(e) {
5128 // if (completion === kAbruptCompletion) completion = kThrowCompletion; 5136 // if (completion === kAbruptCompletion) completion = kThrowCompletion;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
5164 condition, statement, factory()->NewEmptyStatement(nopos), nopos); 5172 condition, statement, factory()->NewEmptyStatement(nopos), nopos);
5165 } 5173 }
5166 5174
5167 // if (condition) { 5175 // if (condition) {
5168 // #BuildIteratorCloseForCompletion(iter, completion) 5176 // #BuildIteratorCloseForCompletion(iter, completion)
5169 // } 5177 // }
5170 Block* maybe_close; 5178 Block* maybe_close;
5171 { 5179 {
5172 Block* block = factory()->NewBlock(nullptr, 2, true, nopos); 5180 Block* block = factory()->NewBlock(nullptr, 2, true, nopos);
5173 Expression* proxy = factory()->NewVariableProxy(completion); 5181 Expression* proxy = factory()->NewVariableProxy(completion);
5174 BuildIteratorCloseForCompletion(block->statements(), iter, proxy); 5182 BuildIteratorCloseForCompletion(use_scope, block->statements(), iter,
5183 proxy);
5175 DCHECK(block->statements()->length() == 2); 5184 DCHECK(block->statements()->length() == 2);
5176 5185
5177 maybe_close = factory()->NewBlock(nullptr, 1, true, nopos); 5186 maybe_close = factory()->NewBlock(nullptr, 1, true, nopos);
5178 maybe_close->statements()->Add( 5187 maybe_close->statements()->Add(
5179 factory()->NewIfStatement(condition, block, 5188 factory()->NewIfStatement(condition, block,
5180 factory()->NewEmptyStatement(nopos), nopos), 5189 factory()->NewEmptyStatement(nopos), nopos),
5181 zone()); 5190 zone());
5182 } 5191 }
5183 5192
5184 // try { #try_block } 5193 // try { #try_block }
5185 // catch(e) { 5194 // catch(e) {
5186 // #set_completion_throw; 5195 // #set_completion_throw;
5187 // %ReThrow(e); 5196 // %ReThrow(e);
5188 // } 5197 // }
5189 Statement* try_catch; 5198 Statement* try_catch;
5190 { 5199 {
5191 Scope* catch_scope = NewScopeWithParent(scope(), CATCH_SCOPE); 5200 Scope* catch_scope = NewScopeWithParent(use_scope, CATCH_SCOPE);
5192 Variable* catch_variable = 5201 Variable* catch_variable =
5193 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, 5202 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
5194 kCreatedInitialized, NORMAL_VARIABLE); 5203 kCreatedInitialized, NORMAL_VARIABLE);
5195 catch_scope->set_is_hidden(); 5204 catch_scope->set_is_hidden();
5196 5205
5197 Statement* rethrow; 5206 Statement* rethrow;
5198 // We use %ReThrow rather than the ordinary throw because we want to 5207 // We use %ReThrow rather than the ordinary throw because we want to
5199 // preserve the original exception message. This is also why we create a 5208 // preserve the original exception message. This is also why we create a
5200 // TryCatchStatementForReThrow below (which does not clear the pending 5209 // TryCatchStatementForReThrow below (which does not clear the pending
5201 // message), rather than a TryCatchStatement. 5210 // message), rather than a TryCatchStatement.
(...skipping 19 matching lines...) Expand all
5221 try_block->statements()->Add(try_catch, zone()); 5230 try_block->statements()->Add(try_catch, zone());
5222 5231
5223 try_finally = 5232 try_finally =
5224 factory()->NewTryFinallyStatement(try_block, maybe_close, nopos); 5233 factory()->NewTryFinallyStatement(try_block, maybe_close, nopos);
5225 } 5234 }
5226 5235
5227 target->statements()->Add(initialize_completion, zone()); 5236 target->statements()->Add(initialize_completion, zone());
5228 target->statements()->Add(try_finally, zone()); 5237 target->statements()->Add(try_finally, zone());
5229 } 5238 }
5230 5239
5231 void Parser::BuildIteratorCloseForCompletion(ZoneList<Statement*>* statements, 5240 void Parser::BuildIteratorCloseForCompletion(Scope* scope,
5241 ZoneList<Statement*>* statements,
5232 Variable* iterator, 5242 Variable* iterator,
5233 Expression* completion) { 5243 Expression* completion) {
5234 // 5244 //
5235 // This function adds two statements to [statements], corresponding to the 5245 // This function adds two statements to [statements], corresponding to the
5236 // following code: 5246 // following code:
5237 // 5247 //
5238 // let iteratorReturn = iterator.return; 5248 // let iteratorReturn = iterator.return;
5239 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { 5249 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
5240 // if (completion === kThrowCompletion) { 5250 // if (completion === kThrowCompletion) {
5241 // if (!IS_CALLABLE(iteratorReturn)) { 5251 // if (!IS_CALLABLE(iteratorReturn)) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
5287 5297
5288 Expression* call = 5298 Expression* call =
5289 factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos); 5299 factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos);
5290 5300
5291 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); 5301 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos);
5292 try_block->statements()->Add(factory()->NewExpressionStatement(call, nopos), 5302 try_block->statements()->Add(factory()->NewExpressionStatement(call, nopos),
5293 zone()); 5303 zone());
5294 5304
5295 Block* catch_block = factory()->NewBlock(nullptr, 0, false, nopos); 5305 Block* catch_block = factory()->NewBlock(nullptr, 0, false, nopos);
5296 5306
5297 Scope* catch_scope = NewScope(CATCH_SCOPE); 5307 Scope* catch_scope = NewScopeWithParent(scope, CATCH_SCOPE);
5298 Variable* catch_variable = 5308 Variable* catch_variable =
5299 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, 5309 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
5300 kCreatedInitialized, NORMAL_VARIABLE); 5310 kCreatedInitialized, NORMAL_VARIABLE);
5301 catch_scope->set_is_hidden(); 5311 catch_scope->set_is_hidden();
5302 5312
5303 try_call_return = factory()->NewTryCatchStatement( 5313 try_call_return = factory()->NewTryCatchStatement(
5304 try_block, catch_scope, catch_variable, catch_block, nopos); 5314 try_block, catch_scope, catch_variable, catch_block, nopos);
5305 } 5315 }
5306 5316
5307 // let output = %_Call(iteratorReturn, iterator); 5317 // let output = %_Call(iteratorReturn, iterator);
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
5424 closing_condition = factory()->NewUnaryOperation( 5434 closing_condition = factory()->NewUnaryOperation(
5425 Token::NOT, factory()->NewBinaryOperation(Token::OR, lhs, rhs, nopos), 5435 Token::NOT, factory()->NewBinaryOperation(Token::OR, lhs, rhs, nopos),
5426 nopos); 5436 nopos);
5427 } 5437 }
5428 5438
5429 Block* final_loop = factory()->NewBlock(nullptr, 2, false, nopos); 5439 Block* final_loop = factory()->NewBlock(nullptr, 2, false, nopos);
5430 { 5440 {
5431 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); 5441 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos);
5432 try_block->statements()->Add(loop, zone()); 5442 try_block->statements()->Add(loop, zone());
5433 5443
5434 FinalizeIteratorUse(var_completion, closing_condition, loop->iterator(), 5444 // The scope in which the parser creates this loop.
5435 try_block, final_loop); 5445 Scope* loop_scope = scope()->outer_scope();
5446 DCHECK_EQ(loop_scope->scope_type(), BLOCK_SCOPE);
5447 DCHECK_EQ(scope()->scope_type(), BLOCK_SCOPE);
5448
5449 FinalizeIteratorUse(loop_scope, var_completion, closing_condition,
5450 loop->iterator(), try_block, final_loop);
5436 } 5451 }
5437 5452
5438 return final_loop; 5453 return final_loop;
5439 } 5454 }
5440 5455
5441 #undef CHECK_OK 5456 #undef CHECK_OK
5442 #undef CHECK_OK_VOID 5457 #undef CHECK_OK_VOID
5443 #undef CHECK_FAILED 5458 #undef CHECK_FAILED
5444 5459
5445 } // namespace internal 5460 } // namespace internal
5446 } // namespace v8 5461 } // namespace v8
OLDNEW
« src/ast/scopes.cc ('K') | « src/parsing/parser.h ('k') | src/parsing/pattern-rewriter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698