从JavaScript调用@JSFunction,TypeError:找不到对象的默认值

我正在调用ScriptableObject@JSFunction注释方法

JavaScript文件

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

Java文件

 public class Target extends ScriptableObject { private static final long serialVersionUID = 1L; public List 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"; } } 

但我明白了

 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) 

而且不知道从那里去哪里。 当我不调用addModifier方法时,给定的代码工作,并且在堆栈跟踪中给出错误notFunctionError ,我认为Rhino没有将给定的方法解释为JavaScript函数。

  • OSX 10.8.2
  • Java 7
  • 犀牛1.7R4

可以在此处找到重现错误的完整Maven项目

tl;博士看到这 两种选择。

上述方法的问题是在脚本范围中没有正确设置Target.prototype 。 有关如何在脚本范围中正确定义原型的详细信息,请参阅静态ScriptableObject.defineClass()方法。

您可以使用几种方法为脚本提供Target构造函数。 第一种选择是始终为所有脚本定义Target构造函数。 如果您事先知道Target希望全局可用,则此方法很有效。 这主要归结为以下几点:

 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(); } 

如果您希望脚本作者决定哪些构造函数是必需的,那么第二种方法是为脚本提供defineClass函数。 使用此函数,脚本作者可以在其类路径上“导入”任何可编写脚本的对象(可能超出您想要的范围)。 要向脚本提供defineClass函数,请在输入上下文后执行以下操作:

 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(); } 

然后,JavaScript作者使用Target构造函数,其中包含以下内容:

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

在上述两个分支中,如果您向Target构造函数添加更多内容,我还做了一些其他更改,这些更改可以让您更好。 零参数构造函数不需要@JSConstructor注释。 如果您以后想要一个接受参数的构造函数,那么这个零参数构造函数将被用作原型构造函数,并且您可以在将用于初始化对象的方法上使用@JSConstructor注释。 根据您编写此构造函数方法的方式,在JavaScript中使用new关键字将变得非常重要。

简而言之, Packages.com.acme...语法对于从脚本访问ScriptableObject构造函数没有用。

我通过使用new运算符使其工作(非常相似的代码)。 在你的例子中做

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

也应该工作。