| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index 8ac4ec94794245da7e9f349c2f92221312135679..fb3a78d2cec020df915f93e89de7b4a28da882c6 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -682,7 +682,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
| }
|
| original_scope_ = scope;
|
| if (info->is_eval()) {
|
| - if (!scope->is_global_scope() || info->language_mode() != SLOPPY_MODE) {
|
| + if (!scope->is_global_scope() || info->strict_mode() == STRICT) {
|
| scope = NewScope(scope, EVAL_SCOPE);
|
| }
|
| } else if (info->is_global()) {
|
| @@ -703,16 +703,16 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
| // Enters 'scope'.
|
| FunctionState function_state(&function_state_, &scope_, scope, zone());
|
|
|
| - scope_->SetLanguageMode(info->language_mode());
|
| + scope_->SetStrictMode(info->strict_mode());
|
| ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
|
| bool ok = true;
|
| int beg_pos = scanner()->location().beg_pos;
|
| ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok);
|
| - if (ok && !scope_->is_sloppy_mode()) {
|
| + if (ok && strict_mode() == STRICT) {
|
| CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
|
| }
|
|
|
| - if (ok && is_extended_mode()) {
|
| + if (ok && FLAG_harmony_scoping && strict_mode() == STRICT) {
|
| CheckConflictingVarDeclarations(scope_, &ok);
|
| }
|
|
|
| @@ -817,11 +817,9 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
|
| }
|
| original_scope_ = scope;
|
| FunctionState function_state(&function_state_, &scope_, scope, zone());
|
| - ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_sloppy_mode());
|
| - ASSERT(scope->language_mode() != EXTENDED_MODE ||
|
| - info()->is_extended_mode());
|
| - ASSERT(info()->language_mode() == shared_info->language_mode());
|
| - scope->SetLanguageMode(shared_info->language_mode());
|
| + ASSERT(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT);
|
| + ASSERT(info()->strict_mode() == shared_info->strict_mode());
|
| + scope->SetStrictMode(shared_info->strict_mode());
|
| FunctionLiteral::FunctionType function_type = shared_info->is_expression()
|
| ? (shared_info->is_anonymous()
|
| ? FunctionLiteral::ANONYMOUS_EXPRESSION
|
| @@ -897,7 +895,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
|
| Handle<String> directive = Handle<String>::cast(literal->value());
|
|
|
| // Check "use strict" directive (ES5 14.1).
|
| - if (scope_->is_sloppy_mode() &&
|
| + if (strict_mode() == SLOPPY &&
|
| directive->Equals(isolate()->heap()->use_strict_string()) &&
|
| token_loc.end_pos - token_loc.beg_pos ==
|
| isolate()->heap()->use_strict_string()->length() + 2) {
|
| @@ -914,9 +912,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
|
| scope_ = scope;
|
| mode_ = PARSE_EAGERLY;
|
| }
|
| - // TODO(ES6): Fix entering extended mode, once it is specified.
|
| - scope_->SetLanguageMode(allow_harmony_scoping()
|
| - ? EXTENDED_MODE : STRICT_MODE);
|
| + scope_->SetStrictMode(STRICT);
|
| // "use strict" is the only directive for now.
|
| directive_prologue = false;
|
| }
|
| @@ -1058,7 +1054,7 @@ Module* Parser::ParseModuleLiteral(bool* ok) {
|
|
|
| Expect(Token::LBRACE, CHECK_OK);
|
| scope->set_start_position(scanner()->location().beg_pos);
|
| - scope->SetLanguageMode(EXTENDED_MODE);
|
| + scope->SetStrictMode(STRICT);
|
|
|
| {
|
| BlockState block_state(&scope_, scope);
|
| @@ -1443,7 +1439,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
|
| // In Harmony mode, this case also handles the extension:
|
| // Statement:
|
| // GeneratorDeclaration
|
| - if (!scope_->is_sloppy_mode()) {
|
| + if (strict_mode() == STRICT) {
|
| ReportMessageAt(scanner()->peek_location(), "strict_function");
|
| *ok = false;
|
| return NULL;
|
| @@ -1488,7 +1484,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
|
| // Similarly, strict mode eval scope does not leak variable declarations to
|
| // the caller's scope so we declare all locals, too.
|
| if (declaration_scope->is_function_scope() ||
|
| - declaration_scope->is_strict_or_extended_eval_scope() ||
|
| + declaration_scope->is_strict_eval_scope() ||
|
| declaration_scope->is_block_scope() ||
|
| declaration_scope->is_module_scope() ||
|
| declaration_scope->is_global_scope()) {
|
| @@ -1521,8 +1517,8 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
|
| // because the var declaration is hoisted to the function scope where 'x'
|
| // is already bound.
|
| ASSERT(IsDeclaredVariableMode(var->mode()));
|
| - if (is_extended_mode()) {
|
| - // In harmony mode we treat re-declarations as early errors. See
|
| + if (FLAG_harmony_scoping && strict_mode() == STRICT) {
|
| + // In harmony we treat re-declarations as early errors. See
|
| // ES5 16 for a definition of early errors.
|
| SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
|
| const char* elms[2] = { "Variable", c_string.get() };
|
| @@ -1559,7 +1555,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
|
| // Runtime::DeclareContextSlot() calls.
|
| declaration_scope->AddDeclaration(declaration);
|
|
|
| - if (mode == CONST && declaration_scope->is_global_scope()) {
|
| + if (mode == CONST_LEGACY && 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;
|
| @@ -1567,7 +1563,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
|
| declaration_scope, name, mode, true, kind,
|
| kNeedsInitialization, proxy->interface());
|
| } else if (declaration_scope->is_eval_scope() &&
|
| - declaration_scope->is_sloppy_mode()) {
|
| + declaration_scope->strict_mode() == SLOPPY) {
|
| // For variable declarations in a sloppy eval scope the proxy is bound
|
| // to a lookup variable to force a dynamic declaration using the
|
| // DeclareContextSlot runtime function.
|
| @@ -1699,7 +1695,8 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
|
| // In extended mode, a function behaves as a lexical binding, except in the
|
| // global scope.
|
| VariableMode mode =
|
| - is_extended_mode() && !scope_->is_global_scope() ? LET : VAR;
|
| + FLAG_harmony_scoping &&
|
| + strict_mode() == STRICT && !scope_->is_global_scope() ? LET : VAR;
|
| VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
|
| Declaration* declaration =
|
| factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
|
| @@ -1710,7 +1707,9 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
|
|
|
|
|
| Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
|
| - if (scope_->is_extended_mode()) return ParseScopedBlock(labels, ok);
|
| + if (FLAG_harmony_scoping && strict_mode() == STRICT) {
|
| + return ParseScopedBlock(labels, ok);
|
| + }
|
|
|
| // Block ::
|
| // '{' Statement* '}'
|
| @@ -1830,25 +1829,27 @@ Block* Parser::ParseVariableDeclarations(
|
| // existing pages. Therefore we keep allowing const with the old
|
| // non-harmony semantics in sloppy mode.
|
| Consume(Token::CONST);
|
| - switch (scope_->language_mode()) {
|
| - case SLOPPY_MODE:
|
| - mode = CONST;
|
| - init_op = Token::INIT_CONST;
|
| + switch (strict_mode()) {
|
| + case SLOPPY:
|
| + mode = CONST_LEGACY;
|
| + init_op = Token::INIT_CONST_LEGACY;
|
| break;
|
| - case STRICT_MODE:
|
| - ReportMessage("strict_const", Vector<const char*>::empty());
|
| - *ok = false;
|
| - return NULL;
|
| - case EXTENDED_MODE:
|
| - if (var_context == kStatement) {
|
| - // In extended mode 'const' declarations are only allowed in source
|
| - // element positions.
|
| - ReportMessage("unprotected_const", Vector<const char*>::empty());
|
| + case STRICT:
|
| + if (FLAG_harmony_scoping) {
|
| + if (var_context == kStatement) {
|
| + // In strict mode 'const' declarations are only allowed in source
|
| + // element positions.
|
| + ReportMessage("unprotected_const", Vector<const char*>::empty());
|
| + *ok = false;
|
| + return NULL;
|
| + }
|
| + mode = CONST;
|
| + init_op = Token::INIT_CONST;
|
| + } else {
|
| + ReportMessage("strict_const", Vector<const char*>::empty());
|
| *ok = false;
|
| return NULL;
|
| }
|
| - mode = CONST_HARMONY;
|
| - init_op = Token::INIT_CONST_HARMONY;
|
| }
|
| is_const = true;
|
| needs_init = true;
|
| @@ -1859,7 +1860,9 @@ Block* Parser::ParseVariableDeclarations(
|
| //
|
| // * It is a Syntax Error if the code that matches this production is not
|
| // contained in extended code.
|
| - if (!is_extended_mode()) {
|
| + //
|
| + // TODO(rossberg): make 'let' a legal identifier in sloppy mode.
|
| + if (!FLAG_harmony_scoping || strict_mode() == SLOPPY) {
|
| ReportMessage("illegal_let", Vector<const char*>::empty());
|
| *ok = false;
|
| return NULL;
|
| @@ -1964,7 +1967,7 @@ Block* Parser::ParseVariableDeclarations(
|
| Expression* value = NULL;
|
| int pos = -1;
|
| // Harmony consts have non-optional initializers.
|
| - if (peek() == Token::ASSIGN || mode == CONST_HARMONY) {
|
| + if (peek() == Token::ASSIGN || mode == CONST) {
|
| Expect(Token::ASSIGN, CHECK_OK);
|
| pos = position();
|
| value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
|
| @@ -2032,8 +2035,8 @@ Block* Parser::ParseVariableDeclarations(
|
| } else {
|
| // Add strict mode.
|
| // We may want to pass singleton to avoid Literal allocations.
|
| - LanguageMode language_mode = initialization_scope->language_mode();
|
| - arguments->Add(factory()->NewNumberLiteral(language_mode, pos), zone());
|
| + StrictMode strict_mode = initialization_scope->strict_mode();
|
| + arguments->Add(factory()->NewNumberLiteral(strict_mode, pos), zone());
|
|
|
| // Be careful not to assign a value to the global variable if
|
| // we're in a with. The initialization value should not
|
| @@ -2333,7 +2336,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
|
| Expect(Token::WITH, CHECK_OK);
|
| int pos = position();
|
|
|
| - if (!scope_->is_sloppy_mode()) {
|
| + if (strict_mode() == STRICT) {
|
| ReportMessage("strict_mode_with", Vector<const char*>::empty());
|
| *ok = false;
|
| return NULL;
|
| @@ -2485,7 +2488,8 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
| Expect(Token::RPAREN, CHECK_OK);
|
|
|
| Target target(&this->target_stack_, &catch_collector);
|
| - VariableMode mode = is_extended_mode() ? LET : VAR;
|
| + VariableMode mode =
|
| + FLAG_harmony_scoping && strict_mode() == STRICT ? LET : VAR;
|
| catch_variable =
|
| catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
|
|
|
| @@ -2907,7 +2911,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
|
| expression = NewThrowReferenceError(message);
|
| }
|
|
|
| - if (!scope_->is_sloppy_mode()) {
|
| + if (strict_mode() == STRICT) {
|
| // Assignment to eval or arguments is disallowed in strict mode.
|
| CheckStrictModeLValue(expression, CHECK_OK);
|
| }
|
| @@ -2941,7 +2945,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
|
| // name if we're dealing with "a = function(){...}();"-like
|
| // expression.
|
| if ((op == Token::INIT_VAR
|
| - || op == Token::INIT_CONST
|
| + || op == Token::INIT_CONST_LEGACY
|
| || op == Token::ASSIGN)
|
| && (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
|
| fni_->Infer();
|
| @@ -3131,7 +3135,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
|
| }
|
|
|
| // "delete identifier" is a syntax error in strict mode.
|
| - if (op == Token::DELETE && !scope_->is_sloppy_mode()) {
|
| + if (op == Token::DELETE && strict_mode() == STRICT) {
|
| VariableProxy* operand = expression->AsVariableProxy();
|
| if (operand != NULL && !operand->is_this()) {
|
| ReportMessage("strict_delete", Vector<const char*>::empty());
|
| @@ -3179,7 +3183,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
|
| expression = NewThrowReferenceError(message);
|
| }
|
|
|
| - if (!scope_->is_sloppy_mode()) {
|
| + if (strict_mode() == STRICT) {
|
| // Prefix expression operand in strict mode may not be eval or arguments.
|
| CheckStrictModeLValue(expression, CHECK_OK);
|
| }
|
| @@ -3213,7 +3217,7 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
|
| expression = NewThrowReferenceError(message);
|
| }
|
|
|
| - if (!scope_->is_sloppy_mode()) {
|
| + if (strict_mode() == STRICT) {
|
| // Postfix expression operand in strict mode may not be eval or arguments.
|
| CheckStrictModeLValue(expression, CHECK_OK);
|
| }
|
| @@ -3503,7 +3507,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
| int number_of_boilerplate_properties = 0;
|
| bool has_function = false;
|
|
|
| - ObjectLiteralChecker checker(this, scope_->language_mode());
|
| + ObjectLiteralChecker checker(this, strict_mode());
|
|
|
| Expect(Token::LBRACE, CHECK_OK);
|
|
|
| @@ -3691,13 +3695,13 @@ class SingletonLogger : public ParserRecorder {
|
| int end,
|
| int literals,
|
| int properties,
|
| - LanguageMode mode) {
|
| + StrictMode strict_mode) {
|
| ASSERT(!has_error_);
|
| start_ = start;
|
| end_ = end;
|
| literals_ = literals;
|
| properties_ = properties;
|
| - mode_ = mode;
|
| + strict_mode_ = strict_mode;
|
| };
|
|
|
| // Logs a symbol creation of a literal or identifier.
|
| @@ -3746,9 +3750,9 @@ class SingletonLogger : public ParserRecorder {
|
| ASSERT(!has_error_);
|
| return properties_;
|
| }
|
| - LanguageMode language_mode() {
|
| + StrictMode strict_mode() {
|
| ASSERT(!has_error_);
|
| - return mode_;
|
| + return strict_mode_;
|
| }
|
| const char* message() {
|
| ASSERT(has_error_);
|
| @@ -3766,7 +3770,7 @@ class SingletonLogger : public ParserRecorder {
|
| // For function entries.
|
| int literals_;
|
| int properties_;
|
| - LanguageMode mode_;
|
| + StrictMode strict_mode_;
|
| // For error messages.
|
| const char* message_;
|
| const char* argument_opt_;
|
| @@ -3828,7 +3832,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| Scope* declaration_scope = scope_->DeclarationScope();
|
| Scope* original_declaration_scope = original_scope_->DeclarationScope();
|
| Scope* scope =
|
| - function_type == FunctionLiteral::DECLARATION && !is_extended_mode() &&
|
| + function_type == FunctionLiteral::DECLARATION &&
|
| + (!FLAG_harmony_scoping || strict_mode() == SLOPPY) &&
|
| (original_scope_ == original_declaration_scope ||
|
| declaration_scope != original_declaration_scope)
|
| ? NewScope(declaration_scope, FUNCTION_SCOPE)
|
| @@ -3917,10 +3922,13 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| // future we can change the AST to only refer to VariableProxies
|
| // instead of Variables and Proxis as is the case now.
|
| Variable* fvar = NULL;
|
| - Token::Value fvar_init_op = Token::INIT_CONST;
|
| + Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
|
| if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
|
| - if (is_extended_mode()) fvar_init_op = Token::INIT_CONST_HARMONY;
|
| - VariableMode fvar_mode = is_extended_mode() ? CONST_HARMONY : CONST;
|
| + if (FLAG_harmony_scoping && strict_mode() == STRICT) {
|
| + fvar_init_op = Token::INIT_CONST;
|
| + }
|
| + VariableMode fvar_mode = FLAG_harmony_scoping && strict_mode() == STRICT
|
| + ? CONST : CONST_LEGACY;
|
| fvar = new(zone()) Variable(scope_,
|
| function_name, fvar_mode, true /* is valid LHS */,
|
| Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
|
| @@ -3990,7 +3998,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| scope->end_position() - function_block_pos);
|
| materialized_literal_count = entry.literal_count();
|
| expected_property_count = entry.property_count();
|
| - scope_->SetLanguageMode(entry.language_mode());
|
| + scope_->SetStrictMode(entry.strict_mode());
|
| } else {
|
| // This case happens when we have preparse data but it doesn't contain
|
| // an entry for the function. As a safety net, fall back to eager
|
| @@ -4038,7 +4046,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| scope->end_position() - function_block_pos);
|
| materialized_literal_count = logger.literals();
|
| expected_property_count = logger.properties();
|
| - scope_->SetLanguageMode(logger.language_mode());
|
| + scope_->SetStrictMode(logger.strict_mode());
|
| }
|
| }
|
|
|
| @@ -4102,7 +4110,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|
|
| // Validate strict mode. We can do this only after parsing the function,
|
| // since the function can declare itself strict.
|
| - if (!scope_->is_sloppy_mode()) {
|
| + if (strict_mode() == STRICT) {
|
| if (IsEvalOrArguments(function_name)) {
|
| ReportMessageAt(function_name_location, "strict_eval_arguments");
|
| *ok = false;
|
| @@ -4137,7 +4145,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
|
| }
|
|
|
| - if (is_extended_mode()) {
|
| + if (FLAG_harmony_scoping && strict_mode() == STRICT) {
|
| CheckConflictingVarDeclarations(scope, CHECK_OK);
|
| }
|
|
|
| @@ -4183,7 +4191,7 @@ PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
|
| allow_harmony_numeric_literals());
|
| }
|
| PreParser::PreParseResult result =
|
| - reusable_preparser_->PreParseLazyFunction(scope_->language_mode(),
|
| + reusable_preparser_->PreParseLazyFunction(strict_mode(),
|
| is_generator(),
|
| logger);
|
| return result;
|
| @@ -4265,7 +4273,7 @@ void Parser::MarkAsLValue(Expression* expression) {
|
| // in strict mode.
|
| void Parser::CheckStrictModeLValue(Expression* expression,
|
| bool* ok) {
|
| - ASSERT(!scope_->is_sloppy_mode());
|
| + ASSERT(strict_mode() == STRICT);
|
| VariableProxy* lhs = expression != NULL
|
| ? expression->AsVariableProxy()
|
| : NULL;
|
|
|