2021-12-07 13:18:08 -05:00

118 lines
2.6 KiB
JavaScript

const { inherits } = require('util')
function Reporter (options) {
this._reporterState = {
obj: null,
path: [],
options: options || {},
errors: []
}
}
Reporter.prototype.isError = function isError (obj) {
return obj instanceof ReporterError
}
Reporter.prototype.save = function save () {
const state = this._reporterState
return { obj: state.obj, pathLen: state.path.length }
}
Reporter.prototype.restore = function restore (data) {
const state = this._reporterState
state.obj = data.obj
state.path = state.path.slice(0, data.pathLen)
}
Reporter.prototype.enterKey = function enterKey (key) {
return this._reporterState.path.push(key)
}
Reporter.prototype.exitKey = function exitKey (index) {
const state = this._reporterState
state.path = state.path.slice(0, index - 1)
}
Reporter.prototype.leaveKey = function leaveKey (index, key, value) {
const state = this._reporterState
this.exitKey(index)
if (state.obj !== null) { state.obj[key] = value }
}
Reporter.prototype.path = function path () {
return this._reporterState.path.join('/')
}
Reporter.prototype.enterObject = function enterObject () {
const state = this._reporterState
const prev = state.obj
state.obj = {}
return prev
}
Reporter.prototype.leaveObject = function leaveObject (prev) {
const state = this._reporterState
const now = state.obj
state.obj = prev
return now
}
Reporter.prototype.error = function error (msg) {
let err
const state = this._reporterState
const inherited = msg instanceof ReporterError
if (inherited) {
err = msg
} else {
err = new ReporterError(state.path.map(function (elem) {
return `[${JSON.stringify(elem)}]`
}).join(''), msg.message || msg, msg.stack)
}
if (!state.options.partial) { throw err }
if (!inherited) { state.errors.push(err) }
return err
}
Reporter.prototype.wrapResult = function wrapResult (result) {
const state = this._reporterState
if (!state.options.partial) { return result }
return {
result: this.isError(result) ? null : result,
errors: state.errors
}
}
function ReporterError (path, msg) {
this.path = path
this.rethrow(msg)
}
inherits(ReporterError, Error)
ReporterError.prototype.rethrow = function rethrow (msg) {
this.message = `${msg} at: ${this.path || '(shallow)'}`
if (Error.captureStackTrace) { Error.captureStackTrace(this, ReporterError) }
if (!this.stack) {
try {
// IE only adds stack when thrown
throw new Error(this.message)
} catch (e) {
this.stack = e.stack
}
}
return this
}
exports.Reporter = Reporter