Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index e746ed4f5d582d4c50c4651941f21b469a8cd88c..bdd9348ec41807662484b107c1bde98d9e8e56f1 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -437,59 +437,6 @@ bool ParserTraits::IsEvalOrArguments(Handle<String> identifier) const { |
} |
-bool ParserTraits::IsThisProperty(Expression* expression) { |
- ASSERT(expression != NULL); |
- Property* property = expression->AsProperty(); |
- return property != NULL && |
- property->obj()->AsVariableProxy() != NULL && |
- property->obj()->AsVariableProxy()->is_this(); |
-} |
- |
- |
-void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left, |
- Expression* right) { |
- ASSERT(left != NULL); |
- if (left->AsProperty() != NULL && |
- right->AsFunctionLiteral() != NULL) { |
- right->AsFunctionLiteral()->set_pretenure(); |
- } |
-} |
- |
- |
-Expression* ParserTraits::ValidateAssignmentLeftHandSide( |
- Expression* expression) const { |
- ASSERT(expression != NULL); |
- if (!expression->IsValidLeftHandSide()) { |
- Handle<String> message = |
- parser_->isolate()->factory()->invalid_lhs_in_assignment_string(); |
- expression = parser_->NewThrowReferenceError(message); |
- } |
- return expression; |
-} |
- |
- |
-Expression* ParserTraits::MarkExpressionAsLValue(Expression* expression) { |
- VariableProxy* proxy = expression != NULL |
- ? expression->AsVariableProxy() |
- : NULL; |
- if (proxy != NULL) proxy->MarkAsLValue(); |
- return expression; |
-} |
- |
- |
-void ParserTraits::CheckStrictModeLValue(Expression* expression, |
- bool* ok) { |
- VariableProxy* lhs = expression != NULL |
- ? expression->AsVariableProxy() |
- : NULL; |
- if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) { |
- parser_->ReportMessage("strict_eval_arguments", |
- Vector<const char*>::empty()); |
- *ok = false; |
- } |
-} |
- |
- |
void ParserTraits::ReportMessageAt(Scanner::Location source_location, |
const char* message, |
Vector<const char*> args) { |
@@ -619,6 +566,11 @@ Literal* ParserTraits::GetLiteralTheHole( |
} |
+Expression* ParserTraits::ParseAssignmentExpression(bool accept_IN, bool* ok) { |
+ return parser_->ParseAssignmentExpression(accept_IN, ok); |
+} |
+ |
+ |
Expression* ParserTraits::ParseV8Intrinsic(bool* ok) { |
return parser_->ParseV8Intrinsic(ok); |
} |
@@ -638,16 +590,6 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral( |
} |
-Expression* ParserTraits::ParseYieldExpression(bool* ok) { |
- return parser_->ParseYieldExpression(ok); |
-} |
- |
- |
-Expression* ParserTraits::ParseConditionalExpression(bool accept_IN, bool* ok) { |
- return parser_->ParseConditionalExpression(accept_IN, ok); |
-} |
- |
- |
Parser::Parser(CompilationInfo* info) |
: ParserBase<ParserTraits>(&scanner_, |
info->isolate()->stack_guard()->real_climit(), |
@@ -2935,6 +2877,85 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { |
} |
+// Precedence = 2 |
+Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) { |
+ // AssignmentExpression :: |
+ // ConditionalExpression |
+ // YieldExpression |
+ // LeftHandSideExpression AssignmentOperator AssignmentExpression |
+ |
+ if (peek() == Token::YIELD && is_generator()) { |
+ return ParseYieldExpression(ok); |
+ } |
+ |
+ if (fni_ != NULL) fni_->Enter(); |
+ Expression* expression = 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. |
+ if (expression == NULL || !expression->IsValidLeftHandSide()) { |
+ Handle<String> message = |
+ isolate()->factory()->invalid_lhs_in_assignment_string(); |
+ expression = NewThrowReferenceError(message); |
+ } |
+ |
+ if (strict_mode() == STRICT) { |
+ // Assignment to eval or arguments is disallowed in strict mode. |
+ CheckStrictModeLValue(expression, CHECK_OK); |
+ } |
+ MarkAsLValue(expression); |
+ |
+ Token::Value op = Next(); // Get assignment operator. |
+ int pos = position(); |
+ Expression* right = 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. |
+ Property* property = expression ? expression->AsProperty() : NULL; |
+ if (op == Token::ASSIGN && |
+ property != NULL && |
+ property->obj()->AsVariableProxy() != NULL && |
+ property->obj()->AsVariableProxy()->is_this()) { |
+ function_state_->AddProperty(); |
+ } |
+ |
+ // If we assign a function literal to a property we pretenure the |
+ // literal so it can be added as a constant function property. |
+ if (property != NULL && right->AsFunctionLiteral() != NULL) { |
+ right->AsFunctionLiteral()->set_pretenure(); |
+ } |
+ |
+ 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); |
+} |
+ |
+ |
Expression* Parser::ParseYieldExpression(bool* ok) { |
// YieldExpression :: |
// 'yield' '*'? AssignmentExpression |
@@ -3163,7 +3184,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) { |
// Prefix expression operand in strict mode may not be eval or arguments. |
CheckStrictModeLValue(expression, CHECK_OK); |
} |
- MarkExpressionAsLValue(expression); |
+ MarkAsLValue(expression); |
return factory()->NewCountOperation(op, |
true /* prefix */, |
@@ -3197,7 +3218,7 @@ Expression* Parser::ParsePostfixExpression(bool* ok) { |
// Postfix expression operand in strict mode may not be eval or arguments. |
CheckStrictModeLValue(expression, CHECK_OK); |
} |
- MarkExpressionAsLValue(expression); |
+ MarkAsLValue(expression); |
Token::Value next = Next(); |
expression = |
@@ -3953,6 +3974,31 @@ Literal* Parser::GetLiteralUndefined(int position) { |
} |
+void Parser::MarkAsLValue(Expression* expression) { |
+ VariableProxy* proxy = expression != NULL |
+ ? expression->AsVariableProxy() |
+ : NULL; |
+ |
+ if (proxy != NULL) proxy->MarkAsLValue(); |
+} |
+ |
+ |
+// Checks LHS expression for assignment and prefix/postfix increment/decrement |
+// in strict mode. |
+void Parser::CheckStrictModeLValue(Expression* expression, |
+ bool* ok) { |
+ ASSERT(strict_mode() == STRICT); |
+ VariableProxy* lhs = expression != NULL |
+ ? expression->AsVariableProxy() |
+ : NULL; |
+ |
+ if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) { |
+ ReportMessage("strict_eval_arguments", Vector<const char*>::empty()); |
+ *ok = false; |
+ } |
+} |
+ |
+ |
void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { |
Declaration* decl = scope->CheckConflictingVarDeclarations(); |
if (decl != NULL) { |