Search code examples
javascriptjavadatenashorn

Supply JavaScript date to Nashorn script


I am working on an API in Java that allows users to write scripts and access a specific set of methods that are passed in (in the form of an API object) by the Nashorn script engine.

I want to, in the JavaScript, call a function getDate(), which will return some arbitrary date (as a native JavaScript date) that's provided from the Java side.

I have tried simply putting an org.java.util.Date on the API object, but that won't behave like a JS date. The goal is to make this as simple as possible for end-users who are experienced with JS.

Java Example:

public class MyAPI {
    public void log(String text){
        System.out.println(text);
    }

    public Date getDate(){
        // Return something that converts to a native-JS date
    }

    public static void main(){
        // MyClassFilter implements Nashorn's ClassFilter
        ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine(new MyClassFilter());
        ((Invokable) engine).invokeFunction("entryPoint", new MyAPI());
    }

JavaScript example

function entryPoint(myApi){
    var date = myApi.getDate();
    myApi.log(date.getMinutes());
}

Solution

  • The Nashorn engine has objects it uses internally which represent the Javascript objects. As you have guessed the java.util.Date != new Date() (in javascript). The engine uses a class called jdk.nashorn.internal.objects.NativeDate to represent its JS date.

    If I were building this out I would not have the NativeDate constructed in the Java but instead have a wrapper in Javascript for the MyApi object which would contain a few other native JS methods, such as getDate().

    var MYAPI_JAVASCRIPT = {
        log: function() {
            print(arguments);
        },
        getDate: function() {
            return new Date();
        }
    }
    

    You could then pass that object as the method parameter.


    However if your really set on using the NativeDate in your Java code then you can construct one like so:

    public NativeDate getDate() {
        return (NativeDate) NativeDate.construct(true, null);
    }