| Index: src/parser.cc
|
| ===================================================================
|
| --- src/parser.cc (revision 8931)
|
| +++ src/parser.cc (working copy)
|
| @@ -584,7 +584,8 @@
|
| 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 @@
|
| 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 @@
|
|
|
|
|
| Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
|
| + if (harmony_block_scoping_) return ParseScopedBlock(labels, ok);
|
| +
|
| // Block ::
|
| // '{' Statement* '}'
|
|
|
| @@ -1510,6 +1516,56 @@
|
| }
|
|
|
|
|
| +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 ';'
|
| @@ -1956,41 +2012,6 @@
|
| }
|
|
|
|
|
| -Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) {
|
| - // Parse the statement and collect escaping labels.
|
| - TargetCollector collector;
|
| - Statement* stat;
|
| - { Target target(&this->target_stack_, &collector);
|
| - with_nesting_level_++;
|
| - top_scope_->DeclarationScope()->RecordWithStatement();
|
| - stat = ParseStatement(labels, CHECK_OK);
|
| - with_nesting_level_--;
|
| - }
|
| - // Create resulting block with two statements.
|
| - // 1: Evaluate the with expression.
|
| - // 2: The try-finally block evaluating the body.
|
| - Block* result = new(zone()) Block(isolate(), NULL, 2, false);
|
| -
|
| - if (result != NULL) {
|
| - result->AddStatement(new(zone()) EnterWithContextStatement(obj));
|
| -
|
| - // Create body block.
|
| - Block* body = new(zone()) Block(isolate(), NULL, 1, false);
|
| - body->AddStatement(stat);
|
| -
|
| - // Create exit block.
|
| - Block* exit = new(zone()) Block(isolate(), NULL, 1, false);
|
| - exit->AddStatement(new(zone()) ExitContextStatement());
|
| -
|
| - // Return a try-finally statement.
|
| - TryFinallyStatement* wrapper = new(zone()) TryFinallyStatement(body, exit);
|
| - wrapper->set_escaping_targets(collector.targets());
|
| - result->AddStatement(wrapper);
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -
|
| Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
|
| // WithStatement ::
|
| // 'with' '(' Expression ')' Statement
|
| @@ -2007,7 +2028,11 @@
|
| Expression* expr = ParseExpression(true, CHECK_OK);
|
| Expect(Token::RPAREN, CHECK_OK);
|
|
|
| - return WithHelper(expr, labels, CHECK_OK);
|
| + ++with_nesting_level_;
|
| + top_scope_->DeclarationScope()->RecordWithStatement();
|
| + Statement* stmt = ParseStatement(labels, CHECK_OK);
|
| + --with_nesting_level_;
|
| + return new(zone()) WithStatement(expr, stmt);
|
| }
|
|
|
|
|
| @@ -2142,39 +2167,22 @@
|
| Expect(Token::RPAREN, CHECK_OK);
|
|
|
| if (peek() == Token::LBRACE) {
|
| - // Rewrite the catch body B to a single statement block
|
| - // { try B finally { PopContext }}.
|
| - Block* inner_body;
|
| - // We need to collect escapes from the body for both the inner
|
| - // try/finally used to pop the catch context and any possible outer
|
| - // try/finally.
|
| - TargetCollector inner_collector;
|
| - { Target target(&this->target_stack_, &catch_collector);
|
| - { Target target(&this->target_stack_, &inner_collector);
|
| - catch_scope = NewScope(top_scope_, Scope::CATCH_SCOPE, inside_with());
|
| - if (top_scope_->is_strict_mode()) {
|
| - catch_scope->EnableStrictMode();
|
| - }
|
| - catch_variable = catch_scope->DeclareLocal(name, Variable::VAR);
|
| -
|
| - Scope* saved_scope = top_scope_;
|
| - top_scope_ = catch_scope;
|
| - inner_body = ParseBlock(NULL, CHECK_OK);
|
| - top_scope_ = saved_scope;
|
| - }
|
| + // Rewrite the catch body { B } to a block:
|
| + // { { B } ExitContext; }.
|
| + Target target(&this->target_stack_, &catch_collector);
|
| + catch_scope = NewScope(top_scope_, Scope::CATCH_SCOPE, inside_with());
|
| + if (top_scope_->is_strict_mode()) {
|
| + catch_scope->EnableStrictMode();
|
| }
|
| + catch_variable = catch_scope->DeclareLocal(name, Variable::VAR);
|
| + catch_block = new(zone()) Block(isolate(), NULL, 2, false);
|
|
|
| - // Create exit block.
|
| - Block* inner_finally = new(zone()) Block(isolate(), NULL, 1, false);
|
| - inner_finally->AddStatement(new(zone()) ExitContextStatement());
|
| -
|
| - // Create a try/finally statement.
|
| - TryFinallyStatement* inner_try_finally =
|
| - new(zone()) TryFinallyStatement(inner_body, inner_finally);
|
| - inner_try_finally->set_escaping_targets(inner_collector.targets());
|
| -
|
| - catch_block = new(zone()) Block(isolate(), NULL, 1, false);
|
| - catch_block->AddStatement(inner_try_finally);
|
| + Scope* saved_scope = top_scope_;
|
| + top_scope_ = catch_scope;
|
| + Block* catch_body = ParseBlock(NULL, CHECK_OK);
|
| + top_scope_ = saved_scope;
|
| + catch_block->AddStatement(catch_body);
|
| + catch_block->AddStatement(new(zone()) ExitContextStatement());
|
| } else {
|
| Expect(Token::LBRACE, CHECK_OK);
|
| }
|
| @@ -5105,6 +5113,8 @@
|
| 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 +5122,8 @@
|
| 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 +5142,6 @@
|
| info->StrictMode());
|
| }
|
| }
|
| -
|
| info->SetFunction(result);
|
| return (result != NULL);
|
| }
|
|
|