# HG changeset patch # User attila # Date 1367270540 -7200 # Node ID a2232050cd8f16e903d69ae1067ee8e654c0af33 # Parent ab536782f24784552e52577011515d356468e845 8008814: Configurable ignore/warning/error behavior for function declaration as statement Reviewed-by: jlaskey, sundar diff -r ab536782f247 -r a2232050cd8f nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java --- 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. diff -r ab536782f247 -r a2232050cd8f nashorn/src/jdk/nashorn/internal/parser/Parser.java --- 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); diff -r ab536782f247 -r a2232050cd8f nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java --- 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"); diff -r ab536782f247 -r a2232050cd8f nashorn/src/jdk/nashorn/internal/runtime/options/Options.java --- 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; } /** diff -r ab536782f247 -r a2232050cd8f nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties --- 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.", \ diff -r ab536782f247 -r a2232050cd8f nashorn/test/script/basic/JDK-8008814-3.js --- /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() diff -r ab536782f247 -r a2232050cd8f nashorn/test/script/basic/JDK-8008814-3.js.EXPECTED --- /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! diff -r ab536782f247 -r a2232050cd8f nashorn/test/script/basic/JDK-8008814-4.js --- /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() diff -r ab536782f247 -r a2232050cd8f nashorn/test/script/basic/JDK-8008814-4.js.EXPECTED --- /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! diff -r ab536782f247 -r a2232050cd8f nashorn/test/script/error/JDK-8008814-1.js --- /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() { + } +} diff -r ab536782f247 -r a2232050cd8f nashorn/test/script/error/JDK-8008814-1.js.EXPECTED --- /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() { + ^ diff -r ab536782f247 -r a2232050cd8f nashorn/test/script/error/JDK-8008814-2.js --- /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() { + } +} diff -r ab536782f247 -r a2232050cd8f nashorn/test/script/error/JDK-8008814-2.js.EXPECTED --- /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() { + ^