OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/ast/ast.h" | 5 #include "src/ast/ast.h" |
6 #include "src/messages.h" | 6 #include "src/messages.h" |
7 #include "src/parsing/parameter-initializer-rewriter.h" | 7 #include "src/parsing/parameter-initializer-rewriter.h" |
8 #include "src/parsing/parser.h" | 8 #include "src/parsing/parser.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 | 11 |
12 namespace internal { | 12 namespace internal { |
13 | 13 |
14 | |
15 void Parser::PatternRewriter::DeclareAndInitializeVariables( | 14 void Parser::PatternRewriter::DeclareAndInitializeVariables( |
16 Block* block, const DeclarationDescriptor* declaration_descriptor, | 15 Block* block, const DeclarationDescriptor* declaration_descriptor, |
17 const DeclarationParsingResult::Declaration* declaration, | 16 const DeclarationParsingResult::Declaration* declaration, |
18 ZoneList<const AstRawString*>* names, bool* ok) { | 17 ZoneList<const AstRawString*>* names, bool* ok) { |
19 PatternRewriter rewriter; | 18 PatternRewriter rewriter; |
20 | 19 |
| 20 rewriter.scope_ = declaration_descriptor->scope; |
| 21 rewriter.parser_ = declaration_descriptor->parser; |
| 22 rewriter.context_ = BINDING; |
21 rewriter.pattern_ = declaration->pattern; | 23 rewriter.pattern_ = declaration->pattern; |
22 rewriter.initializer_position_ = declaration->initializer_position; | 24 rewriter.initializer_position_ = declaration->initializer_position; |
23 rewriter.block_ = block; | 25 rewriter.block_ = block; |
24 rewriter.descriptor_ = declaration_descriptor; | 26 rewriter.descriptor_ = declaration_descriptor; |
25 rewriter.names_ = names; | 27 rewriter.names_ = names; |
26 rewriter.ok_ = ok; | 28 rewriter.ok_ = ok; |
27 | 29 |
28 rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer); | 30 rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer); |
29 } | 31 } |
30 | 32 |
31 | 33 |
| 34 void Parser::PatternRewriter::RewriteDestructuringAssignment( |
| 35 Parser* parser, RewritableAssignmentExpression* to_rewrite, Scope* scope, |
| 36 bool* ok) { |
| 37 PatternRewriter rewriter; |
| 38 |
| 39 DCHECK(!to_rewrite->is_rewritten()); |
| 40 |
| 41 rewriter.scope_ = scope; |
| 42 rewriter.parser_ = parser; |
| 43 rewriter.context_ = ASSIGNMENT; |
| 44 rewriter.pattern_ = to_rewrite; |
| 45 rewriter.block_ = nullptr; |
| 46 rewriter.descriptor_ = nullptr; |
| 47 rewriter.names_ = nullptr; |
| 48 rewriter.ok_ = ok; |
| 49 |
| 50 rewriter.RecurseIntoSubpattern(rewriter.pattern_, nullptr); |
| 51 } |
| 52 |
| 53 |
| 54 bool Parser::PatternRewriter::IsAssignmentContext(PatternContext c) const { |
| 55 return c == ASSIGNMENT || c == ASSIGNMENT_INITIALIZER; |
| 56 } |
| 57 |
| 58 |
| 59 bool Parser::PatternRewriter::IsBindingContext(PatternContext c) const { |
| 60 return c == BINDING || c == INITIALIZER; |
| 61 } |
| 62 |
| 63 |
| 64 Parser::PatternRewriter::PatternContext |
| 65 Parser::PatternRewriter::SetAssignmentContextIfNeeded(Expression* node) { |
| 66 PatternContext old_context = context(); |
| 67 if (node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN) { |
| 68 set_context(ASSIGNMENT); |
| 69 } |
| 70 return old_context; |
| 71 } |
| 72 |
| 73 |
| 74 Parser::PatternRewriter::PatternContext |
| 75 Parser::PatternRewriter::SetInitializerContextIfNeeded(Expression* node) { |
| 76 // Set appropriate initializer context for BindingElement and |
| 77 // AssignmentElement nodes |
| 78 PatternContext old_context = context(); |
| 79 bool is_destructuring_assignment = |
| 80 node->IsRewritableAssignmentExpression() && |
| 81 !node->AsRewritableAssignmentExpression()->is_rewritten(); |
| 82 bool is_assignment = |
| 83 node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN; |
| 84 if (is_destructuring_assignment || is_assignment) { |
| 85 switch (old_context) { |
| 86 case BINDING: |
| 87 set_context(INITIALIZER); |
| 88 break; |
| 89 case ASSIGNMENT: |
| 90 set_context(ASSIGNMENT_INITIALIZER); |
| 91 break; |
| 92 default: |
| 93 break; |
| 94 } |
| 95 } |
| 96 return old_context; |
| 97 } |
| 98 |
| 99 |
32 void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) { | 100 void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) { |
33 Expression* value = current_value_; | 101 Expression* value = current_value_; |
| 102 |
| 103 if (IsAssignmentContext()) { |
| 104 // In an assignment context, simply perform the assignment |
| 105 Assignment* assignment = factory()->NewAssignment( |
| 106 Token::ASSIGN, pattern, value, pattern->position()); |
| 107 block_->statements()->Add( |
| 108 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), |
| 109 zone()); |
| 110 return; |
| 111 } |
| 112 |
34 descriptor_->scope->RemoveUnresolved(pattern); | 113 descriptor_->scope->RemoveUnresolved(pattern); |
35 | 114 |
36 // Declare variable. | 115 // Declare variable. |
37 // Note that we *always* must treat the initial value via a separate init | 116 // Note that we *always* must treat the initial value via a separate init |
38 // assignment for variables and constants because the value must be assigned | 117 // assignment for variables and constants because the value must be assigned |
39 // when the variable is encountered in the source. But the variable/constant | 118 // when the variable is encountered in the source. But the variable/constant |
40 // is declared (and set to 'undefined') upon entering the function within | 119 // is declared (and set to 'undefined') upon entering the function within |
41 // which the variable or constant is declared. Only function variables have | 120 // which the variable or constant is declared. Only function variables have |
42 // an initial value in the declaration (because they are initialized upon | 121 // an initial value in the declaration (because they are initialized upon |
43 // entering the function). | 122 // entering the function). |
44 // | 123 // |
45 // If we have a legacy const declaration, in an inner scope, the proxy | 124 // If we have a legacy const declaration, in an inner scope, the proxy |
46 // is always bound to the declared variable (independent of possibly | 125 // is always bound to the declared variable (independent of possibly |
47 // surrounding 'with' statements). | 126 // surrounding 'with' statements). |
48 // For let/const declarations in harmony mode, we can also immediately | 127 // For let/const declarations in harmony mode, we can also immediately |
49 // pre-resolve the proxy because it resides in the same scope as the | 128 // pre-resolve the proxy because it resides in the same scope as the |
50 // declaration. | 129 // declaration. |
51 Parser* parser = descriptor_->parser; | |
52 const AstRawString* name = pattern->raw_name(); | 130 const AstRawString* name = pattern->raw_name(); |
53 VariableProxy* proxy = parser->NewUnresolved(name, descriptor_->mode); | 131 VariableProxy* proxy = parser_->NewUnresolved(name, descriptor_->mode); |
54 Declaration* declaration = factory()->NewVariableDeclaration( | 132 Declaration* declaration = factory()->NewVariableDeclaration( |
55 proxy, descriptor_->mode, descriptor_->scope, | 133 proxy, descriptor_->mode, descriptor_->scope, |
56 descriptor_->declaration_pos); | 134 descriptor_->declaration_pos); |
57 Variable* var = parser->Declare(declaration, descriptor_->declaration_kind, | 135 Variable* var = |
58 descriptor_->mode != VAR, ok_, | 136 parser_->Declare(declaration, descriptor_->declaration_kind, |
59 descriptor_->hoist_scope); | 137 descriptor_->mode != VAR, ok_, descriptor_->hoist_scope); |
60 if (!*ok_) return; | 138 if (!*ok_) return; |
61 DCHECK_NOT_NULL(var); | 139 DCHECK_NOT_NULL(var); |
62 DCHECK(!proxy->is_resolved() || proxy->var() == var); | 140 DCHECK(!proxy->is_resolved() || proxy->var() == var); |
63 var->set_initializer_position(initializer_position_); | 141 var->set_initializer_position(initializer_position_); |
64 | 142 |
65 DCHECK(initializer_position_ != RelocInfo::kNoPosition); | 143 DCHECK(initializer_position_ != RelocInfo::kNoPosition); |
66 | 144 |
67 Scope* declaration_scope = IsLexicalVariableMode(descriptor_->mode) | 145 Scope* declaration_scope = IsLexicalVariableMode(descriptor_->mode) |
68 ? descriptor_->scope | 146 ? descriptor_->scope |
69 : descriptor_->scope->DeclarationScope(); | 147 : descriptor_->scope->DeclarationScope(); |
70 if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) { | 148 if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) { |
71 parser->ReportMessage(MessageTemplate::kTooManyVariables); | 149 parser_->ReportMessage(MessageTemplate::kTooManyVariables); |
72 *ok_ = false; | 150 *ok_ = false; |
73 return; | 151 return; |
74 } | 152 } |
75 if (names_) { | 153 if (names_) { |
76 names_->Add(name, zone()); | 154 names_->Add(name, zone()); |
77 } | 155 } |
78 | 156 |
79 // Initialize variables if needed. A | 157 // Initialize variables if needed. A |
80 // declaration of the form: | 158 // declaration of the form: |
81 // | 159 // |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 Assignment* assignment = factory()->NewAssignment( | 287 Assignment* assignment = factory()->NewAssignment( |
210 Token::INIT, proxy, value, descriptor_->initialization_pos); | 288 Token::INIT, proxy, value, descriptor_->initialization_pos); |
211 block_->statements()->Add( | 289 block_->statements()->Add( |
212 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), | 290 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), |
213 zone()); | 291 zone()); |
214 } | 292 } |
215 } | 293 } |
216 | 294 |
217 | 295 |
218 Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) { | 296 Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) { |
219 auto temp = descriptor_->parser->scope_->NewTemporary( | 297 auto temp = scope()->NewTemporary(ast_value_factory()->empty_string()); |
220 ast_value_factory()->empty_string()); | |
221 if (value != nullptr) { | 298 if (value != nullptr) { |
222 auto assignment = factory()->NewAssignment( | 299 auto assignment = factory()->NewAssignment( |
223 Token::ASSIGN, factory()->NewVariableProxy(temp), value, | 300 Token::ASSIGN, factory()->NewVariableProxy(temp), value, |
224 RelocInfo::kNoPosition); | 301 RelocInfo::kNoPosition); |
225 | 302 |
226 block_->statements()->Add( | 303 block_->statements()->Add( |
227 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), | 304 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), |
228 zone()); | 305 zone()); |
229 } | 306 } |
230 return temp; | 307 return temp; |
231 } | 308 } |
232 | 309 |
233 | 310 |
234 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) { | 311 void Parser::PatternRewriter::VisitRewritableAssignmentExpression( |
235 auto temp = CreateTempVar(current_value_); | 312 RewritableAssignmentExpression* node) { |
| 313 if (!IsAssignmentContext()) { |
| 314 // Mark the assignment as rewritten to prevent redundant rewriting, and |
| 315 // perform BindingPattern rewriting |
| 316 DCHECK(!node->is_rewritten()); |
| 317 node->Rewrite(node->expression()); |
| 318 return node->expression()->Accept(this); |
| 319 } |
236 | 320 |
237 block_->statements()->Add(descriptor_->parser->BuildAssertIsCoercible(temp), | 321 if (node->is_rewritten()) return; |
238 zone()); | 322 DCHECK(IsAssignmentContext()); |
| 323 Assignment* assign = node->expression()->AsAssignment(); |
| 324 DCHECK_NOT_NULL(assign); |
| 325 DCHECK_EQ(Token::ASSIGN, assign->op()); |
| 326 |
| 327 auto initializer = assign->value(); |
| 328 auto value = initializer; |
| 329 |
| 330 if (IsInitializerContext()) { |
| 331 // let {<pattern> = <init>} = <value> |
| 332 // becomes |
| 333 // temp = <value>; |
| 334 // <pattern> = temp === undefined ? <init> : temp; |
| 335 auto temp_var = CreateTempVar(current_value_); |
| 336 Expression* is_undefined = factory()->NewCompareOperation( |
| 337 Token::EQ_STRICT, factory()->NewVariableProxy(temp_var), |
| 338 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), |
| 339 RelocInfo::kNoPosition); |
| 340 value = factory()->NewConditional(is_undefined, initializer, |
| 341 factory()->NewVariableProxy(temp_var), |
| 342 RelocInfo::kNoPosition); |
| 343 } |
| 344 |
| 345 PatternContext old_context = SetAssignmentContextIfNeeded(initializer); |
| 346 int pos = assign->position(); |
| 347 Block* old_block = block_; |
| 348 block_ = factory()->NewBlock(nullptr, 8, false, pos); |
| 349 Variable* temp = nullptr; |
| 350 Expression* pattern = assign->target(); |
| 351 Expression* old_value = current_value_; |
| 352 current_value_ = value; |
| 353 if (pattern->IsObjectLiteral()) { |
| 354 VisitObjectLiteral(pattern->AsObjectLiteral(), &temp); |
| 355 } else { |
| 356 DCHECK(pattern->IsArrayLiteral()); |
| 357 VisitArrayLiteral(pattern->AsArrayLiteral(), &temp); |
| 358 } |
| 359 DCHECK_NOT_NULL(temp); |
| 360 current_value_ = old_value; |
| 361 Expression* expr = factory()->NewDoExpression(block_, temp, pos); |
| 362 node->Rewrite(expr); |
| 363 block_ = old_block; |
| 364 if (block_) { |
| 365 block_->statements()->Add(factory()->NewExpressionStatement(expr, pos), |
| 366 zone()); |
| 367 } |
| 368 return set_context(old_context); |
| 369 } |
| 370 |
| 371 |
| 372 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern, |
| 373 Variable** temp_var) { |
| 374 auto temp = *temp_var = CreateTempVar(current_value_); |
| 375 |
| 376 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone()); |
239 | 377 |
240 for (ObjectLiteralProperty* property : *pattern->properties()) { | 378 for (ObjectLiteralProperty* property : *pattern->properties()) { |
| 379 PatternContext context = SetInitializerContextIfNeeded(property->value()); |
241 RecurseIntoSubpattern( | 380 RecurseIntoSubpattern( |
242 property->value(), | 381 property->value(), |
243 factory()->NewProperty(factory()->NewVariableProxy(temp), | 382 factory()->NewProperty(factory()->NewVariableProxy(temp), |
244 property->key(), RelocInfo::kNoPosition)); | 383 property->key(), RelocInfo::kNoPosition)); |
| 384 set_context(context); |
245 } | 385 } |
246 } | 386 } |
247 | 387 |
248 | 388 |
249 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { | 389 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) { |
250 auto temp = CreateTempVar(current_value_); | 390 Variable* temp_var = nullptr; |
| 391 VisitObjectLiteral(node, &temp_var); |
| 392 } |
251 | 393 |
252 block_->statements()->Add(descriptor_->parser->BuildAssertIsCoercible(temp), | |
253 zone()); | |
254 | 394 |
255 auto iterator = CreateTempVar(descriptor_->parser->GetIterator( | 395 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node, |
| 396 Variable** temp_var) { |
| 397 auto temp = *temp_var = CreateTempVar(current_value_); |
| 398 |
| 399 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone()); |
| 400 |
| 401 auto iterator = CreateTempVar(parser_->GetIterator( |
256 factory()->NewVariableProxy(temp), factory(), RelocInfo::kNoPosition)); | 402 factory()->NewVariableProxy(temp), factory(), RelocInfo::kNoPosition)); |
257 auto done = CreateTempVar( | 403 auto done = CreateTempVar( |
258 factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition)); | 404 factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition)); |
259 auto result = CreateTempVar(); | 405 auto result = CreateTempVar(); |
260 auto v = CreateTempVar(); | 406 auto v = CreateTempVar(); |
261 | 407 |
262 Spread* spread = nullptr; | 408 Spread* spread = nullptr; |
263 for (Expression* value : *node->values()) { | 409 for (Expression* value : *node->values()) { |
264 if (value->IsSpread()) { | 410 if (value->IsSpread()) { |
265 spread = value->AsSpread(); | 411 spread = value->AsSpread(); |
266 break; | 412 break; |
267 } | 413 } |
268 | 414 |
| 415 PatternContext context = SetInitializerContextIfNeeded(value); |
269 // if (!done) { | 416 // if (!done) { |
270 // result = IteratorNext(iterator); | 417 // result = IteratorNext(iterator); |
271 // v = (done = result.done) ? undefined : result.value; | 418 // v = (done = result.done) ? undefined : result.value; |
272 // } | 419 // } |
273 auto next_block = | 420 auto next_block = |
274 factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition); | 421 factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition); |
275 next_block->statements()->Add( | 422 next_block->statements()->Add(factory()->NewExpressionStatement( |
276 factory()->NewExpressionStatement( | 423 parser_->BuildIteratorNextResult( |
277 descriptor_->parser->BuildIteratorNextResult( | 424 factory()->NewVariableProxy(iterator), |
278 factory()->NewVariableProxy(iterator), result, | 425 result, RelocInfo::kNoPosition), |
279 RelocInfo::kNoPosition), | 426 RelocInfo::kNoPosition), |
280 RelocInfo::kNoPosition), | 427 zone()); |
281 zone()); | |
282 | 428 |
283 auto assign_to_done = factory()->NewAssignment( | 429 auto assign_to_done = factory()->NewAssignment( |
284 Token::ASSIGN, factory()->NewVariableProxy(done), | 430 Token::ASSIGN, factory()->NewVariableProxy(done), |
285 factory()->NewProperty( | 431 factory()->NewProperty( |
286 factory()->NewVariableProxy(result), | 432 factory()->NewVariableProxy(result), |
287 factory()->NewStringLiteral(ast_value_factory()->done_string(), | 433 factory()->NewStringLiteral(ast_value_factory()->done_string(), |
288 RelocInfo::kNoPosition), | 434 RelocInfo::kNoPosition), |
289 RelocInfo::kNoPosition), | 435 RelocInfo::kNoPosition), |
290 RelocInfo::kNoPosition); | 436 RelocInfo::kNoPosition); |
291 auto next_value = factory()->NewConditional( | 437 auto next_value = factory()->NewConditional( |
(...skipping 16 matching lines...) Expand all Loading... |
308 factory()->NewUnaryOperation(Token::NOT, | 454 factory()->NewUnaryOperation(Token::NOT, |
309 factory()->NewVariableProxy(done), | 455 factory()->NewVariableProxy(done), |
310 RelocInfo::kNoPosition), | 456 RelocInfo::kNoPosition), |
311 next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition), | 457 next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition), |
312 RelocInfo::kNoPosition); | 458 RelocInfo::kNoPosition); |
313 block_->statements()->Add(if_statement, zone()); | 459 block_->statements()->Add(if_statement, zone()); |
314 | 460 |
315 if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) { | 461 if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) { |
316 RecurseIntoSubpattern(value, factory()->NewVariableProxy(v)); | 462 RecurseIntoSubpattern(value, factory()->NewVariableProxy(v)); |
317 } | 463 } |
| 464 set_context(context); |
318 } | 465 } |
319 | 466 |
320 if (spread != nullptr) { | 467 if (spread != nullptr) { |
321 // array = []; | 468 // array = []; |
322 // if (!done) %concat_iterable_to_array(array, iterator); | 469 // if (!done) %concat_iterable_to_array(array, iterator); |
323 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone()); | 470 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone()); |
324 auto array = CreateTempVar(factory()->NewArrayLiteral( | 471 auto array = CreateTempVar(factory()->NewArrayLiteral( |
325 empty_exprs, | 472 empty_exprs, |
326 // Reuse pattern's literal index - it is unused since there is no | 473 // Reuse pattern's literal index - it is unused since there is no |
327 // actual literal allocated. | 474 // actual literal allocated. |
328 node->literal_index(), is_strong(descriptor_->parser->language_mode()), | 475 node->literal_index(), is_strong(scope()->language_mode()), |
329 RelocInfo::kNoPosition)); | 476 RelocInfo::kNoPosition)); |
330 | 477 |
331 auto arguments = new (zone()) ZoneList<Expression*>(2, zone()); | 478 auto arguments = new (zone()) ZoneList<Expression*>(2, zone()); |
332 arguments->Add(factory()->NewVariableProxy(array), zone()); | 479 arguments->Add(factory()->NewVariableProxy(array), zone()); |
333 arguments->Add(factory()->NewVariableProxy(iterator), zone()); | 480 arguments->Add(factory()->NewVariableProxy(iterator), zone()); |
334 auto spread_into_array_call = | 481 auto spread_into_array_call = |
335 factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX, | 482 factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX, |
336 arguments, RelocInfo::kNoPosition); | 483 arguments, RelocInfo::kNoPosition); |
337 | 484 |
338 auto if_statement = factory()->NewIfStatement( | 485 auto if_statement = factory()->NewIfStatement( |
339 factory()->NewUnaryOperation(Token::NOT, | 486 factory()->NewUnaryOperation(Token::NOT, |
340 factory()->NewVariableProxy(done), | 487 factory()->NewVariableProxy(done), |
341 RelocInfo::kNoPosition), | 488 RelocInfo::kNoPosition), |
342 factory()->NewExpressionStatement(spread_into_array_call, | 489 factory()->NewExpressionStatement(spread_into_array_call, |
343 RelocInfo::kNoPosition), | 490 RelocInfo::kNoPosition), |
344 factory()->NewEmptyStatement(RelocInfo::kNoPosition), | 491 factory()->NewEmptyStatement(RelocInfo::kNoPosition), |
345 RelocInfo::kNoPosition); | 492 RelocInfo::kNoPosition); |
346 block_->statements()->Add(if_statement, zone()); | 493 block_->statements()->Add(if_statement, zone()); |
347 | 494 |
348 RecurseIntoSubpattern(spread->expression(), | 495 RecurseIntoSubpattern(spread->expression(), |
349 factory()->NewVariableProxy(array)); | 496 factory()->NewVariableProxy(array)); |
350 } | 497 } |
351 } | 498 } |
352 | 499 |
353 | 500 |
| 501 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { |
| 502 Variable* temp_var = nullptr; |
| 503 VisitArrayLiteral(node, &temp_var); |
| 504 } |
| 505 |
| 506 |
354 void Parser::PatternRewriter::VisitAssignment(Assignment* node) { | 507 void Parser::PatternRewriter::VisitAssignment(Assignment* node) { |
355 // let {<pattern> = <init>} = <value> | 508 // let {<pattern> = <init>} = <value> |
356 // becomes | 509 // becomes |
357 // temp = <value>; | 510 // temp = <value>; |
358 // <pattern> = temp === undefined ? <init> : temp; | 511 // <pattern> = temp === undefined ? <init> : temp; |
359 DCHECK(node->op() == Token::ASSIGN); | 512 DCHECK_EQ(Token::ASSIGN, node->op()); |
| 513 |
| 514 auto initializer = node->value(); |
| 515 auto value = initializer; |
360 auto temp = CreateTempVar(current_value_); | 516 auto temp = CreateTempVar(current_value_); |
361 Expression* is_undefined = factory()->NewCompareOperation( | 517 |
362 Token::EQ_STRICT, factory()->NewVariableProxy(temp), | 518 if (IsInitializerContext()) { |
363 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), | 519 Expression* is_undefined = factory()->NewCompareOperation( |
364 RelocInfo::kNoPosition); | 520 Token::EQ_STRICT, factory()->NewVariableProxy(temp), |
365 Expression* initializer = node->value(); | 521 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), |
366 if (descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER && | 522 RelocInfo::kNoPosition); |
367 descriptor_->scope->is_arrow_scope()) { | 523 value = factory()->NewConditional(is_undefined, initializer, |
368 // TODO(adamk): Only call this if necessary. | 524 factory()->NewVariableProxy(temp), |
369 RewriteParameterInitializerScope( | 525 RelocInfo::kNoPosition); |
370 descriptor_->parser->stack_limit(), initializer, | |
371 descriptor_->scope->outer_scope(), descriptor_->scope); | |
372 } | 526 } |
373 Expression* value = factory()->NewConditional( | 527 |
374 is_undefined, initializer, factory()->NewVariableProxy(temp), | 528 if (IsBindingContext() && |
375 RelocInfo::kNoPosition); | 529 descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER && |
| 530 scope()->is_arrow_scope()) { |
| 531 RewriteParameterInitializerScope(parser_->stack_limit(), initializer, |
| 532 scope()->outer_scope(), scope()); |
| 533 } |
| 534 |
| 535 PatternContext old_context = SetAssignmentContextIfNeeded(initializer); |
376 RecurseIntoSubpattern(node->target(), value); | 536 RecurseIntoSubpattern(node->target(), value); |
| 537 set_context(old_context); |
377 } | 538 } |
378 | 539 |
379 | 540 |
| 541 // =============== AssignmentPattern only ================== |
| 542 |
| 543 void Parser::PatternRewriter::VisitProperty(v8::internal::Property* node) { |
| 544 DCHECK(IsAssignmentContext()); |
| 545 auto value = current_value_; |
| 546 |
| 547 Assignment* assignment = |
| 548 factory()->NewAssignment(Token::ASSIGN, node, value, node->position()); |
| 549 |
| 550 block_->statements()->Add( |
| 551 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), |
| 552 zone()); |
| 553 } |
| 554 |
| 555 |
380 // =============== UNREACHABLE ============================= | 556 // =============== UNREACHABLE ============================= |
381 | 557 |
382 void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); } | 558 void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); } |
383 | 559 |
384 #define NOT_A_PATTERN(Node) \ | 560 #define NOT_A_PATTERN(Node) \ |
385 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \ | 561 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \ |
386 UNREACHABLE(); \ | 562 UNREACHABLE(); \ |
387 } | 563 } |
388 | 564 |
389 NOT_A_PATTERN(BinaryOperation) | 565 NOT_A_PATTERN(BinaryOperation) |
(...skipping 17 matching lines...) Expand all Loading... |
407 NOT_A_PATTERN(ExpressionStatement) | 583 NOT_A_PATTERN(ExpressionStatement) |
408 NOT_A_PATTERN(ForInStatement) | 584 NOT_A_PATTERN(ForInStatement) |
409 NOT_A_PATTERN(ForOfStatement) | 585 NOT_A_PATTERN(ForOfStatement) |
410 NOT_A_PATTERN(ForStatement) | 586 NOT_A_PATTERN(ForStatement) |
411 NOT_A_PATTERN(FunctionDeclaration) | 587 NOT_A_PATTERN(FunctionDeclaration) |
412 NOT_A_PATTERN(FunctionLiteral) | 588 NOT_A_PATTERN(FunctionLiteral) |
413 NOT_A_PATTERN(IfStatement) | 589 NOT_A_PATTERN(IfStatement) |
414 NOT_A_PATTERN(ImportDeclaration) | 590 NOT_A_PATTERN(ImportDeclaration) |
415 NOT_A_PATTERN(Literal) | 591 NOT_A_PATTERN(Literal) |
416 NOT_A_PATTERN(NativeFunctionLiteral) | 592 NOT_A_PATTERN(NativeFunctionLiteral) |
417 NOT_A_PATTERN(Property) | |
418 NOT_A_PATTERN(RegExpLiteral) | 593 NOT_A_PATTERN(RegExpLiteral) |
419 NOT_A_PATTERN(ReturnStatement) | 594 NOT_A_PATTERN(ReturnStatement) |
420 NOT_A_PATTERN(SloppyBlockFunctionStatement) | 595 NOT_A_PATTERN(SloppyBlockFunctionStatement) |
421 NOT_A_PATTERN(Spread) | 596 NOT_A_PATTERN(Spread) |
422 NOT_A_PATTERN(SuperPropertyReference) | 597 NOT_A_PATTERN(SuperPropertyReference) |
423 NOT_A_PATTERN(SuperCallReference) | 598 NOT_A_PATTERN(SuperCallReference) |
424 NOT_A_PATTERN(SwitchStatement) | 599 NOT_A_PATTERN(SwitchStatement) |
425 NOT_A_PATTERN(ThisFunction) | 600 NOT_A_PATTERN(ThisFunction) |
426 NOT_A_PATTERN(Throw) | 601 NOT_A_PATTERN(Throw) |
427 NOT_A_PATTERN(TryCatchStatement) | 602 NOT_A_PATTERN(TryCatchStatement) |
428 NOT_A_PATTERN(TryFinallyStatement) | 603 NOT_A_PATTERN(TryFinallyStatement) |
429 NOT_A_PATTERN(UnaryOperation) | 604 NOT_A_PATTERN(UnaryOperation) |
430 NOT_A_PATTERN(VariableDeclaration) | 605 NOT_A_PATTERN(VariableDeclaration) |
431 NOT_A_PATTERN(WhileStatement) | 606 NOT_A_PATTERN(WhileStatement) |
432 NOT_A_PATTERN(WithStatement) | 607 NOT_A_PATTERN(WithStatement) |
433 NOT_A_PATTERN(Yield) | 608 NOT_A_PATTERN(Yield) |
434 | 609 |
435 #undef NOT_A_PATTERN | 610 #undef NOT_A_PATTERN |
436 } // namespace internal | 611 } // namespace internal |
437 } // namespace v8 | 612 } // namespace v8 |
OLD | NEW |