aboutsummaryrefslogtreecommitdiff
path: root/node_modules/pretty-error/src/PrettyError.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/pretty-error/src/PrettyError.coffee')
-rw-r--r--node_modules/pretty-error/src/PrettyError.coffee312
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]