82f2b76e25
We now use webpack instead of SystemJS, effectively bundling modules into one file (plus commons chunks) for every entry point. This results in a much smaller extension size (almost half). Furthermore we use yarn/npm even for extension run-time dependencies. This relieves us from manually vendoring and building dependencies. It's also easier to understand for new developers familiar with node.
131 lines
3.7 KiB
JavaScript
131 lines
3.7 KiB
JavaScript
var util = require('util');
|
|
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) {
|
|
opt = opt || {};
|
|
if (typeof plugin === 'object') {
|
|
opt = plugin;
|
|
} else {
|
|
if (message instanceof Error) {
|
|
opt.error = message;
|
|
} else if (typeof message === 'object') {
|
|
opt = message;
|
|
} else {
|
|
opt.message = message;
|
|
}
|
|
opt.plugin = plugin;
|
|
}
|
|
|
|
return objectAssign({
|
|
showStack: false,
|
|
showProperties: true
|
|
}, opt);
|
|
};
|
|
|
|
function PluginError(plugin, message, opt) {
|
|
if (!(this instanceof PluginError)) throw new Error('Call PluginError using new');
|
|
|
|
Error.call(this);
|
|
|
|
var options = parseOptions(plugin, message, opt);
|
|
var self = this;
|
|
|
|
// if options has an error, grab details from it
|
|
if (options.error) {
|
|
// 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];
|
|
}, this);
|
|
|
|
// defaults
|
|
if (!this.name) this.name = 'Error';
|
|
|
|
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');
|
|
}
|
|
|
|
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 = 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;
|