diff --git a/src/parser.h b/src/parser.h index fd24e8d4e9..b04f1dade1 100644 --- a/src/parser.h +++ b/src/parser.h @@ -339,6 +339,23 @@ class RegExpParser BASE_EMBEDDED { // ---------------------------------------------------------------------------- // JAVASCRIPT PARSING + +class ParserCheckpoint BASE_EMBEDDED { + public: + template + explicit ParserCheckpoint(Parser* parser) { + isolate_ = parser->zone()->isolate(); + saved_ast_node_id_ = isolate_->ast_node_id(); + } + + void Restore() { isolate_->set_ast_node_id(saved_ast_node_id_); } + + private: + Isolate* isolate_; + int saved_ast_node_id_; +}; + + class Parser; class SingletonLogger; @@ -354,6 +371,7 @@ class ParserTraits { typedef v8::internal::Scope* ScopePtr; typedef Variable GeneratorVariable; typedef v8::internal::Zone Zone; + typedef ParserCheckpoint Checkpoint; typedef v8::internal::AstProperties AstProperties; typedef Vector ParameterIdentifierVector; diff --git a/src/preparser.h b/src/preparser.h index 517403d347..06de6ebe2e 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -114,6 +114,8 @@ class ParserBase : public Traits { } protected: + friend class Traits::Type::Checkpoint; + enum AllowEvalOrArgumentsAsIdentifier { kAllowEvalOrArguments, kDontAllowEvalOrArguments @@ -124,6 +126,8 @@ class ParserBase : public Traits { PARSE_EAGERLY }; + class ParserCheckpoint; + // --------------------------------------------------------------------------- // FunctionState and BlockState together implement the parser's scope stack. // The parser's current scope is in scope_. BlockState and FunctionState @@ -219,6 +223,38 @@ class ParserBase : public Traits { typename Traits::Type::Factory factory_; friend class ParserTraits; + friend class ParserCheckpoint; + }; + + // Annoyingly, arrow functions first parse as comma expressions, then when we + // see the => we have to go back and reinterpret the arguments as being formal + // parameters. To do so we need to reset some of the parser state back to + // what it was before the arguments were first seen. + class ParserCheckpoint : public Traits::Type::Checkpoint { + public: + template + explicit ParserCheckpoint(Parser* parser) + : Traits::Type::Checkpoint(parser) { + function_state_ = parser->function_state_; + next_materialized_literal_index_ = + function_state_->next_materialized_literal_index_; + next_handler_index_ = function_state_->next_handler_index_; + expected_property_count_ = function_state_->expected_property_count_; + } + + void Restore() { + Traits::Type::Checkpoint::Restore(); + function_state_->next_materialized_literal_index_ = + next_materialized_literal_index_; + function_state_->next_handler_index_ = next_handler_index_; + function_state_->expected_property_count_ = expected_property_count_; + } + + private: + FunctionState* function_state_; + int next_materialized_literal_index_; + int next_handler_index_; + int expected_property_count_; }; class ParsingModeScope BASE_EMBEDDED { @@ -1021,6 +1057,14 @@ class PreParserFactory { }; +class PreParserCheckpoint BASE_EMBEDDED { + public: + template + explicit PreParserCheckpoint(Parser* parser) {} + void Restore() {} +}; + + class PreParser; class PreParserTraits { @@ -1033,6 +1077,7 @@ class PreParserTraits { // Used by FunctionState and BlockState. typedef PreParserScope Scope; typedef PreParserScope ScopePtr; + typedef PreParserCheckpoint Checkpoint; // PreParser doesn't need to store generator variables. typedef void GeneratorVariable; @@ -2006,10 +2051,12 @@ ParserBase::ParseAssignmentExpression(bool accept_IN, bool* ok) { } if (fni_ != NULL) fni_->Enter(); + ParserCheckpoint checkpoint(this); ExpressionT expression = this->ParseConditionalExpression(accept_IN, CHECK_OK); if (allow_arrow_functions() && peek() == Token::ARROW) { + checkpoint.Restore(); expression = this->ParseArrowFunctionLiteral(lhs_location.beg_pos, expression, CHECK_OK); return expression;