Reviewers: Lasse Reichstein,

Message:
Next installment of strict mode.

Description:
Strict mode eval/arguments LHS.


BUG=
TEST=

Please review this at http://codereview.chromium.org/6335013/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/messages.js
  M src/parser.h
  M src/parser.cc
  M test/mjsunit/strict-mode.js


Index: src/messages.js
diff --git a/src/messages.js b/src/messages.js
index 634771524f31b3453ef0678a259e1a4672a11a3a..50493bf9ade71bb91a0270e1910ae54c9b0d54a2 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -236,6 +236,9 @@ function FormatMessage(message) {
strict_duplicate_property: "Duplicate data property in object literal not allowed in strict mode", accessor_data_property: "Object literal may not have data and accessor property with the same name", accessor_get_set: "Object literal may not have multiple get/set accessors with the same name", + strict_lhs_eval_assignment: "Assignment to eval or arguments is not allowed in strict mode", + strict_lhs_postfix: "Operand of postfix expression may not be eval or arguments in strict mode", + strict_lhs_prefix: "Operand of prefix expression may not be eval or arguments in strict mode",
     };
   }
   var format = kMessages[message.type];
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 9f74a8b240906c78e7f0a595ca8d49deef71f48c..76fe6cd1be09e5ad4c26e172977cec5b728020e0 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -2292,6 +2292,11 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
     expression = NewThrowReferenceError(type);
   }

+  if (temp_scope_->StrictMode()) {
+    // Assignment to eval or arguments is disallowed in strict mode.
+    CheckStrictModeLHSName(expression, "strict_lhs_assignment", CHECK_OK);
+  }
+
   Token::Value op = Next();  // Get assignment operator.
   int pos = scanner().location().beg_pos;
   Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
@@ -2518,6 +2523,12 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
       Handle<String> type = Factory::invalid_lhs_in_prefix_op_symbol();
       expression = NewThrowReferenceError(type);
     }
+
+    if (temp_scope_->StrictMode()) {
+ // Prefix expression operand in strict mode may not be eval or arguments.
+      CheckStrictModeLHSName(expression, "strict_lhs_prefix", CHECK_OK);
+    }
+
     int position = scanner().location().beg_pos;
     IncrementOperation* increment = new IncrementOperation(op, expression);
     return new CountOperation(true /* prefix */, increment, position);
@@ -2543,6 +2554,12 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
       Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol();
       expression = NewThrowReferenceError(type);
     }
+
+    if (temp_scope_->StrictMode()) {
+ // Postfix expression operand in strict mode may not be eval or arguments.
+      CheckStrictModeLHSName(expression, "strict_lhs_prefix", CHECK_OK);
+    }
+
     Token::Value next = Next();
     int position = scanner().location().beg_pos;
IncrementOperation* increment = new IncrementOperation(next, expression); @@ -3692,6 +3709,24 @@ Handle<String> Parser::ParseIdentifierName(bool* ok) {
   return GetSymbol(ok);
 }

+
+// Checks LHS expression for assignment and prefix/postfix increment/decrement
+// in strict mode.
+void Parser::CheckStrictModeLHSName(Expression* expression,
+                                    const char* error,
+                                    bool* ok) {
+  ASSERT(temp_scope_->StrictMode());
+  VariableProxy* lhs = expression != NULL
+      ? expression->AsVariableProxy()
+      : NULL;
+
+  if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
+    ReportMessage(error, Vector<const char*>::empty());
+    *ok = false;
+  }
+}
+
+
 // Checks whether octal literal last seen is between beg_pos and end_pos.
 // If so, reports an error.
 void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
Index: src/parser.h
diff --git a/src/parser.h b/src/parser.h
index 916f9ed102ad25bfc3310624a8c22f939371021b..891bc8e3ba6f8e842c2b90b06f5fa1af54b5b457 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -613,6 +613,11 @@ class Parser {
                                            bool* is_set,
                                            bool* ok);

+  // Strict mode validation of LValue expressions
+  void CheckStrictModeLHSName(Expression* expression,
+                              const char* error,
+                              bool* ok);
+
   // Strict mode octal literal validation.
   void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);

Index: test/mjsunit/strict-mode.js
diff --git a/test/mjsunit/strict-mode.js b/test/mjsunit/strict-mode.js
index 14c00e9d434b77af7e21cc7318401c950db3a8c3..842a5ffdbda67bbe72104fb1e248d8069bf45795 100644
--- a/test/mjsunit/strict-mode.js
+++ b/test/mjsunit/strict-mode.js
@@ -145,8 +145,6 @@ function StrictModeNonDuplicate() {
var x = { 123: 1, '123.00000000000000000000000000000000000000000000000000000000000000000001' : 2 }
 }

-//CheckStrictMode("", SyntaxError)
-
 // Two getters (non-strict)
 assertThrows("var x = { get foo() { }, get foo() { } };", SyntaxError)
 assertThrows("var x = { get foo(){}, get 'foo'(){}};", SyntaxError)
@@ -178,3 +176,44 @@ assertThrows("var x = { 'foo': 'data', get foo() { } };", SyntaxError)
 assertThrows("var x = { get 'foo'() { }, 'foo': 'data' };", SyntaxError)
 assertThrows("var x = { '12': 1, get '12'(){}};", SyntaxError);
 assertThrows("var x = { '12': 1, get 12(){}};", SyntaxError);
+
+// Assignment to eval or arguments
+CheckStrictMode("function strict() { eval = undefined; }", SyntaxError)
+CheckStrictMode("function strict() { arguments = undefined; }", SyntaxError) +CheckStrictMode("function strict() { print(eval = undefined); }", SyntaxError) +CheckStrictMode("function strict() { print(arguments = undefined); }", SyntaxError) +CheckStrictMode("function strict() { var x = eval = undefined; }", SyntaxError) +CheckStrictMode("function strict() { var x = arguments = undefined; }", SyntaxError)
+
+// Postfix increment with eval or arguments
+CheckStrictMode("function strict() { eval++; }", SyntaxError)
+CheckStrictMode("function strict() { arguments++; }", SyntaxError)
+CheckStrictMode("function strict() { print(eval++); }", SyntaxError)
+CheckStrictMode("function strict() { print(arguments++); }", SyntaxError)
+CheckStrictMode("function strict() { var x = eval++; }", SyntaxError)
+CheckStrictMode("function strict() { var x = arguments++; }", SyntaxError)
+
+// Postfix decrement with eval or arguments
+CheckStrictMode("function strict() { eval--; }", SyntaxError)
+CheckStrictMode("function strict() { arguments--; }", SyntaxError)
+CheckStrictMode("function strict() { print(eval--); }", SyntaxError)
+CheckStrictMode("function strict() { print(arguments--); }", SyntaxError)
+CheckStrictMode("function strict() { var x = eval--; }", SyntaxError)
+CheckStrictMode("function strict() { var x = arguments--; }", SyntaxError)
+
+// Prefix increment with eval or arguments
+CheckStrictMode("function strict() { ++eval; }", SyntaxError)
+CheckStrictMode("function strict() { ++arguments; }", SyntaxError)
+CheckStrictMode("function strict() { print(++eval); }", SyntaxError)
+CheckStrictMode("function strict() { print(++arguments); }", SyntaxError)
+CheckStrictMode("function strict() { var x = ++eval; }", SyntaxError)
+CheckStrictMode("function strict() { var x = ++arguments; }", SyntaxError)
+
+// Prefix decrement with eval or arguments
+CheckStrictMode("function strict() { --eval; }", SyntaxError)
+CheckStrictMode("function strict() { --arguments; }", SyntaxError)
+CheckStrictMode("function strict() { print(--eval); }", SyntaxError)
+CheckStrictMode("function strict() { print(--arguments); }", SyntaxError)
+CheckStrictMode("function strict() { var x = --eval; }", SyntaxError)
+CheckStrictMode("function strict() { var x = --arguments; }", SyntaxError)
+


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to