| Index: src/preparser.h
|
| diff --git a/src/preparser.h b/src/preparser.h
|
| index d53447c92196c232f39bbc293412d61479fa8c4d..1ff9f1ef42af4f38c4a4b131a8131e2a626d759a 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,
|
| @@ -1674,8 +1681,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 +1896,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 +1975,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 +2802,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?
|
| FunctionState* function_state = function_state_;
|
| while (IsArrowFunction(function_state->kind())) {
|
| function_state = function_state->outer();
|
| @@ -2805,18 +2945,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());
|
| }
|
| }
|
| @@ -2958,7 +3092,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 +3123,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);
|
|
|
|
|