Open renatoathaydes opened 2 years ago
@renatoathaydes thanks for reporting the issue, we will check it out and get back to you
@renatoathaydes I tried the reproducer and got the same error as you reported in https://github.com/oracle/graal/issues/4047 Is there another reproducer for the error reported in this issue?
In that ticket, they say issue #4047 is fixed on graalvm ce 22.0.0-dev build, if you try that, maybe you can reproduce? Otherwise, you need to remove the crypto module and use a non-https URL, I believe.
@renatoathaydes please provide a reproducer specific to this issue
Here you go: https://github.com/renatoathaydes/graalvm-js-jlink-demo
It's a very simple problem. I wanted to be able to load and run JS code from within a Java module, however when running with JPMS, JS scripts can only see exported packages from any module. Non-exported members of even the module loading the JS script itself are not visible.
The demo project demonstrates that.
Check the README page for an explanation of how to build/run it.
Everything is working fine, but if you remove the line exports demo.pub
from module-info.java, you will see that the default script, as well as any script you try to run, won't be able to see the JavaType
anymore.
Example successful run (no JPMS):
programming/projects/graalvm-js-jlink-demo master ā 4m ā
ā¶ java -cp build/libs/graalvm-js-jlink-demo-1.0-SNAPSHOT.jar demo.Main
Calling Java type method
Got Java message: hello world
done
Example bad run using JPMS:
programming/projects/graalvm-js-jlink-demo master ā 4m ā
ā¶ java -p build/libs/graalvm-js-jlink-demo-1.0-SNAPSHOT.jar -m "demo.app/demo.Main"
Calling Java type method
Exception in thread "main" TypeError: invokeMember (getMessage) on demo.pub.JavaType@62e6b5c8 failed due to: Unknown identifier: getMessage
at <js> :program(Unnamed:2:64-84)
at org.graalvm.sdk/org.graalvm.polyglot.Context.eval(Context.java:379)
at demo.app/demo.Main.main(Main.java:42)
Perhaps, the ideal solution would be a "flag" in the Context
to tell the JS engine whether to run the JS script with visibility into the module that's loading it or not.
In my case, the JS code I am running is considered as an "internal" part of the module that loads it, so I would want its code to be treated as if it were part of the Java module itself (i.e. having the same visibility, exactly, as the Java classes within the same module - including what it can see from other modules - it currently appears the JS code automatically "imports" everything exported from any module).
@renatoathaydes thanks for the reproducer, I will raise it to javascript team
Issue Description
When using the Java module system, a JS script executed through a
Context
instance cannot see non-exported types and methods from the host, even when loaded from the same module and allowing all access in the given context.Steps to reproduce the issue
Context
instance and allow all access to the host.SomeClass.class.getResource("path")
.Context
and pass a Java object with a type from the same module into it (arg toexecute
).Here's how the
Context
is created:To fully reproduce the problem, you can checkout branch
java-modularization
of my project at https://github.com/renatoathaydes/rawhttp/tree/java-modularizationBuild with
./gradlew jlink
.Run the CLI with the following commands:
The script: https://github.com/renatoathaydes/rawhttp/blob/665f4496db10929f928e5fc40141948f3ae2f384/rawhttp-req-in-edit/src/main/resources/com/athaydes/rawhttp/reqinedit/js/response_handler.js#L4
The Java type it will try to use: https://github.com/renatoathaydes/rawhttp/blob/java-modularization/rawhttp-req-in-edit/src/main/java/com/athaydes/rawhttp/reqinedit/js/internal/JsTestReporter.java
When the script calls
reporter.failure({name: test.name, time: time, error: e});
, it will fail with the following error:I had expected that method call to correctly reach this method:
If I change the module-info.java file to export this package, then it works.
GraalVM environment:
More details
I would expect the script code to have access to the public methods of a Java type from the same module that loaded the script. If that's not the case by design, it should still be possible to explicitly "open" the module's package somehow only for the script (supposing the script has a "module" that's NOT the module loading the script?).
The only workaround that currently works is to export the package containing the Java type to ALL modules. This is undesirable as it effectively breaks the modularity of the Java application.
I realize that when I load a script with
SomeClass.class.getResource("path")
all I get is a byte-stream, hence it's probably impossible for the script to be made to "belong" to the same module asSomeClass
. However, it seems to me that it should be a a basic feature of GraalVM polyglot support to load scripts using a particular Java module, otherwise it becomes very difficult to develop truly polyglot applications using the Java module system. I am, of course, assuming there's no way to do this already as I tried to find this in the docs but couldn't find any mention of the module system in polyglot applications at all (sorry if I am mistaken).