Revision: 19976
Author:   [email protected]
Date:     Mon Mar 17 10:21:01 2014 UTC
Log:      Make invalid LHSs a parse-time (reference) error

This is required by the spec. It also prevents crashes resulting from the attempt to read type feedback for the RHS of an invalid assignment which full codegen never actually allocated info for.

To do: check properly in preparser already.

[email protected], [email protected]
BUG=351658
LOG=Y

Review URL: https://codereview.chromium.org/200473003
http://code.google.com/p/v8/source/detail?r=19976

Added:
 /branches/bleeding_edge/test/mjsunit/regress/regress-crbug-351658.js
Modified:
 /branches/bleeding_edge/src/a64/full-codegen-a64.cc
 /branches/bleeding_edge/src/arm/full-codegen-arm.cc
 /branches/bleeding_edge/src/factory.cc
 /branches/bleeding_edge/src/factory.h
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
 /branches/bleeding_edge/src/messages.js
 /branches/bleeding_edge/src/parser.cc
 /branches/bleeding_edge/src/parser.h
 /branches/bleeding_edge/src/preparser.cc
 /branches/bleeding_edge/src/preparser.h
 /branches/bleeding_edge/src/x64/full-codegen-x64.cc
 /branches/bleeding_edge/test/cctest/test-parsing.cc
 /branches/bleeding_edge/test/mjsunit/invalid-lhs.js

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-crbug-351658.js Mon Mar 17 10:21:01 2014 UTC
@@ -0,0 +1,14 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+try {
+  var f = eval("(function(){0 = y + y})");
+  %OptimizeFunctionOnNextCall(f);
+  f();
+  assertUnreachable();
+} catch(e) {
+  assertTrue(e instanceof ReferenceError);
+}
=======================================
--- /branches/bleeding_edge/src/a64/full-codegen-a64.cc Mon Mar 17 08:31:21 2014 UTC +++ /branches/bleeding_edge/src/a64/full-codegen-a64.cc Mon Mar 17 10:21:01 2014 UTC
@@ -1854,13 +1854,9 @@


 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
+  ASSERT(expr->target()->IsValidLeftHandSide());
+
   Comment cmnt(masm_, "[ Assignment");
-  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
-  // on the left-hand side.
-  if (!expr->target()->IsValidLeftHandSide()) {
-    VisitForEffect(expr->target());
-    return;
-  }

// Left-hand side can only be a property, a global or a (parameter or local)
   // slot.
@@ -2099,12 +2095,7 @@


 void FullCodeGenerator::EmitAssignment(Expression* expr) {
-  // Invalid left-hand sides are rewritten to have a 'throw
-  // ReferenceError' on the left-hand side.
-  if (!expr->IsValidLeftHandSide()) {
-    VisitForEffect(expr);
-    return;
-  }
+  ASSERT(expr->IsValidLeftHandSide());

// Left-hand side can only be a property, a global or a (parameter or local)
   // slot.
@@ -3990,15 +3981,10 @@


 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
+  ASSERT(expr->expression()->IsValidLeftHandSide());
+
   Comment cmnt(masm_, "[ CountOperation");
   SetSourcePosition(expr->position());
-
-  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
-  // as the left-hand side.
-  if (!expr->expression()->IsValidLeftHandSide()) {
-    VisitForEffect(expr->expression());
-    return;
-  }

   // Expression can only be a property, a global or a (parameter or local)
   // slot.
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Mon Mar 17 08:31:21 2014 UTC +++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Mon Mar 17 10:21:01 2014 UTC
@@ -1865,13 +1865,9 @@


 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
+  ASSERT(expr->target()->IsValidLeftHandSide());
+
   Comment cmnt(masm_, "[ Assignment");
-  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
-  // on the left-hand side.
-  if (!expr->target()->IsValidLeftHandSide()) {
-    VisitForEffect(expr->target());
-    return;
-  }

// Left-hand side can only be a property, a global or a (parameter or local)
   // slot.
@@ -2402,12 +2398,7 @@


 void FullCodeGenerator::EmitAssignment(Expression* expr) {
-  // Invalid left-hand sides are rewritten by the parser to have a 'throw
-  // ReferenceError' on the left-hand side.
-  if (!expr->IsValidLeftHandSide()) {
-    VisitForEffect(expr);
-    return;
-  }
+  ASSERT(expr->IsValidLeftHandSide());

// Left-hand side can only be a property, a global or a (parameter or local)
   // slot.
@@ -4282,15 +4273,10 @@


 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
+  ASSERT(expr->expression()->IsValidLeftHandSide());
+
   Comment cmnt(masm_, "[ CountOperation");
   SetSourcePosition(expr->position());
-
-  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
-  // as the left-hand side.
-  if (!expr->expression()->IsValidLeftHandSide()) {
-    VisitForEffect(expr->expression());
-    return;
-  }

   // Expression can only be a property, a global or a (parameter or local)
   // slot.
=======================================
--- /branches/bleeding_edge/src/factory.cc      Mon Mar 17 08:31:21 2014 UTC
+++ /branches/bleeding_edge/src/factory.cc      Mon Mar 17 10:21:01 2014 UTC
@@ -1065,6 +1065,12 @@
                                           Vector< Handle<Object> > args) {
   return NewError("MakeReferenceError", message, args);
 }
+
+
+Handle<Object> Factory::NewReferenceError(const char* message,
+                                          Handle<JSArray> args) {
+  return NewError("MakeReferenceError", message, args);
+}


 Handle<Object> Factory::NewReferenceError(Handle<String> message) {
=======================================
--- /branches/bleeding_edge/src/factory.h       Mon Mar 17 08:31:21 2014 UTC
+++ /branches/bleeding_edge/src/factory.h       Mon Mar 17 10:21:01 2014 UTC
@@ -436,6 +436,7 @@

   Handle<Object> NewReferenceError(const char* message,
                                    Vector< Handle<Object> > args);
+ Handle<Object> NewReferenceError(const char* message, Handle<JSArray> args);
   Handle<Object> NewReferenceError(Handle<String> message);

   Handle<Object> NewEvalError(const char* message,
=======================================
--- /branches/bleeding_edge/src/heap.h  Tue Mar 11 14:41:22 2014 UTC
+++ /branches/bleeding_edge/src/heap.h  Mon Mar 17 10:21:01 2014 UTC
@@ -333,10 +333,6 @@
   V(MakeReferenceError_string, "MakeReferenceError")                     \
   V(MakeSyntaxError_string, "MakeSyntaxError")                           \
   V(MakeTypeError_string, "MakeTypeError")                               \
-  V(invalid_lhs_in_assignment_string, "invalid_lhs_in_assignment")       \
-  V(invalid_lhs_in_for_in_string, "invalid_lhs_in_for_in")               \
-  V(invalid_lhs_in_postfix_op_string, "invalid_lhs_in_postfix_op")       \
-  V(invalid_lhs_in_prefix_op_string, "invalid_lhs_in_prefix_op")         \
   V(illegal_return_string, "illegal_return")                             \
   V(illegal_break_string, "illegal_break")                               \
   V(illegal_continue_string, "illegal_continue")                         \
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon Mar 17 08:31:21 2014 UTC +++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon Mar 17 10:21:01 2014 UTC
@@ -1818,13 +1818,9 @@


 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
+  ASSERT(expr->target()->IsValidLeftHandSide());
+
   Comment cmnt(masm_, "[ Assignment");
-  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
-  // on the left-hand side.
-  if (!expr->target()->IsValidLeftHandSide()) {
-    VisitForEffect(expr->target());
-    return;
-  }

// Left-hand side can only be a property, a global or a (parameter or local)
   // slot.
@@ -2353,12 +2349,7 @@


 void FullCodeGenerator::EmitAssignment(Expression* expr) {
-  // Invalid left-hand sides are rewritten by the parser to have a 'throw
-  // ReferenceError' on the left-hand side.
-  if (!expr->IsValidLeftHandSide()) {
-    VisitForEffect(expr);
-    return;
-  }
+  ASSERT(expr->IsValidLeftHandSide());

// Left-hand side can only be a property, a global or a (parameter or local)
   // slot.
@@ -4284,15 +4275,10 @@


 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
+  ASSERT(expr->expression()->IsValidLeftHandSide());
+
   Comment cmnt(masm_, "[ CountOperation");
   SetSourcePosition(expr->position());
-
-  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
-  // as the left-hand side.
-  if (!expr->expression()->IsValidLeftHandSide()) {
-    VisitForEffect(expr->expression());
-    return;
-  }

   // Expression can only be a property, a global or a (parameter or local)
   // slot.
=======================================
--- /branches/bleeding_edge/src/messages.js     Sat Mar 15 20:37:13 2014 UTC
+++ /branches/bleeding_edge/src/messages.js     Mon Mar 17 10:21:01 2014 UTC
@@ -45,10 +45,6 @@
   unterminated_regexp:           ["Invalid regular expression: missing /"],
regexp_flags: ["Cannot supply flags when constructing one RegExp from another"], incompatible_method_receiver: ["Method ", "%0", " called on incompatible receiver ", "%1"],
-  invalid_lhs_in_assignment:     ["Invalid left-hand side in assignment"],
-  invalid_lhs_in_for_in:         ["Invalid left-hand side in for-in"],
- invalid_lhs_in_postfix_op: ["Invalid left-hand side expression in postfix operation"], - invalid_lhs_in_prefix_op: ["Invalid left-hand side expression in prefix operation"], multiple_defaults_in_switch: ["More than one default clause in switch statement"],
   newline_after_throw:           ["Illegal newline after throw"],
redeclaration: ["%0", " '", "%1", "' has already been declared"],
@@ -132,6 +128,11 @@
   stack_overflow:                ["Maximum call stack size exceeded"],
   invalid_time_value:            ["Invalid time value"],
   invalid_count_value:           ["Invalid count value"],
+  // ReferenceError
+  invalid_lhs_in_assignment:     ["Invalid left-hand side in assignment"],
+  invalid_lhs_in_for:            ["Invalid left-hand side in for-loop"],
+ invalid_lhs_in_postfix_op: ["Invalid left-hand side expression in postfix operation"], + invalid_lhs_in_prefix_op: ["Invalid left-hand side expression in prefix operation"],
   // SyntaxError
paren_in_arg_string: ["Function arg string contains parenthesis"],
   not_isvar:                     ["builtin %IS_VAR: not a variable"],
=======================================
--- /branches/bleeding_edge/src/parser.cc       Fri Mar 14 09:51:22 2014 UTC
+++ /branches/bleeding_edge/src/parser.cc       Mon Mar 17 10:21:01 2014 UTC
@@ -454,18 +454,6 @@
     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) {
@@ -492,7 +480,8 @@

 void ParserTraits::ReportMessageAt(Scanner::Location source_location,
                                    const char* message,
-                                   Vector<const char*> args) {
+                                   Vector<const char*> args,
+                                   bool is_reference_error) {
   if (parser_->stack_overflow()) {
// Suppress the error message (syntax error or such) in the presence of a // stack overflow. The isolate allows only one pending exception at at time
@@ -509,21 +498,25 @@
     elements->set(i, *arg_string);
   }
   Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
-  Handle<Object> result = factory->NewSyntaxError(message, array);
+  Handle<Object> result = is_reference_error
+      ? factory->NewReferenceError(message, array)
+      : factory->NewSyntaxError(message, array);
   parser_->isolate()->Throw(*result, &location);
 }


 void ParserTraits::ReportMessage(const char* message,
-                                 Vector<Handle<String> > args) {
+                                 Vector<Handle<String> > args,
+                                 bool is_reference_error) {
   Scanner::Location source_location = parser_->scanner()->location();
-  ReportMessageAt(source_location, message, args);
+  ReportMessageAt(source_location, message, args, is_reference_error);
 }


 void ParserTraits::ReportMessageAt(Scanner::Location source_location,
                                    const char* message,
-                                   Vector<Handle<String> > args) {
+                                   Vector<Handle<String> > args,
+                                   bool is_reference_error) {
   if (parser_->stack_overflow()) {
// Suppress the error message (syntax error or such) in the presence of a // stack overflow. The isolate allows only one pending exception at at time
@@ -539,7 +532,9 @@
     elements->set(i, *args[i]);
   }
   Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
-  Handle<Object> result = factory->NewSyntaxError(message, array);
+  Handle<Object> result = is_reference_error
+      ? factory->NewReferenceError(message, array)
+      : factory->NewSyntaxError(message, array);
   parser_->isolate()->Throw(*result, &location);
 }

@@ -2844,19 +2839,16 @@
         init = variable_statement;
       }
     } else {
+      Scanner::Location lhs_location = scanner()->peek_location();
       Expression* expression = ParseExpression(false, CHECK_OK);
       ForEachStatement::VisitMode mode;
       bool accept_OF = expression->AsVariableProxy();

       if (CheckInOrOf(accept_OF, &mode)) {
-        // 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.
         if (expression == NULL || !expression->IsValidLeftHandSide()) {
-          Handle<String> message =
-              isolate()->factory()->invalid_lhs_in_for_in_string();
-          expression = NewThrowReferenceError(message);
+          ReportMessageAt(lhs_location, "invalid_lhs_in_for", true);
+          *ok = false;
+          return NULL;
         }
         ForEachStatement* loop =
             factory()->NewForEachStatement(mode, labels, pos);
@@ -3125,15 +3117,12 @@

   } else if (Token::IsCountOp(op)) {
     op = Next();
+    Scanner::Location lhs_location = scanner()->peek_location();
     Expression* expression = ParseUnaryExpression(CHECK_OK);
-    // 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.
     if (expression == NULL || !expression->IsValidLeftHandSide()) {
-      Handle<String> message =
-          isolate()->factory()->invalid_lhs_in_prefix_op_string();
-      expression = NewThrowReferenceError(message);
+      ReportMessageAt(lhs_location, "invalid_lhs_in_prefix_op", true);
+      *ok = false;
+      return NULL;
     }

     if (strict_mode() == STRICT) {
@@ -3157,17 +3146,14 @@
   // PostfixExpression ::
   //   LeftHandSideExpression ('++' | '--')?

+  Scanner::Location lhs_location = scanner()->peek_location();
   Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
   if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
       Token::IsCountOp(peek())) {
-    // 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.
     if (expression == NULL || !expression->IsValidLeftHandSide()) {
-      Handle<String> message =
-          isolate()->factory()->invalid_lhs_in_postfix_op_string();
-      expression = NewThrowReferenceError(message);
+      ReportMessageAt(lhs_location, "invalid_lhs_in_postfix_op", true);
+      *ok = false;
+      return NULL;
     }

     if (strict_mode() == STRICT) {
=======================================
--- /branches/bleeding_edge/src/parser.h        Fri Mar 14 09:51:22 2014 UTC
+++ /branches/bleeding_edge/src/parser.h        Mon Mar 17 10:21:01 2014 UTC
@@ -484,10 +484,10 @@
   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 whether the expression is a valid assignment left-hand side.
+  static bool IsValidLeftHandSide(Expression* expression) {
+    return expression->IsValidLeftHandSide();
+  }

// 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
@@ -501,11 +501,15 @@
   // Reporting errors.
   void ReportMessageAt(Scanner::Location source_location,
                        const char* message,
-                       Vector<const char*> args);
-  void ReportMessage(const char* message, Vector<Handle<String> > args);
+                       Vector<const char*> args,
+                       bool is_reference_error = false);
+  void ReportMessage(const char* message,
+                     Vector<Handle<String> > args,
+                     bool is_reference_error = false);
   void ReportMessageAt(Scanner::Location source_location,
                        const char* message,
-                       Vector<Handle<String> > args);
+                       Vector<Handle<String> > args,
+                       bool is_reference_error = false);

   // "null" return type creators.
   static Handle<String> EmptyIdentifier() {
=======================================
--- /branches/bleeding_edge/src/preparser.cc    Fri Mar 14 09:51:22 2014 UTC
+++ /branches/bleeding_edge/src/preparser.cc    Mon Mar 17 10:21:01 2014 UTC
@@ -69,17 +69,20 @@

 void PreParserTraits::ReportMessageAt(Scanner::Location location,
                                       const char* message,
-                                      Vector<const char*> args) {
+                                      Vector<const char*> args,
+                                      bool is_reference_error) {
   ReportMessageAt(location.beg_pos,
                   location.end_pos,
                   message,
-                  args.length() > 0 ? args[0] : NULL);
+                  args.length() > 0 ? args[0] : NULL,
+                  is_reference_error);
 }


 void PreParserTraits::ReportMessageAt(Scanner::Location location,
                                       const char* type,
-                                      const char* name_opt) {
+                                      const char* name_opt,
+                                      bool is_reference_error) {
   pre_parser_->log_
       ->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
 }
@@ -88,7 +91,8 @@
 void PreParserTraits::ReportMessageAt(int start_pos,
                                       int end_pos,
                                       const char* type,
-                                      const char* name_opt) {
+                                      const char* name_opt,
+                                      bool is_reference_error) {
   pre_parser_->log_->LogMessage(start_pos, end_pos, type, name_opt);
 }

=======================================
--- /branches/bleeding_edge/src/preparser.h     Fri Mar 14 09:51:22 2014 UTC
+++ /branches/bleeding_edge/src/preparser.h     Mon Mar 17 10:21:01 2014 UTC
@@ -342,13 +342,16 @@
   bool is_generator() const { return function_state_->is_generator(); }

   // Report syntax errors.
-  void ReportMessage(const char* message, Vector<const char*> args) {
+  void ReportMessage(const char* message, Vector<const char*> args,
+                     bool is_reference_error = false) {
     Scanner::Location source_location = scanner()->location();
-    Traits::ReportMessageAt(source_location, message, args);
+ Traits::ReportMessageAt(source_location, message, args, is_reference_error);
   }

-  void ReportMessageAt(Scanner::Location location, const char* message) {
- Traits::ReportMessageAt(location, message, Vector<const char*>::empty());
+  void ReportMessageAt(Scanner::Location location, const char* message,
+                       bool is_reference_error = false) {
+ Traits::ReportMessageAt(location, message, Vector<const char*>::empty(),
+                            is_reference_error);
   }

   void ReportUnexpectedToken(Token::Value token);
@@ -789,12 +792,10 @@
   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;
+  // Determine whether the expression is a valid assignment left-hand side.
+  static bool IsValidLeftHandSide(PreParserExpression expression) {
+    // TODO(marja): check properly; for now, leave it to parser.
+    return true;
   }

   static PreParserExpression MarkExpressionAsLValue(
@@ -812,14 +813,17 @@
   // Reporting errors.
   void ReportMessageAt(Scanner::Location location,
                        const char* message,
-                       Vector<const char*> args);
+                       Vector<const char*> args,
+                       bool is_reference_error = false);
   void ReportMessageAt(Scanner::Location location,
                        const char* type,
-                       const char* name_opt);
+                       const char* name_opt,
+                       bool is_reference_error = false);
   void ReportMessageAt(int start_pos,
                        int end_pos,
                        const char* type,
-                       const char* name_opt);
+                       const char* name_opt,
+                       bool is_reference_error = false);

   // "null" return type creators.
   static PreParserIdentifier EmptyIdentifier() {
@@ -1606,6 +1610,8 @@
   //   YieldExpression
   //   LeftHandSideExpression AssignmentOperator AssignmentExpression

+  Scanner::Location lhs_location = scanner()->peek_location();
+
   if (peek() == Token::YIELD && is_generator()) {
     return this->ParseYieldExpression(ok);
   }
@@ -1620,12 +1626,11 @@
     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 (!IsValidLeftHandSide(expression)) {
+    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.
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Mon Mar 17 08:31:21 2014 UTC +++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Mon Mar 17 10:21:01 2014 UTC
@@ -1843,13 +1843,9 @@


 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
+  ASSERT(expr->target()->IsValidLeftHandSide());
+
   Comment cmnt(masm_, "[ Assignment");
-  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
-  // on the left-hand side.
-  if (!expr->target()->IsValidLeftHandSide()) {
-    VisitForEffect(expr->target());
-    return;
-  }

// Left-hand side can only be a property, a global or a (parameter or local)
   // slot.
@@ -2346,12 +2342,7 @@


 void FullCodeGenerator::EmitAssignment(Expression* expr) {
-  // Invalid left-hand sides are rewritten by the parser to have a 'throw
-  // ReferenceError' on the left-hand side.
-  if (!expr->IsValidLeftHandSide()) {
-    VisitForEffect(expr);
-    return;
-  }
+  ASSERT(expr->IsValidLeftHandSide());

// Left-hand side can only be a property, a global or a (parameter or local)
   // slot.
@@ -4283,15 +4274,10 @@


 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
+  ASSERT(expr->expression()->IsValidLeftHandSide());
+
   Comment cmnt(masm_, "[ CountOperation");
   SetSourcePosition(expr->position());
-
-  // Invalid left-hand-sides are rewritten to have a 'throw
-  // ReferenceError' as the left-hand side.
-  if (!expr->expression()->IsValidLeftHandSide()) {
-    VisitForEffect(expr->expression());
-    return;
-  }

   // Expression can only be a property, a global or a (parameter or local)
   // slot.
=======================================
--- /branches/bleeding_edge/test/cctest/test-parsing.cc Fri Mar 14 10:20:33 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-parsing.cc Mon Mar 17 10:21:01 2014 UTC
@@ -2218,7 +2218,6 @@
     "new foo[bar].baz(baz)()[bar].baz;",
     "new \"foo\"",  // Runtime error
     "new 1",  // Runtime error
-    "new foo++",
     // This even runs:
     "(new new Function(\"this.x = 1\")).x;",
     "new new Test_Two(String, 2).v(0123).length;",
@@ -2240,6 +2239,8 @@
     "new foo bar",
     "new ) foo",
     "new ++foo",
+    // TODO(marja): Activate this test once the preparser checks correctly.
+    // "new foo ++",
     NULL
   };

=======================================
--- /branches/bleeding_edge/test/mjsunit/invalid-lhs.js Tue Dec 7 11:01:02 2010 UTC +++ /branches/bleeding_edge/test/mjsunit/invalid-lhs.js Mon Mar 17 10:21:01 2014 UTC
@@ -29,37 +29,37 @@
 // exceptions are delayed until runtime.

 // Normal assignments:
-assertThrows("12 = 12");
-assertThrows("x++ = 12");
-assertThrows("eval('var x') = 12");
-assertDoesNotThrow("if (false) eval('var x') = 12");
+assertThrows("12 = 12", ReferenceError);
+assertThrows("x++ = 12", ReferenceError);
+assertThrows("eval('var x') = 12", ReferenceError);
+assertThrows("if (false) eval('var x') = 12", ReferenceError);

 // Pre- and post-fix operations:
-assertThrows("12++");
-assertThrows("12--");
-assertThrows("--12");
-assertThrows("++12");
-assertThrows("++(eval('12'))");
-assertThrows("(eval('12'))++");
-assertDoesNotThrow("if (false) ++(eval('12'))");
-assertDoesNotThrow("if (false) (eval('12'))++");
+assertThrows("12++", ReferenceError);
+assertThrows("12--", ReferenceError);
+assertThrows("--12", ReferenceError);
+assertThrows("++12", ReferenceError);
+assertThrows("++(eval('12'))", ReferenceError);
+assertThrows("(eval('12'))++", ReferenceError);
+assertThrows("if (false) ++(eval('12'))", ReferenceError);
+assertThrows("if (false) (eval('12'))++", ReferenceError);

 // For in:
-assertThrows("for (12 in [1]) print(12);");
-assertThrows("for (eval('var x') in [1]) print(12);");
-assertDoesNotThrow("if (false) for (eval('var x') in [1]) print(12);");
+assertThrows("for (12 in [1]) print(12);", ReferenceError);
+assertThrows("for (eval('var x') in [1]) print(12);", ReferenceError);
+assertThrows("if (false) for (eval('0') in [1]) print(12);", ReferenceError);

 // For:
-assertThrows("for (12 = 1;;) print(12);");
-assertThrows("for (eval('var x') = 1;;) print(12);");
-assertDoesNotThrow("if (false) for (eval('var x') = 1;;) print(12);");
+assertThrows("for (12 = 1;;) print(12);", ReferenceError);
+assertThrows("for (eval('var x') = 1;;) print(12);", ReferenceError);
+assertThrows("if (false) for (eval('var x') = 1;;) print(12);", ReferenceError);

 // Assignments to 'this'.
-assertThrows("this = 42");
-assertDoesNotThrow("function f() { this = 12; }");
-assertThrows("for (this in {x:3, y:4, z:5}) ;");
-assertThrows("for (this = 0;;) ;");
-assertThrows("this++");
-assertThrows("++this");
-assertThrows("this--");
-assertThrows("--this");
+assertThrows("this = 42", ReferenceError);
+assertThrows("function f() { this = 12; }", ReferenceError);
+assertThrows("for (this in {x:3, y:4, z:5}) ;", ReferenceError);
+assertThrows("for (this = 0;;) ;", ReferenceError);
+assertThrows("this++", ReferenceError);
+assertThrows("++this", ReferenceError);
+assertThrows("this--", ReferenceError);
+assertThrows("--this", ReferenceError);

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to