function tryCatch(fn, source) {
  try {
    return fn()
  }
  catch (err) {
    err.originalMessage = err.message
    err.message = formatMessage(err.message, source)

    // if source seems interesting, enhance error
    if (typeof source === "object") {
      // add a stack item if something interesting available
      if ((source.input && source.input.file) || source.start) {
        var stack = err.stack.split(SPLITTER)
        var firstStackItem = stack.shift()
        stack.unshift(sourceString(source))
        stack.unshift(firstStackItem)
        err.stack = stack.join(SPLITTER)
      }

      if (source.input && source.input.file) {
        err.fileName = source.input.file
      }
      if (source.start) {
        err.lineNumber = source.start.line
        err.columnNumber = source.start.column
      }
    }

    throw err
  }
}
Do something and throw an error with enhanced exception (from given source)

@param {Function} fn     [description]
@param {[type]}   source [description]