JDK-8148134 : AbstractJSObject function does not support "apply()"
  • Type: Bug
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Affected Version: 8u66,9
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: generic
  • CPU: generic
  • Submitted: 2016-01-25
  • Updated: 2016-06-07
  • Resolved: 2016-02-08
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux XXX 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt20-1+deb8u3 (2016-01-17) x86_64 GNU/Linux


A DESCRIPTION OF THE PROBLEM :

When an AbstractJSObject claims to be a function (isFunction()), and is put in the context with put(String, Object), you cannot call apply on it.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
    public void nashornApply() throws Exception {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
        engine.put("f", new AbstractJSObject() {
            @Override
            public boolean isFunction() {
                return true;
            }
            @Override
            public Object call(Object thiz, Object... args) {
                System.out.println("thiz = " + thiz);
                System.out.println("args = " + Arrays.toString(args));
                return null;
            }
        });
        engine.eval("f(1,2,3);");
        engine.eval("f.apply(null, [1,2,3]);");
    }


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
thiz = undefined
args = [1, 2, 3]
thiz = undefined
args = [1, 2, 3]

ACTUAL -
thiz = undefined
args = [1, 2, 3]
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.445 sec <<< FAILURE!
nashornApply(dk.kosmisk.jslib.NashornApplyTest)  Time elapsed: 0.409 sec  <<< ERROR!
javax.script.ScriptException: TypeError: null is not a function in <eval> at line number 1
	at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:467)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:451)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:403)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:399)
	at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
...

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" javax.script.ScriptException: TypeError: null is not a function in <eval> at line number 1
	at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:467)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:451)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:403)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:399)
	at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
	at Main.main(Main.java:46)
Caused by: <eval>:1 TypeError: null is not a function
	at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57)
	at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:213)
	at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:185)
	at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:172)
	at jdk.nashorn.internal.runtime.linker.NashornBottomLinker.linkNull(NashornBottomLinker.java:172)
	at jdk.nashorn.internal.runtime.linker.NashornBottomLinker.getGuardedInvocation(NashornBottomLinker.java:64)
	at jdk.internal.dynalink.support.CompositeGuardingDynamicLinker.getGuardedInvocation(CompositeGuardingDynamicLinker.java:124)
	at jdk.internal.dynalink.support.LinkerServicesImpl.getGuardedInvocation(LinkerServicesImpl.java:154)
	at jdk.internal.dynalink.DynamicLinker.relink(DynamicLinker.java:253)
	at jdk.nashorn.internal.scripts.Script$1$\^eval\_.:program(<eval>:1)
	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:640)
	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:228)
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:446)
	... 5 more


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------

public class Main {
    public static void main(String[] args) throws Exception {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
        engine.put("f", new AbstractJSObject() {
            @Override
            public boolean isFunction() {
                return true;
            }
            @Override
            public Object call(Object thiz, Object... args) {
                System.out.println("thiz = " + thiz);
                System.out.println("args = " + Arrays.toString(args));
                return null;
            }
        });
        engine.eval("f(1,2,3);");
        engine.eval("f.apply(null, [1,2,3]);");
    }
}
---------- END SOURCE ----------


Comments
The user should provide an implementation of apply() in getMember(). There is however a bug in how apply() is called, see JDK-8148140.
08-02-2016

Attached test case executed on : JDK 8u66 - Fail JDK 8u72 - Fail JDK 9 - Fail
25-01-2016