rt/vm/src/main/java/org/apidesign/vm4brwsr/ClosureWrapper.java
author Lubomir Nerad <lubomir.nerad@oracle.com>
Wed, 08 May 2013 14:54:32 +0200
branchclosure
changeset 1086 2ac4283ee209
parent 1083 9d6130cb464f
child 1094 36961c9a009f
permissions -rw-r--r--
Reenabled obfuscation
     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 
    42     private String compiledCode;
    43     private String externsCode;
    44 
    45     private ClosureWrapper(Appendable out, 
    46                            String compilationLevel,
    47                            Bck2Brwsr.Resources res,
    48                            StringArray classes,
    49                            boolean extension) {
    50         super(
    51             generateArguments(compilationLevel),
    52             new PrintStream(new APS(out)), System.err
    53         );
    54         this.res = res;
    55         this.classes = classes;
    56         this.extension = extension;
    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, res, classes, extension);
   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.Resources resources,
   144                          StringArray arr,
   145                          boolean extension) throws IOException {
   146         final ClosureWrapper cw =
   147                 new ClosureWrapper(output,
   148                                    (obfuscationLevel == ObfuscationLevel.FULL)
   149                                            ? "ADVANCED_OPTIMIZATIONS"
   150                                            : "SIMPLE_OPTIMIZATIONS",
   151                                    resources, arr, extension);
   152         try {
   153             return cw.doRun();
   154         } catch (FlagUsageException ex) {
   155             throw new IOException(ex);
   156         }
   157     }
   158 
   159     private static final String[] FIXED_EXTERNS = {
   160         "bck2brwsr",
   161         "$class",
   162         "anno",
   163         "array",
   164         "access",
   165         "cls",
   166         "vm",
   167         "loadClass",
   168         "loadBytes",
   169         "jvmName",
   170         "primitive",
   171         "superclass",
   172         "cnstr",
   173         "add32",
   174         "sub32",
   175         "mul32",
   176         "neg32",
   177         "toInt8",
   178         "toInt16",
   179         "next32",
   180         "high32",
   181         "toInt32",
   182         "toFP",
   183         "toLong",
   184         "toExactString",
   185         "add64",
   186         "sub64",
   187         "mul64",
   188         "and64",
   189         "or64",
   190         "xor64",
   191         "shl64",
   192         "shr64",
   193         "ushr64",
   194         "compare64",
   195         "neg64",
   196         "div32",
   197         "mod32",
   198         "div64",
   199         "mod64",
   200         "at",
   201         "getClass__Ljava_lang_Class_2",
   202         "clone__Ljava_lang_Object_2"
   203     };
   204 }