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); |