0

I have a Javascript file: https://gist.github.com/VanitySoft/0cfd26991fa9ac33e03782e4316695c2

// lppDecode decodes an array of bytes into an array of ojects, 
function lppDecode(bytes) {
  //...
}

In my Java test case, i'm trying to send an array of bytes:

@Test
public void testTestDecorder() throws IOException {
  Context context = Context.create();
  String javaSctiptDecorder = FileUtils.readFileToString(new File("src/main/resources/decoderOnly.js"));
  Value decodeFunction = context.eval("js", javaSctiptDecorder);
  byte[] bytes = "016700E1027329EC038807FDD800BEE10000C8".getBytes();
  String json = decodeFunction.execute(new String(bytes)).asString();
  logger.debug(json);       
}

But I keep getting an error:

java.lang.UnsupportedOperationException: Unsupported operation Value.execute(Object...) for 'undefined'(language: JavaScript, type: undefined). You can ensure that the operation is supported using Value.canExecute().
  at com.oracle.truffle.polyglot.PolyglotEngineException.unsupported(PolyglotEngineException.java:144)
  at com.oracle.truffle.polyglot.PolyglotValue.unsupported(PolyglotValue.java:620)
  at com.oracle.truffle.polyglot.PolyglotValue.executeUnsupported(PolyglotValue.java:263)
  at com.oracle.truffle.polyglot.PolyglotValue$InteropCodeCache$AbstractExecuteNode.executeShared(PolyglotValue.java:1906)
  at com.oracle.truffle.polyglot.PolyglotValue$InteropCodeCache$ExecuteNode.executeImpl(PolyglotValue.java:1978)
  at com.oracle.truffle.polyglot.HostToGuestRootNode.execute(HostToGuestRootNode.java:113)
  at com.oracle.truffle.api.impl.DefaultCallTarget.callDirectOrIndirect(DefaultCallTarget.java:84)
  at com.oracle.truffle.api.impl.DefaultCallTarget.call(DefaultCallTarget.java:99)
  at com.oracle.truffle.api.impl.DefaultRuntimeAccessor$DefaultRuntimeSupport.callProfiled(DefaultRuntimeAccessor.java:119)
  at com.oracle.truffle.polyglot.PolyglotValue$InteropValue.execute(PolyglotValue.java:2787)
  at org.graalvm.polyglot.Value.execute(Value.java:457)
  at com.vanitysoft.nearsight.domain.dao.impl.GraavlTest.testTestDecorder(GraavlTest.java:44)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:566)
  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
  at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
  at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
  at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
  at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
  at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
  at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
  at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
  at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:43)
  at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
  at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
  at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
  at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
  at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
  at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
  at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
  at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
  at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
  at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
  at org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:82)
  at org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:73)
  at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
  at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
  at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
  at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
  at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:141)
  at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
  at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: Attached Guest Language Frames (1)

How can I get GraalVM to work with this byte array?

2 Answers 2

1
+100

The problem is that in decoderFunction.js you are defining the named function lppDecode. In Javascript, this is considered a function declaration, a statement, and not an expression, and it cannot be evaluated by Graal.

The problem is described in this Github issue. alexjordan's in his answer provides the solution:

You need to add parentheses around it, otherwise a named function is considered a statement not an expression in JavaScript. (function test() { return 'Hello World' }) should work.

So, enclosing your function within parentheses, either in the original Javascript file, or when constructing your Java variables, as pointed out as well by Mythos in his answer, should work.

You can check the indicated behavior in a browser Javascript console. Try defining for instance the following:

function lppDecode(bytes) { console.log('Bytes:', bytes); return bytes;}

As a result, as indicated, the browser will print undefined:

named function declaration

On the contrary, if you enclose your function within parentheses:

(function lppDecode(bytes) { console.log('Bytes:', bytes); return bytes;})

you will receive a reference to the function instead:

function reference

that can be used directly:

use function expression

That is what Graal will do.

These great related references provide further information:

Sign up to request clarification or add additional context in comments.

Comments

1

Seems like you're missing parenthesis around your js code. I have kept spelling typos in variable names in your code as they are.

@Test
public void testTestDecorder() throws IOException {
    Context context = Context.create();
    String javaSctiptDecorder = FileUtils.readFileToString(new File("src/main/resources/decoderOnly.js"));
    javaSctiptDecorder = "(" + javaSctiptDecorder + ")";
    Value decodeFunction = context.eval("js", javaSctiptDecorder);
    byte[] bytes = "016700E1027329EC038807FDD800BEE10000C8".getBytes();
    String json = decodeFunction .execute(new String(bytes)).asString();
    logger.debug(json);     
}

Check out these official examples: 1 and 2
Notice the paranthesis around JS objects/functions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.