oracle / graal

GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀
https://www.graalvm.org
Other
20.21k stars 1.62k forks source link

[GR-46209] JS style HashMap access not working with Integer keys #6459

Open OrkValerian opened 1 year ago

OrkValerian commented 1 year ago

Hi,

We have a java application that runs on GraalVM 22.3.0 (Java 17.0.5)/Debian 11 bullseye AMD64, and we include a "low-code" module that allows us to write JS batch scripts that can be executed by a user of the application or scheduled at fixed rate.

I have a strange behavior with Java Maps, when using a JS-like syntax to access the map (the polyglot Context is configured with allowMapAccess to true). Map access do not behave the same when using String or integer as key, everything works fine with String keys, but with integer keys, we get a null anytime we want to retrieve a value. I don't know yet if it is a real bug or is due to a misunderstanding of my part, and for the time being, I will use a String representation of my integers, but this heterogeneous behaviour does not feel "clean" to me.

Here is a simple script to reproduce the behaviour (MOQ.log() is part of our API, used to log stuff):

const MapClass = Java.type("java.util.HashMap");

const stringMap = new MapClass();

stringMap.put("k1", "V1");
stringMap.put("k2", "V2");

MOQ.log("stringMap value for key 'k1'")
MOQ.log(stringMap["k1"]);
const intMap = new MapClass();

intMap.put(1, "V1")
intMap.put(2, "V2")

MOQ.log("intMap value for key 1")
MOQ.log(intMap[1]);

This script yields the following output:

stringMap value for key 'k1'
V1
intMap value for key 1
null

Thanks for any help you may provide

oubidar-Abderrahim commented 1 year ago

Hi, Thank you for reporting this issue, could you please verify with the latest version of 22.3.2? if the issue is still there, please share a full reproducer code with steps to reproduce. Thank you

OrkValerian commented 1 year ago

Hi, thanks for your reply.

I tested against latest version 22.3.2 with the same behavior.

Here is a reproducer code in java:

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.HostAccess;

import java.util.*;

class JsMapBugTest {
    static String JS_CODE = """
            const MapClass = Java.type("java.util.HashMap");

            const stringMap = new MapClass();

            stringMap.put("k1", "V1");
            stringMap.put("k2", "V2");

            console.log("stringMap value for key 'k1' (expecting 'v1')")
            console.log(stringMap["k1"]);
            const intMap = new MapClass();

            intMap.put(1, "V1")
            intMap.put(2, "V2")

            console.log("intMap value for key 1 (expecting 'v1')")
            console.log(intMap[1]);""";

    private static final Set<String> ALLOWED_CLASS_LOOKUP = Set.of(
            ArrayList.class.getName(),
            HashMap.class.getName(),
            Calendar.class.getName()
    );

    public static void main(String[] args) {
        System.out.println("JS Map bug test");
        try (Context context = Context.newBuilder("js")
                .allowHostClassLookup(ALLOWED_CLASS_LOOKUP::contains)
                .allowHostAccess(HostAccess.newBuilder().
                        allowPublicAccess(true).
                        allowAllImplementations(true).
                        allowAllClassImplementations(true).
                        allowArrayAccess(true).allowListAccess(true).allowBufferAccess(true).
                        allowIterableAccess(true).allowIteratorAccess(true).allowMapAccess(true).
                        allowAccessInheritance(true).
                        build())
                .build()) {
            context.eval("js", JS_CODE);
        }
    }
}

This code outputs the following:

JS Map bug test
stringMap value for key 'k1' (expecting 'v1')
V1
intMap value for key 1 (expecting 'v1')
undefined
oubidar-Abderrahim commented 1 year ago

Tracked internally on GR 46209