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