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