| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index a4735520366b9f91e98dcc592fc6929fd7de72a7..6e2346584110dfa0f3609176f5a441deb3749a38 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -282,7 +282,8 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
|
| const AstRawString* name = ast_value_factory()->empty_string();
|
|
|
| Scope* function_scope = NewScope(scope, FUNCTION_SCOPE);
|
| - function_scope->SetStrictMode(STRICT);
|
| + function_scope->SetLanguageMode(
|
| + static_cast<LanguageMode>(scope->language_mode() | STRICT));
|
| // Set start and end position to the same value
|
| function_scope->set_start_position(pos);
|
| function_scope->set_end_position(pos);
|
| @@ -918,7 +919,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
|
| }
|
| original_scope_ = *scope;
|
| if (info->is_eval()) {
|
| - if (!(*scope)->is_script_scope() || info->strict_mode() == STRICT) {
|
| + if (!(*scope)->is_script_scope() || is_strict(info->language_mode())) {
|
| *scope = NewScope(*scope, EVAL_SCOPE);
|
| }
|
| } else if (info->is_global()) {
|
| @@ -940,7 +941,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
|
| FunctionState function_state(&function_state_, &scope_, *scope,
|
| &function_factory);
|
|
|
| - scope_->SetStrictMode(info->strict_mode());
|
| + scope_->SetLanguageMode(info->language_mode());
|
| ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
|
| bool ok = true;
|
| int beg_pos = scanner()->location().beg_pos;
|
| @@ -956,11 +957,11 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
|
| ParseStatementList(body, Token::EOS, info->is_eval(), eval_scope, &ok);
|
| }
|
|
|
| - if (ok && strict_mode() == STRICT) {
|
| + if (ok && is_strict(language_mode())) {
|
| CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
|
| }
|
|
|
| - if (ok && allow_harmony_scoping() && strict_mode() == STRICT) {
|
| + if (ok && allow_harmony_scoping() && is_strict(language_mode())) {
|
| CheckConflictingVarDeclarations(scope_, &ok);
|
| }
|
|
|
| @@ -1059,9 +1060,10 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
|
| AstNodeFactory function_factory(ast_value_factory());
|
| FunctionState function_state(&function_state_, &scope_, scope,
|
| &function_factory);
|
| - DCHECK(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT);
|
| - DCHECK(info()->strict_mode() == shared_info->strict_mode());
|
| - scope->SetStrictMode(shared_info->strict_mode());
|
| + DCHECK(!is_strict(scope->language_mode()) ||
|
| + is_strict(info()->language_mode()));
|
| + DCHECK(info()->language_mode() == shared_info->language_mode());
|
| + scope->SetLanguageMode(shared_info->language_mode());
|
| FunctionLiteral::FunctionType function_type = shared_info->is_expression()
|
| ? (shared_info->is_anonymous()
|
| ? FunctionLiteral::ANONYMOUS_EXPRESSION
|
| @@ -1139,7 +1141,7 @@ void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
|
| literal->raw_value()->IsString()) {
|
| // Check "use strict" directive (ES5 14.1) and "use asm" directive. Only
|
| // one can be present.
|
| - if (strict_mode() == SLOPPY &&
|
| + if (!is_strict(language_mode()) &&
|
| literal->raw_value()->AsString() ==
|
| ast_value_factory()->use_strict_string() &&
|
| token_loc.end_pos - token_loc.beg_pos ==
|
| @@ -1161,7 +1163,8 @@ void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
|
| }
|
| mode_ = PARSE_EAGERLY;
|
| }
|
| - scope_->SetStrictMode(STRICT);
|
| + scope_->SetLanguageMode(
|
| + static_cast<LanguageMode>(scope_->language_mode() | STRICT));
|
| // "use strict" is the only directive for now.
|
| directive_prologue = false;
|
| } else if (literal->raw_value()->AsString() ==
|
| @@ -1202,7 +1205,7 @@ Statement* Parser::ParseStatementListItem(bool* ok) {
|
| return ParseVariableStatement(kStatementListItem, NULL, ok);
|
| case Token::LET:
|
| DCHECK(allow_harmony_scoping());
|
| - if (strict_mode() == STRICT) {
|
| + if (is_strict(language_mode())) {
|
| return ParseVariableStatement(kStatementListItem, NULL, ok);
|
| }
|
| // Fall through.
|
| @@ -1247,7 +1250,8 @@ Module* Parser::ParseModule(bool* ok) {
|
| Scope* scope = NewScope(scope_, MODULE_SCOPE);
|
|
|
| scope->set_start_position(scanner()->location().beg_pos);
|
| - scope->SetStrictMode(STRICT);
|
| + scope->SetLanguageMode(
|
| + static_cast<LanguageMode>(scope->language_mode() | STRICT));
|
|
|
| {
|
| BlockState block_state(&scope_, scope);
|
| @@ -1728,7 +1732,7 @@ Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
|
| // In Harmony mode, this case also handles the extension:
|
| // Statement:
|
| // GeneratorDeclaration
|
| - if (strict_mode() == STRICT) {
|
| + if (is_strict(language_mode())) {
|
| ReportMessageAt(scanner()->peek_location(), "strict_function");
|
| *ok = false;
|
| return NULL;
|
| @@ -1746,7 +1750,7 @@ Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
|
| // In ES6 CONST is not allowed as a Statement, only as a
|
| // LexicalDeclaration, however we continue to allow it in sloppy mode for
|
| // backwards compatibility.
|
| - if (strict_mode() == SLOPPY) {
|
| + if (!is_strict(language_mode())) {
|
| return ParseVariableStatement(kStatement, NULL, ok);
|
| }
|
|
|
| @@ -1814,7 +1818,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
|
| // because the var declaration is hoisted to the function scope where 'x'
|
| // is already bound.
|
| DCHECK(IsDeclaredVariableMode(var->mode()));
|
| - if (allow_harmony_scoping() && strict_mode() == STRICT) {
|
| + if (allow_harmony_scoping() && is_strict(language_mode())) {
|
| // In harmony we treat re-declarations as early errors. See
|
| // ES5 16 for a definition of early errors.
|
| ParserTraits::ReportMessage("var_redeclaration", name);
|
| @@ -1855,7 +1859,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
|
| Variable(declaration_scope, name, mode, true, kind,
|
| kNeedsInitialization, kNotAssigned, proxy->interface());
|
| } else if (declaration_scope->is_eval_scope() &&
|
| - declaration_scope->strict_mode() == SLOPPY) {
|
| + !is_strict(declaration_scope->language_mode())) {
|
| // For variable declarations in a sloppy eval scope the proxy is bound
|
| // to a lookup variable to force a dynamic declaration using the
|
| // DeclareLookupSlot runtime function.
|
| @@ -1989,9 +1993,11 @@ Statement* Parser::ParseFunctionDeclaration(
|
| // In ES6, a function behaves as a lexical binding, except in
|
| // a script scope, or the initial scope of eval or another function.
|
| VariableMode mode =
|
| - allow_harmony_scoping() && strict_mode() == STRICT &&
|
| - !(scope_->is_script_scope() || scope_->is_eval_scope() ||
|
| - scope_->is_function_scope()) ? LET : VAR;
|
| + allow_harmony_scoping() && is_strict(language_mode()) &&
|
| + !(scope_->is_script_scope() || scope_->is_eval_scope() ||
|
| + scope_->is_function_scope())
|
| + ? LET
|
| + : VAR;
|
| VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
|
| Declaration* declaration =
|
| factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
|
| @@ -2017,7 +2023,7 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
|
| // so rewrite it as such.
|
|
|
| Expect(Token::CLASS, CHECK_OK);
|
| - if (!allow_harmony_sloppy() && strict_mode() == SLOPPY) {
|
| + if (!allow_harmony_sloppy() && !is_strict(language_mode())) {
|
| ReportMessage("sloppy_lexical");
|
| *ok = false;
|
| return NULL;
|
| @@ -2046,7 +2052,7 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
|
|
|
|
|
| Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
|
| - if (allow_harmony_scoping() && strict_mode() == STRICT) {
|
| + if (allow_harmony_scoping() && is_strict(language_mode())) {
|
| return ParseScopedBlock(labels, ok);
|
| }
|
|
|
| @@ -2157,25 +2163,23 @@ Block* Parser::ParseVariableDeclarations(
|
| Consume(Token::VAR);
|
| } else if (peek() == Token::CONST) {
|
| Consume(Token::CONST);
|
| - switch (strict_mode()) {
|
| - case SLOPPY:
|
| - mode = CONST_LEGACY;
|
| - init_op = Token::INIT_CONST_LEGACY;
|
| - break;
|
| - case STRICT:
|
| - DCHECK(var_context != kStatement);
|
| - // In ES5 const is not allowed in strict mode.
|
| - if (!allow_harmony_scoping()) {
|
| - ReportMessage("strict_const");
|
| - *ok = false;
|
| - return NULL;
|
| - }
|
| - mode = CONST;
|
| - init_op = Token::INIT_CONST;
|
| + if (!is_strict(language_mode())) {
|
| + mode = CONST_LEGACY;
|
| + init_op = Token::INIT_CONST_LEGACY;
|
| + } else {
|
| + DCHECK(var_context != kStatement);
|
| + // In ES5 const is not allowed in strict mode.
|
| + if (!allow_harmony_scoping()) {
|
| + ReportMessage("strict_const");
|
| + *ok = false;
|
| + return NULL;
|
| + }
|
| + mode = CONST;
|
| + init_op = Token::INIT_CONST;
|
| }
|
| is_const = true;
|
| needs_init = true;
|
| - } else if (peek() == Token::LET && strict_mode() == STRICT) {
|
| + } else if (peek() == Token::LET && is_strict(language_mode())) {
|
| DCHECK(allow_harmony_scoping());
|
| Consume(Token::LET);
|
| DCHECK(var_context != kStatement);
|
| @@ -2346,10 +2350,10 @@ Block* Parser::ParseVariableDeclarations(
|
| Runtime::FunctionForId(Runtime::kInitializeConstGlobal), arguments,
|
| pos);
|
| } else {
|
| - // Add strict mode.
|
| + // Add language mode.
|
| // We may want to pass singleton to avoid Literal allocations.
|
| - StrictMode strict_mode = initialization_scope->strict_mode();
|
| - arguments->Add(factory()->NewNumberLiteral(strict_mode, pos), zone());
|
| + LanguageMode language_mode = initialization_scope->language_mode();
|
| + arguments->Add(factory()->NewNumberLiteral(language_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
|
| @@ -2658,7 +2662,7 @@ Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels,
|
| Expect(Token::WITH, CHECK_OK);
|
| int pos = position();
|
|
|
| - if (strict_mode() == STRICT) {
|
| + if (is_strict(language_mode())) {
|
| ReportMessage("strict_mode_with");
|
| *ok = false;
|
| return NULL;
|
| @@ -3228,7 +3232,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| bool is_let_identifier_expression = false;
|
| if (peek() != Token::SEMICOLON) {
|
| if (peek() == Token::VAR ||
|
| - (peek() == Token::CONST && strict_mode() == SLOPPY)) {
|
| + (peek() == Token::CONST && !is_strict(language_mode()))) {
|
| bool is_const = peek() == Token::CONST;
|
| const AstRawString* name = NULL;
|
| VariableDeclarationProperties decl_props = kHasNoInitializers;
|
| @@ -3267,7 +3271,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| init = variable_statement;
|
| }
|
| } else if ((peek() == Token::LET || peek() == Token::CONST) &&
|
| - strict_mode() == STRICT) {
|
| + is_strict(language_mode())) {
|
| bool is_const = peek() == Token::CONST;
|
| const AstRawString* name = NULL;
|
| VariableDeclarationProperties decl_props = kHasNoInitializers;
|
| @@ -3374,7 +3378,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
|
|
| // Parsed initializer at this point.
|
| // Detect attempts at 'let' declarations in sloppy mode.
|
| - if (peek() == Token::IDENTIFIER && strict_mode() == SLOPPY &&
|
| + if (peek() == Token::IDENTIFIER && !is_strict(language_mode()) &&
|
| is_let_identifier_expression) {
|
| ReportMessage("sloppy_lexical", NULL);
|
| *ok = false;
|
| @@ -3629,9 +3633,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| Scope* original_declaration_scope = original_scope_->DeclarationScope();
|
| Scope* scope =
|
| function_type == FunctionLiteral::DECLARATION &&
|
| - (!allow_harmony_scoping() || strict_mode() == SLOPPY) &&
|
| - (original_scope_ == original_declaration_scope ||
|
| - declaration_scope != original_declaration_scope)
|
| + (!allow_harmony_scoping() || !is_strict(language_mode())) &&
|
| + (original_scope_ == original_declaration_scope ||
|
| + declaration_scope != original_declaration_scope)
|
| ? NewScope(declaration_scope, FUNCTION_SCOPE)
|
| : NewScope(scope_, FUNCTION_SCOPE);
|
| ZoneList<Statement*>* body = NULL;
|
| @@ -3703,7 +3707,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| }
|
|
|
| Variable* var = scope_->DeclareParameter(param_name, VAR, is_rest);
|
| - if (scope->strict_mode() == SLOPPY) {
|
| + if (!is_strict(scope->language_mode())) {
|
| // TODO(sigurds) Mark every parameter as maybe assigned. This is a
|
| // conservative approximation necessary to account for parameters
|
| // that are assigned via the arguments array.
|
| @@ -3740,12 +3744,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| Variable* fvar = NULL;
|
| Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
|
| if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
|
| - if (allow_harmony_scoping() && strict_mode() == STRICT) {
|
| + if (allow_harmony_scoping() && is_strict(language_mode())) {
|
| fvar_init_op = Token::INIT_CONST;
|
| }
|
| VariableMode fvar_mode =
|
| - allow_harmony_scoping() && strict_mode() == STRICT
|
| - ? CONST : CONST_LEGACY;
|
| + allow_harmony_scoping() && is_strict(language_mode()) ? CONST
|
| + : CONST_LEGACY;
|
| DCHECK(function_name != NULL);
|
| fvar = new (zone())
|
| Variable(scope_, function_name, fvar_mode, true /* is valid LHS */,
|
| @@ -3810,7 +3814,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| // Concise methods use StrictFormalParameters.
|
| // Functions for which IsSimpleParameterList() returns false use
|
| // StrictFormalParameters.
|
| - if (strict_mode() == STRICT || IsConciseMethod(kind) || is_rest) {
|
| + if (is_strict(language_mode()) || IsConciseMethod(kind) || is_rest) {
|
| CheckStrictFunctionNameAndParameters(function_name,
|
| name_is_strict_reserved,
|
| function_name_location,
|
| @@ -3819,11 +3823,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| reserved_loc,
|
| CHECK_OK);
|
| }
|
| - if (strict_mode() == STRICT) {
|
| + if (is_strict(language_mode())) {
|
| CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
|
| CHECK_OK);
|
| }
|
| - if (allow_harmony_scoping() && strict_mode() == STRICT) {
|
| + if (allow_harmony_scoping() && is_strict(language_mode())) {
|
| CheckConflictingVarDeclarations(scope, CHECK_OK);
|
| }
|
| }
|
| @@ -3866,7 +3870,7 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
|
| total_preparse_skipped_ += scope_->end_position() - function_block_pos;
|
| *materialized_literal_count = entry.literal_count();
|
| *expected_property_count = entry.property_count();
|
| - scope_->SetStrictMode(entry.strict_mode());
|
| + scope_->SetLanguageMode(entry.language_mode());
|
| return;
|
| }
|
| cached_parse_data_->Reject();
|
| @@ -3897,13 +3901,13 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
|
| total_preparse_skipped_ += scope_->end_position() - function_block_pos;
|
| *materialized_literal_count = logger.literals();
|
| *expected_property_count = logger.properties();
|
| - scope_->SetStrictMode(logger.strict_mode());
|
| + scope_->SetLanguageMode(logger.language_mode());
|
| if (produce_cached_parse_data()) {
|
| DCHECK(log_);
|
| // Position right after terminal '}'.
|
| int body_end = scanner()->location().end_pos;
|
| log_->LogFunction(function_block_pos, body_end, *materialized_literal_count,
|
| - *expected_property_count, scope_->strict_mode());
|
| + *expected_property_count, scope_->language_mode());
|
| }
|
| }
|
|
|
| @@ -3998,10 +4002,8 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
|
| reusable_preparser_->set_allow_harmony_rest_params(
|
| allow_harmony_rest_params());
|
| }
|
| - PreParser::PreParseResult result =
|
| - reusable_preparser_->PreParseLazyFunction(strict_mode(),
|
| - is_generator(),
|
| - logger);
|
| + PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
|
| + language_mode(), is_generator(), logger);
|
| if (pre_parse_timer_ != NULL) {
|
| pre_parse_timer_->Stop();
|
| }
|
| @@ -4027,7 +4029,8 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
|
|
|
| Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
|
| BlockState block_state(&scope_, block_scope);
|
| - scope_->SetStrictMode(STRICT);
|
| + scope_->SetLanguageMode(
|
| + static_cast<LanguageMode>(scope_->language_mode() | STRICT));
|
| scope_->SetScopeName(name);
|
|
|
| VariableProxy* proxy = NULL;
|
|
|