Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index f32e9177b5a9120905a287fb1fdac1891c3eb7a6..1167f43df519321d34a8a7efad9e085b2af7e548 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -584,7 +584,8 @@ Parser::Parser(Handle<Script> script, |
pre_data_(pre_data), |
fni_(NULL), |
stack_overflow_(false), |
- parenthesized_function_(false) { |
+ parenthesized_function_(false), |
+ harmony_block_scoping_(false) { |
AstNode::ResetIds(); |
} |
@@ -809,6 +810,9 @@ void Parser::ReportMessageAt(Scanner::Location source_location, |
isolate()->Throw(*result, &location); |
} |
+void Parser::SetHarmonyBlockScoping(bool block_scoping) { |
+ harmony_block_scoping_ = block_scoping; |
+} |
// Base class containing common code for the different finder classes used by |
// the parser. |
@@ -1487,6 +1491,8 @@ Statement* Parser::ParseFunctionDeclaration(bool* ok) { |
Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { |
+ if (harmony_block_scoping_) return ParseScopedBlock(labels, ok); |
+ |
// Block :: |
// '{' Statement* '}' |
@@ -1510,6 +1516,56 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { |
} |
+Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { |
+ // Construct block expecting 16 statements. |
+ Block* body = new(zone()) Block(isolate(), labels, 16, false); |
+ Scope* saved_scope = top_scope_; |
+ Scope* block_scope = NewScope(top_scope_, |
+ Scope::BLOCK_SCOPE, |
+ inside_with()); |
+ body->set_block_scope(block_scope); |
+ block_scope->DeclareLocal(isolate()->factory()->block_scope_symbol(), |
+ Variable::VAR); |
+ if (top_scope_->is_strict_mode()) { |
+ block_scope->EnableStrictMode(); |
+ } |
+ top_scope_ = block_scope; |
+ |
+ // Parse the statements and collect escaping labels. |
+ TargetCollector collector; |
+ Target target(&this->target_stack_, &collector); |
+ Expect(Token::LBRACE, CHECK_OK); |
+ { |
+ Target target_body(&this->target_stack_, body); |
+ InitializationBlockFinder block_finder(top_scope_, target_stack_); |
+ |
+ while (peek() != Token::RBRACE) { |
+ Statement* stat = ParseStatement(NULL, CHECK_OK); |
+ if (stat && !stat->IsEmpty()) { |
+ body->AddStatement(stat); |
+ block_finder.Update(stat); |
+ } |
+ } |
+ } |
+ Expect(Token::RBRACE, CHECK_OK); |
+ |
+ // Create exit block. |
+ Block* exit = new(zone()) Block(isolate(), NULL, 1, false); |
+ exit->AddStatement(new(zone()) ExitContextStatement()); |
+ |
+ // Create a try-finally statement. |
+ TryFinallyStatement* try_finally = |
+ new(zone()) TryFinallyStatement(body, exit); |
+ try_finally->set_escaping_targets(collector.targets()); |
+ top_scope_ = saved_scope; |
+ |
+ // Create a result block. |
+ Block* result = new(zone()) Block(isolate(), NULL, 1, false); |
+ result->AddStatement(try_finally); |
+ return result; |
+} |
+ |
+ |
Block* Parser::ParseVariableStatement(bool* ok) { |
// VariableStatement :: |
// VariableDeclarations ';' |
@@ -5105,6 +5161,8 @@ bool ParserApi::Parse(CompilationInfo* info) { |
Handle<Script> script = info->script(); |
if (info->is_lazy()) { |
Parser parser(script, true, NULL, NULL); |
+ parser.SetHarmonyBlockScoping(!info->is_native() && |
+ FLAG_harmony_block_scoping); |
result = parser.ParseLazy(info); |
} else { |
// Whether we allow %identifier(..) syntax. |
@@ -5112,6 +5170,8 @@ bool ParserApi::Parse(CompilationInfo* info) { |
info->allows_natives_syntax() || FLAG_allow_natives_syntax; |
ScriptDataImpl* pre_data = info->pre_parse_data(); |
Parser parser(script, allow_natives_syntax, info->extension(), pre_data); |
+ parser.SetHarmonyBlockScoping(!info->is_native() && |
+ FLAG_harmony_block_scoping); |
if (pre_data != NULL && pre_data->has_error()) { |
Scanner::Location loc = pre_data->MessageLocation(); |
const char* message = pre_data->BuildMessage(); |
@@ -5130,7 +5190,6 @@ bool ParserApi::Parse(CompilationInfo* info) { |
info->StrictMode()); |
} |
} |
- |
info->SetFunction(result); |
return (result != NULL); |
} |