Line data Source code
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 : ZoneList<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 209328 : explicit AssignmentElementScope(PatternRewriter* rewriter)
44 : : rewriter_(rewriter), context_(rewriter->context()) {
45 209328 : if (context_ == ASSIGNMENT) rewriter->context_ = ASSIGNMENT_ELEMENT;
46 : }
47 209328 : ~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 9255900 : 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 279648 : Expression* old_value = current_value_;
76 9457762 : current_value_ = value;
77 9535548 : recursion_level_++;
78 9535548 : Visit(pattern);
79 279648 : recursion_level_--;
80 279648 : 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 9269631 : 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 747807 : return parser_->ast_value_factory();
100 : }
101 8907815 : 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 : ZoneList<const AstRawString*>* names_;
112 : Expression* current_value_;
113 : int recursion_level_;
114 : bool* ok_;
115 :
116 19099586 : DEFINE_AST_VISITOR_MEMBERS_WITHOUT_STACKOVERFLOW()
117 : };
118 :
119 9178114 : void Parser::DeclareAndInitializeVariables(
120 : Block* block, const DeclarationDescriptor* declaration_descriptor,
121 : const DeclarationParsingResult::Declaration* declaration,
122 : ZoneList<const AstRawString*>* names, bool* ok) {
123 : PatternRewriter::DeclareAndInitializeVariables(
124 9178114 : this, block, declaration_descriptor, declaration, names, ok);
125 9178116 : }
126 :
127 60912 : void Parser::RewriteDestructuringAssignment(RewritableExpression* to_rewrite) {
128 77786 : PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope());
129 60912 : }
130 :
131 16874 : Expression* Parser::RewriteDestructuringAssignment(Assignment* assignment) {
132 : DCHECK_NOT_NULL(assignment);
133 : DCHECK_EQ(Token::ASSIGN, assignment->op());
134 33748 : auto to_rewrite = factory()->NewRewritableExpression(assignment);
135 : RewriteDestructuringAssignment(to_rewrite);
136 16874 : return to_rewrite->expression();
137 : }
138 :
139 9178114 : void PatternRewriter::DeclareAndInitializeVariables(
140 : Parser* parser, Block* block,
141 : const DeclarationDescriptor* declaration_descriptor,
142 : const Parser::DeclarationParsingResult::Declaration* declaration,
143 : ZoneList<const AstRawString*>* names, bool* ok) {
144 : DCHECK(block->ignore_completion_value());
145 :
146 9178114 : PatternRewriter rewriter(declaration_descriptor->scope, parser, BINDING);
147 9178114 : rewriter.initializer_position_ = declaration->initializer_position;
148 9178114 : rewriter.value_beg_position_ = declaration->value_beg_position;
149 9178114 : rewriter.block_ = block;
150 9178114 : rewriter.descriptor_ = declaration_descriptor;
151 9178114 : rewriter.names_ = names;
152 9178114 : rewriter.ok_ = ok;
153 :
154 : rewriter.RecurseIntoSubpattern(declaration->pattern,
155 9178114 : declaration->initializer);
156 9178116 : }
157 :
158 77786 : 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 77786 : }
166 :
167 58967743 : void PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
168 9269631 : Expression* value = current_value_;
169 :
170 9269631 : if (IsAssignmentContext()) {
171 : // In an assignment context, simply perform the assignment
172 : Assignment* assignment = factory()->NewAssignment(
173 9441778 : Token::ASSIGN, pattern, value, pattern->position());
174 : block_->statements()->Add(
175 60584 : factory()->NewExpressionStatement(assignment, pattern->position()),
176 60584 : zone());
177 1909649 : return;
178 : }
179 :
180 : DCHECK_NOT_NULL(block_);
181 : DCHECK_NOT_NULL(descriptor_);
182 : DCHECK_NOT_NULL(ok_);
183 :
184 9210459 : 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 9209048 : const AstRawString* name = pattern->raw_name();
195 7420568 : VariableProxy* proxy =
196 9209048 : factory()->NewVariableProxy(name, NORMAL_VARIABLE, pattern->position());
197 : Declaration* declaration;
198 17499448 : if (descriptor_->mode == VAR && !descriptor_->scope->is_declaration_scope()) {
199 : DCHECK(descriptor_->scope->is_block_scope() ||
200 : descriptor_->scope->is_with_scope());
201 : declaration = factory()->NewNestedVariableDeclaration(
202 1594470 : proxy, descriptor_->scope, descriptor_->declaration_pos);
203 : } else {
204 : declaration =
205 16823626 : factory()->NewVariableDeclaration(proxy, descriptor_->declaration_pos);
206 : }
207 :
208 : // When an extra declaration scope needs to be inserted to account for
209 : // a sloppy eval in a default parameter or function body, the parameter
210 : // needs to be declared in the function's scope, not in the varblock
211 : // scope which will be used for the initializer expression.
212 : Scope* outer_function_scope = nullptr;
213 9209048 : if (DeclaresParameterContainingSloppyEval()) {
214 1412 : outer_function_scope = descriptor_->scope->outer_scope();
215 : }
216 : Variable* var = parser_->Declare(
217 : declaration, descriptor_->declaration_kind, descriptor_->mode,
218 9209048 : Variable::DefaultInitializationFlag(descriptor_->mode), ok_,
219 18418096 : outer_function_scope);
220 9209049 : if (!*ok_) return;
221 : DCHECK_NOT_NULL(var);
222 : DCHECK(proxy->is_resolved());
223 : DCHECK_NE(initializer_position_, kNoSourcePosition);
224 9162555 : var->set_initializer_position(initializer_position_);
225 :
226 : Scope* declaration_scope =
227 : outer_function_scope != nullptr
228 : ? outer_function_scope
229 9161143 : : (IsLexicalVariableMode(descriptor_->mode)
230 : ? descriptor_->scope
231 18323698 : : descriptor_->scope->GetDeclarationScope());
232 9162555 : if (declaration_scope->num_var() > kMaxNumFunctionLocals) {
233 0 : parser_->ReportMessage(MessageTemplate::kTooManyVariables);
234 0 : *ok_ = false;
235 0 : return;
236 : }
237 9162555 : if (names_) {
238 168230 : names_->Add(name, zone());
239 : }
240 :
241 : // If there's no initializer, we're done.
242 9162555 : if (value == nullptr) return;
243 :
244 7420568 : Scope* var_init_scope = descriptor_->scope;
245 : Parser::MarkLoopVariableAsAssigned(var_init_scope, proxy->var(),
246 7420568 : descriptor_->declaration_kind);
247 :
248 : // A declaration of the form:
249 : //
250 : // var v = x;
251 : //
252 : // is syntactic sugar for:
253 : //
254 : // var v; v = x;
255 : //
256 : // In particular, we need to re-lookup 'v' as it may be a different
257 : // 'v' than the 'v' in the declaration (e.g., if we are inside a
258 : // 'with' statement or 'catch' block). Global var declarations
259 : // also need special treatment.
260 :
261 : // For 'let' and 'const' declared variables the initialization always
262 : // assigns to the declared variable.
263 : // But for var declarations we need to do a new lookup.
264 7420568 : if (descriptor_->mode == VAR) {
265 6540591 : proxy = var_init_scope->NewUnresolved(factory(), name);
266 : } else {
267 : DCHECK_NOT_NULL(proxy);
268 : DCHECK_NOT_NULL(proxy->var());
269 : }
270 : // Add break location for destructured sub-pattern.
271 7420568 : int pos = value_beg_position_;
272 7420568 : if (pos == kNoSourcePosition) {
273 627544 : pos = IsSubPattern() ? pattern->position() : value->position();
274 : }
275 : Assignment* assignment =
276 7420568 : factory()->NewAssignment(Token::INIT, proxy, value, pos);
277 7420567 : block_->statements()->Add(factory()->NewExpressionStatement(assignment, pos),
278 7420567 : zone());
279 : }
280 :
281 2234165 : Variable* PatternRewriter::CreateTempVar(Expression* value) {
282 1128674 : auto temp = scope()->NewTemporary(ast_value_factory()->empty_string());
283 564337 : if (value != nullptr) {
284 : auto assignment = factory()->NewAssignment(
285 368497 : Token::ASSIGN, factory()->NewVariableProxy(temp), value,
286 368497 : kNoSourcePosition);
287 :
288 : block_->statements()->Add(
289 368497 : factory()->NewExpressionStatement(assignment, kNoSourcePosition),
290 368497 : zone());
291 : }
292 564337 : return temp;
293 : }
294 :
295 428924 : void PatternRewriter::VisitRewritableExpression(RewritableExpression* node) {
296 92031 : if (!node->expression()->IsAssignment()) {
297 : // RewritableExpressions are also used for desugaring Spread, which is
298 : // orthogonal to PatternRewriter; just visit the underlying expression.
299 : DCHECK_EQ(AstNode::kArrayLiteral, node->expression()->node_type());
300 16986 : return Visit(node->expression());
301 89290 : } else if (context() != ASSIGNMENT) {
302 : // This is not a destructuring assignment. Mark the node as rewritten to
303 : // prevent redundant rewriting and visit the underlying expression.
304 : DCHECK(!node->is_rewritten());
305 : node->set_rewritten();
306 11504 : return Visit(node->expression());
307 : }
308 :
309 : DCHECK(!node->is_rewritten());
310 : DCHECK_EQ(ASSIGNMENT, context());
311 233358 : Assignment* assign = node->expression()->AsAssignment();
312 : DCHECK_NOT_NULL(assign);
313 : DCHECK_EQ(Token::ASSIGN, assign->op());
314 :
315 77786 : int pos = assign->position();
316 77786 : Block* old_block = block_;
317 77786 : block_ = factory()->NewBlock(8, true);
318 77786 : Variable* temp = nullptr;
319 : Expression* pattern = assign->target();
320 77786 : Expression* old_value = current_value_;
321 77786 : current_value_ = assign->value();
322 77786 : if (pattern->IsObjectLiteral()) {
323 89760 : VisitObjectLiteral(pattern->AsObjectLiteral(), &temp);
324 : } else {
325 : DCHECK(pattern->IsArrayLiteral());
326 65812 : VisitArrayLiteral(pattern->AsArrayLiteral(), &temp);
327 : }
328 : DCHECK_NOT_NULL(temp);
329 77786 : current_value_ = old_value;
330 155572 : Expression* expr = factory()->NewDoExpression(block_, temp, pos);
331 : node->Rewrite(expr);
332 77786 : block_ = old_block;
333 77786 : if (block_) {
334 0 : block_->statements()->Add(factory()->NewExpressionStatement(expr, pos),
335 0 : zone());
336 : }
337 : }
338 :
339 9341869 : bool PatternRewriter::DeclaresParameterContainingSloppyEval() const {
340 : // Need to check for a binding context to make sure we have a descriptor.
341 18512462 : if (IsBindingContext() &&
342 : // Only relevant for parameters.
343 9341869 : descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER &&
344 : // And only when scope is a block scope;
345 : // without eval, it is a function scope.
346 60965 : scope()->is_block_scope()) {
347 : DCHECK(scope()->is_declaration_scope());
348 : DCHECK(scope()->AsDeclarationScope()->calls_sloppy_eval());
349 : DCHECK(scope()->outer_scope()->is_function_scope());
350 : return true;
351 : }
352 :
353 0 : return false;
354 : }
355 :
356 : // When an extra declaration scope needs to be inserted to account for
357 : // a sloppy eval in a default parameter or function body, the expressions
358 : // needs to be in that new inner scope which was added after initial
359 : // parsing.
360 72234 : void PatternRewriter::RewriteParameterScopes(Expression* expr) {
361 71856 : if (DeclaresParameterContainingSloppyEval()) {
362 378 : ReparentExpressionScope(parser_->stack_limit(), expr, scope());
363 : }
364 71856 : }
365 :
366 433219 : void PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
367 364053 : Variable** temp_var) {
368 102057 : auto temp = *temp_var = CreateTempVar(current_value_);
369 :
370 : ZoneList<Expression*>* rest_runtime_callargs = nullptr;
371 102057 : if (pattern->has_rest_property()) {
372 : // non_rest_properties_count = pattern->properties()->length - 1;
373 : // args_length = 1 + non_rest_properties_count because we need to
374 : // pass temp as well to the runtime function.
375 3515 : int args_length = pattern->properties()->length();
376 : rest_runtime_callargs =
377 3515 : new (zone()) ZoneList<Expression*>(args_length, zone());
378 7030 : rest_runtime_callargs->Add(factory()->NewVariableProxy(temp), zone());
379 : }
380 :
381 102057 : block_->statements()->Add(parser_->BuildAssertIsCoercible(temp, pattern),
382 102057 : zone());
383 :
384 331162 : for (ObjectLiteralProperty* property : *pattern->properties()) {
385 : Expression* value;
386 :
387 127048 : if (property->kind() == ObjectLiteralProperty::Kind::SPREAD) {
388 : // var { y, [x++]: a, ...c } = temp
389 : // becomes
390 : // var y = temp.y;
391 : // var temp1 = %ToName(x++);
392 : // var a = temp[temp1];
393 : // var c;
394 : // c = %CopyDataPropertiesWithExcludedProperties(temp, "y", temp1);
395 : value = factory()->NewCallRuntime(
396 : Runtime::kCopyDataPropertiesWithExcludedProperties,
397 3515 : rest_runtime_callargs, kNoSourcePosition);
398 : } else {
399 253566 : Expression* key = property->key();
400 :
401 123533 : if (!key->IsLiteral()) {
402 : // Computed property names contain expressions which might require
403 : // scope rewriting.
404 8351 : RewriteParameterScopes(key);
405 : }
406 :
407 123533 : if (pattern->has_rest_property()) {
408 2985 : Expression* excluded_property = key;
409 :
410 2985 : if (property->is_computed_name()) {
411 : DCHECK(!key->IsPropertyName() || !key->IsNumberLiteral());
412 280 : auto args = new (zone()) ZoneList<Expression*>(1, zone());
413 280 : args->Add(key, zone());
414 : auto to_name_key = CreateTempVar(factory()->NewCallRuntime(
415 280 : Runtime::kToName, args, kNoSourcePosition));
416 560 : key = factory()->NewVariableProxy(to_name_key);
417 560 : excluded_property = factory()->NewVariableProxy(to_name_key);
418 : } else {
419 : DCHECK(key->IsPropertyName() || key->IsNumberLiteral());
420 : }
421 :
422 : DCHECK_NOT_NULL(rest_runtime_callargs);
423 2985 : rest_runtime_callargs->Add(excluded_property, zone());
424 : }
425 :
426 123533 : value = factory()->NewProperty(factory()->NewVariableProxy(temp), key,
427 247066 : kNoSourcePosition);
428 : }
429 :
430 : AssignmentElementScope element_scope(this);
431 : RecurseIntoSubpattern(property->value(), value);
432 : }
433 102057 : }
434 :
435 57177 : void PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
436 57177 : Variable* temp_var = nullptr;
437 57177 : VisitObjectLiteral(node, &temp_var);
438 57177 : }
439 :
440 130560 : void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
441 4101795 : Variable** temp_var) {
442 : DCHECK(block_->ignore_completion_value());
443 :
444 65280 : auto temp = *temp_var = CreateTempVar(current_value_);
445 : auto iterator = CreateTempVar(factory()->NewGetIterator(
446 65280 : factory()->NewVariableProxy(temp), current_value_, IteratorType::kNormal,
447 195840 : current_value_->position()));
448 : auto done =
449 65280 : CreateTempVar(factory()->NewBooleanLiteral(false, kNoSourcePosition));
450 65280 : auto result = CreateTempVar();
451 65280 : auto v = CreateTempVar();
452 65280 : auto completion = CreateTempVar();
453 : auto nopos = kNoSourcePosition;
454 :
455 : // For the purpose of iterator finalization, we temporarily set block_ to a
456 : // new block. In the main body of this function, we write to block_ (both
457 : // explicitly and implicitly via recursion). At the end of the function, we
458 : // wrap this new block in a try-finally statement, restore block_ to its
459 : // original value, and add the try-finally statement to block_.
460 65280 : auto target = block_;
461 65280 : block_ = factory()->NewBlock(8, true);
462 :
463 6815 : Spread* spread = nullptr;
464 215480 : for (Expression* value : *node->values()) {
465 91735 : if (value->IsSpread()) {
466 6815 : spread = value->AsSpread();
467 6815 : break;
468 : }
469 :
470 : // if (!done) {
471 : // done = true; // If .next, .done or .value throws, don't close.
472 : // result = IteratorNext(iterator);
473 : // if (result.done) {
474 : // v = undefined;
475 : // } else {
476 : // v = result.value;
477 : // done = false;
478 : // }
479 : // }
480 : Statement* if_not_done;
481 : {
482 : auto result_done = factory()->NewProperty(
483 84920 : factory()->NewVariableProxy(result),
484 : factory()->NewStringLiteral(ast_value_factory()->done_string(),
485 169840 : kNoSourcePosition),
486 84920 : kNoSourcePosition);
487 :
488 : auto assign_undefined = factory()->NewAssignment(
489 84920 : Token::ASSIGN, factory()->NewVariableProxy(v),
490 169840 : factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
491 :
492 : auto assign_value = factory()->NewAssignment(
493 84920 : Token::ASSIGN, factory()->NewVariableProxy(v),
494 : factory()->NewProperty(
495 84920 : factory()->NewVariableProxy(result),
496 : factory()->NewStringLiteral(ast_value_factory()->value_string(),
497 169840 : kNoSourcePosition),
498 84920 : kNoSourcePosition),
499 84920 : kNoSourcePosition);
500 :
501 : auto unset_done = factory()->NewAssignment(
502 84920 : Token::ASSIGN, factory()->NewVariableProxy(done),
503 84920 : factory()->NewBooleanLiteral(false, kNoSourcePosition),
504 84920 : kNoSourcePosition);
505 :
506 84920 : auto inner_else = factory()->NewBlock(2, true);
507 : inner_else->statements()->Add(
508 169840 : factory()->NewExpressionStatement(assign_value, nopos), zone());
509 : inner_else->statements()->Add(
510 169840 : factory()->NewExpressionStatement(unset_done, nopos), zone());
511 :
512 : auto inner_if = factory()->NewIfStatement(
513 : result_done,
514 84920 : factory()->NewExpressionStatement(assign_undefined, nopos),
515 84920 : inner_else, nopos);
516 :
517 84920 : auto next_block = factory()->NewBlock(3, true);
518 : next_block->statements()->Add(
519 : factory()->NewExpressionStatement(
520 : factory()->NewAssignment(
521 84920 : Token::ASSIGN, factory()->NewVariableProxy(done),
522 169840 : factory()->NewBooleanLiteral(true, nopos), nopos),
523 84920 : nopos),
524 84920 : zone());
525 : next_block->statements()->Add(
526 : factory()->NewExpressionStatement(
527 : parser_->BuildIteratorNextResult(
528 84920 : factory()->NewVariableProxy(iterator), result,
529 : IteratorType::kNormal, kNoSourcePosition),
530 169840 : kNoSourcePosition),
531 84920 : zone());
532 84920 : next_block->statements()->Add(inner_if, zone());
533 :
534 : if_not_done = factory()->NewIfStatement(
535 : factory()->NewUnaryOperation(
536 169840 : Token::NOT, factory()->NewVariableProxy(done), kNoSourcePosition),
537 84920 : next_block, factory()->NewEmptyStatement(kNoSourcePosition),
538 169840 : kNoSourcePosition);
539 : }
540 84920 : block_->statements()->Add(if_not_done, zone());
541 :
542 87560 : if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
543 : {
544 : // completion = kAbruptCompletion;
545 82280 : Expression* proxy = factory()->NewVariableProxy(completion);
546 : Expression* assignment = factory()->NewAssignment(
547 : Token::ASSIGN, proxy,
548 164560 : factory()->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
549 : block_->statements()->Add(
550 164560 : factory()->NewExpressionStatement(assignment, nopos), zone());
551 : }
552 :
553 : {
554 : AssignmentElementScope element_scope(this);
555 82280 : RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
556 : }
557 :
558 : {
559 : // completion = kNormalCompletion;
560 82280 : Expression* proxy = factory()->NewVariableProxy(completion);
561 : Expression* assignment = factory()->NewAssignment(
562 : Token::ASSIGN, proxy,
563 164560 : factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
564 : block_->statements()->Add(
565 164560 : factory()->NewExpressionStatement(assignment, nopos), zone());
566 : }
567 : }
568 : }
569 :
570 65280 : if (spread != nullptr) {
571 : // A spread can only occur as the last component. It is not handled by
572 : // RecurseIntoSubpattern above.
573 :
574 : // let array = [];
575 : // while (!done) {
576 : // done = true; // If .next, .done or .value throws, don't close.
577 : // result = IteratorNext(iterator);
578 : // if (!result.done) {
579 : // %AppendElement(array, result.value);
580 : // done = false;
581 : // }
582 : // }
583 :
584 : // let array = [];
585 : Variable* array;
586 : {
587 6815 : auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
588 : array = CreateTempVar(
589 13630 : factory()->NewArrayLiteral(empty_exprs, kNoSourcePosition));
590 : }
591 :
592 : // done = true;
593 : Statement* set_done = factory()->NewExpressionStatement(
594 : factory()->NewAssignment(
595 6815 : Token::ASSIGN, factory()->NewVariableProxy(done),
596 13630 : factory()->NewBooleanLiteral(true, nopos), nopos),
597 13630 : nopos);
598 :
599 : // result = IteratorNext(iterator);
600 : Statement* get_next = factory()->NewExpressionStatement(
601 6815 : parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
602 : result, IteratorType::kNormal, nopos),
603 20445 : nopos);
604 :
605 : // %AppendElement(array, result.value);
606 : Statement* append_element;
607 : {
608 6815 : auto args = new (zone()) ZoneList<Expression*>(2, zone());
609 13630 : args->Add(factory()->NewVariableProxy(array), zone());
610 : args->Add(factory()->NewProperty(
611 6815 : factory()->NewVariableProxy(result),
612 : factory()->NewStringLiteral(
613 13630 : ast_value_factory()->value_string(), nopos),
614 6815 : nopos),
615 6815 : zone());
616 : append_element = factory()->NewExpressionStatement(
617 6815 : factory()->NewCallRuntime(Runtime::kAppendElement, args, nopos),
618 13630 : nopos);
619 : }
620 :
621 : // done = false;
622 : Statement* unset_done = factory()->NewExpressionStatement(
623 : factory()->NewAssignment(
624 6815 : Token::ASSIGN, factory()->NewVariableProxy(done),
625 13630 : factory()->NewBooleanLiteral(false, nopos), nopos),
626 13630 : nopos);
627 :
628 : // if (!result.done) { #append_element; #unset_done }
629 : Statement* maybe_append_and_unset_done;
630 : {
631 : Expression* result_done =
632 6815 : factory()->NewProperty(factory()->NewVariableProxy(result),
633 : factory()->NewStringLiteral(
634 13630 : ast_value_factory()->done_string(), nopos),
635 6815 : nopos);
636 :
637 6815 : Block* then = factory()->NewBlock(2, true);
638 6815 : then->statements()->Add(append_element, zone());
639 6815 : then->statements()->Add(unset_done, zone());
640 :
641 : maybe_append_and_unset_done = factory()->NewIfStatement(
642 6815 : factory()->NewUnaryOperation(Token::NOT, result_done, nopos), then,
643 20445 : factory()->NewEmptyStatement(nopos), nopos);
644 : }
645 :
646 : // while (!done) {
647 : // #set_done;
648 : // #get_next;
649 : // #maybe_append_and_unset_done;
650 : // }
651 6815 : WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
652 : {
653 : Expression* condition = factory()->NewUnaryOperation(
654 13630 : Token::NOT, factory()->NewVariableProxy(done), nopos);
655 6815 : Block* body = factory()->NewBlock(3, true);
656 6815 : body->statements()->Add(set_done, zone());
657 6815 : body->statements()->Add(get_next, zone());
658 6815 : body->statements()->Add(maybe_append_and_unset_done, zone());
659 : loop->Initialize(condition, body);
660 : }
661 :
662 6815 : block_->statements()->Add(loop, zone());
663 : RecurseIntoSubpattern(spread->expression(),
664 6815 : factory()->NewVariableProxy(array));
665 : }
666 :
667 : Expression* closing_condition = factory()->NewUnaryOperation(
668 130560 : Token::NOT, factory()->NewVariableProxy(done), nopos);
669 :
670 : parser_->FinalizeIteratorUse(completion, closing_condition, iterator, block_,
671 65280 : target, IteratorType::kNormal);
672 65280 : block_ = target;
673 65280 : }
674 :
675 32374 : void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
676 32374 : Variable* temp_var = nullptr;
677 32374 : VisitArrayLiteral(node, &temp_var);
678 32374 : }
679 :
680 444535 : void PatternRewriter::VisitAssignment(Assignment* node) {
681 : // let {<pattern> = <init>} = <value>
682 : // becomes
683 : // temp = <value>;
684 : // <pattern> = temp === undefined ? <init> : temp;
685 : DCHECK_EQ(Token::ASSIGN, node->op());
686 :
687 : // Rewriting of Assignment nodes for destructuring assignment
688 : // is handled in VisitRewritableExpression().
689 : DCHECK_NE(ASSIGNMENT, context());
690 :
691 : auto initializer = node->value();
692 : auto value = initializer;
693 63505 : auto temp = CreateTempVar(current_value_);
694 :
695 : Expression* is_undefined = factory()->NewCompareOperation(
696 63505 : Token::EQ_STRICT, factory()->NewVariableProxy(temp),
697 127010 : factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
698 : value = factory()->NewConditional(is_undefined, initializer,
699 63505 : factory()->NewVariableProxy(temp),
700 63505 : kNoSourcePosition);
701 :
702 : // Initializer may have been parsed in the wrong scope.
703 63505 : RewriteParameterScopes(initializer);
704 :
705 : RecurseIntoSubpattern(node->target(), value);
706 63505 : }
707 :
708 :
709 : // =============== AssignmentPattern only ==================
710 :
711 105225 : void PatternRewriter::VisitProperty(v8::internal::Property* node) {
712 : DCHECK(IsAssignmentContext());
713 35075 : auto value = current_value_;
714 :
715 : Assignment* assignment =
716 70150 : factory()->NewAssignment(Token::ASSIGN, node, value, node->position());
717 :
718 : block_->statements()->Add(
719 70150 : factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
720 35075 : }
721 :
722 :
723 : // =============== UNREACHABLE =============================
724 :
725 : #define NOT_A_PATTERN(Node) \
726 : void PatternRewriter::Visit##Node(v8::internal::Node*) { UNREACHABLE(); }
727 :
728 0 : NOT_A_PATTERN(BinaryOperation)
729 0 : NOT_A_PATTERN(Block)
730 0 : NOT_A_PATTERN(BreakStatement)
731 0 : NOT_A_PATTERN(Call)
732 0 : NOT_A_PATTERN(CallNew)
733 0 : NOT_A_PATTERN(CallRuntime)
734 0 : NOT_A_PATTERN(ClassLiteral)
735 0 : NOT_A_PATTERN(CompareOperation)
736 0 : NOT_A_PATTERN(CompoundAssignment)
737 0 : NOT_A_PATTERN(Conditional)
738 0 : NOT_A_PATTERN(ContinueStatement)
739 0 : NOT_A_PATTERN(CountOperation)
740 0 : NOT_A_PATTERN(DebuggerStatement)
741 0 : NOT_A_PATTERN(DoExpression)
742 0 : NOT_A_PATTERN(DoWhileStatement)
743 0 : NOT_A_PATTERN(EmptyStatement)
744 0 : NOT_A_PATTERN(EmptyParentheses)
745 0 : NOT_A_PATTERN(ExpressionStatement)
746 0 : NOT_A_PATTERN(ForInStatement)
747 0 : NOT_A_PATTERN(ForOfStatement)
748 0 : NOT_A_PATTERN(ForStatement)
749 0 : NOT_A_PATTERN(FunctionDeclaration)
750 0 : NOT_A_PATTERN(FunctionLiteral)
751 0 : NOT_A_PATTERN(GetIterator)
752 0 : NOT_A_PATTERN(GetTemplateObject)
753 0 : NOT_A_PATTERN(IfStatement)
754 0 : NOT_A_PATTERN(ImportCallExpression)
755 0 : NOT_A_PATTERN(Literal)
756 0 : NOT_A_PATTERN(NativeFunctionLiteral)
757 0 : NOT_A_PATTERN(RegExpLiteral)
758 0 : NOT_A_PATTERN(ReturnStatement)
759 0 : NOT_A_PATTERN(SloppyBlockFunctionStatement)
760 0 : NOT_A_PATTERN(Spread)
761 0 : NOT_A_PATTERN(SuperPropertyReference)
762 0 : NOT_A_PATTERN(SuperCallReference)
763 0 : NOT_A_PATTERN(SwitchStatement)
764 0 : NOT_A_PATTERN(ThisFunction)
765 0 : NOT_A_PATTERN(Throw)
766 0 : NOT_A_PATTERN(TryCatchStatement)
767 0 : NOT_A_PATTERN(TryFinallyStatement)
768 0 : NOT_A_PATTERN(UnaryOperation)
769 0 : NOT_A_PATTERN(VariableDeclaration)
770 0 : NOT_A_PATTERN(WhileStatement)
771 0 : NOT_A_PATTERN(WithStatement)
772 0 : NOT_A_PATTERN(Yield)
773 0 : NOT_A_PATTERN(YieldStar)
774 0 : NOT_A_PATTERN(Await)
775 :
776 : #undef NOT_A_PATTERN
777 : } // namespace internal
778 : } // namespace v8
|