private void compileRaw(Config config) { Preconditions.checkArgument( config.getCompilationMode() == CompilationMode.RAW, "Config must be in RAW mode"); StringBuilder builder = new StringBuilder(); for (SourceFile input : inputs) { try { builder.append(input.getCode()); } catch (IOException e) { throw new RuntimeException(e); } } inputJsConcatenatedInOrder = builder.toString(); // Need to have a dummy Result that appears to be a success (i.e., has // no // errors or warnings). this.result = new Result( new JSError[0], // errors new JSError[0], // warnings null, null, null, null, null, null, null, null, null, null); }
public void compile(Config config) { this.compileStartTimestamp = System.currentTimeMillis(); this.config = config; if (config.getCompilationMode() == CompilationMode.RAW) { compileRaw(config); } else { PlovrClosureCompiler compiler = new PlovrClosureCompiler(); compile(config, compiler, config.getCompilerOptions(compiler)); } }
/** * This method always calls compiler.toSource(module), which means that it can be followed by a * call to compiler.getSourceMap().appendTo(writer, module), though * compiler.getSourceMap().reset() should be called immediately after when that is the case. * * <p>This method is sychronized in order to fix * http://code.google.com/p/plovr/issues/detail?id=31. The problem is that if two modules are * requested at the same time, it is often the case that compiler.toSource(module) is executing * for the second module while the source map is still being modified for the first module, * causing an IllegalStateException. Empirically, synchronizing this method appears to fix things, * though a more provably correct (and minimal) solution should be sought. */ private synchronized String getCodeForModule( String moduleName, boolean isDebugMode, Function<String, String> moduleNameToUri, boolean resetSourceMap) { Preconditions.checkState(hasResult(), "Code has not been compiled yet"); Preconditions.checkState(modules != null, "This compilation does not use modules"); StringBuilder builder = new StringBuilder(); ModuleConfig moduleConfig = config.getModuleConfig(); String rootModule = moduleConfig.getRootModule(); boolean isRootModule = rootModule.equals(moduleName); if (isRootModule) { // For the root module, prepend the following global variables: // // PLOVR_MODULE_INFO // PLOVR_MODULE_URIS // PLOVR_MODULE_USE_DEBUG_MODE // // Because the standard way to read these variables in the // application is: // // moduleLoader.setDebugMode(!!goog.global['PLOVR_MODULE_USE_DEBUG_MODE']); // moduleManager.setLoader(moduleLoader); // moduleManager.setAllModuleInfo(goog.global['PLOVR_MODULE_INFO']); // moduleManager.setModuleUris(goog.global['PLOVR_MODULE_URIS']); // // It is important that the PLOVR variables are guaranteed to be // global, // which (as much as it pains me) is why "var" is omitted. if (!moduleConfig.excludeModuleInfoFromRootModule()) { try { appendRootModuleInfo(builder, isDebugMode, moduleNameToUri); } catch (IOException e) { // This should not occur because data is being appended to // an // in-memory StringBuilder rather than a file. throw new RuntimeException(e); } } } int lineOffset = 0; JSModule module = nameToModule.get(moduleName); StringBuffer prependBuffer = new StringBuffer(); if (isRootModule) { lineOffset++; // one line for the function wrapper for (File prepend : config.getPrependInputs()) { try { String s = Files.toString(prepend); if (s != null) { String[] lines = s.split("\n"); for (String line : lines) { prependBuffer.append(line); prependBuffer.append("\n"); lineOffset++; } } } catch (IOException e) { e.printStackTrace(); } } } compiler.setPrependedLineOffset(lineOffset); String moduleCode = compiler.toSource(module); boolean hasGlobalScopeName = !Strings.isNullOrEmpty(config.getGlobalScopeName()) && config.getCompilationMode() != CompilationMode.WHITESPACE; // Optionally wrap the module in an anonymous function, with the // requisite wrapper to make it work. if (hasGlobalScopeName) { if (isRootModule) { builder.append(prependBuffer.toString()); // Initialize the global scope in the root module. builder.append(config.getGlobalScopeName()); builder.append("={};"); } builder.append("(function("); builder.append(Config.GLOBAL_SCOPE_NAME); // Including a newline makes the offset into the source map easier to calculate. builder.append("){\n"); } builder.append(moduleCode); if (hasGlobalScopeName) { builder.append("})("); builder.append(config.getGlobalScopeName()); builder.append(");"); } if (resetSourceMap) { SourceMap sourceMap = compiler.getSourceMap(); if (sourceMap != null) sourceMap.reset(); } // http://code.google.com/p/closure-library/issues/detail?id=196 // http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/ // non-root modules are loaded with eval, give it a sourceURL for better // debugging if (!isRootModule) { builder.append("\n//@ sourceURL=" + moduleNameToUri.apply(moduleName)); } return builder.toString(); }