-
Bug
-
Resolution: Fixed
-
P3
-
8u20, 9
-
b15
-
x86_64
-
windows_7
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8045105 | 8u25 | Sundararajan Athijegannathan | P3 | Resolved | Fixed | b01 |
JDK-8044016 | 8u20 | Sundararajan Athijegannathan | P3 | Resolved | Fixed | b17 |
JDK-8052507 | emb-8u26 | Sundararajan Athijegannathan | P3 | Resolved | Fixed | b18 |
FULL PRODUCT VERSION :
java version "1.9.0-ea"
Java(TM) SE Runtime Environment (build 1.9.0-ea-b13)
Java HotSpot(TM) 64-Bit Server VM (build 1.9.0-ea-b13, mixed mode)
java version "1.8.0_20-ea"
Java(TM) SE Runtime Environment (build 1.8.0_20-ea-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b10, mixed mode)
java version "1.8.0_20-ea"
Java(TM) SE Runtime Environment (build 1.8.0_20-ea-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b15, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
A small conversion script of mine is failing to correctly handle script objects after they have been transferred to a different Global. The immediate cause of this is the fact that access to undefined properties / functions does not return "undefined" as they should, instead returning null when the conversion script is run against the object in the second Global. This incorrectly triggers a conditional block in the conversion script that is designed to handle String-like values.
This issue manifests itself in a very peculiar constellation for which the causality escapes my understanding.
- a prior execution (in an unrelated Global) has to include an instance of a Map as the value of a property of the script object to be converted
- the conversion script has to contain a conditional block that handles conversion of native JavaScript objects into Map instances
If either of these parameters is altered (e.g. the Map instance in the prior execution replace by a simple Object) the issue does not occur.
The test case works correctly when run in JDK 1.8.0_05
REGRESSION. Last worked in version 8
ADDITIONAL REGRESSION INFORMATION:
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the test case with assertions enabled (-ea)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The program completes without failing any of the assertions.
ACTUAL -
The pogram fails the second to last of the assertion. The result of the conversion is an instance of java.lang.String instead of the expected java.util.Map
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.AssertionError
at Test2.main(Test2.java:52)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.Collections;
import java.util.Map;
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class Test2
{
private static final String TEST_SCRIPT =
"function convert(o) {" +
"var b = o, c, d, e, f, g;" +
// test for native or Java String
"if (typeof o === 'string' || o.toUpperCase!== undefined) {" +
"c = Java.type('java.lang.String');" +
"b = new c(o);" +
"} else if (typeof o === 'object') {" +
"c = Java.type('java.util.HashMap');" +
"b = new c();" +
"for (d in o) { b.put(convert(d), convert(o[d])); }" +
"} return b; }" +
"javaObj = convert(nashornObj);";
public static void main(final String[] args) throws Exception
{
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
// construct object with reference to a Java Map (this somehow triggers the assert to fail in the end)
// Note: replacing map with Object => everything works fine again
final Bindings globalBindings = engine.createBindings();
globalBindings.put("map", Collections.<String, Object> emptyMap());
engine.eval("nashornObj = { test: map };", globalBindings);
engine.eval(TEST_SCRIPT, globalBindings);
assert !(globalBindings.get("javaObj") instanceof String);
assert globalBindings.get("javaObj") instanceof Map<?, ?>;
// construct object in new Global
final Bindings originalBindings = engine.createBindings();
engine.eval("nashornObj = { test: 12 }", originalBindings);
// show that it works in original Global
engine.eval(TEST_SCRIPT, originalBindings);
assert !(originalBindings.get("javaObj") instanceof String);
assert originalBindings.get("javaObj") instanceof Map<?, ?>;
// transfer to a different Global
final Bindings secondaryBindings = engine.createBindings();
secondaryBindings.put("nashornObj", originalBindings.get("nashornObj"));
// it should also work in different Global, but doesn't
engine.eval(TEST_SCRIPT, secondaryBindings);
assert !(secondaryBindings.get("javaObj") instanceof String);
assert secondaryBindings.get("javaObj") instanceof Map<?, ?>;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
The primary workaround for the test case is to always combine checks against undefined with checks against null, even though null is 100 % certain to either undefined or a function reference.
java version "1.9.0-ea"
Java(TM) SE Runtime Environment (build 1.9.0-ea-b13)
Java HotSpot(TM) 64-Bit Server VM (build 1.9.0-ea-b13, mixed mode)
java version "1.8.0_20-ea"
Java(TM) SE Runtime Environment (build 1.8.0_20-ea-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b10, mixed mode)
java version "1.8.0_20-ea"
Java(TM) SE Runtime Environment (build 1.8.0_20-ea-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b15, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
A small conversion script of mine is failing to correctly handle script objects after they have been transferred to a different Global. The immediate cause of this is the fact that access to undefined properties / functions does not return "undefined" as they should, instead returning null when the conversion script is run against the object in the second Global. This incorrectly triggers a conditional block in the conversion script that is designed to handle String-like values.
This issue manifests itself in a very peculiar constellation for which the causality escapes my understanding.
- a prior execution (in an unrelated Global) has to include an instance of a Map as the value of a property of the script object to be converted
- the conversion script has to contain a conditional block that handles conversion of native JavaScript objects into Map instances
If either of these parameters is altered (e.g. the Map instance in the prior execution replace by a simple Object) the issue does not occur.
The test case works correctly when run in JDK 1.8.0_05
REGRESSION. Last worked in version 8
ADDITIONAL REGRESSION INFORMATION:
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the test case with assertions enabled (-ea)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The program completes without failing any of the assertions.
ACTUAL -
The pogram fails the second to last of the assertion. The result of the conversion is an instance of java.lang.String instead of the expected java.util.Map
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.AssertionError
at Test2.main(Test2.java:52)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.Collections;
import java.util.Map;
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class Test2
{
private static final String TEST_SCRIPT =
"function convert(o) {" +
"var b = o, c, d, e, f, g;" +
// test for native or Java String
"if (typeof o === 'string' || o.toUpperCase!== undefined) {" +
"c = Java.type('java.lang.String');" +
"b = new c(o);" +
"} else if (typeof o === 'object') {" +
"c = Java.type('java.util.HashMap');" +
"b = new c();" +
"for (d in o) { b.put(convert(d), convert(o[d])); }" +
"} return b; }" +
"javaObj = convert(nashornObj);";
public static void main(final String[] args) throws Exception
{
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
// construct object with reference to a Java Map (this somehow triggers the assert to fail in the end)
// Note: replacing map with Object => everything works fine again
final Bindings globalBindings = engine.createBindings();
globalBindings.put("map", Collections.<String, Object> emptyMap());
engine.eval("nashornObj = { test: map };", globalBindings);
engine.eval(TEST_SCRIPT, globalBindings);
assert !(globalBindings.get("javaObj") instanceof String);
assert globalBindings.get("javaObj") instanceof Map<?, ?>;
// construct object in new Global
final Bindings originalBindings = engine.createBindings();
engine.eval("nashornObj = { test: 12 }", originalBindings);
// show that it works in original Global
engine.eval(TEST_SCRIPT, originalBindings);
assert !(originalBindings.get("javaObj") instanceof String);
assert originalBindings.get("javaObj") instanceof Map<?, ?>;
// transfer to a different Global
final Bindings secondaryBindings = engine.createBindings();
secondaryBindings.put("nashornObj", originalBindings.get("nashornObj"));
// it should also work in different Global, but doesn't
engine.eval(TEST_SCRIPT, secondaryBindings);
assert !(secondaryBindings.get("javaObj") instanceof String);
assert secondaryBindings.get("javaObj") instanceof Map<?, ?>;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
The primary workaround for the test case is to always combine checks against undefined with checks against null, even though null is 100 % certain to either undefined or a function reference.
- backported by
-
JDK-8044016 Access to undefined property yields "null" instead of "undefined"
- Resolved
-
JDK-8045105 Access to undefined property yields "null" instead of "undefined"
- Resolved
-
JDK-8052507 Access to undefined property yields "null" instead of "undefined"
- Resolved