| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 'use strict'; |
|
|
| |
| |
| |
| |
| class CustomError extends Error { |
| constructor(plugin, message) { |
| if (message instanceof Error) { |
| super(`Error in ${plugin}`); |
| this.original = message; |
| |
| this.stack = `${this.stack.split('\n').slice(0,2).join('\n')}\n${message.stack}`; |
| } else { |
| super(`${plugin}: ${message}`); |
| } |
| } |
| } |
|
|
| |
| |
| |
| |
| module.exports = function(initOptions) { |
| const filesToJson = require('./concat-to-json'); |
| const jsonToVinyl = require('./json-to-vinyl'); |
| const stream = require('stream'); |
| const {getNativeImagePath, getFirstSupportedPlatform} = require('../utils'); |
| |
| const PLUGIN_NAME = 'gulp-google-closure-compiler'; |
|
|
| const applySourceMap = require('vinyl-sourcemaps-apply'); |
| const chalk = require('chalk'); |
| const File = require('vinyl'); |
|
|
| const extraCommandArguments = initOptions ? initOptions.extraArguments : undefined; |
|
|
| let PluginError; |
| try { |
| PluginError = require('gulp-util').PluginError; |
| } catch(e) { |
| PluginError = CustomError; |
| } |
|
|
| let gulpLog; |
| try { |
| gulpLog = require('gulp-util').log; |
| } catch(e) { |
| gulpLog = console; |
| } |
|
|
| function getCompiler(platform) { |
| return require('../node/closure-compiler'); |
| } |
|
|
| class CompilationStream extends stream.Transform { |
| constructor(compilationOptions, pluginOptions) { |
| super({objectMode: true}); |
| pluginOptions = pluginOptions || {}; |
|
|
| this.compilationOptions_ = compilationOptions; |
| this.streamMode_ = pluginOptions.streamMode || 'BOTH'; |
| this.logger_ = pluginOptions.logger || gulpLog; |
| this.PLUGIN_NAME_ = pluginOptions.pluginName || PLUGIN_NAME; |
|
|
| this.fileList_ = []; |
| this._streamInputRequired = pluginOptions.requireStreamInput !== false; |
|
|
| let platforms = (pluginOptions && pluginOptions.platform) || ['native', 'java']; |
| if (!Array.isArray(platforms)) { |
| platforms = [platforms]; |
| } |
| this.platform = getFirstSupportedPlatform(platforms); |
| } |
|
|
| src() { |
| this._streamInputRequired = false; |
| process.nextTick(() => { |
| const stdInStream = new stream.Readable({ read: function() { |
| return new File(); |
| }}); |
| stdInStream.pipe(this); |
| stdInStream.push(null); |
| }); |
| return this; |
| } |
|
|
| _transform(file, enc, cb) { |
| |
| if (!file || file.isNull()) { |
| cb(); |
| return; |
| } |
|
|
| if (file.isStream()) { |
| this.emit('error', new PluginError(this.PLUGIN_NAME_, 'Streaming not supported')); |
| cb(); |
| return; |
| } |
|
|
| this.fileList_.push(file); |
| cb(); |
| } |
|
|
| _flush(cb) { |
| let jsonFiles; |
| if (this.fileList_.length > 0) { |
| |
| jsonFiles = filesToJson(this.fileList_); |
| } else { |
| |
| if (this._streamInputRequired) { |
| this.push(null); |
| cb(); |
| return; |
| } |
|
|
| |
| |
| jsonFiles = []; |
| } |
| const Compiler = getCompiler(this.platform); |
| const compiler = new Compiler(this.compilationOptions_, extraCommandArguments); |
| if (this.platform === 'native') { |
| compiler.JAR_PATH = null; |
| compiler.javaPath = getNativeImagePath(); |
| } |
| let stdOutData = ''; |
| let stdErrData = ''; |
|
|
| |
| |
| |
| compiler.commandArguments.push('--json_streams', this.streamMode_); |
| const compilerProcess = compiler.run(); |
|
|
| compilerProcess.stdout.on('data', data => { |
| stdOutData += data; |
| }); |
| compilerProcess.stderr.on('data', data => { |
| stdErrData += data; |
| }); |
| |
| compilerProcess.on('error', err => { |
| this.emit('error', new PluginError(this.PLUGIN_NAME_, |
| 'Process spawn error. Is java in the path?\n' + err.message)); |
| cb(); |
| }); |
| compilerProcess.stdin.on('error', err => { |
| stdErrData += `Error writing to stdin of the compiler. ${err.message}`; |
| }); |
|
|
| Promise.all([ |
| new Promise(resolve => compilerProcess.on('close', resolve)), |
| new Promise(resolve => compilerProcess.stdout.on('end', resolve)), |
| new Promise(resolve => compilerProcess.stderr.on('end', resolve)) |
| ]).then(results => { |
| const code = results[0]; |
|
|
| |
| |
| let outputFiles = []; |
| if (stdOutData.trim().length > 0) { |
| if (code !== 0) { |
| this.emit('error', new PluginError(this.PLUGIN_NAME_, 'Compiler error.\n' + stdOutData + '\n' + stdErrData)); |
| cb(); |
| return; |
| } |
| |
| |
| try { |
| outputFiles = JSON.parse(stdOutData); |
| } catch (e) { |
| this.emit('error', new PluginError(this.PLUGIN_NAME_, 'Error parsing json encoded files')); |
| cb(); |
| return; |
| } |
| } |
|
|
| this._compilationComplete(code, outputFiles, stdErrData); |
| cb(); |
| }).catch(err => { |
| this.emit('error', new PluginError(this.PLUGIN_NAME_, err, { showStack: true })); |
| cb(); |
| }); |
|
|
| const stdInStream = new stream.Readable({ read: function() {}}); |
| stdInStream.pipe(compilerProcess.stdin); |
| process.nextTick(() => { |
| stdInStream.push(JSON.stringify(jsonFiles)); |
| stdInStream.push(null); |
| }); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| _compilationComplete(exitCode, compiledJs, errors) { |
| |
| if (errors && errors.trim().length > 0) { |
| const logger = this.logger_.warn ? this.logger_.warn : this.logger_; |
| logger(`${chalk.yellow(this.PLUGIN_NAME_)}: ${errors}`); |
| } |
|
|
| |
| if (exitCode !== 0) { |
| this.emit('error', new PluginError(this.PLUGIN_NAME_, `Compilation errors occurred`)); |
| } |
|
|
| |
| |
| let outputFiles = jsonToVinyl(compiledJs); |
|
|
| for (let i = 0; i < outputFiles.length; i++) { |
| if (outputFiles[i].sourceMap) { |
| applySourceMap(outputFiles[i], outputFiles[i].sourceMap); |
| } |
| this.push(outputFiles[i]); |
| } |
| } |
| } |
|
|
| return (compilationOptions, pluginOptions) => new CompilationStream(compilationOptions, pluginOptions); |
| }; |
|
|