JDK 1.8.0_92 Nashorn JS引擎indexOf行为

时间:2022-09-25 21:09:05

I am using "nashorn" javascript engine in java8 to evaluate some expressions during runtime. I have a util class for this with method:

我在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));
}

for which I created some unit tests. One of them goes like this:

我为此创建了一些单元测试。其中一个是这样的:

    String expression = "var arr = [1, 3, 2, 5, 4]; arr.indexOf(0);";
    assertEquals("-1", ExpressionEvaluatorUtil.evaluateJavaScriptExpression(expression));

It worked fine for me while I was using java version "1.8.0_91". But someone who used java version "1.8.0_92" reported that the test is failing. I switched my version to build 92 and it failed for me as well. The actual result for it is "-1.0". Also, i tried the same js code in Chrome console and it is returning "-1" as in build 91.

当我使用java版“1.8.0_91”时,它对我来说很好。但是使用java版本“1.8.0_92”的人报告说测试失败了。我将我的版本改为92版,但对我来说也失败了。它的实际结果是“-1.0”。此外,我在Chrome控制台中尝试了相同的js代码,它在构建91中返回“-1”。

Does anyone know why there is such difference in results between the two jdk versions? Is this a bug or it was purposely changed?

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

2 个解决方案

#1


4  

Well, if you know the precise version number of the change, you know where to look: the list of 1.8u92 bugfixes lists some fixes regarding Nashorn, the most interesting being JDK-8144020:

好吧,如果你知道更改的确切版本号,你知道在哪里看:1.8u92错误修正列表列出了一些关于Nashorn的修复,最有趣的是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. …

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

At the first glance, this seems to be an internal change only, but the picture changes, if you realize that your former result stemmed from the fact that previously, eval returned a Long for this code, being formatted to "-1".

乍一看,这似乎只是一个内部更改,但如果您意识到您之前的结果源于之前的事实,eval为此代码返回Long,格式化为“-1”,则图片会发生变化。

Now consider the first sentence of this bug report: “ECMA defines double as the only number type in JavaScript”. This leads to the conclusion that returning a Long was not a specified result type, but an implementation artifact.

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

So apparently, when long was removed from the internal usage, the possibility to return Long was eliminated and the engine now doesn’t return Integer instead, but Double, as a byproduct of the change.

很明显,当从内部使用中移除很长时间后,返回Long的可能性被消除,引擎现在不会返回Integer,而是Double,作为更改的副产品。

This explains, why there are other scripts like "var str = 'abcd'; str.indexOf('x');" which still produce an output without fractional digits. The latter script evaluated to Integer and still does. Since the change of the output type was a byproduct of removing internal long usage, not an intentional action to change all non-Double numeric results, places internally using int were not affected.

这解释了为什么还有其他脚本,如“var str ='abcd'; str.indexOf('x');”仍然产生没有小数位的输出。后一个脚本评估为Integer,但仍然如此。由于输出类型的更改是删除内部长使用的副产品,而不是有意更改所有非Double数字结果的操作,因此内部使用int的位置不受影响。

When comparing the result with Chrome’s engine, you have to consider that you are only comparing formatted output, with the number to string conversion not being part of the script. So the outcome is unspecified. The browser may take the freedom to present all numeric values matching an integer value without fractional digits.

将结果与Chrome引擎进行比较时,您必须考虑只是比较格式化输出,而字符串转换的数字不是脚本的一部分。所以结果没有具体说明。浏览器可以*地呈现匹配整数值而没有小数位的所有数值。

#2


0  

If we take a look at the java documentation for ScriptEngine.eval(String input) method, it returns an object, then it is upto the developer using to typecast the object to correct type as per return type of javascript. So, I think the the problem is with String.valueOf() method call, Evaluation of expression returns a floating point number.

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

I think you will have to change your code to do Integer.valueOf(javaScriptEngine.eval(expression));

我想你必须改变你的代码来做Integer.valueOf(javaScriptEngine.eval(expression));

Hope this helps :)

希望这可以帮助 :)

#1


4  

Well, if you know the precise version number of the change, you know where to look: the list of 1.8u92 bugfixes lists some fixes regarding Nashorn, the most interesting being JDK-8144020:

好吧,如果你知道更改的确切版本号,你知道在哪里看:1.8u92错误修正列表列出了一些关于Nashorn的修复,最有趣的是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. …

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

At the first glance, this seems to be an internal change only, but the picture changes, if you realize that your former result stemmed from the fact that previously, eval returned a Long for this code, being formatted to "-1".

乍一看,这似乎只是一个内部更改,但如果您意识到您之前的结果源于之前的事实,eval为此代码返回Long,格式化为“-1”,则图片会发生变化。

Now consider the first sentence of this bug report: “ECMA defines double as the only number type in JavaScript”. This leads to the conclusion that returning a Long was not a specified result type, but an implementation artifact.

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

So apparently, when long was removed from the internal usage, the possibility to return Long was eliminated and the engine now doesn’t return Integer instead, but Double, as a byproduct of the change.

很明显,当从内部使用中移除很长时间后,返回Long的可能性被消除,引擎现在不会返回Integer,而是Double,作为更改的副产品。

This explains, why there are other scripts like "var str = 'abcd'; str.indexOf('x');" which still produce an output without fractional digits. The latter script evaluated to Integer and still does. Since the change of the output type was a byproduct of removing internal long usage, not an intentional action to change all non-Double numeric results, places internally using int were not affected.

这解释了为什么还有其他脚本,如“var str ='abcd'; str.indexOf('x');”仍然产生没有小数位的输出。后一个脚本评估为Integer,但仍然如此。由于输出类型的更改是删除内部长使用的副产品,而不是有意更改所有非Double数字结果的操作,因此内部使用int的位置不受影响。

When comparing the result with Chrome’s engine, you have to consider that you are only comparing formatted output, with the number to string conversion not being part of the script. So the outcome is unspecified. The browser may take the freedom to present all numeric values matching an integer value without fractional digits.

将结果与Chrome引擎进行比较时,您必须考虑只是比较格式化输出,而字符串转换的数字不是脚本的一部分。所以结果没有具体说明。浏览器可以*地呈现匹配整数值而没有小数位的所有数值。

#2


0  

If we take a look at the java documentation for ScriptEngine.eval(String input) method, it returns an object, then it is upto the developer using to typecast the object to correct type as per return type of javascript. So, I think the the problem is with String.valueOf() method call, Evaluation of expression returns a floating point number.

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

I think you will have to change your code to do Integer.valueOf(javaScriptEngine.eval(expression));

我想你必须改变你的代码来做Integer.valueOf(javaScriptEngine.eval(expression));

Hope this helps :)

希望这可以帮助 :)