Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 80abc63b4b204a7e687fb6748498f049bcc067fb..32eaf91f2f1a26c55c4d522a06185f263ffe0fdf 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -735,7 +735,7 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, |
// Parse the function literal. |
Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE); |
if (!info->closure().is_null()) { |
- scope = Scope::DeserializeScopeChain(info, scope); |
+ scope = Scope::DeserializeScopeChain(info->closure()->context(), scope); |
} |
FunctionState function_state(this, scope, isolate()); |
ASSERT(scope->strict_mode_flag() == kNonStrictMode || |
@@ -1362,6 +1362,8 @@ VariableProxy* Parser::Declare(Handle<String> name, |
// enclosing scope. |
Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY) |
? top_scope_ : top_scope_->DeclarationScope(); |
+ InitializationFlag init_flag = (fun != NULL || mode == VAR) |
+ ? kCreatedInitialized : kNeedsInitialization; |
// If a function scope exists, then we can statically declare this |
// variable and also set its mode. In any case, a Declaration node |
@@ -1380,8 +1382,6 @@ VariableProxy* Parser::Declare(Handle<String> name, |
var = declaration_scope->LocalLookup(name); |
if (var == NULL) { |
// Declare the name. |
- InitializationFlag init_flag = (fun != NULL || mode == VAR) |
- ? kCreatedInitialized : kNeedsInitialization; |
var = declaration_scope->DeclareLocal(name, mode, init_flag); |
} else { |
// The name was declared in this scope before; check for conflicting |
@@ -1444,17 +1444,31 @@ VariableProxy* Parser::Declare(Handle<String> name, |
declaration_scope->AddDeclaration( |
new(zone()) Declaration(proxy, mode, fun, top_scope_)); |
- // For global const variables we bind the proxy to a variable. |
if ((mode == CONST || mode == CONST_HARMONY) && |
declaration_scope->is_global_scope()) { |
+ // For global const variables we bind the proxy to a variable. |
ASSERT(resolve); // should be set by all callers |
Variable::Kind kind = Variable::NORMAL; |
var = new(zone()) Variable(declaration_scope, |
name, |
- CONST, |
+ mode, |
true, |
kind, |
kNeedsInitialization); |
+ } else if (declaration_scope->is_eval_scope() && |
+ !declaration_scope->is_strict_mode()) { |
+ // For variable declarations in a non-strict eval scope the proxy is bound |
+ // to a lookup variable to force a dynamic declaration using the |
+ // DeclareContextSlot runtime function. |
+ Variable::Kind kind = Variable::NORMAL; |
+ var = new(zone()) Variable(declaration_scope, |
+ name, |
+ mode, |
+ true, |
+ kind, |
+ init_flag); |
+ var->AllocateTo(Variable::LOOKUP, -1); |
+ resolve = true; |
} |
// If requested and we have a local variable, bind the proxy to the variable |
@@ -1901,22 +1915,30 @@ Block* Parser::ParseVariableDeclarations( |
} |
block->AddStatement(new(zone()) ExpressionStatement(initialize)); |
+ } else if (needs_init) { |
+ // Constant initializations always assign to the declared constant which |
+ // is always at the function scope level. This is only relevant for |
+ // dynamically looked-up variables and constants (the start context for |
+ // constant lookups is always the function context, while it is the top |
+ // context for var declared variables). Sigh... |
+ // For 'let' and 'const' declared variables in harmony mode the |
+ // initialization also always assigns to the declared variable. |
+ ASSERT(proxy != NULL); |
+ ASSERT(proxy->var() != NULL); |
+ ASSERT(value != NULL); |
+ Assignment* assignment = |
+ new(zone()) Assignment(isolate(), init_op, proxy, value, position); |
+ block->AddStatement(new(zone()) ExpressionStatement(assignment)); |
+ value = NULL; |
} |
// Add an assignment node to the initialization statement block if we still |
- // have a pending initialization value. We must distinguish between |
- // different kinds of declarations: 'var' initializations are simply |
- // assignments (with all the consequences if they are inside a 'with' |
- // statement - they may change a 'with' object property). Constant |
- // initializations always assign to the declared constant which is |
- // always at the function scope level. This is only relevant for |
- // dynamically looked-up variables and constants (the start context |
- // for constant lookups is always the function context, while it is |
- // the top context for var declared variables). Sigh... |
- // For 'let' and 'const' declared variables in harmony mode the |
- // initialization is in the same scope as the declaration. Thus dynamic |
- // lookups are unnecessary even if the block scope is inside a with. |
+ // have a pending initialization value. |
if (value != NULL) { |
+ ASSERT(mode == VAR); |
+ // 'var' initializations are simply assignments (with all the consequences |
+ // if they are inside a 'with' statement - they may change a 'with' object |
+ // property). |
VariableProxy* proxy = initialization_scope->NewUnresolved(name); |
Assignment* assignment = |
new(zone()) Assignment(isolate(), init_op, proxy, value, position); |