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