JDK 1.8.0_92 Nashorn JS 引擎 indexOf 行为
JDK 1.8.0_92 Nashorn JS engine indexOf behaviour
我在 java8 中使用 "nashorn" java 脚本引擎在运行时评估一些表达式。我有一个 util class 方法:
public static String evaluateJavaScriptExpression(String expression) throws ScriptException {
if (expression == null) {
return null;
}
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine javaScriptEngine = scriptEngineManager.getEngineByName(JAVASCRIPT_ENGINE);
return String.valueOf(javaScriptEngine.eval(expression));
}
我为此创建了一些单元测试。其中之一是这样的:
String expression = "var arr = [1, 3, 2, 5, 4]; arr.indexOf(0);";
assertEquals("-1", ExpressionEvaluatorUtil.evaluateJavaScriptExpression(expression));
当我使用 java 版本“1.8.0_91”时,它对我来说工作正常。但是使用 java 版本“1.8.0_92”的人报告说测试失败。我将我的版本切换到 build 92,但它对我来说也失败了。它的实际结果是“-1.0”。
另外,我在 Chrome 控制台中尝试了相同的 js 代码,它返回“-1”,就像在 build 91 中一样。
有谁知道为什么两个 jdk 版本的结果会有如此大的差异?这是一个错误还是被故意更改?
如果我们看一下 java documentation for ScriptEngine.eval(String input) 方法,它 return 是一个对象,然后由开发人员使用类型转换对象以将类型更正为每个 return 类型 javascript。所以,我认为问题在于 String.valueOf() 方法调用,表达式求值 returns 是一个浮点数。
我认为您必须更改代码才能执行 Integer.valueOf(javaScriptEngine.eval(expression));
希望对您有所帮助:)
好吧,如果您知道更改的准确版本号,您就知道在哪里查看:the list of 1.8u92 bugfixes lists some fixes regarding Nashorn, the most interesting being JDK-8144020:
Remove long as an internal numeric type
ECMA defines double as the only number type in JavaScript. In Nashorn, we internally represent numbers as int, long and double. Use of long is problematic because it adds extra precision to the 53 bits provided by double. …
乍一看,这似乎只是一个内部变化,但如果你意识到你以前的结果源于之前的事实,那么情况就变了,eval
return Long
对于此代码,正在格式化为 "-1"
.
现在考虑这个错误报告的第一句话:“ECMA 将双精度定义为 JavaScript 中唯一的数字类型”。这得出的结论是 returning a Long
不是指定的结果类型,而是一个实现工件。
很明显,当 long
从内部使用中删除时,return Long
的可能性就被消除了,引擎现在不会 return Integer
,而是 Double
,作为更改的副产品。
这解释了为什么还有其他脚本如 "var str = 'abcd'; str.indexOf('x');"
仍然产生没有小数位的输出。后一个脚本评估为 Integer
并且仍然如此。由于输出类型的更改是删除内部 long
使用的副产品,而不是更改所有非 Double
数字结果的有意操作,因此内部使用 int
的地方不受影响。
将结果与 Chrome 的引擎进行比较时,您必须考虑到您只是在比较格式化输出,数字到字符串的转换不是脚本的一部分。所以结局未定。浏览器可以自由显示所有匹配整数值的数值,不带小数位。
我在 java8 中使用 "nashorn" java 脚本引擎在运行时评估一些表达式。我有一个 util class 方法:
public static String evaluateJavaScriptExpression(String expression) throws ScriptException {
if (expression == null) {
return null;
}
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine javaScriptEngine = scriptEngineManager.getEngineByName(JAVASCRIPT_ENGINE);
return String.valueOf(javaScriptEngine.eval(expression));
}
我为此创建了一些单元测试。其中之一是这样的:
String expression = "var arr = [1, 3, 2, 5, 4]; arr.indexOf(0);";
assertEquals("-1", ExpressionEvaluatorUtil.evaluateJavaScriptExpression(expression));
当我使用 java 版本“1.8.0_91”时,它对我来说工作正常。但是使用 java 版本“1.8.0_92”的人报告说测试失败。我将我的版本切换到 build 92,但它对我来说也失败了。它的实际结果是“-1.0”。 另外,我在 Chrome 控制台中尝试了相同的 js 代码,它返回“-1”,就像在 build 91 中一样。
有谁知道为什么两个 jdk 版本的结果会有如此大的差异?这是一个错误还是被故意更改?
如果我们看一下 java documentation for ScriptEngine.eval(String input) 方法,它 return 是一个对象,然后由开发人员使用类型转换对象以将类型更正为每个 return 类型 javascript。所以,我认为问题在于 String.valueOf() 方法调用,表达式求值 returns 是一个浮点数。
我认为您必须更改代码才能执行 Integer.valueOf(javaScriptEngine.eval(expression));
希望对您有所帮助:)
好吧,如果您知道更改的准确版本号,您就知道在哪里查看:the list of 1.8u92 bugfixes lists some fixes regarding Nashorn, the most interesting being JDK-8144020:
Remove long as an internal numeric type
ECMA defines double as the only number type in JavaScript. In Nashorn, we internally represent numbers as int, long and double. Use of long is problematic because it adds extra precision to the 53 bits provided by double. …
乍一看,这似乎只是一个内部变化,但如果你意识到你以前的结果源于之前的事实,那么情况就变了,eval
return Long
对于此代码,正在格式化为 "-1"
.
现在考虑这个错误报告的第一句话:“ECMA 将双精度定义为 JavaScript 中唯一的数字类型”。这得出的结论是 returning a Long
不是指定的结果类型,而是一个实现工件。
很明显,当 long
从内部使用中删除时,return Long
的可能性就被消除了,引擎现在不会 return Integer
,而是 Double
,作为更改的副产品。
这解释了为什么还有其他脚本如 "var str = 'abcd'; str.indexOf('x');"
仍然产生没有小数位的输出。后一个脚本评估为 Integer
并且仍然如此。由于输出类型的更改是删除内部 long
使用的副产品,而不是更改所有非 Double
数字结果的有意操作,因此内部使用 int
的地方不受影响。
将结果与 Chrome 的引擎进行比较时,您必须考虑到您只是在比较格式化输出,数字到字符串的转换不是脚本的一部分。所以结局未定。浏览器可以自由显示所有匹配整数值的数值,不带小数位。