Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index 06880d5274716257b8a12e81be98ceb18bd723d9..48bbfeaffaa1205ae0e57801a8d4d7dd60033685 100644 |
--- a/src/preparser.h |
+++ b/src/preparser.h |
@@ -382,6 +382,8 @@ class ParserBase : public Traits { |
typename Traits::Type::Expression ParseArrayLiteral(bool* ok); |
typename Traits::Type::Expression ParseObjectLiteral(bool* ok); |
typename Traits::Type::ExpressionList ParseArguments(bool* ok); |
+ typename Traits::Type::Expression ParseAssignmentExpression(bool accept_IN, |
+ bool* ok); |
// Used to detect duplicates in object literals. Each of the values |
// kGetterProperty, kSetterProperty and kValueProperty represents |
@@ -564,6 +566,14 @@ class PreParserExpression { |
bool IsStrictFunction() { return code_ == kStrictFunctionExpression; } |
+ // Dummy implementation for making expression->AsCall() work (see below). |
+ PreParserExpression* operator->() { return this; } |
+ |
+ // These are only used when doing function name inferring, and PreParser |
+ // doesn't do function name inferring. |
+ void* AsCall() const { return NULL; } |
+ void* AsCallNew() const { return NULL; } |
+ |
private: |
// First two/three bits are used as flags. |
// Bit 0 and 1 represent identifiers or strings literals, and are |
@@ -683,6 +693,13 @@ class PreParserFactory { |
int pos) { |
return PreParserExpression::Default(); |
} |
+ |
+ PreParserExpression NewAssignment(Token::Value op, |
+ PreParserExpression left, |
+ PreParserExpression right, |
+ int pos) { |
+ return PreParserExpression::Default(); |
+ } |
}; |
@@ -729,6 +746,11 @@ class PreParserTraits { |
return identifier.IsEvalOrArguments(); |
} |
+ // Returns true if the expression is of type "this.foo". |
+ static bool IsThisProperty(PreParserExpression expression) { |
+ return expression.IsThisProperty(); |
+ } |
+ |
static bool IsBoilerplateProperty(PreParserExpression property) { |
// PreParser doesn't count boilerplate properties. |
return false; |
@@ -738,6 +760,8 @@ class PreParserTraits { |
return false; |
} |
+ // Functions for encapsulating the differences between parsing and preparsing; |
+ // operations interleaved with the recursive descent. |
static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) { |
// PreParser should not use FuncNameInferrer. |
ASSERT(false); |
@@ -746,6 +770,29 @@ class PreParserTraits { |
static void CheckFunctionLiteralInsideTopLevelObjectLiteral( |
PreParserScope* scope, PreParserExpression value, bool* has_function) {} |
+ static void CheckAssigningFunctionLiteralToProperty( |
+ PreParserExpression left, PreParserExpression right) {} |
+ |
+ |
+ static PreParserExpression ValidateAssignmentLeftHandSide( |
+ PreParserExpression expression) { |
+ // Parser generates a runtime error here if the left hand side is not valid. |
+ // PreParser doesn't have to. |
+ return expression; |
+ } |
+ |
+ static PreParserExpression MarkExpressionAsLValue( |
+ PreParserExpression expression) { |
+ // TODO(marja): To be able to produce the same errors, the preparser needs |
+ // to start tracking which expressions are variables and which are lvalues. |
+ return expression; |
+ } |
+ |
+ // Checks LHS expression for assignment and prefix/postfix increment/decrement |
+ // in strict mode. |
+ void CheckStrictModeLValue(PreParserExpression expression, bool* ok); |
+ |
+ |
// Reporting errors. |
void ReportMessageAt(Scanner::Location location, |
const char* message, |
@@ -815,7 +862,6 @@ class PreParserTraits { |
} |
// Temporary glue; these functions will move to ParserBase. |
- PreParserExpression ParseAssignmentExpression(bool accept_IN, bool* ok); |
PreParserExpression ParseV8Intrinsic(bool* ok); |
PreParserExpression ParseFunctionLiteral( |
PreParserIdentifier name, |
@@ -825,6 +871,8 @@ class PreParserTraits { |
int function_token_position, |
FunctionLiteral::FunctionType type, |
bool* ok); |
+ PreParserExpression ParseYieldExpression(bool* ok); |
+ PreParserExpression ParseConditionalExpression(bool accept_IN, bool* ok); |
private: |
PreParser* pre_parser_; |
@@ -989,8 +1037,6 @@ class PreParser : public ParserBase<PreParserTraits> { |
Statement ParseThrowStatement(bool* ok); |
Statement ParseTryStatement(bool* ok); |
Statement ParseDebuggerStatement(bool* ok); |
- |
- Expression ParseAssignmentExpression(bool accept_IN, bool* ok); |
Expression ParseYieldExpression(bool* ok); |
Expression ParseConditionalExpression(bool accept_IN, bool* ok); |
Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok); |
@@ -1537,6 +1583,75 @@ typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments( |
return result; |
} |
+// Precedence = 2 |
+template <class Traits> |
+typename Traits::Type::Expression ParserBase<Traits>::ParseAssignmentExpression( |
+ bool accept_IN, bool* ok) { |
+ // AssignmentExpression :: |
+ // ConditionalExpression |
+ // YieldExpression |
+ // LeftHandSideExpression AssignmentOperator AssignmentExpression |
+ |
+ if (peek() == Token::YIELD && is_generator()) { |
+ return this->ParseYieldExpression(ok); |
+ } |
+ |
+ if (fni_ != NULL) fni_->Enter(); |
+ typename Traits::Type::Expression expression = |
+ this->ParseConditionalExpression(accept_IN, CHECK_OK); |
+ |
+ if (!Token::IsAssignmentOp(peek())) { |
+ if (fni_ != NULL) fni_->Leave(); |
+ // Parsed conditional expression only (no assignment). |
+ return expression; |
+ } |
+ |
+ // Signal a reference error if the expression is an invalid left-hand |
+ // side expression. We could report this as a syntax error here but |
+ // for compatibility with JSC we choose to report the error at |
+ // runtime. |
+ // TODO(ES5): Should change parsing for spec conformance. |
+ expression = this->ValidateAssignmentLeftHandSide(expression); |
+ |
+ if (strict_mode() == STRICT) { |
+ // Assignment to eval or arguments is disallowed in strict mode. |
+ this->CheckStrictModeLValue(expression, CHECK_OK); |
+ } |
+ expression = this->MarkExpressionAsLValue(expression); |
+ |
+ Token::Value op = Next(); // Get assignment operator. |
+ int pos = position(); |
+ typename Traits::Type::Expression right = |
+ this->ParseAssignmentExpression(accept_IN, CHECK_OK); |
+ |
+ // TODO(1231235): We try to estimate the set of properties set by |
+ // constructors. We define a new property whenever there is an |
+ // assignment to a property of 'this'. We should probably only add |
+ // properties if we haven't seen them before. Otherwise we'll |
+ // probably overestimate the number of properties. |
+ if (op == Token::ASSIGN && this->IsThisProperty(expression)) { |
+ function_state_->AddProperty(); |
+ } |
+ |
+ this->CheckAssigningFunctionLiteralToProperty(expression, right); |
+ |
+ if (fni_ != NULL) { |
+ // Check if the right hand side is a call to avoid inferring a |
+ // name if we're dealing with "a = function(){...}();"-like |
+ // expression. |
+ if ((op == Token::INIT_VAR |
+ || op == Token::INIT_CONST_LEGACY |
+ || op == Token::ASSIGN) |
+ && (right->AsCall() == NULL && right->AsCallNew() == NULL)) { |
+ fni_->Infer(); |
+ } else { |
+ fni_->RemoveLastFunction(); |
+ } |
+ fni_->Leave(); |
+ } |
+ |
+ return factory()->NewAssignment(op, expression, right, pos); |
+} |
#undef CHECK_OK |
#undef CHECK_OK_CUSTOM |