The JS array slice function doesn't work anymore with Java 8

Hi,

My JS scripts fail under Java 8 when they try to use the slice function on an array. It used to work (using Java 6) even if the array was coming from a java method that returned a Java array, but now it doesn’t want to hear about it. I guess I could try to convert array types (I do it a lot already in my scripts) but for now it is simpler to just replace the split() by a loop. Just wanted to make other scripters aware.

@christlet Can you please post a short example illustrating the problem? Do you think this is a Rhino vs. Nashorn issue?

I don’t have a minimal example at hand (will try to make one). The script I have generates a java double array containing values of a line profile using the ProfilePlot.getProfile() method. when I call simple split on this array directly in JS [array.slice(begin,end)], I get an error that there is no split function. It used to work in Java 6 so I think it is due to a Nashorn vs Rhino type handling discrepancy in the case where you mix Java and JS arrays (I know it’s bad, but but it happens frequently when you use JS to script IJ java classes).

Can you split on a regex? See e.g. this SO post. Apparently that works in both Rhino and Nashorn…

Sorry I made an error in my last post… it’s not split it’s slice (I edited my previous post)! It’s to make a sub-array.

@christlet If you want any concrete suggestions on how to make it work, you are going to need to post some code.

Actually it’s not for me, I have isolated the bug and changed the code in my scripts to remove the problem. It’s for others to avoid spending their time figuring out and doing the same.

Here is a minimal code:

importClass(Packages.ij.IJ);
importClass(Packages.ij.gui.ProfilePlot);
importClass(Packages.ij.gui.Line);

imp = IJ.openImage("http://imagej.nih.gov/ij/images/AuPbSn40.jpg");
imp.setRoi(new Line(205,63,323,257));
var profPlot = new ProfilePlot(imp);
var rawY = profPlot.getProfile();
sub = rawY.slice(0, rawY.length-5);

results in the error:

New_.js:9 TypeError: [D@3e091574 has no such function "slice"
at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57)
at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:213)
at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:185)
at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:172)
at jdk.nashorn.internal.runtime.linker.NashornBottomLinker.linkBean(NashornBottomLinker.java:106)
at jdk.nashorn.internal.runtime.linker.NashornBottomLinker.getGuardedInvocation(NashornBottomLinker.java:71)
at jdk.internal.dynalink.support.CompositeGuardingDynamicLinker.getGuardedInvocation(CompositeGuardingDynamicLinker.java:124)
at jdk.internal.dynalink.support.LinkerServicesImpl.getGuardedInvocation(LinkerServicesImpl.java:154)
at jdk.internal.dynalink.DynamicLinker.relink(DynamicLinker.java:253)
at jdk.nashorn.internal.scripts.Script$44$New_.:program(New_.js:9)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:640)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:228)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:446)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:403)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:399)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:150)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:249)
at org.scijava.script.ScriptModule.run(ScriptModule.java:174)
at org.scijava.module.ModuleRunner.run(ModuleRunner.java:167)
at org.scijava.module.ModuleRunner.call(ModuleRunner.java:126)
at org.scijava.module.ModuleRunner.call(ModuleRunner.java:65)
at org.scijava.thread.DefaultThreadService$2.call(DefaultThreadService.java:191)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

Just to illustrate how to actually avoid this problem:

var ints = [1,2,3,4,5,6];
print("ints = " + ints);

// slicing JS arrays works
print(ints.slice(2, 5));

// slicing Java arrays does not
var javaInts = Java.to(ints,"int[]");
//print(javaInts.slice(2, 5));

// but you can convert a Java array to a JS one
var jsInts = Java.from(javaInts);
print(jsInts.slice(2, 5));

See also Oracle’s Using Java from scripts article.

2 Likes

Great! Thanks Curtis.