Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Would expect that access to host classes static fields can be inherited from interfaces and base classes #10025

Open
in-fke opened this issue Nov 4, 2024 · 1 comment
Assignees
Labels

Comments

@in-fke
Copy link

in-fke commented Nov 4, 2024

Describe GraalVM and your environment :

  • GraalVM version or commit id if built from source: 23.0.4
  • CE or EE: CE
  • JDK version: OpenJDK Runtime Environment Corretto-17.0.10.7.1 (build 17.0.10+7-LTS)
  • OS and OS Version: Windows
  • Architecture: amd64
  • The output of java -Xinternalversion:
OpenJDK 64-Bit Server VM (17.0.10+7-LTS) for windows-amd64 JRE (17.0.10+7-LTS), built on Jan 10 2024 22:11:07 by "Administrator" with
MS VC++ 16.10 / 16.11 (VS2019)

Have you verified this issue still happens when using the latest snapshot?
No, but the source code still looks the same.

Describe the issue
Access to host classes static fields is not inherited from interfaces or base classes.
In the given example, in Java and Rhino, "Implementation.INTERFACE_CONSTANT" would yield "X", in Graal, it yields "undefined".

Code snippet or code repository that reproduces the issue

    /**
     * The Interface Interface.
     */
    public interface Interface {
        
        /** The constant. */
        public static final String INTERFACE_CONSTANT = "X";
    }
    
    /**
     * The Class BaseImplementation.
     */
    public static class BaseImplementation {
        
        /** The Constant BASE_CONSTANT. */
        public static final String BASE_CONSTANT = "Y";
    }    
    
    /**
     * The Class Implementation.
     */
    public static class Implementation extends BaseImplementation implements Interface {
        
    }
    
    /**
     * Test.
     */
    @Test
    public void test() {
        try (Context context = Context.newBuilder("js")
                .allowHostAccess(org.graalvm.polyglot.HostAccess.ALL)
                .allowHostClassLookup(className -> true) // Allow access to all classes
                .build()) {

            Value result;
            
            // yields null, yet in Java, "Implementation.INTERFACE_CONSTANT" yields "X"
            result = context.eval("js", "(Java.type('" + Implementation.class.getName() + "')).INTERFACE_CONSTANT");
            // assertEquals(Implementation.INTERFACE_CONSTANT, result.asString());
            assertNull(result.asString());

            // yields null, yet in Java, "Implementation.BASE_CONSTANT" yields "Y"
            result = context.eval("js", "(Java.type('" + Implementation.class.getName() + "')).BASE_CONSTANT");
            // assertEquals(Implementation.BASE_CONSTANT, result.asString());
            assertNull(result.asString());            
            
            // yields "X", since we are accessing the interface directly
            result = context.eval("js", "(Java.type('" + Interface.class.getName() + "')).INTERFACE_CONSTANT");
            assertEquals("X", result.asString());            
            
            // yields "Y", since we are accessing the base class directly
            result = context.eval("js", "(Java.type('" + BaseImplementation.class.getName() + "')).BASE_CONSTANT");
            assertEquals("Y", result.asString());            
            
        }        
    }

Steps to reproduce the issue
See example.
The code to "blame" seems to be here:
https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassDesc.java#L354

While collectPublicMethods makes use of allowsAccessInheritance and inherits methods,
the method collectPublicFields does not. See

                        // do not inherit static fields
                        if (f.getDeclaringClass() == type && hostAccess.allowsAccess(f)) {
                            staticFieldMap.put(f.getName(), HostFieldDesc.unreflect(lookup, f));
                        }

Expected behavior
Along the lines of Java and Rhino, one would expect that public static fields are also inherited from Interfaces and Superclasses.
If behaviour would be broken by simply changing the code, mabye introducing allowsAccessFieldInheritance would help to introduce this functionality while staying backwards compatible.

@in-fke in-fke added the truffle label Nov 4, 2024
@in-fke
Copy link
Author

in-fke commented Nov 5, 2024

Or rather allowsFieldAccessInheritance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants