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 |