JDK-8184720 : Nashorn engine in strict mode throws a java.lang.ClassCastException when calling apply() and passing the arguments object
  • Type: Bug
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Affected Version: 8,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2017-07-14
  • Updated: 2017-09-01
  • Resolved: 2017-08-31
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 10
10 b22Fixed
Description
FULL PRODUCT VERSION :
java version "1.8.0_131"
java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.3.9600] (windows 8 64bit)

A DESCRIPTION OF THE PROBLEM :
When I call eval (in strict mode) on a nashorn engine with the following script I get an exception:

    var yfunc = function () {
      (function(){}).apply(null, arguments);
    };
    yfunc();

The "(function(){})" on line 2 can be replaced with anything between parenthesis or a local variable, either way just something that shouldn't throw a compile error, and it will yield the same result. 

The Exception thrown is this:

    Exception in thread "main" java.lang.ClassCastException: Cannot cast jdk.nashorn.internal.runtime.Undefined to jdk.nashorn.internal.runtime.ScriptFunction

When I call this method with an owner, the exception thrown changes. Example code: 

    var yfunc = {
        method: function () {
              (null).apply(null, arguments);
        }
    };
    var x = yfunc.method();

Then the thrown exception looks like this:

    Exception in thread "main" java.lang.ClassCastException: Cannot cast jdk.nashorn.internal.scripts.JO4 to jdk.nashorn.internal.runtime.ScriptFunction

I've reproduced the issue so far on specifically these environments:

 - windows 7 64bit -> jdk 1.8.0_60 64bit
 - windows 8 64bit -> jdk 1.8.0_131 64bit



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the supplied source in this bug report.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No output.
ACTUAL -
Throws ClassCastException

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.ClassCastException: Cannot cast jdk.nashorn.internal.runtime.Undefined to jdk.nashorn.internal.runtime.ScriptFunction
	at java.lang.invoke.MethodHandleImpl.newClassCastException(MethodHandleImpl.java:361)
	at java.lang.invoke.MethodHandleImpl.castReference(MethodHandleImpl.java:356)
	at jdk.nashorn.internal.scripts.Script$\^eval\_.:program(<eval>:4)
	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:449)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:406)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:402)
	at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
	at root.Main.main(Main.java:19)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;

public class Main {
public static void main(String[] args) throws Throwable {

        final ScriptEngine engine = ((NashornScriptEngineFactory) new ScriptEngineManager()
                .getEngineFactories()
                .iterator()
                .next())
                .getScriptEngine(new String[]{ //
            "-strict"
        });

        engine.eval(""
                + "var yfunc = function () {\n"
                + "(function(){}).apply(null, arguments);\n"
                + "};\n"
                + "yfunc();\n");
}
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Any of the following:

 1. Putting "arguments" in a variable first (but simply wrapping it in parenthesis doesn't work!)
 2. Calling something other than apply
 3. Passing "arguments" in a different argument slot when calling apply
 4. Calling print() (with or without passing any arguments) as a preceding line of code inside the function body of yfunc
 5. Defining more than 0 parameters for yfunc()
 6. Binding yfunc first and then calling the bound method instead of calling yfunc directly
 7. Calling yfunc via Function.apply (not so much with Function.call)

SUPPORT :
YES


Comments
workaround for this bug is disabling apply2call optimization(-Dnashorn.apply2call=false).
22-08-2017

understanding issue
12-08-2017

To reproduce the issue, run the attached test case. Following are the results: JDK 8u131 - Fail JDK 9-ea+174 - Fail Following is the output on running the test case: Exception in thread "main" java.lang.ClassCastException: Cannot cast jdk.nashorn.internal.runtime.Undefined to jdk.nashorn.internal.runtime.ScriptFunction at java.base/java.lang.Class.cast(Unknown Source) at jdk.scripting.nashorn.scripts/jdk.nashorn.internal.scripts.Script$Recompilation$1$\^eval\_/203849460.:program(<eval>:4) at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(Unknown Source) at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunction.invoke(Unknown Source) at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptRuntime.apply(Unknown Source) at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source) at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source) at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source) at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.eval(Unknown Source) at java.scripting/javax.script.AbstractScriptEngine.eval(Unknown Source) at JI9049997.main(JI9049997.java:18)
17-07-2017