Estoy intentando usar GraalVM versión 20.1.0 para Java 8 (graalvm-ce-java8-windows-amd64-20.1.0) para ejecutar algunos JavaScript ES6 desde Java. Estoy usando Context así:

try (final Context jsContext = Context.newBuilder("js").allowAllAccess(true).build()) {
    final URL resource = this.getClass().getClassLoader().getResource("index.js");
    final File file = Paths.get(resource.toURI()).toFile();
    final Source source = Source.newBuilder("js", file).mimeType("application/javascript+module").build();
    final Value value = jsContext.eval(source);

    System.out.println(value);
} catch (final IOException e) {
    e.printStackTrace();
} catch (final URISyntaxException e) {
    e.printStackTrace();
}

Los archivos JS que estoy usando se ven así:

// index.js
import testFn from "./testFn";
testFn; // return value to Java

// testFn.js
function testFn() {
    print("Test!");
}

export default testFn;

Al ejecutar esto, aparece el error muy no descriptivo `

Exception in thread "main" Error: C:/path/to/testFn.js
    at org.graalvm.polyglot.Context.eval(Context.java:345)
    // This error points to "final Value value = jsContext.eval(source);" in the Java code

Sin embargo, si ejecuto testFn.js directamente reemplazando index.js con testFn.js en el código Java, ¡funciona bien! También funciona bien si elimino la importación, por lo que supongo que algo está defectuoso con las importaciones de ES6. Cambiar el nombre de los archivos para usar la extensión *.mjs no hace ninguna diferencia. Agregar allowIO(true) a la configuración Context tampoco cambia nada.

Todo el código anterior es un MVCE que puede probar, si es necesario.


Obtengo el mismo error si intento importar también un archivo inexistente (import "./asdasd"), por lo que tal vez no se encuentre el archivo. Aunque he verificado dos veces que el archivo existe en el directorio que enumera, tal vez sea solo una coincidencia.

1
Charanor 11 jun. 2020 a las 06:02

2 respuestas

La mejor respuesta

Debe especificar la extensión del archivo al importar en GraalVM:

import testFn from "./testFn.js"; // needs '.js' after file name!
testFn;

Tenga en cuenta que el archivo de índice debe tener la extensión de archivo .mjs, no .js, O , debe usar .mimeType("application/javascript+module") para que las importaciones funcionen. Sin embargo, los archivos que importa no necesitan una extensión de archivo específica.

He identificado esto como un error y he realizado un informe de error aquí. Los futuros lectores verifican el enlace para ver si se ha solucionado este error.

1
Charanor 13 jun. 2020 a las 04:58

Como veo (pero no estoy completamente seguro), el método Context.eval(Source source) de GraalVM funciona de la misma manera que la función eval() de JavaScript.

Eso puede causar el problema, ya que JS eval siempre trata su entrada como un Script, no como un Módulo, y los import s estáticos solo se permiten dentro de los Módulos.

Podría intentar utilizar la sintaxis dinámica await import('./testFn') en su lugar, que también está permitida dentro de los Scripts (si GraalVM lo admite), pero desafortunadamente no puedo decir si funcionará, y no sé cómo pasar volver recursos asíncronos a Java.

0
FZs 12 jun. 2020 a las 13:52