Nashorn no longer works with BigDecimal

We upgraded from Oracle JDK 8u77 to 8u92 and all of a sudden scripts that previously worked no longer work. Minimum Player:

Map<String, Object> attributes = Collections.singletonMap("GROSSREIMBAMOUNT", BigDecimal.ZERO); String script = "GROSSREIMBAMOUNT.toFixed(2)"; ScriptEngineManager mgr = new ScriptEngineManager(); ScriptEngine jsEngine = mgr.getEngineByName("JavaScript"); for (Entry<String, Object> entry : attributes.entrySet()) { jsEngine.put(entry.getKey(), entry.getValue()); } System.out.println(jsEngine.eval(script)); 

We used to get

 0.00 

But now we get.

 TypeError: GROSSREIMBAMOUNT.toFixed is not a function 

typeof now returns an object , where it previously returned number .

Is my question intentional behavior or error? I initially, although this will be a mistake, but the JDK-8010732 seems to suggest otherwise.

+6
source share
1 answer

The initial release of Nashorn treated all Java numeric primitives and all java.lang.Number subclasses as JavaScript numbers. However, JavaScript numbers are defined as doubles, which means that numeric types that do not map to doubles, such as longs or java.lang.BigDecimals, will be lost when converted to JavaScript numbers.

As you noticed, we recorded this between 8u77 and 8u92. Instances of java.lang.Number that cannot be unambiguously mapped to doubles are no longer treated as JavaScript numbers in Nashorn.

You have two ways around this. One of them is to simply treat these numbers as Java objects and use the methods provided by the Java class. This is usually the best option since the Java class was written to work with a numeric type at hand. Another option is to explicitly convert to JavaScript number. This is usually done by calling the global constructor of Number () without a "new" keyword or simply adding the unary operator "+". Please note, however, that this conversion can lead to loss of accuracy without your attention, so the first option is probably a safer way.

+7
source

All Articles