rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java
branchclosure
changeset 1029 b1fe994d4267
parent 1020 a6bacea2518f
child 1083 9d6130cb464f
     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      }