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