UNPKG

dojo-util

Version:

Dojo utilities including build system for optimizing JavaScript application performance, and DOH testing tool

334 lines (300 loc) 10.3 kB
/*jshint rhino:true white:false */ /*global Packages:false com:false */ function writeFile(filename, contents, encoding, cb) { if (arguments.length === 3 && typeof encoding !== "string") { cb = encoding; encoding = 0; } var outFile = new java.io.File(filename), outWriter; if(encoding){ outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding); }else{ outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile)); } var os = new java.io.BufferedWriter(outWriter); try{ os.write(contents); }finally{ os.close(); } if (cb) { cb(0); } } var built = "//>>built\n"; function sscompile(src, dest, optimizeSwitch, copyright){ // decode the optimize switch var options = optimizeSwitch.split("."), comments = 0, keepLines = 0, strip = null; while(options.length){ switch(options.pop()){ case "normal": strip = "normal"; break; case "warn": strip = "warn"; break; case "all": strip = "all"; break; case "keeplines": keepLines = 1; break; case "comments": comments = 1; break; } } //Use rhino to help do minifying/compressing. var context = Packages.org.mozilla.javascript.Context.enter(), text; try{ // Use the interpreter for interactive input (copied this from Main rhino class). context.setOptimizationLevel(-1); text = readFile(src, "utf-8"); if(comments){ //Strip comments var script = context.compileString(text, dest, 1, null); text = new String(context.decompileScript(script, 0)); //Replace the spaces with tabs. //Ideally do this in the pretty printer rhino code. text = text.replace(/ /g, "\t"); }else{ //Apply compression using custom compression call in Dojo-modified rhino. text = new String(Packages.org.dojotoolkit.shrinksafe.Compressor.compressScript(text, 0, 1, strip)); if(!keepLines){ text = text.replace(/[\r\n]/g, ""); } } }finally{ Packages.org.mozilla.javascript.Context.exit(); } writeFile(dest, copyright + built + text, "utf-8"); } var JSSourceFilefromCode, closurefromCode, compiler, jscomp = 0; function ccompile(src, dest, optimizeSwitch, copyright, optimizeOptions, useSourceMaps){ optimizeOptions = optimizeOptions || {}; if(!jscomp){ JSSourceFilefromCode=java.lang.Class.forName("com.google.javascript.jscomp.SourceFile").getMethod("fromCode", [java.lang.String, java.lang.String]); closurefromCode = function(filename,content){ return JSSourceFilefromCode.invoke(null,[filename,content]); }; jscomp = com.google.javascript.jscomp; } //Fake extern required with 'Symbol' defined var externSourceFile = closurefromCode("fakeextern.js", "function Symbol(description) {}"); //Set up source input // it is possible dest could have backslashes on windows (particularly with cygwin) var destFilename = dest.match(/^.+[\\\/](.+)$/)[1], jsSourceFile = closurefromCode(destFilename + ".uncompressed.js", String(readFile(src, "utf-8"))); //Set up options var options = new jscomp.CompilerOptions(); var set; // Set the closure optimization level, use simple optimizations by default var FLAG_compilation_level = jscomp.CompilationLevel.SIMPLE_OPTIMIZATIONS; if (optimizeOptions.compilationLevel) { switch (optimizeOptions.compilationLevel.toUpperCase()) { case "WHITESPACE_ONLY": FLAG_compilation_level = jscomp.CompilationLevel.WHITESPACE_ONLY; break; case "SIMPLE_OPTIMIZATIONS": FLAG_compilation_level = jscomp.CompilationLevel.SIMPLE_OPTIMIZATIONS; break; case "ADVANCED_OPTIMIZATIONS": FLAG_compilation_level = jscomp.CompilationLevel.ADVANCED_OPTIMIZATIONS; break; } } FLAG_compilation_level.setOptionsForCompilationLevel(options); var FLAG_warning_level = jscomp.WarningLevel.DEFAULT; FLAG_warning_level.setOptionsForWarningLevel(options); // force this option to false to prevent overly aggressive code elimination (#18919) options.setDeadAssignmentElimination(false); options.setEmitUseStrict(false); options.setStrictModeInput(false); options.setWarningLevel(jscomp.DiagnosticGroups.ES5_STRICT, jscomp.CheckLevel.WARNING); for(var k in optimizeOptions){ // Skip compilation level option if (k === 'compilationLevel') { continue; } // Set functions requiring Java Enum values if (k === 'languageIn') { options.setLanguageIn(jscomp.CompilerOptions.LanguageMode.fromString(optimizeOptions[k].toUpperCase())); continue; } if (k === 'languageOut') { options.setLanguageOut(jscomp.CompilerOptions.LanguageMode.fromString(optimizeOptions[k].toUpperCase())); continue; } if (k === 'variableRenaming') { switch (optimizeOptions[k].toUpperCase()) { case 'OFF': options.setVariableRenaming(jscomp.VariableRenamingPolicy.OFF); break; case 'LOCAL': options.setVariableRenaming(jscomp.VariableRenamingPolicy.LOCAL); break; case 'ALL': options.setVariableRenaming(jscomp.VariableRenamingPolicy.ALL); break; } continue; } if (k === 'propertyRenaming') { switch (optimizeOptions[k].toUpperCase()) { case 'OFF': options.setPropertyRenaming(jscomp.PropertyRenamingPolicy.OFF); break; case 'ALL_UNQUOTED': options.setPropertyRenaming(jscomp.PropertyRenamingPolicy.ALL_UNQUOTED); break; } continue; } if (k === 'checkGlobalThisLevel') { switch (optimizeOptions[k].toUpperCase()) { case 'ERROR': options.setCheckGlobalThisLevel(jscomp.CheckLevel.ERROR); break; case 'WARNING': options.setCheckGlobalThisLevel(jscomp.CheckLevel.WARNING); break; case 'OFF': options.setCheckGlobalThisLevel(jscomp.CheckLevel.OFF); break; } continue; } if (k === 'uselessCode') { var uselessCode = jscomp.DiagnosticGroups.CHECK_USELESS_CODE; switch (optimizeOptions[k].toUpperCase()) { case 'ERROR': options.setWarningLevel(uselessCode, jscomp.CheckLevel.ERROR); break; case 'WARNING': options.setWarningLevel(uselessCode, jscomp.CheckLevel.WARNING); break; case 'OFF': options.setWarningLevel(uselessCode, jscomp.CheckLevel.OFF); break; } continue; } if (k in { 'removeUnusedVariables': 1, 'inlineVariables': 1, 'inlineFunctions': 1 }) { set = "set" + k.charAt(0).toUpperCase() + k.substr(1); switch (optimizeOptions[k].toUpperCase()) { case 'ALL': options[set](jscomp.CompilerOptions.Reach.ALL); break; case 'LOCAL_ONLY': options[set](jscomp.CompilerOptions.Reach.LOCAL_ONLY); break; case 'NONE': options[set](jscomp.CompilerOptions.Reach.NONE); break; } continue; } // Set functions with boolean values if (k === 'dependencySorting') { options.dependencyOptions.setDependencySorting(optimizeOptions[k]); continue; } if (k in { 'assumeClosuresOnlyCaptureReferences': 1, 'closurePass': 1, 'coalesceVariableNames': 1, 'collapseAnonymousFunctions': 1, 'collapseProperties': 1, 'collapseVariableDeclarations': 1, 'computeFunctionSideEffects': 1, 'crossModuleCodeMotion': 1, 'crossModuleMethodMotion': 1, 'deadAssignmentElimination': 1, 'devirtualizePrototypeMethods': 1, 'extractPrototypeMemberDeclarations': 1, 'flowSensitiveInlineVariables': 1, 'foldConstants': 1, 'inlineConstantVars': 1, 'optimizeArgumentsArray': 1, 'removeDeadCode': 1, 'removeUnusedClassProperties': 1, 'removeUnusedPrototypeProperties': 1, 'removeUnusedPrototypePropertiesInExterns': 1, 'rewriteFunctionExpressions': 1, 'smartNameRemoval': 1 }) { set = 'set' + k.charAt(0).toUpperCase() + k.substr(1); options[set](optimizeOptions[k]); continue; } // Otherwise assign value to key options[k] = optimizeOptions[k]; } // Must have non-null path to trigger source map generation, also fix version options.setSourceMapOutputPath(""); options.setSourceMapFormat(jscomp.SourceMap.Format.V3); if(optimizeSwitch.indexOf(".keeplines") !== -1){ options.prettyPrint = true; } //Prevent too-verbose logging output Packages.com.google.javascript.jscomp.Compiler.setLoggingLevel(java.util.logging.Level.SEVERE); // Run the compiler // File name and associated map name var mapTag = useSourceMaps ? ("\n//# sourceMappingURL=" + destFilename + ".map") : ""; compiler = new Packages.com.google.javascript.jscomp.Compiler(Packages.java.lang.System.err); compiler.compile(externSourceFile, jsSourceFile, options); writeFile(dest, copyright + built + compiler.toSource() + mapTag, "utf-8"); if(useSourceMaps){ var sourceMap = compiler.getSourceMap(); sourceMap.setWrapperPrefix(copyright + built); var sb = new java.lang.StringBuffer(); sourceMap.appendTo(sb, destFilename); writeFile(dest + ".map", sb.toString(), "utf-8"); } } function shutdownClosureExecutorService(){ try{ var compilerClass = compiler.getClass(); var compilerExecutorField = compilerClass.getDeclaredMethod("getCompilerExecutor"); compilerExecutorField.setAccessible(true); var compilerExecutor = compilerExecutorField.invoke(compiler); compilerClass = compilerExecutor.getClass(); compilerExecutorField = compilerClass.getDeclaredMethod("getExecutorService"); compilerExecutorField.setAccessible(true); compilerExecutor = compilerExecutorField.invoke(compilerExecutor); compilerExecutor.shutdown(); }catch (e){ print(e); if("javaException" in e){ e.javaException.printStackTrace(); } } } var console = new java.io.BufferedReader(new java.io.InputStreamReader(java.lang.System["in"])), readLine = function(){ // the + "" convert to a Javascript string return console.readLine() + ""; }, src, dest, optimizeSwitch; while(1){ src = readLine(); if(src === "."){ break; } dest = readLine(); optimizeSwitch = readLine(); var options = eval("(" + readLine() + ")"); print(dest + ":"); var start = (new Date()).getTime(), exception = ""; try{ if(/closure/.test(optimizeSwitch)){ ccompile(src, dest, optimizeSwitch, options.copyright, options.options, options.useSourceMaps); }else{ sscompile(src, dest, optimizeSwitch, options.copyright); } }catch(e){ exception = ". OPTIMIZER FAILED: " + e; } print("Done (compile time:" + ((new Date()).getTime()-start)/1000 + "s)" + exception); } if (jscomp) { shutdownClosureExecutorService(); }