rt/vm/src/main/java/org/apidesign/vm4brwsr/ClosureWrapper.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 26 Apr 2014 21:30:06 +0200
branchclosure
changeset 1491 4a1398eff4fb
parent 1147 894a5045e354
child 1493 234fea368401
permissions -rw-r--r--
Different meaning of root vs. added classes. Ability to explicitly enumerate classes that should be exported and available with fully qualified name.
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, version 2 of the License.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. Look for COPYING file in the top folder.
    16  * If not, see http://opensource.org/licenses/GPL-2.0.
    17  */
    18 package org.apidesign.vm4brwsr;
    19 
    20 import com.google.javascript.jscomp.CommandLineRunner;
    21 import com.google.javascript.jscomp.SourceFile;
    22 import java.io.IOException;
    23 import java.io.OutputStream;
    24 import java.io.PrintStream;
    25 import java.util.ArrayList;
    26 import java.util.Collections;
    27 import java.util.List;
    28 import org.apidesign.bck2brwsr.core.ExtraJavaScript;
    29 
    30 /**
    31  *
    32  * @author Jaroslav Tulach <jtulach@netbeans.org>
    33  */
    34 @ExtraJavaScript(processByteCode = false, resource="")
    35 final class ClosureWrapper extends CommandLineRunner {
    36     private static final String[] ARGS = { "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--js", "bck2brwsr-raw.js" /*, "--debug", "--formatting", "PRETTY_PRINT" */ };
    37 
    38     private final Bck2Brwsr.Resources res;
    39     private final StringArray classes;
    40     private final boolean extension;
    41     private final StringArray rootClasses;
    42 
    43     private String compiledCode;
    44     private String externsCode;
    45 
    46     private ClosureWrapper(Appendable out, 
    47                            String compilationLevel,
    48                            Bck2Brwsr.Resources res,
    49                            StringArray rootClasses,
    50                            StringArray classes,
    51                            boolean extension) {
    52         super(
    53             generateArguments(compilationLevel),
    54             new PrintStream(new APS(out)), System.err
    55         );
    56         this.res = res;
    57         this.rootClasses = rootClasses;
    58         this.classes = classes;
    59         this.extension = extension;
    60     }
    61 
    62     @Override
    63     protected List<SourceFile> createInputs(List<String> files, boolean allowStdIn) throws FlagUsageException, IOException {
    64         if (files.size() != 1 || !"bck2brwsr-raw.js".equals(files.get(0))) {
    65             throw new IOException("Unexpected files: " + files);
    66         }
    67         return Collections.nCopies(
    68                    1,
    69                    SourceFile.fromGenerator(
    70                        "bck2brwsr-raw.js",
    71                        new SourceFile.Generator() {
    72                            @Override
    73                            public String getCode() {
    74                                return getCompiledCode();
    75                            }
    76                        }));
    77     }
    78 
    79 
    80     @Override
    81     protected List<SourceFile> createExterns()
    82             throws FlagUsageException, IOException {
    83         final List<SourceFile> externsFiles =
    84                 new ArrayList<SourceFile>(super.createExterns());
    85 
    86         externsFiles.add(
    87                 SourceFile.fromGenerator(
    88                         "bck2brwsr_externs.js",
    89                         new SourceFile.Generator() {
    90                             @Override
    91                             public String getCode() {
    92                                 return getExternsCode();
    93                             }
    94                         }));
    95         return externsFiles;
    96     }
    97 
    98     private String getCompiledCode() {
    99         if (compiledCode == null) {
   100             StringBuilder sb = new StringBuilder();
   101             try {
   102                 VM.compile(sb, res, rootClasses, classes, extension);
   103                 compiledCode = sb.toString();
   104             } catch (IOException ex) {
   105                 compiledCode = ex.getMessage();
   106             }
   107         }
   108         return compiledCode;
   109     }
   110 
   111     private String getExternsCode() {
   112         if (externsCode == null) {
   113             // need compiled code at this point
   114             getCompiledCode();
   115 
   116             final StringBuilder sb = new StringBuilder("function RAW() {};\n");
   117             for (final String extern: FIXED_EXTERNS) {
   118                 sb.append("RAW.prototype.").append(extern).append(";\n");
   119             }
   120             externsCode = sb.toString();
   121         }
   122         return externsCode;
   123     }
   124 
   125     private static final class APS extends OutputStream {
   126         private final Appendable out;
   127 
   128         public APS(Appendable out) {
   129             this.out = out;
   130         }
   131         @Override
   132         public void write(int b) throws IOException {
   133             out.append((char)b);
   134         }
   135     }
   136 
   137     private static String[] generateArguments(String compilationLevel) {
   138         String[] finalArgs = ARGS.clone();
   139         finalArgs[1] = compilationLevel;
   140 
   141         return finalArgs;
   142     }
   143 
   144     static int produceTo(Appendable output,
   145                          ObfuscationLevel obfuscationLevel,
   146                          Bck2Brwsr.Resources resources,
   147                          StringArray rootArr,
   148                          StringArray arr,
   149                          boolean extension) throws IOException {
   150         final ClosureWrapper cw =
   151                 new ClosureWrapper(output,
   152                                    (obfuscationLevel == ObfuscationLevel.FULL)
   153                                            ? "ADVANCED_OPTIMIZATIONS"
   154                                            : "SIMPLE_OPTIMIZATIONS",
   155                                    resources, rootArr, arr, extension);
   156         try {
   157             return cw.doRun();
   158         } catch (FlagUsageException ex) {
   159             throw new IOException(ex);
   160         }
   161     }
   162 
   163     private static final String[] FIXED_EXTERNS = {
   164         "bck2brwsr",
   165         "bck2BrwsrCnvrt",
   166         "registerExtension",
   167         "$class",
   168         "anno",
   169         "array",
   170         "access",
   171         "cls",
   172         "vm",
   173         "loadClass",
   174         "loadBytes",
   175         "jvmName",
   176         "primitive",
   177         "superclass",
   178         "cnstr",
   179         "add32",
   180         "sub32",
   181         "mul32",
   182         "neg32",
   183         "toInt8",
   184         "toInt16",
   185         "next32",
   186         "high32",
   187         "toInt32",
   188         "toFP",
   189         "toLong",
   190         "toExactString",
   191         "add64",
   192         "sub64",
   193         "mul64",
   194         "and64",
   195         "or64",
   196         "xor64",
   197         "shl64",
   198         "shr64",
   199         "ushr64",
   200         "compare64",
   201         "neg64",
   202         "div32",
   203         "mod32",
   204         "div64",
   205         "mod64",
   206         "at",
   207         "getClass__Ljava_lang_Class_2",
   208         "clone__Ljava_lang_Object_2"
   209     };
   210 }