diff options
Diffstat (limited to 'node_modules/gulp-util/lib/PluginError.js')
-rw-r--r-- | node_modules/gulp-util/lib/PluginError.js | 114 |
1 files changed, 90 insertions, 24 deletions
diff --git a/node_modules/gulp-util/lib/PluginError.js b/node_modules/gulp-util/lib/PluginError.js index 6640346ed..d60159ab1 100644 --- a/node_modules/gulp-util/lib/PluginError.js +++ b/node_modules/gulp-util/lib/PluginError.js @@ -1,22 +1,32 @@ var util = require('util'); -var colors = require('./colors'); +var arrayDiffer = require('array-differ'); +var arrayUniq = require('array-uniq'); +var chalk = require('chalk'); +var objectAssign = require('object-assign'); + +var nonEnumberableProperties = ['name', 'message', 'stack']; +var propertiesNotToDisplay = nonEnumberableProperties.concat(['plugin', 'showStack', 'showProperties', '__safety', '_stack']); // wow what a clusterfuck var parseOptions = function(plugin, message, opt) { - if (!opt) opt = {}; + opt = opt || {}; if (typeof plugin === 'object') { opt = plugin; - } else if (message instanceof Error) { - opt.error = message; - opt.plugin = plugin; - } else if (typeof message === 'object') { - opt = message; - opt.plugin = plugin; - } else if (typeof opt === 'object') { + } else { + if (message instanceof Error) { + opt.error = message; + } else if (typeof message === 'object') { + opt = message; + } else { + opt.message = message; + } opt.plugin = plugin; - opt.message = message; } - return opt; + + return objectAssign({ + showStack: false, + showProperties: true + }, opt); }; function PluginError(plugin, message, opt) { @@ -25,19 +35,19 @@ function PluginError(plugin, message, opt) { Error.call(this); var options = parseOptions(plugin, message, opt); - - this.plugin = options.plugin; - this.showStack = options.showStack === true; - - var properties = ['name', 'message', 'fileName', 'lineNumber', 'stack']; + var self = this; // if options has an error, grab details from it if (options.error) { - properties.forEach(function(prop) { - if (prop in options.error) this[prop] = options.error[prop]; - }, this); + // These properties are not enumerable, so we have to add them explicitly. + arrayUniq(Object.keys(options.error).concat(nonEnumberableProperties)) + .forEach(function(prop) { + self[prop] = options.error[prop]; + }); } + var properties = ['name', 'message', 'fileName', 'lineNumber', 'stack', 'showStack', 'showProperties', 'plugin']; + // options object can override properties.forEach(function(prop) { if (prop in options) this[prop] = options[prop]; @@ -46,8 +56,18 @@ function PluginError(plugin, message, opt) { // defaults if (!this.name) this.name = 'Error'; - // TODO: figure out why this explodes mocha - if (!this.stack) Error.captureStackTrace(this, arguments.callee || this.constructor); + if (!this.stack) { + // Error.captureStackTrace appends a stack property which relies on the toString method of the object it is applied to. + // Since we are using our own toString method which controls when to display the stack trace if we don't go through this + // safety object, then we'll get stack overflow problems. + var safety = { + toString: function() { + return this._messageWithDetails() + '\nStack:'; + }.bind(this) + }; + Error.captureStackTrace(safety, arguments.callee || this.constructor); + this.__safety = safety; + } if (!this.plugin) throw new Error('Missing plugin name'); if (!this.message) throw new Error('Missing error message'); @@ -55,10 +75,56 @@ function PluginError(plugin, message, opt) { util.inherits(PluginError, Error); +PluginError.prototype._messageWithDetails = function() { + var messageWithDetails = 'Message:\n ' + this.message; + var details = this._messageDetails(); + + if (details !== '') { + messageWithDetails += '\n' + details; + } + + return messageWithDetails; +}; + +PluginError.prototype._messageDetails = function() { + if (!this.showProperties) { + return ''; + } + + var properties = arrayDiffer(Object.keys(this), propertiesNotToDisplay); + + if (properties.length === 0) { + return ''; + } + + var self = this; + properties = properties.map(function stringifyProperty(prop) { + return ' ' + prop + ': ' + self[prop]; + }); + + return 'Details:\n' + properties.join('\n'); +}; + PluginError.prototype.toString = function () { - var sig = this.name+' in plugin \''+colors.cyan(this.plugin)+'\''; - var msg = this.showStack ? (this._stack || this.stack) : this.message; - return sig+'\n'+msg; + var sig = chalk.red(this.name) + ' in plugin \'' + chalk.cyan(this.plugin) + '\''; + var detailsWithStack = function(stack) { + return this._messageWithDetails() + '\nStack:\n' + stack; + }.bind(this); + + var msg; + if (this.showStack) { + if (this.__safety) { // There is no wrapped error, use the stack captured in the PluginError ctor + msg = this.__safety.stack; + } else if (this._stack) { + msg = detailsWithStack(this._stack); + } else { // Stack from wrapped error + msg = detailsWithStack(this.stack); + } + } else { + msg = this._messageWithDetails(); + } + + return sig + '\n' + msg; }; module.exports = PluginError; |