Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 08395106a60d0b5ffe436252bdac060a6925bc4e..b004ac481f43f997bbbb19cac4e61255a718579f 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -609,7 +609,7 @@ Parser::Parser(Handle<Script> script, |
FunctionLiteral* Parser::ParseProgram(Handle<String> source, |
bool in_global_context, |
- StrictModeFlag strict_mode) { |
+ LanguageMode language_mode) { |
ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT); |
HistogramTimerScope timer(isolate()->counters()->parse()); |
@@ -625,18 +625,20 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, |
ExternalTwoByteStringUC16CharacterStream stream( |
Handle<ExternalTwoByteString>::cast(source), 0, source->length()); |
scanner_.Initialize(&stream); |
- return DoParseProgram(source, in_global_context, strict_mode, &zone_scope); |
+ return |
+ DoParseProgram(source, in_global_context, language_mode, &zone_scope); |
} else { |
GenericStringUC16CharacterStream stream(source, 0, source->length()); |
scanner_.Initialize(&stream); |
- return DoParseProgram(source, in_global_context, strict_mode, &zone_scope); |
+ return |
+ DoParseProgram(source, in_global_context, language_mode, &zone_scope); |
} |
} |
FunctionLiteral* Parser::DoParseProgram(Handle<String> source, |
bool in_global_context, |
- StrictModeFlag strict_mode, |
+ LanguageMode language_mode, |
ZoneScope* zone_scope) { |
ASSERT(top_scope_ == NULL); |
ASSERT(target_stack_ == NULL); |
@@ -654,13 +656,13 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source, |
scope->set_start_position(0); |
scope->set_end_position(source->length()); |
FunctionState function_state(this, scope, isolate()); |
- ASSERT(top_scope_->strict_mode_flag() == kNonStrictMode); |
- top_scope_->SetStrictModeFlag(strict_mode); |
+ ASSERT(top_scope_->language_mode() == CLASSIC_MODE); |
+ top_scope_->SetLanguageMode(language_mode); |
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16); |
bool ok = true; |
int beg_loc = scanner().location().beg_pos; |
ParseSourceElements(body, Token::EOS, &ok); |
- if (ok && top_scope_->is_strict_mode()) { |
+ if (ok && !top_scope_->is_classic_mode()) { |
CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok); |
} |
@@ -746,10 +748,11 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, |
scope = Scope::DeserializeScopeChain(info, scope); |
} |
FunctionState function_state(this, scope, isolate()); |
- ASSERT(scope->strict_mode_flag() == kNonStrictMode || |
- scope->strict_mode_flag() == info->strict_mode_flag()); |
- ASSERT(info->strict_mode_flag() == shared_info->strict_mode_flag()); |
- scope->SetStrictModeFlag(shared_info->strict_mode_flag()); |
+ ASSERT(scope->language_mode() != STRICT_MODE || !info->is_classic_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()); |
FunctionLiteral::Type type = shared_info->is_expression() |
? (shared_info->is_anonymous() |
? FunctionLiteral::ANONYMOUS_EXPRESSION |
@@ -1192,11 +1195,12 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, |
Handle<String> directive = Handle<String>::cast(literal->handle()); |
// Check "use strict" directive (ES5 14.1). |
- if (!top_scope_->is_strict_mode() && |
+ if (top_scope_->is_classic_mode() && |
directive->Equals(isolate()->heap()->use_strict()) && |
token_loc.end_pos - token_loc.beg_pos == |
isolate()->heap()->use_strict()->length() + 2) { |
- top_scope_->SetStrictModeFlag(kStrictMode); |
+ top_scope_->SetLanguageMode(harmony_scoping_ |
+ ? EXTENDED_MODE : STRICT_MODE); |
// "use strict" is the only directive for now. |
directive_prologue = false; |
} |
@@ -1334,7 +1338,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) { |
// FunctionDeclaration |
// Common language extension is to allow function declaration in place |
// of any statement. This language extension is disabled in strict mode. |
- if (top_scope_->is_strict_mode() || harmony_scoping_) { |
+ if (!top_scope_->is_classic_mode()) { |
ReportMessageAt(scanner().peek_location(), "strict_function", |
Vector<const char*>::empty()); |
*ok = false; |
@@ -1382,7 +1386,7 @@ VariableProxy* Parser::Declare(Handle<String> name, |
// Also for block scoped let/const bindings the variable can be |
// statically declared. |
if (declaration_scope->is_function_scope() || |
- declaration_scope->is_strict_mode_eval_scope() || |
+ declaration_scope->is_strict_or_extended_eval_scope() || |
declaration_scope->is_block_scope()) { |
// Declare the variable in the function scope. |
var = declaration_scope->LocalLookup(name); |
@@ -1574,7 +1578,7 @@ Statement* Parser::ParseFunctionDeclaration(bool* ok) { |
Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { |
- if (harmony_scoping_) return ParseScopedBlock(labels, ok); |
+ if (top_scope_->is_extended_mode()) return ParseScopedBlock(labels, ok); |
// Block :: |
// '{' Statement* '}' |
@@ -1690,28 +1694,31 @@ Block* Parser::ParseVariableDeclarations( |
Consume(Token::VAR); |
} else if (peek() == Token::CONST) { |
Consume(Token::CONST); |
- if (harmony_scoping_) { |
- if (var_context != kSourceElement && |
- var_context != kForStatement) { |
- // In harmony mode 'const' declarations are only allowed in source |
- // element positions. |
- ReportMessage("unprotected_const", Vector<const char*>::empty()); |
+ switch (top_scope_->language_mode()) { |
+ case CLASSIC_MODE: |
+ mode = CONST; |
+ init_op = Token::INIT_CONST; |
+ break; |
+ case STRICT_MODE: |
+ ReportMessage("strict_const", Vector<const char*>::empty()); |
*ok = false; |
return NULL; |
- } |
- mode = CONST_HARMONY; |
- init_op = Token::INIT_CONST_HARMONY; |
- } else if (top_scope_->is_strict_mode()) { |
- ReportMessage("strict_const", Vector<const char*>::empty()); |
- *ok = false; |
- return NULL; |
- } else { |
- mode = CONST; |
- init_op = Token::INIT_CONST; |
+ case EXTENDED_MODE: |
+ if (var_context != kSourceElement && |
+ var_context != kForStatement) { |
+ // In extended mode 'const' declarations are only allowed in source |
+ // element positions. |
+ ReportMessage("unprotected_const", Vector<const char*>::empty()); |
+ *ok = false; |
+ return NULL; |
+ } |
+ mode = CONST_HARMONY; |
+ init_op = Token::INIT_CONST_HARMONY; |
} |
is_const = true; |
needs_init = true; |
} else if (peek() == Token::LET) { |
+ ASSERT(top_scope_->is_extended_mode()); |
Consume(Token::LET); |
if (var_context != kSourceElement && |
var_context != kForStatement) { |
@@ -1755,7 +1762,7 @@ Block* Parser::ParseVariableDeclarations( |
if (fni_ != NULL) fni_->PushVariableName(name); |
// Strict mode variables may not be named eval or arguments |
- if (declaration_scope->is_strict_mode() && IsEvalOrArguments(name)) { |
+ if (!declaration_scope->is_classic_mode() && IsEvalOrArguments(name)) { |
ReportMessage("strict_var_name", Vector<const char*>::empty()); |
*ok = false; |
return NULL; |
@@ -1884,8 +1891,8 @@ Block* Parser::ParseVariableDeclarations( |
} else { |
// Add strict mode. |
// We may want to pass singleton to avoid Literal allocations. |
- StrictModeFlag flag = initialization_scope->strict_mode_flag(); |
- arguments->Add(NewNumberLiteral(flag)); |
+ LanguageMode language_mode = initialization_scope->language_mode(); |
+ arguments->Add(NewNumberLiteral(language_mode)); |
// Be careful not to assign a value to the global variable if |
// we're in a with. The initialization value should not |
@@ -2141,7 +2148,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { |
Expect(Token::WITH, CHECK_OK); |
- if (top_scope_->is_strict_mode()) { |
+ if (!top_scope_->is_classic_mode()) { |
ReportMessage("strict_mode_with", Vector<const char*>::empty()); |
*ok = false; |
return NULL; |
@@ -2287,7 +2294,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { |
catch_scope->set_start_position(scanner().location().beg_pos); |
name = ParseIdentifier(CHECK_OK); |
- if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) { |
+ if (!top_scope_->is_classic_mode() && IsEvalOrArguments(name)) { |
ReportMessage("strict_catch_variable", Vector<const char*>::empty()); |
*ok = false; |
return NULL; |
@@ -2638,7 +2645,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) { |
expression = NewThrowReferenceError(type); |
} |
- if (top_scope_->is_strict_mode()) { |
+ if (!top_scope_->is_classic_mode()) { |
// Assignment to eval or arguments is disallowed in strict mode. |
CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK); |
} |
@@ -2847,7 +2854,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) { |
} |
// "delete identifier" is a syntax error in strict mode. |
- if (op == Token::DELETE && top_scope_->is_strict_mode()) { |
+ if (op == Token::DELETE && !top_scope_->is_classic_mode()) { |
VariableProxy* operand = expression->AsVariableProxy(); |
if (operand != NULL && !operand->is_this()) { |
ReportMessage("strict_delete", Vector<const char*>::empty()); |
@@ -2871,7 +2878,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) { |
expression = NewThrowReferenceError(type); |
} |
- if (top_scope_->is_strict_mode()) { |
+ if (!top_scope_->is_classic_mode()) { |
// Prefix expression operand in strict mode may not be eval or arguments. |
CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK); |
} |
@@ -2906,7 +2913,7 @@ Expression* Parser::ParsePostfixExpression(bool* ok) { |
expression = NewThrowReferenceError(type); |
} |
- if (top_scope_->is_strict_mode()) { |
+ if (!top_scope_->is_classic_mode()) { |
// Postfix expression operand in strict mode may not be eval or arguments. |
CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK); |
} |
@@ -3137,9 +3144,9 @@ void Parser::ReportUnexpectedToken(Token::Value token) { |
return ReportMessage("unexpected_reserved", |
Vector<const char*>::empty()); |
case Token::FUTURE_STRICT_RESERVED_WORD: |
- return ReportMessage(top_scope_->is_strict_mode() ? |
- "unexpected_strict_reserved" : |
- "unexpected_token_identifier", |
+ return ReportMessage(top_scope_->is_classic_mode() ? |
+ "unexpected_token_identifier" : |
+ "unexpected_strict_reserved", |
Vector<const char*>::empty()); |
default: |
const char* name = Token::String(token); |
@@ -3485,11 +3492,11 @@ bool IsEqualNumber(void* first, void* second); |
// Validation per 11.1.5 Object Initialiser |
class ObjectLiteralPropertyChecker { |
public: |
- ObjectLiteralPropertyChecker(Parser* parser, bool strict) : |
+ ObjectLiteralPropertyChecker(Parser* parser, LanguageMode language_mode) : |
props(&IsEqualString), |
elems(&IsEqualNumber), |
parser_(parser), |
- strict_(strict) { |
+ language_mode_(language_mode) { |
} |
void CheckProperty( |
@@ -3519,7 +3526,7 @@ class ObjectLiteralPropertyChecker { |
HashMap props; |
HashMap elems; |
Parser* parser_; |
- bool strict_; |
+ LanguageMode language_mode_; |
}; |
@@ -3568,8 +3575,8 @@ void ObjectLiteralPropertyChecker::CheckProperty( |
intptr_t prev = reinterpret_cast<intptr_t> (entry->value); |
intptr_t curr = GetPropertyKind(property); |
- // Duplicate data properties are illegal in strict mode. |
- if (strict_ && (curr & prev & kData) != 0) { |
+ // Duplicate data properties are illegal in strict or extended mode. |
+ if (language_mode_ != CLASSIC_MODE && (curr & prev & kData) != 0) { |
parser_->ReportMessageAt(loc, "strict_duplicate_property", |
Vector<const char*>::empty()); |
*ok = false; |
@@ -3705,7 +3712,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { |
int number_of_boilerplate_properties = 0; |
bool has_function = false; |
- ObjectLiteralPropertyChecker checker(this, top_scope_->is_strict_mode()); |
+ ObjectLiteralPropertyChecker checker(this, top_scope_->language_mode()); |
Expect(Token::LBRACE, CHECK_OK); |
@@ -4011,7 +4018,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name, |
scanner().SeekForward(scope->end_position() - 1); |
materialized_literal_count = entry.literal_count(); |
expected_property_count = entry.property_count(); |
- top_scope_->SetStrictModeFlag(entry.strict_mode_flag()); |
+ top_scope_->SetLanguageMode(entry.language_mode()); |
only_simple_this_property_assignments = false; |
this_property_assignments = isolate()->factory()->empty_fixed_array(); |
Expect(Token::RBRACE, CHECK_OK); |
@@ -4044,7 +4051,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name, |
} |
// Validate strict mode. |
- if (top_scope_->is_strict_mode()) { |
+ if (!top_scope_->is_classic_mode()) { |
if (IsEvalOrArguments(function_name)) { |
int start_pos = scope->start_position(); |
int position = function_token_position != RelocInfo::kNoPosition |
@@ -4230,7 +4237,7 @@ Literal* Parser::GetLiteralNumber(double value) { |
// Parses an identifier that is valid for the current scope, in particular it |
// fails on strict mode future reserved keywords in a strict scope. |
Handle<String> Parser::ParseIdentifier(bool* ok) { |
- if (top_scope_->is_strict_mode()) { |
+ if (!top_scope_->is_classic_mode()) { |
Expect(Token::IDENTIFIER, ok); |
} else if (!Check(Token::IDENTIFIER)) { |
Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); |
@@ -4273,7 +4280,7 @@ Handle<String> Parser::ParseIdentifierName(bool* ok) { |
void Parser::CheckStrictModeLValue(Expression* expression, |
const char* error, |
bool* ok) { |
- ASSERT(top_scope_->is_strict_mode()); |
+ ASSERT(!top_scope_->is_classic_mode()); |
VariableProxy* lhs = expression != NULL |
? expression->AsVariableProxy() |
: NULL; |
@@ -5436,7 +5443,7 @@ bool ParserApi::Parse(CompilationInfo* info) { |
Handle<String> source = Handle<String>(String::cast(script->source())); |
result = parser.ParseProgram(source, |
info->is_global(), |
- info->strict_mode_flag()); |
+ info->language_mode()); |
} |
} |
info->SetFunction(result); |