1.1 --- a/boot/src/main/java/net/java/html/js/JavaScriptBody.java Mon Mar 03 15:14:46 2014 +0100
1.2 +++ b/boot/src/main/java/net/java/html/js/JavaScriptBody.java Tue Mar 04 10:12:22 2014 +0100
1.3 @@ -93,4 +93,6 @@
1.4 * syntax
1.5 */
1.6 public boolean javacall() default false;
1.7 +
1.8 + public boolean wait4js() default true;
1.9 }
2.1 --- a/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java Mon Mar 03 15:14:46 2014 +0100
2.2 +++ b/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java Tue Mar 04 10:12:22 2014 +0100
2.3 @@ -52,6 +52,8 @@
2.4 import java.util.Map;
2.5 import java.util.Set;
2.6 import java.util.concurrent.Executor;
2.7 +import java.util.logging.Level;
2.8 +import java.util.logging.Logger;
2.9 import net.java.html.js.JavaScriptBody;
2.10 import org.netbeans.html.boot.impl.FnContext;
2.11
2.12 @@ -190,6 +192,10 @@
2.13 return FnContext.activate(p);
2.14 }
2.15
2.16 + public void invokeLater(Object thiz, Object... args) throws Exception {
2.17 + invoke(this, args);
2.18 + }
2.19 +
2.20 /** Invokes the defined function with specified <code>this</code> and
2.21 * appropriate arguments.
2.22 *
3.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java Mon Mar 03 15:14:46 2014 +0100
3.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java Tue Mar 04 10:12:22 2014 +0100
3.3 @@ -467,31 +467,38 @@
3.4 FindInMethod.super.visitInsn(Opcodes.AASTORE);
3.5 }
3.6
3.7 - super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
3.8 - "org/apidesign/html/boot/spi/Fn", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
3.9 - );
3.10 - switch (sv.returnType.getSort()) {
3.11 - case Type.VOID:
3.12 - super.visitInsn(Opcodes.RETURN);
3.13 - break;
3.14 - case Type.ARRAY:
3.15 - case Type.OBJECT:
3.16 - super.visitTypeInsn(Opcodes.CHECKCAST, sv.returnType.getInternalName());
3.17 - super.visitInsn(Opcodes.ARETURN);
3.18 - break;
3.19 - case Type.BOOLEAN:
3.20 - super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");
3.21 - super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
3.22 - "java/lang/Boolean", "booleanValue", "()Z"
3.23 - );
3.24 - super.visitInsn(Opcodes.IRETURN);
3.25 - break;
3.26 - default:
3.27 - super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Number");
3.28 - super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
3.29 - "java/lang/Number", sv.returnType.getClassName() + "Value", "()" + sv.returnType.getDescriptor()
3.30 - );
3.31 - super.visitInsn(sv.returnType.getOpcode(Opcodes.IRETURN));
3.32 + if (fia.wait4js) {
3.33 + super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
3.34 + "org/apidesign/html/boot/spi/Fn", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
3.35 + );
3.36 + switch (sv.returnType.getSort()) {
3.37 + case Type.VOID:
3.38 + super.visitInsn(Opcodes.RETURN);
3.39 + break;
3.40 + case Type.ARRAY:
3.41 + case Type.OBJECT:
3.42 + super.visitTypeInsn(Opcodes.CHECKCAST, sv.returnType.getInternalName());
3.43 + super.visitInsn(Opcodes.ARETURN);
3.44 + break;
3.45 + case Type.BOOLEAN:
3.46 + super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");
3.47 + super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
3.48 + "java/lang/Boolean", "booleanValue", "()Z"
3.49 + );
3.50 + super.visitInsn(Opcodes.IRETURN);
3.51 + break;
3.52 + default:
3.53 + super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Number");
3.54 + super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
3.55 + "java/lang/Number", sv.returnType.getClassName() + "Value", "()" + sv.returnType.getDescriptor()
3.56 + );
3.57 + super.visitInsn(sv.returnType.getOpcode(Opcodes.IRETURN));
3.58 + }
3.59 + } else {
3.60 + super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
3.61 + "org/apidesign/html/boot/spi/Fn", "invokeLater", "(Ljava/lang/Object;[Ljava/lang/Object;)V"
3.62 + );
3.63 + super.visitInsn(Opcodes.RETURN);
3.64 }
3.65 if (hasCode) {
3.66 super.visitLabel(noPresenter);
3.67 @@ -522,6 +529,7 @@
3.68 List<String> args = new ArrayList<String>();
3.69 String body;
3.70 boolean javacall = false;
3.71 + boolean wait4js = true;
3.72
3.73 public FindInAnno() {
3.74 super(Opcodes.ASM4);
3.75 @@ -537,6 +545,10 @@
3.76 javacall = (Boolean) value;
3.77 return;
3.78 }
3.79 + if (name.equals("wait4js")) { // NOI18N
3.80 + wait4js = (Boolean) value;
3.81 + return;
3.82 + }
3.83 assert name.equals("body");
3.84 body = (String) value;
3.85 }
4.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/JavaScriptProcesor.java Mon Mar 03 15:14:46 2014 +0100
4.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JavaScriptProcesor.java Tue Mar 04 10:12:22 2014 +0100
4.3 @@ -129,6 +129,9 @@
4.4 if (params.size() != arr.length) {
4.5 msg.printMessage(Diagnostic.Kind.ERROR, "Number of args arguments does not match real arguments!", e);
4.6 }
4.7 + if (!jsb.wait4js() && ee.getReturnType().getKind() != TypeKind.VOID) {
4.8 + msg.printMessage(Diagnostic.Kind.ERROR, "Methods that don't wait for JavaScript to finish must return void!", e);
4.9 + }
4.10 if (!jsb.javacall() && jsb.body().contains(".@")) {
4.11 msg.printMessage(Diagnostic.Kind.WARNING, "Usage of .@ usually requires javacall=true", e);
4.12 }
5.1 --- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java Mon Mar 03 15:14:46 2014 +0100
5.2 +++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java Tue Mar 04 10:12:22 2014 +0100
5.3 @@ -45,6 +45,7 @@
5.4 import net.java.html.js.JavaScriptBody;
5.5 import net.java.html.js.JavaScriptResource;
5.6 import net.java.html.json.Model;
5.7 +import org.apidesign.html.boot.spi.Fn;
5.8 import org.apidesign.html.json.spi.FunctionBinding;
5.9 import org.apidesign.html.json.spi.PropertyBinding;
5.10
5.11 @@ -59,7 +60,9 @@
5.12 */
5.13 @JavaScriptResource("knockout-2.2.1.js")
5.14 final class Knockout {
5.15 - @JavaScriptBody(args = { "model", "prop", "oldValue", "newValue" }, body =
5.16 + @JavaScriptBody(args = { "model", "prop", "oldValue", "newValue" },
5.17 + wait4js = false,
5.18 + body =
5.19 "if (model) {\n"
5.20 + " var koProp = model[prop];\n"
5.21 + " if (koProp && koProp['valueHasMutated']) {\n"
5.22 @@ -75,15 +78,17 @@
5.23 Object model, String prop, Object oldValue, Object newValue
5.24 );
5.25
5.26 - @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);\n")
5.27 + @JavaScriptBody(args = { "bindings" }, wait4js = false, body =
5.28 + "ko.applyBindings(bindings);\n"
5.29 + )
5.30 native static void applyBindings(Object bindings);
5.31
5.32 @JavaScriptBody(
5.33 javacall = true,
5.34 - args = {"model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
5.35 - body
5.36 - = "var ret = {};\n"
5.37 - + "ret['ko-fx.model'] = model;\n"
5.38 + wait4js = false,
5.39 + args = {"ret", "model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
5.40 + body =
5.41 + "ret['ko-fx.model'] = model;\n"
5.42 + "function koComputed(name, readOnly, value, prop) {\n"
5.43 + " function realGetter() {\n"
5.44 + " try {\n"
5.45 @@ -126,14 +131,50 @@
5.46 + "for (var i = 0; i < funcNames.length; i++) {\n"
5.47 + " koExpose(funcNames[i], funcArr[i]);\n"
5.48 + "}\n"
5.49 - + "return ret;\n"
5.50 )
5.51 - static native Object wrapModel(
5.52 - Object model,
5.53 + private static native void wrapImpl(
5.54 + Object jsObject, Object model,
5.55 String[] propNames, boolean[] propReadOnly, Object propValues, PropertyBinding[] propArr,
5.56 String[] funcNames, FunctionBinding[] funcArr
5.57 );
5.58
5.59 + @JavaScriptBody(args = { "cnt" }, body =
5.60 + "var ret = new Array();\n"
5.61 + + "while (cnt-- > 0) {\n"
5.62 + + " ret.push(new Object());\n"
5.63 + + "}\n"
5.64 + + "return ret;\n"
5.65 + )
5.66 + private static native Object[] newObjs(int cnt);
5.67 +
5.68 + private static Fn.Presenter prev;
5.69 + private static int objCounter;
5.70 + private static Object[] objs;
5.71 +
5.72 + private static synchronized Object createJSObj() {
5.73 + if (prev != Fn.activePresenter()) {
5.74 + objs = null;
5.75 + }
5.76 + if (objs == null || objs.length <= objCounter) {
5.77 + objs = newObjs(128);
5.78 + objCounter = 0;
5.79 + }
5.80 + return objs[objCounter++];
5.81 + }
5.82 +
5.83 + static Object wrapModel(
5.84 + Object model,
5.85 + String[] propNames, boolean[] propReadOnly, Object propValues, PropertyBinding[] propArr,
5.86 + String[] funcNames, FunctionBinding[] funcArr
5.87 + ) {
5.88 + Object js = createJSObj();
5.89 + wrapImpl(js, model, propNames, propReadOnly, propValues, propArr, funcNames, funcArr);
5.90 + return js;
5.91 + }
5.92 +
5.93 @JavaScriptBody(args = { "o" }, body = "return o['ko-fx.model'] ? o['ko-fx.model'] : o;")
5.94 - static native Object toModel(Object wrapper);
5.95 + private static native Object toModelImpl(Object wrapper);
5.96 + static Object toModel(Object wrapper) {
5.97 + return toModelImpl(wrapper);
5.98 + }
5.99 }