Spaces:
Runtime error
Runtime error
| const Dispatcher = require('./dispatcher') | |
| const { | |
| ClientDestroyedError, | |
| ClientClosedError, | |
| InvalidArgumentError | |
| } = require('./core/errors') | |
| const { kDestroy, kClose, kDispatch, kInterceptors } = require('./core/symbols') | |
| const kDestroyed = Symbol('destroyed') | |
| const kClosed = Symbol('closed') | |
| const kOnDestroyed = Symbol('onDestroyed') | |
| const kOnClosed = Symbol('onClosed') | |
| const kInterceptedDispatch = Symbol('Intercepted Dispatch') | |
| class DispatcherBase extends Dispatcher { | |
| constructor () { | |
| super() | |
| this[kDestroyed] = false | |
| this[kOnDestroyed] = null | |
| this[kClosed] = false | |
| this[kOnClosed] = [] | |
| } | |
| get destroyed () { | |
| return this[kDestroyed] | |
| } | |
| get closed () { | |
| return this[kClosed] | |
| } | |
| get interceptors () { | |
| return this[kInterceptors] | |
| } | |
| set interceptors (newInterceptors) { | |
| if (newInterceptors) { | |
| for (let i = newInterceptors.length - 1; i >= 0; i--) { | |
| const interceptor = this[kInterceptors][i] | |
| if (typeof interceptor !== 'function') { | |
| throw new InvalidArgumentError('interceptor must be an function') | |
| } | |
| } | |
| } | |
| this[kInterceptors] = newInterceptors | |
| } | |
| close (callback) { | |
| if (callback === undefined) { | |
| return new Promise((resolve, reject) => { | |
| this.close((err, data) => { | |
| return err ? reject(err) : resolve(data) | |
| }) | |
| }) | |
| } | |
| if (typeof callback !== 'function') { | |
| throw new InvalidArgumentError('invalid callback') | |
| } | |
| if (this[kDestroyed]) { | |
| queueMicrotask(() => callback(new ClientDestroyedError(), null)) | |
| return | |
| } | |
| if (this[kClosed]) { | |
| if (this[kOnClosed]) { | |
| this[kOnClosed].push(callback) | |
| } else { | |
| queueMicrotask(() => callback(null, null)) | |
| } | |
| return | |
| } | |
| this[kClosed] = true | |
| this[kOnClosed].push(callback) | |
| const onClosed = () => { | |
| const callbacks = this[kOnClosed] | |
| this[kOnClosed] = null | |
| for (let i = 0; i < callbacks.length; i++) { | |
| callbacks[i](null, null) | |
| } | |
| } | |
| // Should not error. | |
| this[kClose]() | |
| .then(() => this.destroy()) | |
| .then(() => { | |
| queueMicrotask(onClosed) | |
| }) | |
| } | |
| destroy (err, callback) { | |
| if (typeof err === 'function') { | |
| callback = err | |
| err = null | |
| } | |
| if (callback === undefined) { | |
| return new Promise((resolve, reject) => { | |
| this.destroy(err, (err, data) => { | |
| return err ? /* istanbul ignore next: should never error */ reject(err) : resolve(data) | |
| }) | |
| }) | |
| } | |
| if (typeof callback !== 'function') { | |
| throw new InvalidArgumentError('invalid callback') | |
| } | |
| if (this[kDestroyed]) { | |
| if (this[kOnDestroyed]) { | |
| this[kOnDestroyed].push(callback) | |
| } else { | |
| queueMicrotask(() => callback(null, null)) | |
| } | |
| return | |
| } | |
| if (!err) { | |
| err = new ClientDestroyedError() | |
| } | |
| this[kDestroyed] = true | |
| this[kOnDestroyed] = this[kOnDestroyed] || [] | |
| this[kOnDestroyed].push(callback) | |
| const onDestroyed = () => { | |
| const callbacks = this[kOnDestroyed] | |
| this[kOnDestroyed] = null | |
| for (let i = 0; i < callbacks.length; i++) { | |
| callbacks[i](null, null) | |
| } | |
| } | |
| // Should not error. | |
| this[kDestroy](err).then(() => { | |
| queueMicrotask(onDestroyed) | |
| }) | |
| } | |
| [kInterceptedDispatch] (opts, handler) { | |
| if (!this[kInterceptors] || this[kInterceptors].length === 0) { | |
| this[kInterceptedDispatch] = this[kDispatch] | |
| return this[kDispatch](opts, handler) | |
| } | |
| let dispatch = this[kDispatch].bind(this) | |
| for (let i = this[kInterceptors].length - 1; i >= 0; i--) { | |
| dispatch = this[kInterceptors][i](dispatch) | |
| } | |
| this[kInterceptedDispatch] = dispatch | |
| return dispatch(opts, handler) | |
| } | |
| dispatch (opts, handler) { | |
| if (!handler || typeof handler !== 'object') { | |
| throw new InvalidArgumentError('handler must be an object') | |
| } | |
| try { | |
| if (!opts || typeof opts !== 'object') { | |
| throw new InvalidArgumentError('opts must be an object.') | |
| } | |
| if (this[kDestroyed] || this[kOnDestroyed]) { | |
| throw new ClientDestroyedError() | |
| } | |
| if (this[kClosed]) { | |
| throw new ClientClosedError() | |
| } | |
| return this[kInterceptedDispatch](opts, handler) | |
| } catch (err) { | |
| if (typeof handler.onError !== 'function') { | |
| throw new InvalidArgumentError('invalid onError method') | |
| } | |
| handler.onError(err) | |
| return false | |
| } | |
| } | |
| } | |
| module.exports = DispatcherBase | |