chushihua
This commit is contained in:
+346
@@ -0,0 +1,346 @@
|
||||
isPlainObject = require 'lodash/isPlainObject'
|
||||
defaultStyle = require './defaultStyle'
|
||||
ParsedError = require './ParsedError'
|
||||
nodePaths = require './nodePaths'
|
||||
RenderKid = require 'renderkid'
|
||||
merge = require 'lodash/merge'
|
||||
|
||||
arrayUtils =
|
||||
pluckByCallback: (a, cb) ->
|
||||
return a if a.length < 1
|
||||
removed = 0
|
||||
|
||||
for value, index in a
|
||||
if cb value, index
|
||||
removed++
|
||||
continue
|
||||
|
||||
if removed isnt 0
|
||||
a[index - removed] = a[index]
|
||||
|
||||
if removed > 0
|
||||
a.length = a.length - removed
|
||||
|
||||
a
|
||||
|
||||
pluckOneItem: (a, item) ->
|
||||
return a if a.length < 1
|
||||
reached = no
|
||||
|
||||
for value, index in a
|
||||
if not reached
|
||||
if value is item
|
||||
reached = yes
|
||||
continue
|
||||
else
|
||||
a[index - 1] = a[index]
|
||||
|
||||
a.length = a.length - 1 if reached
|
||||
a
|
||||
|
||||
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 isPlainObject 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...) ->
|
||||
arrayUtils.pluckOneItem(@_packagesToSkip, pkg) for pkg in packages
|
||||
@
|
||||
|
||||
unskipAllPackages: ->
|
||||
@_packagesToSkip.length = 0
|
||||
@
|
||||
|
||||
skipPath: (paths...) ->
|
||||
@_pathsToSkip.push path for path in paths
|
||||
@
|
||||
|
||||
unskipPath: (paths...) ->
|
||||
arrayUtils.pluckOneItem(@_pathsToSkip, path) for path in paths
|
||||
@
|
||||
|
||||
unskipAllPaths: ->
|
||||
@_pathsToSkip.length = 0
|
||||
@
|
||||
|
||||
skip: (callbacks...) ->
|
||||
@_skipCallbacks.push cb for cb in callbacks
|
||||
@
|
||||
|
||||
unskip: (callbacks...) ->
|
||||
arrayUtils.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...) ->
|
||||
arrayUtils.pluckOneItem(@_filterCallbacks, cb) for cb in callbacks
|
||||
@
|
||||
|
||||
removeAllFilters: ->
|
||||
@_filterCallbacks.length = 0
|
||||
@
|
||||
|
||||
filterParsedError: (callbacks...) ->
|
||||
@_parsedErrorFilters.push cb for cb in callbacks
|
||||
@
|
||||
|
||||
removeParsedErrorFilter: (callbacks...) ->
|
||||
arrayUtils.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) ->
|
||||
arrayUtils.pluckByCallback @_aliases, (pair) ->
|
||||
pair.stringOrRx is stringOrRx
|
||||
|
||||
@
|
||||
|
||||
removeAllAliases: ->
|
||||
@_aliases.length = 0
|
||||
@
|
||||
|
||||
_getStyle: ->
|
||||
@_style
|
||||
|
||||
appendStyle: (toAppend) ->
|
||||
merge @_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]
|
||||
Reference in New Issue
Block a user