mryan
mryan

Reputation: 392

How can I invoke a method from Nashorn with a webpack js file?

If I run following code I get output:

simple.js

Exception in thread "main" java.lang.NoSuchMethodException: No such function definition

How can I invoke the 'definition' function in my webpack js file using invokeFunction?

Java main:

public static void main(String[] args) throws ScriptException, NoSuchMethodException {
        ScriptEngine jsEngine = new ScriptEngineManager().getEngineByName("nashorn");
        
        Compilable jsCompilable = (Compilable) jsEngine;
        CompiledScript jsScript = jsCompilable.compile(getBasicScript());
        
        ScriptContext scriptCtxt = jsEngine.getContext();
        Bindings engineScope = scriptCtxt.getBindings(ScriptContext.ENGINE_SCOPE);
        jsScript.eval(engineScope);
        
        Invocable jsInvocable = (Invocable) jsEngine;
        jsInvocable.invokeFunction("definition", "mark");
    }    

Webpack file called in getBasicScript():

/******/ (function(modules) { // webpackBootstrap
/******/    // The module cache
/******/    var installedModules = {};

/******/    // The require function
/******/    function __webpack_require__(moduleId) {

/******/        // Check if module is in cache
/******/        if(installedModules[moduleId])
/******/            return installedModules[moduleId].exports;

/******/        // Create a new module (and put it into the cache)
/******/        var module = installedModules[moduleId] = {
/******/            exports: {},
/******/            id: moduleId,
/******/            loaded: false
/******/        };

/******/        // Execute the module function
/******/        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/        // Flag the module as loaded
/******/        module.loaded = true;

/******/        // Return the exports of the module
/******/        return module.exports;
/******/    }


/******/    // expose the modules object (__webpack_modules__)
/******/    __webpack_require__.m = modules;

/******/    // expose the module cache
/******/    __webpack_require__.c = installedModules;

/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "";

/******/    // Load entry module and return exports
/******/    return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports) {

    print('simple.js'); 

    function definition(name) { 
        print('Hello: ' + name); 
    }

/***/ }
/******/ ]);

Upvotes: 0

Views: 1697

Answers (2)

user2691789
user2691789

Reputation: 11

Here is another way to use a webpack built module using invokeMethod instead of invokeFunction:

val root = engine.eval("root") // 'root' being your output.library
engine.invokeMethod(root, "methodName", ...)

Upvotes: 1

Hannes Wallnöfer
Hannes Wallnöfer

Reputation: 906

The problem seems to be that the definition function is not declared in the top level scope. It is declared inside an anonymous function (which is itself passed as argument to the "main" function). Regardless of what happens in the main function, the definition function is practically private to its enclosing function (starting at line 45).

If you want to call a function through the Invocable interface, it must be declared globally (in top-level scope) either as a function declaration or a var-statement.

Upvotes: 1

Related Questions