Home | History | Annotate | Download | only in parsing
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/ast/ast.h"
      6 #include "src/messages.h"
      7 #include "src/parsing/parameter-initializer-rewriter.h"
      8 #include "src/parsing/parser.h"
      9 
     10 namespace v8 {
     11 
     12 namespace internal {
     13 
     14 void Parser::PatternRewriter::DeclareAndInitializeVariables(
     15     Parser* parser, Block* block,
     16     const DeclarationDescriptor* declaration_descriptor,
     17     const DeclarationParsingResult::Declaration* declaration,
     18     ZoneList<const AstRawString*>* names, bool* ok) {
     19   PatternRewriter rewriter;
     20 
     21   DCHECK(block->ignore_completion_value());
     22 
     23   rewriter.scope_ = declaration_descriptor->scope;
     24   rewriter.parser_ = parser;
     25   rewriter.context_ = BINDING;
     26   rewriter.pattern_ = declaration->pattern;
     27   rewriter.initializer_position_ = declaration->initializer_position;
     28   rewriter.block_ = block;
     29   rewriter.descriptor_ = declaration_descriptor;
     30   rewriter.names_ = names;
     31   rewriter.ok_ = ok;
     32   rewriter.recursion_level_ = 0;
     33 
     34   rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer);
     35 }
     36 
     37 
     38 void Parser::PatternRewriter::RewriteDestructuringAssignment(
     39     Parser* parser, RewritableExpression* to_rewrite, Scope* scope) {
     40   DCHECK(!scope->HasBeenRemoved());
     41   DCHECK(!to_rewrite->is_rewritten());
     42 
     43   bool ok = true;
     44 
     45   PatternRewriter rewriter;
     46   rewriter.scope_ = scope;
     47   rewriter.parser_ = parser;
     48   rewriter.context_ = ASSIGNMENT;
     49   rewriter.pattern_ = to_rewrite;
     50   rewriter.block_ = nullptr;
     51   rewriter.descriptor_ = nullptr;
     52   rewriter.names_ = nullptr;
     53   rewriter.ok_ = &ok;
     54   rewriter.recursion_level_ = 0;
     55 
     56   rewriter.RecurseIntoSubpattern(rewriter.pattern_, nullptr);
     57   DCHECK(ok);
     58 }
     59 
     60 
     61 Expression* Parser::PatternRewriter::RewriteDestructuringAssignment(
     62     Parser* parser, Assignment* assignment, Scope* scope) {
     63   DCHECK_NOT_NULL(assignment);
     64   DCHECK_EQ(Token::ASSIGN, assignment->op());
     65   auto to_rewrite = parser->factory()->NewRewritableExpression(assignment);
     66   RewriteDestructuringAssignment(parser, to_rewrite, scope);
     67   return to_rewrite->expression();
     68 }
     69 
     70 
     71 Parser::PatternRewriter::PatternContext
     72 Parser::PatternRewriter::SetAssignmentContextIfNeeded(Expression* node) {
     73   PatternContext old_context = context();
     74   // AssignmentExpressions may occur in the Initializer position of a
     75   // SingleNameBinding. Such expressions should not prompt a change in the
     76   // pattern's context.
     77   if (node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN &&
     78       !IsInitializerContext()) {
     79     set_context(ASSIGNMENT);
     80   }
     81   return old_context;
     82 }
     83 
     84 
     85 Parser::PatternRewriter::PatternContext
     86 Parser::PatternRewriter::SetInitializerContextIfNeeded(Expression* node) {
     87   // Set appropriate initializer context for BindingElement and
     88   // AssignmentElement nodes
     89   PatternContext old_context = context();
     90   bool is_destructuring_assignment =
     91       node->IsRewritableExpression() &&
     92       !node->AsRewritableExpression()->is_rewritten();
     93   bool is_assignment =
     94       node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN;
     95   if (is_destructuring_assignment || is_assignment) {
     96     switch (old_context) {
     97       case BINDING:
     98         set_context(INITIALIZER);
     99         break;
    100       case ASSIGNMENT:
    101         set_context(ASSIGNMENT_INITIALIZER);
    102         break;
    103       default:
    104         break;
    105     }
    106   }
    107   return old_context;
    108 }
    109 
    110 
    111 void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
    112   Expression* value = current_value_;
    113 
    114   if (IsAssignmentContext()) {
    115     // In an assignment context, simply perform the assignment
    116     Assignment* assignment = factory()->NewAssignment(
    117         Token::ASSIGN, pattern, value, pattern->position());
    118     block_->statements()->Add(
    119         factory()->NewExpressionStatement(assignment, pattern->position()),
    120         zone());
    121     return;
    122   }
    123 
    124   descriptor_->scope->RemoveUnresolved(pattern);
    125 
    126   // Declare variable.
    127   // Note that we *always* must treat the initial value via a separate init
    128   // assignment for variables and constants because the value must be assigned
    129   // when the variable is encountered in the source. But the variable/constant
    130   // is declared (and set to 'undefined') upon entering the function within
    131   // which the variable or constant is declared. Only function variables have
    132   // an initial value in the declaration (because they are initialized upon
    133   // entering the function).
    134   const AstRawString* name = pattern->raw_name();
    135   VariableProxy* proxy =
    136       factory()->NewVariableProxy(name, NORMAL_VARIABLE, pattern->position());
    137   Declaration* declaration = factory()->NewVariableDeclaration(
    138       proxy, descriptor_->scope, descriptor_->declaration_pos);
    139   Variable* var = parser_->Declare(
    140       declaration, descriptor_->declaration_kind, descriptor_->mode,
    141       Variable::DefaultInitializationFlag(descriptor_->mode), ok_,
    142       descriptor_->hoist_scope);
    143   if (!*ok_) return;
    144   DCHECK_NOT_NULL(var);
    145   DCHECK(proxy->is_resolved());
    146   DCHECK(initializer_position_ != kNoSourcePosition);
    147   var->set_initializer_position(initializer_position_);
    148 
    149   // TODO(adamk): This should probably be checking hoist_scope.
    150   // Move it to Parser::Declare() to make it easier to test
    151   // the right scope.
    152   Scope* declaration_scope = IsLexicalVariableMode(descriptor_->mode)
    153                                  ? descriptor_->scope
    154                                  : descriptor_->scope->GetDeclarationScope();
    155   if (declaration_scope->num_var() > kMaxNumFunctionLocals) {
    156     parser_->ReportMessage(MessageTemplate::kTooManyVariables);
    157     *ok_ = false;
    158     return;
    159   }
    160   if (names_) {
    161     names_->Add(name, zone());
    162   }
    163 
    164   // If there's no initializer, we're done.
    165   if (value == nullptr) return;
    166 
    167   // A declaration of the form:
    168   //
    169   //    var v = x;
    170   //
    171   // is syntactic sugar for:
    172   //
    173   //    var v; v = x;
    174   //
    175   // In particular, we need to re-lookup 'v' as it may be a different
    176   // 'v' than the 'v' in the declaration (e.g., if we are inside a
    177   // 'with' statement or 'catch' block). Global var declarations
    178   // also need special treatment.
    179   Scope* var_init_scope = descriptor_->scope;
    180 
    181   if (descriptor_->mode == VAR && var_init_scope->is_script_scope()) {
    182     // Global variable declarations must be compiled in a specific
    183     // way. When the script containing the global variable declaration
    184     // is entered, the global variable must be declared, so that if it
    185     // doesn't exist (on the global object itself, see ES5 errata) it
    186     // gets created with an initial undefined value. This is handled
    187     // by the declarations part of the function representing the
    188     // top-level global code; see Runtime::DeclareGlobalVariable. If
    189     // it already exists (in the object or in a prototype), it is
    190     // *not* touched until the variable declaration statement is
    191     // executed.
    192     //
    193     // Executing the variable declaration statement will always
    194     // guarantee to give the global object an own property.
    195     // This way, global variable declarations can shadow
    196     // properties in the prototype chain, but only after the variable
    197     // declaration statement has been executed. This is important in
    198     // browsers where the global object (window) has lots of
    199     // properties defined in prototype objects.
    200 
    201     ZoneList<Expression*>* arguments =
    202         new (zone()) ZoneList<Expression*>(3, zone());
    203     arguments->Add(
    204         factory()->NewStringLiteral(name, descriptor_->declaration_pos),
    205         zone());
    206     arguments->Add(factory()->NewNumberLiteral(var_init_scope->language_mode(),
    207                                                kNoSourcePosition),
    208                    zone());
    209     arguments->Add(value, zone());
    210 
    211     CallRuntime* initialize = factory()->NewCallRuntime(
    212         Runtime::kInitializeVarGlobal, arguments, value->position());
    213     block_->statements()->Add(
    214         factory()->NewExpressionStatement(initialize, initialize->position()),
    215         zone());
    216   } else {
    217     // For 'let' and 'const' declared variables the initialization always
    218     // assigns to the declared variable.
    219     // But for var declarations we need to do a new lookup.
    220     if (descriptor_->mode == VAR) {
    221       proxy = var_init_scope->NewUnresolved(factory(), name);
    222     } else {
    223       DCHECK_NOT_NULL(proxy);
    224       DCHECK_NOT_NULL(proxy->var());
    225     }
    226     // Add break location for destructured sub-pattern.
    227     int pos = IsSubPattern() ? pattern->position() : value->position();
    228     Assignment* assignment =
    229         factory()->NewAssignment(Token::INIT, proxy, value, pos);
    230     block_->statements()->Add(
    231         factory()->NewExpressionStatement(assignment, pos), zone());
    232   }
    233 }
    234 
    235 
    236 Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) {
    237   auto temp = scope()->NewTemporary(ast_value_factory()->empty_string());
    238   if (value != nullptr) {
    239     auto assignment = factory()->NewAssignment(
    240         Token::ASSIGN, factory()->NewVariableProxy(temp), value,
    241         kNoSourcePosition);
    242 
    243     block_->statements()->Add(
    244         factory()->NewExpressionStatement(assignment, kNoSourcePosition),
    245         zone());
    246   }
    247   return temp;
    248 }
    249 
    250 
    251 void Parser::PatternRewriter::VisitRewritableExpression(
    252     RewritableExpression* node) {
    253   // If this is not a destructuring assignment...
    254   if (!IsAssignmentContext()) {
    255     // Mark the node as rewritten to prevent redundant rewriting, and
    256     // perform BindingPattern rewriting
    257     DCHECK(!node->is_rewritten());
    258     node->Rewrite(node->expression());
    259     return Visit(node->expression());
    260   } else if (!node->expression()->IsAssignment()) {
    261     return Visit(node->expression());
    262   }
    263 
    264   if (node->is_rewritten()) return;
    265   DCHECK(IsAssignmentContext());
    266   Assignment* assign = node->expression()->AsAssignment();
    267   DCHECK_NOT_NULL(assign);
    268   DCHECK_EQ(Token::ASSIGN, assign->op());
    269 
    270   auto initializer = assign->value();
    271   auto value = initializer;
    272 
    273   if (IsInitializerContext()) {
    274     // let {<pattern> = <init>} = <value>
    275     //   becomes
    276     // temp = <value>;
    277     // <pattern> = temp === undefined ? <init> : temp;
    278     auto temp_var = CreateTempVar(current_value_);
    279     Expression* is_undefined = factory()->NewCompareOperation(
    280         Token::EQ_STRICT, factory()->NewVariableProxy(temp_var),
    281         factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
    282     value = factory()->NewConditional(is_undefined, initializer,
    283                                       factory()->NewVariableProxy(temp_var),
    284                                       kNoSourcePosition);
    285   }
    286 
    287   PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
    288   int pos = assign->position();
    289   Block* old_block = block_;
    290   block_ = factory()->NewBlock(nullptr, 8, true, pos);
    291   Variable* temp = nullptr;
    292   Expression* pattern = assign->target();
    293   Expression* old_value = current_value_;
    294   current_value_ = value;
    295   if (pattern->IsObjectLiteral()) {
    296     VisitObjectLiteral(pattern->AsObjectLiteral(), &temp);
    297   } else {
    298     DCHECK(pattern->IsArrayLiteral());
    299     VisitArrayLiteral(pattern->AsArrayLiteral(), &temp);
    300   }
    301   DCHECK_NOT_NULL(temp);
    302   current_value_ = old_value;
    303   Expression* expr = factory()->NewDoExpression(block_, temp, pos);
    304   node->Rewrite(expr);
    305   block_ = old_block;
    306   if (block_) {
    307     block_->statements()->Add(factory()->NewExpressionStatement(expr, pos),
    308                               zone());
    309   }
    310   return set_context(old_context);
    311 }
    312 
    313 // When an extra declaration scope needs to be inserted to account for
    314 // a sloppy eval in a default parameter or function body, the expressions
    315 // needs to be in that new inner scope which was added after initial
    316 // parsing.
    317 void Parser::PatternRewriter::RewriteParameterScopes(Expression* expr) {
    318   if (!IsBindingContext()) return;
    319   if (descriptor_->declaration_kind != DeclarationDescriptor::PARAMETER) return;
    320   if (!scope()->is_block_scope()) return;
    321 
    322   DCHECK(scope()->is_declaration_scope());
    323   DCHECK(scope()->outer_scope()->is_function_scope());
    324   DCHECK(scope()->calls_sloppy_eval());
    325 
    326   ReparentParameterExpressionScope(parser_->stack_limit(), expr, scope());
    327 }
    328 
    329 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
    330                                                  Variable** temp_var) {
    331   auto temp = *temp_var = CreateTempVar(current_value_);
    332 
    333   block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
    334 
    335   for (ObjectLiteralProperty* property : *pattern->properties()) {
    336     PatternContext context = SetInitializerContextIfNeeded(property->value());
    337 
    338     // Computed property names contain expressions which might require
    339     // scope rewriting.
    340     if (!property->key()->IsLiteral()) RewriteParameterScopes(property->key());
    341 
    342     RecurseIntoSubpattern(
    343         property->value(),
    344         factory()->NewProperty(factory()->NewVariableProxy(temp),
    345                                property->key(), kNoSourcePosition));
    346     set_context(context);
    347   }
    348 }
    349 
    350 
    351 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
    352   Variable* temp_var = nullptr;
    353   VisitObjectLiteral(node, &temp_var);
    354 }
    355 
    356 
    357 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
    358                                                 Variable** temp_var) {
    359   DCHECK(block_->ignore_completion_value());
    360 
    361   auto temp = *temp_var = CreateTempVar(current_value_);
    362   auto iterator = CreateTempVar(parser_->GetIterator(
    363       factory()->NewVariableProxy(temp), kNoSourcePosition));
    364   auto done =
    365       CreateTempVar(factory()->NewBooleanLiteral(false, kNoSourcePosition));
    366   auto result = CreateTempVar();
    367   auto v = CreateTempVar();
    368   auto completion = CreateTempVar();
    369   auto nopos = kNoSourcePosition;
    370 
    371   // For the purpose of iterator finalization, we temporarily set block_ to a
    372   // new block.  In the main body of this function, we write to block_ (both
    373   // explicitly and implicitly via recursion).  At the end of the function, we
    374   // wrap this new block in a try-finally statement, restore block_ to its
    375   // original value, and add the try-finally statement to block_.
    376   auto target = block_;
    377   block_ = factory()->NewBlock(nullptr, 8, true, nopos);
    378 
    379   Spread* spread = nullptr;
    380   for (Expression* value : *node->values()) {
    381     if (value->IsSpread()) {
    382       spread = value->AsSpread();
    383       break;
    384     }
    385 
    386     PatternContext context = SetInitializerContextIfNeeded(value);
    387 
    388     // if (!done) {
    389     //   done = true;  // If .next, .done or .value throws, don't close.
    390     //   result = IteratorNext(iterator);
    391     //   if (result.done) {
    392     //     v = undefined;
    393     //   } else {
    394     //     v = result.value;
    395     //     done = false;
    396     //   }
    397     // }
    398     Statement* if_not_done;
    399     {
    400       auto result_done = factory()->NewProperty(
    401           factory()->NewVariableProxy(result),
    402           factory()->NewStringLiteral(ast_value_factory()->done_string(),
    403                                       kNoSourcePosition),
    404           kNoSourcePosition);
    405 
    406       auto assign_undefined = factory()->NewAssignment(
    407           Token::ASSIGN, factory()->NewVariableProxy(v),
    408           factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
    409 
    410       auto assign_value = factory()->NewAssignment(
    411           Token::ASSIGN, factory()->NewVariableProxy(v),
    412           factory()->NewProperty(
    413               factory()->NewVariableProxy(result),
    414               factory()->NewStringLiteral(ast_value_factory()->value_string(),
    415                                           kNoSourcePosition),
    416               kNoSourcePosition),
    417           kNoSourcePosition);
    418 
    419       auto unset_done = factory()->NewAssignment(
    420           Token::ASSIGN, factory()->NewVariableProxy(done),
    421           factory()->NewBooleanLiteral(false, kNoSourcePosition),
    422           kNoSourcePosition);
    423 
    424       auto inner_else =
    425           factory()->NewBlock(nullptr, 2, true, kNoSourcePosition);
    426       inner_else->statements()->Add(
    427           factory()->NewExpressionStatement(assign_value, nopos), zone());
    428       inner_else->statements()->Add(
    429           factory()->NewExpressionStatement(unset_done, nopos), zone());
    430 
    431       auto inner_if = factory()->NewIfStatement(
    432           result_done,
    433           factory()->NewExpressionStatement(assign_undefined, nopos),
    434           inner_else, nopos);
    435 
    436       auto next_block =
    437           factory()->NewBlock(nullptr, 3, true, kNoSourcePosition);
    438       next_block->statements()->Add(
    439           factory()->NewExpressionStatement(
    440               factory()->NewAssignment(
    441                   Token::ASSIGN, factory()->NewVariableProxy(done),
    442                   factory()->NewBooleanLiteral(true, nopos), nopos),
    443               nopos),
    444           zone());
    445       next_block->statements()->Add(
    446           factory()->NewExpressionStatement(
    447               parser_->BuildIteratorNextResult(
    448                   factory()->NewVariableProxy(iterator), result,
    449                   kNoSourcePosition),
    450               kNoSourcePosition),
    451           zone());
    452       next_block->statements()->Add(inner_if, zone());
    453 
    454       if_not_done = factory()->NewIfStatement(
    455           factory()->NewUnaryOperation(
    456               Token::NOT, factory()->NewVariableProxy(done), kNoSourcePosition),
    457           next_block, factory()->NewEmptyStatement(kNoSourcePosition),
    458           kNoSourcePosition);
    459     }
    460     block_->statements()->Add(if_not_done, zone());
    461 
    462     if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
    463       {
    464         // completion = kAbruptCompletion;
    465         Expression* proxy = factory()->NewVariableProxy(completion);
    466         Expression* assignment = factory()->NewAssignment(
    467             Token::ASSIGN, proxy,
    468             factory()->NewSmiLiteral(kAbruptCompletion, nopos), nopos);
    469         block_->statements()->Add(
    470             factory()->NewExpressionStatement(assignment, nopos), zone());
    471       }
    472 
    473       RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
    474 
    475       {
    476         // completion = kNormalCompletion;
    477         Expression* proxy = factory()->NewVariableProxy(completion);
    478         Expression* assignment = factory()->NewAssignment(
    479             Token::ASSIGN, proxy,
    480             factory()->NewSmiLiteral(kNormalCompletion, nopos), nopos);
    481         block_->statements()->Add(
    482             factory()->NewExpressionStatement(assignment, nopos), zone());
    483       }
    484     }
    485     set_context(context);
    486   }
    487 
    488   if (spread != nullptr) {
    489     // A spread can only occur as the last component.  It is not handled by
    490     // RecurseIntoSubpattern above.
    491 
    492     // let array = [];
    493     // while (!done) {
    494     //   done = true;  // If .next, .done or .value throws, don't close.
    495     //   result = IteratorNext(iterator);
    496     //   if (!result.done) {
    497     //     %AppendElement(array, result.value);
    498     //     done = false;
    499     //   }
    500     // }
    501 
    502     // let array = [];
    503     Variable* array;
    504     {
    505       auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
    506       array = CreateTempVar(factory()->NewArrayLiteral(
    507           empty_exprs,
    508           // Reuse pattern's literal index - it is unused since there is no
    509           // actual literal allocated.
    510           node->literal_index(), kNoSourcePosition));
    511     }
    512 
    513     // done = true;
    514     Statement* set_done = factory()->NewExpressionStatement(
    515         factory()->NewAssignment(
    516             Token::ASSIGN, factory()->NewVariableProxy(done),
    517             factory()->NewBooleanLiteral(true, nopos), nopos),
    518         nopos);
    519 
    520     // result = IteratorNext(iterator);
    521     Statement* get_next = factory()->NewExpressionStatement(
    522         parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
    523                                          result, nopos),
    524         nopos);
    525 
    526     // %AppendElement(array, result.value);
    527     Statement* append_element;
    528     {
    529       auto args = new (zone()) ZoneList<Expression*>(2, zone());
    530       args->Add(factory()->NewVariableProxy(array), zone());
    531       args->Add(factory()->NewProperty(
    532                     factory()->NewVariableProxy(result),
    533                     factory()->NewStringLiteral(
    534                         ast_value_factory()->value_string(), nopos),
    535                     nopos),
    536                 zone());
    537       append_element = factory()->NewExpressionStatement(
    538           factory()->NewCallRuntime(Runtime::kAppendElement, args, nopos),
    539           nopos);
    540     }
    541 
    542     // done = false;
    543     Statement* unset_done = factory()->NewExpressionStatement(
    544         factory()->NewAssignment(
    545             Token::ASSIGN, factory()->NewVariableProxy(done),
    546             factory()->NewBooleanLiteral(false, nopos), nopos),
    547         nopos);
    548 
    549     // if (!result.done) { #append_element; #unset_done }
    550     Statement* maybe_append_and_unset_done;
    551     {
    552       Expression* result_done =
    553           factory()->NewProperty(factory()->NewVariableProxy(result),
    554                                  factory()->NewStringLiteral(
    555                                      ast_value_factory()->done_string(), nopos),
    556                                  nopos);
    557 
    558       Block* then = factory()->NewBlock(nullptr, 2, true, nopos);
    559       then->statements()->Add(append_element, zone());
    560       then->statements()->Add(unset_done, zone());
    561 
    562       maybe_append_and_unset_done = factory()->NewIfStatement(
    563           factory()->NewUnaryOperation(Token::NOT, result_done, nopos), then,
    564           factory()->NewEmptyStatement(nopos), nopos);
    565     }
    566 
    567     // while (!done) {
    568     //   #set_done;
    569     //   #get_next;
    570     //   #maybe_append_and_unset_done;
    571     // }
    572     WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
    573     {
    574       Expression* condition = factory()->NewUnaryOperation(
    575           Token::NOT, factory()->NewVariableProxy(done), nopos);
    576       Block* body = factory()->NewBlock(nullptr, 3, true, nopos);
    577       body->statements()->Add(set_done, zone());
    578       body->statements()->Add(get_next, zone());
    579       body->statements()->Add(maybe_append_and_unset_done, zone());
    580       loop->Initialize(condition, body);
    581     }
    582 
    583     block_->statements()->Add(loop, zone());
    584     RecurseIntoSubpattern(spread->expression(),
    585                           factory()->NewVariableProxy(array));
    586   }
    587 
    588   Expression* closing_condition = factory()->NewUnaryOperation(
    589       Token::NOT, factory()->NewVariableProxy(done), nopos);
    590 
    591   parser_->FinalizeIteratorUse(scope(), completion, closing_condition, iterator,
    592                                block_, target);
    593   block_ = target;
    594 }
    595 
    596 
    597 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
    598   Variable* temp_var = nullptr;
    599   VisitArrayLiteral(node, &temp_var);
    600 }
    601 
    602 
    603 void Parser::PatternRewriter::VisitAssignment(Assignment* node) {
    604   // let {<pattern> = <init>} = <value>
    605   //   becomes
    606   // temp = <value>;
    607   // <pattern> = temp === undefined ? <init> : temp;
    608   DCHECK_EQ(Token::ASSIGN, node->op());
    609 
    610   auto initializer = node->value();
    611   auto value = initializer;
    612   auto temp = CreateTempVar(current_value_);
    613 
    614   if (IsInitializerContext()) {
    615     Expression* is_undefined = factory()->NewCompareOperation(
    616         Token::EQ_STRICT, factory()->NewVariableProxy(temp),
    617         factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
    618     value = factory()->NewConditional(is_undefined, initializer,
    619                                       factory()->NewVariableProxy(temp),
    620                                       kNoSourcePosition);
    621   }
    622 
    623   // Initializer may have been parsed in the wrong scope.
    624   RewriteParameterScopes(initializer);
    625 
    626   PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
    627   RecurseIntoSubpattern(node->target(), value);
    628   set_context(old_context);
    629 }
    630 
    631 
    632 // =============== AssignmentPattern only ==================
    633 
    634 void Parser::PatternRewriter::VisitProperty(v8::internal::Property* node) {
    635   DCHECK(IsAssignmentContext());
    636   auto value = current_value_;
    637 
    638   Assignment* assignment =
    639       factory()->NewAssignment(Token::ASSIGN, node, value, node->position());
    640 
    641   block_->statements()->Add(
    642       factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
    643 }
    644 
    645 
    646 // =============== UNREACHABLE =============================
    647 
    648 #define NOT_A_PATTERN(Node)                                        \
    649   void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \
    650     UNREACHABLE();                                                 \
    651   }
    652 
    653 NOT_A_PATTERN(BinaryOperation)
    654 NOT_A_PATTERN(Block)
    655 NOT_A_PATTERN(BreakStatement)
    656 NOT_A_PATTERN(Call)
    657 NOT_A_PATTERN(CallNew)
    658 NOT_A_PATTERN(CallRuntime)
    659 NOT_A_PATTERN(CaseClause)
    660 NOT_A_PATTERN(ClassLiteral)
    661 NOT_A_PATTERN(CompareOperation)
    662 NOT_A_PATTERN(Conditional)
    663 NOT_A_PATTERN(ContinueStatement)
    664 NOT_A_PATTERN(CountOperation)
    665 NOT_A_PATTERN(DebuggerStatement)
    666 NOT_A_PATTERN(DoExpression)
    667 NOT_A_PATTERN(DoWhileStatement)
    668 NOT_A_PATTERN(EmptyStatement)
    669 NOT_A_PATTERN(EmptyParentheses)
    670 NOT_A_PATTERN(ExpressionStatement)
    671 NOT_A_PATTERN(ForInStatement)
    672 NOT_A_PATTERN(ForOfStatement)
    673 NOT_A_PATTERN(ForStatement)
    674 NOT_A_PATTERN(FunctionDeclaration)
    675 NOT_A_PATTERN(FunctionLiteral)
    676 NOT_A_PATTERN(IfStatement)
    677 NOT_A_PATTERN(Literal)
    678 NOT_A_PATTERN(NativeFunctionLiteral)
    679 NOT_A_PATTERN(RegExpLiteral)
    680 NOT_A_PATTERN(ReturnStatement)
    681 NOT_A_PATTERN(SloppyBlockFunctionStatement)
    682 NOT_A_PATTERN(Spread)
    683 NOT_A_PATTERN(SuperPropertyReference)
    684 NOT_A_PATTERN(SuperCallReference)
    685 NOT_A_PATTERN(SwitchStatement)
    686 NOT_A_PATTERN(ThisFunction)
    687 NOT_A_PATTERN(Throw)
    688 NOT_A_PATTERN(TryCatchStatement)
    689 NOT_A_PATTERN(TryFinallyStatement)
    690 NOT_A_PATTERN(UnaryOperation)
    691 NOT_A_PATTERN(VariableDeclaration)
    692 NOT_A_PATTERN(WhileStatement)
    693 NOT_A_PATTERN(WithStatement)
    694 NOT_A_PATTERN(Yield)
    695 
    696 #undef NOT_A_PATTERN
    697 }  // namespace internal
    698 }  // namespace v8
    699