Calling @JSFunction from JavaScript, TypeError: cannot find default value for object

I call @JSFunction annotated ScriptableObject method

Javascript file

 Target = Packages.com.acme.rhino.Target; function evaluate() { var t = Target(); t.addModifier("foobar", 1); return t; } 

Java file

 public class Target extends ScriptableObject { private static final long serialVersionUID = 1L; public List<Modifier> modifiers = new LinkedList<>(); @JSConstructor public Target() { } @JSFunction public void addModifier(final String message, final int value) { modifiers.add(new Modifier(message, value)); } public int getValue() { int sum = 0; for (final Modifier modifier : modifiers) { sum += modifier.getValue(); } return sum; } @Override public String getClassName() { return "Target"; } } 

But I get

 org.mozilla.javascript.EcmaError: TypeError: Cannot find default value for object. at org.mozilla.javascript.ScriptRuntime.constructError(ScriptRuntime.java:3687) at org.mozilla.javascript.ScriptRuntime.constructError(ScriptRuntime.java:3665) at org.mozilla.javascript.ScriptRuntime.typeError(ScriptRuntime.java:3693) at org.mozilla.javascript.ScriptRuntime.typeError1(ScriptRuntime.java:3705) at org.mozilla.javascript.ScriptableObject.getDefaultValue(ScriptableObject.java:976 ) at org.mozilla.javascript.ScriptableObject.getDefaultValue(ScriptableObject.java:895 ) at org.mozilla.javascript.ScriptRuntime.toString(ScriptRuntime.java:761) at org.mozilla.javascript.ScriptRuntime.notFunctionError(ScriptRuntime.java:3774) at org.mozilla.javascript.ScriptRuntime.getPropFunctionAndThisHelper(ScriptRuntime. java:2269) at org.mozilla.javascript.ScriptRuntime.getPropFunctionAndThis(ScriptRuntime. java:2251) at org.mozilla.javascript.optimizer.OptRuntime.callProp0(OptRuntime.java:83) at org.mozilla.javascript.gen.script_5._c_evaluate_1(script:6) at org.mozilla.javascript.gen.script_5.call(script) at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:394) at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3091) at org.mozilla.javascript.gen.script_5.call(script) 

and I donโ€™t know where to go from there. When I do not call the addModifier method, this code works, and given the notFunctionError down error in the stack trace, I think that Rhino does not interpret this method as a JavaScript function.

  • OSX 10.8.2
  • Java 7
  • Rhino 1.7r4

The complete Maven project that reproduces the error can be found here.

+8
java javascript rhino
source share
2 answers

tl; dr see these two alternatives .

The problem with the above approach is that Target.prototype incorrectly configured in the script scope. For more information on how to correctly define prototypes in the script area, see the ScriptableObject.defineClass() Static Method.

You have several alternatives for providing the Target constructor for your scripts. The first alternative is to always define the Target constructor for all scripts. This works well if you know in advance that you want Target be available worldwide. It basically boils down to the following:

 final Context context = Context.enter(); try { final ScriptableObject scope = context.initStandardObjects(); ScriptableObject.defineClass(scope, Target.class, false, true); context.evaluateString(scope, script, "script", 1, null); // etc. } finally { Context.exit(); } 

If instead you want the script author to determine which constructors are needed, the second alternative is to provide the defineClass function for the script. Using this function, script authors can "import" any script objects into their class path (which may be more than you want to allow). To provide the defineClass functions for scripts, do the following after entering the context:

 final Context context = Context.enter(); try { final ScriptableObject scope = context.initStandardObjects(); scope.defineFunctionProperties( new String[] {"defineClass"}, Global.class, ScriptableObject.DONTENUM); context.evaluateString(scope, script, "script", 1, null); // etc. } finally { Context.exit(); } 

And then the JavaScript author uses the Target constructor with the following:

 defineClass("com.acme.rhino.Target"); // whatever `getClassName()` returns is now available var target = new Target(); 

In both of the above branches I made a couple of other changes that would improve you if you add more to the Target constructor. The null argument constructor does not need the @JSConstructor annotation. If you later want to have a constructor that takes arguments, this null argument constructor will be used as the prototype constructor, and you can use the @JSConstructor annotation for the method that will be used to initialize your object. Depending on how you create this constructor method, it becomes important to use the new keyword in your JavaScript.

In short, the syntax of Packages.com.acme... not useful for accessing ScriptableObject constructors from scripts.

+3
source share

I get it working (very similar code) with a new operator. In your example, do

  function evaluate() { var t = new Target(); ... 

should also work.

0
source share

All Articles