From 7c66ec93199aa5d817a96a06b504e88bf71d2406 Mon Sep 17 00:00:00 2001 From: "marja@chromium.org" Date: Thu, 13 Mar 2014 16:11:26 +0000 Subject: [PATCH] Revert "Move ParseAssignmentExpression to ParserBase." This reverts revision 19908. Reason: clang doesn't like it. BUG= Review URL: https://codereview.chromium.org/199233003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19909 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/parser.cc | 176 +++++++++++++++++++++++++++++++++++-------------------- src/parser.h | 37 ++++-------- src/preparser.cc | 91 +++++++++++++++++++--------- src/preparser.h | 121 +------------------------------------- 4 files changed, 189 insertions(+), 236 deletions(-) diff --git a/src/parser.cc b/src/parser.cc index e746ed4..bdd9348 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -437,59 +437,6 @@ bool ParserTraits::IsEvalOrArguments(Handle 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 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::empty()); - *ok = false; - } -} - - void ParserTraits::ReportMessageAt(Scanner::Location source_location, const char* message, Vector 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(&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 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::empty()); + *ok = false; + } +} + + void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { Declaration* decl = scope->CheckConflictingVarDeclarations(); if (decl != NULL) { diff --git a/src/parser.h b/src/parser.h index 966dcaa..073d64b 100644 --- a/src/parser.h +++ b/src/parser.h @@ -452,9 +452,6 @@ class ParserTraits { // Helper functions for recursive descent. bool IsEvalOrArguments(Handle identifier) const; - // Returns true if the expression is of type "this.foo". - static bool IsThisProperty(Expression* expression); - static bool IsBoilerplateProperty(ObjectLiteral::Property* property) { return ObjectLiteral::IsBoilerplateProperty(property); } @@ -463,8 +460,6 @@ class ParserTraits { return !string.is_null() && string->AsArrayIndex(index); } - // Functions for encapsulating the differences between parsing and preparsing; - // operations interleaved with the recursive descent. static void PushLiteralName(FuncNameInferrer* fni, Handle id) { fni->PushLiteralName(id); } @@ -478,25 +473,6 @@ class ParserTraits { } } - // If we assign a function literal to a property we pretenure the - // literal so it can be added as a constant function property. - static void CheckAssigningFunctionLiteralToProperty(Expression* left, - Expression* right); - - // Signal a reference error if the expression is an invalid left-hand side - // expression. We could report this as a syntax error but for compatibility - // with JSC we choose to report the error at runtime. - Expression* ValidateAssignmentLeftHandSide(Expression* expression) const; - - // Determine if the expression is a variable proxy and mark it as being used - // in an assignment or with a increment/decrement operator. This is currently - // used on for the statically checking assignments to harmony const bindings. - static Expression* MarkExpressionAsLValue(Expression* expression); - - // Checks LHS expression for assignment and prefix/postfix increment/decrement - // in strict mode. - void CheckStrictModeLValue(Expression*expression, bool* ok); - // Reporting errors. void ReportMessageAt(Scanner::Location source_location, const char* message, @@ -547,6 +523,7 @@ class ParserTraits { } // Temporary glue; these functions will move to ParserBase. + Expression* ParseAssignmentExpression(bool accept_IN, bool* ok); Expression* ParseV8Intrinsic(bool* ok); FunctionLiteral* ParseFunctionLiteral( Handle name, @@ -556,8 +533,6 @@ class ParserTraits { int function_token_position, FunctionLiteral::FunctionType type, bool* ok); - Expression* ParseYieldExpression(bool* ok); - Expression* ParseConditionalExpression(bool accept_IN, bool* ok); private: Parser* parser_; @@ -700,6 +675,7 @@ class Parser : public ParserBase { // Support for hamony block scoped bindings. Block* ParseScopedBlock(ZoneStringList* labels, 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); @@ -735,6 +711,15 @@ class Parser : public ParserBase { // Get odd-ball literals. Literal* GetLiteralUndefined(int position); + // Determine if the expression is a variable proxy and mark it as being used + // in an assignment or with a increment/decrement operator. This is currently + // used on for the statically checking assignments to harmony const bindings. + void MarkAsLValue(Expression* expression); + + // Strict mode validation of LValue expressions + void CheckStrictModeLValue(Expression* expression, + bool* ok); + // For harmony block scoping mode: Check if the scope has conflicting var/let // declarations from different scopes. It covers for example // diff --git a/src/preparser.cc b/src/preparser.cc index 6145834..652c1ba 100644 --- a/src/preparser.cc +++ b/src/preparser.cc @@ -55,18 +55,6 @@ int isfinite(double value); namespace v8 { namespace internal { - -void PreParserTraits::CheckStrictModeLValue(PreParserExpression expression, - bool* ok) { - if (expression.IsIdentifier() && - expression.AsIdentifier().IsEvalOrArguments()) { - pre_parser_->ReportMessage("strict_eval_arguments", - Vector::empty()); - *ok = false; - } -} - - void PreParserTraits::ReportMessageAt(Scanner::Location location, const char* message, Vector args) { @@ -123,6 +111,12 @@ PreParserExpression PreParserTraits::ExpressionFromString( } +PreParserExpression PreParserTraits::ParseAssignmentExpression(bool accept_IN, + bool* ok) { + return pre_parser_->ParseAssignmentExpression(accept_IN, ok); +} + + PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) { return pre_parser_->ParseV8Intrinsic(ok); } @@ -142,17 +136,6 @@ PreParserExpression PreParserTraits::ParseFunctionLiteral( } -PreParserExpression PreParserTraits::ParseYieldExpression(bool* ok) { - return pre_parser_->ParseYieldExpression(ok); -} - - -PreParserExpression PreParserTraits::ParseConditionalExpression(bool accept_IN, - bool* ok) { - return pre_parser_->ParseConditionalExpression(accept_IN, ok); -} - - PreParser::PreParseResult PreParser::PreParseLazyFunction( StrictMode strict_mode, bool is_generator, ParserRecorder* log) { log_ = log; @@ -844,6 +827,47 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { #undef DUMMY +// Precedence = 2 +PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN, + bool* ok) { + // AssignmentExpression :: + // ConditionalExpression + // YieldExpression + // LeftHandSideExpression AssignmentOperator AssignmentExpression + + if (function_state_->is_generator() && peek() == Token::YIELD) { + return ParseYieldExpression(ok); + } + + Scanner::Location before = scanner()->peek_location(); + Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); + + if (!Token::IsAssignmentOp(peek())) { + // Parsed conditional expression only (no assignment). + return expression; + } + + if (strict_mode() == STRICT && + expression.IsIdentifier() && + expression.AsIdentifier().IsEvalOrArguments()) { + Scanner::Location after = scanner()->location(); + PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos, + "strict_eval_arguments", NULL); + *ok = false; + return Expression::Default(); + } + + Token::Value op = Next(); // Get assignment operator. + ParseAssignmentExpression(accept_IN, CHECK_OK); + + if ((op == Token::ASSIGN) && expression.IsThisProperty()) { + function_state_->AddProperty(); + } + + return Expression::Default(); +} + + // Precedence = 3 PreParser::Expression PreParser::ParseYieldExpression(bool* ok) { // YieldExpression :: @@ -915,9 +939,15 @@ PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) { return Expression::Default(); } else if (Token::IsCountOp(op)) { op = Next(); + Scanner::Location before = scanner()->peek_location(); Expression expression = ParseUnaryExpression(CHECK_OK); - if (strict_mode() == STRICT) { - CheckStrictModeLValue(expression, CHECK_OK); + if (strict_mode() == STRICT && + expression.IsIdentifier() && + expression.AsIdentifier().IsEvalOrArguments()) { + Scanner::Location after = scanner()->location(); + PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos, + "strict_eval_arguments", NULL); + *ok = false; } return Expression::Default(); } else { @@ -930,11 +960,18 @@ PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) { // PostfixExpression :: // LeftHandSideExpression ('++' | '--')? + Scanner::Location before = scanner()->peek_location(); Expression expression = ParseLeftHandSideExpression(CHECK_OK); if (!scanner()->HasAnyLineTerminatorBeforeNext() && Token::IsCountOp(peek())) { - if (strict_mode() == STRICT) { - CheckStrictModeLValue(expression, CHECK_OK); + if (strict_mode() == STRICT && + expression.IsIdentifier() && + expression.AsIdentifier().IsEvalOrArguments()) { + Scanner::Location after = scanner()->location(); + PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos, + "strict_eval_arguments", NULL); + *ok = false; + return Expression::Default(); } Next(); return Expression::Default(); diff --git a/src/preparser.h b/src/preparser.h index e7adbc0..06880d5 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -382,8 +382,6 @@ 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 @@ -566,14 +564,6 @@ 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 @@ -693,13 +683,6 @@ class PreParserFactory { int pos) { return PreParserExpression::Default(); } - - PreParserExpression NewAssignment(Token::Value op, - PreParserExpression left, - PreParserExpression right, - int pos) { - return PreParserExpression::Default(); - } }; @@ -746,11 +729,6 @@ 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; @@ -760,8 +738,6 @@ 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); @@ -770,29 +746,6 @@ 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, @@ -862,6 +815,7 @@ 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, @@ -871,8 +825,6 @@ 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_; @@ -1037,6 +989,8 @@ class PreParser : public ParserBase { 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); @@ -1583,75 +1537,6 @@ typename Traits::Type::ExpressionList ParserBase::ParseArguments( return result; } -// Precedence = 2 -template -typename Traits::Type::Expression ParserBase::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. - 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 -- 2.7.4