1.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Thu Apr 25 16:17:48 2013 +0200
1.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Fri Apr 26 18:48:34 2013 +0200
1.3 @@ -19,14 +19,20 @@
1.4
1.5 import java.io.IOException;
1.6 import java.io.InputStream;
1.7 +import org.apidesign.vm4brwsr.ByteCodeParser.ClassData;
1.8
1.9 /** Generator of JavaScript from bytecode of classes on classpath of the VM.
1.10 *
1.11 * @author Jaroslav Tulach <jtulach@netbeans.org>
1.12 */
1.13 abstract class VM extends ByteCodeToJavaScript {
1.14 - private VM(Appendable out, ObfuscationDelegate obfuscationDelegate) {
1.15 - super(out, obfuscationDelegate);
1.16 + protected final Bck2Brwsr.Resources resources;
1.17 + private final ExportedSymbols exportedSymbols;
1.18 +
1.19 + private VM(Appendable out, Bck2Brwsr.Resources resources) {
1.20 + super(out);
1.21 + this.resources = resources;
1.22 + this.exportedSymbols = new ExportedSymbols(resources);
1.23 }
1.24
1.25 static {
1.26 @@ -44,20 +50,19 @@
1.27 return false;
1.28 }
1.29
1.30 - static void compile(Bck2Brwsr.Resources l, Appendable out, StringArray names) throws IOException {
1.31 - VM vm = new Standalone(out, ObfuscationDelegate.NULL);
1.32 - vm.doCompile(l, names);
1.33 + static void compileStandalone(Bck2Brwsr.Resources l, Appendable out, StringArray names) throws IOException {
1.34 + VM vm = new Standalone(out, l);
1.35 + vm.doCompile(names);
1.36 }
1.37
1.38 - static void compile(Bck2Brwsr.Resources l, Appendable out, StringArray names,
1.39 - ObfuscationDelegate obfuscationDelegate) throws IOException {
1.40 - VM vm = new Standalone(out, obfuscationDelegate);
1.41 - vm.doCompile(l, names);
1.42 + static void compileExtension(Bck2Brwsr.Resources l, Appendable out, StringArray names) throws IOException {
1.43 + VM vm = new Extension(out, l);
1.44 + vm.doCompile(names);
1.45 }
1.46
1.47 - private void doCompile(Bck2Brwsr.Resources l, StringArray names) throws IOException {
1.48 + private void doCompile(StringArray names) throws IOException {
1.49 generatePrologue();
1.50 - generateBody(l, names);
1.51 + generateBody(names);
1.52 generateEpilogue();
1.53 }
1.54
1.55 @@ -65,7 +70,24 @@
1.56
1.57 protected abstract void generateEpilogue() throws IOException;
1.58
1.59 - protected void generateBody(Bck2Brwsr.Resources l, StringArray names) throws IOException {
1.60 + protected abstract String generateClass(String className)
1.61 + throws IOException;
1.62 +
1.63 + protected abstract String getExportsObject();
1.64 +
1.65 + @Override
1.66 + protected final void declaredClass(ClassData classData, String mangledName)
1.67 + throws IOException {
1.68 + if (exportedSymbols.isExported(classData)) {
1.69 + out.append("\n").append(getExportsObject()).append("['")
1.70 + .append(mangledName)
1.71 + .append("'] = ")
1.72 + .append(accessClass(mangledName))
1.73 + .append(";\n");
1.74 + }
1.75 + }
1.76 +
1.77 + private void generateBody(StringArray names) throws IOException {
1.78 StringArray processed = new StringArray();
1.79 StringArray initCode = new StringArray();
1.80 for (String baseClass : names.toArray()) {
1.81 @@ -81,12 +103,9 @@
1.82 if (name == null) {
1.83 break;
1.84 }
1.85 - InputStream is = loadClass(l, name);
1.86 - if (is == null) {
1.87 - throw new IOException("Can't find class " + name);
1.88 - }
1.89 +
1.90 try {
1.91 - String ic = compile(is);
1.92 + String ic = generateClass(name);
1.93 processed.add(name);
1.94 initCode.add(ic == null ? "" : ic);
1.95 } catch (RuntimeException ex) {
1.96 @@ -113,7 +132,7 @@
1.97 while (resource.startsWith("/")) {
1.98 resource = resource.substring(1);
1.99 }
1.100 - InputStream emul = l.get(resource);
1.101 + InputStream emul = resources.get(resource);
1.102 if (emul == null) {
1.103 throw new IOException("Can't find " + resource);
1.104 }
1.105 @@ -221,9 +240,8 @@
1.106 }
1.107
1.108 private static final class Standalone extends VM {
1.109 - private Standalone(Appendable out,
1.110 - ObfuscationDelegate obfuscationDelegate) {
1.111 - super(out, obfuscationDelegate);
1.112 + private Standalone(Appendable out, Bck2Brwsr.Resources resources) {
1.113 + super(out, resources);
1.114 }
1.115
1.116 @Override
1.117 @@ -236,9 +254,13 @@
1.118 out.append(
1.119 " return vm;\n"
1.120 + " };\n"
1.121 + + " var extensions = [];\n"
1.122 + " global.bck2brwsr = function() {\n"
1.123 + " var args = Array.prototype.slice.apply(arguments);\n"
1.124 + " var vm = fillInVMSkeleton({});\n"
1.125 + + " for (var i = 0; i < extensions.length; ++i) {\n"
1.126 + + " extensions[i](vm);\n"
1.127 + + " }\n"
1.128 + " var loader = {};\n"
1.129 + " loader.vm = vm;\n"
1.130 + " loader.loadClass = function(name) {\n"
1.131 @@ -261,29 +283,47 @@
1.132 + " loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, null, args);\n"
1.133 + " return loader;\n"
1.134 + " };\n");
1.135 + out.append(
1.136 + " global.bck2brwsr.registerExtension"
1.137 + + " = function(extension) {\n"
1.138 + + " extensions.push(extension);\n"
1.139 + + " };\n");
1.140 out.append("}(this));");
1.141 }
1.142
1.143 @Override
1.144 - String getExportsObject() {
1.145 + protected String generateClass(String className) throws IOException {
1.146 + InputStream is = loadClass(resources, className);
1.147 + if (is == null) {
1.148 + throw new IOException("Can't find class " + className);
1.149 + }
1.150 + return compile(is);
1.151 + }
1.152 +
1.153 + @Override
1.154 + protected String getExportsObject() {
1.155 return "vm";
1.156 }
1.157 }
1.158
1.159 private static final class Extension extends VM {
1.160 - private final String name;
1.161 -
1.162 - private Extension(String name,
1.163 - Appendable out,
1.164 - ObfuscationDelegate obfuscationDelegate) {
1.165 - super(out, obfuscationDelegate);
1.166 - this.name = name;
1.167 + private Extension(Appendable out, Bck2Brwsr.Resources resources) {
1.168 + super(out, resources);
1.169 }
1.170
1.171 @Override
1.172 protected void generatePrologue() throws IOException {
1.173 out.append("bck2brwsr.registerExtension(function(exports) {\n"
1.174 + " var vm = {};\n");
1.175 + out.append(" function link(n, inst) {\n"
1.176 + + " var cls = n.replace__Ljava_lang_String_2CC("
1.177 + + "'/', '_').toString();\n"
1.178 + + " var dot = n.replace__Ljava_lang_String_2CC("
1.179 + + "'/', '.').toString();\n"
1.180 + + " exports.loadClass(dot);\n"
1.181 + + " vm[cls] = exports[cls];\n"
1.182 + + " return vm[cls](inst);\n"
1.183 + + " };\n");
1.184 }
1.185
1.186 @Override
1.187 @@ -292,7 +332,24 @@
1.188 }
1.189
1.190 @Override
1.191 - String getExportsObject() {
1.192 + protected String generateClass(String className) throws IOException {
1.193 + InputStream is = loadClass(resources, className);
1.194 + if (is == null) {
1.195 + out.append("\n").append(assignClass(
1.196 + className.replace('/', '_')))
1.197 + .append("function() {\n return link('")
1.198 + .append(className)
1.199 + .append("', arguments.length == 0 || arguments[0] === true);"
1.200 + + "\n};");
1.201 +
1.202 + return null;
1.203 + }
1.204 +
1.205 + return compile(is);
1.206 + }
1.207 +
1.208 + @Override
1.209 + protected String getExportsObject() {
1.210 return "exports";
1.211 }
1.212 }