| 'use strict'; | 
|   | 
| const inherits = require('inherits'); | 
|   | 
| function Reporter(options) { | 
|   this._reporterState = { | 
|     obj: null, | 
|     path: [], | 
|     options: options || {}, | 
|     errors: [] | 
|   }; | 
| } | 
| exports.Reporter = Reporter; | 
|   | 
| 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; | 
| }; |