1.1 --- a/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java Tue Jul 08 07:30:45 2014 +0200
1.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java Tue Jul 08 07:50:50 2014 +0200
1.3 @@ -43,6 +43,8 @@
1.4 package net.java.html.json.tests;
1.5
1.6 import java.util.List;
1.7 +import java.util.Timer;
1.8 +import java.util.TimerTask;
1.9 import net.java.html.BrwsrCtx;
1.10 import net.java.html.json.ComputedProperty;
1.11 import net.java.html.json.Function;
1.12 @@ -64,6 +66,7 @@
1.13 @Property(name="latitude", type=double.class)
1.14 })
1.15 public final class KnockoutTest {
1.16 + private KnockoutModel js;
1.17
1.18 @KOTest public void modifyValueAssertChangeInModelOnDouble() throws Throwable {
1.19 Object exp = Utils.exposeHTML(KnockoutTest.class,
1.20 @@ -137,6 +140,38 @@
1.21 }
1.22 }
1.23
1.24 + @KOTest public void modifyValueAssertAsyncChangeInModel() throws Exception {
1.25 + if (js == null) {
1.26 + Utils.exposeHTML(KnockoutTest.class,
1.27 + "<h1 data-bind=\"text: helloMessage\">Loading Bck2Brwsr's Hello World...</h1>\n" +
1.28 + "Your name: <input id='input' data-bind=\"value: name\"></input>\n" +
1.29 + "<button id=\"hello\">Say Hello!</button>\n"
1.30 + );
1.31 +
1.32 + js = Models.bind(new KnockoutModel(), newContext());
1.33 + js.setName("Kukuc");
1.34 + js.applyBindings();
1.35 +
1.36 + String v = getSetInput(null);
1.37 + assert "Kukuc".equals(v) : "Value is really kukuc: " + v;
1.38 +
1.39 + Timer t = new Timer("Set to Jardo");
1.40 + t.schedule(new TimerTask() {
1.41 + @Override
1.42 + public void run() {
1.43 + js.setName("Jardo");
1.44 + }
1.45 + }, 1);
1.46 + }
1.47 +
1.48 + String v = getSetInput(null);
1.49 + if (!"Jardo".equals(v)) {
1.50 + throw new InterruptedException();
1.51 + }
1.52 +
1.53 + Utils.exposeHTML(KnockoutTest.class, "");
1.54 + }
1.55 +
1.56 private static String getSetInput(String value) throws Exception {
1.57 String s = "var value = arguments[0];\n"
1.58 + "var n = window.document.getElementById('input'); \n "
2.1 --- a/json-tck/src/main/java/net/java/html/json/tests/OperationsTest.java Tue Jul 08 07:30:45 2014 +0200
2.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/OperationsTest.java Tue Jul 08 07:50:50 2014 +0200
2.3 @@ -66,19 +66,7 @@
2.4
2.5 @KOTest public void asyncOperation() throws InterruptedException {
2.6 if (js == null) {
2.7 - try {
2.8 - // needs full JVM (not Bck2Brwsr VM) to run
2.9 - Class<?> thread = Class.forName("java.lang.Thread");
2.10 - Thread t = new Thread("Empty");
2.11 - // following operations are supposed to generate SecurityException
2.12 - // on bck2brwsr VM
2.13 - t.setName("Different");
2.14 - t.setDaemon(false);
2.15 - t.interrupt();
2.16 - t.start();
2.17 - } catch (ClassNotFoundException ex) {
2.18 - return;
2.19 - } catch (SecurityException ex) {
2.20 + if (Utils.skipIfNoFullJDK()) {
2.21 return;
2.22 }
2.23
2.24 @@ -104,7 +92,4 @@
2.25 assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
2.26 assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
2.27 }
2.28 -
2.29 -
2.30 -
2.31 }
3.1 --- a/json-tck/src/main/java/net/java/html/json/tests/Utils.java Tue Jul 08 07:30:45 2014 +0200
3.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/Utils.java Tue Jul 08 07:50:50 2014 +0200
3.3 @@ -56,6 +56,22 @@
3.4 public final class Utils {
3.5 private static KnockoutTCK instantiatedTCK;
3.6
3.7 + static boolean skipIfNoFullJDK() {
3.8 + try {
3.9 + Class<?> thread = Class.forName("java.lang.Thread");
3.10 + Thread t = new Thread("Empty");
3.11 + t.setName("Different");
3.12 + t.setDaemon(false);
3.13 + t.interrupt();
3.14 + t.start();
3.15 + } catch (ClassNotFoundException ex) {
3.16 + return true;
3.17 + } catch (SecurityException ex) {
3.18 + return true;
3.19 + }
3.20 + return false;
3.21 + }
3.22 +
3.23 private Utils() {
3.24 }
3.25
4.1 --- a/json/src/main/java/org/apidesign/html/json/spi/Proto.java Tue Jul 08 07:30:45 2014 +0200
4.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Proto.java Tue Jul 08 07:50:50 2014 +0200
4.3 @@ -114,10 +114,15 @@
4.4 *
4.5 * @param propName name of the changed property
4.6 */
4.7 - public void valueHasMutated(String propName) {
4.8 - if (ko != null) {
4.9 - ko.valueHasMutated(propName, null, null);
4.10 - }
4.11 + public void valueHasMutated(final String propName) {
4.12 + context.execute(new Runnable() {
4.13 + @Override
4.14 + public void run() {
4.15 + if (ko != null) {
4.16 + ko.valueHasMutated(propName, null, null);
4.17 + }
4.18 + }
4.19 + });
4.20 }
4.21
4.22 /** Whenever model changes a propertyit should notify the
4.23 @@ -131,10 +136,17 @@
4.24 * @param newValue provides new value of the property
4.25 * @since 0.7.6
4.26 */
4.27 - public void valueHasMutated(String propName, Object oldValue, Object newValue) {
4.28 - if (ko != null) {
4.29 - ko.valueHasMutated(propName, oldValue, newValue);
4.30 - }
4.31 + public void valueHasMutated(
4.32 + final String propName, final Object oldValue, final Object newValue
4.33 + ) {
4.34 + context.execute(new Runnable() {
4.35 + @Override
4.36 + public void run() {
4.37 + if (ko != null) {
4.38 + ko.valueHasMutated(propName, oldValue, newValue);
4.39 + }
4.40 + }
4.41 + });
4.42 }
4.43
4.44 /** Initializes the associated model in the current {@link #getContext() context}.