从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(); ...
也应该工作。