Chromium Code Reviews| Index: src/preparser.h |
| diff --git a/src/preparser.h b/src/preparser.h |
| index d53447c92196c232f39bbc293412d61479fa8c4d..195f038eba2caef342315d600e0d4b4f9e3e6e0b 100644 |
| --- a/src/preparser.h |
| +++ b/src/preparser.h |
| @@ -217,16 +217,18 @@ class ParserBase : public Traits { |
| void AddProperty() { expected_property_count_++; } |
| int expected_property_count() { return expected_property_count_; } |
| + Scanner::Location this_location() const { return this_location_; } |
| + Scanner::Location super_location() const { return super_location_; } |
| Scanner::Location return_location() const { return return_location_; } |
| - Scanner::Location super_call_location() const { |
| - return super_call_location_; |
| + void set_this_location(Scanner::Location location) { |
| + this_location_ = location; |
| + } |
| + void set_super_location(Scanner::Location location) { |
| + super_location_ = location; |
| } |
| void set_return_location(Scanner::Location location) { |
| return_location_ = location; |
| } |
| - void set_super_call_location(Scanner::Location location) { |
| - super_call_location_ = location; |
| - } |
| bool is_generator() const { return IsGeneratorFunction(kind_); } |
| @@ -258,11 +260,14 @@ class ParserBase : public Traits { |
| // Properties count estimation. |
| int expected_property_count_; |
| + // Location of most recent use of 'this' (invalid if none). |
| + Scanner::Location this_location_; |
| + |
| // Location of most recent 'return' statement (invalid if none). |
| Scanner::Location return_location_; |
| // Location of call to the "super" constructor (invalid if none). |
| - Scanner::Location super_call_location_; |
| + Scanner::Location super_location_; |
| FunctionKind kind_; |
| // For generators, this variable may hold the generator object. It variable |
| @@ -604,6 +609,8 @@ class ParserBase : public Traits { |
| ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok); |
| void AddTemplateExpression(ExpressionT); |
| ExpressionT ParseSuperExpression(bool is_new, bool* ok); |
| + ExpressionT ParseStrongInitializationExpression(bool* ok); |
| + ExpressionT ParseStrongSuperCallExpression(bool* ok); |
| // Checks if the expression is a valid reference expression (e.g., on the |
| // left-hand side of assignments). Although ruled out by ECMA as early errors, |
| @@ -1447,8 +1454,7 @@ class PreParserTraits { |
| return PreParserExpressionList(); |
| } |
| - V8_INLINE void SkipLazyFunctionBody(PreParserIdentifier function_name, |
| - int* materialized_literal_count, |
| + V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count, |
| int* expected_property_count, bool* ok) { |
| UNREACHABLE(); |
| } |
| @@ -1618,8 +1624,7 @@ class PreParser : public ParserBase<PreParserTraits> { |
| Expression ParseObjectLiteral(bool* ok); |
| Expression ParseV8Intrinsic(bool* ok); |
| - V8_INLINE void SkipLazyFunctionBody(PreParserIdentifier function_name, |
| - int* materialized_literal_count, |
| + V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count, |
| int* expected_property_count, bool* ok); |
| V8_INLINE PreParserStatementList |
| ParseEagerFunctionBody(PreParserIdentifier function_name, int pos, |
| @@ -1674,8 +1679,9 @@ ParserBase<Traits>::FunctionState::FunctionState( |
| : next_materialized_literal_index_(0), |
| next_handler_index_(0), |
| expected_property_count_(0), |
| + this_location_(Scanner::Location::invalid()), |
| return_location_(Scanner::Location::invalid()), |
| - super_call_location_(Scanner::Location::invalid()), |
| + super_location_(Scanner::Location::invalid()), |
| kind_(kind), |
| generator_object_variable_(NULL), |
| function_state_stack_(function_state_stack), |
| @@ -1888,6 +1894,15 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) { |
| switch (token) { |
| case Token::THIS: { |
| Consume(Token::THIS); |
| + if (is_strong(language_mode())) { |
| + // Constructors' usages of 'this' in strong mode are parsed separately. |
| + // TODO(rossberg): this does not work with arrow functions yet. |
| + if (i::IsConstructor(function_state_->kind())) { |
| + ReportMessage("strong_constructor_this"); |
| + *ok = false; |
| + break; |
| + } |
| + } |
| scope_->RecordThisUsage(); |
| result = this->ThisExpression(scope_, factory(), beg_pos); |
| break; |
| @@ -1958,7 +1973,7 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) { |
| case Token::CLASS: { |
| Consume(Token::CLASS); |
| if (!allow_harmony_sloppy() && is_sloppy(language_mode())) { |
| - ReportMessage("sloppy_lexical", NULL); |
| + ReportMessage("sloppy_lexical"); |
| *ok = false; |
| break; |
| } |
| @@ -2785,9 +2800,132 @@ ParserBase<Traits>::ParseMemberExpression(bool* ok) { |
| template <class Traits> |
| typename ParserBase<Traits>::ExpressionT |
| +ParserBase<Traits>::ParseStrongInitializationExpression(bool* ok) { |
| + // InitializationExpression :: (strong mode) |
| + // 'this' '.' IdentifierName '=' AssignmentExpression |
| + // 'this' '[' Expression ']' '=' AssignmentExpression |
| + |
| + Consume(Token::THIS); |
| + int pos = position(); |
| + function_state_->set_this_location(scanner()->location()); |
| + scope_->RecordThisUsage(); |
| + ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos); |
| + |
| + ExpressionT left = this->EmptyExpression(); |
| + switch (peek()) { |
| + case Token::LBRACK: { |
| + Consume(Token::LBRACK); |
| + int pos = position(); |
| + ExpressionT index = this->ParseExpression(true, CHECK_OK); |
| + left = factory()->NewProperty(this_expr, index, pos); |
| + if (fni_ != NULL) { |
| + this->PushPropertyName(fni_, index); |
| + } |
| + Expect(Token::RBRACK, CHECK_OK); |
| + break; |
| + } |
| + case Token::PERIOD: { |
| + Consume(Token::PERIOD); |
| + int pos = position(); |
| + IdentifierT name = ParseIdentifierName(CHECK_OK); |
| + left = factory()->NewProperty( |
| + this_expr, factory()->NewStringLiteral(name, pos), pos); |
| + if (fni_ != NULL) { |
| + this->PushLiteralName(fni_, name); |
| + } |
| + break; |
| + } |
| + default: |
| + ReportMessage("strong_constructor_this"); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } |
| + |
| + if (peek() != Token::ASSIGN) { |
| + ReportMessageAt(function_state_->this_location(), |
| + "strong_constructor_this"); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } |
| + Consume(Token::ASSIGN); |
| + left = this->MarkExpressionAsAssigned(left); |
| + |
| + ExpressionT right = this->ParseAssignmentExpression(true, CHECK_OK); |
| + this->CheckAssigningFunctionLiteralToProperty(left, right); |
| + function_state_->AddProperty(); |
| + if (fni_ != NULL) { |
| + // Check if the right hand side is a call to avoid inferring a |
| + // name if we're dealing with "this.a = function(){...}();"-like |
| + // expression. |
| + if (!right->IsCall() && !right->IsCallNew()) { |
| + fni_->Infer(); |
| + } else { |
| + fni_->RemoveLastFunction(); |
| + } |
| + fni_->Leave(); |
| + } |
| + |
| + if (function_state_->return_location().IsValid()) { |
| + ReportMessageAt(function_state_->return_location(), |
| + "strong_constructor_return_misplaced"); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } |
| + |
| + return factory()->NewAssignment(Token::ASSIGN, left, right, pos); |
| +} |
| + |
| + |
| +template <class Traits> |
| +typename ParserBase<Traits>::ExpressionT |
| +ParserBase<Traits>::ParseStrongSuperCallExpression(bool* ok) { |
| + // SuperCallExpression :: (strong mode) |
| + // 'super' '(' ExpressionList ')' |
| + |
| + Consume(Token::SUPER); |
| + int pos = position(); |
| + Scanner::Location super_loc = scanner()->location(); |
| + ExpressionT expr = this->SuperReference(scope_, factory()); |
| + |
| + if (peek() != Token::LPAREN) { |
| + ReportMessage("strong_constructor_super"); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } |
| + |
| + typename Traits::Type::ExpressionList args = ParseArguments(CHECK_OK); |
| + |
| + // TODO(rossberg): This doesn't work with arrow functions yet. |
| + if (!IsSubclassConstructor(function_state_->kind())) { |
| + ReportMessage("unexpected_super"); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } else if (function_state_->super_location().IsValid()) { |
| + ReportMessageAt(scanner()->location(), "strong_super_call_duplicate"); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } else if (function_state_->this_location().IsValid()) { |
| + ReportMessageAt(scanner()->location(), "strong_super_call_misplaced"); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } else if (function_state_->return_location().IsValid()) { |
| + ReportMessageAt(function_state_->return_location(), |
| + "strong_constructor_return_misplaced"); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } |
| + |
| + function_state_->set_super_location(super_loc); |
| + return factory()->NewCall(expr, args, pos); |
| +} |
| + |
| + |
| +template <class Traits> |
| +typename ParserBase<Traits>::ExpressionT |
| ParserBase<Traits>::ParseSuperExpression(bool is_new, bool* ok) { |
| Expect(Token::SUPER, CHECK_OK); |
| + // TODO(aperez): Does this actually work with lazily compiled arrows? |
|
marja
2015/04/21 09:01:37
-> wingo, since he took over?
rossberg
2015/04/21 09:47:47
Done.
|
| FunctionState* function_state = function_state_; |
| while (IsArrowFunction(function_state->kind())) { |
| function_state = function_state->outer(); |
| @@ -2805,18 +2943,12 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new, bool* ok) { |
| // super() is only allowed in derived constructor |
| if (!is_new && peek() == Token::LPAREN && IsSubclassConstructor(kind)) { |
| if (is_strong(language_mode())) { |
| - if (function_state->super_call_location().IsValid()) { |
| - ReportMessageAt(scanner()->location(), "strong_super_call_duplicate"); |
| - *ok = false; |
| - return this->EmptyExpression(); |
| - } else if (function_state->return_location().IsValid()) { |
| - ReportMessageAt(function_state->return_location(), |
| - "strong_constructor_return_misplaced"); |
| - *ok = false; |
| - return this->EmptyExpression(); |
| - } |
| + // Super calls in strong mode are parsed separately. |
| + ReportMessageAt(scanner()->location(), "strong_constructor_super"); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| } |
| - function_state->set_super_call_location(scanner()->location()); |
| + function_state->set_super_location(scanner()->location()); |
| return this->SuperReference(scope_, factory()); |
| } |
| } |
| @@ -2935,8 +3067,7 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
| (mode() == PARSE_LAZILY && scope_->AllowsLazyCompilation()); |
| if (is_lazily_parsed) { |
| body = this->NewStatementList(0, zone()); |
| - this->SkipLazyFunctionBody(this->EmptyIdentifier(), |
| - &materialized_literal_count, |
| + this->SkipLazyFunctionBody(&materialized_literal_count, |
| &expected_property_count, CHECK_OK); |
| } else { |
| body = this->ParseEagerFunctionBody( |
| @@ -2958,7 +3089,7 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
| expected_property_count = function_state.expected_property_count(); |
| handler_count = function_state.handler_count(); |
| } |
| - super_loc = function_state.super_call_location(); |
| + super_loc = function_state.super_location(); |
| scope->set_start_position(start_pos); |
| scope->set_end_position(scanner()->location().end_pos); |
| @@ -2989,7 +3120,7 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
| start_pos); |
| function_literal->set_function_token_position(start_pos); |
| - if (super_loc.IsValid()) function_state_->set_super_call_location(super_loc); |
| + if (super_loc.IsValid()) function_state_->set_super_location(super_loc); |
| if (fni_ != NULL) this->InferFunctionName(fni_, function_literal); |