Add tests for function statements in strict mode.
authorlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 24 May 2011 14:02:59 +0000 (14:02 +0000)
committerlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 24 May 2011 14:02:59 +0000 (14:02 +0000)
Small fixes.
Added test for const declaration in strict mode.

TEST=preparser/strict-function-statement

Review URL: http://codereview.chromium.org/6990056

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8041 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

preparser/preparser-process.cc
src/preparser.cc
src/preparser.h
test/preparser/strict-const.js [new file with mode: 0644]
test/preparser/strict-function-statement.pyt [new file with mode: 0644]
test/preparser/strict-identifiers.pyt

index 0cd7a63..a19c66b 100644 (file)
@@ -242,8 +242,8 @@ void CheckException(v8::PreParserData* data,
     if (expects->type != NULL) {
       const char* actual_message = reader.message();
       if (strcmp(expects->type, actual_message)) {
-        fail(data, "Wrong error message. Expected <%s>, found <%s>\n",
-             expects->type, actual_message);
+        fail(data, "Wrong error message. Expected <%s>, found <%s> at %d..%d\n",
+             expects->type, actual_message, reader.beg_pos(), reader.end_pos());
       }
     }
     if (expects->beg_pos >= 0) {
index 4ee9bf2..86db379 100644 (file)
@@ -242,7 +242,7 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
     ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
     *ok = false;
   }
-  return Statement::Default();
+  return Statement::FunctionDeclaration();
 }
 
 
@@ -278,7 +278,15 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
   //
   Expect(i::Token::LBRACE, CHECK_OK);
   while (peek() != i::Token::RBRACE) {
-    ParseStatement(CHECK_OK);
+    i::Scanner::Location start_location = scanner_->peek_location();
+    Statement statement = ParseStatement(CHECK_OK);
+    i::Scanner::Location end_location = scanner_->location();
+    if (strict_mode() && statement.IsFunctionDeclaration()) {
+      ReportMessageAt(start_location.beg_pos, end_location.end_pos,
+                      "strict_function", NULL);
+      *ok = false;
+      return Statement::Default();
+    }
   }
   Expect(i::Token::RBRACE, ok);
   return Statement::Default();
@@ -357,7 +365,14 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
   if (peek() == i::Token::COLON && expr.IsRawIdentifier()) {
     if (!strict_mode() || !expr.AsIdentifier().IsFutureReserved()) {
       Consume(i::Token::COLON);
-      ParseStatement(ok);
+      i::Scanner::Location start_location = scanner_->peek_location();
+      Statement statement = ParseStatement(CHECK_OK);
+      if (strict_mode() && statement.IsFunctionDeclaration()) {
+        i::Scanner::Location end_location = scanner_->location();
+        ReportMessageAt(start_location.beg_pos, end_location.end_pos,
+                        "strict_function", NULL);
+        *ok = false;
+      }
       return Statement::Default();
     }
   }
@@ -486,7 +501,15 @@ PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
       Expect(i::Token::DEFAULT, CHECK_OK);
       Expect(i::Token::COLON, CHECK_OK);
     } else {
-      ParseStatement(CHECK_OK);
+      i::Scanner::Location start_location = scanner_->peek_location();
+      Statement statement = ParseStatement(CHECK_OK);
+      if (strict_mode() && statement.IsFunctionDeclaration()) {
+        i::Scanner::Location end_location = scanner_->location();
+        ReportMessageAt(start_location.beg_pos, end_location.end_pos,
+                        "strict_function", NULL);
+        *ok = false;
+        return Statement::Default();
+      }
     }
     token = peek();
   }
index 2a2a49a..2efd53e 100644 (file)
@@ -240,6 +240,10 @@ class PreParser {
       return Statement(kUnknownStatement);
     }
 
+    static Statement FunctionDeclaration() {
+      return Statement(kFunctionDeclaration);
+    }
+
     // Creates expression statement from expression.
     // Preserves being an unparenthesized string literal, possibly
     // "use strict".
@@ -263,11 +267,16 @@ class PreParser {
       return code_ == kUseStrictExpressionStatement;
     }
 
+    bool IsFunctionDeclaration() {
+      return code_ == kFunctionDeclaration;
+    }
+
    private:
     enum Type {
       kUnknownStatement,
       kStringLiteralExpressionStatement,
-      kUseStrictExpressionStatement
+      kUseStrictExpressionStatement,
+      kFunctionDeclaration
     };
 
     explicit Statement(Type code) : code_(code) {}
diff --git a/test/preparser/strict-const.js b/test/preparser/strict-const.js
new file mode 100644 (file)
index 0000000..91e9e39
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"use strict";
+const x = 42;
\ No newline at end of file
diff --git a/test/preparser/strict-function-statement.pyt b/test/preparser/strict-function-statement.pyt
new file mode 100644 (file)
index 0000000..08c4288
--- /dev/null
@@ -0,0 +1,99 @@
+# Copyright 2011 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+#       copyright notice, this list of conditions and the following
+#       disclaimer in the documentation and/or other materials provided
+#       with the distribution.
+#     * Neither the name of Google Inc. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# In strict mode, function declarations may only appear as source elements.
+
+# A template that performs the same strict-mode test in different
+# scopes (global scope, function scope, and nested function scope).
+def StrictTest(name, source):
+  Test(name, '"use strict";\n' + source, "strict_function")
+  Test(name + '-infunc',
+       'function foo() {\n "use strict";\n' + source +'\n}\n',
+       "strict_function")
+  Test(name + '-infunc2',
+       'function foo() {\n "use strict";\n  function bar() {\n' +
+       source +'\n }\n}\n',
+       "strict_function")
+
+# Not testing with-scope, since with is not allowed in strict mode at all.
+
+StrictTest("block", """
+  { function foo() { } }
+""")
+
+StrictTest("try-w-catch", """
+  try { function foo() { } } catch (e) { }
+""")
+
+StrictTest("try-w-finally", """
+  try { function foo() { } } finally { }
+""")
+
+StrictTest("catch", """
+  try { } catch (e) { function foo() { } }
+""")
+
+StrictTest("finally", """
+  try { } finally { function foo() { } }
+""")
+
+StrictTest("for", """
+  for (;;) { function foo() { } }
+""")
+
+StrictTest("while", """
+  while (true) { function foo() { } }
+""")
+
+StrictTest("do", """
+  do { function foo() { } } while (true);
+""")
+
+StrictTest("then", """
+  if (true) { function foo() { } }
+""")
+
+
+StrictTest("then-w-else", """
+  if (true) { function foo() { } } else { }
+""")
+
+
+StrictTest("else", """
+  if (true) { } else { function foo() { } }
+""")
+
+StrictTest("switch-case", """
+  switch (true) { case true: function foo() { } }
+""")
+
+StrictTest("labeled", """
+  label: function foo() { }
+""")
+
+
+
index 20819ce..a0f4612 100644 (file)
@@ -134,6 +134,10 @@ read_var = StrictTemplate("read-reserved-$id", """
   var x = $id;
 """)
 
+setter_arg = StrictTemplate("setter-param-$id", """
+  var x = {set foo($id) { }};
+""")
+
 non_strict_use = Template("nonstrict-$id", """
   var $id = 42;
   $id++;
@@ -144,6 +148,8 @@ non_strict_use = Template("nonstrict-$id", """
   $id -= 10;
   try {} catch ($id) { }
   function $id($id) { }
+  var x = {$id: 42};
+  x = {get $id() {}, set $id(value) {}};
   function foo() { "use strict;" }
   var $id = 42;
   $id++;
@@ -154,6 +160,8 @@ non_strict_use = Template("nonstrict-$id", """
   $id -= 10;
   try {} catch ($id) { }
   function $id($id) { }
+  x = {$id: 42};
+  x = {get $id() {}, set $id(value) {}};
 """)
 
 # ----------------------------------------------------------------------
@@ -165,6 +173,7 @@ for id in ["eval", "arguments"]:
   arg_name_nested({"id": id}, "strict_param_name")
   func_name_own({"id": id}, "strict_function_name")
   func_name_nested({"id": id}, "strict_function_name")
+  setter_arg({"id": id}, "strict_param_name")
   for op in assign_ops.keys():
     assign_var({"id": id, "op":op, "opname": assign_ops[op]},
                "strict_lhs_assignment")
@@ -184,6 +193,7 @@ for reserved_word in reserved_words + strict_reserved_words:
   if (reserved_word == "const"): message = "unexpected_token"
   arg_name_own({"id":reserved_word}, message)
   arg_name_nested({"id":reserved_word}, message)
+  setter_arg({"id": reserved_word}, message)
   func_name_own({"id":reserved_word}, message)
   func_name_nested({"id":reserved_word}, message)
   for op in assign_ops.keys():