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