rt/vm/src/main/java/org/apidesign/vm4brwsr/ClosureWrapper.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 26 Sep 2014 10:22:23 +0200
changeset 1708 8e627eb9edf1
parent 1598 ec62383beb7d
child 1712 c934e2190758
permissions -rw-r--r--
Default constructor cannot be obfuscated
     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         "cons__V",
   205         "getClass__Ljava_lang_Class_2",
   206         "clone__Ljava_lang_Object_2"
   207     };
   208 }