8087292: nashorn should have a "fail-fast" option for scripting, analog to bash "set -e"
authorsundar
Thu, 03 Sep 2015 21:47:48 +0530
changeset 32443 19645ce11626
parent 32442 a29dbbbe10ef
child 32445 9d05e7490a07
8087292: nashorn should have a "fail-fast" option for scripting, analog to bash "set -e" Reviewed-by: hannesw, jlaskey, mhaupt
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties
nashorn/test/script/trusted/JDK-8087292.js
nashorn/test/script/trusted/JDK-8087292.js.EXPECTED
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Wed Sep 02 22:28:31 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Thu Sep 03 21:47:48 2015 +0530
@@ -2419,7 +2419,7 @@
     }
 
     private void initScripting(final ScriptEnvironment scriptEnv) {
-        Object value;
+        ScriptObject value;
         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
 
@@ -2428,11 +2428,13 @@
 
         final String execName = ScriptingFunctions.EXEC_NAME;
         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
+        value.addOwnProperty(ScriptingFunctions.THROW_ON_ERROR_NAME, Attribute.NOT_ENUMERABLE, false);
+
         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
 
         // Nashorn extension: global.echo (scripting-mode-only)
         // alias for "print"
-        value = get("print");
+        value = (ScriptObject)get("print");
         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
 
         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Wed Sep 02 22:28:31 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Thu Sep 03 21:47:48 2015 +0530
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
@@ -70,6 +71,9 @@
     /** EXIT name - special property used by $EXEC API. */
     public static final String EXIT_NAME = "$EXIT";
 
+    /** THROW_ON_ERROR name - special property of the $EXEC function used by $EXEC API. */
+    public static final String THROW_ON_ERROR_NAME = "throwOnError";
+
     /** Names of special properties used by $ENV API. */
     public  static final String ENV_NAME  = "$ENV";
 
@@ -247,6 +251,19 @@
             }
         }
 
+        // if we got a non-zero exit code ("failure"), then we have to decide to throw error or not
+        if (exit != 0) {
+            // get the $EXEC function object from the global object
+            final Object exec = global.get(EXEC_NAME);
+            assert exec instanceof ScriptObject : EXEC_NAME + " is not a script object!";
+
+            // Check if the user has set $EXEC.throwOnError property to true. If so, throw RangeError
+            // If that property is not set or set to false, then silently proceed with the rest.
+            if (JSType.toBoolean(((ScriptObject)exec).get(THROW_ON_ERROR_NAME))) {
+                throw rangeError("exec.returned.non.zero", ScriptRuntime.safeToString(exit));
+            }
+        }
+
         // Return the result from stdout.
         return out;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties	Wed Sep 02 22:28:31 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties	Thu Sep 03 21:47:48 2015 +0530
@@ -163,6 +163,7 @@
 range.error.invalid.date=Invalid Date
 range.error.too.many.errors=Script contains too many errors: {0} errors
 range.error.concat.string.too.big=Concatenated String is too big
+range.error.exec.returned.non.zero=$EXEC returned non-zero exit code: {0}
 
 reference.error.not.defined="{0}" is not defined
 reference.error.cant.be.used.as.lhs="{0}" can not be used as the left-hand side of assignment
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/trusted/JDK-8087292.js	Thu Sep 03 21:47:48 2015 +0530
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+/**
+ * JDK-8087292: nashorn should have a "fail-fast" option for scripting, analog to bash "set -e"
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+function tryExec() {
+    try {
+        `java`
+    } catch (e) {
+        print(e);
+    }
+
+    // make sure we got non-zero ("failure") exit code!
+    if ($EXIT == 0) {
+        print("Error: expected $EXIT code to be non-zero");
+    }
+}
+
+// no exception now!
+tryExec();
+
+// turn on error with non-zero exit code
+$EXEC.throwOnError = true;
+tryExec();
+
+// no exception after this
+$EXEC.throwOnError = false;
+tryExec();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/trusted/JDK-8087292.js.EXPECTED	Thu Sep 03 21:47:48 2015 +0530
@@ -0,0 +1,1 @@
+RangeError: $EXEC returned non-zero exit code: 1