5 #include "src/ast/ast.h" 6 #include "src/message-template.h" 7 #include "src/objects-inl.h" 8 #include "src/parsing/expression-scope-reparenter.h" 9 #include "src/parsing/parser.h" 24 static const int kMaxNumFunctionLocals = 4194303;
26 typedef Parser::DeclarationDescriptor DeclarationDescriptor;
28 static void DeclareAndInitializeVariables(
30 const DeclarationDescriptor* declaration_descriptor,
31 const Parser::DeclarationParsingResult::Declaration* declaration,
39 enum PatternContext : uint8_t { BINDING, ASSIGNMENT };
42 const DeclarationDescriptor* descriptor =
nullptr,
44 int initializer_position = kNoSourcePosition,
45 int value_beg_position = kNoSourcePosition,
46 bool declares_parameter_containing_sloppy_eval =
false)
50 descriptor_(descriptor),
52 current_value_(
nullptr),
53 initializer_position_(initializer_position),
54 value_beg_position_(value_beg_position),
56 declares_parameter_containing_sloppy_eval_(
57 declares_parameter_containing_sloppy_eval),
58 recursion_level_(0) {}
60 #define DECLARE_VISIT(type) void Visit##type(v8::internal::type* node); 62 AST_NODE_LIST(DECLARE_VISIT)
65 PatternContext context()
const {
return context_; }
69 current_value_ = value;
73 current_value_ = old_value;
77 if (parser_->has_error())
return parser_->FailureExpression();
78 DCHECK_EQ(Token::ASSIGN, assign->op());
80 int pos = assign->position();
82 block_ = factory()->NewBlock(8,
true);
86 current_value_ = assign->value();
87 if (pattern->IsObjectLiteral()) {
88 VisitObjectLiteral(pattern->AsObjectLiteral(), &temp);
90 DCHECK(pattern->IsArrayLiteral());
91 VisitArrayLiteral(pattern->AsArrayLiteral(), &temp);
93 DCHECK_NOT_NULL(temp);
94 current_value_ = old_value;
95 return factory()->NewDoExpression(block_, temp, pos);
101 bool IsBindingContext()
const {
return context_ == BINDING; }
102 bool IsAssignmentContext()
const {
return context_ == ASSIGNMENT; }
103 bool IsSubPattern()
const {
return recursion_level_ > 1; }
105 void RewriteParameterScopes(
Expression* expr);
111 return parser_->ast_value_factory();
114 std::vector<void*>* pointer_buffer() {
return parser_->pointer_buffer(); }
116 Zone* zone()
const {
return parser_->zone(); }
117 Scope* scope()
const {
return scope_; }
122 const DeclarationDescriptor* descriptor_;
125 const int initializer_position_;
126 const int value_beg_position_;
127 PatternContext context_;
128 const bool declares_parameter_containing_sloppy_eval_ : 1;
129 int recursion_level_;
131 DEFINE_AST_VISITOR_MEMBERS_WITHOUT_STACKOVERFLOW()
134 void Parser::DeclareAndInitializeVariables(
135 Block* block,
const DeclarationDescriptor* declaration_descriptor,
136 const DeclarationParsingResult::Declaration* declaration,
138 if (has_error())
return;
139 PatternRewriter::DeclareAndInitializeVariables(
140 this, block, declaration_descriptor, declaration, names);
143 void Parser::RewriteDestructuringAssignment(RewritableExpression* to_rewrite) {
144 DCHECK(!to_rewrite->is_rewritten());
145 Assignment* assignment = to_rewrite->expression()->AsAssignment();
146 Expression* result = PatternRewriter::RewriteDestructuringAssignment(
147 this, assignment, scope());
148 to_rewrite->Rewrite(result);
151 Expression* Parser::RewriteDestructuringAssignment(Assignment* assignment) {
152 DCHECK_NOT_NULL(assignment);
153 DCHECK_EQ(Token::ASSIGN, assignment->op());
154 return PatternRewriter::RewriteDestructuringAssignment(
this, assignment,
158 void PatternRewriter::DeclareAndInitializeVariables(
159 Parser* parser, Block* block,
160 const DeclarationDescriptor* declaration_descriptor,
161 const Parser::DeclarationParsingResult::Declaration* declaration,
162 ZonePtrList<const AstRawString>* names) {
163 DCHECK(block->ignore_completion_value());
165 Scope* scope = declaration_descriptor->scope;
166 PatternRewriter rewriter(scope, parser, BINDING, declaration_descriptor,
167 names, declaration->initializer_position,
168 declaration->value_beg_position,
169 declaration_descriptor->declaration_kind ==
170 DeclarationDescriptor::PARAMETER &&
171 scope->is_block_scope());
172 rewriter.block_ = block;
174 rewriter.RecurseIntoSubpattern(declaration->pattern,
175 declaration->initializer);
178 Expression* PatternRewriter::RewriteDestructuringAssignment(
179 Parser* parser, Assignment* to_rewrite, Scope* scope) {
180 DCHECK(!scope->HasBeenRemoved());
182 PatternRewriter rewriter(scope, parser, ASSIGNMENT);
183 return rewriter.Rewrite(to_rewrite);
186 void PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
187 Expression* value = current_value_;
189 if (IsAssignmentContext()) {
191 Assignment* assignment = factory()->NewAssignment(
192 Token::ASSIGN, pattern, value, pattern->position());
193 block_->statements()->Add(
194 factory()->NewExpressionStatement(assignment, pattern->position()),
199 DCHECK_NOT_NULL(block_);
200 DCHECK_NOT_NULL(descriptor_);
202 Scope* outer_function_scope =
nullptr;
203 if (declares_parameter_containing_sloppy_eval_) {
204 outer_function_scope = scope()->outer_scope();
205 outer_function_scope->DeleteUnresolved(pattern);
207 scope()->DeleteUnresolved(pattern);
218 const AstRawString* name = pattern->raw_name();
219 VariableProxy* proxy = pattern;
220 Declaration* declaration;
221 if (descriptor_->mode == VariableMode::kVar &&
222 !scope()->is_declaration_scope()) {
223 DCHECK(scope()->is_block_scope() || scope()->is_with_scope());
224 declaration = factory()->NewNestedVariableDeclaration(
225 proxy, scope(), descriptor_->declaration_pos);
228 factory()->NewVariableDeclaration(proxy, descriptor_->declaration_pos);
235 Variable* var = parser_->Declare(
236 declaration, descriptor_->declaration_kind, descriptor_->mode,
237 Variable::DefaultInitializationFlag(descriptor_->mode),
238 outer_function_scope);
239 if (parser_->has_error())
return;
240 DCHECK_NOT_NULL(var);
241 DCHECK(proxy->is_resolved());
242 DCHECK_NE(initializer_position_, kNoSourcePosition);
243 var->set_initializer_position(initializer_position_);
245 Scope* declaration_scope = outer_function_scope !=
nullptr 246 ? outer_function_scope
247 : (IsLexicalVariableMode(descriptor_->mode)
249 : scope()->GetDeclarationScope());
250 if (declaration_scope->num_var() > kMaxNumFunctionLocals) {
251 parser_->ReportMessage(MessageTemplate::kTooManyVariables);
255 names_->Add(name, zone());
259 if (value ==
nullptr)
return;
261 Scope* var_init_scope = scope();
262 Parser::MarkLoopVariableAsAssigned(var_init_scope, proxy->var(),
263 descriptor_->declaration_kind);
280 if (descriptor_->mode == VariableMode::kVar &&
281 var_init_scope != declaration_scope) {
282 proxy = var_init_scope->NewUnresolved(factory(), name);
284 DCHECK_NOT_NULL(proxy);
285 DCHECK_NOT_NULL(proxy->var());
288 int pos = value_beg_position_;
289 if (pos == kNoSourcePosition) {
290 pos = IsSubPattern() ? pattern->position() : value->position();
292 Assignment* assignment =
293 factory()->NewAssignment(Token::INIT, proxy, value, pos);
294 block_->statements()->Add(factory()->NewExpressionStatement(assignment, pos),
298 Variable* PatternRewriter::CreateTempVar(Expression* value) {
299 auto temp = scope()->NewTemporary(ast_value_factory()->empty_string());
300 if (value !=
nullptr) {
301 auto assignment = factory()->NewAssignment(
302 Token::ASSIGN, factory()->NewVariableProxy(temp), value,
305 block_->statements()->Add(
306 factory()->NewExpressionStatement(assignment, kNoSourcePosition),
312 void PatternRewriter::VisitRewritableExpression(RewritableExpression* node) {
313 DCHECK(node->expression()->IsAssignment());
317 DCHECK(!node->is_rewritten());
318 node->set_rewritten();
319 return Visit(node->expression());
326 void PatternRewriter::RewriteParameterScopes(Expression* expr) {
327 if (declares_parameter_containing_sloppy_eval_) {
328 ReparentExpressionScope(parser_->stack_limit(), expr, scope());
332 void PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
333 Variable** temp_var) {
334 auto temp = *temp_var = CreateTempVar(current_value_);
336 ScopedPtrList<Expression> rest_runtime_callargs(pointer_buffer());
337 if (pattern->has_rest_property()) {
338 rest_runtime_callargs.Add(factory()->NewVariableProxy(temp));
341 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp, pattern),
344 for (ObjectLiteralProperty* property : *pattern->properties()) {
347 if (property->kind() == ObjectLiteralProperty::Kind::SPREAD) {
355 value = factory()->NewCallRuntime(
356 Runtime::kCopyDataPropertiesWithExcludedProperties,
357 rest_runtime_callargs, kNoSourcePosition);
359 Expression* key =
property->key();
361 if (!key->IsLiteral()) {
364 RewriteParameterScopes(key);
367 if (pattern->has_rest_property()) {
368 Expression* excluded_property = key;
370 if (property->is_computed_name()) {
371 DCHECK(!key->IsPropertyName() || !key->IsNumberLiteral());
372 ScopedPtrList<Expression> args(pointer_buffer());
374 auto to_name_key = CreateTempVar(factory()->NewCallRuntime(
375 Runtime::kToName, args, kNoSourcePosition));
376 key = factory()->NewVariableProxy(to_name_key);
377 excluded_property = factory()->NewVariableProxy(to_name_key);
379 DCHECK(key->IsPropertyName() || key->IsNumberLiteral());
382 rest_runtime_callargs.Add(excluded_property);
385 value = factory()->NewProperty(factory()->NewVariableProxy(temp), key,
389 RecurseIntoSubpattern(property->value(), value);
393 void PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
394 Variable* temp_var =
nullptr;
395 VisitObjectLiteral(node, &temp_var);
398 void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
399 Variable** temp_var) {
400 DCHECK(block_->ignore_completion_value());
402 auto temp = *temp_var = CreateTempVar(current_value_);
403 auto iterator = CreateTempVar(factory()->NewGetIterator(
404 factory()->NewVariableProxy(temp), current_value_, IteratorType::kNormal,
405 current_value_->position()));
406 auto next = CreateTempVar(factory()->NewProperty(
407 factory()->NewVariableProxy(iterator),
408 factory()->NewStringLiteral(ast_value_factory()->next_string(),
412 CreateTempVar(factory()->NewBooleanLiteral(
false, kNoSourcePosition));
413 auto result = CreateTempVar();
414 auto v = CreateTempVar();
415 auto completion = CreateTempVar();
416 auto nopos = kNoSourcePosition;
423 auto target = block_;
424 block_ = factory()->NewBlock(8,
true);
426 Spread* spread =
nullptr;
427 for (Expression* value : *node->values()) {
428 if (value->IsSpread()) {
429 spread = value->AsSpread();
443 Statement* if_not_done;
445 auto result_done = factory()->NewProperty(
446 factory()->NewVariableProxy(result),
447 factory()->NewStringLiteral(ast_value_factory()->done_string(),
451 auto assign_undefined = factory()->NewAssignment(
452 Token::ASSIGN, factory()->NewVariableProxy(v),
453 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
455 auto assign_value = factory()->NewAssignment(
456 Token::ASSIGN, factory()->NewVariableProxy(v),
457 factory()->NewProperty(
458 factory()->NewVariableProxy(result),
459 factory()->NewStringLiteral(ast_value_factory()->value_string(),
464 auto unset_done = factory()->NewAssignment(
465 Token::ASSIGN, factory()->NewVariableProxy(done),
466 factory()->NewBooleanLiteral(
false, kNoSourcePosition),
469 auto inner_else = factory()->NewBlock(2,
true);
470 inner_else->statements()->Add(
471 factory()->NewExpressionStatement(assign_value, nopos), zone());
472 inner_else->statements()->Add(
473 factory()->NewExpressionStatement(unset_done, nopos), zone());
475 auto inner_if = factory()->NewIfStatement(
477 factory()->NewExpressionStatement(assign_undefined, nopos),
480 auto next_block = factory()->NewBlock(3,
true);
481 next_block->statements()->Add(
482 factory()->NewExpressionStatement(
483 factory()->NewAssignment(
484 Token::ASSIGN, factory()->NewVariableProxy(done),
485 factory()->NewBooleanLiteral(
true, nopos), nopos),
488 next_block->statements()->Add(
489 factory()->NewExpressionStatement(
490 parser_->BuildIteratorNextResult(
491 factory()->NewVariableProxy(iterator),
492 factory()->NewVariableProxy(next), result,
493 IteratorType::kNormal, kNoSourcePosition),
496 next_block->statements()->Add(inner_if, zone());
498 if_not_done = factory()->NewIfStatement(
499 factory()->NewUnaryOperation(
500 Token::NOT, factory()->NewVariableProxy(done), kNoSourcePosition),
501 next_block, factory()->EmptyStatement(), kNoSourcePosition);
503 block_->statements()->Add(if_not_done, zone());
505 if (!value->IsTheHoleLiteral()) {
508 Expression* proxy = factory()->NewVariableProxy(completion);
509 Expression* assignment = factory()->NewAssignment(
510 Token::ASSIGN, proxy,
511 factory()->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
512 block_->statements()->Add(
513 factory()->NewExpressionStatement(assignment, nopos), zone());
516 RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
520 Expression* proxy = factory()->NewVariableProxy(completion);
521 Expression* assignment = factory()->NewAssignment(
522 Token::ASSIGN, proxy,
523 factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
524 block_->statements()->Add(
525 factory()->NewExpressionStatement(assignment, nopos), zone());
530 if (spread !=
nullptr) {
549 ScopedPtrList<Expression> empty_exprs(pointer_buffer());
550 array = CreateTempVar(
551 factory()->NewArrayLiteral(empty_exprs, kNoSourcePosition));
556 CreateTempVar(factory()->NewSmiLiteral(0, kNoSourcePosition));
559 Statement* set_done = factory()->NewExpressionStatement(
560 factory()->NewAssignment(
561 Token::ASSIGN, factory()->NewVariableProxy(done),
562 factory()->NewBooleanLiteral(
true, nopos), nopos),
566 Statement* get_next = factory()->NewExpressionStatement(
567 parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
568 factory()->NewVariableProxy(next),
569 result, IteratorType::kNormal, nopos),
575 auto value = factory()->NewProperty(
576 factory()->NewVariableProxy(result),
577 factory()->NewStringLiteral(ast_value_factory()->value_string(),
580 store = factory()->NewExpressionStatement(
581 factory()->NewStoreInArrayLiteral(factory()->NewVariableProxy(array),
582 factory()->NewVariableProxy(index),
588 Statement* unset_done = factory()->NewExpressionStatement(
589 factory()->NewAssignment(
590 Token::ASSIGN, factory()->NewVariableProxy(done),
591 factory()->NewBooleanLiteral(
false, nopos), nopos),
595 Statement* maybe_store_and_unset_done;
597 Expression* result_done =
598 factory()->NewProperty(factory()->NewVariableProxy(result),
599 factory()->NewStringLiteral(
600 ast_value_factory()->done_string(), nopos),
603 Block* then = factory()->NewBlock(2,
true);
604 then->statements()->Add(store, zone());
605 then->statements()->Add(unset_done, zone());
607 maybe_store_and_unset_done = factory()->NewIfStatement(
608 factory()->NewUnaryOperation(Token::NOT, result_done, nopos), then,
609 factory()->EmptyStatement(), nopos);
613 Statement* increment_index;
615 increment_index = factory()->NewExpressionStatement(
616 factory()->NewCountOperation(
617 Token::INC,
false, factory()->NewVariableProxy(index), nopos),
627 WhileStatement* loop =
628 factory()->NewWhileStatement(
nullptr,
nullptr, nopos);
630 Expression* condition = factory()->NewUnaryOperation(
631 Token::NOT, factory()->NewVariableProxy(done), nopos);
632 Block* body = factory()->NewBlock(4,
true);
633 body->statements()->Add(set_done, zone());
634 body->statements()->Add(get_next, zone());
635 body->statements()->Add(maybe_store_and_unset_done, zone());
636 body->statements()->Add(increment_index, zone());
637 loop->Initialize(condition, body);
640 block_->statements()->Add(loop, zone());
641 RecurseIntoSubpattern(spread->expression(),
642 factory()->NewVariableProxy(array));
645 Expression* closing_condition = factory()->NewUnaryOperation(
646 Token::NOT, factory()->NewVariableProxy(done), nopos);
648 parser_->FinalizeIteratorUse(completion, closing_condition, iterator, block_,
649 target, IteratorType::kNormal);
653 void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
654 Variable* temp_var =
nullptr;
655 VisitArrayLiteral(node, &temp_var);
658 void PatternRewriter::VisitAssignment(Assignment* node) {
663 DCHECK_EQ(Token::ASSIGN, node->op());
665 auto initializer = node->value();
666 auto value = initializer;
667 auto temp = CreateTempVar(current_value_);
669 Expression* is_undefined = factory()->NewCompareOperation(
670 Token::EQ_STRICT, factory()->NewVariableProxy(temp),
671 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
672 value = factory()->NewConditional(is_undefined, initializer,
673 factory()->NewVariableProxy(temp),
677 RewriteParameterScopes(initializer);
679 RecurseIntoSubpattern(node->target(), value);
686 DCHECK(IsAssignmentContext());
687 auto value = current_value_;
689 Assignment* assignment =
690 factory()->NewAssignment(Token::ASSIGN, node, value, node->position());
692 block_->statements()->Add(
693 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
699 #define NOT_A_PATTERN(Node) \ 700 void PatternRewriter::Visit##Node(v8::internal::Node*) { UNREACHABLE(); } 702 NOT_A_PATTERN(BinaryOperation)
703 NOT_A_PATTERN(NaryOperation)
705 NOT_A_PATTERN(BreakStatement)
707 NOT_A_PATTERN(CallNew)
708 NOT_A_PATTERN(CallRuntime)
709 NOT_A_PATTERN(ClassLiteral)
710 NOT_A_PATTERN(CompareOperation)
711 NOT_A_PATTERN(CompoundAssignment)
712 NOT_A_PATTERN(Conditional)
713 NOT_A_PATTERN(ContinueStatement)
714 NOT_A_PATTERN(CountOperation)
715 NOT_A_PATTERN(DebuggerStatement)
716 NOT_A_PATTERN(DoExpression)
717 NOT_A_PATTERN(DoWhileStatement)
718 NOT_A_PATTERN(EmptyStatement)
719 NOT_A_PATTERN(EmptyParentheses)
720 NOT_A_PATTERN(ExpressionStatement)
721 NOT_A_PATTERN(ForInStatement)
722 NOT_A_PATTERN(ForOfStatement)
723 NOT_A_PATTERN(ForStatement)
724 NOT_A_PATTERN(FunctionDeclaration)
725 NOT_A_PATTERN(FunctionLiteral)
726 NOT_A_PATTERN(GetIterator)
727 NOT_A_PATTERN(GetTemplateObject)
728 NOT_A_PATTERN(IfStatement)
729 NOT_A_PATTERN(ImportCallExpression)
730 NOT_A_PATTERN(Literal)
731 NOT_A_PATTERN(NativeFunctionLiteral)
732 NOT_A_PATTERN(RegExpLiteral)
733 NOT_A_PATTERN(ResolvedProperty)
734 NOT_A_PATTERN(ReturnStatement)
735 NOT_A_PATTERN(SloppyBlockFunctionStatement)
736 NOT_A_PATTERN(Spread)
737 NOT_A_PATTERN(StoreInArrayLiteral)
738 NOT_A_PATTERN(SuperPropertyReference)
739 NOT_A_PATTERN(SuperCallReference)
740 NOT_A_PATTERN(SwitchStatement)
741 NOT_A_PATTERN(TemplateLiteral)
742 NOT_A_PATTERN(ThisFunction)
744 NOT_A_PATTERN(TryCatchStatement)
745 NOT_A_PATTERN(TryFinallyStatement)
746 NOT_A_PATTERN(UnaryOperation)
747 NOT_A_PATTERN(VariableDeclaration)
748 NOT_A_PATTERN(WhileStatement)
749 NOT_A_PATTERN(WithStatement)
751 NOT_A_PATTERN(YieldStar)
753 NOT_A_PATTERN(InitializeClassMembersStatement)