| 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);
|
|
|