Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: src/pattern-rewriter.cc

Issue 1309813007: [es6] implement destructuring assignment (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: An implementation Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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.h" 5 #include "src/ast.h"
6 #include "src/messages.h" 6 #include "src/messages.h"
7 #include "src/parameter-initializer-rewriter.h" 7 #include "src/parameter-initializer-rewriter.h"
8 #include "src/parser.h" 8 #include "src/parser.h"
9 9
10 namespace v8 { 10 namespace v8 {
11 11
12 namespace internal { 12 namespace internal {
13 13
14 14
15 void Parser::PatternRewriter::DeclareAndInitializeVariables( 15 void Parser::PatternRewriter::DeclareAndInitializeVariables(
16 Block* block, const DeclarationDescriptor* declaration_descriptor, 16 Block* block, const DeclarationDescriptor* declaration_descriptor,
17 const DeclarationParsingResult::Declaration* declaration, 17 const DeclarationParsingResult::Declaration* declaration,
18 ZoneList<const AstRawString*>* names, bool* ok) { 18 ZoneList<const AstRawString*>* names, bool* ok) {
19 PatternRewriter rewriter; 19 PatternRewriter rewriter;
20 20
21 rewriter.scope_ = declaration_descriptor->parser->scope_;
22 rewriter.parser_ = declaration_descriptor->parser;
23 rewriter.context_ = BINDING;
21 rewriter.pattern_ = declaration->pattern; 24 rewriter.pattern_ = declaration->pattern;
22 rewriter.initializer_position_ = declaration->initializer_position; 25 rewriter.initializer_position_ = declaration->initializer_position;
23 rewriter.block_ = block; 26 rewriter.block_ = block;
24 rewriter.descriptor_ = declaration_descriptor; 27 rewriter.descriptor_ = declaration_descriptor;
25 rewriter.names_ = names; 28 rewriter.names_ = names;
26 rewriter.ok_ = ok; 29 rewriter.ok_ = ok;
27 30
28 rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer); 31 rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer);
29 } 32 }
30 33
31 34
35 void Parser::PatternRewriter::RewriteDestructuringAssignment(
36 Parser* parser, Assignment* assignment, Scope* scope, bool* ok) {
37 PatternRewriter rewriter;
38
39 DCHECK(assignment->target()->IsAssignmentPattern());
40 DCHECK_EQ(assignment->op(), Token::ASSIGN);
41
42 rewriter.scope_ = scope;
43 rewriter.parser_ = parser;
44 rewriter.context_ = ASSIGNMENT;
45 rewriter.pattern_ = assignment->target();
46 rewriter.block_ = nullptr;
47 rewriter.descriptor_ = nullptr;
48 rewriter.names_ = nullptr;
49 rewriter.ok_ = ok;
50
51 rewriter.RecurseIntoSubpattern(rewriter.pattern_, assignment->value());
52 }
53
54
32 void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) { 55 void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
33 Expression* value = current_value_; 56 Expression* value = current_value_;
57
58 if (context() == ASSIGNMENT) {
59 // In an assignment context, simply perform the assignment
60 Assignment* assignment = factory()->NewAssignment(
61 Token::ASSIGN, pattern, value, pattern->position());
62 block_->statements()->Add(
63 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
64 zone());
65 return;
66 }
67
34 descriptor_->scope->RemoveUnresolved(pattern); 68 descriptor_->scope->RemoveUnresolved(pattern);
35 69
36 // Declare variable. 70 // Declare variable.
37 // Note that we *always* must treat the initial value via a separate init 71 // 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 72 // assignment for variables and constants because the value must be assigned
39 // when the variable is encountered in the source. But the variable/constant 73 // when the variable is encountered in the source. But the variable/constant
40 // is declared (and set to 'undefined') upon entering the function within 74 // is declared (and set to 'undefined') upon entering the function within
41 // which the variable or constant is declared. Only function variables have 75 // which the variable or constant is declared. Only function variables have
42 // an initial value in the declaration (because they are initialized upon 76 // an initial value in the declaration (because they are initialized upon
43 // entering the function). 77 // entering the function).
44 // 78 //
45 // If we have a legacy const declaration, in an inner scope, the proxy 79 // If we have a legacy const declaration, in an inner scope, the proxy
46 // is always bound to the declared variable (independent of possibly 80 // is always bound to the declared variable (independent of possibly
47 // surrounding 'with' statements). 81 // surrounding 'with' statements).
48 // For let/const declarations in harmony mode, we can also immediately 82 // 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 83 // pre-resolve the proxy because it resides in the same scope as the
50 // declaration. 84 // declaration.
51 Parser* parser = descriptor_->parser;
52 const AstRawString* name = pattern->raw_name(); 85 const AstRawString* name = pattern->raw_name();
53 VariableProxy* proxy = parser->NewUnresolved(name, descriptor_->mode); 86 VariableProxy* proxy = parser_->NewUnresolved(name, descriptor_->mode);
54 Declaration* declaration = factory()->NewVariableDeclaration( 87 Declaration* declaration = factory()->NewVariableDeclaration(
55 proxy, descriptor_->mode, descriptor_->scope, 88 proxy, descriptor_->mode, descriptor_->scope,
56 descriptor_->declaration_pos); 89 descriptor_->declaration_pos);
57 Variable* var = parser->Declare(declaration, descriptor_->declaration_kind, 90 Variable* var =
58 descriptor_->mode != VAR, ok_, 91 parser_->Declare(declaration, descriptor_->declaration_kind,
59 descriptor_->hoist_scope); 92 descriptor_->mode != VAR, ok_, descriptor_->hoist_scope);
60 if (!*ok_) return; 93 if (!*ok_) return;
61 DCHECK_NOT_NULL(var); 94 DCHECK_NOT_NULL(var);
62 DCHECK(!proxy->is_resolved() || proxy->var() == var); 95 DCHECK(!proxy->is_resolved() || proxy->var() == var);
63 var->set_initializer_position(initializer_position_); 96 var->set_initializer_position(initializer_position_);
64 97
65 DCHECK(initializer_position_ != RelocInfo::kNoPosition); 98 DCHECK(initializer_position_ != RelocInfo::kNoPosition);
66 99
67 if (descriptor_->declaration_scope->num_var_or_const() > 100 if (descriptor_->declaration_scope->num_var_or_const() >
68 kMaxNumFunctionLocals) { 101 kMaxNumFunctionLocals) {
69 parser->ReportMessage(MessageTemplate::kTooManyVariables); 102 parser_->ReportMessage(MessageTemplate::kTooManyVariables);
70 *ok_ = false; 103 *ok_ = false;
71 return; 104 return;
72 } 105 }
73 if (names_) { 106 if (names_) {
74 names_->Add(name, zone()); 107 names_->Add(name, zone());
75 } 108 }
76 109
77 // Initialize variables if needed. A 110 // Initialize variables if needed. A
78 // declaration of the form: 111 // declaration of the form:
79 // 112 //
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 Assignment* assignment = factory()->NewAssignment( 240 Assignment* assignment = factory()->NewAssignment(
208 descriptor_->init_op, proxy, value, descriptor_->initialization_pos); 241 descriptor_->init_op, proxy, value, descriptor_->initialization_pos);
209 block_->statements()->Add( 242 block_->statements()->Add(
210 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), 243 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
211 zone()); 244 zone());
212 } 245 }
213 } 246 }
214 247
215 248
216 Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) { 249 Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) {
217 auto temp = descriptor_->parser->scope_->NewTemporary( 250 auto temp = scope()->NewTemporary(ast_value_factory()->empty_string());
218 ast_value_factory()->empty_string());
219 if (value != nullptr) { 251 if (value != nullptr) {
220 auto assignment = factory()->NewAssignment( 252 auto assignment = factory()->NewAssignment(
221 Token::ASSIGN, factory()->NewVariableProxy(temp), value, 253 Token::ASSIGN, factory()->NewVariableProxy(temp), value,
222 RelocInfo::kNoPosition); 254 RelocInfo::kNoPosition);
223 255
224 block_->statements()->Add( 256 block_->statements()->Add(
225 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), 257 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
226 zone()); 258 zone());
227 } 259 }
228 return temp; 260 return temp;
229 } 261 }
230 262
231 263
232 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) { 264 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
233 auto temp = CreateTempVar(current_value_); 265 Variable** temp_var) {
266 auto temp = *temp_var = CreateTempVar(current_value_);
234 267
235 block_->statements()->Add(descriptor_->parser->BuildAssertIsCoercible(temp), 268 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
236 zone());
237 269
238 for (ObjectLiteralProperty* property : *pattern->properties()) { 270 for (ObjectLiteralProperty* property : *pattern->properties()) {
239 RecurseIntoSubpattern( 271 RecurseIntoSubpattern(
240 property->value(), 272 property->value(),
241 factory()->NewProperty(factory()->NewVariableProxy(temp), 273 factory()->NewProperty(factory()->NewVariableProxy(temp),
242 property->key(), RelocInfo::kNoPosition)); 274 property->key(), RelocInfo::kNoPosition));
243 } 275 }
244 } 276 }
245 277
246 278
247 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { 279 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
248 auto temp = CreateTempVar(current_value_); 280 Variable** temp_var) {
281 auto temp = *temp_var = CreateTempVar(current_value_);
249 282
250 block_->statements()->Add(descriptor_->parser->BuildAssertIsCoercible(temp), 283 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
251 zone());
252 284
253 auto iterator = CreateTempVar(descriptor_->parser->GetIterator( 285 auto iterator = CreateTempVar(
254 factory()->NewVariableProxy(temp), factory())); 286 parser_->GetIterator(factory()->NewVariableProxy(temp), factory()));
255 auto done = CreateTempVar( 287 auto done = CreateTempVar(
256 factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition)); 288 factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition));
257 auto result = CreateTempVar(); 289 auto result = CreateTempVar();
258 auto v = CreateTempVar(); 290 auto v = CreateTempVar();
259 291
260 Spread* spread = nullptr; 292 Spread* spread = nullptr;
261 for (Expression* value : *node->values()) { 293 for (Expression* value : *node->values()) {
262 if (value->IsSpread()) { 294 if (value->IsSpread()) {
263 spread = value->AsSpread(); 295 spread = value->AsSpread();
264 break; 296 break;
265 } 297 }
266 298
267 // if (!done) { 299 // if (!done) {
268 // result = IteratorNext(iterator); 300 // result = IteratorNext(iterator);
269 // v = (done = result.done) ? undefined : result.value; 301 // v = (done = result.done) ? undefined : result.value;
270 // } 302 // }
271 auto next_block = 303 auto next_block =
272 factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition); 304 factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
273 next_block->statements()->Add( 305 next_block->statements()->Add(factory()->NewExpressionStatement(
274 factory()->NewExpressionStatement( 306 parser_->BuildIteratorNextResult(
275 descriptor_->parser->BuildIteratorNextResult( 307 factory()->NewVariableProxy(iterator),
276 factory()->NewVariableProxy(iterator), result, 308 result, RelocInfo::kNoPosition),
277 RelocInfo::kNoPosition), 309 RelocInfo::kNoPosition),
278 RelocInfo::kNoPosition), 310 zone());
279 zone());
280 311
281 auto assign_to_done = factory()->NewAssignment( 312 auto assign_to_done = factory()->NewAssignment(
282 Token::ASSIGN, factory()->NewVariableProxy(done), 313 Token::ASSIGN, factory()->NewVariableProxy(done),
283 factory()->NewProperty( 314 factory()->NewProperty(
284 factory()->NewVariableProxy(result), 315 factory()->NewVariableProxy(result),
285 factory()->NewStringLiteral(ast_value_factory()->done_string(), 316 factory()->NewStringLiteral(ast_value_factory()->done_string(),
286 RelocInfo::kNoPosition), 317 RelocInfo::kNoPosition),
287 RelocInfo::kNoPosition), 318 RelocInfo::kNoPosition),
288 RelocInfo::kNoPosition); 319 RelocInfo::kNoPosition);
289 auto next_value = factory()->NewConditional( 320 auto next_value = factory()->NewConditional(
(...skipping 26 matching lines...) Expand all
316 } 347 }
317 348
318 if (spread != nullptr) { 349 if (spread != nullptr) {
319 // array = []; 350 // array = [];
320 // if (!done) %concat_iterable_to_array(array, iterator); 351 // if (!done) %concat_iterable_to_array(array, iterator);
321 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone()); 352 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
322 auto array = CreateTempVar(factory()->NewArrayLiteral( 353 auto array = CreateTempVar(factory()->NewArrayLiteral(
323 empty_exprs, 354 empty_exprs,
324 // Reuse pattern's literal index - it is unused since there is no 355 // Reuse pattern's literal index - it is unused since there is no
325 // actual literal allocated. 356 // actual literal allocated.
326 node->literal_index(), is_strong(descriptor_->parser->language_mode()), 357 node->literal_index(), is_strong(scope_->language_mode()),
327 RelocInfo::kNoPosition)); 358 RelocInfo::kNoPosition));
328 359
329 auto arguments = new (zone()) ZoneList<Expression*>(2, zone()); 360 auto arguments = new (zone()) ZoneList<Expression*>(2, zone());
330 arguments->Add(factory()->NewVariableProxy(array), zone()); 361 arguments->Add(factory()->NewVariableProxy(array), zone());
331 arguments->Add(factory()->NewVariableProxy(iterator), zone()); 362 arguments->Add(factory()->NewVariableProxy(iterator), zone());
332 auto spread_into_array_call = 363 auto spread_into_array_call =
333 factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX, 364 factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX,
334 arguments, RelocInfo::kNoPosition); 365 arguments, RelocInfo::kNoPosition);
335 366
336 auto if_statement = factory()->NewIfStatement( 367 auto if_statement = factory()->NewIfStatement(
(...skipping 10 matching lines...) Expand all
347 factory()->NewVariableProxy(array)); 378 factory()->NewVariableProxy(array));
348 } 379 }
349 } 380 }
350 381
351 382
352 void Parser::PatternRewriter::VisitAssignment(Assignment* node) { 383 void Parser::PatternRewriter::VisitAssignment(Assignment* node) {
353 // let {<pattern> = <init>} = <value> 384 // let {<pattern> = <init>} = <value>
354 // becomes 385 // becomes
355 // temp = <value>; 386 // temp = <value>;
356 // <pattern> = temp === undefined ? <init> : temp; 387 // <pattern> = temp === undefined ? <init> : temp;
388 PatternContext old_context = context();
389 if (old_context == BINDING) {
390 set_context(INITIALIZER);
391 } else {
392 set_context(ASSIGNMENT);
393 RecurseIntoSubpattern(node->target(), node->value());
394 return set_context(old_context);
395 }
396
357 DCHECK(node->op() == Token::ASSIGN); 397 DCHECK(node->op() == Token::ASSIGN);
358 auto temp = CreateTempVar(current_value_); 398 auto temp = CreateTempVar(current_value_);
359 Expression* is_undefined = factory()->NewCompareOperation( 399 Expression* is_undefined = factory()->NewCompareOperation(
360 Token::EQ_STRICT, factory()->NewVariableProxy(temp), 400 Token::EQ_STRICT, factory()->NewVariableProxy(temp),
361 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), 401 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
362 RelocInfo::kNoPosition); 402 RelocInfo::kNoPosition);
363 Expression* initializer = node->value(); 403 Expression* initializer = node->value();
364 if (descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER && 404 if (descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER &&
365 descriptor_->scope->is_arrow_scope()) { 405 descriptor_->scope->is_arrow_scope()) {
366 // TODO(adamk): Only call this if necessary. 406 // TODO(adamk): Only call this if necessary.
367 RewriteParameterInitializerScope( 407 RewriteParameterInitializerScope(
368 descriptor_->parser->stack_limit(), initializer, 408 descriptor_->parser->stack_limit(), initializer,
369 descriptor_->scope->outer_scope(), descriptor_->scope); 409 descriptor_->scope->outer_scope(), descriptor_->scope);
370 } 410 }
371 Expression* value = factory()->NewConditional( 411 Expression* value = factory()->NewConditional(
372 is_undefined, initializer, factory()->NewVariableProxy(temp), 412 is_undefined, initializer, factory()->NewVariableProxy(temp),
373 RelocInfo::kNoPosition); 413 RelocInfo::kNoPosition);
374 RecurseIntoSubpattern(node->target(), value); 414 RecurseIntoSubpattern(node->target(), value);
415 set_context(old_context);
375 } 416 }
376 417
377 418
419 void Parser::PatternRewriter::VisitAssignmentPattern(AssignmentPattern* node) {
420 if (node->is_rewritten()) return;
421
422 Block* old_block = block_;
423 int pos = node->position();
424 block_ = factory()->NewBlock(nullptr, 8, false, pos);
425 Variable* temp = nullptr;
426 if (node->pattern()->IsObjectLiteral()) {
427 VisitObjectLiteral(node->pattern()->AsObjectLiteral(), &temp);
428 } else if (node->pattern()->IsArrayLiteral()) {
429 VisitArrayLiteral(node->pattern()->AsArrayLiteral(), &temp);
430 }
431 DCHECK_NOT_NULL(temp);
432 DoExpression* expr = factory()->NewDoExpression(block_, temp, pos);
adamk 2015/11/20 22:42:59 Looks like this creates a DoExpression even for de
433 node->set_expression(expr);
434 block_ = old_block;
435 if (block_) {
436 block_->statements()->Add(factory()->NewExpressionStatement(expr, pos),
437 zone());
438 }
439 }
440
441 // =============== AssignmentPattern only ==================
442
443 void Parser::PatternRewriter::VisitProperty(v8::internal::Property* node) {
444 DCHECK_EQ(context(), ASSIGNMENT);
445 Expression* value = current_value_;
446 Assignment* assignment =
447 factory()->NewAssignment(Token::ASSIGN, node, value, node->position());
448 block_->statements()->Add(
449 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
450 zone());
451 }
452
378 // =============== UNREACHABLE ============================= 453 // =============== UNREACHABLE =============================
379 454
380 void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); } 455 void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); }
381 456
382 #define NOT_A_PATTERN(Node) \ 457 #define NOT_A_PATTERN(Node) \
383 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \ 458 void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \
384 UNREACHABLE(); \ 459 UNREACHABLE(); \
385 } 460 }
386 461
387 NOT_A_PATTERN(BinaryOperation) 462 NOT_A_PATTERN(BinaryOperation)
(...skipping 17 matching lines...) Expand all
405 NOT_A_PATTERN(ExpressionStatement) 480 NOT_A_PATTERN(ExpressionStatement)
406 NOT_A_PATTERN(ForInStatement) 481 NOT_A_PATTERN(ForInStatement)
407 NOT_A_PATTERN(ForOfStatement) 482 NOT_A_PATTERN(ForOfStatement)
408 NOT_A_PATTERN(ForStatement) 483 NOT_A_PATTERN(ForStatement)
409 NOT_A_PATTERN(FunctionDeclaration) 484 NOT_A_PATTERN(FunctionDeclaration)
410 NOT_A_PATTERN(FunctionLiteral) 485 NOT_A_PATTERN(FunctionLiteral)
411 NOT_A_PATTERN(IfStatement) 486 NOT_A_PATTERN(IfStatement)
412 NOT_A_PATTERN(ImportDeclaration) 487 NOT_A_PATTERN(ImportDeclaration)
413 NOT_A_PATTERN(Literal) 488 NOT_A_PATTERN(Literal)
414 NOT_A_PATTERN(NativeFunctionLiteral) 489 NOT_A_PATTERN(NativeFunctionLiteral)
415 NOT_A_PATTERN(Property)
416 NOT_A_PATTERN(RegExpLiteral) 490 NOT_A_PATTERN(RegExpLiteral)
417 NOT_A_PATTERN(ReturnStatement) 491 NOT_A_PATTERN(ReturnStatement)
418 NOT_A_PATTERN(SloppyBlockFunctionStatement) 492 NOT_A_PATTERN(SloppyBlockFunctionStatement)
419 NOT_A_PATTERN(Spread) 493 NOT_A_PATTERN(Spread)
420 NOT_A_PATTERN(SuperPropertyReference) 494 NOT_A_PATTERN(SuperPropertyReference)
421 NOT_A_PATTERN(SuperCallReference) 495 NOT_A_PATTERN(SuperCallReference)
422 NOT_A_PATTERN(SwitchStatement) 496 NOT_A_PATTERN(SwitchStatement)
423 NOT_A_PATTERN(ThisFunction) 497 NOT_A_PATTERN(ThisFunction)
424 NOT_A_PATTERN(Throw) 498 NOT_A_PATTERN(Throw)
425 NOT_A_PATTERN(TryCatchStatement) 499 NOT_A_PATTERN(TryCatchStatement)
426 NOT_A_PATTERN(TryFinallyStatement) 500 NOT_A_PATTERN(TryFinallyStatement)
427 NOT_A_PATTERN(UnaryOperation) 501 NOT_A_PATTERN(UnaryOperation)
428 NOT_A_PATTERN(VariableDeclaration) 502 NOT_A_PATTERN(VariableDeclaration)
429 NOT_A_PATTERN(WhileStatement) 503 NOT_A_PATTERN(WhileStatement)
430 NOT_A_PATTERN(WithStatement) 504 NOT_A_PATTERN(WithStatement)
431 NOT_A_PATTERN(Yield) 505 NOT_A_PATTERN(Yield)
432 506
433 #undef NOT_A_PATTERN 507 #undef NOT_A_PATTERN
434 } // namespace internal 508 } // namespace internal
435 } // namespace v8 509 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698