-
Bug
-
Resolution: Not an Issue
-
P3
-
8, 9
-
generic
-
generic
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]
A DESCRIPTION OF THE PROBLEM :
When using an instance of a custom implementation of AbstractJSObject, under certain conditions the method "getDefaultValue(Class)" is called.
When using that instance from within an eval call to the nashorn engine, it seems counterintuitive which argument value is passed, and is lacking the required consistency to be able to correctly follow the ECMAscript 5.1 (262) spec (specifically section 8.12.8).
Given a "var a" that holds the instance of the AbstractJSObject implementation, evaluating the following expression causes the hint argument to be null (where a non-null value is expected):
- ""+a
- a+""
- 1+a
- a+1
- 1-a
- a-1
The reason I post specifically this set of expressions is that, when "a" is replaced with a native javascript object (expressed as "{}"), each expression yields a different result from each other listed expression.
But it is impossible to influence the outcome from within the custom implementation of AbstractJSObject.getDefaultValue(Class), in such a way that a similar result can be achieved.
The main factor seems to be that under most of these conditions, the value passed as parameter Class hint is null. This is the case for the following expressions:
- ""+a
- a+""
- 1+a
- a+1
Becuase in all 4 cases the same hint value of null is passed, it is impossible to create an implementation that can determine a proper output.
For the remaining 2 expressions, the argument is an instance of Number.class:
- 1-a
- a-1
But in none of these situations is it possible in the implementation of AbstractJSObject.getDefaultValue(Class) to determine under what pretense the method is called, and subsequently create a matching output to what otherwise would be returned in the case of a native javascript object
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the provided source code.
The expected result is more of a "desired" result in that scenario, as there is no indication according to the nashorn API under what circumstances to expect which arguments are given. As such, the provided source is a lacking "reference" implementation, in a more-or-less theoretical decent-case scenario regarding the nashorn API.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The following output:
[object Object]
[object Object]
0.0
0.0
1[object Object]
1[object Object]
1
1
NaN
NaN
-1
-1
ACTUAL -
The following output:
[object Object]
null
0.0
null
1[object Object]
1.0
1
1.0
NaN
1.0
-1
-1.0
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import jdk.nashorn.api.scripting.AbstractJSObject;
import jdk.nashorn.api.scripting.NashornScriptEngine;
public class A {
public static void main(String[] args) throws Throwable {
NashornScriptEngine engine = (NashornScriptEngine) new jdk.nashorn.api.scripting.NashornScriptEngineFactory().getScriptEngine();
AbstractJSObject obj = new AbstractJSObject() {
@Override
public Object getDefaultValue(Class<?> hint) {
if (hint == null) {
return null;
}
if (String.class.isAssignableFrom(hint)) {
return "[object Object]";
}
if (Number.class.isAssignableFrom(hint)) {
return 0;
}
throw new IllegalStateException();
}
};
engine.put("a", obj);
System.out.println(engine.eval("\"\"+{};"));
System.out.println(engine.eval("\"\"+a;"));
System.out.println("");
System.out.println(engine.eval("{}+\"\";"));
System.out.println(engine.eval("a+\"\";"));
System.out.println("");
System.out.println(engine.eval("1+{};"));
System.out.println(engine.eval("1+a;"));
System.out.println("");
System.out.println(engine.eval("{}+1;"));
System.out.println(engine.eval("a+1;"));
System.out.println("");
System.out.println(engine.eval("1-{};"));
System.out.println(engine.eval("1-a;"));
System.out.println("");
System.out.println(engine.eval("{}-1;"));
System.out.println(engine.eval("a-1;"));
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
No workaround possible.
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]
A DESCRIPTION OF THE PROBLEM :
When using an instance of a custom implementation of AbstractJSObject, under certain conditions the method "getDefaultValue(Class)" is called.
When using that instance from within an eval call to the nashorn engine, it seems counterintuitive which argument value is passed, and is lacking the required consistency to be able to correctly follow the ECMAscript 5.1 (262) spec (specifically section 8.12.8).
Given a "var a" that holds the instance of the AbstractJSObject implementation, evaluating the following expression causes the hint argument to be null (where a non-null value is expected):
- ""+a
- a+""
- 1+a
- a+1
- 1-a
- a-1
The reason I post specifically this set of expressions is that, when "a" is replaced with a native javascript object (expressed as "{}"), each expression yields a different result from each other listed expression.
But it is impossible to influence the outcome from within the custom implementation of AbstractJSObject.getDefaultValue(Class), in such a way that a similar result can be achieved.
The main factor seems to be that under most of these conditions, the value passed as parameter Class hint is null. This is the case for the following expressions:
- ""+a
- a+""
- 1+a
- a+1
Becuase in all 4 cases the same hint value of null is passed, it is impossible to create an implementation that can determine a proper output.
For the remaining 2 expressions, the argument is an instance of Number.class:
- 1-a
- a-1
But in none of these situations is it possible in the implementation of AbstractJSObject.getDefaultValue(Class) to determine under what pretense the method is called, and subsequently create a matching output to what otherwise would be returned in the case of a native javascript object
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the provided source code.
The expected result is more of a "desired" result in that scenario, as there is no indication according to the nashorn API under what circumstances to expect which arguments are given. As such, the provided source is a lacking "reference" implementation, in a more-or-less theoretical decent-case scenario regarding the nashorn API.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The following output:
[object Object]
[object Object]
0.0
0.0
1[object Object]
1[object Object]
1
1
NaN
NaN
-1
-1
ACTUAL -
The following output:
[object Object]
null
0.0
null
1[object Object]
1.0
1
1.0
NaN
1.0
-1
-1.0
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import jdk.nashorn.api.scripting.AbstractJSObject;
import jdk.nashorn.api.scripting.NashornScriptEngine;
public class A {
public static void main(String[] args) throws Throwable {
NashornScriptEngine engine = (NashornScriptEngine) new jdk.nashorn.api.scripting.NashornScriptEngineFactory().getScriptEngine();
AbstractJSObject obj = new AbstractJSObject() {
@Override
public Object getDefaultValue(Class<?> hint) {
if (hint == null) {
return null;
}
if (String.class.isAssignableFrom(hint)) {
return "[object Object]";
}
if (Number.class.isAssignableFrom(hint)) {
return 0;
}
throw new IllegalStateException();
}
};
engine.put("a", obj);
System.out.println(engine.eval("\"\"+{};"));
System.out.println(engine.eval("\"\"+a;"));
System.out.println("");
System.out.println(engine.eval("{}+\"\";"));
System.out.println(engine.eval("a+\"\";"));
System.out.println("");
System.out.println(engine.eval("1+{};"));
System.out.println(engine.eval("1+a;"));
System.out.println("");
System.out.println(engine.eval("{}+1;"));
System.out.println(engine.eval("a+1;"));
System.out.println("");
System.out.println(engine.eval("1-{};"));
System.out.println(engine.eval("1-a;"));
System.out.println("");
System.out.println(engine.eval("{}-1;"));
System.out.println(engine.eval("a-1;"));
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
No workaround possible.