Letting BrwsrCtx invoke runnables correctly and reschedule them into the appropriate thread if necessary. Caching JavaScript objects in the hope to allow asynchronous execution of the JavaScript snippets.
1.1 --- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java Tue Mar 04 12:28:27 2014 +0100
1.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java Tue Mar 04 17:09:22 2014 +0100
1.3 @@ -43,6 +43,8 @@
1.4 package org.netbeans.html.boot.fx;
1.5
1.6 import java.io.BufferedReader;
1.7 +import java.io.Closeable;
1.8 +import java.io.IOException;
1.9 import java.io.Reader;
1.10 import java.net.URL;
1.11 import java.util.ArrayList;
1.12 @@ -234,11 +236,35 @@
1.13 }
1.14 }
1.15
1.16 - @Override public void execute(Runnable r) {
1.17 + @Override public void execute(final Runnable r) {
1.18 if (Platform.isFxApplicationThread()) {
1.19 - r.run();
1.20 + Closeable c = Fn.activate(this);
1.21 + try {
1.22 + r.run();
1.23 + } finally {
1.24 + try {
1.25 + c.close();
1.26 + } catch (IOException ex) {
1.27 + // ignore
1.28 + }
1.29 + }
1.30 } else {
1.31 - Platform.runLater(r);
1.32 + class Wrap implements Runnable {
1.33 + @Override
1.34 + public void run() {
1.35 + Closeable c = Fn.activate(AbstractFXPresenter.this);
1.36 + try {
1.37 + r.run();
1.38 + } finally {
1.39 + try {
1.40 + c.close();
1.41 + } catch (IOException ex) {
1.42 + // ignore
1.43 + }
1.44 + }
1.45 + }
1.46 + }
1.47 + Platform.runLater(new Wrap());
1.48 }
1.49 }
1.50
2.1 --- a/boot/src/main/java/net/java/html/boot/BrowserBuilder.java Tue Mar 04 12:28:27 2014 +0100
2.2 +++ b/boot/src/main/java/net/java/html/boot/BrowserBuilder.java Tue Mar 04 17:09:22 2014 +0100
2.3 @@ -51,11 +51,13 @@
2.4 import java.util.Collection;
2.5 import java.util.Enumeration;
2.6 import java.util.ServiceLoader;
2.7 +import java.util.concurrent.Executor;
2.8 import java.util.logging.Level;
2.9 import java.util.logging.Logger;
2.10 import net.java.html.BrwsrCtx;
2.11 import net.java.html.js.JavaScriptBody;
2.12 import org.apidesign.html.boot.spi.Fn;
2.13 +import org.apidesign.html.context.spi.Contexts;
2.14 import org.netbeans.html.boot.impl.FindResources;
2.15 import org.netbeans.html.boot.impl.FnContext;
2.16 import org.netbeans.html.boot.impl.FnUtils;
2.17 @@ -246,7 +248,15 @@
2.18 if (browserClass != null) {
2.19 browserClass[0] = newClazz;
2.20 }
2.21 - BrwsrCtx c = BrwsrCtx.findDefault(newClazz);
2.22 + Contexts.Builder cb = Contexts.newBuilder();
2.23 + if (!Contexts.fillInByProviders(newClazz, cb)) {
2.24 + LOG.log(Level.WARNING, "Using empty technology for {0}", newClazz);
2.25 + }
2.26 + if (currentP instanceof Executor) {
2.27 + cb.register(Executor.class, (Executor)currentP, 1000);
2.28 + }
2.29 + cb.register(Fn.Presenter.class, currentP, 1000);
2.30 + BrwsrCtx c = cb.build();
2.31 c.execute(this);
2.32 return;
2.33 }
3.1 --- a/context/src/main/java/net/java/html/BrwsrCtx.java Tue Mar 04 12:28:27 2014 +0100
3.2 +++ b/context/src/main/java/net/java/html/BrwsrCtx.java Tue Mar 04 17:09:22 2014 +0100
3.3 @@ -42,7 +42,7 @@
3.4 */
3.5 package net.java.html;
3.6
3.7 -import java.util.ServiceLoader;
3.8 +import java.util.concurrent.Executor;
3.9 import java.util.logging.Logger;
3.10 import org.netbeans.html.context.impl.CtxAccssr;
3.11 import org.netbeans.html.context.impl.CtxImpl;
3.12 @@ -88,7 +88,8 @@
3.13
3.14 /** Seeks for the default context that is associated with the requesting
3.15 * class. If no suitable context is found, a warning message is
3.16 - * printed and {@link #EMPTY} context is returned.
3.17 + * printed and {@link #EMPTY} context is returned. One can enter
3.18 + * a context by calling {@link #execute(java.lang.Runnable)}.
3.19 *
3.20 * @param requestor the class that makes the request
3.21 * @return appropriate context for the request
3.22 @@ -100,38 +101,7 @@
3.23 }
3.24
3.25 org.apidesign.html.context.spi.Contexts.Builder cb = Contexts.newBuilder();
3.26 - boolean found = false;
3.27 -
3.28 - ClassLoader l;
3.29 - try {
3.30 - l = requestor.getClassLoader();
3.31 - } catch (SecurityException ex) {
3.32 - l = null;
3.33 - }
3.34 -
3.35 - for (org.apidesign.html.context.spi.Contexts.Provider cp : ServiceLoader.load(
3.36 - org.apidesign.html.context.spi.Contexts.Provider.class, l
3.37 - )) {
3.38 - cp.fillContext(cb, requestor);
3.39 - found = true;
3.40 - }
3.41 - try {
3.42 - for (org.apidesign.html.context.spi.Contexts.Provider cp : ServiceLoader.load(org.apidesign.html.context.spi.Contexts.Provider.class, org.apidesign.html.context.spi.Contexts.Provider.class.getClassLoader())) {
3.43 - cp.fillContext(cb, requestor);
3.44 - found = true;
3.45 - }
3.46 - } catch (SecurityException ex) {
3.47 - if (!found) {
3.48 - throw ex;
3.49 - }
3.50 - // if we have some data from regular provides, go on
3.51 - }
3.52 - if (!found) {
3.53 - for (org.apidesign.html.context.spi.Contexts.Provider cp : ServiceLoader.load(org.apidesign.html.context.spi.Contexts.Provider.class)) {
3.54 - cp.fillContext(cb, requestor);
3.55 - found = true;
3.56 - }
3.57 - }
3.58 + boolean found = Contexts.fillInByProviders(requestor, cb);
3.59 if (!found) {
3.60 LOG.warning("No browser context found. Returning empty technology!");
3.61 return EMPTY;
3.62 @@ -140,21 +110,37 @@
3.63 }
3.64
3.65 /** Runs provided code in the context of this {@link BrwsrCtx}.
3.66 - * While the <code>exec</code> is running, the {@link #findDefault(java.lang.Class)}
3.67 - * method returns <code>this</code>. The provided code is executed
3.68 - * synchronously on the same thread;
3.69 - * the call returns when <code>exec.run()</code> is over.
3.70 + * If there is an {@link Executor} {@link Contexts#find(net.java.html.BrwsrCtx, java.lang.Class) registered in the context}
3.71 + * it is used to perform the given code. While the code <code>exec</code>
3.72 + * is running the value of {@link #findDefault(java.lang.Class)} returns
3.73 + * <code>this</code>. If the executor supports a single thread execution
3.74 + * policy, it may execute the runnable later (in such case this method
3.75 + * returns immediately). If the call to this method is done on the right
3.76 + * thread, the runnable should be executed synchronously.
3.77 *
3.78 * @param exec the code to execute
3.79 * @since 0.7.6
3.80 */
3.81 - public final void execute(Runnable exec) {
3.82 - BrwsrCtx prev = CURRENT.get();
3.83 - try {
3.84 - CURRENT.set(this);
3.85 - exec.run();
3.86 - } finally {
3.87 - CURRENT.set(prev);
3.88 + public final void execute(final Runnable exec) {
3.89 + class Wrap implements Runnable {
3.90 + @Override
3.91 + public void run() {
3.92 + BrwsrCtx prev = CURRENT.get();
3.93 + try {
3.94 + CURRENT.set(BrwsrCtx.this);
3.95 + exec.run();
3.96 + } finally {
3.97 + CURRENT.set(prev);
3.98 + }
3.99 + }
3.100 + }
3.101 + Wrap w = new Wrap();
3.102 + Executor runIn = Contexts.find(this, Executor.class);
3.103 + if (runIn == null) {
3.104 + w.run();
3.105 + } else {
3.106 + runIn.execute(w);
3.107 }
3.108 }
3.109 }
3.110 +
4.1 --- a/context/src/main/java/org/apidesign/html/context/spi/Contexts.java Tue Mar 04 12:28:27 2014 +0100
4.2 +++ b/context/src/main/java/org/apidesign/html/context/spi/Contexts.java Tue Mar 04 17:09:22 2014 +0100
4.3 @@ -42,6 +42,7 @@
4.4 */
4.5 package org.apidesign.html.context.spi;
4.6
4.7 +import java.util.ServiceLoader;
4.8 import net.java.html.BrwsrCtx;
4.9 import org.netbeans.html.context.impl.CtxImpl;
4.10
4.11 @@ -77,6 +78,47 @@
4.12 return CtxImpl.find(context, technology);
4.13 }
4.14
4.15 + /** Seeks {@link ServiceLoader} for all registered instances of
4.16 + * {@link Provider} and asks them to {@link Provider#fillContext(org.apidesign.html.context.spi.Contexts.Builder, java.lang.Class) fill
4.17 + * the builder}.
4.18 + *
4.19 + * @param requestor the application class for which to find the context
4.20 + * @param cb the context builder to register technologies into
4.21 + * @return <code>true</code>, if some instances of the provider were
4.22 + * found, <code>false</code> otherwise
4.23 + * @since 0.7.6
4.24 + */
4.25 + public static boolean fillInByProviders(Class<?> requestor, Contexts.Builder cb) {
4.26 + boolean found = false;
4.27 + ClassLoader l;
4.28 + try {
4.29 + l = requestor.getClassLoader();
4.30 + } catch (SecurityException ex) {
4.31 + l = null;
4.32 + }
4.33 + for (Provider cp : ServiceLoader.load(Provider.class, l)) {
4.34 + cp.fillContext(cb, requestor);
4.35 + found = true;
4.36 + }
4.37 + try {
4.38 + for (Provider cp : ServiceLoader.load(Provider.class, Provider.class.getClassLoader())) {
4.39 + cp.fillContext(cb, requestor);
4.40 + found = true;
4.41 + }
4.42 + } catch (SecurityException ex) {
4.43 + if (!found) {
4.44 + throw ex;
4.45 + }
4.46 + }
4.47 + if (!found) {
4.48 + for (Provider cp : ServiceLoader.load(Provider.class)) {
4.49 + cp.fillContext(cb, requestor);
4.50 + found = true;
4.51 + }
4.52 + }
4.53 + return found;
4.54 + }
4.55 +
4.56 /** Implementors of various HTML technologies should
4.57 * register their implementation via {@link java.util.ServiceProvider} so
4.58 * {@link java.util.ServiceProvider} can find them, when their JARs are included
4.59 @@ -144,4 +186,18 @@
4.60 return impl.build();
4.61 }
4.62 }
4.63 +
4.64 + /** Injects a {@link BrwsrCtx} into a technology registered by
4.65 + * {@link Builder#register(java.lang.Class, java.lang.Object, int)} when
4.66 + * appropriate context is created.
4.67 + *
4.68 + * @since 0.7.6
4.69 + */
4.70 + public interface CtxAware {
4.71 + /** Injects associated context into an technology.
4.72 + *
4.73 + * @param ctx the context this technology is registed in
4.74 + */
4.75 + public void injectCtx(BrwsrCtx ctx);
4.76 + }
4.77 }
5.1 --- a/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java Tue Mar 04 12:28:27 2014 +0100
5.2 +++ b/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java Tue Mar 04 17:09:22 2014 +0100
5.3 @@ -46,6 +46,7 @@
5.4 import java.util.Collections;
5.5 import java.util.List;
5.6 import net.java.html.BrwsrCtx;
5.7 +import org.apidesign.html.context.spi.Contexts;
5.8
5.9 /** Implementation detail. Holds list of technologies for particular
5.10 * {@link BrwsrCtx}.
5.11 @@ -75,8 +76,16 @@
5.12
5.13 public BrwsrCtx build() {
5.14 Collections.sort(techs);
5.15 - CtxImpl impl = new CtxImpl(Collections.unmodifiableList(techs));
5.16 - return CtxAccssr.getDefault().newContext(impl);
5.17 + final List<Bind<?>> arr = Collections.unmodifiableList(techs);
5.18 + CtxImpl impl = new CtxImpl(arr);
5.19 + BrwsrCtx ctx = CtxAccssr.getDefault().newContext(impl);
5.20 + for (Bind<?> b : arr) {
5.21 + if (b.impl instanceof Contexts.CtxAware) {
5.22 + Contexts.CtxAware aw = (Contexts.CtxAware)b.impl;
5.23 + aw.injectCtx(ctx);
5.24 + }
5.25 + }
5.26 + return ctx;
5.27 }
5.28
5.29 public <Tech> void register(Class<Tech> type, Tech impl, int priority) {
6.1 --- a/json/src/main/java/org/apidesign/html/json/spi/JSONCall.java Tue Mar 04 12:28:27 2014 +0100
6.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/JSONCall.java Tue Mar 04 17:09:22 2014 +0100
6.3 @@ -45,6 +45,7 @@
6.4 import java.io.IOException;
6.5 import java.io.OutputStream;
6.6 import net.java.html.BrwsrCtx;
6.7 +import org.apidesign.html.context.spi.Contexts;
6.8 import org.netbeans.html.json.impl.JSON;
6.9 import org.netbeans.html.json.impl.RcvrJSON;
6.10
6.11 @@ -123,7 +124,7 @@
6.12 }
6.13
6.14 private void dispatch(final RcvrJSON.MsgEvnt ev) {
6.15 - JSON.runInBrowser(ctx, new Runnable() {
6.16 + ctx.execute(new Runnable() {
6.17 @Override
6.18 public void run() {
6.19 ev.dispatch(whenDone);
7.1 --- a/json/src/main/java/org/apidesign/html/json/spi/Proto.java Tue Mar 04 12:28:27 2014 +0100
7.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Proto.java Tue Mar 04 17:09:22 2014 +0100
7.3 @@ -154,7 +154,7 @@
7.4 * @param run the action to execute
7.5 */
7.6 public void runInBrowser(Runnable run) {
7.7 - JSON.runInBrowser(context, run);
7.8 + context.execute(run);
7.9 }
7.10
7.11 /** Initializes the provided collection with a content of the <code>array</code>.
8.1 --- a/json/src/main/java/org/netbeans/html/json/impl/JSON.java Tue Mar 04 12:28:27 2014 +0100
8.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSON.java Tue Mar 04 17:09:22 2014 +0100
8.3 @@ -80,16 +80,6 @@
8.4 return t == null ? EmptyTech.EMPTY : t;
8.5 }
8.6
8.7 - public static void runInBrowser(final BrwsrCtx c, final Runnable runnable) {
8.8 - class Wrap implements Runnable {
8.9 - @Override
8.10 - public void run() {
8.11 - c.execute(runnable);
8.12 - }
8.13 - }
8.14 - findTechnology(c).runSafe(new Wrap());
8.15 - }
8.16 -
8.17 public static void extract(BrwsrCtx c, Object value, String[] props, Object[] values) {
8.18 Transfer t = findTransfer(c);
8.19 t.extract(value, props, values);
9.1 --- a/ko-osgi-test/src/main/java/org/netbeans/html/ko/osgi/test/KnockoutEquinoxTCKImpl.java Tue Mar 04 12:28:27 2014 +0100
9.2 +++ b/ko-osgi-test/src/main/java/org/netbeans/html/ko/osgi/test/KnockoutEquinoxTCKImpl.java Tue Mar 04 17:09:22 2014 +0100
9.3 @@ -53,6 +53,7 @@
9.4 import java.net.URLConnection;
9.5 import java.util.Map;
9.6 import java.util.concurrent.Callable;
9.7 +import java.util.concurrent.Executor;
9.8 import java.util.concurrent.Executors;
9.9 import net.java.html.BrwsrCtx;
9.10 import net.java.html.boot.BrowserBuilder;
9.11 @@ -143,7 +144,8 @@
9.12 Object fx = cnstr.newInstance(browserContext);
9.13 Contexts.Builder cb = Contexts.newBuilder().
9.14 register(Technology.class, (Technology)fx, 10).
9.15 - register(Transfer.class, (Transfer)fx, 10);
9.16 + register(Transfer.class, (Transfer)fx, 10).
9.17 + register(Executor.class, (Executor)browserContext, 10);
9.18 // if (fx.areWebSocketsSupported()) {
9.19 // cb.register(WSTransfer.class, fx, 10);
9.20 // }
10.1 --- a/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusKnockoutTest.java Tue Mar 04 12:28:27 2014 +0100
10.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusKnockoutTest.java Tue Mar 04 17:09:22 2014 +0100
10.3 @@ -54,6 +54,7 @@
10.4 import java.util.ArrayList;
10.5 import java.util.List;
10.6 import java.util.Map;
10.7 +import java.util.concurrent.Executor;
10.8 import java.util.concurrent.Executors;
10.9 import net.java.html.BrwsrCtx;
10.10 import net.java.html.boot.BrowserBuilder;
10.11 @@ -154,7 +155,10 @@
10.12 Contexts.Builder cb = Contexts.newBuilder().
10.13 register(Technology.class, ko.knockout(), 10).
10.14 register(Transfer.class, tc, 10).
10.15 - register(WSTransfer.class, tc, 10);
10.16 + register(WSTransfer.class, tc, 10).
10.17 + register(Executor.class, (Executor)browserContext, 10).
10.18 + register(Fn.Presenter.class, (Fn.Presenter)browserContext, 10);
10.19 +
10.20 return cb.build();
10.21 }
10.22
11.1 --- a/ko4j/src/main/java/org/netbeans/html/ko4j/FXContext.java Tue Mar 04 12:28:27 2014 +0100
11.2 +++ b/ko4j/src/main/java/org/netbeans/html/ko4j/FXContext.java Tue Mar 04 17:09:22 2014 +0100
11.3 @@ -51,8 +51,10 @@
11.4 import java.net.URL;
11.5 import java.util.concurrent.Executor;
11.6 import java.util.logging.Logger;
11.7 +import net.java.html.BrwsrCtx;
11.8 import net.java.html.js.JavaScriptBody;
11.9 import org.apidesign.html.boot.spi.Fn;
11.10 +import org.apidesign.html.context.spi.Contexts;
11.11 import org.apidesign.html.json.spi.FunctionBinding;
11.12 import org.apidesign.html.json.spi.JSONCall;
11.13 import org.apidesign.html.json.spi.PropertyBinding;
11.14 @@ -69,13 +71,19 @@
11.15 */
11.16 final class FXContext
11.17 implements Technology.BatchInit<Object>, Technology.ValueMutated<Object>,
11.18 -Transfer, WSTransfer<LoadWS> {
11.19 +Transfer, WSTransfer<LoadWS>, Contexts.CtxAware {
11.20 static final Logger LOG = Logger.getLogger(FXContext.class.getName());
11.21 private static Boolean javaScriptEnabled;
11.22 - private final Fn.Presenter browserContext;
11.23 + private BrwsrCtx browserContext;
11.24 + private Object[] jsObjects;
11.25 + private int jsIndex;
11.26
11.27 public FXContext(Fn.Presenter browserContext) {
11.28 - this.browserContext = browserContext;
11.29 + Contexts.Builder cb = Contexts.newBuilder();
11.30 + if (browserContext instanceof Executor) {
11.31 + cb.register(Executor.class, (Executor)browserContext, 1000);
11.32 + }
11.33 + this.browserContext = cb.build();
11.34 }
11.35
11.36 @JavaScriptBody(args = {}, body = "if (window) return true; else return false;")
11.37 @@ -125,13 +133,24 @@
11.38 for (int i = 0; i < funcNames.length; i++) {
11.39 funcNames[i] = funcArr[i].getFunctionName();
11.40 }
11.41 - Object ret = Knockout.wrapModel(model,
11.42 + Object ret = getJSObject();
11.43 + Knockout.wrapModel(ret, model,
11.44 propNames, propReadOnly, propValues, propArr,
11.45 funcNames, funcArr
11.46 );
11.47 return ret;
11.48 }
11.49
11.50 + private Object getJSObject() {
11.51 + int len = 64;
11.52 + if (jsObjects != null && jsIndex < (len = jsObjects.length)) {
11.53 + return jsObjects[jsIndex++];
11.54 + }
11.55 + jsObjects = Knockout.allocJS(len * 2);
11.56 + jsIndex = 1;
11.57 + return jsObjects[0];
11.58 + }
11.59 +
11.60 @Override
11.61 public Object wrapModel(Object model) {
11.62 throw new UnsupportedOperationException();
11.63 @@ -213,26 +232,7 @@
11.64
11.65 @Override
11.66 public void runSafe(final Runnable r) {
11.67 - class Wrap implements Runnable {
11.68 - @Override public void run() {
11.69 - Closeable c = Fn.activate(browserContext);
11.70 - try {
11.71 - r.run();
11.72 - } finally {
11.73 - try {
11.74 - c.close();
11.75 - } catch (IOException ex) {
11.76 - // cannot be thrown
11.77 - }
11.78 - }
11.79 - }
11.80 - }
11.81 - Wrap w = new Wrap();
11.82 - if (browserContext instanceof Executor) {
11.83 - ((Executor)browserContext).execute(w);
11.84 - } else {
11.85 - w.run();
11.86 - }
11.87 + browserContext.execute(r);
11.88 }
11.89
11.90 @Override
11.91 @@ -250,6 +250,11 @@
11.92 socket.close();
11.93 }
11.94
11.95 + @Override
11.96 + public void injectCtx(BrwsrCtx ctx) {
11.97 + browserContext = ctx;
11.98 + }
11.99 +
11.100 private static final class TrueFn extends Fn implements Fn.Presenter {
11.101 @Override
11.102 public Object invoke(Object thiz, Object... args) throws Exception {
12.1 --- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java Tue Mar 04 12:28:27 2014 +0100
12.2 +++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java Tue Mar 04 17:09:22 2014 +0100
12.3 @@ -78,12 +78,18 @@
12.4 @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);\n")
12.5 native static void applyBindings(Object bindings);
12.6
12.7 + @JavaScriptBody(args = { "cnt" }, body =
12.8 + "var arr = new Array(cnt);\n" +
12.9 + "for (var i = 0; i < cnt; i++) arr[i] = new Object();\n" +
12.10 + "return arr;\n"
12.11 + )
12.12 + native static Object[] allocJS(int cnt);
12.13 +
12.14 @JavaScriptBody(
12.15 javacall = true,
12.16 - args = {"model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
12.17 - body
12.18 - = "var ret = {};\n"
12.19 - + "ret['ko-fx.model'] = model;\n"
12.20 + args = {"ret", "model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
12.21 + body =
12.22 + "ret['ko-fx.model'] = model;\n"
12.23 + "function koComputed(name, readOnly, value, prop) {\n"
12.24 + " function realGetter() {\n"
12.25 + " try {\n"
12.26 @@ -126,10 +132,9 @@
12.27 + "for (var i = 0; i < funcNames.length; i++) {\n"
12.28 + " koExpose(funcNames[i], funcArr[i]);\n"
12.29 + "}\n"
12.30 - + "return ret;\n"
12.31 )
12.32 - static native Object wrapModel(
12.33 - Object model,
12.34 + static native void wrapModel(
12.35 + Object ret, Object model,
12.36 String[] propNames, boolean[] propReadOnly, Object propValues, PropertyBinding[] propArr,
12.37 String[] funcNames, FunctionBinding[] funcArr
12.38 );
13.1 --- a/ko4j/src/test/java/org/netbeans/html/ko4j/KnockoutFXTest.java Tue Mar 04 12:28:27 2014 +0100
13.2 +++ b/ko4j/src/test/java/org/netbeans/html/ko4j/KnockoutFXTest.java Tue Mar 04 17:09:22 2014 +0100
13.3 @@ -54,6 +54,7 @@
13.4 import java.util.ArrayList;
13.5 import java.util.List;
13.6 import java.util.Map;
13.7 +import java.util.concurrent.Executor;
13.8 import java.util.concurrent.Executors;
13.9 import net.java.html.BrwsrCtx;
13.10 import net.java.html.boot.BrowserBuilder;
13.11 @@ -160,7 +161,10 @@
13.12 if (fx.areWebSocketsSupported()) {
13.13 cb.register(WSTransfer.class, fx, 10);
13.14 }
13.15 - return cb.build();
13.16 + cb.register(Executor.class, (Executor)browserContext, 10);
13.17 + cb.register(Fn.Presenter.class, browserContext, 10);
13.18 + BrwsrCtx ctx = cb.build();
13.19 + return ctx;
13.20 }
13.21
13.22 @Override