jaroslav@750: /** jaroslav@750: * Back 2 Browser Bytecode Translator jaroslav@750: * Copyright (C) 2012 Jaroslav Tulach jaroslav@750: * jaroslav@750: * This program is free software: you can redistribute it and/or modify jaroslav@750: * it under the terms of the GNU General Public License as published by jaroslav@750: * the Free Software Foundation, version 2 of the License. jaroslav@750: * jaroslav@750: * This program is distributed in the hope that it will be useful, jaroslav@750: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@750: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@750: * GNU General Public License for more details. jaroslav@750: * jaroslav@750: * You should have received a copy of the GNU General Public License jaroslav@750: * along with this program. Look for COPYING file in the top folder. jaroslav@750: * If not, see http://opensource.org/licenses/GPL-2.0. jaroslav@750: */ jaroslav@750: package org.apidesign.vm4brwsr; jaroslav@750: jaroslav@750: import com.google.javascript.jscomp.CommandLineRunner; jaroslav@750: import com.google.javascript.jscomp.SourceFile; jaroslav@750: import java.io.IOException; jaroslav@750: import java.io.OutputStream; jaroslav@750: import java.io.PrintStream; lubomir@869: import java.util.ArrayList; jaroslav@750: import java.util.Collections; jaroslav@750: import java.util.List; jaroslav@750: import org.apidesign.bck2brwsr.core.ExtraJavaScript; jaroslav@750: jaroslav@750: /** jaroslav@750: * jaroslav@750: * @author Jaroslav Tulach jaroslav@750: */ jaroslav@750: @ExtraJavaScript(processByteCode = false, resource="") lubomir@869: final class ClosureWrapper extends CommandLineRunner { jaroslav@1562: private static final String[] ARGS = { jaroslav@1562: "--compilation_level", jaroslav@1562: "SIMPLE_OPTIMIZATIONS", jaroslav@1588: "--output_wrapper", "(function() {%output%})(this);", jaroslav@1562: "--js", "bck2brwsr-raw.js" jaroslav@1562: //, "--debug" jaroslav@1562: //, "--formatting", "PRETTY_PRINT" jaroslav@1562: }; jaroslav@750: jaroslav@1493: private final Bck2Brwsr config; lubomir@869: lubomir@869: private String compiledCode; lubomir@869: private String externsCode; lubomir@869: jaroslav@1493: private ClosureWrapper(Appendable out, jaroslav@1493: String compilationLevel, Bck2Brwsr config) { jaroslav@750: super( lubomir@869: generateArguments(compilationLevel), jaroslav@750: new PrintStream(new APS(out)), System.err jaroslav@750: ); jaroslav@1493: this.config = config; jaroslav@750: } jaroslav@750: jaroslav@750: @Override jaroslav@750: protected List createInputs(List files, boolean allowStdIn) throws FlagUsageException, IOException { jaroslav@750: if (files.size() != 1 || !"bck2brwsr-raw.js".equals(files.get(0))) { jaroslav@750: throw new IOException("Unexpected files: " + files); jaroslav@750: } lubomir@869: return Collections.nCopies( lubomir@869: 1, lubomir@869: SourceFile.fromGenerator( lubomir@869: "bck2brwsr-raw.js", lubomir@869: new SourceFile.Generator() { lubomir@869: @Override lubomir@869: public String getCode() { lubomir@869: return getCompiledCode(); lubomir@869: } lubomir@869: })); jaroslav@750: } jaroslav@750: lubomir@869: jaroslav@750: @Override lubomir@869: protected List createExterns() lubomir@869: throws FlagUsageException, IOException { lubomir@869: final List externsFiles = lubomir@869: new ArrayList(super.createExterns()); lubomir@869: lubomir@869: externsFiles.add( lubomir@869: SourceFile.fromGenerator( lubomir@869: "bck2brwsr_externs.js", lubomir@869: new SourceFile.Generator() { lubomir@869: @Override lubomir@869: public String getCode() { lubomir@869: return getExternsCode(); lubomir@869: } lubomir@869: })); lubomir@869: return externsFiles; lubomir@869: } lubomir@869: lubomir@869: private String getCompiledCode() { lubomir@869: if (compiledCode == null) { jaroslav@750: StringBuilder sb = new StringBuilder(); jaroslav@750: try { jaroslav@1493: VM.compile(sb, config); lubomir@869: compiledCode = sb.toString(); jaroslav@750: } catch (IOException ex) { lubomir@869: compiledCode = ex.getMessage(); jaroslav@750: } jaroslav@750: } lubomir@869: return compiledCode; lubomir@869: } lubomir@869: lubomir@869: private String getExternsCode() { lubomir@869: if (externsCode == null) { lubomir@869: // need compiled code at this point lubomir@869: getCompiledCode(); lubomir@869: lubomir@869: final StringBuilder sb = new StringBuilder("function RAW() {};\n"); lubomir@1083: for (final String extern: FIXED_EXTERNS) { lubomir@869: sb.append("RAW.prototype.").append(extern).append(";\n"); lubomir@869: } lubomir@869: externsCode = sb.toString(); lubomir@869: } lubomir@869: return externsCode; jaroslav@750: } lubomir@849: jaroslav@750: private static final class APS extends OutputStream { jaroslav@750: private final Appendable out; jaroslav@750: jaroslav@750: public APS(Appendable out) { jaroslav@750: this.out = out; jaroslav@750: } jaroslav@750: @Override jaroslav@750: public void write(int b) throws IOException { jaroslav@750: out.append((char)b); jaroslav@750: } jaroslav@750: } lubomir@849: lubomir@869: private static String[] generateArguments(String compilationLevel) { lubomir@849: String[] finalArgs = ARGS.clone(); lubomir@869: finalArgs[1] = compilationLevel; lubomir@849: lubomir@849: return finalArgs; lubomir@849: } lubomir@849: lubomir@1086: static int produceTo(Appendable output, jaroslav@1493: ObfuscationLevel obfuscationLevel, jaroslav@1493: Bck2Brwsr config jaroslav@1493: ) throws IOException { lubomir@1086: final ClosureWrapper cw = lubomir@1086: new ClosureWrapper(output, lubomir@1086: (obfuscationLevel == ObfuscationLevel.FULL) lubomir@1086: ? "ADVANCED_OPTIMIZATIONS" lubomir@1086: : "SIMPLE_OPTIMIZATIONS", jaroslav@1493: config); jaroslav@750: try { jaroslav@750: return cw.doRun(); jaroslav@750: } catch (FlagUsageException ex) { jaroslav@750: throw new IOException(ex); jaroslav@750: } jaroslav@750: } lubomir@869: lubomir@1083: private static final String[] FIXED_EXTERNS = { lubomir@1083: "bck2brwsr", jaroslav@1522: "bck2BrwsrThrwrbl", jaroslav@1598: "register", lubomir@1083: "$class", lubomir@1083: "anno", lubomir@1083: "array", lubomir@1083: "access", lubomir@1083: "cls", lubomir@1083: "vm", lubomir@1083: "loadClass", lubomir@1083: "loadBytes", lubomir@1083: "jvmName", lubomir@1083: "primitive", lubomir@1083: "superclass", lubomir@1083: "cnstr", lubomir@1083: "add32", lubomir@1083: "sub32", lubomir@1083: "mul32", lubomir@1083: "neg32", lubomir@1083: "toInt8", lubomir@1083: "toInt16", lubomir@1083: "next32", lubomir@1083: "high32", lubomir@1083: "toInt32", lubomir@1083: "toFP", lubomir@1083: "toLong", jaroslav@1562: "toJS", lubomir@1083: "toExactString", lubomir@1083: "add64", lubomir@1083: "sub64", lubomir@1083: "mul64", lubomir@1083: "and64", lubomir@1083: "or64", lubomir@1083: "xor64", lubomir@1083: "shl64", lubomir@1083: "shr64", lubomir@1083: "ushr64", jaroslav@1562: "compare", lubomir@1083: "compare64", lubomir@1083: "neg64", lubomir@1083: "div32", lubomir@1083: "mod32", lubomir@1083: "div64", lubomir@1083: "mod64", lubomir@1083: "at", lubomir@1083: "getClass__Ljava_lang_Class_2", lubomir@1083: "clone__Ljava_lang_Object_2" lubomir@1083: }; jaroslav@750: }