Strict mode - allow function only in SourceElements.
authormmaly@chromium.org <mmaly@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 28 Feb 2011 19:07:02 +0000 (19:07 +0000)
committermmaly@chromium.org <mmaly@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 28 Feb 2011 19:07:02 +0000 (19:07 +0000)
Review URL: http://codereview.chromium.org/6598023/

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

src/messages.js
src/parser.cc
test/mjsunit/strict-mode.js

index 7c74abc..db33753 100644 (file)
@@ -227,6 +227,7 @@ function FormatMessage(message) {
       strict_delete:                ["Delete of an unqualified identifier in strict mode."],
       strict_delete_property:       ["Cannot delete property '", "%0", "' of ", "%1"],
       strict_const:                 ["Use of const in strict mode."],
+      strict_function:              ["In strict mode code, functions can only be declared at top level or immediately within another function." ],
     };
   }
   var message_type = %MessageGetType(message);
index de3bcf9..9fedfc9 100644 (file)
@@ -1106,7 +1106,20 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
     }
 
     Scanner::Location token_loc = scanner().peek_location();
-    Statement* stat = ParseStatement(NULL, CHECK_OK);
+
+    Statement* stat;
+    if (peek() == Token::FUNCTION) {
+      // FunctionDeclaration is only allowed in the context of SourceElements
+      // (Ecma 262 5th Edition, clause 14):
+      // SourceElement:
+      //    Statement
+      //    FunctionDeclaration
+      // Common language extension is to allow function declaration in place
+      // of any statement. This language extension is disabled in strict mode.
+      stat = ParseFunctionDeclaration(CHECK_OK);
+    } else {
+      stat = ParseStatement(NULL, CHECK_OK);
+    }
 
     if (stat == NULL || stat->IsEmpty()) {
       directive_prologue = false;   // End of directive prologue.
@@ -1263,8 +1276,17 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
       return result;
     }
 
-    case Token::FUNCTION:
+    case Token::FUNCTION: {
+      // In strict mode, FunctionDeclaration is only allowed in the context
+      // of SourceElements.
+      if (temp_scope_->StrictMode()) {
+        ReportMessageAt(scanner().peek_location(), "strict_function",
+                        Vector<const char*>::empty());
+        *ok = false;
+        return NULL;
+      }
       return ParseFunctionDeclaration(ok);
+    }
 
     case Token::NATIVE:
       return ParseNativeDeclaration(ok);
index 28a0455..42d8355 100644 (file)
@@ -285,6 +285,14 @@ CheckStrictMode("const x = 0;", SyntaxError);
 CheckStrictMode("for (const x = 0; false;) {}", SyntaxError);
 CheckStrictMode("function strict() { const x = 0; }", SyntaxError);
 
+// Strict mode only allows functions in SourceElements
+CheckStrictMode("if (true) { function invalid() {} }", SyntaxError);
+CheckStrictMode("for (;false;) { function invalid() {} }", SyntaxError);
+CheckStrictMode("{ function invalid() {} }", SyntaxError);
+CheckStrictMode("try { function invalid() {} } catch(e) {}", SyntaxError);
+CheckStrictMode("try { } catch(e) { function invalid() {} }", SyntaxError);
+CheckStrictMode("function outer() {{ function invalid() {} }}", SyntaxError);
+
 // Delete of an unqualified identifier
 CheckStrictMode("delete unqualified;", SyntaxError);
 CheckStrictMode("function strict() { delete unqualified; }", SyntaxError);