| Index: src/parsing/parser.cc
|
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
| index 19b4891281a1bf82676755a39f64bfca5be9feb9..53506a9d91c1253a115401c6bc8a1e6b948bb826 100644
|
| --- a/src/parsing/parser.cc
|
| +++ b/src/parsing/parser.cc
|
| @@ -1690,7 +1690,7 @@ Statement* Parser::ParseExportDefault(bool* ok) {
|
| VariableProxy* proxy = NewUnresolved(local_name, CONST);
|
| Declaration* declaration =
|
| factory()->NewVariableDeclaration(proxy, CONST, scope(), pos);
|
| - Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, CHECK_OK);
|
| proxy->var()->set_initializer_position(position());
|
|
|
| Assignment* assignment = factory()->NewAssignment(
|
| @@ -1980,13 +1980,12 @@ void Parser::DeclareConstVariable(const AstRawString* name,
|
| VariableProxy* proxy = NewUnresolved(name, CONST);
|
| Declaration* declaration =
|
| factory()->NewVariableDeclaration(proxy, CONST, scope(), init, pos);
|
| - Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK_VOID);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, CHECK_OK_VOID);
|
| }
|
|
|
| -
|
| Variable* Parser::Declare(Declaration* declaration,
|
| DeclarationDescriptor::Kind declaration_kind,
|
| - bool resolve, bool* ok, Scope* scope) {
|
| + bool* ok, Scope* scope) {
|
| VariableProxy* proxy = declaration->proxy();
|
| DCHECK(proxy->raw_name() != NULL);
|
| const AstRawString* name = proxy->raw_name();
|
| @@ -1994,40 +1993,41 @@ Variable* Parser::Declare(Declaration* declaration,
|
| DCHECK(IsDeclaredVariableMode(mode) && mode != CONST_LEGACY);
|
| bool is_function_declaration = declaration->IsFunctionDeclaration();
|
| if (scope == nullptr) scope = this->scope();
|
| - Scope* declaration_scope =
|
| - IsLexicalVariableMode(mode) ? scope : scope->GetDeclarationScope();
|
| - Variable* var = NULL;
|
| + if (mode == VAR) scope = scope->GetDeclarationScope();
|
|
|
| - // If a suitable scope exists, then we can statically declare this
|
| - // variable and also set its mode. In any case, a Declaration node
|
| - // will be added to the scope so that the declaration can be added
|
| - // to the corresponding activation frame at runtime if necessary.
|
| - // For instance, var declarations inside a sloppy eval scope need
|
| - // to be added to the calling function context. Similarly, strict
|
| - // mode eval scope and lexical eval bindings do not leak variable
|
| - // declarations to the caller's scope so we declare all locals, too.
|
| - if (declaration_scope->is_function_scope() ||
|
| - declaration_scope->is_block_scope() ||
|
| - declaration_scope->is_module_scope() ||
|
| - declaration_scope->is_script_scope() ||
|
| - (declaration_scope->is_eval_scope() &&
|
| - (is_strict(declaration_scope->language_mode()) ||
|
| - IsLexicalVariableMode(mode)))) {
|
| + DCHECK(!scope->is_catch_scope());
|
| + DCHECK(!scope->is_with_scope());
|
| + DCHECK(scope->is_declaration_scope() ||
|
| + (IsLexicalVariableMode(mode) && scope->is_block_scope()));
|
| +
|
| + Variable* var = NULL;
|
| + if (scope->is_eval_scope() && is_sloppy(scope->language_mode()) &&
|
| + mode == VAR) {
|
| + // In a var binding in a sloppy direct eval, pollute the enclosing scope
|
| + // with this new binding by doing the following:
|
| + // The proxy is bound to a lookup variable to force a dynamic declaration
|
| + // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
|
| + Variable::Kind kind = Variable::NORMAL;
|
| + // TODO(sigurds) figure out if kNotAssigned is OK here
|
| + var = new (zone()) Variable(scope, name, mode, kind,
|
| + declaration->initialization(), kNotAssigned);
|
| + var->AllocateTo(VariableLocation::LOOKUP, -1);
|
| + } else {
|
| // Declare the variable in the declaration scope.
|
| - var = declaration_scope->LookupLocal(name);
|
| + var = scope->LookupLocal(name);
|
| if (var == NULL) {
|
| // Declare the name.
|
| Variable::Kind kind = Variable::NORMAL;
|
| if (is_function_declaration) {
|
| kind = Variable::FUNCTION;
|
| }
|
| - var = declaration_scope->DeclareLocal(
|
| - name, mode, declaration->initialization(), kind, kNotAssigned);
|
| + var = scope->DeclareLocal(name, mode, declaration->initialization(), kind,
|
| + kNotAssigned);
|
| } else if (IsLexicalVariableMode(mode) ||
|
| IsLexicalVariableMode(var->mode())) {
|
| // Allow duplicate function decls for web compat, see bug 4693.
|
| bool duplicate_allowed = false;
|
| - if (is_sloppy(language_mode()) && is_function_declaration &&
|
| + if (is_sloppy(scope->language_mode()) && is_function_declaration &&
|
| var->is_function()) {
|
| DCHECK(IsLexicalVariableMode(mode) &&
|
| IsLexicalVariableMode(var->mode()));
|
| @@ -2073,67 +2073,20 @@ Variable* Parser::Declare(Declaration* declaration,
|
| } else if (mode == VAR) {
|
| var->set_maybe_assigned();
|
| }
|
| - } else if (declaration_scope->is_eval_scope() &&
|
| - is_sloppy(declaration_scope->language_mode()) &&
|
| - !IsLexicalVariableMode(mode)) {
|
| - // In a var binding in a sloppy direct eval, pollute the enclosing scope
|
| - // with this new binding by doing the following:
|
| - // The proxy is bound to a lookup variable to force a dynamic declaration
|
| - // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
|
| - Variable::Kind kind = Variable::NORMAL;
|
| - // TODO(sigurds) figure out if kNotAssigned is OK here
|
| - var = new (zone()) Variable(declaration_scope, name, mode, kind,
|
| - declaration->initialization(), kNotAssigned);
|
| - var->AllocateTo(VariableLocation::LOOKUP, -1);
|
| - resolve = true;
|
| }
|
| -
|
| + DCHECK_NOT_NULL(var);
|
|
|
| // We add a declaration node for every declaration. The compiler
|
| // will only generate code if necessary. In particular, declarations
|
| // for inner local variables that do not represent functions won't
|
| // result in any generated code.
|
| //
|
| - // Note that we always add an unresolved proxy even if it's not
|
| - // used, simply because we don't know in this method (w/o extra
|
| - // parameters) if the proxy is needed or not. The proxy will be
|
| - // bound during variable resolution time unless it was pre-bound
|
| - // below.
|
| - //
|
| - // WARNING: This will lead to multiple declaration nodes for the
|
| + // This will lead to multiple declaration nodes for the
|
| // same variable if it is declared several times. This is not a
|
| - // semantic issue as long as we keep the source order, but it may be
|
| - // a performance issue since it may lead to repeated
|
| - // DeclareEvalVar or DeclareEvalFunction calls.
|
| - declaration_scope->AddDeclaration(declaration);
|
| -
|
| - // If requested and we have a local variable, bind the proxy to the variable
|
| - // at parse-time. This is used for functions (and consts) declared inside
|
| - // statements: the corresponding function (or const) variable must be in the
|
| - // function scope and not a statement-local scope, e.g. as provided with a
|
| - // 'with' statement:
|
| - //
|
| - // with (obj) {
|
| - // function f() {}
|
| - // }
|
| - //
|
| - // which is translated into:
|
| - //
|
| - // with (obj) {
|
| - // // in this case this is not: 'var f; f = function () {};'
|
| - // var f = function () {};
|
| - // }
|
| - //
|
| - // Note that if 'f' is accessed from inside the 'with' statement, it
|
| - // will be allocated in the context (because we must be able to look
|
| - // it up dynamically) but it will also be accessed statically, i.e.,
|
| - // with a context slot index and a context chain length for this
|
| - // initialization code. Thus, inside the 'with' statement, we need
|
| - // both access to the static and the dynamic context chain; the
|
| - // runtime needs to provide both.
|
| - if (resolve && var != NULL) {
|
| - proxy->BindTo(var);
|
| - }
|
| + // semantic issue, but it may be a performance issue since it may
|
| + // lead to repeated DeclareEvalVar or DeclareEvalFunction calls.
|
| + scope->AddDeclaration(declaration);
|
| + proxy->BindTo(var);
|
| return var;
|
| }
|
|
|
| @@ -2173,7 +2126,7 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
|
| VariableProxy* proxy = NewUnresolved(name, VAR);
|
| Declaration* declaration =
|
| factory()->NewVariableDeclaration(proxy, VAR, scope(), pos);
|
| - Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, CHECK_OK);
|
| NativeFunctionLiteral* lit =
|
| factory()->NewNativeFunctionLiteral(name, extension_, kNoSourcePosition);
|
| return factory()->NewExpressionStatement(
|
| @@ -2263,7 +2216,7 @@ Statement* Parser::ParseHoistableDeclaration(
|
| VariableProxy* proxy = NewUnresolved(variable_name, mode);
|
| Declaration* declaration =
|
| factory()->NewFunctionDeclaration(proxy, mode, fun, scope(), pos);
|
| - Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, CHECK_OK);
|
| if (names) names->Add(variable_name, zone());
|
| EmptyStatement* empty = factory()->NewEmptyStatement(kNoSourcePosition);
|
| // Async functions don't undergo sloppy mode block scoped hoisting, and don't
|
| @@ -2322,7 +2275,7 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
|
| VariableProxy* proxy = NewUnresolved(variable_name, LET);
|
| Declaration* declaration =
|
| factory()->NewVariableDeclaration(proxy, LET, scope(), pos);
|
| - Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, CHECK_OK);
|
| proxy->var()->set_initializer_position(position());
|
| Assignment* assignment =
|
| factory()->NewAssignment(Token::INIT, proxy, value, pos);
|
| @@ -3555,7 +3508,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
|
| VariableProxy* proxy = NewUnresolved(names->at(i), mode);
|
| Declaration* declaration = factory()->NewVariableDeclaration(
|
| proxy, mode, scope(), kNoSourcePosition);
|
| - Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, CHECK_OK);
|
| inner_vars.Add(declaration->proxy()->var(), zone());
|
| VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
|
| Assignment* assignment = factory()->NewAssignment(
|
| @@ -3906,8 +3859,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| VariableProxy* tdz_proxy = NewUnresolved(bound_names[i], LET);
|
| Declaration* tdz_decl = factory()->NewVariableDeclaration(
|
| tdz_proxy, LET, scope(), kNoSourcePosition);
|
| - Variable* tdz_var = Declare(
|
| - tdz_decl, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| + Variable* tdz_var =
|
| + Declare(tdz_decl, DeclarationDescriptor::NORMAL, CHECK_OK);
|
| tdz_var->set_initializer_position(position());
|
| }
|
| }
|
| @@ -5088,7 +5041,7 @@ Expression* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
|
| // TODO(verwaest): declare via block_state.
|
| Declaration* declaration = factory()->NewVariableDeclaration(
|
| proxy, CONST, block_state.scope(), pos);
|
| - Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, CHECK_OK);
|
| }
|
|
|
| Expression* extends = nullptr;
|
| @@ -5366,7 +5319,7 @@ void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope,
|
| VariableProxy* proxy = scope->NewUnresolved(factory(), name);
|
| Declaration* declaration = factory()->NewVariableDeclaration(
|
| proxy, VAR, scope, kNoSourcePosition);
|
| - Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, ok, scope);
|
| DCHECK(ok); // Based on the preceding check, this should not fail
|
| if (!ok) return;
|
| }
|
|
|