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 2017/09/03 12:48:54 UTC

[21/24] incubator-netbeans-html4j git commit: [INFRA-15006] Initial donation of HTML/Java NetBeans API. Equivalent to the content of html4j-donation-review.zip donated as part of ApacheNetBeansDonation1.zip with SHA256 being 7f2ca0f61953a190613c9a0fbcc1b

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-script/src/test/java/net/java/html/boot/script/ko4j/DynamicHTTP.java
----------------------------------------------------------------------
diff --git a/boot-script/src/test/java/net/java/html/boot/script/ko4j/DynamicHTTP.java b/boot-script/src/test/java/net/java/html/boot/script/ko4j/DynamicHTTP.java
new file mode 100644
index 0000000..a408c3b
--- /dev/null
+++ b/boot-script/src/test/java/net/java/html/boot/script/ko4j/DynamicHTTP.java
@@ -0,0 +1,261 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.boot.script.ko4j;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.glassfish.grizzly.PortRange;
+import org.glassfish.grizzly.http.server.HttpHandler;
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.grizzly.http.server.NetworkListener;
+import org.glassfish.grizzly.http.server.Request;
+import org.glassfish.grizzly.http.server.Response;
+import org.glassfish.grizzly.http.server.ServerConfiguration;
+import org.glassfish.grizzly.websockets.WebSocket;
+import org.glassfish.grizzly.websockets.WebSocketAddOn;
+import org.glassfish.grizzly.websockets.WebSocketApplication;
+import org.glassfish.grizzly.websockets.WebSocketEngine;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+final class DynamicHTTP extends HttpHandler {
+    private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName());
+    private static int resourcesCount;
+    private static List<Resource> resources;
+    private static ServerConfiguration conf;
+    private static HttpServer server;
+
+    private DynamicHTTP() {
+    }
+
+    static URI initServer() throws Exception {
+        server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
+        final WebSocketAddOn addon = new WebSocketAddOn();
+        for (NetworkListener listener : server.getListeners()) {
+            listener.registerAddOn(addon);
+        }
+        resources = new ArrayList<Resource>();
+
+        conf = server.getServerConfiguration();
+        final DynamicHTTP dh = new DynamicHTTP();
+
+        conf.addHttpHandler(dh, "/");
+
+        server.start();
+
+        return pageURL("http", server, "/test.html");
+    }
+
+    @Override
+    public void service(Request request, Response response) throws Exception {
+        if ("/test.html".equals(request.getRequestURI())) {
+            response.setContentType("text/html");
+            final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
+            copyStream(is, response.getOutputStream(), null);
+            return;
+        }
+        if ("/dynamic".equals(request.getRequestURI())) {
+            String mimeType = request.getParameter("mimeType");
+            List<String> params = new ArrayList<String>();
+            boolean webSocket = false;
+            for (int i = 0;; i++) {
+                String p = request.getParameter("param" + i);
+                if (p == null) {
+                    break;
+                }
+                if ("protocol:ws".equals(p)) {
+                    webSocket = true;
+                    continue;
+                }
+                params.add(p);
+            }
+            final String cnt = request.getParameter("content");
+            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
+            ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
+            URI url;
+            final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
+            if (webSocket) {
+                url = registerWebSocket(res);
+            } else {
+                url = registerResource(res);
+            }
+            response.getWriter().write(url.toString());
+            response.getWriter().write("\n");
+            return;
+        }
+
+        for (Resource r : resources) {
+            if (r.httpPath.equals(request.getRequestURI())) {
+                response.setContentType(r.httpType);
+                r.httpContent.reset();
+                String[] params = null;
+                if (r.parameters.length != 0) {
+                    params = new String[r.parameters.length];
+                    for (int i = 0; i < r.parameters.length; i++) {
+                        params[i] = request.getParameter(r.parameters[i]);
+                        if (params[i] == null) {
+                            if ("http.method".equals(r.parameters[i])) {
+                                params[i] = request.getMethod().toString();
+                            } else if ("http.requestBody".equals(r.parameters[i])) {
+                                Reader rdr = request.getReader();
+                                StringBuilder sb = new StringBuilder();
+                                for (;;) {
+                                    int ch = rdr.read();
+                                    if (ch == -1) {
+                                        break;
+                                    }
+                                    sb.append((char) ch);
+                                }
+                                params[i] = sb.toString();
+                            } else if (r.parameters[i].startsWith("http.header.")) {
+                                params[i] = request.getHeader(r.parameters[i].substring(12));
+                            }
+                        }
+                        if (params[i] == null) {
+                            params[i] = "null";
+                        }
+                    }
+                }
+
+                copyStream(r.httpContent, response.getOutputStream(), null, params);
+            }
+        }
+    }
+
+    private URI registerWebSocket(Resource r) {
+        WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
+        return pageURL("ws", server, r.httpPath);
+    }
+
+    private URI registerResource(Resource r) {
+        if (!resources.contains(r)) {
+            resources.add(r);
+            conf.addHttpHandler(this, r.httpPath);
+        }
+        return pageURL("http", server, r.httpPath);
+    }
+
+    private static URI pageURL(String proto, HttpServer server, final String page) {
+        NetworkListener listener = server.getListeners().iterator().next();
+        int port = listener.getPort();
+        try {
+            return new URI(proto + "://localhost:" + port + page);
+        } catch (URISyntaxException ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    static final class Resource {
+
+        final InputStream httpContent;
+        final String httpType;
+        final String httpPath;
+        final String[] parameters;
+
+        Resource(InputStream httpContent, String httpType, String httpPath,
+            String[] parameters) {
+            httpContent.mark(Integer.MAX_VALUE);
+            this.httpContent = httpContent;
+            this.httpType = httpType;
+            this.httpPath = httpPath;
+            this.parameters = parameters;
+        }
+    }
+
+    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
+        for (;;) {
+            int ch = is.read();
+            if (ch == -1) {
+                break;
+            }
+            if (ch == '$' && params.length > 0) {
+                int cnt = is.read() - '0';
+                if (baseURL != null && cnt == 'U' - '0') {
+                    os.write(baseURL.getBytes("UTF-8"));
+                } else {
+                    if (cnt >= 0 && cnt < params.length) {
+                        os.write(params[cnt].getBytes("UTF-8"));
+                    } else {
+                        os.write('$');
+                        os.write(cnt + '0');
+                    }
+                }
+            } else {
+                os.write(ch);
+            }
+        }
+    }
+
+    private static class WS extends WebSocketApplication {
+        private final Resource r;
+
+        private WS(Resource r) {
+            this.r = r;
+        }
+
+        @Override
+        public void onMessage(WebSocket socket, String text) {
+            try {
+                r.httpContent.reset();
+                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                copyStream(r.httpContent, out, null, text);
+                String s = new String(out.toByteArray(), "UTF-8");
+                socket.send(s);
+            } catch (IOException ex) {
+                LOG.log(Level.WARNING, "Error processing message " + text, ex);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-script/src/test/java/net/java/html/boot/script/ko4j/KOCase.java
----------------------------------------------------------------------
diff --git a/boot-script/src/test/java/net/java/html/boot/script/ko4j/KOCase.java b/boot-script/src/test/java/net/java/html/boot/script/ko4j/KOCase.java
new file mode 100644
index 0000000..0498ea8
--- /dev/null
+++ b/boot-script/src/test/java/net/java/html/boot/script/ko4j/KOCase.java
@@ -0,0 +1,140 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.boot.script.ko4j;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.netbeans.html.boot.spi.Fn;
+import org.testng.ITest;
+import org.testng.SkipException;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public final class KOCase implements ITest, Runnable {
+    static final Executor JS = Executors.newSingleThreadExecutor();
+    private final Fn.Presenter p;
+    private final Method m;
+    private final String skipMsg;
+    private Object result;
+    private Object inst;
+    private int count;
+
+    KOCase(Fn.Presenter p, Method m, String skipMsg) {
+        this.p = p;
+        this.m = m;
+        this.skipMsg = skipMsg;
+    }
+
+    @Override
+    public String getTestName() {
+        return m.getName();
+    }
+
+    @Test
+    public synchronized void executeTest() throws Exception {
+        if (skipMsg != null) {
+            throw new SkipException(skipMsg);
+        }
+        if (result == null) {
+            JS.execute(this);
+            wait();
+        }
+        if (result instanceof Exception) {
+            throw (Exception)result;
+        }
+        if (result instanceof Error) {
+            throw (Error)result;
+        }
+    }
+
+    @Override
+    public synchronized void run() {
+        boolean notify = true;
+        Closeable a = Fn.activate(p);
+        try {
+            if (inst == null) {
+                inst = m.getDeclaringClass().newInstance();
+            }
+            result = m.invoke(inst);
+            if (result == null) {
+                result = this;
+            }
+        } catch (InvocationTargetException ex) {
+            Throwable r = ex.getTargetException();
+            if (r instanceof InterruptedException) {
+                if (count++ < 1000) {
+                    notify = false;
+                    try {
+                        Thread.sleep(30);
+                    } catch (InterruptedException ignore) {
+                        // just go on
+                    }
+                    JS.execute(this);
+                    return;
+                }
+            }
+            result = r;
+        } catch (Exception ex) {
+            result = ex;
+        } finally {
+            if (notify) {
+                notifyAll();
+            }
+            try {
+                a.close();
+            } catch (IOException ex) {
+                throw new IllegalStateException(ex);
+            }
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-script/src/test/java/net/java/html/boot/script/ko4j/KnockoutEnvJSTest.java
----------------------------------------------------------------------
diff --git a/boot-script/src/test/java/net/java/html/boot/script/ko4j/KnockoutEnvJSTest.java b/boot-script/src/test/java/net/java/html/boot/script/ko4j/KnockoutEnvJSTest.java
new file mode 100644
index 0000000..8ed88c5
--- /dev/null
+++ b/boot-script/src/test/java/net/java/html/boot/script/ko4j/KnockoutEnvJSTest.java
@@ -0,0 +1,266 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.boot.script.ko4j;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import net.java.html.BrwsrCtx;
+import net.java.html.boot.BrowserBuilder;
+import net.java.html.boot.script.Scripts;
+import net.java.html.js.JavaScriptBody;
+import org.netbeans.html.boot.spi.Fn;
+import org.netbeans.html.context.spi.Contexts;
+import org.netbeans.html.json.spi.Technology;
+import org.netbeans.html.json.spi.Transfer;
+import org.netbeans.html.json.tck.KOTest;
+import org.netbeans.html.json.tck.KnockoutTCK;
+import org.netbeans.html.ko4j.KO4J;
+import org.netbeans.html.wstyrus.TyrusContext;
+import org.openide.util.lookup.ServiceProvider;
+import org.testng.Assert;
+import static org.testng.Assert.*;
+import org.testng.annotations.Factory;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@ServiceProvider(service = KnockoutTCK.class)
+public final class KnockoutEnvJSTest extends KnockoutTCK {
+    private static Class<?> browserClass;
+    private static Fn.Presenter browserContext;
+    private static URI baseUri;
+
+    public KnockoutEnvJSTest() {
+    }
+
+    @Factory public static Object[] compatibilityTests() throws Exception {
+        try {
+            Class.forName("java.lang.FunctionalInterface");
+        } catch (ClassNotFoundException ex) {
+            // only runs on JDK8
+            return new Object[0];
+        }
+
+
+        Class[] arr = testClasses();
+        for (int i = 0; i < arr.length; i++) {
+            assertEquals(
+                arr[i].getClassLoader(),
+                KnockoutEnvJSTest.class.getClassLoader(),
+                "All classes loaded by the same classloader"
+            );
+        }
+
+        baseUri = DynamicHTTP.initServer();
+
+        final Fn.Presenter p = Scripts.createPresenter(KOCase.JS);
+        URL envNashorn = new URL("https://bugs.openjdk.java.net/secure/attachment/11894/env.nashorn.1.2-debug.js");
+        InputStream is = envNashorn.openStream();
+        p.loadScript(new InputStreamReader(is));
+        is.close();
+
+        final BrowserBuilder bb = BrowserBuilder.newBrowser(p).
+            loadClass(KnockoutEnvJSTest.class).
+            loadPage(baseUri.toString()).
+            invoke("initialized");
+
+        Executors.newSingleThreadExecutor().submit(new Runnable() {
+            @Override
+            public void run() {
+                bb.showAndWait();
+            }
+        });
+
+        ClassLoader l = getClassLoader();
+        List<Object> res = new ArrayList<Object>();
+        for (int i = 0; i < arr.length; i++) {
+            Class<?> c = Class.forName(arr[i].getName(), true, l);
+            seekKOTests(c, res);
+        }
+        return res.toArray();
+    }
+
+    private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
+        Class<? extends Annotation> koTest =
+            c.getClassLoader().loadClass(KOTest.class.getName()).
+            asSubclass(Annotation.class);
+        for (Method m : c.getMethods()) {
+            if (m.getAnnotation(koTest) != null) {
+                res.add(new KOCase(browserContext, m, skipMsg(m.getName())));
+            }
+        }
+    }
+
+    private static String skipMsg(String methodName) {
+        final String ver = System.getProperty("java.runtime.version"); // NOI18N
+        if (
+            ver.startsWith("1.8.0_25") ||
+            ver.startsWith("1.8.0_40")
+        ) {
+            return "Broken due to JDK-8047764";
+        }
+        if (
+            !ver.startsWith("1.8.0_")
+        ) {
+            // 1.8.0_ are and will remain broken
+            return null;
+        }
+        switch (methodName) {
+            case "paintTheGridOnClick":
+            case "displayContentOfArrayOfPeople":
+            case "connectUsingWebSocket":
+            case "selectWorksOnModels":
+            case "archetypeArrayModificationVisible":
+            case "noLongerNeededArrayElementsCanDisappear":
+                return "Does not work on JDK8, due to JDK-8046013";
+            case "modifyRadioValueOnEnum":
+                return "Does not work on JDK8";
+        }
+        return null;
+    }
+
+    static synchronized ClassLoader getClassLoader() throws InterruptedException {
+        while (browserClass == null) {
+            KnockoutEnvJSTest.class.wait();
+        }
+        return browserClass.getClassLoader();
+    }
+
+    public static synchronized void initialized(Class<?> browserCls) throws Exception {
+        browserClass = browserCls;
+        browserContext = Fn.activePresenter();
+        KnockoutEnvJSTest.class.notifyAll();
+    }
+
+    public static void initialized() throws Exception {
+        Assert.assertSame(
+            KnockoutEnvJSTest.class.getClassLoader(),
+            ClassLoader.getSystemClassLoader(),
+            "No special classloaders"
+        );
+        KnockoutEnvJSTest.initialized(KnockoutEnvJSTest.class);
+        browserContext = Fn.activePresenter();
+    }
+
+    @Override
+    public BrwsrCtx createContext() {
+        KO4J fx = new KO4J(browserContext);
+        TyrusContext tc = new TyrusContext();
+        Contexts.Builder cb = Contexts.newBuilder().
+            register(Technology.class, fx.knockout(), 10).
+            register(Transfer.class, tc, 10);
+        cb.register(Fn.Presenter.class, browserContext, 10);
+        cb.register(Executor.class, (Executor)browserContext, 10);
+        BrwsrCtx ctx = cb.build();
+        return ctx;
+    }
+
+    @Override
+    public Object createJSON(Map<String, Object> values) {
+        Object json = createJSON();
+        for (Map.Entry<String, Object> entry : values.entrySet()) {
+            setProperty(json, entry.getKey(), entry.getValue());
+        }
+        return json;
+    }
+
+    @JavaScriptBody(args = {}, body = "return new Object();")
+    private static native Object createJSON();
+    @JavaScriptBody(args = { "json", "key", "value" }, body = "json[key] = value;")
+    private static native void setProperty(Object json, String key, Object value);
+
+    @Override
+    @JavaScriptBody(args = { "s", "args" }, body = "\n"
+        + "var f = new Function(s);\n"
+        + "return f.apply(null, args);\n"
+    )
+    public native Object executeScript(String script, Object[] arguments);
+
+    private static String findBaseURL() {
+        return baseUri.toString();
+    }
+
+    @Override
+    public URI prepareURL(String content, String mimeType, String[] parameters) {
+        try {
+            final URL baseURL = new URL(findBaseURL());
+            StringBuilder sb = new StringBuilder();
+            sb.append("/dynamic?mimeType=").append(mimeType);
+            for (int i = 0; i < parameters.length; i++) {
+                sb.append("&param" + i).append("=").append(parameters[i]);
+            }
+            String mangle = content.replace("\n", "%0a")
+                .replace("\"", "\\\"").replace(" ", "%20");
+            sb.append("&content=").append(mangle);
+
+            URL query = new URL(baseURL, sb.toString());
+            URLConnection c = query.openConnection();
+            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
+            URI connectTo = new URI(br.readLine());
+            return connectTo;
+        } catch (IOException ex) {
+            throw new IllegalStateException(ex);
+        } catch (URISyntaxException ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    @Override
+    public boolean canFailWebSocketTest() {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-script/src/test/resources/net/java/html/boot/script/ko4j/test.html
----------------------------------------------------------------------
diff --git a/boot-script/src/test/resources/net/java/html/boot/script/ko4j/test.html b/boot-script/src/test/resources/net/java/html/boot/script/ko4j/test.html
new file mode 100644
index 0000000..af8ad2e
--- /dev/null
+++ b/boot-script/src/test/resources/net/java/html/boot/script/ko4j/test.html
@@ -0,0 +1,56 @@
+<!--
+
+    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+    Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+
+    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+    Other names may be trademarks of their respective owners.
+
+    The contents of this file are subject to the terms of either the GNU
+    General Public License Version 2 only ("GPL") or the Common
+    Development and Distribution License("CDDL") (collectively, the
+    "License"). You may not use this file except in compliance with the
+    License. You can obtain a copy of the License at
+    http://www.netbeans.org/cddl-gplv2.html
+    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+    specific language governing permissions and limitations under the
+    License.  When distributing the software, include this License Header
+    Notice in each file and include the License file at
+    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+    particular file as subject to the "Classpath" exception as provided
+    by Oracle in the GPL Version 2 section of the License file that
+    accompanied this code. If applicable, add the following below the
+    License Header, with the fields enclosed by brackets [] replaced by
+    your own identifying information:
+    "Portions Copyrighted [year] [name of copyright owner]"
+
+    Contributor(s):
+
+    The Original Software is NetBeans. The Initial Developer of the Original
+    Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+
+    If you wish your version of this file to be governed by only the CDDL
+    or only the GPL Version 2, indicate your decision by adding
+    "[Contributor] elects to include this software in this distribution
+    under the [CDDL or GPL Version 2] license." If you do not indicate a
+    single choice of license, a recipient has the option to distribute
+    your version of this file under either the CDDL, the GPL Version 2 or
+    to extend the choice of license to its licensees as provided above.
+    However, if you add GPL Version 2 code and therefore, elected the GPL
+    Version 2 license, then the option applies only if the new code is
+    made subject to such option by the copyright holder.
+
+-->
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Knockout.fx Execution Harness</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+        <meta name="viewport" content="width=device-width">
+    </head>
+    <body>
+        <h1>Knockout in Env.Execution Harness</h1>
+        <script></script>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/empty.sigtest
----------------------------------------------------------------------
diff --git a/boot-truffle/empty.sigtest b/boot-truffle/empty.sigtest
new file mode 100644
index 0000000..42942c0
--- /dev/null
+++ b/boot-truffle/empty.sigtest
@@ -0,0 +1,21 @@
+#Signature file v4.1
+#Version 2.0-SNAPSHOT
+
+CLSS public java.lang.Object
+cons public init()
+meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException
+meth protected void finalize() throws java.lang.Throwable
+meth public boolean equals(java.lang.Object)
+meth public final java.lang.Class<?> getClass()
+meth public final void notify()
+meth public final void notifyAll()
+meth public final void wait() throws java.lang.InterruptedException
+meth public final void wait(long) throws java.lang.InterruptedException
+meth public final void wait(long,int) throws java.lang.InterruptedException
+meth public int hashCode()
+meth public java.lang.String toString()
+
+CLSS public final net.java.html.boot.truffle.TrufflePresenters
+meth public static org.netbeans.html.boot.spi.Fn$Presenter create(java.util.concurrent.Executor)
+supr java.lang.Object
+

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/pom.xml
----------------------------------------------------------------------
diff --git a/boot-truffle/pom.xml b/boot-truffle/pom.xml
new file mode 100644
index 0000000..912aca0
--- /dev/null
+++ b/boot-truffle/pom.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+    Copyright 2013-2016 Oracle and/or its affiliates. All rights reserved.
+
+    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+    Other names may be trademarks of their respective owners.
+
+    The contents of this file are subject to the terms of either the GNU
+    General Public License Version 2 only ("GPL") or the Common
+    Development and Distribution License("CDDL") (collectively, the
+    "License"). You may not use this file except in compliance with the
+    License. You can obtain a copy of the License at
+    http://www.netbeans.org/cddl-gplv2.html
+    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+    specific language governing permissions and limitations under the
+    License.  When distributing the software, include this License Header
+    Notice in each file and include the License file at
+    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+    particular file as subject to the "Classpath" exception as provided
+    by Oracle in the GPL Version 2 section of the License file that
+    accompanied this code. If applicable, add the following below the
+    License Header, with the fields enclosed by brackets [] replaced by
+    your own identifying information:
+    "Portions Copyrighted [year] [name of copyright owner]"
+
+    Contributor(s):
+
+    The Original Software is NetBeans. The Initial Developer of the Original
+    Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+
+    If you wish your version of this file to be governed by only the CDDL
+    or only the GPL Version 2, indicate your decision by adding
+    "[Contributor] elects to include this software in this distribution
+    under the [CDDL or GPL Version 2] license." If you do not indicate a
+    single choice of license, a recipient has the option to distribute
+    your version of this file under either the CDDL, the GPL Version 2 or
+    to extend the choice of license to its licensees as provided above.
+    However, if you add GPL Version 2 code and therefore, elected the GPL
+    Version 2 license, then the option applies only if the new code is
+    made subject to such option by the copyright holder.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.netbeans.html</groupId>
+        <artifactId>pom</artifactId>
+        <version>2.0-SNAPSHOT</version>
+    </parent>
+    <name>Presenter via Truffle</name>
+    <artifactId>net.java.html.boot.truffle</artifactId>
+    <version>2.0-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+    <properties>
+        <netbeans.compile.on.save>NONE</netbeans.compile.on.save>
+        <publicPackages>net.java.html.boot.truffle</publicPackages>
+        <trufflejs>${java.home}/language/js/trufflejs.jar</trufflejs>
+        <skipTests>true</skipTests>
+    </properties>
+    <build>
+      <plugins>
+          <plugin>
+              <groupId>org.apache.felix</groupId>
+              <artifactId>maven-bundle-plugin</artifactId>
+              <extensions>true</extensions>
+              <configuration>
+                  <instructions>
+                      <Export-Package>${publicPackages}</Export-Package>
+                      <Bundle-SymbolicName>net.java.html.boot.truffle</Bundle-SymbolicName>
+                  </instructions>
+              </configuration>
+          </plugin>
+          <plugin>
+              <groupId>org.netbeans.html</groupId>
+              <artifactId>html4j-maven-plugin</artifactId>
+          </plugin>
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-compiler-plugin</artifactId>
+            <version>2.3.2</version>
+            <configuration>
+               <source>1.7</source>
+               <target>1.7</target>
+            </configuration>
+         </plugin>
+         <plugin>
+             <groupId>org.netbeans.tools</groupId>
+             <artifactId>sigtest-maven-plugin</artifactId>
+             <version>1.0</version>
+             <executions>
+                 <execution>
+                     <goals>
+                         <goal>generate</goal>
+                         <goal>check</goal>
+                     </goals>
+                 </execution>
+             </executions>
+             <configuration>
+                 <sigfile>empty.sigtest</sigfile>
+             </configuration>
+         </plugin>
+      </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.netbeans.api</groupId>
+            <artifactId>org-openide-util-lookup</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.oracle.truffle</groupId>
+            <artifactId>truffle-api</artifactId>
+            <version>0.18</version>
+        </dependency>
+        <dependency>
+            <groupId>com.oracle.truffle</groupId>
+            <artifactId>truffle-dsl-processor</artifactId>
+            <version>0.18</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.netbeans.html</groupId>
+            <artifactId>net.java.html.boot</artifactId>
+            <version>${project.version}</version>
+            <type>jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>net.java.html.json.tck</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.grizzly</groupId>
+            <artifactId>grizzly-http-server</artifactId>
+            <version>${grizzly.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.grizzly</groupId>
+            <artifactId>grizzly-websockets-server</artifactId>
+            <version>${grizzly.version}</version>
+            <scope>test</scope>
+            <type>jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.grizzly</groupId>
+            <artifactId>grizzly-http-servlet</artifactId>
+            <version>${grizzly.version}</version>
+            <scope>test</scope>
+        </dependency>    
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>test</scope>
+            <version>3.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.netbeans.html</groupId>
+            <artifactId>ko4j</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+            <type>jar</type>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>ko-ws-tyrus</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+            <type>jar</type>
+        </dependency>
+        <dependency>
+            <groupId>com.dukescript.libraries</groupId>
+            <artifactId>net.java.html.lib</artifactId>
+            <version>0.3</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <profiles>
+        <profile>
+            <id>graalvm</id>
+            <activation>
+                <file>
+                    <exists>${trufflejs}</exists>
+                </file>
+            </activation>
+            <properties>
+                <skipTests>false</skipTests>
+            </properties>
+            <dependencies>
+                <dependency>
+                    <groupId>com.oracle.graaljs</groupId>
+                    <artifactId>truffle-js</artifactId>
+                    <version>0.07</version>
+                    <systemPath>${trufflejs}</systemPath>
+                    <scope>system</scope>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/IsArrayNode.java
----------------------------------------------------------------------
diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/IsArrayNode.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/IsArrayNode.java
new file mode 100644
index 0000000..a4e8913
--- /dev/null
+++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/IsArrayNode.java
@@ -0,0 +1,68 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.boot.truffle;
+
+import com.oracle.truffle.api.TruffleLanguage;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.RootNode;
+
+final class IsArrayNode extends RootNode {
+    @Child
+    private Node check;
+
+    IsArrayNode() {
+        super(TruffleLanguage.class, null, null);
+        this.check = Message.HAS_SIZE.createNode();
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        final Object[] args = frame.getArguments();
+        Object result = ForeignAccess.sendHasSize(check, frame, (TruffleObject) args[0]);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/IsNullNode.java
----------------------------------------------------------------------
diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/IsNullNode.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/IsNullNode.java
new file mode 100644
index 0000000..250ae42
--- /dev/null
+++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/IsNullNode.java
@@ -0,0 +1,68 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.boot.truffle;
+
+import com.oracle.truffle.api.TruffleLanguage;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.RootNode;
+
+final class IsNullNode extends RootNode {
+    @Child
+    private Node check;
+
+    IsNullNode() {
+        super(TruffleLanguage.class, null, null);
+        this.check = Message.IS_NULL.createNode();
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        final Object[] args = frame.getArguments();
+        Object result = ForeignAccess.sendIsNull(check, frame, (TruffleObject) args[0]);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaArray.java
----------------------------------------------------------------------
diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaArray.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaArray.java
new file mode 100644
index 0000000..2e7c8a1
--- /dev/null
+++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaArray.java
@@ -0,0 +1,102 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.boot.truffle;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import java.lang.reflect.Array;
+
+@MessageResolution(receiverType = JavaArray.class, language = TrufflePresenter.JavaLang.class)
+final class JavaArray extends JavaValue implements TruffleObject {
+    final TrufflePresenter.WrapArray wrap;
+    final Object arr;
+
+    public JavaArray(TrufflePresenter.WrapArray wrap, Object arr) {
+        this.arr = arr;
+        this.wrap = wrap;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return JavaArrayForeign.ACCESS;
+    }
+
+    @Override
+    public Object get() {
+        return arr;
+    }
+
+    static boolean isInstance(TruffleObject obj) {
+        return obj instanceof JavaArray;
+    }
+
+    static boolean isArray(Object obj) {
+        return obj != null && obj.getClass().getComponentType() != null;
+    }
+
+    @Resolve(message = "READ")
+    static abstract class ReadNode extends Node {
+        protected Object access(JavaArray arr, int index) {
+            Object obj = Array.get(arr.arr, index);
+            return toJavaScript(obj, arr.wrap);
+        }
+    }
+
+    @Resolve(message = "HAS_SIZE")
+    static abstract class HasSizeNode extends Node {
+        protected boolean access(JavaArray arr) {
+            return true;
+        }
+    }
+
+    @Resolve(message = "GET_SIZE")
+    static abstract class GetSizeNode extends Node {
+        protected int access(JavaArray arr) {
+            return Array.getLength(arr.arr);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaObject.java
----------------------------------------------------------------------
diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaObject.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaObject.java
new file mode 100644
index 0000000..234f396
--- /dev/null
+++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaObject.java
@@ -0,0 +1,82 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.boot.truffle;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+
+@MessageResolution(receiverType = JavaObject.class, language = TrufflePresenter.JavaLang.class)
+final class JavaObject extends JavaValue implements TruffleObject {
+    final Object obj;
+
+    JavaObject(Object obj) {
+        this.obj = obj;
+    }
+
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return JavaObjectForeign.ACCESS;
+    }
+
+    public static boolean isInstance(TruffleObject obj) {
+        return obj instanceof JavaObject;
+    }
+
+    @Override
+    public Object get() {
+        return obj;
+    }
+
+    @Resolve(message = "HAS_SIZE")
+    static abstract class NoSizeNode extends Node {
+
+        protected boolean access(JavaObject obj) {
+            return false;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaValue.java
----------------------------------------------------------------------
diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaValue.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaValue.java
new file mode 100644
index 0000000..94bba23
--- /dev/null
+++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaValue.java
@@ -0,0 +1,91 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.boot.truffle;
+
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
+
+abstract class JavaValue {
+    public abstract Object get();
+
+    static Object toJavaScript(Object conv, TrufflePresenter.WrapArray wrap) {
+        if (conv instanceof TruffleObject) {
+            return conv;
+        }
+        if (JavaArray.isArray(conv)) {
+            conv = wrap.copy(new JavaArray(wrap, conv));
+        }
+        if (conv instanceof Character) {
+            conv = (int) (Character) conv;
+        }
+        if (conv == null || conv.getClass().getName().endsWith(".$JsCallbacks$")) { // NOI18N
+            conv = JavaInterop.asTruffleObject(conv);
+        } else if (!isJSReady(conv)) {
+            conv = new JavaObject(conv);
+        }
+        return conv;
+    }
+
+    private static boolean isJSReady(Object obj) {
+        if (obj == null) {
+            return true;
+        }
+        if (obj instanceof String) {
+            return true;
+        }
+        if (obj instanceof Number) {
+            return true;
+        }
+        if (obj instanceof Character) {
+            return true;
+        }
+        if (obj instanceof Boolean) {
+            return true;
+        }
+        if (obj instanceof TruffleObject) {
+            return true;
+        }
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenter.java
----------------------------------------------------------------------
diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenter.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenter.java
new file mode 100644
index 0000000..7d75efb
--- /dev/null
+++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenter.java
@@ -0,0 +1,293 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.boot.truffle;
+
+import com.oracle.truffle.api.CallTarget;
+import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.TruffleLanguage;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.Reader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+import org.netbeans.html.boot.spi.Fn;
+import org.netbeans.html.boot.spi.Fn.Presenter;
+
+/**
+ * Implementation of {@link Presenter} that delegates to Truffle.
+ *
+ * @author Jaroslav Tulach
+ */
+final class TrufflePresenter implements Fn.KeepAlive,
+    Presenter, Fn.FromJavaScript, Fn.ToJavaScript, Executor {
+
+    private Eval eval;
+    private WrapArray copy;
+    private final Executor exc;
+    private final CallTarget isNull;
+    private final CallTarget isArray;
+    private Apply apply;
+    private TruffleObject jsNull;
+
+    TrufflePresenter(Executor exc, TruffleObject eval) {
+        this.exc = exc;
+        this.eval = eval == null ? null : JavaInterop.asJavaFunction(Eval.class, eval);
+        this.isNull = Truffle.getRuntime().createCallTarget(new IsNullNode());
+        this.isArray = Truffle.getRuntime().createCallTarget(new IsArrayNode());
+    }
+
+    @Override
+    public Fn defineFn(String code, String... names) {
+        return defineImpl(code, names, null);
+    }
+
+    @Override
+    public Fn defineFn(String code, String[] names, boolean[] keepAlive) {
+        return defineImpl(code, names, keepAlive);
+    }
+
+    private FnImpl defineImpl(String code, String[] names, boolean[] keepAlive) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("(function() {\n");
+        sb.append("  var args = Array.prototype.slice.call(arguments);\n");
+        sb.append("  var thiz = args.shift();\n");
+        sb.append("  return (function(");
+        String sep = "";
+        for (String n : names) {
+            sb.append(sep).append(n);
+            sep = ",";
+        }
+        sb.append(") {\n");
+        sb.append(code);
+        sb.append("\n  }).apply(thiz, args);\n");
+        sb.append("})\n");
+
+        TruffleObject fn = (TruffleObject) getEval().eval(sb.toString());
+        return new FnImpl(this, fn, names.length);
+    }
+
+    @Override
+    public void displayPage(URL page, Runnable onPageLoad) {
+        if (onPageLoad != null) {
+            onPageLoad.run();
+        }
+    }
+
+    @Override
+    public void loadScript(Reader code) throws Exception {
+        Source src = Source.newBuilder(code).
+            name("unknown.js").
+            mimeType("text/javascript").
+            build();
+        getEval().eval(src.getCode());
+    }
+
+    interface Apply {
+        public Object apply(Object... args);
+    }
+
+    interface WrapArray {
+        public Object copy(Object arr);
+    }
+
+    interface Eval {
+        public Object eval(String code);
+    }
+
+    final Object checkArray(Object val) throws Exception {
+        if (val instanceof TruffleObject) {
+            final TruffleObject truffleObj = (TruffleObject)val;
+            boolean hasSize = (boolean) isArray.call(truffleObj);
+            if (hasSize) {
+                List<?> list = JavaInterop.asJavaObject(List.class, truffleObj);
+                Object[] arr = list.toArray();
+                for (int i = 0; i < arr.length; i++) {
+                    arr[i] = toJava(arr[i]);
+                }
+                return arr;
+            }
+        }
+        return val;
+    }
+
+    @Override
+    public Object toJava(Object jsArray) {
+        if (jsArray instanceof JavaValue) {
+            jsArray = ((JavaValue) jsArray).get();
+        }
+        if (jsArray instanceof TruffleObject) {
+            boolean checkNull = (boolean) isNull.call(jsArray);
+            if (checkNull) {
+                return null;
+            }
+        }
+        try {
+            return checkArray(jsArray);
+        } catch (Exception ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    @Override
+    public Object toJavaScript(Object conv) {
+        return JavaValue.toJavaScript(conv, getWrap());
+    }
+
+    @Override
+    public void execute(final Runnable command) {
+        if (Fn.activePresenter() == this) {
+            command.run();
+            return;
+        }
+
+        class Wrap implements Runnable {
+
+            @Override
+            public void run() {
+                try (Closeable c = Fn.activate(TrufflePresenter.this)) {
+                    command.run();
+                } catch (IOException ex) {
+                    throw new IllegalStateException(ex);
+                }
+            }
+        }
+        final Runnable wrap = new Wrap();
+        if (exc == null) {
+            wrap.run();
+        } else {
+            exc.execute(wrap);
+        }
+    }
+
+    private Eval getEval() {
+        if (eval == null) {
+            try {
+                final PolyglotEngine engine = PolyglotEngine.newBuilder().build();
+                TruffleObject fn = (TruffleObject) engine.eval(
+                    Source.newBuilder("eval.bind(this)").
+                        mimeType("text/javascript").
+                        name("eval.js").build()
+                ).get();
+                eval = JavaInterop.asJavaFunction(Eval.class, fn);
+            } catch (RuntimeException ex) {
+                throw ex;
+            } catch (Exception ex) {
+                throw new IllegalStateException(ex);
+            }
+        }
+        return eval;
+    }
+
+    private WrapArray getWrap() {
+        if (copy == null) {
+            TruffleObject fn = (TruffleObject) getEval().eval("(function(arr) {\n"
+                + "  var n = [];\n"
+                + "  for (var i = 0; i < arr.length; i++) {\n"
+                + "    n[i] = arr[i];\n"
+                + "  }\n"
+                + "  return n;\n"
+                + "}).bind(this)"
+            );
+            copy = JavaInterop.asJavaFunction(WrapArray.class, fn);
+        }
+        return copy;
+    }
+
+    private Apply getApply() {
+        if (apply == null) {
+            TruffleObject fn = (TruffleObject) getEval().eval("(function() {\n"
+                + "  var args = Array.prototype.slice.call(arguments);\n"
+                + "  var fn = args.shift();\n"
+                + "  return fn.apply(null, args);\n"
+                + "}).bind(this)"
+            );
+            apply = JavaInterop.asJavaFunction(Apply.class, fn);
+        }
+        return apply;
+    }
+
+    private TruffleObject jsNull() {
+        if (jsNull == null) {
+            jsNull = (TruffleObject) getEval().eval("null"); // NOI18N
+        }
+        return jsNull;
+    }
+
+    private class FnImpl extends Fn {
+
+        private final TruffleObject fn;
+
+        public FnImpl(Presenter presenter, TruffleObject fn, int arity) {
+            super(presenter);
+            this.fn = fn;
+        }
+
+        @Override
+        public Object invoke(Object thiz, Object... args) throws Exception {
+            List<Object> all = new ArrayList<>(args.length + 1);
+            all.add(fn);
+            all.add(thiz == null ? jsNull() : toJavaScript(thiz));
+            for (Object conv : args) {
+                conv = toJavaScript(conv);
+                all.add(conv);
+            }
+            Object ret = getApply().apply(all.toArray());
+            if (ret instanceof JavaValue) {
+                ret = ((JavaValue)ret).get();
+            }
+            if (ret == fn) {
+                return null;
+            }
+            return toJava(ret);
+        }
+    }
+
+    static abstract class JavaLang extends TruffleLanguage<Object> {
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenters.java
----------------------------------------------------------------------
diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenters.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenters.java
new file mode 100644
index 0000000..47df9d3
--- /dev/null
+++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenters.java
@@ -0,0 +1,66 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.boot.truffle;
+
+import java.util.concurrent.Executor;
+import org.netbeans.html.boot.spi.Fn;
+
+
+/** Integration with Truffle and
+ * <a href="http://www.oracle.com/technetwork/oracle-labs/program-languages/overview/">GraalVM</a>.
+ *
+ * @since 1.4
+ */
+public final class TrufflePresenters {
+    private TrufflePresenters() {
+    }
+
+    /** Creates new instance of Truffle based presenter.
+     *
+     * @param executor the executor to run requests in
+     * @return new instance of the presenter
+     */
+    public static Fn.Presenter create(Executor executor) {
+        return new TrufflePresenter(executor, null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/package.html
----------------------------------------------------------------------
diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/package.html b/boot-truffle/src/main/java/net/java/html/boot/truffle/package.html
new file mode 100644
index 0000000..321c3e9
--- /dev/null
+++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/package.html
@@ -0,0 +1,51 @@
+<!--
+
+    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+    Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+
+    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+    Other names may be trademarks of their respective owners.
+
+    The contents of this file are subject to the terms of either the GNU
+    General Public License Version 2 only ("GPL") or the Common
+    Development and Distribution License("CDDL") (collectively, the
+    "License"). You may not use this file except in compliance with the
+    License. You can obtain a copy of the License at
+    http://www.netbeans.org/cddl-gplv2.html
+    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+    specific language governing permissions and limitations under the
+    License.  When distributing the software, include this License Header
+    Notice in each file and include the License file at
+    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+    particular file as subject to the "Classpath" exception as provided
+    by Oracle in the GPL Version 2 section of the License file that
+    accompanied this code. If applicable, add the following below the
+    License Header, with the fields enclosed by brackets [] replaced by
+    your own identifying information:
+    "Portions Copyrighted [year] [name of copyright owner]"
+
+    Contributor(s):
+
+    The Original Software is NetBeans. The Initial Developer of the Original
+    Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+
+    If you wish your version of this file to be governed by only the CDDL
+    or only the GPL Version 2, indicate your decision by adding
+    "[Contributor] elects to include this software in this distribution
+    under the [CDDL or GPL Version 2] license." If you do not indicate a
+    single choice of license, a recipient has the option to distribute
+    your version of this file under either the CDDL, the GPL Version 2 or
+    to extend the choice of license to its licensees as provided above.
+    However, if you add GPL Version 2 code and therefore, elected the GPL
+    Version 2 license, then the option applies only if the new code is
+    made subject to such option by the copyright holder.
+
+-->
+<body>
+    <p>
+        Integration with <a href="http://github.com/graalvm/truffle">Truffle</a>
+        useful to execute against <b>node.js</b> running on top of
+        the <a href="http://www.oracle.com/technetwork/oracle-labs/program-languages/overview/">GraalVM</a>.
+    </p>
+</body>

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/test/java/net/java/html/boot/truffle/JsArrayTruffleTest.java
----------------------------------------------------------------------
diff --git a/boot-truffle/src/test/java/net/java/html/boot/truffle/JsArrayTruffleTest.java b/boot-truffle/src/test/java/net/java/html/boot/truffle/JsArrayTruffleTest.java
new file mode 100644
index 0000000..1b7c4f0
--- /dev/null
+++ b/boot-truffle/src/test/java/net/java/html/boot/truffle/JsArrayTruffleTest.java
@@ -0,0 +1,140 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.boot.truffle;
+
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import java.io.Closeable;
+import java.io.IOException;
+import net.java.html.lib.Array;
+import net.java.html.lib.Function;
+import org.netbeans.html.boot.spi.Fn;
+import org.testng.Assert;
+import static org.testng.Assert.assertEquals;
+import org.testng.SkipException;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class JsArrayTruffleTest {
+    private Fn.Presenter presenter;
+    private Closeable close;
+    
+    @BeforeMethod
+    public void initializePresenter() throws Exception {
+        PolyglotEngine engine = PolyglotEngine.newBuilder().build();
+        int fourtyTwo;
+        try {
+            fourtyTwo = engine.eval(
+                Source.newBuilder("6 * 7").
+                mimeType("text/javascript").
+                name("meaning.js").
+                build()
+            ).as(Number.class).intValue();
+            presenter = TrufflePresenters.create(null);
+            close = Fn.activate(presenter);
+        } catch (Throwable ex) {
+            fourtyTwo = 42;
+        }
+        assertEquals(fourtyTwo, 42, "Meaning of Graal");
+
+    }
+
+    @AfterMethod
+    public void closePresenter() throws IOException {
+        if (close != null) {
+            close.close();
+        }
+    }
+
+
+    @Test
+    public void forEachArray() {
+        if (presenter == null) {
+            throw new SkipException("No presenter found, not running on GraalVM");
+        }
+        Array<String> array = new Array<>();
+        array.push("Hello");
+        array.push("World");
+        array.push("how");
+        array.push("are", "You?");
+
+        Assert.assertEquals(array.length(), 5, "Five words");
+
+        final Array<String> lowerCaseArray = new Array<>();
+        array.forEach(new Function.A1<String, Void>() {
+            @Override
+            public Void call(String p1) {
+                lowerCaseArray.push(p1.toLowerCase());
+                return null;
+            }
+
+            @Override
+            public Void call(String p1, Object p2) {
+                return call(p1);
+            }
+
+            @Override
+            public Void call(String p1, Object p2, Object p3) {
+                return call(p1);
+            }
+
+            @Override
+            public Void call(String p1, Object p2, Object p3, Object p4) {
+                return call(p1);
+            }
+
+            @Override
+            public Void call(String p1, Object p2, Object p3, Object p4, Object p5) {
+                return call(p1);
+            }
+        });
+
+        assertEquals(lowerCaseArray.$get(0), "hello");
+        assertEquals(lowerCaseArray.$get(1), "world");
+        assertEquals(lowerCaseArray.$get(2), "how");
+        assertEquals(lowerCaseArray.$get(3), "are");
+        assertEquals(lowerCaseArray.$get(4), "you?");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/test/java/net/java/html/boot/truffle/SingleCase.java
----------------------------------------------------------------------
diff --git a/boot-truffle/src/test/java/net/java/html/boot/truffle/SingleCase.java b/boot-truffle/src/test/java/net/java/html/boot/truffle/SingleCase.java
new file mode 100644
index 0000000..7bf99b0
--- /dev/null
+++ b/boot-truffle/src/test/java/net/java/html/boot/truffle/SingleCase.java
@@ -0,0 +1,127 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.boot.truffle;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import org.netbeans.html.boot.spi.Fn;
+import org.netbeans.html.boot.impl.FnContext;
+import org.testng.IHookCallBack;
+import org.testng.IHookable;
+import org.testng.ITest;
+import org.testng.ITestResult;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public final class SingleCase implements ITest, IHookable, Runnable {
+    static final Executor JS = Executors.newSingleThreadExecutor();
+    private final Fn.Presenter p;
+    private final Method m;
+    private Object result;
+    private Object inst;
+
+    SingleCase(Fn.Presenter p, Method m) {
+        this.p = p;
+        this.m = m;
+    }
+
+    @Override
+    public String getTestName() {
+        return m.getName();
+    }
+
+    @Test
+    public synchronized void executeTest() throws Exception {
+        if (result == null) {
+            JS.execute(this);
+            wait();
+        }
+        if (result instanceof Exception) {
+            throw (Exception)result;
+        }
+        if (result instanceof Error) {
+            throw (Error)result;
+        }
+    }
+
+    @Override
+    public synchronized void run() {
+        boolean notify = true;
+        try {
+            FnContext.currentPresenter(p);
+            if (inst == null) {
+                inst = m.getDeclaringClass().newInstance();
+            }
+            result = m.invoke(inst);
+            if (result == null) {
+                result = this;
+            }
+        } catch (InvocationTargetException ex) {
+            Throwable r = ex.getTargetException();
+            if (r instanceof InterruptedException) {
+                notify = false;
+                JS.execute(this);
+                return;
+            }
+            result = r;
+        } catch (Exception ex) {
+            result = ex;
+        } finally {
+            if (notify) {
+                notifyAll();
+            }
+            FnContext.currentPresenter(null);
+        }
+    }
+
+    @Override
+    public void run(IHookCallBack ihcb, ITestResult itr) {
+        ihcb.runTestMethod(itr);
+    }
+    
+}