JDK 1.8.0_92 Nashorn JS引擎indexOf行为

JDK 1.8.0_92 Nashorn JS engine indexOf behaviour

本文关键字:JS 引擎 indexOf 行为 Nashorn JDK      更新时间:2023-09-26

我在java8中使用"nashorn" javascript引擎在运行时评估一些表达式。我有一个util类,方法是:

    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",如在构建91。

有谁知道为什么两个jdk版本之间的结果会有这样的差异?这是一个bug还是故意更改的?

如果您知道更改的确切版本号,您就知道该去哪里查看:1.8u92错误修复列表列出了有关Nashorn的一些修复,最有趣的是JDK-8144020:

删除long作为内部数字类型

ECMA将double定义为JavaScript中唯一的数字类型。在Nashorn中,我们内部将数字表示为int、long和double。使用long是有问题的,因为它在double提供的53位基础上增加了额外的精度。…

乍一看,这似乎只是一个内部的变化,但如果你意识到你以前的结果源于这样一个事实,即以前,eval返回了一个Long为这个代码,被格式化为"-1"

现在考虑这个bug报告的第一句话:"ECMA将double定义为JavaScript中唯一的数字类型"。由此得出的结论是,返回Long不是指定的结果类型,而是实现工件。

显然,当long从内部使用中删除时,返回Long的可能性被消除了,引擎现在不返回Integer,而是返回Double,作为变化的副产品。

这解释了为什么像"var str = 'abcd'; str.indexOf('x');"这样的脚本仍然产生没有小数的输出。后一个脚本的计算结果为Integer,现在仍然如此。由于输出类型的更改是删除内部long使用的副产品,而不是有意更改所有非Double数字结果,因此内部使用int的位置不受影响。

当与Chrome的引擎比较结果时,你必须考虑到你只是比较格式化的输出,数字到字符串的转换不是脚本的一部分。所以结果是不确定的。浏览器可以自由地显示所有与整数值匹配的数值,而不包含小数。

如果我们看一下ScriptEngine的java文档。eval(String input)方法,它返回一个对象,然后由开发人员根据javascript的返回类型将对象类型转换为正确的类型。所以,我认为问题在于String.valueOf()方法调用,表达式的求值返回一个浮点数。

我认为你将不得不改变你的代码做Integer.valueOf(javascriptenengine .eval(expression));

希望这对你有帮助