FULL PRODUCT VERSION : java version "1.8.0_25" Java(TM) SE Runtime Environment (build 1.8.0_25-b18) Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode) ADDITIONAL OS VERSION INFORMATION : Microsoft Windows [Version 6.1.7601] A DESCRIPTION OF THE PROBLEM : If __noSuchMethod__ is used on a Prototype, it seems that the ScriptEngine executes the function with the first Object the script was called (ScriptEngien.eval). The second call to the ScriptEngine with invokeFunction the JavaScript object behaves like a singleton. I tested this with a JDK7 (Rhino) successfully, but on a JDK8 it did'nt work like expected. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1. Execute TestCase with JDK7, look for output 2. Execute TestCase with JDK8 compare outputs EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - 868385821 == 868385821 675655832 == 675655832 2001526735 == 2001526735 1475988537 == 1475988537 1355734862 == 1355734862 ACTUAL - 1073533248 == 1073533248 576936864 != 1073533248 1653844940 != 1073533248 260840925 != 1073533248 1891502635 != 1073533248 REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; public class PrototypeTest { private static final String TEST_SCRIPT = "function proxyCall(realObj, mthName, args) {\r\n" + " var funcMap = {\r\n" + " 'arg0': function (obj, id, arg) {\r\n" + " return obj[id]();\r\n" + " }\r\n" + " };\r\n" + " var argType = 'arg' + args.length;\r\n" + " if (!(argType in funcMap)) {\r\n" + " var funcStr = 'function(obj, id, arg){return obj[id](';\r\n" + " for (var i = 0, len = args.length; i < len; i++) {\r\n" + " funcStr += 'arg[' + i + ']';\r\n" + " if ((i + 1) < len) {\r\n" + " funcStr += ',';\r\n" + " }\r\n" + " }\r\n" + " funcStr += ');}';\r\n" + " funcMap[argType] = eval(funcStr);\r\n" + " }\r\n" + " return funcMap[argType](realObj, mthName, args);\r\n" + "}\r\n" + "function Dummy(obj) {\r\n" + " this.myObj = obj;\r\n" + "}\r\n" + "Dummy.prototype.hashCodeFunc = function () {\r\n" + " return this.myObj.hashCode();\r\n" + "};\r\n" + "Dummy.prototype.__noSuchMethod__ = function (name, args) {\r\n" + " var callArgs;\r\n" + " if (arguments.length == 2 && Array.isArray(args)) {\r\n" + " callArgs = args;\r\n" + " } else {\r\n" + " callArgs = Array.prototype.slice.call(arguments, 1);\r\n" + " }\r\n" + " return proxyCall(this.myObj, name, callArgs);\r\n" + "};\r\n" + "function handle(obj) {\r\n" + " var dum = new Dummy(obj);\r\n" + " var hc1 = dum.hashCodeFunc();\r\n" + " var hc2 = dum.hashCode();\r\n" + " print(hc1 + (hc1 == hc2 ? ' == ' : ' != ') + hc2 + '\\r\\n');\r\n" + "}\r\n"; public static void main(String[] args) { ScriptEngine se = new ScriptEngineManager().getEngineByName("JavaScript"); try { se.eval(TEST_SCRIPT); for(int i=0; i<5; i++) { ((Invocable)se).invokeFunction("handle", new Object()); } } catch (ScriptException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } } ---------- END SOURCE ----------
|