Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index 38d12e11afa752c2eea349b76519d1d59ef1d885..3781631cca9e762ff3ec001351686ab0ace676ec 100644 |
--- a/src/preparser.h |
+++ b/src/preparser.h |
@@ -425,6 +425,13 @@ class ParserBase : public Traits { |
ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, |
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, |
+ // we allow calls for web compatibility and rewrite them to a runtime throw. |
+ ExpressionT CheckAndRewriteReferenceExpression( |
+ ExpressionT expression, |
+ Scanner::Location location, const char* message, bool* ok); |
+ |
// Used to detect duplicates in object literals. Each of the values |
// kGetterProperty, kSetterProperty and kValueProperty represents |
// a type of object literal property. When parsing a property, its |
@@ -589,10 +596,14 @@ class PreParserExpression { |
return PreParserExpression(kPropertyExpression); |
} |
+ static PreParserExpression Call() { |
+ return PreParserExpression(kCallExpression); |
+ } |
+ |
bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; } |
- // Only works corretly if it is actually an identifier expression. |
PreParserIdentifier AsIdentifier() { |
+ ASSERT(IsIdentifier()); |
return PreParserIdentifier( |
static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift)); |
} |
@@ -611,13 +622,14 @@ class PreParserExpression { |
return code_ == kPropertyExpression || code_ == kThisPropertyExpression; |
} |
- bool IsValidLeftHandSide() { |
+ bool IsCall() { return code_ == kCallExpression; } |
+ |
+ bool IsValidReferenceExpression() { |
return IsIdentifier() || IsProperty(); |
} |
// At the moment PreParser doesn't track these expression types. |
bool IsFunctionLiteral() const { return false; } |
- bool IsCall() const { return false; } |
bool IsCallNew() const { return false; } |
PreParserExpression AsFunctionLiteral() { return *this; } |
@@ -651,7 +663,8 @@ class PreParserExpression { |
// 2 least significant bits for flags. |
kThisExpression = 1 << 2, |
kThisPropertyExpression = 2 << 2, |
- kPropertyExpression = 3 << 2 |
+ kPropertyExpression = 3 << 2, |
+ kCallExpression = 4 << 2 |
}; |
explicit PreParserExpression(int expression_code) : code_(expression_code) {} |
@@ -782,7 +795,7 @@ class PreParserFactory { |
PreParserExpression NewCall(PreParserExpression expression, |
PreParserExpressionList arguments, |
int pos) { |
- return PreParserExpression::Default(); |
+ return PreParserExpression::Call(); |
} |
PreParserExpression NewCallNew(PreParserExpression expression, |
PreParserExpressionList arguments, |
@@ -845,6 +858,10 @@ class PreParserTraits { |
return expression.IsIdentifier(); |
} |
+ static PreParserIdentifier AsIdentifier(PreParserExpression expression) { |
+ return expression.AsIdentifier(); |
+ } |
+ |
static bool IsBoilerplateProperty(PreParserExpression property) { |
// PreParser doesn't count boilerplate properties. |
return false; |
@@ -883,10 +900,6 @@ class PreParserTraits { |
return expression; |
} |
- // Checks LHS expression for assignment and prefix/postfix increment/decrement |
- // in strict mode. |
- void CheckStrictModeLValue(PreParserExpression expression, bool* ok); |
- |
bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x, |
PreParserExpression y, |
Token::Value op, |
@@ -901,6 +914,18 @@ class PreParserTraits { |
return PreParserExpression::Default(); |
} |
+ PreParserExpression NewThrowReferenceError(const char* type, int pos) { |
+ return PreParserExpression::Default(); |
+ } |
+ PreParserExpression NewThrowSyntaxError( |
+ const char* type, Handle<Object> arg, int pos) { |
+ return PreParserExpression::Default(); |
+ } |
+ PreParserExpression NewThrowTypeError( |
+ const char* type, Handle<Object> arg1, Handle<Object> arg2, int pos) { |
+ return PreParserExpression::Default(); |
+ } |
+ |
// Reporting errors. |
void ReportMessageAt(Scanner::Location location, |
const char* message, |
@@ -1695,16 +1720,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) { |
return expression; |
} |
- if (!expression->IsValidLeftHandSide()) { |
- this->ReportMessageAt(lhs_location, "invalid_lhs_in_assignment", true); |
- *ok = false; |
- return this->EmptyExpression(); |
- } |
- |
- if (strict_mode() == STRICT) { |
- // Assignment to eval or arguments is disallowed in strict mode. |
- this->CheckStrictModeLValue(expression, CHECK_OK); |
- } |
+ expression = this->CheckAndRewriteReferenceExpression( |
+ expression, lhs_location, "invalid_lhs_in_assignment", CHECK_OK); |
expression = this->MarkExpressionAsLValue(expression); |
Token::Value op = Next(); // Get assignment operator. |
@@ -1864,17 +1881,9 @@ ParserBase<Traits>::ParseUnaryExpression(bool* ok) { |
} else if (Token::IsCountOp(op)) { |
op = Next(); |
Scanner::Location lhs_location = scanner()->peek_location(); |
- ExpressionT expression = ParseUnaryExpression(CHECK_OK); |
- if (!expression->IsValidLeftHandSide()) { |
- ReportMessageAt(lhs_location, "invalid_lhs_in_prefix_op", true); |
- *ok = false; |
- return this->EmptyExpression(); |
- } |
- |
- if (strict_mode() == STRICT) { |
- // Prefix expression operand in strict mode may not be eval or arguments. |
- this->CheckStrictModeLValue(expression, CHECK_OK); |
- } |
+ ExpressionT expression = this->ParseUnaryExpression(CHECK_OK); |
+ expression = this->CheckAndRewriteReferenceExpression( |
+ expression, lhs_location, "invalid_lhs_in_prefix_op", CHECK_OK); |
this->MarkExpressionAsLValue(expression); |
return factory()->NewCountOperation(op, |
@@ -1898,16 +1907,8 @@ ParserBase<Traits>::ParsePostfixExpression(bool* ok) { |
ExpressionT expression = this->ParseLeftHandSideExpression(CHECK_OK); |
if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
Token::IsCountOp(peek())) { |
- if (!expression->IsValidLeftHandSide()) { |
- ReportMessageAt(lhs_location, "invalid_lhs_in_postfix_op", true); |
- *ok = false; |
- return this->EmptyExpression(); |
- } |
- |
- if (strict_mode() == STRICT) { |
- // Postfix expression operand in strict mode may not be eval or arguments. |
- this->CheckStrictModeLValue(expression, CHECK_OK); |
- } |
+ expression = this->CheckAndRewriteReferenceExpression( |
+ expression, lhs_location, "invalid_lhs_in_postfix_op", CHECK_OK); |
expression = this->MarkExpressionAsLValue(expression); |
Token::Value next = Next(); |
@@ -2117,6 +2118,32 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression, |
} |
+template <typename Traits> |
+typename ParserBase<Traits>::ExpressionT |
+ParserBase<Traits>::CheckAndRewriteReferenceExpression( |
+ ExpressionT expression, |
+ Scanner::Location location, const char* message, bool* ok) { |
+ if (strict_mode() == STRICT && this->IsIdentifier(expression) && |
+ this->IsEvalOrArguments(this->AsIdentifier(expression))) { |
+ this->ReportMessageAt(location, "strict_eval_arguments", false); |
+ *ok = false; |
+ return this->EmptyExpression(); |
+ } else if (expression->IsValidReferenceExpression()) { |
+ return expression; |
+ } else if (expression->IsCall()) { |
+ // If it is a call, make it a runtime error for legacy web compatibility. |
+ // Rewrite `expr' to `expr[throw ReferenceError]'. |
+ int pos = location.beg_pos; |
+ ExpressionT error = this->NewThrowReferenceError(message, pos); |
+ return factory()->NewProperty(expression, error, pos); |
+ } else { |
+ this->ReportMessageAt(location, message, true); |
+ *ok = false; |
+ return this->EmptyExpression(); |
+ } |
+} |
+ |
+ |
#undef CHECK_OK |
#undef CHECK_OK_CUSTOM |