Variables in modules do not end up in the global object/scope, so you can't access them via context.getBindings("js")
When embedding JavaScript as part of a Java environment and enabling the modules feature, it is not possible to access any of the variables through the global object/scope from Java.
For example, given a module 'hello.js':
export function hello(x) { print('hello here ' + x); return true; }
And a test file 'test.js':
import { hello } from 'hello.js';
function testing(x) { hello(x); return true; }
If you compile the source using:
File sourceFile = deploymentPath.resolve("test.js").toFile(); Source graalSource = Source.newBuilder(language, sourceFile).mimeType("application/javascript+module").build(); Value result = context.eval(graalSource);
And then attempt get the function:
Value function = context.getBindings(language).getMember("testing");
The function variable will be null. No bindings are available with the following returning an empty set:
Set<String> members = context.getBindings(language).getMemberKeys();
As suggested on Slack, this very ugly hack works.
'hello.js':
export function hello(x) { print('hello here ' + x); return true; }
'test.js':
import { hello } from 'hello.js';
export function testing(x) { hello(x); return true; }
'wrap.js':
import * as exports from 'test.js'; exports;
If you compile 'wrap.js' with:
File sourceFile = deploymentPath.resolve(source).toFile();
Source graalSource = Source.newBuilder(language, sourceFile).mimeType("application/javascript+module").build();
You can then put the exports from 'test.js' back into the bindings with:
Value result = context.eval(graalSource); if (result.hasMembers()) {
Set<String> members = result.getMemberKeys(); for (String member : members) { context.getBindings(language).putMember(member, result.getMember(member)); }}
Would rather a cleaner way. :)
If I remove the mimeType("application/javascript+module") I get the const & vars populated in the bindings set.
https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/Context.html
FYI - I realise that this is the point of this issue with "modules" and thank you for your workaround :)
I have also checked Value result = context.eval and context.getPolyglotBindings and they are empty also.
I think it is right that the variables are not in the global scope. This is the meaning of modules. I consider it a mistake that the exported variables and functions are not available in the output object (in the result in your code).
Probably the new option --js.esm-eval-returns-exports would be helpful. It's documented in the JavaScript Modules section in the docs: https://www.graalvm.org/22.0/reference-manual/js/Modules/