From 3525130c5062e3d5f60804e359f7f06889c80f08 Mon Sep 17 00:00:00 2001 From: indexzero Date: Wed, 5 Oct 2011 22:11:36 -0400 Subject: [PATCH] [minor] Update lib/forever* for JSHint --- lib/forever.js | 418 ++++++++++++++++++++++------------------- lib/forever/cli.js | 162 ++++++++-------- lib/forever/monitor.js | 21 ++- 3 files changed, 320 insertions(+), 281 deletions(-) diff --git a/lib/forever.js b/lib/forever.js index d7a23760..b51e88bc 100644 --- a/lib/forever.js +++ b/lib/forever.js @@ -49,6 +49,97 @@ forever.cli = require('./forever/cli'); // require('pkginfo')(module, 'version'); +// +// ### function getSockets (sockPath, callback) +// #### @sockPath {string} Path in which to look for UNIX domain sockets +// #### @callback {function} Continuation to pass control to when complete +// Attempts to read the files from `sockPath` if the directory does not exist, +// then it is created using `mkdirp`. +// +function getSockets(sockPath, callback) { + var sockets; + + try { + sockets = fs.readdirSync(sockPath); + } + catch (ex) { + if (ex.code !== 'ENOENT') { + return callback(ex); + } + + return mkdirp(sockPath, '0755', function (err) { + return err ? callback(err) : callback(null, []); + }); + } + + callback(null, sockets); +} + +// +// ### function getAllProcess (callback) +// #### @callback {function} Continuation to respond to when complete. +// Returns all data for processes managed by forever. +// +function getAllProcesses(callback) { + var sockPath = forever.config.get('sockPath'), + results = []; + + function getProcess(name, next) { + var fullPath = path.join(sockPath, name), + socket = new net.Socket({ type: 'unix' }); + + socket.on('error', function (err) { + if (err.code === 'ECONNREFUSED') { + try { + fs.unlinkSync(fullPath); + } + catch (ex) { } + return next(); + } + else if (err.code === 'EACCES') { + forever.log.warn('Error contacting: ' + fullPath.magenta); + } + else { + forever.log.error('Unknown error (' + err.code + ') when contacting: ' + fullPath.magenta); + } + + next(); + }); + + socket.on('data', function (data) { + var monitors = JSON.parse(data.toString()); + results.push.apply(results, monitors.monitors); + next(); + }); + + socket.connect(fullPath); + } + + getSockets(sockPath, function (err, sockets) { + if (err || (sockets && sockets.length === 0)) { + return callback(err); + } + + async.forEach(sockets, getProcess, function () { + callback(results); + }); + }); +} + +// +// ### function getAllPids () +// Returns the set of all pids managed by forever. +// e.x. [{ pid: 12345, foreverPid: 12346 }, ...] +// +function getAllPids(processes) { + return !processes ? null : processes.map(function (proc) { + return { + pid: proc.pid, + foreverPid: proc.foreverPid + }; + }); +} + // // ### function load (options, [callback]) // #### @options {Object} Options to load into the forever module @@ -78,9 +169,11 @@ forever.load = function (options) { // Try to load the forever `config.json` from // the specified location. // - try { forever.config.loadSync() } + try { + forever.config.loadSync(); + } catch (ex) { } - + // // Setup the columns for `forever list`. // @@ -90,7 +183,7 @@ forever.load = function (options) { 'uid', 'command', 'script', 'forever', 'pid', 'logfile', 'uptime' ]; } - + forever.config.set('root', options.root); forever.config.set('pidPath', options.pidPath); forever.config.set('sockPath', options.sockPath); @@ -116,8 +209,10 @@ forever.load = function (options) { // an additional overhead here of the sync action. It simplifies // the setup of forever dramatically. // - function tryCreate (dir) { - try { fs.mkdirSync(dir, 0755) } + function tryCreate(dir) { + try { + fs.mkdirSync(dir, '0755'); + } catch (ex) { } } @@ -127,7 +222,9 @@ forever.load = function (options) { // // Attempt to save the new `config.json` for forever // - try { forever.config.saveSync() } + try { + forever.config.saveSync(); + } catch (ex) { } forever.initialized = true; @@ -139,15 +236,15 @@ forever.load = function (options) { // forever._debug = function () { var debug = forever.config.get('debug'); - + if (!debug) { forever.config.set('debug', true); forever.log.add(winston.transports.File, { level: 'silly', filename: path.join(forever.config.get('root'), 'forever.debug.log') - }); + }); } -} +}; // // Ensure forever will always be loaded the first time it is required. @@ -242,10 +339,12 @@ forever.startServer = function () { monitors = [], callback, server; - + args.forEach(function (a) { if (Array.isArray(a)) { - monitors = monitors.concat(a.filter(function (m) { return m instanceof forever.Monitor })); + monitors = monitors.concat(a.filter(function (m) { + return m instanceof forever.Monitor; + })); } else if (a instanceof forever.Monitor) { monitors.push(a); @@ -254,28 +353,30 @@ forever.startServer = function () { callback = a; } }); - + server = net.createServer(function (socket) { // // Write the specified data and close the socket // - socket.end(JSON.stringify({ - monitors: monitors.map(function (m) { return m.data }) + socket.end(JSON.stringify({ + monitors: monitors.map(function (m) { + return m.data; + }) })); }); + + function onError(err) { + monitors.forEach(function (mon) { + mon.emit('error', err); + }); + } portfinder.getSocket({ path: socket }, function (err, socket) { if (err) { - // - // TODO: This is really bad. - // + return onError(err); } - server.on('error', function () { - // - // TODO: This is really bad. - // - }); + server.on('error', onError); server.listen(socket, function () { if (callback) { @@ -304,7 +405,9 @@ forever.stop = function (target, format) { if (procs && procs.length > 0) { procs.forEach(function (proc) { [proc.foreverPid, proc.pid].forEach(function (pid) { - try { process.kill(pid) } + try { + process.kill(pid); + } catch (ex) { } }); }); @@ -365,7 +468,7 @@ forever.restart = function (target, format) { restartCommand.push(proc.file, proc.options.join(' ')); forever.log.silly('Restarting with options', { options: restartCommand.join(' ') }); - + exec(restartCommand.join(' '), function (err, stdout, stderr) { next(); }); @@ -393,7 +496,7 @@ forever.restart = function (target, format) { // Finds the process with the specified index. // forever.findByIndex = function (index, processes) { - var proc = processes && processes[parseInt(index)]; + var proc = processes && processes[parseInt(index, 10)]; return proc ? [proc] : null; }; @@ -404,9 +507,11 @@ forever.findByIndex = function (index, processes) { // Finds the process with the specified script name. // forever.findByScript = function (script, processes) { - return processes - ? processes.filter(function (p) { return p.file === script }) - : null; + return !processes + ? null + : processes.filter(function (p) { + return p.file === script; + }); }; // @@ -418,15 +523,22 @@ forever.stopAll = function (format) { var emitter = new events.EventEmitter(); getAllProcesses(function (processes) { - var pids = getAllPids(processes); + var pids = getAllPids(processes), + fPids, + cPids; if (format) { processes = forever.format(format, processes); } if (pids && processes) { - var fPids = pids.map(function (pid) { return pid.foreverPid }), - cPids = pids.map(function (pid) { return pid.pid }); + fPids = pids.map(function (pid) { + return pid.foreverPid; + }); + + cPids = pids.map(function (pid) { + return pid.pid; + }); fPids.concat(cPids).forEach(function (pid) { try { @@ -474,39 +586,40 @@ forever.format = function (format, procs) { if (!procs || procs.length === 0) { return null; } + + var index = 0, + columns = forever.config.get('columns'), + rows = [[' '].concat(columns)], + formatted; + + function mapColumns(prefix, mapFn) { + return [prefix].concat(columns.map(mapFn)); + } if (format) { - var index = 0, - columns = forever.config.get('columns'), - rows = [[' '].concat(columns)]; - - function mapColumns (prefix, mapFn) { - return [prefix].concat(columns.map(mapFn)); - } - // // Iterate over the procs to see which has the // longest options string // procs.forEach(function (proc) { rows.push(mapColumns('[' + index + ']', function (column) { - return forever.columns[column] - ? forever.columns[column].get(proc) + return forever.columns[column] + ? forever.columns[column].get(proc) : 'MISSING'; })); - + index++; }); formatted = cliff.stringifyRows(rows, mapColumns('white', function (column) { - return forever.columns[column] - ? forever.columns[column].color + return forever.columns[column] + ? forever.columns[column].color : 'white'; })); } return format ? formatted : procs; -} +}; // // ### function cleanUp () @@ -521,64 +634,64 @@ forever.cleanUp = function (cleanLogs, allowManager) { if (cleanLogs) { forever.cleanLogsSync(processes); } + + function unlinkProcess(proc, done) { + fs.unlink(path.join(pidPath, proc.uid + '.pid'), function () { + // + // Ignore errors (in case the file doesnt exist). + // - if (processes && processes.length > 0) { - function unlinkProcess (proc, done) { - fs.unlink(path.join(pidPath, proc.uid + '.pid'), function () { + if (cleanLogs && proc.logFile) { // - // Ignore errors (in case the file doesnt exist). + // If we are cleaning logs then do so if the process + // has a logfile. // + return fs.unlink(proc.logFile, function () { + done(); + }); + } - if (cleanLogs && proc.logFile) { - // - // If we are cleaning logs then do so if the process - // has a logfile. - // - return fs.unlink(proc.logFile, function () { - done(); - }); - } + done(); + }); + } - done(); - }); + function cleanProcess(proc, done) { + if (proc.child && proc.manager) { + return done(); + } + else if (!proc.child && !proc.manager + || (!proc.child && proc.manager && allowManager) + || proc.dead) { + return unlinkProcess(proc, done); } - function cleanProcess (proc, done) { - if (proc.child && proc.manager) { - return done(); - } - else if (!proc.child && !proc.manager - || (!proc.child && proc.manager && allowManager) - || proc.dead) { - return unlinkProcess(proc, done); - } - - // - // If we have a manager but no child, wait a moment - // in-case the child is currently restarting, but **only** - // if we have not already waited for this process - // - if (!proc.waited) { - proc.waited = true; - return setTimeout(function () { - checkProcess(proc, done); - }, 500); - } - - done(); + // + // If we have a manager but no child, wait a moment + // in-case the child is currently restarting, but **only** + // if we have not already waited for this process + // + if (!proc.waited) { + proc.waited = true; + return setTimeout(function () { + checkProcess(proc, done); + }, 500); } - function checkProcess (proc, next) { - forever.checkProcess(proc.pid, function (child) { - proc.child = child; - forever.checkProcess(proc.foreverPid, function (manager) { - proc.manager = manager; - cleanProcess(proc, next); - }); + done(); + } + + function checkProcess(proc, next) { + forever.checkProcess(proc.pid, function (child) { + proc.child = child; + forever.checkProcess(proc.foreverPid, function (manager) { + proc.manager = manager; + cleanProcess(proc, next); }); - } + }); + } - (function cleanBatch (batch) { + if (processes && processes.length > 0) { + (function cleanBatch(batch) { async.forEach(batch, checkProcess, function () { return processes.length > 0 ? cleanBatch(processes.splice(0, 10)) @@ -605,8 +718,16 @@ forever.cleanUp = function (cleanLogs, allowManager) { forever.cleanLogsSync = function (processes) { var root = forever.config.get('root'), files = fs.readdirSync(root), - running = processes && processes.filter(function (p) { return p && p.logFile }), - runningLogs = running && running.map(function (p) { return p.logFile.split('/').pop() }); + running, + runningLogs; + + running = processes && processes.filter(function (p) { + return p && p.logFile; + }); + + runningLogs = running && running.map(function (p) { + return p.logFile.split('/').pop(); + }); files.forEach(function (file) { if (/\.log$/.test(file) && (!runningLogs || runningLogs.indexOf(file) === -1)) { @@ -630,10 +751,10 @@ forever.randomString = function (bits) { // in v8, Math.random() yields 32 pseudo-random bits (in spidermonkey it gives 53) // while (bits > 0) { - rand = Math.floor(Math.random()*0x100000000) // 32-bit integer + rand = Math.floor(Math.random() * 0x100000000); // 32-bit integer // base 64 means 6 bits per character, so we use the top 30 bits from rand to give 30/6=5 characters. - for (i=26; i>0 && bits>0; i-=6, bits-=6) { - ret+=chars[0x3F & rand >>> i]; + for (i = 26; i > 0 && bits > 0; i -= 6, bits -= 6) { + ret += chars[0x3F & rand >>> i]; } } @@ -645,7 +766,7 @@ forever.randomString = function (bits) { // #### @logFile {string} Log file path // Determines the full logfile path name // -forever.logFilePath = function(logFile, uid) { +forever.logFilePath = function (logFile, uid) { return logFile && logFile[0] === '/' ? logFile : path.join(forever.config.get('root'), logFile || (uid || 'forever') + '.log'); @@ -656,7 +777,7 @@ forever.logFilePath = function(logFile, uid) { // #### @logFile {string} Pid file path // Determines the full pid file path name // -forever.pidFilePath = function(pidFile) { +forever.pidFilePath = function (pidFile) { return pidFile && pidFile[0] === '/' ? pidFile : path.join(forever.config.get('pidPath'), pidFile); @@ -700,121 +821,34 @@ forever.columns = { return (proc.command || 'node').grey; } }, - script: { + script: { color: 'grey', get: function (proc) { return [proc.file].concat(proc.options).join(' ').grey; } }, - forever: { + forever: { color: 'white', get: function (proc) { return proc.foreverPid; } }, - pid: { + pid: { color: 'white', get: function (proc) { return proc.pid; } }, - logfile: { + logfile: { color: 'magenta', get: function (proc) { return proc.logFile ? proc.logFile.magenta : ''; } }, - uptime: { + uptime: { color: 'yellow', get: function (proc) { return timespan.fromDates(new Date(proc.ctime), new Date()).toString().yellow; } } -}; - -// -// ### function getAllProcess (callback) -// #### @callback {function} Continuation to respond to when complete. -// Returns all data for processes managed by forever. -// -function getAllProcesses (callback) { - var sockPath = forever.config.get('sockPath'), - results = []; - - function getProcess (name, next) { - var fullPath = path.join(sockPath, name), - socket = new net.Socket({ type: 'unix' }); - - socket.on('error', function (err) { - if (err.code === 'ECONNREFUSED') { - try { fs.unlinkSync(fullPath) } - catch (ex) { } - return next(); - } - else if (err.code === 'EACCES') { - forever.log.warn('Error contacting: ' + fullPath.magenta); - } - else { - forever.log.error('Unknown error (' + err.code + ') when contacting: ' + fullPath.magenta); - } - - next(); - }); - - socket.on('data', function (data) { - var monitors = JSON.parse(data.toString()); - results.push.apply(results, monitors.monitors); - next(); - }); - - socket.connect(fullPath); - } - - getSockets(sockPath, function (err, sockets) { - if (err || (sockets && sockets.length === 0)) { - return callback(err); - } - - async.forEach(sockets, getProcess, function () { - callback(results); - }); - }) -}; - -// -// ### function getSockets (sockPath, callback) -// #### @sockPath {string} Path in which to look for UNIX domain sockets -// #### @callback {function} Continuation to pass control to when complete -// Attempts to read the files from `sockPath` if the directory does not exist, -// then it is created using `mkdirp`. -// -function getSockets (sockPath, callback) { - try { - var sockets = fs.readdirSync(sockPath); - } - catch (ex) { - if (ex.code !== 'ENOENT') { - return callback(ex); - } - - return mkdirp(sockPath, 0755, function (err) { - return err ? callback(err) : callback(null, []); - }); - } - - callback(null, sockets); -} - -// -// ### function getAllPids () -// Returns the set of all pids managed by forever. -// e.x. [{ pid: 12345, foreverPid: 12346 }, ...] -// -function getAllPids (processes) { - return !processes ? null : processes.map(function (proc) { - return { - pid: proc.pid, - foreverPid: proc.foreverPid - } - }); -}; +}; \ No newline at end of file diff --git a/lib/forever/cli.js b/lib/forever/cli.js index 5fd3ec66..39b468e9 100644 --- a/lib/forever/cli.js +++ b/lib/forever/cli.js @@ -9,14 +9,58 @@ var fs = require('fs'), path = require('path'), cliff = require('cliff'), - tty = require('tty'); - daemon = require('daemon'); + tty = require('tty'), + daemon = require('daemon'), forever = require('../forever'); var cli = exports; var reserved = ['root', 'pidPath']; +// +// ### @private function (file, options, callback) +// #### @file {string} Target script to start +// #### @options {Object} Options to start the script with +// #### @callback {function} Continuation to respond to when complete. +// Helper function that sets up the pathing for the specified `file` +// then stats the appropriate files and responds. +// +function tryStart(file, options, callback) { + var fullLog, fullScript; + + fullLog = forever.logFilePath(options.logFile, options.uid); + fullScript = path.join(options.sourceDir, file); + + forever.stat(fullLog, fullScript, options.appendLog, function (err) { + if (err) { + forever.log.error('Cannot start forever'); + forever.log.error(err.message); + process.exit(-1); + } + + callback(); + }); +} + +// +// ### @private function updateConfig (updater) +// #### @updater {function} Function which updates the forever config +// Helper which runs the specified `updater` and then saves the forever +// config to `forever.config.get('root')`. +// +function updateConfig(updater) { + updater(); + forever.config.save(function (err) { + if (err) { + return forever.log.error('Error saving config: ' + err.message); + } + + cli.config(); + var configFile = path.join(forever.config.get('root'), 'config.json'); + forever.log.info('Forever config saved: ' + configFile.yellow); + }); +} + // // ### function exec (action, file, options) // #### @action {string} CLI action to execute @@ -25,15 +69,16 @@ var reserved = ['root', 'pidPath']; // Executes the `action` in forever with the specified `file` and `options`. // cli.exec = function (action, file, options) { - var display = Array.isArray(action) ? action.join(' ') : action; - + var display = Array.isArray(action) ? action.join(' ') : action, + tidy; + if (action) { forever.log.info('Running action: ' + display.yellow); } if (action === 'cleanlogs') { forever.log.silly('Tidying ' + forever.config.get('root')); - var tidy = forever.cleanUp(action === 'cleanlogs'); + tidy = forever.cleanUp(action === 'cleanlogs'); tidy.on('cleanUp', function () { forever.log.silly(forever.config.get('root') + ' tidied.'); }); @@ -60,7 +105,7 @@ cli.exec = function (action, file, options) { return cli.start(file, options); } - return Array.isArray(action) + return Array.isArray(action) ? cli[action[0]](action[1], options) : cli[action](file, options, true); }; @@ -100,7 +145,7 @@ cli.stop = function (file) { }); runner.on('error', function (err) { - forever.log.error('Forever cannot find process with index: ' + file) + forever.log.error('Forever cannot find process with index: ' + file); }); }; @@ -158,7 +203,7 @@ cli.list = function () { forever.log.info('Forever processes running'); processes.split('\n').forEach(function (line) { forever.log.data(line); - }) + }); } else { forever.log.info('No forever processes running'); @@ -177,8 +222,8 @@ cli.config = function () { if (keys.length <= 2) { conf = conf.replace(/\{\s/, '{ \n') .replace(/\}/, '\n}') - .replace('\033[90m', ' \033[90m') - .replace(/, /ig, ',\n ') + .replace('\\033[90m', ' \\033[90m') + .replace(/, /ig, ',\n '); } else { conf = conf.replace(/\n\s{4}/ig, '\n '); @@ -229,7 +274,7 @@ cli.clear = function (key) { // ### function columns (action, value) // #### @action {string} The subaction to execute // #### @value {Array} The value to use in the specified `action`. -// Executes the specified subaction: `add`, `rm`, and `set` which +// Executes the specified subaction: `add`, `rm`, and `set` which // add, remove, or completely overrides the columns used by `forever list` // and `forever.list()`. // @@ -239,33 +284,34 @@ cli.columns = function (action, value) { forever.log.info('Use: ' + 'columns '.yellow); return; } - + var columns = forever.config.get('columns'), - actions = { add: addColumn, rm: rmColumn, set: setColumns }, - allColumns = Object.keys(forever.columns); + allColumns = Object.keys(forever.columns), + actions; - function addColumn () { - if (~columns.indexOf(value)) { - return forever.log.warn(value.magenta + ' already exists in forever'); - } - - forever.log.info('Adding column: ' + value.magenta); - columns.push(value); - } - - function rmColumn () { - if (!~columns.indexOf(value)) { - return forever.log.warn(value.magenta + ' doesn\'t exist in forever'); + + actions = { + add: function addColumn() { + if (~columns.indexOf(value)) { + return forever.log.warn(value.magenta + ' already exists in forever'); + } + + forever.log.info('Adding column: ' + value.magenta); + columns.push(value); + }, + rm: function rmColumn() { + if (!~columns.indexOf(value)) { + return forever.log.warn(value.magenta + ' doesn\'t exist in forever'); + } + + forever.log.info('Removing column: ' + value.magenta); + columns.splice(columns.indexOf(value), 1); + }, + set: function setColumns() { + forever.log.info('Setting columns: ' + value.join(' ').magenta); + columns = value; } - - forever.log.info('Removing column: ' + value.magenta); - columns.splice(columns.indexOf(value), 1); - } - - function setColumns () { - forever.log.info('Setting columns: ' + value.join(' ').magenta); - columns = value; - } + }; if (action !== 'set') { value = value[0]; @@ -278,48 +324,4 @@ cli.columns = function (action, value) { actions[action](); forever.config.set('columns', columns); forever.config.saveSync(); -} - -// -// ### @private function (file, options, callback) -// #### @file {string} Target script to start -// #### @options {Object} Options to start the script with -// #### @callback {function} Continuation to respond to when complete. -// Helper function that sets up the pathing for the specified `file` -// then stats the appropriate files and responds. -// -function tryStart (file, options, callback) { - var fullLog, fullScript; - - fullLog = forever.logFilePath(options.logFile, options.uid); - fullScript = path.join(options.sourceDir, file); - - forever.stat(fullLog, fullScript, options.appendLog, function (err) { - if (err) { - forever.log.error('Cannot start forever'); - forever.log.error(err.message); - process.exit(-1); - } - - callback(); - }); -} - -// -// ### @private function updateConfig (updater) -// #### @updater {function} Function which updates the forever config -// Helper which runs the specified `updater` and then saves the forever -// config to `forever.config.get('root')`. -// -function updateConfig (updater) { - updater(); - forever.config.save(function (err) { - if (err) { - return forever.log.error('Error saving config: ' + err.message); - } - - cli.config(); - var configFile = path.join(forever.config.get('root'), 'config.json'); - forever.log.info('Forever config saved: ' + configFile.yellow); - }); -} +}; \ No newline at end of file diff --git a/lib/forever/monitor.js b/lib/forever/monitor.js index 82ffdc20..4034393c 100644 --- a/lib/forever/monitor.js +++ b/lib/forever/monitor.js @@ -106,12 +106,12 @@ var Monitor = exports.Monitor = function (script, options) { // If we should log stdout, open a file buffer if (this.outFile) { - this.stdout = fs.createWriteStream(this.outFile, { flags: 'a+', encoding: 'utf8', mode: 0666 }); + this.stdout = fs.createWriteStream(this.outFile, { flags: 'a+', encoding: 'utf8', mode: '0666' }); } // If we should log stderr, open a file buffer if (this.errFile) { - this.stderr = fs.createWriteStream(this.errFile, { flags: 'a+', encoding: 'utf8', mode: 0666 }); + this.stderr = fs.createWriteStream(this.errFile, { flags: 'a+', encoding: 'utf8', mode: '0666' }); } // @@ -138,15 +138,17 @@ util.inherits(Monitor, events.EventEmitter); // Start the process that this instance is configured for // Monitor.prototype.start = function (restart) { - var self = this; + var self = this, + child; if (this.running && !restart) { process.nextTick(function () { self.emit('error', new Error('Cannot start process that is already running.')); }); + return this; } - var child = this.trySpawn(); + child = this.trySpawn(); if (!child) { process.nextTick(function () { self.emit('error', new Error('Target script does not exist: ' + self.options[0])); @@ -163,8 +165,8 @@ Monitor.prototype.start = function (restart) { }); // Hook all stream data and process it - function listenTo (stream) { - function ldata (data) { + function listenTo(stream) { + function ldata(data) { if (!self.silent && !self[stream]) { // // If we haven't been silenced, and we don't have a file stream @@ -273,7 +275,8 @@ Monitor.prototype.trySpawn = function () { // this `Monitor` instance and it's associated child process. // Monitor.prototype.__defineGetter__('data', function () { - var self = this; + var self = this, + childData; if (!this.running) { // @@ -283,7 +286,7 @@ Monitor.prototype.__defineGetter__('data', function () { return {}; } - var childData = { + childData = { ctime: this.ctime, command: this.command, file: this.options[0], @@ -438,7 +441,7 @@ Monitor.prototype._getEnv = function () { var self = this, merged = {}; - function addKey (key, source) { + function addKey(key, source) { merged[key] = source[key]; }