1.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java Thu Dec 06 22:02:10 2012 +0100
1.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java Fri Dec 07 06:29:54 2012 +0100
1.3 @@ -31,6 +31,11 @@
1.4 super(out);
1.5 }
1.6
1.7 + static {
1.8 + // uses VMLazy to load dynamic classes
1.9 + VMLazy.init();
1.10 + }
1.11 +
1.12 static void compile(Appendable out, String... names) throws IOException {
1.13 compile(out, StringArray.asList(names));
1.14 }
1.15 @@ -113,9 +118,19 @@
1.16 }
1.17 }
1.18 out.append(
1.19 - " global.bck2brwsr = function() { return {\n"
1.20 - + " loadClass : function(name) { return vm[name.replace__Ljava_lang_String_2CC(name, '.','_')](true); }\n"
1.21 - + " };\n};\n");
1.22 + " global.bck2brwsr = function() {\n"
1.23 + + " var args = arguments;\n"
1.24 + + " var loader = {};\n"
1.25 + + " loader.vm = vm;\n"
1.26 + + " loader.loadClass = function(name) {\n"
1.27 + + " var attr = name.replace__Ljava_lang_String_2CC(name, '.','_');\n"
1.28 + + " var fn = vm[attr];\n"
1.29 + + " if (fn) return fn(false);\n"
1.30 + + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
1.31 + + " load___3Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
1.32 + + " }\n"
1.33 + + " return loader;\n"
1.34 + + " };\n");
1.35 out.append("}(this));");
1.36 }
1.37 private static void readResource(InputStream emul, Appendable out) throws IOException {
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Fri Dec 07 06:29:54 2012 +0100
2.3 @@ -0,0 +1,100 @@
2.4 +/**
2.5 + * Back 2 Browser Bytecode Translator
2.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
2.7 + *
2.8 + * This program is free software: you can redistribute it and/or modify
2.9 + * it under the terms of the GNU General Public License as published by
2.10 + * the Free Software Foundation, version 2 of the License.
2.11 + *
2.12 + * This program is distributed in the hope that it will be useful,
2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.15 + * GNU General Public License for more details.
2.16 + *
2.17 + * You should have received a copy of the GNU General Public License
2.18 + * along with this program. Look for COPYING file in the top folder.
2.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
2.20 + */
2.21 +package org.apidesign.vm4brwsr;
2.22 +
2.23 +import java.io.ByteArrayInputStream;
2.24 +import java.io.IOException;
2.25 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
2.26 +
2.27 +/**
2.28 + *
2.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
2.30 + */
2.31 +class VMLazy extends ByteCodeToJavaScript {
2.32 + private final Object loader;
2.33 +
2.34 + private VMLazy(Object loader, Appendable out) {
2.35 + super(out);
2.36 + this.loader = loader;
2.37 + }
2.38 +
2.39 + static void init() {
2.40 + }
2.41 +
2.42 + @JavaScriptBody(args={"res", "args" }, body = "return args[0](res.toString());")
2.43 + private static native byte[] read(String res, Object[] args);
2.44 +
2.45 + static Object load(Object loader, String name, Object[] arguments)
2.46 + throws IOException, ClassNotFoundException {
2.47 + String res = name.replace('.', '/') + ".class";
2.48 + byte[] arr = read(res, arguments);
2.49 + if (arr == null) {
2.50 + throw new ClassNotFoundException(name);
2.51 + }
2.52 + String code = toJavaScript(loader, arr);
2.53 + return applyCode(loader, name, code);
2.54 + }
2.55 +
2.56 + @JavaScriptBody(args = {"loader", "name", "script" }, body =
2.57 + "try {\n" +
2.58 + " new Function(script)(loader, name);\n" +
2.59 + "} catch (ex) {\n" +
2.60 + " throw 'Cannot compile ' + ex + ' script:\\\\n' + script;\n" +
2.61 + "}\n" +
2.62 + "return vm[name](false);\n"
2.63 + )
2.64 + private static native Object applyCode(Object loader, String name, String script);
2.65 +
2.66 + private static String toJavaScript(Object loader, byte[] is) throws IOException {
2.67 + StringBuilder sb = new StringBuilder();
2.68 + sb.append("var loader = arguments[0];\n");
2.69 + sb.append("var vm = loader.vm;\n");
2.70 + new VMLazy(loader, sb).compile(new ByteArrayInputStream(is));
2.71 + return sb.toString().toString();
2.72 + }
2.73 +
2.74 + @JavaScriptBody(args = { "self", "n" },
2.75 + body=
2.76 + "var cls = n.replace__Ljava_lang_String_2CC(n,'/','_').toString();"
2.77 + + "var loader = self.fld_loader;"
2.78 + + "var vm = loader.vm;"
2.79 + + "if (vm[cls]) return false;"
2.80 + + "vm[cls] = function() {"
2.81 + + " return loader.loadClass(n,cls);"
2.82 + + "};"
2.83 + + "return true;"
2.84 + )
2.85 + @Override
2.86 + protected boolean requireReference(String internalClassName) {
2.87 + throw new UnsupportedOperationException();
2.88 + }
2.89 +
2.90 + @Override
2.91 + protected void requireScript(String resourcePath) {
2.92 + }
2.93 +
2.94 + @Override
2.95 + String assignClass(String className) {
2.96 + return "vm[arguments[1]]=";
2.97 + }
2.98 +
2.99 + @Override
2.100 + String accessClass(String classOperation) {
2.101 + return "vm." + classOperation;
2.102 + }
2.103 +}
3.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMLazy.java Thu Dec 06 22:02:10 2012 +0100
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,68 +0,0 @@
3.4 -/**
3.5 - * Back 2 Browser Bytecode Translator
3.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
3.7 - *
3.8 - * This program is free software: you can redistribute it and/or modify
3.9 - * it under the terms of the GNU General Public License as published by
3.10 - * the Free Software Foundation, version 2 of the License.
3.11 - *
3.12 - * This program is distributed in the hope that it will be useful,
3.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.15 - * GNU General Public License for more details.
3.16 - *
3.17 - * You should have received a copy of the GNU General Public License
3.18 - * along with this program. Look for COPYING file in the top folder.
3.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
3.20 - */
3.21 -package org.apidesign.vm4brwsr;
3.22 -
3.23 -import java.io.ByteArrayInputStream;
3.24 -import java.io.IOException;
3.25 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
3.26 -
3.27 -/**
3.28 - *
3.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
3.30 - */
3.31 -class VMLazy extends ByteCodeToJavaScript {
3.32 - private final Object vm;
3.33 - private final Object global;
3.34 -
3.35 - private VMLazy(Object global, Object vm, Appendable out) {
3.36 - super(out);
3.37 - this.vm = vm;
3.38 - this.global = global;
3.39 - }
3.40 -
3.41 - static String toJavaScript(Object global, Object vm, byte[] is) throws IOException {
3.42 - StringBuilder sb = new StringBuilder();
3.43 - new VMLazy(global, vm, sb).compile(new ByteArrayInputStream(is));
3.44 - return sb.toString().toString();
3.45 - }
3.46 -
3.47 - @JavaScriptBody(args = { "self", "n" },
3.48 - body=
3.49 - "var cls = n.replace__Ljava_lang_String_2CC(n,'/','_').toString();"
3.50 - + "var glb = self.fld_global;"
3.51 - + "var vm = self.fld_vm;"
3.52 - + "if (glb[cls]) return false;"
3.53 - + "glb[cls] = function() {"
3.54 - + " return vm.loadClass(n,cls);"
3.55 - + "};"
3.56 - + "return true;"
3.57 - )
3.58 - @Override
3.59 - protected boolean requireReference(String internalClassName) {
3.60 - throw new UnsupportedOperationException();
3.61 - }
3.62 -
3.63 - @Override
3.64 - protected void requireScript(String resourcePath) {
3.65 - }
3.66 -
3.67 - @Override
3.68 - protected String assignClass(String className) {
3.69 - return "arguments[0][arguments[1]]=";
3.70 - }
3.71 -}
4.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java Thu Dec 06 22:02:10 2012 +0100
4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java Fri Dec 07 06:29:54 2012 +0100
4.3 @@ -19,6 +19,8 @@
4.4
4.5 import java.io.IOException;
4.6 import java.io.InputStream;
4.7 +import java.util.Set;
4.8 +import java.util.TreeSet;
4.9 import javax.script.Invocable;
4.10 import javax.script.ScriptContext;
4.11 import javax.script.ScriptEngine;
4.12 @@ -40,36 +42,18 @@
4.13 @BeforeClass
4.14 public void compileTheCode() throws Exception {
4.15 StringBuilder sb = new StringBuilder();
4.16 -
4.17 - sb.append("\nfunction test(clazz, as, method) {");
4.18 - sb.append("\n var l = new lazyVM(this);");
4.19 - sb.append("\n var c = l.loadClass(clazz, as);");
4.20 + sb.append("\nvar data = {};");
4.21 + sb.append("\nfunction test(clazz, method) {");
4.22 + sb.append("\n if (!data.bck2brwsr) data.bck2brwsr = bck2brwsr(function(name) { return loader.get(name); });");
4.23 + sb.append("\n var c = data.bck2brwsr.loadClass(clazz);");
4.24 sb.append("\n return c[method]();");
4.25 sb.append("\n}");
4.26
4.27
4.28 - sb.append("\nfunction lazyVM(global) {");
4.29 - sb.append("\n var self = this;");
4.30 - sb.append("\n var glb = global;");
4.31 - sb.append("\n lazyVM.prototype.loadClass = function(res, name) {");
4.32 - sb.append("\n var script = org_apidesign_vm4brwsr_VMLazy(true)."
4.33 - + "toJavaScript__Ljava_lang_String_2Ljava_lang_Object_2Ljava_lang_Object_2_3B("
4.34 - + " glb, self,"
4.35 - + " loader.get(res + '.class')"
4.36 - + ");");
4.37 - sb.append("\n try {");
4.38 - sb.append("\n new Function(script)(glb, name);");
4.39 - sb.append("\n } catch (ex) {");
4.40 - sb.append("\n throw 'Cannot compile ' + res + ' error: ' + ex + ' script:\\n' + script;");
4.41 - sb.append("\n };");
4.42 - sb.append("\n return glb[name](true);");
4.43 - sb.append("\n };");
4.44 - sb.append("\n");
4.45 - sb.append("\n}\n");
4.46 -
4.47 +
4.48 ScriptEngine[] arr = { null };
4.49 code = StaticMethodTest.compileClass(sb, arr,
4.50 - "org/apidesign/vm4brwsr/VMLazy"
4.51 + "org/apidesign/vm4brwsr/GenJS"
4.52 );
4.53 arr[0].getContext().setAttribute("loader", new FindBytes(), ScriptContext.ENGINE_SCOPE);
4.54 codeSeq = sb;
4.55 @@ -77,13 +61,13 @@
4.56
4.57 @Test public void invokeStaticMethod() throws Exception {
4.58 assertExec("Trying to get -1", "test", Double.valueOf(-1),
4.59 - "org/apidesign/vm4brwsr/StaticMethod", "org_apidesign_vm4brwsr_StaticMethod", "minusOne__I"
4.60 + StaticMethod.class.getName(), "minusOne__I"
4.61 );
4.62 }
4.63
4.64 @Test public void loadDependantClass() throws Exception {
4.65 - assertExec("Trying to get zero", "test", Double.valueOf(0),
4.66 - "org/apidesign/vm4brwsr/InstanceSub", "org_apidesign_vm4brwsr_InstanceSub", "recallDbl__D"
4.67 + assertExec("Expecting zero", "test", Double.valueOf(0),
4.68 + InstanceSub.class.getName(), "recallDbl__D"
4.69 );
4.70 }
4.71
4.72 @@ -106,7 +90,13 @@
4.73 }
4.74
4.75 public static final class FindBytes {
4.76 + private static Set<String> requested = new TreeSet<String>();
4.77 +
4.78 public byte[] get(String name) throws IOException {
4.79 + if (!requested.add(name)) {
4.80 + throw new IllegalStateException("Requested for second time: " + name);
4.81 + }
4.82 +
4.83 InputStream is = VMLazyTest.class.getClassLoader().getResourceAsStream(name);
4.84 if (is == null) {
4.85 throw new IOException("Can't find " + name);