Revision: 6474
Author: [email protected]
Date: Tue Jan 25 09:21:45 2011
Log: Strict mode parameter validation.
http://code.google.com/p/v8/source/detail?r=6474

Modified:
 /branches/bleeding_edge/src/parser.cc
 /branches/bleeding_edge/src/scanner-base.h
 /branches/bleeding_edge/src/scopes.h
 /branches/bleeding_edge/test/mjsunit/strict-mode.js

=======================================
--- /branches/bleeding_edge/src/parser.cc       Mon Jan 24 10:13:18 2011
+++ /branches/bleeding_edge/src/parser.cc       Tue Jan 25 09:21:45 2011
@@ -3300,10 +3300,21 @@
     //    '(' (Identifier)*[','] ')'
     Expect(Token::LPAREN, CHECK_OK);
     int start_pos = scanner().location().beg_pos;
+    Scanner::Location name_loc = Scanner::NoLocation();
+    Scanner::Location dupe_loc = Scanner::NoLocation();

     bool done = (peek() == Token::RPAREN);
     while (!done) {
       Handle<String> param_name = ParseIdentifier(CHECK_OK);
+
+      // Store locations for possible future error reports.
+      if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
+        name_loc = scanner().location();
+      }
+      if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
+        dupe_loc = scanner().location();
+      }
+
Variable* parameter = top_scope_->DeclareLocal(param_name, Variable::VAR);
       top_scope_->AddParameter(parameter);
       num_parameters++;
@@ -3381,13 +3392,25 @@
     if (temp_scope_->StrictMode()) {
       if (IsEvalOrArguments(name)) {
         int position = function_token_position != RelocInfo::kNoPosition
-                         ? function_token_position
-                         : (start_pos > 0 ? start_pos - 1 : start_pos);
+            ? function_token_position
+            : (start_pos > 0 ? start_pos - 1 : start_pos);
         ReportMessageAt(Scanner::Location(position, start_pos),
"strict_function_name", Vector<const char*>::empty());
         *ok = false;
         return NULL;
       }
+      if (name_loc.IsValid()) {
+        ReportMessageAt(name_loc, "strict_param_name",
+                        Vector<const char*>::empty());
+        *ok = false;
+        return NULL;
+      }
+      if (dupe_loc.IsValid()) {
+        ReportMessageAt(dupe_loc, "strict_param_dupe",
+                        Vector<const char*>::empty());
+        *ok = false;
+        return NULL;
+      }
       CheckOctalLiteral(start_pos, end_pos, CHECK_OK);
     }

=======================================
--- /branches/bleeding_edge/src/scanner-base.h  Mon Jan 24 10:13:18 2011
+++ /branches/bleeding_edge/src/scanner-base.h  Tue Jan 25 09:21:45 2011
@@ -274,10 +274,19 @@
   struct Location {
     Location(int b, int e) : beg_pos(b), end_pos(e) { }
     Location() : beg_pos(0), end_pos(0) { }
+
+    bool IsValid() const {
+      return beg_pos >= 0 && end_pos >= beg_pos;
+    }
+
     int beg_pos;
     int end_pos;
   };

+  static Location NoLocation() {
+    return Location(-1, -1);
+  }
+
   // Returns the location information for the current token
   // (the token returned by Next()).
   Location location() const { return current_.location; }
=======================================
--- /branches/bleeding_edge/src/scopes.h        Tue Jan 18 15:01:50 2011
+++ /branches/bleeding_edge/src/scopes.h        Tue Jan 25 09:21:45 2011
@@ -287,6 +287,17 @@

   // The number of contexts between this and scope; zero if this == scope.
   int ContextChainLength(Scope* scope);
+
+ // ---------------------------------------------------------------------------
+  // Strict mode support.
+  bool IsDeclared(Handle<String> name) {
+    // During formal parameter list parsing the scope only contains
+    // two variables inserted at initialization: "this" and "arguments".
+ // "this" is an invalid parameter name and "arguments" is invalid parameter + // name in strict mode. Therefore looking up with the map which includes
+    // "this" and "arguments" in addition to all formal parameters is safe.
+    return variables_.Lookup(name) != NULL;
+  }

// ---------------------------------------------------------------------------
   // Debugging.
=======================================
--- /branches/bleeding_edge/test/mjsunit/strict-mode.js Mon Jan 24 10:13:18 2011 +++ /branches/bleeding_edge/test/mjsunit/strict-mode.js Tue Jan 25 09:21:45 2011
@@ -76,19 +76,19 @@
 CheckStrictMode("function arguments() {}", SyntaxError)

 // Function parameter named 'eval'.
-//CheckStrictMode("function foo(a, b, eval, c, d) {}", SyntaxError)
+CheckStrictMode("function foo(a, b, eval, c, d) {}", SyntaxError)

 // Function parameter named 'arguments'.
-//CheckStrictMode("function foo(a, b, arguments, c, d) {}", SyntaxError)
+CheckStrictMode("function foo(a, b, arguments, c, d) {}", SyntaxError)

 // Property accessor parameter named 'eval'.
-//CheckStrictMode("var o = { set foo(eval) {} }", SyntaxError)
+CheckStrictMode("var o = { set foo(eval) {} }", SyntaxError)

 // Property accessor parameter named 'arguments'.
-//CheckStrictMode("var o = { set foo(arguments) {} }", SyntaxError)
+CheckStrictMode("var o = { set foo(arguments) {} }", SyntaxError)

 // Duplicate function parameter name.
-//CheckStrictMode("function foo(a, b, c, d, b) {}", SyntaxError)
+CheckStrictMode("function foo(a, b, c, d, b) {}", SyntaxError)

 // catch(eval)
 CheckStrictMode("try{}catch(eval){};", SyntaxError)
@@ -103,10 +103,10 @@
 CheckStrictMode("var arguments;", SyntaxError)

 // Strict mode applies to the function in which the directive is used..
-//assertThrows('\
-//function foo(eval) {\
-//  "use strict";\
-//}', SyntaxError);
+assertThrows('\
+function foo(eval) {\
+  "use strict";\
+}', SyntaxError);

 // Strict mode doesn't affect the outer stop of strict code.
 function NotStrict(eval) {

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

Reply via email to