2013-01-28 19 views
8

Tôi gọi một @JSFunction phương pháp chú thích của một ScriptableObjectCalling @JSFunction từ JavaScript, Lỗi Loại: Không thể tìm thấy giá trị mặc định cho đối tượng

nộp JavaScript

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

Nhưng tôi nhận được

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) 

và không biết phải đi đâu từ đó. Khi tôi không gọi phương thức addModifier mã đã cho hoạt động và được đưa ra lỗi notFunctionError trong theo dõi ngăn xếp, tôi nghĩ rằng tê giác không giải thích phương thức đã cho dưới dạng hàm JavaScript.

  • OSX 10.8.2
  • Java 7
  • Rhino 1.7R4

Toàn bộ dự án Maven rằng tái tạo các lỗi có thể được tìm thấy here

Trả lời

3

tl; dr thấy thesetwo lựa chọn thay thế.

Sự cố với cách tiếp cận ở trên là Target.prototype không được thiết lập đúng trong phạm vi tập lệnh. Xem phương thức tĩnh ScriptableObject.defineClass() để biết chi tiết về cách xác định đúng nguyên mẫu trong phạm vi tập lệnh.

Bạn có một vài lựa chọn thay thế để cung cấp hàm tạo Target cho tập lệnh của mình. first alternative sẽ luôn xác định hàm tạo Target cho tất cả các tập lệnh. Điều này hoạt động tốt nếu bạn biết trước thời hạn mà bạn muốn Target khả dụng trên toàn cầu. Này về cơ bản đi xuống như sau:

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

Nếu thay vào đó bạn muốn tác giả kịch bản để quyết định nhà thầu là cần thiết, second alternative là để cung cấp các chức năng để defineClass kịch bản. Với chức năng này, tác giả kịch bản có thể "nhập" bất kỳ đối tượng có thể chạy được trên đường dẫn lớp của chúng (có thể nhiều hơn mức bạn muốn cho phép). Để cung cấp các defineClass chức năng để kịch bản, làm như sau sau khi vào bối cảnh:

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

Và sau đó, tác giả JavaScript tận dụng các nhà xây dựng Target như sau:

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

Trong cả hai trên các nhánh, tôi đã thực hiện một vài thay đổi khác giúp bạn thiết lập tốt hơn nếu bạn thêm nhiều hơn vào hàm tạo Target. Hàm tạo đối số 0 không cần chú thích @JSConstructor. Nếu sau này bạn muốn có một hàm tạo chấp nhận đối số, hàm tạo đối số 0 này sẽ được sử dụng làm hàm tạo nguyên mẫu và bạn có thể sử dụng chú thích @JSConstructor trên phương thức sẽ được sử dụng để khởi tạo đối tượng của bạn. Tùy thuộc vào cách bạn tạo phương thức khởi tạo này, nó sẽ trở nên quan trọng để sử dụng từ khóa new trong JavaScript của bạn.

Tóm lại, cú pháp Packages.com.acme...không hữu ích để truy cập vào ScriptableObject hàm tạo từ tập lệnh.

+3

Chỉ cần lưu ý rằng các liên kết github của bạn không hoạt động nữa. – lycono

0

Tôi làm cho nó hoạt động (mã rất giống nhau) bằng cách sử dụng toán tử mới. Trong ví dụ của bạn làm

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

cũng sẽ hoạt động.