8

私はの@JSFunction注釈付きメソッドを呼び出していますScriptableObject

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<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";
    }
}

しかし、私は得る

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
  • Rhino 1.7R4

エラーを再現する完全なMavenプロジェクトはここにあります

4

2 に答える 2

3

tl;drこれらの 2つの選択肢を参照してください。

上記のアプローチの問題は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();
}

代わりに、スクリプトの作成者に必要なコンストラクターを決定させたい場合、2番目の方法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、オブジェクトの初期化に使用されるメソッドのアノテーションを使用できます。このコンストラクターメソッドの作成方法によってはnew、JavaScriptでキーワードを使用することが重要になります。

つまり、このPackages.com.acme...構文は、スクリプトからコンストラクターにアクセスするのに役立ちません。ScriptableObject

于 2013-01-29T17:34:03.863 に答える
0

new演算子を使用して、動作させます(非常によく似たコード)。あなたの例では

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

同様に機能するはずです。

于 2016-09-26T20:42:21.843 に答える