How are native functions created in Rhino?

2.8k views Asked by At

I've been looking at the Rhino documentation and source code for a clue as to how to implement my own global native function. This task is however more complicated than I expected it to be.

After reading the code of the implementation of the require function in RingoJS I believe I need to do something along the following lines:

import org.mozilla.javascript.BaseFunction;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.Context;

public class MyGlobalNativeFunction extends BaseFunction {
    public MyGlobalNativeFunction() {}

    public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
        // implementation of my function
    }

    public int getArity() {
        return 1;
    }
}

Am I on the correct track? A step by step walkthrough on how to achieve this would be great.

Also it would be great if I could use Rhino's defineClass function to create my global native function. I'm not too keen on rolling out my own modified version of Rhino just because I want to implement one native function.

2

There are 2 answers

1
Hannes Wallnöfer On BEST ANSWER

I think this should work, and if you only want to implement a single global function it's a good approach. If you want to implement multiple functions or a host object, there are other approaches.

You'd then use something like this to instantiate your function:

scope.defineProperty("myNativeFunction",
                     new MyGlobalNativeFunction(),
                     ScriptableObject.DONTENUM);

Check out RingoGlobal for how this is done (it also shows how to define multiple functions in one sweep without having to creating a class for each). The Rhino examples directory contains some examples of how to create proper host objects with Rhino.

0
Dominik Kunicki On

First of all You need to init your global scope (init all javascript standard object, functions, etc), next to add your function to this scope as Hannes Wallnöfer wrote.

Context cx = Context.enter();  //enter rhino context - bind context with current thread
Scriptable globalScope= cx.initStandardObjects();  //init js standard object in global scope
globalScope.defineProperty("myNativeFunction",
                     new MyGlobalNativeFunction(),
                     ScriptableObject.DONTENUM);

and that's it.

Now to call this function invoke:

Object result = cx.evaluateString(globalScope, "myNativeFunction()", "<cmd>", 1, null);

For more information see: rhino embedding tutorial