diff options
Diffstat (limited to 'node_modules/pretty-error/src/PrettyError.coffee')
| -rw-r--r-- | node_modules/pretty-error/src/PrettyError.coffee | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/node_modules/pretty-error/src/PrettyError.coffee b/node_modules/pretty-error/src/PrettyError.coffee new file mode 100644 index 00000000..dc44943a --- /dev/null +++ b/node_modules/pretty-error/src/PrettyError.coffee @@ -0,0 +1,312 @@ +{object, array} = require 'utila' +defaultStyle = require './defaultStyle' +ParsedError = require './ParsedError' +nodePaths = require './nodePaths' +RenderKid = require 'renderkid' + +instance = null + +module.exports = class PrettyError + self = @ + + @_filters: + 'module.exports': (item) -> + return unless item.what? + item.what = item.what.replace /\.module\.exports\./g, ' - ' + return + + @_getDefaultStyle: -> + defaultStyle() + + @start: -> + unless instance? + instance = new self + instance.start() + + instance + + @stop: -> + instance?.stop() + + constructor: -> + @_useColors = yes + @_maxItems = 50 + @_packagesToSkip = [] + @_pathsToSkip = [] + @_skipCallbacks = [] + @_filterCallbacks = [] + @_parsedErrorFilters = [] + @_aliases = [] + @_renderer = new RenderKid + @_style = self._getDefaultStyle() + @_renderer.style @_style + + start: -> + @_oldPrepareStackTrace = Error.prepareStackTrace + + prepeare = @_oldPrepareStackTrace or (exc, frames) -> + result = exc.toString() + frames = frames.map (frame) -> " at #{frame.toString()}" + result + "\n" + frames.join "\n" + + # https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi + Error.prepareStackTrace = (exc, trace) => + stack = prepeare.apply(null, arguments) + @render {stack, message: exc.toString().replace /^.*: /, ''}, no + + @ + + stop: -> + Error.prepareStackTrace = @_oldPrepareStackTrace + @_oldPrepareStackTrace = null + + config: (c) -> + if c.skipPackages? + if c.skipPackages is no + @unskipAllPackages() + else + @skipPackage.apply @, c.skipPackages + + if c.skipPaths? + if c.skipPaths is no + @unskipAllPaths() + else + @skipPath.apply @, c.skipPaths + + if c.skip? + if c.skip is no + @unskipAll() + else + @skip.apply @, c.skip + + if c.maxItems? + @setMaxItems c.maxItems + + if c.skipNodeFiles is yes + @skipNodeFiles() + else if c.skipNodeFiles is no + @unskipNodeFiles() + + if c.filters? + if c.filters is no + @removeAllFilters() + else + @filter.apply @, c.filters + + if c.parsedErrorFilters? + if c.parsedErrorFilters is no + @removeAllParsedErrorFilters() + else + @filterParsedError.apply @, c.parsedErrorFilters + + if c.aliases? + if object.isBareObject c.aliases + @alias path, alias for path, alias of c.aliases + else if c.aliases is no + @removeAllAliases() + + @ + + withoutColors: -> + @_useColors = false + @ + + withColors: -> + @_useColors = true + @ + + skipPackage: (packages...) -> + @_packagesToSkip.push String pkg for pkg in packages + @ + + unskipPackage: (packages...) -> + array.pluckOneItem(@_packagesToSkip, pkg) for pkg in packages + @ + + unskipAllPackages: -> + @_packagesToSkip.length = 0 + @ + + skipPath: (paths...) -> + @_pathsToSkip.push path for path in paths + @ + + unskipPath: (paths...) -> + array.pluckOneItem(@_pathsToSkip, path) for path in paths + @ + + unskipAllPaths: -> + @_pathsToSkip.length = 0 + @ + + skip: (callbacks...) -> + @_skipCallbacks.push cb for cb in callbacks + @ + + unskip: (callbacks...) -> + array.pluckOneItem(@_skipCallbacks, cb) for cb in callbacks + @ + + unskipAll: -> + @_skipCallbacks.length = 0 + @ + + skipNodeFiles: -> + @skipPath.apply @, nodePaths + + unskipNodeFiles: -> + @unskipPath.apply @, nodePaths + + filter: (callbacks...) -> + @_filterCallbacks.push cb for cb in callbacks + @ + + removeFilter: (callbacks...) -> + array.pluckOneItem(@_filterCallbacks, cb) for cb in callbacks + @ + + removeAllFilters: -> + @_filterCallbacks.length = 0 + @ + + filterParsedError: (callbacks...) -> + @_parsedErrorFilters.push cb for cb in callbacks + @ + + removeParsedErrorFilter: (callbacks...) -> + array.pluckOneItem(@_parsedErrorFilters, cb) for cb in callbacks + @ + + removeAllParsedErrorFilters: -> + @_parsedErrorFilters.length = 0 + @ + + setMaxItems: (maxItems = 50) -> + if maxItems is 0 then maxItems = 50 + @_maxItems = maxItems|0 + @ + + alias: (stringOrRx, alias) -> + @_aliases.push {stringOrRx, alias} + @ + + removeAlias: (stringOrRx) -> + array.pluckByCallback @_aliases, (pair) -> + pair.stringOrRx is stringOrRx + + @ + + removeAllAliases: -> + @_aliases.length = 0 + @ + + _getStyle: -> + @_style + + appendStyle: (toAppend) -> + object.appendOnto @_style, toAppend + @_renderer.style toAppend + @ + + _getRenderer: -> + @_renderer + + render: (e, logIt = no, useColors = @_useColors) -> + obj = @getObject e + rendered = @_renderer.render(obj, useColors) + console.error rendered if logIt is yes + rendered + + getObject: (e) -> + unless e instanceof ParsedError + e = new ParsedError e + + @_applyParsedErrorFiltersOn e + + header = + title: do -> + ret = {} + + # some errors are thrown to display other errors. + # we call them wrappers here. + if e.wrapper isnt '' + ret.wrapper = "#{e.wrapper}" + + ret.kind = e.kind + ret + + colon: ':' + + message: String(e.message).trim() + + traceItems = [] + count = -1 + + for item, i in e.trace + continue unless item? + continue if @_skipOrFilter(item, i) is yes + + count++ + + break if count > @_maxItems + + if typeof item is 'string' + traceItems.push item: custom: item + continue + + traceItems.push do -> + markupItem = item: + header: + pointer: do -> + return '' unless item.file? + + file: item.file + colon: ':' + line: item.line + + footer: do -> + foooter = addr: item.shortenedAddr + if item.extra? then foooter.extra = item.extra + foooter + + markupItem.item.header.what = item.what if typeof item.what is 'string' and item.what.trim().length > 0 + markupItem + + + obj = 'pretty-error': + header: header + + if traceItems.length > 0 + obj['pretty-error'].trace = traceItems + + obj + + _skipOrFilter: (item, itemNumber) -> + if typeof item is 'object' + return yes if item.modName in @_packagesToSkip + return yes if item.path in @_pathsToSkip + + for modName in item.packages + return yes if modName in @_packagesToSkip + + if typeof item.shortenedAddr is 'string' + for pair in @_aliases + item.shortenedAddr = item.shortenedAddr.replace pair.stringOrRx, pair.alias + + for cb in @_skipCallbacks + return yes if cb(item, itemNumber) is yes + + for cb in @_filterCallbacks + cb(item, itemNumber) + + return no + + _applyParsedErrorFiltersOn: (error) -> + for cb in @_parsedErrorFilters + cb error + + return + +for prop in ['renderer', 'style'] then do -> + methodName = '_get' + prop[0].toUpperCase() + prop.substr(1, prop.length) + PrettyError::__defineGetter__ prop, -> do @[methodName] |
