rt/vm/src/main/java/org/apidesign/vm4brwsr/ClosureWrapper.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 26 May 2014 16:20:51 +0200
branchclosure
changeset 1598 ec62383beb7d
parent 1588 c1b6db1bdd87
child 1708 8e627eb9edf1
permissions -rw-r--r--
Shorten the name to register an extension and use configuration object with a generated magic to ensure basic level of consistency.
     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 = { 
    37         "--compilation_level", 
    38         "SIMPLE_OPTIMIZATIONS", 
    39         "--output_wrapper", "(function() {%output%})(this);",
    40         "--js", "bck2brwsr-raw.js" 
    41         //, "--debug"
    42         //, "--formatting", "PRETTY_PRINT"
    43     };
    44 
    45     private final Bck2Brwsr config;
    46 
    47     private String compiledCode;
    48     private String externsCode;
    49 
    50     private ClosureWrapper(Appendable out,
    51                            String compilationLevel, Bck2Brwsr config) {
    52         super(
    53             generateArguments(compilationLevel),
    54             new PrintStream(new APS(out)), System.err
    55         );
    56         this.config = config;
    57     }
    58 
    59     @Override
    60     protected List<SourceFile> createInputs(List<String> files, boolean allowStdIn) throws FlagUsageException, IOException {
    61         if (files.size() != 1 || !"bck2brwsr-raw.js".equals(files.get(0))) {
    62             throw new IOException("Unexpected files: " + files);
    63         }
    64         return Collections.nCopies(
    65                    1,
    66                    SourceFile.fromGenerator(
    67                        "bck2brwsr-raw.js",
    68                        new SourceFile.Generator() {
    69                            @Override
    70                            public String getCode() {
    71                                return getCompiledCode();
    72                            }
    73                        }));
    74     }
    75 
    76 
    77     @Override
    78     protected List<SourceFile> createExterns()
    79             throws FlagUsageException, IOException {
    80         final List<SourceFile> externsFiles =
    81                 new ArrayList<SourceFile>(super.createExterns());
    82 
    83         externsFiles.add(
    84                 SourceFile.fromGenerator(
    85                         "bck2brwsr_externs.js",
    86                         new SourceFile.Generator() {
    87                             @Override
    88                             public String getCode() {
    89                                 return getExternsCode();
    90                             }
    91                         }));
    92         return externsFiles;
    93     }
    94 
    95     private String getCompiledCode() {
    96         if (compiledCode == null) {
    97             StringBuilder sb = new StringBuilder();
    98             try {
    99                 VM.compile(sb, config);
   100                 compiledCode = sb.toString();
   101             } catch (IOException ex) {
   102                 compiledCode = ex.getMessage();
   103             }
   104         }
   105         return compiledCode;
   106     }
   107 
   108     private String getExternsCode() {
   109         if (externsCode == null) {
   110             // need compiled code at this point
   111             getCompiledCode();
   112 
   113             final StringBuilder sb = new StringBuilder("function RAW() {};\n");
   114             for (final String extern: FIXED_EXTERNS) {
   115                 sb.append("RAW.prototype.").append(extern).append(";\n");
   116             }
   117             externsCode = sb.toString();
   118         }
   119         return externsCode;
   120     }
   121 
   122     private static final class APS extends OutputStream {
   123         private final Appendable out;
   124 
   125         public APS(Appendable out) {
   126             this.out = out;
   127         }
   128         @Override
   129         public void write(int b) throws IOException {
   130             out.append((char)b);
   131         }
   132     }
   133 
   134     private static String[] generateArguments(String compilationLevel) {
   135         String[] finalArgs = ARGS.clone();
   136         finalArgs[1] = compilationLevel;
   137 
   138         return finalArgs;
   139     }
   140 
   141     static int produceTo(Appendable output,
   142         ObfuscationLevel obfuscationLevel,
   143         Bck2Brwsr config
   144     ) throws IOException {
   145         final ClosureWrapper cw =
   146                 new ClosureWrapper(output,
   147                                    (obfuscationLevel == ObfuscationLevel.FULL)
   148                                            ? "ADVANCED_OPTIMIZATIONS"
   149                                            : "SIMPLE_OPTIMIZATIONS",
   150                                    config);
   151         try {
   152             return cw.doRun();
   153         } catch (FlagUsageException ex) {
   154             throw new IOException(ex);
   155         }
   156     }
   157 
   158     private static final String[] FIXED_EXTERNS = {
   159         "bck2brwsr",
   160         "bck2BrwsrThrwrbl",
   161         "register",
   162         "$class",
   163         "anno",
   164         "array",
   165         "access",
   166         "cls",
   167         "vm",
   168         "loadClass",
   169         "loadBytes",
   170         "jvmName",
   171         "primitive",
   172         "superclass",
   173         "cnstr",
   174         "add32",
   175         "sub32",
   176         "mul32",
   177         "neg32",
   178         "toInt8",
   179         "toInt16",
   180         "next32",
   181         "high32",
   182         "toInt32",
   183         "toFP",
   184         "toLong",
   185         "toJS",
   186         "toExactString",
   187         "add64",
   188         "sub64",
   189         "mul64",
   190         "and64",
   191         "or64",
   192         "xor64",
   193         "shl64",
   194         "shr64",
   195         "ushr64",
   196         "compare",
   197         "compare64",
   198         "neg64",
   199         "div32",
   200         "mod32",
   201         "div64",
   202         "mod64",
   203         "at",
   204         "getClass__Ljava_lang_Class_2",
   205         "clone__Ljava_lang_Object_2"
   206     };
   207 }