¿Cómo agrego funciones globales personalizadas al objeto 'this' de JavaScript de GraalVM sin usar el modo de compatibilidad de Nashorn a través del método Object.bindProperties() (consulte esto: ¿Definir un objeto Java predeterminado/global para el motor de script de Nashorn? )? No pude encontrar una manera de usar los métodos de contexto y el reflejo del objeto de contexto no muestra un método bindProperties() similar que pueda usar.
Ejemplo:
Tengo estos métodos:
class GlobalMethods { public void a() {...} public void b() {...} public void c() {...} }y quiero que a(), b() y c() se puedan llamar en JavaScript sin alcance/calificación:
context.eval("js", "a()");¡Gracias por adelantado!
Para funciones js, puede definir un archivo, digamos globals.js , donde los globales se inicializan y se agregan al objeto global de JavaScript:
globalThis.someFunction = function() {...} y establezca la opción js.commonjs-global-properties para cargar este archivo en el momento de la creación del contexto:
Context context = Context.newBuilder("js") .option("js.commonjs-global-properties", "./globals.js") .build(); Para vincular las opciones de Java a JS, debe habilitar polyglot.js.allowHostAccess a través de Bindings :
Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE); bindings.put("polyglot.js.allowHostAccess", true); bindings.put("polyglot.js.allowHostClassLookup", (Predicate<String>) s -> true); bindings.put("javaObj", new Object());o con Contexto:
Context context = Context.newBuilder("js") .allowHostAccess(true) .build(); context.getBindings("js").putMember("a", GlobalMethods.a); O puede usar el decorador @HostAccess.Export en la definición de clase:
@HostAccess.Export public void a() {...} Aunque no estoy seguro de que pueda acceder a un método estático como GlobalMethods.a() sin hacer referencia al nombre de clase al menos una vez, tal vez pasar la salida de la función directamente sea suficiente para satisfacer sus necesidades, o pasar la definición de clase, seguida de una evaluación globalThis.a = GlobalMethods.a (no probado).
La respuesta de Eric que usa global.js funciona si los métodos no están sobrecargados. Además, la configuración completa para el objeto de contexto se ve así con algunas opciones adicionales requeridas:
context = Context.newBuilder("js") .allowHostAccess(true) .allowExperimentalOptions(true) .allowAllAccess(true) .allowIO(true) // required .option("js.nashorn-compat", "false") // Must be false .option("js.commonjs-require", "true") // required .option("js.commonjs-require-cwd", "/path/to/globals.js") // required .option("js.commonjs-global-properties", "./globals.js") .build();