OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast.h" | 8 #include "src/ast.h" |
9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
(...skipping 2293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2304 // | 2304 // |
2305 // ConstDeclaration :: | 2305 // ConstDeclaration :: |
2306 // const ConstBinding (',' ConstBinding)* ';' | 2306 // const ConstBinding (',' ConstBinding)* ';' |
2307 // ConstBinding :: | 2307 // ConstBinding :: |
2308 // Identifier '=' AssignmentExpression | 2308 // Identifier '=' AssignmentExpression |
2309 // | 2309 // |
2310 // TODO(ES6): | 2310 // TODO(ES6): |
2311 // ConstBinding :: | 2311 // ConstBinding :: |
2312 // BindingPattern '=' AssignmentExpression | 2312 // BindingPattern '=' AssignmentExpression |
2313 | 2313 |
2314 int pos = peek_position(); | 2314 PatternMatcher::DeclarationDescriptor decl; |
2315 VariableMode mode = VAR; | 2315 decl.parser = this; |
2316 decl.pos = peek_position(); | |
2317 decl.mode = VAR; | |
2316 // True if the binding needs initialization. 'let' and 'const' declared | 2318 // True if the binding needs initialization. 'let' and 'const' declared |
2317 // bindings are created uninitialized by their declaration nodes and | 2319 // bindings are created uninitialized by their declaration nodes and |
2318 // need initialization. 'var' declared bindings are always initialized | 2320 // need initialization. 'var' declared bindings are always initialized |
2319 // immediately by their declaration nodes. | 2321 // immediately by their declaration nodes. |
2320 bool needs_init = false; | 2322 decl.needs_init = false; |
2321 bool is_const = false; | 2323 decl.is_const = false; |
2322 Token::Value init_op = Token::INIT_VAR; | 2324 decl.init_op = Token::INIT_VAR; |
2325 decl.names = names; | |
2323 if (peek() == Token::VAR) { | 2326 if (peek() == Token::VAR) { |
2324 if (is_strong(language_mode())) { | 2327 if (is_strong(language_mode())) { |
2325 Scanner::Location location = scanner()->peek_location(); | 2328 Scanner::Location location = scanner()->peek_location(); |
2326 ReportMessageAt(location, "strong_var"); | 2329 ReportMessageAt(location, "strong_var"); |
2327 *ok = false; | 2330 *ok = false; |
2328 return NULL; | 2331 return NULL; |
2329 } | 2332 } |
2330 Consume(Token::VAR); | 2333 Consume(Token::VAR); |
2331 } else if (peek() == Token::CONST) { | 2334 } else if (peek() == Token::CONST) { |
2332 Consume(Token::CONST); | 2335 Consume(Token::CONST); |
2333 if (is_sloppy(language_mode())) { | 2336 if (is_sloppy(language_mode())) { |
2334 mode = CONST_LEGACY; | 2337 decl.mode = CONST_LEGACY; |
2335 init_op = Token::INIT_CONST_LEGACY; | 2338 decl.init_op = Token::INIT_CONST_LEGACY; |
2336 ++use_counts_[v8::Isolate::kLegacyConst]; | 2339 ++use_counts_[v8::Isolate::kLegacyConst]; |
2337 } else { | 2340 } else { |
2338 DCHECK(var_context != kStatement); | 2341 DCHECK(var_context != kStatement); |
2339 mode = CONST; | 2342 decl.mode = CONST; |
2340 init_op = Token::INIT_CONST; | 2343 decl.init_op = Token::INIT_CONST; |
2341 } | 2344 } |
2342 is_const = true; | 2345 decl.is_const = true; |
2343 needs_init = true; | 2346 decl.needs_init = true; |
2344 } else if (peek() == Token::LET && is_strict(language_mode())) { | 2347 } else if (peek() == Token::LET && is_strict(language_mode())) { |
2345 Consume(Token::LET); | 2348 Consume(Token::LET); |
2346 DCHECK(var_context != kStatement); | 2349 DCHECK(var_context != kStatement); |
2347 mode = LET; | 2350 decl.mode = LET; |
2348 needs_init = true; | 2351 decl.needs_init = true; |
2349 init_op = Token::INIT_LET; | 2352 decl.init_op = Token::INIT_LET; |
2350 } else { | 2353 } else { |
2351 UNREACHABLE(); // by current callers | 2354 UNREACHABLE(); // by current callers |
2352 } | 2355 } |
2353 | 2356 |
2354 Scope* declaration_scope = DeclarationScope(mode); | 2357 decl.declaration_scope = DeclarationScope(decl.mode); |
2358 decl.scope = scope_; | |
2359 | |
2355 | 2360 |
2356 // The scope of a var/const declared variable anywhere inside a function | 2361 // The scope of a var/const declared variable anywhere inside a function |
2357 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can | 2362 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can |
2358 // transform a source-level var/const declaration into a (Function) | 2363 // transform a source-level var/const declaration into a (Function) |
2359 // Scope declaration, and rewrite the source-level initialization into an | 2364 // Scope declaration, and rewrite the source-level initialization into an |
2360 // assignment statement. We use a block to collect multiple assignments. | 2365 // assignment statement. We use a block to collect multiple assignments. |
2361 // | 2366 // |
2362 // We mark the block as initializer block because we don't want the | 2367 // We mark the block as initializer block because we don't want the |
2363 // rewriter to add a '.result' assignment to such a block (to get compliant | 2368 // rewriter to add a '.result' assignment to such a block (to get compliant |
2364 // behavior for code such as print(eval('var x = 7')), and for cosmetic | 2369 // behavior for code such as print(eval('var x = 7')), and for cosmetic |
2365 // reasons when pretty-printing. Also, unless an assignment (initialization) | 2370 // reasons when pretty-printing. Also, unless an assignment (initialization) |
2366 // is inside an initializer block, it is ignored. | 2371 // is inside an initializer block, it is ignored. |
2367 // | 2372 // |
2368 // Create new block with one expected declaration. | 2373 // Create new block with one expected declaration. |
rossberg
2015/05/11 11:49:33
Nit: Is the "one" comment still accurate?
Dmitry Lomov (no reviews)
2015/05/11 12:52:57
Yes - we still expect 1 declaration in the majorit
| |
2369 Block* block = factory()->NewBlock(NULL, 1, true, pos); | 2374 decl.block = factory()->NewBlock(NULL, 1, true, decl.pos); |
2370 int nvars = 0; // the number of variables declared | 2375 int nvars = 0; // the number of variables declared |
2376 decl.nvars = &nvars; | |
rossberg
2015/05/11 11:49:33
Why not move nvars itself to decl, instead of a po
Dmitry Lomov (no reviews)
2015/05/11 12:52:57
I want to keep decl_ const in PatternRewriter.
rossberg
2015/05/11 13:18:29
Hm, I see. In that case I'd rather pass the pointe
| |
2371 int bindings_start = peek_position(); | 2377 int bindings_start = peek_position(); |
2372 const AstRawString* name = NULL; | |
2373 const AstRawString* first_name = NULL; | 2378 const AstRawString* first_name = NULL; |
2374 bool is_for_iteration_variable; | 2379 bool is_for_iteration_variable; |
2375 do { | 2380 do { |
2376 if (fni_ != NULL) fni_->Enter(); | 2381 if (fni_ != NULL) fni_->Enter(); |
2377 | 2382 |
2378 // Parse variable name. | 2383 // Parse variable name. |
2379 if (nvars > 0) Consume(Token::COMMA); | 2384 if (nvars > 0) Consume(Token::COMMA); |
2380 | 2385 |
2386 PatternMatcher pattern_matcher; | |
2381 { | 2387 { |
2382 ExpressionClassifier pattern_classifier; | 2388 ExpressionClassifier pattern_classifier; |
2383 Token::Value next = peek(); | 2389 Token::Value next = peek(); |
2384 Expression* pattern = | 2390 Expression* pattern = |
2385 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); | 2391 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); |
2386 ValidateBindingPattern(&pattern_classifier, CHECK_OK); | 2392 ValidateBindingPattern(&pattern_classifier, CHECK_OK); |
2387 if (pattern->IsVariableProxy() && | 2393 pattern_matcher = PatternMatcher(&decl, pattern); |
2388 pattern->AsVariableProxy()->IsValidReferenceExpression()) { | 2394 if (!allow_harmony_destructuring() && |
2389 scope_->RemoveUnresolved(pattern->AsVariableProxy()); | 2395 !pattern_matcher.IsSingleVariableBinding()) { |
2390 name = pattern->AsVariableProxy()->raw_name(); | |
2391 } else if (allow_harmony_destructuring()) { | |
2392 // TODO(dslomov): really destructure. | |
2393 name = ast_value_factory()->GetOneByteString(".temp.variable"); | |
2394 } else { | |
2395 ReportUnexpectedToken(next); | 2396 ReportUnexpectedToken(next); |
2396 *ok = false; | 2397 *ok = false; |
2397 return nullptr; | 2398 return nullptr; |
2398 } | 2399 } |
2400 | |
2401 // TODO(dslomov): unify | |
2399 } | 2402 } |
2400 | 2403 |
2401 if (!first_name) first_name = name; | |
2402 Scanner::Location variable_loc = scanner()->location(); | 2404 Scanner::Location variable_loc = scanner()->location(); |
2403 if (fni_ != NULL) fni_->PushVariableName(name); | 2405 const bool single_name = pattern_matcher.IsSingleVariableBinding(); |
2406 if (single_name) { | |
2407 if (!first_name) first_name = pattern_matcher.SingleName(); | |
2408 if (fni_ != NULL) fni_->PushVariableName(pattern_matcher.SingleName()); | |
2409 } | |
2404 | 2410 |
2405 // Declare variable. | |
2406 // Note that we *always* must treat the initial value via a separate init | |
2407 // assignment for variables and constants because the value must be assigned | |
2408 // when the variable is encountered in the source. But the variable/constant | |
2409 // is declared (and set to 'undefined') upon entering the function within | |
2410 // which the variable or constant is declared. Only function variables have | |
2411 // an initial value in the declaration (because they are initialized upon | |
2412 // entering the function). | |
2413 // | |
2414 // If we have a const declaration, in an inner scope, the proxy is always | |
2415 // bound to the declared variable (independent of possibly surrounding with | |
2416 // statements). | |
2417 // For let/const declarations in harmony mode, we can also immediately | |
2418 // pre-resolve the proxy because it resides in the same scope as the | |
2419 // declaration. | |
2420 is_for_iteration_variable = | 2411 is_for_iteration_variable = |
2421 var_context == kForStatement && | 2412 var_context == kForStatement && |
2422 (peek() == Token::IN || PeekContextualKeyword(CStrVector("of"))); | 2413 (peek() == Token::IN || PeekContextualKeyword(CStrVector("of"))); |
2423 if (is_for_iteration_variable && mode == CONST) { | 2414 if (is_for_iteration_variable && decl.mode == CONST) { |
2424 needs_init = false; | 2415 decl.needs_init = false; |
2425 } | 2416 } |
2426 | |
2427 VariableProxy* proxy = NewUnresolved(name, mode); | |
2428 Declaration* declaration = | |
2429 factory()->NewVariableDeclaration(proxy, mode, scope_, pos); | |
2430 Variable* var = Declare(declaration, mode != VAR, CHECK_OK); | |
2431 DCHECK_NOT_NULL(var); | |
2432 DCHECK(!proxy->is_resolved() || proxy->var() == var); | |
2433 nvars++; | |
2434 if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) { | |
2435 ReportMessage("too_many_variables"); | |
2436 *ok = false; | |
2437 return NULL; | |
2438 } | |
2439 if (names) names->Add(name, zone()); | |
2440 | |
2441 // Parse initialization expression if present and/or needed. A | 2417 // Parse initialization expression if present and/or needed. A |
rossberg
2015/05/11 11:49:33
The remainder of this comment mainly explains the
Dmitry Lomov (no reviews)
2015/05/11 12:52:57
Done.
| |
2442 // declaration of the form: | 2418 // declaration of the form: |
2443 // | 2419 // |
2444 // var v = x; | 2420 // var v = x; |
2445 // | 2421 // |
2446 // is syntactic sugar for: | 2422 // is syntactic sugar for: |
2447 // | 2423 // |
2448 // var v; v = x; | 2424 // var v; v = x; |
2449 // | 2425 // |
2426 | |
2450 // In particular, we need to re-lookup 'v' (in scope_, not | 2427 // In particular, we need to re-lookup 'v' (in scope_, not |
2451 // declaration_scope) as it may be a different 'v' than the 'v' in the | 2428 // declaration_scope) as it may be a different 'v' than the 'v' in the |
2452 // declaration (e.g., if we are inside a 'with' statement or 'catch' | 2429 // declaration (e.g., if we are inside a 'with' statement or 'catch' |
2453 // block). | 2430 // block). |
2454 // | 2431 // |
2455 // However, note that const declarations are different! A const | 2432 // However, note that const declarations are different! A const |
2456 // declaration of the form: | 2433 // declaration of the form: |
2457 // | 2434 // |
2458 // const c = x; | 2435 // const c = x; |
2459 // | 2436 // |
2460 // is *not* syntactic sugar for: | 2437 // is *not* syntactic sugar for: |
2461 // | 2438 // |
2462 // const c; c = x; | 2439 // const c; c = x; |
2463 // | 2440 // |
2464 // The "variable" c initialized to x is the same as the declared | 2441 // The "variable" c initialized to x is the same as the declared |
2465 // one - there is no re-lookup (see the last parameter of the | 2442 // one - there is no re-lookup (see the last parameter of the |
2466 // Declare() call above). | 2443 // Declare() call above). |
2467 | 2444 |
2468 Scope* initialization_scope = is_const ? declaration_scope : scope_; | |
2469 Expression* value = NULL; | 2445 Expression* value = NULL; |
2470 int pos = -1; | 2446 decl.pos = -1; |
2447 decl.initializer_position = -1; | |
2471 // Harmony consts have non-optional initializers. | 2448 // Harmony consts have non-optional initializers. |
2472 if (peek() == Token::ASSIGN || | 2449 if (peek() == Token::ASSIGN || |
2473 (mode == CONST && !is_for_iteration_variable)) { | 2450 (decl.mode == CONST && !is_for_iteration_variable)) { |
2474 Expect(Token::ASSIGN, CHECK_OK); | 2451 Expect(Token::ASSIGN, CHECK_OK); |
2475 pos = position(); | 2452 decl.pos = position(); |
2476 ExpressionClassifier classifier; | 2453 ExpressionClassifier classifier; |
2477 value = ParseAssignmentExpression(var_context != kForStatement, | 2454 value = ParseAssignmentExpression(var_context != kForStatement, |
2478 &classifier, CHECK_OK); | 2455 &classifier, CHECK_OK); |
2479 ValidateExpression(&classifier, CHECK_OK); | 2456 ValidateExpression(&classifier, CHECK_OK); |
2480 variable_loc.end_pos = scanner()->location().end_pos; | 2457 variable_loc.end_pos = scanner()->location().end_pos; |
2481 | 2458 |
2482 if (first_initializer_loc && !first_initializer_loc->IsValid()) { | 2459 if (first_initializer_loc && !first_initializer_loc->IsValid()) { |
2483 *first_initializer_loc = variable_loc; | 2460 *first_initializer_loc = variable_loc; |
2484 } | 2461 } |
2485 | 2462 |
2486 // Don't infer if it is "a = function(){...}();"-like expression. | 2463 // Don't infer if it is "a = function(){...}();"-like expression. |
2487 if (fni_ != NULL && | 2464 if (single_name) { |
2488 value->AsCall() == NULL && | 2465 if (fni_ != NULL && value->AsCall() == NULL && |
2489 value->AsCallNew() == NULL) { | 2466 value->AsCallNew() == NULL) { |
2490 fni_->Infer(); | 2467 fni_->Infer(); |
2491 } else { | 2468 } else { |
2492 fni_->RemoveLastFunction(); | 2469 fni_->RemoveLastFunction(); |
2470 } | |
2493 } | 2471 } |
2494 // End position of the initializer is after the assignment expression. | 2472 // End position of the initializer is after the assignment expression. |
2495 var->set_initializer_position(scanner()->location().end_pos); | 2473 decl.initializer_position = scanner()->location().end_pos; |
2496 } else { | 2474 } else { |
2497 // End position of the initializer is after the variable. | 2475 // End position of the initializer is after the variable. |
2498 var->set_initializer_position(position()); | 2476 decl.initializer_position = position(); |
2499 } | 2477 } |
2500 | 2478 |
2501 // Make sure that 'const x' and 'let x' initialize 'x' to undefined. | 2479 // Make sure that 'const x' and 'let x' initialize 'x' to undefined. |
2502 if (value == NULL && needs_init) { | 2480 if (value == NULL && decl.needs_init) { |
2503 value = GetLiteralUndefined(position()); | 2481 value = GetLiteralUndefined(position()); |
2504 } | 2482 } |
2505 | 2483 |
2506 // Global variable declarations must be compiled in a specific | 2484 pattern_matcher.DeclareAndInitializeVariables(value, CHECK_OK); |
2507 // way. When the script containing the global variable declaration | |
2508 // is entered, the global variable must be declared, so that if it | |
2509 // doesn't exist (on the global object itself, see ES5 errata) it | |
2510 // gets created with an initial undefined value. This is handled | |
2511 // by the declarations part of the function representing the | |
2512 // top-level global code; see Runtime::DeclareGlobalVariable. If | |
2513 // it already exists (in the object or in a prototype), it is | |
2514 // *not* touched until the variable declaration statement is | |
2515 // executed. | |
2516 // | |
2517 // Executing the variable declaration statement will always | |
2518 // guarantee to give the global object an own property. | |
2519 // This way, global variable declarations can shadow | |
2520 // properties in the prototype chain, but only after the variable | |
2521 // declaration statement has been executed. This is important in | |
2522 // browsers where the global object (window) has lots of | |
2523 // properties defined in prototype objects. | |
2524 if (initialization_scope->is_script_scope() && | |
2525 !IsLexicalVariableMode(mode)) { | |
2526 // Compute the arguments for the runtime call. | |
2527 ZoneList<Expression*>* arguments = | |
2528 new(zone()) ZoneList<Expression*>(3, zone()); | |
2529 // We have at least 1 parameter. | |
2530 arguments->Add(factory()->NewStringLiteral(name, pos), zone()); | |
2531 CallRuntime* initialize; | |
2532 | 2485 |
2533 if (is_const) { | 2486 if (single_name && fni_ != NULL) fni_->Leave(); |
2534 arguments->Add(value, zone()); | |
2535 value = NULL; // zap the value to avoid the unnecessary assignment | |
2536 | |
2537 // Construct the call to Runtime_InitializeConstGlobal | |
2538 // and add it to the initialization statement block. | |
2539 // Note that the function does different things depending on | |
2540 // the number of arguments (1 or 2). | |
2541 initialize = factory()->NewCallRuntime( | |
2542 ast_value_factory()->initialize_const_global_string(), | |
2543 Runtime::FunctionForId(Runtime::kInitializeConstGlobal), arguments, | |
2544 pos); | |
2545 } else { | |
2546 // Add language mode. | |
2547 // We may want to pass singleton to avoid Literal allocations. | |
2548 LanguageMode language_mode = initialization_scope->language_mode(); | |
2549 arguments->Add(factory()->NewNumberLiteral(language_mode, pos), zone()); | |
2550 | |
2551 // Be careful not to assign a value to the global variable if | |
2552 // we're in a with. The initialization value should not | |
2553 // necessarily be stored in the global object in that case, | |
2554 // which is why we need to generate a separate assignment node. | |
2555 if (value != NULL && !inside_with()) { | |
2556 arguments->Add(value, zone()); | |
2557 value = NULL; // zap the value to avoid the unnecessary assignment | |
2558 // Construct the call to Runtime_InitializeVarGlobal | |
2559 // and add it to the initialization statement block. | |
2560 initialize = factory()->NewCallRuntime( | |
2561 ast_value_factory()->initialize_var_global_string(), | |
2562 Runtime::FunctionForId(Runtime::kInitializeVarGlobal), arguments, | |
2563 pos); | |
2564 } else { | |
2565 initialize = NULL; | |
2566 } | |
2567 } | |
2568 | |
2569 if (initialize != NULL) { | |
2570 block->AddStatement(factory()->NewExpressionStatement( | |
2571 initialize, RelocInfo::kNoPosition), | |
2572 zone()); | |
2573 } | |
2574 } else if (needs_init) { | |
2575 // Constant initializations always assign to the declared constant which | |
2576 // is always at the function scope level. This is only relevant for | |
2577 // dynamically looked-up variables and constants (the start context for | |
2578 // constant lookups is always the function context, while it is the top | |
2579 // context for var declared variables). Sigh... | |
2580 // For 'let' and 'const' declared variables in harmony mode the | |
2581 // initialization also always assigns to the declared variable. | |
2582 DCHECK(proxy != NULL); | |
2583 DCHECK(proxy->var() != NULL); | |
2584 DCHECK(value != NULL); | |
2585 Assignment* assignment = | |
2586 factory()->NewAssignment(init_op, proxy, value, pos); | |
2587 block->AddStatement( | |
2588 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), | |
2589 zone()); | |
2590 value = NULL; | |
2591 } | |
2592 | |
2593 // Add an assignment node to the initialization statement block if we still | |
2594 // have a pending initialization value. | |
2595 if (value != NULL) { | |
2596 DCHECK(mode == VAR); | |
2597 // 'var' initializations are simply assignments (with all the consequences | |
2598 // if they are inside a 'with' statement - they may change a 'with' object | |
2599 // property). | |
2600 VariableProxy* proxy = | |
2601 initialization_scope->NewUnresolved(factory(), name); | |
2602 Assignment* assignment = | |
2603 factory()->NewAssignment(init_op, proxy, value, pos); | |
2604 block->AddStatement( | |
2605 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), | |
2606 zone()); | |
2607 } | |
2608 | |
2609 if (fni_ != NULL) fni_->Leave(); | |
2610 } while (peek() == Token::COMMA); | 2487 } while (peek() == Token::COMMA); |
2611 | 2488 |
2612 if (bindings_loc) { | 2489 if (bindings_loc) { |
2613 *bindings_loc = | 2490 *bindings_loc = |
2614 Scanner::Location(bindings_start, scanner()->location().end_pos); | 2491 Scanner::Location(bindings_start, scanner()->location().end_pos); |
2615 } | 2492 } |
2616 | 2493 |
2617 if (num_decl) *num_decl = nvars; | 2494 if (num_decl) *num_decl = nvars; |
2618 *out = first_name; | 2495 *out = first_name; |
2619 | 2496 |
2620 return block; | 2497 return decl.block; |
2621 } | 2498 } |
2622 | 2499 |
2623 | 2500 |
2624 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, | 2501 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, |
2625 const AstRawString* label) { | 2502 const AstRawString* label) { |
2626 DCHECK(label != NULL); | 2503 DCHECK(label != NULL); |
2627 if (labels != NULL) { | 2504 if (labels != NULL) { |
2628 for (int i = labels->length(); i-- > 0; ) { | 2505 for (int i = labels->length(); i-- > 0; ) { |
2629 if (labels->at(i) == label) { | 2506 if (labels->at(i) == label) { |
2630 return true; | 2507 return true; |
(...skipping 3289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5920 | 5797 |
5921 Expression* Parser::SpreadCallNew(Expression* function, | 5798 Expression* Parser::SpreadCallNew(Expression* function, |
5922 ZoneList<v8::internal::Expression*>* args, | 5799 ZoneList<v8::internal::Expression*>* args, |
5923 int pos) { | 5800 int pos) { |
5924 args->InsertAt(0, function, zone()); | 5801 args->InsertAt(0, function, zone()); |
5925 | 5802 |
5926 return factory()->NewCallRuntime( | 5803 return factory()->NewCallRuntime( |
5927 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 5804 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
5928 } | 5805 } |
5929 } } // namespace v8::internal | 5806 } } // namespace v8::internal |
OLD | NEW |