8008814: Configurable ignore/warning/error behavior for function declaration as statement
authorattila
Mon, 29 Apr 2013 23:22:20 +0200
changeset 17257 a2232050cd8f
parent 17256 ab536782f247
child 17258 f4480af13364
8008814: Configurable ignore/warning/error behavior for function declaration as statement Reviewed-by: jlaskey, sundar
nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java
nashorn/src/jdk/nashorn/internal/parser/Parser.java
nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
nashorn/src/jdk/nashorn/internal/runtime/options/Options.java
nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties
nashorn/test/script/basic/JDK-8008814-3.js
nashorn/test/script/basic/JDK-8008814-3.js.EXPECTED
nashorn/test/script/basic/JDK-8008814-4.js
nashorn/test/script/basic/JDK-8008814-4.js.EXPECTED
nashorn/test/script/error/JDK-8008814-1.js
nashorn/test/script/error/JDK-8008814-1.js.EXPECTED
nashorn/test/script/error/JDK-8008814-2.js
nashorn/test/script/error/JDK-8008814-2.js.EXPECTED
--- a/nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java	Mon Apr 29 18:40:40 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java	Mon Apr 29 23:22:20 2013 +0200
@@ -37,8 +37,8 @@
 import jdk.nashorn.internal.runtime.ErrorManager;
 import jdk.nashorn.internal.runtime.JSErrorType;
 import jdk.nashorn.internal.runtime.ParserException;
+import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.regexp.RegExpFactory;
-import jdk.nashorn.internal.runtime.Source;
 
 /**
  * Base class for parsers.
@@ -245,6 +245,16 @@
     }
 
     /**
+     * Report a warning to the error manager.
+     *
+     * @param errorType  The error type of the warning
+     * @param message    Warning message.
+     */
+    protected final void warning(final JSErrorType errorType, final String message, final long errorToken) {
+        errors.warning(error(errorType, message, errorToken));
+    }
+
+    /**
      * Generate 'expected' message.
      *
      * @param expected Expected tokenType.
--- a/nashorn/src/jdk/nashorn/internal/parser/Parser.java	Mon Apr 29 18:40:40 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/parser/Parser.java	Mon Apr 29 23:22:20 2013 +0200
@@ -675,9 +675,6 @@
         if (type == FUNCTION) {
             // As per spec (ECMA section 12), function declarations as arbitrary statement
             // is not "portable". Implementation can issue a warning or disallow the same.
-            if (isStrictMode && !topLevel) {
-                throw error(AbstractParser.message("strict.no.func.here"), token);
-            }
             functionExpression(true, topLevel);
             return;
         }
@@ -2332,6 +2329,12 @@
         if (isStatement) {
             if (topLevel) {
                 functionNode = functionNode.setFlag(lc, FunctionNode.IS_DECLARED);
+            } else if (isStrictMode) {
+                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
+            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
+                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
+            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
+                warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
             }
             if (ARGUMENTS.symbolName().equals(name.getName())) {
                 lc.setFlag(lc.getCurrentFunction(), FunctionNode.DEFINES_ARGUMENTS);
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Mon Apr 29 18:40:40 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Mon Apr 29 23:22:20 2013 +0200
@@ -85,6 +85,33 @@
     /** Launch using as fx application */
     public final boolean _fx;
 
+    /**
+     * Behavior when encountering a function declaration in a lexical context where only statements are acceptable
+     * (function declarations are source elements, but not statements).
+     */
+    public enum FunctionStatementBehavior {
+        /**
+         * Accept the function declaration silently and treat it as if it were a function expression assigned to a local
+         * variable.
+         */
+        ACCEPT,
+        /**
+         * Log a parser warning, but accept the function declaration and treat it as if it were a function expression
+         * assigned to a local variable.
+         */
+        WARNING,
+        /**
+         * Raise a {@code SyntaxError}.
+         */
+        ERROR
+    }
+
+    /**
+     * Behavior when encountering a function declaration in a lexical context where only statements are acceptable
+     * (function declarations are source elements, but not statements).
+     */
+    public final FunctionStatementBehavior _function_statement;
+
     /** Should lazy compilation take place */
     public final boolean _lazy_compilation;
 
@@ -161,6 +188,13 @@
         _early_lvalue_error   = options.getBoolean("early.lvalue.error");
         _empty_statements     = options.getBoolean("empty.statements");
         _fullversion          = options.getBoolean("fullversion");
+        if(options.getBoolean("function.statement.error")) {
+            _function_statement = FunctionStatementBehavior.ERROR;
+        } else if(options.getBoolean("function.statement.warning")) {
+            _function_statement = FunctionStatementBehavior.WARNING;
+        } else {
+            _function_statement = FunctionStatementBehavior.ACCEPT;
+        }
         _fx                   = options.getBoolean("fx");
         _lazy_compilation     = options.getBoolean("lazy.compilation");
         _loader_per_compile   = options.getBoolean("loader.per.compile");
--- a/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java	Mon Apr 29 18:40:40 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java	Mon Apr 29 23:22:20 2013 +0200
@@ -243,7 +243,13 @@
      */
     public String getString(final String key) {
         final Option<?> option = get(key);
-        return option != null ? (String)option.getValue() : null;
+        if(option != null) {
+            final String value = (String)option.getValue();
+            if(value != null) {
+                return value.intern();
+            }
+        }
+        return null;
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties	Mon Apr 29 18:40:40 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties	Mon Apr 29 23:22:20 2013 +0200
@@ -144,6 +144,20 @@
     desc="Print full version info of Nashorn." \
 }
 
+nashorn.option.function.statement.error= {                                    \
+    name="--function-statement-error",                                        \
+    desc="Report an error when function declaration is used as a statement.", \
+    is_undocumented=true,                                                     \
+    default=false                                                             \
+}
+
+nashorn.option.function.statement.warning = {                      \
+    name="--function-statement-warning",                           \
+    desc="Warn when function declaration is used as a statement.", \
+    is_undocumented=true,                                          \
+    default=false                                                  \
+}
+
 nashorn.option.fx = {                           \
     name="-fx",                                 \
     desc="Launch script as an fx application.", \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8008814-3.js	Mon Apr 29 23:22:20 2013 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * NASHORN-8008814: it's not a compile time error to have a nested strict function declaration when the outer one is not strict
+ *
+ * @test
+ * @run
+ */
+
+function f() {
+  if(true) {
+    function g() {
+      "use strict";
+      print("g invoked!")
+    }
+  }
+  g()
+}
+f()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8008814-3.js.EXPECTED	Mon Apr 29 23:22:20 2013 +0200
@@ -0,0 +1,1 @@
+g invoked!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8008814-4.js	Mon Apr 29 23:22:20 2013 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * NASHORN-8008814: it's not a compile time error to have a nested function declaration when warnings are reported
+ *
+ * @option --function-statement-warning
+ * @test
+ * @run/ignore-std-error
+ */
+
+function f() {
+  if(true) {
+    function g() {
+      print("g invoked!")
+    }
+  }
+  g()
+}
+f()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8008814-4.js.EXPECTED	Mon Apr 29 23:22:20 2013 +0200
@@ -0,0 +1,1 @@
+g invoked!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/JDK-8008814-1.js	Mon Apr 29 23:22:20 2013 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * NASHORN-8008814: it's a compile time error to have a nested function declaration when there's an option to treat it as an error
+ *
+ * @option --function-statement-error
+ * @test/compile-error
+ */
+
+if(true) {
+  function g() {
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/JDK-8008814-1.js.EXPECTED	Mon Apr 29 23:22:20 2013 +0200
@@ -0,0 +1,3 @@
+test/script/error/NASHORN-8008814-1.js:32:2 Function declarations can only occur at program or function body level. You should use a function expression here instead.
+  function g() {
+  ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/JDK-8008814-2.js	Mon Apr 29 23:22:20 2013 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * NASHORN-8008814: it's a compile time error to have a nested function declaration in strict mode
+ *
+ * @test/compile-error
+ */
+
+"use strict";
+if(true) {
+  function g() {
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/JDK-8008814-2.js.EXPECTED	Mon Apr 29 23:22:20 2013 +0200
@@ -0,0 +1,3 @@
+test/script/error/NASHORN-8008814-2.js:32:2 In strict mode, function declarations can only occur at program or function body level. You should use a function expression here instead.
+  function g() {
+  ^