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