| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 | 728 |
| 729 mode_ = PARSE_EAGERLY; | 729 mode_ = PARSE_EAGERLY; |
| 730 | 730 |
| 731 // Place holder for the result. | 731 // Place holder for the result. |
| 732 FunctionLiteral* result = NULL; | 732 FunctionLiteral* result = NULL; |
| 733 | 733 |
| 734 { | 734 { |
| 735 // Parse the function literal. | 735 // Parse the function literal. |
| 736 Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE); | 736 Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE); |
| 737 if (!info->closure().is_null()) { | 737 if (!info->closure().is_null()) { |
| 738 scope = Scope::DeserializeScopeChain(info, scope); | 738 scope = Scope::DeserializeScopeChain(info->closure()->context(), scope); |
| 739 } | 739 } |
| 740 FunctionState function_state(this, scope, isolate()); | 740 FunctionState function_state(this, scope, isolate()); |
| 741 ASSERT(scope->strict_mode_flag() == kNonStrictMode || | 741 ASSERT(scope->strict_mode_flag() == kNonStrictMode || |
| 742 scope->strict_mode_flag() == info->strict_mode_flag()); | 742 scope->strict_mode_flag() == info->strict_mode_flag()); |
| 743 ASSERT(info->strict_mode_flag() == shared_info->strict_mode_flag()); | 743 ASSERT(info->strict_mode_flag() == shared_info->strict_mode_flag()); |
| 744 scope->SetStrictModeFlag(shared_info->strict_mode_flag()); | 744 scope->SetStrictModeFlag(shared_info->strict_mode_flag()); |
| 745 FunctionLiteral::Type type = shared_info->is_expression() | 745 FunctionLiteral::Type type = shared_info->is_expression() |
| 746 ? (shared_info->is_anonymous() | 746 ? (shared_info->is_anonymous() |
| 747 ? FunctionLiteral::ANONYMOUS_EXPRESSION | 747 ? FunctionLiteral::ANONYMOUS_EXPRESSION |
| 748 : FunctionLiteral::NAMED_EXPRESSION) | 748 : FunctionLiteral::NAMED_EXPRESSION) |
| (...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1355 bool resolve, | 1355 bool resolve, |
| 1356 bool* ok) { | 1356 bool* ok) { |
| 1357 Variable* var = NULL; | 1357 Variable* var = NULL; |
| 1358 // If we are inside a function, a declaration of a var/const variable is a | 1358 // If we are inside a function, a declaration of a var/const variable is a |
| 1359 // truly local variable, and the scope of the variable is always the function | 1359 // truly local variable, and the scope of the variable is always the function |
| 1360 // scope. | 1360 // scope. |
| 1361 // Let/const variables in harmony mode are always added to the immediately | 1361 // Let/const variables in harmony mode are always added to the immediately |
| 1362 // enclosing scope. | 1362 // enclosing scope. |
| 1363 Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY) | 1363 Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY) |
| 1364 ? top_scope_ : top_scope_->DeclarationScope(); | 1364 ? top_scope_ : top_scope_->DeclarationScope(); |
| 1365 InitializationFlag init_flag = (fun != NULL || mode == VAR) |
| 1366 ? kCreatedInitialized : kNeedsInitialization; |
| 1365 | 1367 |
| 1366 // If a function scope exists, then we can statically declare this | 1368 // If a function scope exists, then we can statically declare this |
| 1367 // variable and also set its mode. In any case, a Declaration node | 1369 // variable and also set its mode. In any case, a Declaration node |
| 1368 // will be added to the scope so that the declaration can be added | 1370 // will be added to the scope so that the declaration can be added |
| 1369 // to the corresponding activation frame at runtime if necessary. | 1371 // to the corresponding activation frame at runtime if necessary. |
| 1370 // For instance declarations inside an eval scope need to be added | 1372 // For instance declarations inside an eval scope need to be added |
| 1371 // to the calling function context. | 1373 // to the calling function context. |
| 1372 // Similarly, strict mode eval scope does not leak variable declarations to | 1374 // Similarly, strict mode eval scope does not leak variable declarations to |
| 1373 // the caller's scope so we declare all locals, too. | 1375 // the caller's scope so we declare all locals, too. |
| 1374 // Also for block scoped let/const bindings the variable can be | 1376 // Also for block scoped let/const bindings the variable can be |
| 1375 // statically declared. | 1377 // statically declared. |
| 1376 if (declaration_scope->is_function_scope() || | 1378 if (declaration_scope->is_function_scope() || |
| 1377 declaration_scope->is_strict_mode_eval_scope() || | 1379 declaration_scope->is_strict_mode_eval_scope() || |
| 1378 declaration_scope->is_block_scope()) { | 1380 declaration_scope->is_block_scope()) { |
| 1379 // Declare the variable in the function scope. | 1381 // Declare the variable in the function scope. |
| 1380 var = declaration_scope->LocalLookup(name); | 1382 var = declaration_scope->LocalLookup(name); |
| 1381 if (var == NULL) { | 1383 if (var == NULL) { |
| 1382 // Declare the name. | 1384 // Declare the name. |
| 1383 InitializationFlag init_flag = (fun != NULL || mode == VAR) | |
| 1384 ? kCreatedInitialized : kNeedsInitialization; | |
| 1385 var = declaration_scope->DeclareLocal(name, mode, init_flag); | 1385 var = declaration_scope->DeclareLocal(name, mode, init_flag); |
| 1386 } else { | 1386 } else { |
| 1387 // The name was declared in this scope before; check for conflicting | 1387 // The name was declared in this scope before; check for conflicting |
| 1388 // re-declarations. We have a conflict if either of the declarations is | 1388 // re-declarations. We have a conflict if either of the declarations is |
| 1389 // not a var. There is similar code in runtime.cc in the Declare | 1389 // not a var. There is similar code in runtime.cc in the Declare |
| 1390 // functions. The function CheckNonConflictingScope checks for conflicting | 1390 // functions. The function CheckNonConflictingScope checks for conflicting |
| 1391 // var and let bindings from different scopes whereas this is a check for | 1391 // var and let bindings from different scopes whereas this is a check for |
| 1392 // conflicting declarations within the same scope. This check also covers | 1392 // conflicting declarations within the same scope. This check also covers |
| 1393 // | 1393 // |
| 1394 // function () { let x; { var x; } } | 1394 // function () { let x; { var x; } } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1437 // WARNING: This will lead to multiple declaration nodes for the | 1437 // WARNING: This will lead to multiple declaration nodes for the |
| 1438 // same variable if it is declared several times. This is not a | 1438 // same variable if it is declared several times. This is not a |
| 1439 // semantic issue as long as we keep the source order, but it may be | 1439 // semantic issue as long as we keep the source order, but it may be |
| 1440 // a performance issue since it may lead to repeated | 1440 // a performance issue since it may lead to repeated |
| 1441 // Runtime::DeclareContextSlot() calls. | 1441 // Runtime::DeclareContextSlot() calls. |
| 1442 VariableProxy* proxy = declaration_scope->NewUnresolved( | 1442 VariableProxy* proxy = declaration_scope->NewUnresolved( |
| 1443 name, scanner().location().beg_pos); | 1443 name, scanner().location().beg_pos); |
| 1444 declaration_scope->AddDeclaration( | 1444 declaration_scope->AddDeclaration( |
| 1445 new(zone()) Declaration(proxy, mode, fun, top_scope_)); | 1445 new(zone()) Declaration(proxy, mode, fun, top_scope_)); |
| 1446 | 1446 |
| 1447 // For global const variables we bind the proxy to a variable. | |
| 1448 if ((mode == CONST || mode == CONST_HARMONY) && | 1447 if ((mode == CONST || mode == CONST_HARMONY) && |
| 1449 declaration_scope->is_global_scope()) { | 1448 declaration_scope->is_global_scope()) { |
| 1449 // For global const variables we bind the proxy to a variable. |
| 1450 ASSERT(resolve); // should be set by all callers | 1450 ASSERT(resolve); // should be set by all callers |
| 1451 Variable::Kind kind = Variable::NORMAL; | 1451 Variable::Kind kind = Variable::NORMAL; |
| 1452 var = new(zone()) Variable(declaration_scope, | 1452 var = new(zone()) Variable(declaration_scope, |
| 1453 name, | 1453 name, |
| 1454 CONST, | 1454 mode, |
| 1455 true, | 1455 true, |
| 1456 kind, | 1456 kind, |
| 1457 kNeedsInitialization); | 1457 kNeedsInitialization); |
| 1458 } else if (declaration_scope->is_eval_scope() && |
| 1459 !declaration_scope->is_strict_mode()) { |
| 1460 // For variable declarations in a non-strict eval scope the proxy is bound |
| 1461 // to a lookup variable to force a dynamic declaration using the |
| 1462 // DeclareContextSlot runtime function. |
| 1463 Variable::Kind kind = Variable::NORMAL; |
| 1464 var = new(zone()) Variable(declaration_scope, |
| 1465 name, |
| 1466 mode, |
| 1467 true, |
| 1468 kind, |
| 1469 init_flag); |
| 1470 var->AllocateTo(Variable::LOOKUP, -1); |
| 1471 resolve = true; |
| 1458 } | 1472 } |
| 1459 | 1473 |
| 1460 // If requested and we have a local variable, bind the proxy to the variable | 1474 // If requested and we have a local variable, bind the proxy to the variable |
| 1461 // at parse-time. This is used for functions (and consts) declared inside | 1475 // at parse-time. This is used for functions (and consts) declared inside |
| 1462 // statements: the corresponding function (or const) variable must be in the | 1476 // statements: the corresponding function (or const) variable must be in the |
| 1463 // function scope and not a statement-local scope, e.g. as provided with a | 1477 // function scope and not a statement-local scope, e.g. as provided with a |
| 1464 // 'with' statement: | 1478 // 'with' statement: |
| 1465 // | 1479 // |
| 1466 // with (obj) { | 1480 // with (obj) { |
| 1467 // function f() {} | 1481 // function f() {} |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1894 // the number of arguments (2 or 3). | 1908 // the number of arguments (2 or 3). |
| 1895 initialize = | 1909 initialize = |
| 1896 new(zone()) CallRuntime( | 1910 new(zone()) CallRuntime( |
| 1897 isolate(), | 1911 isolate(), |
| 1898 isolate()->factory()->InitializeVarGlobal_symbol(), | 1912 isolate()->factory()->InitializeVarGlobal_symbol(), |
| 1899 Runtime::FunctionForId(Runtime::kInitializeVarGlobal), | 1913 Runtime::FunctionForId(Runtime::kInitializeVarGlobal), |
| 1900 arguments); | 1914 arguments); |
| 1901 } | 1915 } |
| 1902 | 1916 |
| 1903 block->AddStatement(new(zone()) ExpressionStatement(initialize)); | 1917 block->AddStatement(new(zone()) ExpressionStatement(initialize)); |
| 1918 } else if (needs_init) { |
| 1919 // Constant initializations always assign to the declared constant which |
| 1920 // is always at the function scope level. This is only relevant for |
| 1921 // dynamically looked-up variables and constants (the start context for |
| 1922 // constant lookups is always the function context, while it is the top |
| 1923 // context for var declared variables). Sigh... |
| 1924 // For 'let' and 'const' declared variables in harmony mode the |
| 1925 // initialization also always assigns to the declared variable. |
| 1926 ASSERT(proxy != NULL); |
| 1927 ASSERT(proxy->var() != NULL); |
| 1928 ASSERT(value != NULL); |
| 1929 Assignment* assignment = |
| 1930 new(zone()) Assignment(isolate(), init_op, proxy, value, position); |
| 1931 block->AddStatement(new(zone()) ExpressionStatement(assignment)); |
| 1932 value = NULL; |
| 1904 } | 1933 } |
| 1905 | 1934 |
| 1906 // Add an assignment node to the initialization statement block if we still | 1935 // Add an assignment node to the initialization statement block if we still |
| 1907 // have a pending initialization value. We must distinguish between | 1936 // have a pending initialization value. |
| 1908 // different kinds of declarations: 'var' initializations are simply | |
| 1909 // assignments (with all the consequences if they are inside a 'with' | |
| 1910 // statement - they may change a 'with' object property). Constant | |
| 1911 // initializations always assign to the declared constant which is | |
| 1912 // always at the function scope level. This is only relevant for | |
| 1913 // dynamically looked-up variables and constants (the start context | |
| 1914 // for constant lookups is always the function context, while it is | |
| 1915 // the top context for var declared variables). Sigh... | |
| 1916 // For 'let' and 'const' declared variables in harmony mode the | |
| 1917 // initialization is in the same scope as the declaration. Thus dynamic | |
| 1918 // lookups are unnecessary even if the block scope is inside a with. | |
| 1919 if (value != NULL) { | 1937 if (value != NULL) { |
| 1938 ASSERT(mode == VAR); |
| 1939 // 'var' initializations are simply assignments (with all the consequences |
| 1940 // if they are inside a 'with' statement - they may change a 'with' object |
| 1941 // property). |
| 1920 VariableProxy* proxy = initialization_scope->NewUnresolved(name); | 1942 VariableProxy* proxy = initialization_scope->NewUnresolved(name); |
| 1921 Assignment* assignment = | 1943 Assignment* assignment = |
| 1922 new(zone()) Assignment(isolate(), init_op, proxy, value, position); | 1944 new(zone()) Assignment(isolate(), init_op, proxy, value, position); |
| 1923 block->AddStatement(new(zone()) ExpressionStatement(assignment)); | 1945 block->AddStatement(new(zone()) ExpressionStatement(assignment)); |
| 1924 } | 1946 } |
| 1925 | 1947 |
| 1926 if (fni_ != NULL) fni_->Leave(); | 1948 if (fni_ != NULL) fni_->Leave(); |
| 1927 } while (peek() == Token::COMMA); | 1949 } while (peek() == Token::COMMA); |
| 1928 | 1950 |
| 1929 // If there was a single non-const declaration, return it in the output | 1951 // If there was a single non-const declaration, return it in the output |
| (...skipping 3488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5418 result = parser.ParseProgram(source, | 5440 result = parser.ParseProgram(source, |
| 5419 info->is_global(), | 5441 info->is_global(), |
| 5420 info->strict_mode_flag()); | 5442 info->strict_mode_flag()); |
| 5421 } | 5443 } |
| 5422 } | 5444 } |
| 5423 info->SetFunction(result); | 5445 info->SetFunction(result); |
| 5424 return (result != NULL); | 5446 return (result != NULL); |
| 5425 } | 5447 } |
| 5426 | 5448 |
| 5427 } } // namespace v8::internal | 5449 } } // namespace v8::internal |
| OLD | NEW |