0

I'm attempting to put together a basic test framework for a number of JS scripts that I've been provided. These all run on nashorn (JDK 11) without issue in their original habitat. I'm attempting to load and run the scripts myself, and execute tests by comparing input and output.

The issue I'm having is with the format of the scripts. While I know they can be run via Nashorn, I don't have access to the source code that does it, and I'm having a problem grabbing references to all of the functions/methods I need. The source files follow this pattern:

(function () {
    "use strict";

    print("Canary: Here I am inside the root level function");

    function writeLogEntry(message) {
        echo(message);
    }

    return function main(data) {
        print("Canary: Here I am inside main");
        writeLogEntry(data.someVitalStat());
        return true;
    };
})();

I do not have the option to change the source files - I have to use them as-is. The issue has been with getting a reference to functions other than main. I was able to get a ref for main in the following way, which required two passes:

String scriptTextRaw = new String(Files.readAllBytes(Paths.get(location)), StandardCharsets.UTF_8);
var ee = new ScriptEngineManager().getEngineByName("Nashorn");
scriptTextRaw = "var mainfunc = " + scriptTextRaw;
ee.eval(scriptTextRaw);
Object mainRef = ee.get("mainfunc");
// Second eval pass
ee.eval(mainRef.toString());
var mainInvocable = (ScriptObjectMirror)ee.get("main");

// Invoke main function
Object mainResult = mainInvocable.call(myDataObject);

I'm open to better ways to get that main reference. However, the bigger problem is that the anonymous functions encapsulated in the script aren't accessible. Running the above code, I get:

Exception in thread "main" <eval>:3 ReferenceError: "writeLogEntry" is not defined. 

I've tried a few things, e.g.:

Object writeLogEntryRef = (ScriptObjectMirror)ee.get("writeLogEntry"); 

(Both after the first and second eval pass)

But this is unsuccessful. I've also paused the program in the debugger after each eval pass to examine the returned object, but I don't find any references to the other methods.

Can anyone suggest an approach to parsing and running a script formatted like this one? All input is appreciated.

1 Answer 1

0

As so often happens, writing up the question granted me the insight to answer it. The root problem here was my odd two-pass eval approach, which I thought was necessary to grab a reference to the returned main function. Instead, I tried omitting the "var mainref = " string that I had prepended, then invoked call from the result of that first pass:

    ScriptEngine ee = new ScriptEngineManager().getEngineByName("Nashorn");
    String scriptTextRaw = new String(Files.readAllBytes(Paths.get(location)), StandardCharsets.UTF_8);

    Object pass1Result = ee.eval(scriptTextRaw);

    System.out.println(((ScriptObjectMirror) pass1Result).call("main", "blah"));

Using this approach, when the main function is invoked, the calls to other functions succeed.

My initial impression that the first pass didn't yield a usable reference to main was probably borne out of ignorance of Nashorn and the debugger's odd inability to see into ScriptObjectMirror objects.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.