You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by jt...@apache.org on 2019/02/15 19:57:23 UTC

[incubator-netbeans-html4j] branch master updated (857a495 -> ef25d5b)

This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git.


    from 857a495  Bugfixing behavior of subList().toArray
     new 000668d  Using the same model in two views with ko4j binding fails
     new 8c5f0bb  Create the objs in constructor
     new 62410a4  Initialize on demand
     new 0500441  Keep JavaScript object per presenter
     new e31a1a2  Keep js() internal to Knockout instance
     new 8cb4dbf  Notify change in all known presenters
     new 16f7f46  Caching needs to be done per presenter
     new b8a57f2  Testing dependency on JFXPanel
     new af4a741  Encapsulate the multi-js-object operations into separate class
     new 220254b  Avoid usage of HashMap
     new 4da1644  Testing behavior of MapObjs support
     new 68228fa  Use round-robin cache
     new e057d5f  Use Model.asList instead of HashSet in the TCK
     new 4ec660c  Moving exposed properties check into own class
     new ef25d5b  Documenting usage of model in two views

The 15 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../java/html/js/tests/ExposedPropertiesTest.java  | 168 ++++++++++++++++++++
 .../net/java/html/js/tests/JavaScriptBodyTest.java | 152 +-----------------
 .../org/netbeans/html/json/tck/JavaScriptTCK.java  |   3 +-
 ko4j/pom.xml                                       |   5 +
 .../java/org/netbeans/html/ko4j/CacheObjs.java     |  68 ++++++++
 .../main/java/org/netbeans/html/ko4j/KOTech.java   |  49 +-----
 .../main/java/org/netbeans/html/ko4j/Knockout.java |  91 +++++++++--
 .../main/java/org/netbeans/html/ko4j/MapObjs.java  | 118 ++++++++++++++
 .../org/netbeans/html/ko4j/DoubleViewTest.java     | 173 +++++++++++++++++++++
 .../java/org/netbeans/html/ko4j/MapObjsTest.java   |  84 ++++++++++
 .../resources/org/netbeans/html/ko4j/double.html   |   7 +-
 pom.xml                                            |   6 +
 src/main/javadoc/overview.html                     |   9 +-
 13 files changed, 728 insertions(+), 205 deletions(-)
 create mode 100644 json-tck/src/main/java/net/java/html/js/tests/ExposedPropertiesTest.java
 create mode 100644 ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java
 create mode 100644 ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java
 create mode 100644 ko4j/src/test/java/org/netbeans/html/ko4j/DoubleViewTest.java
 create mode 100644 ko4j/src/test/java/org/netbeans/html/ko4j/MapObjsTest.java
 copy boot-fx/src/test/resources/org/netbeans/html/boot/fx/empty.html => ko4j/src/test/resources/org/netbeans/html/ko4j/double.html (77%)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 04/15: Keep JavaScript object per presenter

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit 050044109ba848857b20d34a328cc9e1cbbcf2bd
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Tue Feb 12 19:59:33 2019 +0100

    Keep JavaScript object per presenter
---
 ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
index 9222296..70c3287 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
@@ -18,9 +18,12 @@
  */
 package org.netbeans.html.ko4j;
 
+import java.util.HashMap;
+import java.util.Map;
 import net.java.html.js.JavaScriptBody;
 import net.java.html.js.JavaScriptResource;
 import net.java.html.json.Model;
+import org.netbeans.html.boot.spi.Fn;
 import org.netbeans.html.json.spi.FunctionBinding;
 import org.netbeans.html.json.spi.PropertyBinding;
 
@@ -55,7 +58,7 @@ final class Knockout  {
 
     private PropertyBinding[] props;
     private FunctionBinding[] funcs;
-    private Object js;
+    private final Map<Fn.Presenter,Object> objs = new HashMap<Fn.Presenter, Object>();
     private Object copyFrom;
     private Object strong;
 
@@ -73,8 +76,10 @@ final class Knockout  {
     }
 
     final Object js() {
+        Object js = objs.get(Fn.activePresenter());
         if (js == null) {
-            this.js = initObjs(copyFrom);
+            js = initObjs(copyFrom);
+            objs.put(Fn.activePresenter(), js);
         }
         return js;
     }
@@ -110,8 +115,8 @@ final class Knockout  {
             if (ko == null) {
                 return;
             }
-            clean(ko.js);
-            ko.js = null;
+            Object js = ko.objs.remove(Fn.activePresenter());
+            clean(js);
             ko.props = null;
             ko.funcs = null;
         }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 15/15: Documenting usage of model in two views

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit ef25d5b311370e4f6e38891bf7a444697331bd4d
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Fri Feb 15 07:13:01 2019 +0100

    Documenting usage of model in two views
---
 src/main/javadoc/overview.html | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/main/javadoc/overview.html b/src/main/javadoc/overview.html
index 21926b2..13f6c70 100644
--- a/src/main/javadoc/overview.html
+++ b/src/main/javadoc/overview.html
@@ -112,7 +112,8 @@ $ mvn -f client/pom.xml process-classes exec:exec
         
         
         <h3>Try it</h3>
-        <p>And finally, if you want to see this API in action, look no further, here's an example
+        <p>And finally, if you want to see this API in action, look no further, here's 
+            <a target="_blank" href="https://github.com/jtulach/minesweeper">an example</a>
             application running with the <a href="https://github.com/jtulach/bck2brwsr/" target="_blank">Bck2Brwsr VM</a> directly in your browser.</p>
                 <script type="text/html" id="field">
             <style type="text/css">
@@ -162,6 +163,12 @@ $ mvn -f client/pom.xml process-classes exec:exec
             vm.loadClass('org.apidesign.demo.minesweeper.MainBrwsr');
         </script>
         
+        <h3>New in version 1.6.1</h3>
+        <p>
+            One model instance can be used in two views
+            (<a target="_blank" href="https://github.com/apache/incubator-netbeans-html4j/pull/14">PR #14</a>).
+        </p>
+
         <h3>New in version 1.6</h3>
 
         <p>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 06/15: Notify change in all known presenters

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit 8cb4dbf8dab3d1a429595ce2898a01ea454e5977
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Thu Feb 14 05:33:50 2019 +0100

    Notify change in all known presenters
---
 .../main/java/org/netbeans/html/ko4j/Knockout.java | 29 ++++++++++++++++-
 .../org/netbeans/html/ko4j/DoubleViewTest.java     | 38 +++++++++++++++-------
 2 files changed, 55 insertions(+), 12 deletions(-)

diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
index f83534f..ac91bcc 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
@@ -18,8 +18,11 @@
  */
 package org.netbeans.html.ko4j;
 
+import java.io.Closeable;
+import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.Executor;
 import net.java.html.js.JavaScriptBody;
 import net.java.html.js.JavaScriptResource;
 import net.java.html.json.Model;
@@ -144,7 +147,31 @@ final class Knockout  {
         funcs[index].call(data, ev);
     }
 
-    final void valueHasMutated(String propertyName, Object oldValue, Object newValue) {
+    final void valueHasMutated(final String propertyName, Object oldValue, Object newValue) {
+        for (Map.Entry<Fn.Presenter, Object> e : objs.entrySet()) {
+            Fn.Presenter p = e.getKey();
+            final Object o = e.getValue();
+            if (p != Fn.activePresenter()) {
+                if (p instanceof Executor) {
+                    ((Executor) p).execute(new Runnable() {
+                        @Override
+                        public void run() {
+                            valueHasMutated(o, propertyName, null, null);
+                        }
+                    });
+                } else {
+                    Closeable c = Fn.activate(p);
+                    try {
+                        valueHasMutated(o, propertyName, null, null);
+                    } finally {
+                        try {
+                            c.close();
+                        } catch (IOException ex) {
+                        }
+                    }
+                }
+            }
+        }
         valueHasMutated(js(), propertyName, oldValue, newValue);
     }
 
diff --git a/ko4j/src/test/java/org/netbeans/html/ko4j/DoubleViewTest.java b/ko4j/src/test/java/org/netbeans/html/ko4j/DoubleViewTest.java
index 7232bc2..83a48ed 100644
--- a/ko4j/src/test/java/org/netbeans/html/ko4j/DoubleViewTest.java
+++ b/ko4j/src/test/java/org/netbeans/html/ko4j/DoubleViewTest.java
@@ -41,20 +41,24 @@ import org.testng.annotations.Test;
     @Property(name = "message", type = String.class)
 })
 public class DoubleViewTest {
+    private static String set;
+
     @Function
     static void change(DoubleView model) {
-        model.setMessage("Modified");
+        assertNotNull(set);
+        model.setMessage(set);
+        set = null;
     }
-    
+
     DoubleView doubleView;
     private WebView view1;
     private WebView view2;
-    
+
     @BeforeMethod
     public void initializeViews() throws Exception {
         final JFXPanel panel = new JFXPanel();
         final JFXPanel p2 = new JFXPanel();
-        
+
         final CountDownLatch initViews = new CountDownLatch(1);
         Platform.runLater(new Runnable() {
             @Override
@@ -64,15 +68,15 @@ public class DoubleViewTest {
             }
         });
         initViews.await();
-        
+
         doubleView = new DoubleView();
         doubleView.setMessage("Initialized");
 
         final URL page = DoubleViewTest.class.getResource("double.html");
         assertNotNull(page, "double.html found");
 
-        
-        
+
+
         final CountDownLatch view1Init = new CountDownLatch(1);
         final CountDownLatch view2Init = new CountDownLatch(1);
         Platform.runLater(new Runnable() {
@@ -98,11 +102,11 @@ public class DoubleViewTest {
         view1Init.await();
         view2Init.await();
     }
-    
+
     private void displayFrame(JFXPanel panel, JFXPanel p2) {
         view1 = displayWebView(panel);
         view2 = displayWebView(p2);
-        
+
         JFrame f = new JFrame();
         f.getContentPane().setLayout(new FlowLayout());
         f.getContentPane().add(panel);
@@ -119,7 +123,7 @@ public class DoubleViewTest {
         panel.setScene(scene);
         return webView;
     }
-    
+
     @Test
     public void synchronizationOfViews() throws Throwable {
         final CountDownLatch cdl = new CountDownLatch(1);
@@ -130,6 +134,14 @@ public class DoubleViewTest {
                 try {
                     assertMessages("In view one", view1, "Initialized");
                     assertMessages("In view two", view2, "Initialized");
+                    set = "Change1";
+                    clickButton(view1);
+                    assertMessages("In view one", view1, "Change1");
+                    assertMessages("In view two", view2, "Change1");
+                    set = "Change2";
+                    clickButton(view2);
+                    assertMessages("In view one", view1, "Change2");
+                    assertMessages("In view two", view2, "Change2");
                 } catch (Throwable t) {
                     arr[0] = t;
                 } finally {
@@ -142,7 +154,7 @@ public class DoubleViewTest {
             throw arr[0];
         }
     }
-    
+
     @AfterMethod
     public void waitABit() throws Exception {
     }
@@ -154,4 +166,8 @@ public class DoubleViewTest {
         Object prop = v.getEngine().executeScript("document.getElementById('property').innerHTML");
         assertEquals(prop, expected, msg + " 'property' check");
     }
+
+    private void clickButton(WebView v) {
+        v.getEngine().executeScript("document.getElementById('change').click()");
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 08/15: Testing dependency on JFXPanel

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit b8a57f23b6493366ae8e82ea71f3322a803dedf3
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Thu Feb 14 05:57:01 2019 +0100

    Testing dependency on JFXPanel
---
 ko4j/pom.xml | 5 +++++
 pom.xml      | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/ko4j/pom.xml b/ko4j/pom.xml
index 71ac1a2..fbe56bb 100644
--- a/ko4j/pom.xml
+++ b/ko4j/pom.xml
@@ -102,6 +102,11 @@
         <scope>test</scope>
     </dependency>
     <dependency>
+        <groupId>org.openjfx</groupId>
+        <artifactId>javafx-swing</artifactId>
+        <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.glassfish.grizzly</groupId>
       <artifactId>grizzly-http-server</artifactId>
       <version>${grizzly.version}</version>
diff --git a/pom.xml b/pom.xml
index 70d68d3..bbe30d8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -337,6 +337,12 @@ org.netbeans.html.boot.impl:org.netbeans.html.boot.fx:org.netbeans.html.context.
             <version>11</version>
         </dependency>
         <dependency>
+            <groupId>org.openjfx</groupId>
+            <artifactId>javafx-swing</artifactId>
+            <scope>test</scope>
+            <version>11</version>
+        </dependency>
+        <dependency>
             <groupId>com.vaadin.external.google</groupId>
             <artifactId>android-json</artifactId>
             <version>0.0.20131108.vaadin1</version>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 13/15: Use Model.asList instead of HashSet in the TCK

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit e057d5fec15d77fc12fa3c2e0c2e05c0ff596d96
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Thu Feb 14 19:11:02 2019 +0100

    Use Model.asList instead of HashSet in the TCK
---
 json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java b/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java
index 247d8ae..57e3083 100644
--- a/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java
+++ b/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java
@@ -21,6 +21,7 @@ package net.java.html.js.tests;
 import java.io.StringReader;
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import net.java.html.json.Models;
@@ -403,7 +404,7 @@ public class JavaScriptBodyTest {
         Sum s = new Sum();
         Object[] props = Bodies.forIn(s);
 
-        Set<Object> all = new HashSet<>(Arrays.asList(props));
+        List<Object> all = Models.asList(props);
         assertEquals(0, all.size(), "No own properties: " + all);
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 05/15: Keep js() internal to Knockout instance

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit e31a1a2e01918df2be0669d6c2a6654088a6f737
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Wed Feb 13 11:08:15 2019 +0100

    Keep js() internal to Knockout instance
---
 ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java   |  4 ++--
 ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java | 16 ++++++++++++----
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java b/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java
index 04f9928..9586c8c 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java
@@ -74,7 +74,7 @@ Technology.ApplyId<Knockout>, Technology.ToJavaScript<Knockout> {
             if (newValue instanceof Enum) {
                 newValue = newValue.toString();
             }
-            Knockout.valueHasMutated(data.js(), propertyName, oldValue, newValue);
+            data.valueHasMutated(propertyName, oldValue, newValue);
         }
     }
 
@@ -89,7 +89,7 @@ Technology.ApplyId<Knockout>, Technology.ToJavaScript<Knockout> {
     }
     @Override
     public void applyBindings(String id, Knockout data) {
-        Object ko = Knockout.applyBindings(id, data.js());
+        Object ko = data.applyBindings(id);
         if (ko instanceof Knockout) {
             ((Knockout)ko).hold();
             applied.add((Knockout) ko);
diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
index 70c3287..f83534f 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
@@ -59,8 +59,8 @@ final class Knockout  {
     private PropertyBinding[] props;
     private FunctionBinding[] funcs;
     private final Map<Fn.Presenter,Object> objs = new HashMap<Fn.Presenter, Object>();
-    private Object copyFrom;
-    private Object strong;
+    private final Object copyFrom;
+    private final Object strong;
 
     public Knockout(Object model, Object copyFrom, PropertyBinding[] props, FunctionBinding[] funcs) {
         this.strong = model;
@@ -144,6 +144,10 @@ final class Knockout  {
         funcs[index].call(data, ev);
     }
 
+    final void valueHasMutated(String propertyName, Object oldValue, Object newValue) {
+        valueHasMutated(js(), propertyName, oldValue, newValue);
+    }
+
     @JavaScriptBody(args = { "model", "prop", "oldValue", "newValue" },
         wait4js = false,
         body =
@@ -161,10 +165,14 @@ final class Knockout  {
         + "  }\n"
         + "}\n"
     )
-    native static void valueHasMutated(
+    private native static void valueHasMutated(
         Object model, String prop, Object oldValue, Object newValue
     );
 
+    final Object applyBindings(String id) {
+        return applyBindings(id, js());
+    }
+
     @JavaScriptBody(args = { "id", "bindings" }, body =
         "var d = window['document'];\n" +
         "var e = id ? d['getElementById'](id) : d['body'];\n" +
@@ -172,7 +180,7 @@ final class Knockout  {
         "ko['applyBindings'](bindings, e);\n" +
         "return bindings['ko4j'];\n"
     )
-    native static Object applyBindings(String id, Object bindings);
+    private native static Object applyBindings(String id, Object bindings);
 
     @JavaScriptBody(args = { "cnt" }, body =
         "var arr = new Array(cnt);\n" +


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 01/15: Using the same model in two views with ko4j binding fails

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit 000668ddfcc252e189a1fd5ecb09b025e9691949
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Mon Feb 11 11:11:44 2019 +0100

    Using the same model in two views with ko4j binding fails
---
 .../org/netbeans/html/ko4j/DoubleViewTest.java     | 157 +++++++++++++++++++++
 .../resources/org/netbeans/html/ko4j/double.html   |  34 +++++
 2 files changed, 191 insertions(+)

diff --git a/ko4j/src/test/java/org/netbeans/html/ko4j/DoubleViewTest.java b/ko4j/src/test/java/org/netbeans/html/ko4j/DoubleViewTest.java
new file mode 100644
index 0000000..7232bc2
--- /dev/null
+++ b/ko4j/src/test/java/org/netbeans/html/ko4j/DoubleViewTest.java
@@ -0,0 +1,157 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.html.ko4j;
+
+import java.awt.FlowLayout;
+import java.net.URL;
+import java.util.concurrent.CountDownLatch;
+import javafx.application.Platform;
+import javafx.embed.swing.JFXPanel;
+import javafx.scene.Scene;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.web.WebView;
+import javax.swing.JFrame;
+import net.java.html.boot.fx.FXBrowsers;
+import net.java.html.json.Function;
+import net.java.html.json.Model;
+import net.java.html.json.Property;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+@Model(className = "DoubleView", targetId = "", properties = {
+    @Property(name = "message", type = String.class)
+})
+public class DoubleViewTest {
+    @Function
+    static void change(DoubleView model) {
+        model.setMessage("Modified");
+    }
+    
+    DoubleView doubleView;
+    private WebView view1;
+    private WebView view2;
+    
+    @BeforeMethod
+    public void initializeViews() throws Exception {
+        final JFXPanel panel = new JFXPanel();
+        final JFXPanel p2 = new JFXPanel();
+        
+        final CountDownLatch initViews = new CountDownLatch(1);
+        Platform.runLater(new Runnable() {
+            @Override
+            public void run() {
+                displayFrame(panel, p2);
+                initViews.countDown();
+            }
+        });
+        initViews.await();
+        
+        doubleView = new DoubleView();
+        doubleView.setMessage("Initialized");
+
+        final URL page = DoubleViewTest.class.getResource("double.html");
+        assertNotNull(page, "double.html found");
+
+        
+        
+        final CountDownLatch view1Init = new CountDownLatch(1);
+        final CountDownLatch view2Init = new CountDownLatch(1);
+        Platform.runLater(new Runnable() {
+            @Override
+            public void run() {
+                FXBrowsers.load(view1, page, new Runnable() {
+                    @Override
+                    public void run() {
+                        doubleView.applyBindings();
+                        view1Init.countDown();
+                    }
+                });
+
+                FXBrowsers.load(view2, page, new Runnable() {
+                    @Override
+                    public void run() {
+                        doubleView.applyBindings();
+                        view2Init.countDown();
+                    }
+                });
+            }
+        });
+        view1Init.await();
+        view2Init.await();
+    }
+    
+    private void displayFrame(JFXPanel panel, JFXPanel p2) {
+        view1 = displayWebView(panel);
+        view2 = displayWebView(p2);
+        
+        JFrame f = new JFrame();
+        f.getContentPane().setLayout(new FlowLayout());
+        f.getContentPane().add(panel);
+        f.getContentPane().add(p2);
+        f.pack();
+        f.setVisible(true);
+    }
+
+    private WebView displayWebView(JFXPanel panel) {
+        BorderPane pane = new BorderPane();
+        Scene scene = new Scene(pane, 800, 600);
+        WebView webView = new WebView();
+        pane.setCenter(webView);
+        panel.setScene(scene);
+        return webView;
+    }
+    
+    @Test
+    public void synchronizationOfViews() throws Throwable {
+        final CountDownLatch cdl = new CountDownLatch(1);
+        final Throwable[] arr = new Throwable[1];
+        Platform.runLater(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    assertMessages("In view one", view1, "Initialized");
+                    assertMessages("In view two", view2, "Initialized");
+                } catch (Throwable t) {
+                    arr[0] = t;
+                } finally {
+                    cdl.countDown();
+                }
+            }
+        });
+        cdl.await();
+        if (arr[0] != null) {
+            throw arr[0];
+        }
+    }
+    
+    @AfterMethod
+    public void waitABit() throws Exception {
+    }
+
+    private void assertMessages(String msg, WebView v, String expected) {
+        Object func = v.getEngine().executeScript("document.getElementById('function').innerHTML");
+        assertEquals(func, expected, msg + " 'function' check");
+
+        Object prop = v.getEngine().executeScript("document.getElementById('property').innerHTML");
+        assertEquals(prop, expected, msg + " 'property' check");
+    }
+}
diff --git a/ko4j/src/test/resources/org/netbeans/html/ko4j/double.html b/ko4j/src/test/resources/org/netbeans/html/ko4j/double.html
new file mode 100644
index 0000000..30d5883
--- /dev/null
+++ b/ko4j/src/test/resources/org/netbeans/html/ko4j/double.html
@@ -0,0 +1,34 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Double Usage</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+        <meta name="viewport" content="width=device-width">
+    </head>
+    <body>
+        <h1>Double Usage</h1>
+        <div id='property' data-bind="text: message">Message as property</div>
+        <div id='function' data-bind="text: message()">Message as function</div>
+        <button id='change' data-bind="click: change">Change</button>
+    </body>
+</html>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 10/15: Avoid usage of HashMap

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit 220254be373dcecaad8478e7ee616f3b49c3412d
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Thu Feb 14 07:01:01 2019 +0100

    Avoid usage of HashMap
---
 .../main/java/org/netbeans/html/ko4j/MapObjs.java  | 94 ++++++++++++++++------
 1 file changed, 68 insertions(+), 26 deletions(-)

diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java b/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java
index ef3ec28..672710a 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java
@@ -19,49 +19,91 @@
 
 package org.netbeans.html.ko4j;
 
-import java.util.HashMap;
-import java.util.Map;
+import java.util.List;
+import net.java.html.json.Models;
 import org.netbeans.html.boot.spi.Fn;
 
 final class MapObjs {
+    private static final Object UNINITIALIZED = new Object();
+    private static Object onlyPresenter = UNINITIALIZED;
+
+    private final List<Object> all;
+
+    private MapObjs(Object... arr) {
+        this.all = Models.asList(arr);
+    }
+
+
     static Object put(Object now, Fn.Presenter key, Object js) {
-        Map<Fn.Presenter, Object> map = (Map<Fn.Presenter, Object>) now;
-        if (map == null) {
-            map = new HashMap<Fn.Presenter, Object>();
+        if (now instanceof MapObjs) {
+            return ((MapObjs)now).put(key, js);
+        } else {
+            if (onlyPresenter == UNINITIALIZED) {
+                onlyPresenter = key;
+                return js;
+            } else if (onlyPresenter == key) {
+                return js;
+            } else {
+                if (onlyPresenter == null) {
+                    assert now == null;
+                    return new MapObjs(key, js);
+                } else {
+                    final MapObjs map = new MapObjs(onlyPresenter, now, key, js);
+                    onlyPresenter = null;
+                    return map;
+                }
+            }
         }
-        map.put(key, js);
-        return map;
     }
 
     static Object get(Object now, Fn.Presenter key) {
-        if (now instanceof Map) {
-            Map<?,?> map = (Map<?,?>) now;
-            return map.get(key);
+        if (now instanceof MapObjs) {
+            return ((MapObjs)now).get(key);
         }
-        return null;
+        return key == onlyPresenter ? now : null;
     }
 
     static Object[] remove(Object now, Fn.Presenter key) {
-        Map<?,?> map = (Map<?,?>) now;
-        Object prev = map.remove(key);
-        return new Object[] { prev, map };
+        if (now instanceof MapObjs) {
+            return ((MapObjs)now).remove(key);
+        }
+        return new Object[] { now, null };
     }
 
     static Object[] toArray(Object now) {
-        if (now instanceof Map) {
-            Map<?, ?> map = (Map<?, ?>) now;
-            Object[] res = new Object[map.size() * 2];
-            int at = 0;
-            for (Map.Entry<? extends Object, ? extends Object> entry : map.entrySet()) {
-                Object key = entry.getKey();
-                Object value = entry.getValue();
+        if (now instanceof MapObjs) {
+            return ((MapObjs) now).all.toArray();
+        }
+        return new Object[] { onlyPresenter, now };
+    }
+
+    private Object put(Fn.Presenter key, Object js) {
+        for (int i = 0; i < all.size(); i += 2) {
+            if (all.get(i) == key) {
+                all.set(i + 1, js);
+                return this;
+            }
+        }
+        all.add(key);
+        all.add(js);
+        return this;
+    }
+
+    private Object get(Fn.Presenter key) {
+        for (int i = 0; i < all.size(); i += 2) {
+            if (all.get(i) == key) {
+                return all.get(i + 1);
+            }
+        }
+        return null;
+    }
 
-                res[at] = key;
-                res[at + 1] = value;
-                at += 2;
+    private Object[] remove(Fn.Presenter key) {
+        for (int i = 0; i < all.size(); i += 2) {
+            if (all.get(i) == key) {
+                return new Object[] { all.get(i + 1), this };
             }
-            return res;
         }
-        return new Object[0];
+        return new Object[] { null, this };
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 14/15: Moving exposed properties check into own class

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit 4ec660c0b0e16ddc0e51b82c2fecd5a9525c4ad7
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Fri Feb 15 06:52:12 2019 +0100

    Moving exposed properties check into own class
---
 .../java/html/js/tests/ExposedPropertiesTest.java  | 168 +++++++++++++++++++++
 .../net/java/html/js/tests/JavaScriptBodyTest.java | 151 +-----------------
 .../org/netbeans/html/json/tck/JavaScriptTCK.java  |   3 +-
 3 files changed, 175 insertions(+), 147 deletions(-)

diff --git a/json-tck/src/main/java/net/java/html/js/tests/ExposedPropertiesTest.java b/json-tck/src/main/java/net/java/html/js/tests/ExposedPropertiesTest.java
new file mode 100644
index 0000000..96e4610
--- /dev/null
+++ b/json-tck/src/main/java/net/java/html/js/tests/ExposedPropertiesTest.java
@@ -0,0 +1,168 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package net.java.html.js.tests;
+
+import java.util.List;
+import static net.java.html.js.tests.JavaScriptBodyTest.assertEquals;
+import static net.java.html.js.tests.JavaScriptBodyTest.assertNull;
+import static net.java.html.js.tests.JavaScriptBodyTest.fail;
+import net.java.html.json.Models;
+import org.netbeans.html.json.tck.KOTest;
+
+public class ExposedPropertiesTest {
+    @KOTest
+    public void exposedPropertiesOfAJavaObject() {
+        Sum s = new Sum();
+        Object[] props = Bodies.forIn(s);
+
+        List<Object> all = Models.asList(props);
+        assertEquals(0, all.size(), "No own properties: " + all);
+    }
+
+    @KOTest
+    public void exposedEqualsOfAJavaObject() {
+        Sum s = new Sum();
+        assertNoProp(s, "equals", s);
+    }
+
+    @KOTest
+    public void exposedHashCodeOfAJavaObject() {
+        Sum s = new Sum();
+
+        assertNoProp(s, "hashCode", null);
+    }
+
+    @KOTest
+    public void exposedWaitOfAJavaObject() {
+        Sum s = new Sum();
+
+        assertNoProp(s, "wait", null);
+    }
+
+    @KOTest
+    public void exposedGetClassOfAJavaObject() {
+        Sum s = new Sum();
+
+        assertNoProp(s, "getClass", null);
+    }
+
+    @KOTest
+    public void exposedNotifyOfAJavaObject() {
+        Sum s = new Sum();
+
+        assertNoProp(s, "notify", null);
+    }
+
+    @KOTest
+    public void exposedNotifyAllOfAJavaObject() {
+        Sum s = new Sum();
+
+        assertNoProp(s, "notifyAll", null);
+    }
+
+    @KOTest
+    public void exposedEqualsOfAJavaArray() {
+        Object s = new Object[5];
+        assertNoProp(s, "equals", s);
+    }
+
+    @KOTest
+    public void exposedHashCodeOfAJavaArray() {
+        Object s = new Object[5];
+
+        assertNoProp(s, "hashCode", null);
+    }
+
+    @KOTest
+    public void exposedWaitOfAJavaArray() {
+        Object s = new Object[5];
+
+        assertNoProp(s, "wait", null);
+    }
+
+    @KOTest
+    public void exposedGetClassOfAJavaArray() {
+        Object s = new Object[5];
+
+        assertNoProp(s, "getClass", null);
+    }
+
+    @KOTest
+    public void exposedNotifyOfAJavaArray() {
+        Object s = new Object[5];
+
+        assertNoProp(s, "notify", null);
+    }
+
+    @KOTest
+    public void exposedNotifyAllOfAJavaArray() {
+        Object s = new Object[5];
+
+        assertNoProp(s, "notifyAll", null);
+    }
+
+    @KOTest
+    public void exposedEqualsOfAJavaPrimitiveArray() {
+        Object s = new int[5];
+        assertNoProp(s, "equals", s);
+    }
+
+    @KOTest
+    public void exposedHashCodeOfAJavaPrimitiveArray() {
+        Object s = new int[5];
+
+        assertNoProp(s, "hashCode", null);
+    }
+
+    @KOTest
+    public void exposedWaitOfAJavaPrimitiveArray() {
+        Object s = new int[5];
+
+        assertNoProp(s, "wait", null);
+    }
+
+    @KOTest
+    public void exposedGetClassOfAJavaPrimitiveArray() {
+        Object s = new int[5];
+
+        assertNoProp(s, "getClass", null);
+    }
+
+    @KOTest
+    public void exposedNotifyOfAJavaPrimitiveArray() {
+        Object s = new int[5];
+
+        assertNoProp(s, "notify", null);
+    }
+
+    private static void assertNoProp(Object obj, String name, Object arg) {
+        Object prop = Bodies.get(obj, name);
+        assertNull(prop, "Expecting no value for property " + name + ", but was " + Bodies.typeof(prop, false));
+
+        try {
+            Object res = Bodies.invoke(obj, name, arg);
+            if (name.equals(res)) {
+                return;
+            }
+            fail("Invoking " + name + " on " + obj + " returned " + res);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java b/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java
index 57e3083..86f15f4 100644
--- a/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java
+++ b/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java
@@ -134,22 +134,6 @@ public class JavaScriptBodyTest {
         assertEquals("number", doubleType, "Expecting number type: " + doubleType);
     }
 
-    private static void assertNoProp(Object obj, String name, Object arg) {
-        Object prop = Bodies.get(obj, name);
-        assertNull(prop, "Expecting no value for property " + name + ", but was " + Bodies.typeof(prop, false));
-
-        try {
-            Object res = Bodies.invoke(obj, name, arg);
-            if (name.equals(res)) {
-                return;
-            }
-            fail("Invoking " + name + " on " + obj + " returned " + res);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-
-    }
-
     enum Two {
         ONE, TWO;
     }
@@ -399,132 +383,6 @@ public class JavaScriptBodyTest {
         assertEquals(nullAndUnknown, 1, "Only one slot");
     }
 
-    @KOTest
-    public void exposedPropertiesOfAJavaObject() {
-        Sum s = new Sum();
-        Object[] props = Bodies.forIn(s);
-
-        List<Object> all = Models.asList(props);
-        assertEquals(0, all.size(), "No own properties: " + all);
-    }
-
-
-    @KOTest
-    public void exposedEqualsOfAJavaObject() {
-        Sum s = new Sum();
-        assertNoProp(s, "equals", s);
-    }
-
-    @KOTest
-    public void exposedHashCodeOfAJavaObject() {
-        Sum s = new Sum();
-
-        assertNoProp(s, "hashCode", null);
-    }
-
-    @KOTest
-    public void exposedWaitOfAJavaObject() {
-        Sum s = new Sum();
-
-        assertNoProp(s, "wait", null);
-    }
-
-    @KOTest
-    public void exposedGetClassOfAJavaObject() {
-        Sum s = new Sum();
-
-        assertNoProp(s, "getClass", null);
-    }
-
-    @KOTest
-    public void exposedNotifyOfAJavaObject() {
-        Sum s = new Sum();
-
-        assertNoProp(s, "notify", null);
-    }
-
-    @KOTest
-    public void exposedNotifyAllOfAJavaObject() {
-        Sum s = new Sum();
-
-        assertNoProp(s, "notifyAll", null);
-    }
-
-    @KOTest
-    public void exposedEqualsOfAJavaArray() {
-        Object s = new Object[5];
-        assertNoProp(s, "equals", s);
-    }
-
-    @KOTest
-    public void exposedHashCodeOfAJavaArray() {
-        Object s = new Object[5];
-
-        assertNoProp(s, "hashCode", null);
-    }
-
-    @KOTest
-    public void exposedWaitOfAJavaArray() {
-        Object s = new Object[5];
-
-        assertNoProp(s, "wait", null);
-    }
-
-    @KOTest
-    public void exposedGetClassOfAJavaArray() {
-        Object s = new Object[5];
-
-        assertNoProp(s, "getClass", null);
-    }
-
-    @KOTest
-    public void exposedNotifyOfAJavaArray() {
-        Object s = new Object[5];
-
-        assertNoProp(s, "notify", null);
-    }
-
-    @KOTest
-    public void exposedNotifyAllOfAJavaArray() {
-        Object s = new Object[5];
-
-        assertNoProp(s, "notifyAll", null);
-    }
-
-    @KOTest
-    public void exposedEqualsOfAJavaPrimitiveArray() {
-        Object s = new int[5];
-        assertNoProp(s, "equals", s);
-    }
-
-    @KOTest
-    public void exposedHashCodeOfAJavaPrimitiveArray() {
-        Object s = new int[5];
-
-        assertNoProp(s, "hashCode", null);
-    }
-
-    @KOTest
-    public void exposedWaitOfAJavaPrimitiveArray() {
-        Object s = new int[5];
-
-        assertNoProp(s, "wait", null);
-    }
-
-    @KOTest
-    public void exposedGetClassOfAJavaPrimitiveArray() {
-        Object s = new int[5];
-
-        assertNoProp(s, "getClass", null);
-    }
-
-    @KOTest
-    public void exposedNotifyOfAJavaPrimitiveArray() {
-        Object s = new int[5];
-
-        assertNoProp(s, "notify", null);
-    }
-
     @KOTest public void problematicString() {
         String orig = Bodies.problematicString();
         String js = Bodies.problematicCallback();
@@ -654,23 +512,24 @@ public class JavaScriptBodyTest {
         }
         throw new AssertionError("Expecting " + b + " but found " + a);
     }
-    private static void fail(String msg) {
+
+    static void fail(String msg) {
         throw new AssertionError(msg);
     }
 
-    private static void assertTrue(boolean c, String msg) {
+    static void assertTrue(boolean c, String msg) {
         if (!c) {
             throw new AssertionError(msg);
         }
     }
 
-    private static void assertFalse(boolean c, String msg) {
+    static void assertFalse(boolean c, String msg) {
         if (c) {
             throw new AssertionError(msg);
         }
     }
 
-    private static void assertNull(Object o, String msg) {
+    static void assertNull(Object o, String msg) {
         if (o != null) {
             throw new AssertionError(msg);
         }
diff --git a/json-tck/src/main/java/org/netbeans/html/json/tck/JavaScriptTCK.java b/json-tck/src/main/java/org/netbeans/html/json/tck/JavaScriptTCK.java
index 84c7cec..09b8315 100644
--- a/json-tck/src/main/java/org/netbeans/html/json/tck/JavaScriptTCK.java
+++ b/json-tck/src/main/java/org/netbeans/html/json/tck/JavaScriptTCK.java
@@ -20,6 +20,7 @@ package org.netbeans.html.json.tck;
 
 import net.java.html.js.tests.GCBodyTest;
 import net.java.html.js.tests.JavaScriptBodyTest;
+import net.java.html.js.tests.ExposedPropertiesTest;
 import org.netbeans.html.boot.spi.Fn;
 import org.netbeans.html.boot.spi.Fn.Presenter;
 
@@ -42,7 +43,7 @@ public abstract class JavaScriptTCK {
      */
     protected static Class<?>[] testClasses() {
         return new Class[] { 
-            JavaScriptBodyTest.class, GCBodyTest.class
+            JavaScriptBodyTest.class, GCBodyTest.class, ExposedPropertiesTest.class
         };
     }
     


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 02/15: Create the objs in constructor

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit 8c5f0bbf05983cda70a2b9a8575f09b67b06c2fd
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Tue Feb 12 19:23:34 2019 +0100

    Create the objs in constructor
---
 .../java/org/netbeans/html/ko4j/CacheObjs.java     | 46 ++++++++++++++++++++++
 .../main/java/org/netbeans/html/ko4j/KOTech.java   | 45 +--------------------
 .../main/java/org/netbeans/html/ko4j/Knockout.java | 31 +++++++++++++--
 3 files changed, 75 insertions(+), 47 deletions(-)

diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java b/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java
new file mode 100644
index 0000000..af7e9f6
--- /dev/null
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.html.ko4j;
+
+final class CacheObjs {
+    private static final CacheObjs C = new CacheObjs();
+
+    private Object[] jsObjects;
+    private int jsIndex;
+
+    static CacheObjs find() {
+        return C;
+    }
+
+    Object getJSObject() {
+        int len = 64;
+        if (jsObjects != null && jsIndex < (len = jsObjects.length)) {
+            Object ret = jsObjects[jsIndex];
+            jsObjects[jsIndex] = null;
+            jsIndex++;
+            return ret;
+        }
+        jsObjects = Knockout.allocJS(len * 2);
+        jsIndex = 1;
+        Object ret = jsObjects[0];
+        jsObjects[0] = null;
+        return ret;
+    }
+}
diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java b/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java
index 32f0ea9..04f9928 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java
@@ -36,9 +36,6 @@ import org.netbeans.html.json.spi.Technology;
 final class KOTech
 implements Technology.BatchCopy<Knockout>, Technology.ValueMutated<Knockout>,
 Technology.ApplyId<Knockout>, Technology.ToJavaScript<Knockout> {
-    private Object[] jsObjects;
-    private int jsIndex;
-
     public KOTech() {
     }
     
@@ -48,53 +45,13 @@ Technology.ApplyId<Knockout>, Technology.ToJavaScript<Knockout> {
     }
 
     final Knockout createKO(Object model, Object copyFrom, PropertyBinding[] propArr, FunctionBinding[] funcArr, Knockout[] ko) {
-        String[] propNames = new String[propArr.length];
-        Number[] propInfo = new Number[propArr.length];
-        Object[] propValues = new Object[propArr.length];
-        for (int i = 0; i < propNames.length; i++) {
-            propNames[i] = propArr[i].getPropertyName();
-            int info =
-                (propArr[i].isReadOnly() ? 1 : 0) +
-                (propArr[i].isConstant()? 2 : 0);
-            propInfo[i] = info;
-            Object value = propArr[i].getValue();
-            if (value instanceof Enum) {
-                value = value.toString();
-            }
-            propValues[i] = value;
-        }
-        String[] funcNames = new String[funcArr.length];
-        for (int i = 0; i < funcNames.length; i++) {
-            funcNames[i] = funcArr[i].getFunctionName();
-        }
-        Object ret = getJSObject();
-        Knockout newKO = new Knockout(model, ret, propArr, funcArr);
+        Knockout newKO = new Knockout(model, copyFrom, propArr, funcArr);
         if (ko != null) {
             ko[0] = newKO;
         }
-        Knockout.wrapModel(
-            newKO,
-            ret, copyFrom,
-            propNames, propInfo, propValues, funcNames
-        );
         return newKO;
     }
     
-    private Object getJSObject() {
-        int len = 64;
-        if (jsObjects != null && jsIndex < (len = jsObjects.length)) {
-            Object ret = jsObjects[jsIndex];
-            jsObjects[jsIndex] = null;
-            jsIndex++;
-            return ret;
-        }
-        jsObjects = Knockout.allocJS(len * 2);
-        jsIndex = 1;
-        Object ret = jsObjects[0];
-        jsObjects[0] = null;
-        return ret;
-    }
-    
     @Override
     public Knockout wrapModel(Object model) {
         throw new UnsupportedOperationException();
diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
index ae52c39..7efd4e3 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
@@ -58,9 +58,8 @@ final class Knockout  {
     private Object js;
     private Object strong;
 
-    public Knockout(Object model, Object js, PropertyBinding[] props, FunctionBinding[] funcs) {
+    public Knockout(Object model, Object copyFrom, PropertyBinding[] props, FunctionBinding[] funcs) {
         this.strong = model;
-        this.js = js;
         this.props = new PropertyBinding[props.length];
         for (int i = 0; i < props.length; i++) {
             this.props[i] = props[i].weak();
@@ -69,12 +68,38 @@ final class Knockout  {
         for (int i = 0; i < funcs.length; i++) {
             this.funcs[i] = funcs[i].weak();
         }
+        this.js = initObjs(copyFrom);
     }
 
     final Object js() {
         return js;
     }
 
+    private Object initObjs(Object copyFrom) {
+        String[] propNames = new String[props.length];
+        Number[] propInfo = new Number[props.length];
+        Object[] propValues = new Object[props.length];
+        for (int i = 0; i < propNames.length; i++) {
+            propNames[i] = props[i].getPropertyName();
+            int info
+                    = (props[i].isReadOnly() ? 1 : 0)
+                    + (props[i].isConstant() ? 2 : 0);
+            propInfo[i] = info;
+            Object value = props[i].getValue();
+            if (value instanceof Enum) {
+                value = value.toString();
+            }
+            propValues[i] = value;
+        }
+        String[] funcNames = new String[funcs.length];
+        for (int i = 0; i < funcNames.length; i++) {
+            funcNames[i] = funcs[i].getFunctionName();
+        }
+        Object ret = CacheObjs.find().getJSObject();
+        wrapModel(this,ret, copyFrom, propNames, propInfo, propValues, funcNames);
+        return ret;
+    }
+
     static void cleanUp() {
         for (;;) {
             Knockout ko = null;
@@ -228,7 +253,7 @@ final class Knockout  {
         + "  koExpose(i, funcNames[i]);\n"
         + "}\n"
         )
-    static native void wrapModel(
+    private static native void wrapModel(
         Knockout thiz,
         Object ret, Object copyFrom,
         String[] propNames, Number[] propInfo,


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 07/15: Caching needs to be done per presenter

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit 16f7f4614742e98f7f0d7d9cea9bf6cdcca20b47
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Thu Feb 14 05:49:56 2019 +0100

    Caching needs to be done per presenter
---
 .../java/org/netbeans/html/ko4j/CacheObjs.java     | 50 ++++++++++++++++++++--
 .../main/java/org/netbeans/html/ko4j/Knockout.java | 11 ++---
 2 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java b/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java
index af7e9f6..6311ff2 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java
@@ -19,14 +19,56 @@
 
 package org.netbeans.html.ko4j;
 
-final class CacheObjs {
-    private static final CacheObjs C = new CacheObjs();
+import java.lang.ref.WeakReference;
+import org.netbeans.html.boot.spi.Fn;
 
+final class CacheObjs extends WeakReference<Fn.Presenter> {
+    /* both @GuardedBy CacheObjs.class */
+    private static CacheObjs list;
+    private CacheObjs next;
+
+    /* both @GuardedBy presenter single threaded access */
     private Object[] jsObjects;
     private int jsIndex;
 
-    static CacheObjs find() {
-        return C;
+    private CacheObjs(CacheObjs next, Fn.Presenter p) {
+        super(p);
+        this.next = next;
+    }
+
+    static synchronized CacheObjs find(Fn.Presenter key) {
+        if (list == null) {
+            return list = new CacheObjs(null, key);
+        }
+
+        Fn.Presenter p;
+        for (;;) {
+            p = list.get();
+            if (p != null) {
+                break;
+            }
+            list = list.next;
+        }
+
+        if (p == key) {
+            return list;
+        }
+
+        CacheObjs prev = list;
+        CacheObjs now = list.next;
+
+        while (now != null) {
+            p = now.get();
+            if (p == null) {
+                prev.next = now;
+            }
+            if (p == key) {
+                return now;
+            }
+            prev = now;
+            now = now.next;
+        }
+        return prev.next = new CacheObjs(null, key);
     }
 
     Object getJSObject() {
diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
index ac91bcc..cc41bb8 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
@@ -79,15 +79,16 @@ final class Knockout  {
     }
 
     final Object js() {
-        Object js = objs.get(Fn.activePresenter());
+        final Fn.Presenter c = Fn.activePresenter();
+        Object js = objs.get(c);
         if (js == null) {
-            js = initObjs(copyFrom);
-            objs.put(Fn.activePresenter(), js);
+            js = initObjs(c, copyFrom);
+            objs.put(c, js);
         }
         return js;
     }
 
-    private Object initObjs(Object copyFrom) {
+    private Object initObjs(Fn.Presenter p, Object copyFrom) {
         String[] propNames = new String[props.length];
         Number[] propInfo = new Number[props.length];
         Object[] propValues = new Object[props.length];
@@ -107,7 +108,7 @@ final class Knockout  {
         for (int i = 0; i < funcNames.length; i++) {
             funcNames[i] = funcs[i].getFunctionName();
         }
-        Object ret = CacheObjs.find().getJSObject();
+        Object ret = CacheObjs.find(p).getJSObject();
         wrapModel(this,ret, copyFrom, propNames, propInfo, propValues, funcNames);
         return ret;
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 03/15: Initialize on demand

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit 62410a4869d273931c51205d946a842b22f01124
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Tue Feb 12 19:36:17 2019 +0100

    Initialize on demand
---
 ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
index 7efd4e3..9222296 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
@@ -56,6 +56,7 @@ final class Knockout  {
     private PropertyBinding[] props;
     private FunctionBinding[] funcs;
     private Object js;
+    private Object copyFrom;
     private Object strong;
 
     public Knockout(Object model, Object copyFrom, PropertyBinding[] props, FunctionBinding[] funcs) {
@@ -68,10 +69,13 @@ final class Knockout  {
         for (int i = 0; i < funcs.length; i++) {
             this.funcs[i] = funcs[i].weak();
         }
-        this.js = initObjs(copyFrom);
+        this.copyFrom = copyFrom;
     }
 
     final Object js() {
+        if (js == null) {
+            this.js = initObjs(copyFrom);
+        }
         return js;
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 09/15: Encapsulate the multi-js-object operations into separate class

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit af4a74110d2eda1b5c8be42ff250b43ba9cf5d97
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Thu Feb 14 06:21:26 2019 +0100

    Encapsulate the multi-js-object operations into separate class
---
 .../main/java/org/netbeans/html/ko4j/Knockout.java | 17 +++---
 .../main/java/org/netbeans/html/ko4j/MapObjs.java  | 67 ++++++++++++++++++++++
 2 files changed, 77 insertions(+), 7 deletions(-)

diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
index cc41bb8..912d12d 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
@@ -61,7 +61,7 @@ final class Knockout  {
 
     private PropertyBinding[] props;
     private FunctionBinding[] funcs;
-    private final Map<Fn.Presenter,Object> objs = new HashMap<Fn.Presenter, Object>();
+    private Object objs;
     private final Object copyFrom;
     private final Object strong;
 
@@ -80,10 +80,10 @@ final class Knockout  {
 
     final Object js() {
         final Fn.Presenter c = Fn.activePresenter();
-        Object js = objs.get(c);
+        Object js = MapObjs.get(objs, c);
         if (js == null) {
             js = initObjs(c, copyFrom);
-            objs.put(c, js);
+            objs = MapObjs.put(objs, c, js);
         }
         return js;
     }
@@ -119,7 +119,9 @@ final class Knockout  {
             if (ko == null) {
                 return;
             }
-            Object js = ko.objs.remove(Fn.activePresenter());
+            Object[] both = MapObjs.remove(ko.objs, Fn.activePresenter());
+            Object js = both[0];
+            ko.objs = both[1];
             clean(js);
             ko.props = null;
             ko.funcs = null;
@@ -149,9 +151,10 @@ final class Knockout  {
     }
 
     final void valueHasMutated(final String propertyName, Object oldValue, Object newValue) {
-        for (Map.Entry<Fn.Presenter, Object> e : objs.entrySet()) {
-            Fn.Presenter p = e.getKey();
-            final Object o = e.getValue();
+        Object[] all = MapObjs.toArray(objs);
+        for (int i = 0; i < all.length; i += 2) {
+            Fn.Presenter p = (Fn.Presenter) all[i];
+            final Object o = all[i + 1];
             if (p != Fn.activePresenter()) {
                 if (p instanceof Executor) {
                     ((Executor) p).execute(new Runnable() {
diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java b/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java
new file mode 100644
index 0000000..ef3ec28
--- /dev/null
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.html.ko4j;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.netbeans.html.boot.spi.Fn;
+
+final class MapObjs {
+    static Object put(Object now, Fn.Presenter key, Object js) {
+        Map<Fn.Presenter, Object> map = (Map<Fn.Presenter, Object>) now;
+        if (map == null) {
+            map = new HashMap<Fn.Presenter, Object>();
+        }
+        map.put(key, js);
+        return map;
+    }
+
+    static Object get(Object now, Fn.Presenter key) {
+        if (now instanceof Map) {
+            Map<?,?> map = (Map<?,?>) now;
+            return map.get(key);
+        }
+        return null;
+    }
+
+    static Object[] remove(Object now, Fn.Presenter key) {
+        Map<?,?> map = (Map<?,?>) now;
+        Object prev = map.remove(key);
+        return new Object[] { prev, map };
+    }
+
+    static Object[] toArray(Object now) {
+        if (now instanceof Map) {
+            Map<?, ?> map = (Map<?, ?>) now;
+            Object[] res = new Object[map.size() * 2];
+            int at = 0;
+            for (Map.Entry<? extends Object, ? extends Object> entry : map.entrySet()) {
+                Object key = entry.getKey();
+                Object value = entry.getValue();
+
+                res[at] = key;
+                res[at + 1] = value;
+                at += 2;
+            }
+            return res;
+        }
+        return new Object[0];
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 12/15: Use round-robin cache

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit 68228faeff77a74649e2076f1cb504c35aca8bf2
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Thu Feb 14 19:02:17 2019 +0100

    Use round-robin cache
---
 .../java/org/netbeans/html/ko4j/CacheObjs.java     | 54 +++++++---------------
 1 file changed, 17 insertions(+), 37 deletions(-)

diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java b/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java
index 6311ff2..4da77c2 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java
@@ -19,56 +19,36 @@
 
 package org.netbeans.html.ko4j;
 
-import java.lang.ref.WeakReference;
 import org.netbeans.html.boot.spi.Fn;
 
-final class CacheObjs extends WeakReference<Fn.Presenter> {
+final class CacheObjs {
     /* both @GuardedBy CacheObjs.class */
-    private static CacheObjs list;
-    private CacheObjs next;
+    private static CacheObjs[] list = new CacheObjs[16];
+    private static int listAt = 0;
+    private final Fn.Presenter ref;
 
     /* both @GuardedBy presenter single threaded access */
     private Object[] jsObjects;
     private int jsIndex;
 
-    private CacheObjs(CacheObjs next, Fn.Presenter p) {
-        super(p);
-        this.next = next;
+    private CacheObjs(Fn.Presenter p) {
+        this.ref = p;
     }
 
-    static synchronized CacheObjs find(Fn.Presenter key) {
-        if (list == null) {
-            return list = new CacheObjs(null, key);
-        }
-
-        Fn.Presenter p;
-        for (;;) {
-            p = list.get();
-            if (p != null) {
-                break;
-            }
-            list = list.next;
-        }
-
-        if (p == key) {
-            return list;
-        }
-
-        CacheObjs prev = list;
-        CacheObjs now = list.next;
+    Fn.Presenter get() {
+        return ref;
+    }
 
-        while (now != null) {
-            p = now.get();
-            if (p == null) {
-                prev.next = now;
-            }
-            if (p == key) {
-                return now;
+    static synchronized CacheObjs find(Fn.Presenter key) {
+        for (int i = 0; i < list.length; i++) {
+            if (list[i] != null && list[i].get() == key) {
+                return list[i];
             }
-            prev = now;
-            now = now.next;
         }
-        return prev.next = new CacheObjs(null, key);
+        CacheObjs co = new CacheObjs(key);
+        list[listAt] = co;
+        listAt = (listAt + 1) % list.length;
+        return co;
     }
 
     Object getJSObject() {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[incubator-netbeans-html4j] 11/15: Testing behavior of MapObjs support

Posted by jt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans-html4j.git

commit 4da1644d2d8262506cf9a94157d49b2d7690ec49
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Thu Feb 14 18:30:36 2019 +0100

    Testing behavior of MapObjs support
---
 .../main/java/org/netbeans/html/ko4j/MapObjs.java  | 35 +++++----
 .../java/org/netbeans/html/ko4j/MapObjsTest.java   | 84 ++++++++++++++++++++++
 2 files changed, 106 insertions(+), 13 deletions(-)

diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java b/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java
index 672710a..1f3a998 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java
@@ -24,8 +24,17 @@ import net.java.html.json.Models;
 import org.netbeans.html.boot.spi.Fn;
 
 final class MapObjs {
-    private static final Object UNINITIALIZED = new Object();
-    private static Object onlyPresenter = UNINITIALIZED;
+    private static Object onlyPresenter;
+    private static boolean usePresenter;
+
+    static {
+        reset();
+    }
+
+    static void reset() {
+        onlyPresenter = null;
+        usePresenter = true;
+    }
 
     private final List<Object> all;
 
@@ -38,21 +47,21 @@ final class MapObjs {
         if (now instanceof MapObjs) {
             return ((MapObjs)now).put(key, js);
         } else {
-            if (onlyPresenter == UNINITIALIZED) {
-                onlyPresenter = key;
-                return js;
-            } else if (onlyPresenter == key) {
-                return js;
-            } else {
+            if (usePresenter) {
                 if (onlyPresenter == null) {
-                    assert now == null;
-                    return new MapObjs(key, js);
+                    onlyPresenter = key;
+                    return js;
+                } else if (onlyPresenter == key) {
+                    return js;
                 } else {
-                    final MapObjs map = new MapObjs(onlyPresenter, now, key, js);
-                    onlyPresenter = null;
-                    return map;
+                    usePresenter = false;
                 }
             }
+            if (now == null) {
+                return new MapObjs(key, js);
+            } else {
+                return new MapObjs(onlyPresenter, now, key, js);
+            }
         }
     }
 
diff --git a/ko4j/src/test/java/org/netbeans/html/ko4j/MapObjsTest.java b/ko4j/src/test/java/org/netbeans/html/ko4j/MapObjsTest.java
new file mode 100644
index 0000000..43c5c18
--- /dev/null
+++ b/ko4j/src/test/java/org/netbeans/html/ko4j/MapObjsTest.java
@@ -0,0 +1,84 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.html.ko4j;
+
+import java.io.Reader;
+import java.net.URL;
+import org.netbeans.html.boot.spi.Fn;
+import static org.testng.Assert.*;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class MapObjsTest {
+
+    private Pres p1;
+    private Pres p2;
+
+    public MapObjsTest() {
+    }
+
+    @BeforeMethod
+    public void setUpClass() throws Exception {
+        MapObjs.reset();
+        p1 = new Pres();
+        p2 = new Pres();
+    }
+
+    @Test
+    public void testValuesForP1P2() {
+        Value v1 = new Value();
+        Value v2 = new Value();
+
+        v1.put(p1, "p1");
+        v2.put(p1, "p1");
+        v1.put(p2, "p2");
+
+        assertEquals(v1.get(p1), "p1");
+        assertEquals(v2.get(p1), "p1");
+        assertEquals(v1.get(p2), "p2");
+        assertEquals(v2.get(p2), null);
+    }
+
+    private static final class Value {
+        private Object now;
+
+        void put(Fn.Presenter p, Object v) {
+            now = MapObjs.put(now, p, v);
+        }
+
+        Object get(Fn.Presenter p) {
+            return MapObjs.get(now, p);
+        }
+    }
+
+    private static final class Pres implements Fn.Presenter {
+        @Override
+        public Fn defineFn(String code, String... names) {
+            return null;
+        }
+
+        @Override
+        public void displayPage(URL page, Runnable onPageLoad) {
+        }
+
+        @Override
+        public void loadScript(Reader code) throws Exception {
+        }
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists