8008814: Configurable ignore/warning/error behavior for function declaration as statement
Reviewed-by: jlaskey, sundar
--- 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() {
+ ^