11cb0ef41Sopenharmony_ci'use strict'
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst Dispatcher = require('./dispatcher')
41cb0ef41Sopenharmony_ciconst {
51cb0ef41Sopenharmony_ci  ClientDestroyedError,
61cb0ef41Sopenharmony_ci  ClientClosedError,
71cb0ef41Sopenharmony_ci  InvalidArgumentError
81cb0ef41Sopenharmony_ci} = require('./core/errors')
91cb0ef41Sopenharmony_ciconst { kDestroy, kClose, kDispatch, kInterceptors } = require('./core/symbols')
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ciconst kDestroyed = Symbol('destroyed')
121cb0ef41Sopenharmony_ciconst kClosed = Symbol('closed')
131cb0ef41Sopenharmony_ciconst kOnDestroyed = Symbol('onDestroyed')
141cb0ef41Sopenharmony_ciconst kOnClosed = Symbol('onClosed')
151cb0ef41Sopenharmony_ciconst kInterceptedDispatch = Symbol('Intercepted Dispatch')
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ciclass DispatcherBase extends Dispatcher {
181cb0ef41Sopenharmony_ci  constructor () {
191cb0ef41Sopenharmony_ci    super()
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci    this[kDestroyed] = false
221cb0ef41Sopenharmony_ci    this[kOnDestroyed] = null
231cb0ef41Sopenharmony_ci    this[kClosed] = false
241cb0ef41Sopenharmony_ci    this[kOnClosed] = []
251cb0ef41Sopenharmony_ci  }
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci  get destroyed () {
281cb0ef41Sopenharmony_ci    return this[kDestroyed]
291cb0ef41Sopenharmony_ci  }
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  get closed () {
321cb0ef41Sopenharmony_ci    return this[kClosed]
331cb0ef41Sopenharmony_ci  }
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  get interceptors () {
361cb0ef41Sopenharmony_ci    return this[kInterceptors]
371cb0ef41Sopenharmony_ci  }
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  set interceptors (newInterceptors) {
401cb0ef41Sopenharmony_ci    if (newInterceptors) {
411cb0ef41Sopenharmony_ci      for (let i = newInterceptors.length - 1; i >= 0; i--) {
421cb0ef41Sopenharmony_ci        const interceptor = this[kInterceptors][i]
431cb0ef41Sopenharmony_ci        if (typeof interceptor !== 'function') {
441cb0ef41Sopenharmony_ci          throw new InvalidArgumentError('interceptor must be an function')
451cb0ef41Sopenharmony_ci        }
461cb0ef41Sopenharmony_ci      }
471cb0ef41Sopenharmony_ci    }
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci    this[kInterceptors] = newInterceptors
501cb0ef41Sopenharmony_ci  }
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  close (callback) {
531cb0ef41Sopenharmony_ci    if (callback === undefined) {
541cb0ef41Sopenharmony_ci      return new Promise((resolve, reject) => {
551cb0ef41Sopenharmony_ci        this.close((err, data) => {
561cb0ef41Sopenharmony_ci          return err ? reject(err) : resolve(data)
571cb0ef41Sopenharmony_ci        })
581cb0ef41Sopenharmony_ci      })
591cb0ef41Sopenharmony_ci    }
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci    if (typeof callback !== 'function') {
621cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('invalid callback')
631cb0ef41Sopenharmony_ci    }
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci    if (this[kDestroyed]) {
661cb0ef41Sopenharmony_ci      queueMicrotask(() => callback(new ClientDestroyedError(), null))
671cb0ef41Sopenharmony_ci      return
681cb0ef41Sopenharmony_ci    }
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci    if (this[kClosed]) {
711cb0ef41Sopenharmony_ci      if (this[kOnClosed]) {
721cb0ef41Sopenharmony_ci        this[kOnClosed].push(callback)
731cb0ef41Sopenharmony_ci      } else {
741cb0ef41Sopenharmony_ci        queueMicrotask(() => callback(null, null))
751cb0ef41Sopenharmony_ci      }
761cb0ef41Sopenharmony_ci      return
771cb0ef41Sopenharmony_ci    }
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci    this[kClosed] = true
801cb0ef41Sopenharmony_ci    this[kOnClosed].push(callback)
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci    const onClosed = () => {
831cb0ef41Sopenharmony_ci      const callbacks = this[kOnClosed]
841cb0ef41Sopenharmony_ci      this[kOnClosed] = null
851cb0ef41Sopenharmony_ci      for (let i = 0; i < callbacks.length; i++) {
861cb0ef41Sopenharmony_ci        callbacks[i](null, null)
871cb0ef41Sopenharmony_ci      }
881cb0ef41Sopenharmony_ci    }
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci    // Should not error.
911cb0ef41Sopenharmony_ci    this[kClose]()
921cb0ef41Sopenharmony_ci      .then(() => this.destroy())
931cb0ef41Sopenharmony_ci      .then(() => {
941cb0ef41Sopenharmony_ci        queueMicrotask(onClosed)
951cb0ef41Sopenharmony_ci      })
961cb0ef41Sopenharmony_ci  }
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  destroy (err, callback) {
991cb0ef41Sopenharmony_ci    if (typeof err === 'function') {
1001cb0ef41Sopenharmony_ci      callback = err
1011cb0ef41Sopenharmony_ci      err = null
1021cb0ef41Sopenharmony_ci    }
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci    if (callback === undefined) {
1051cb0ef41Sopenharmony_ci      return new Promise((resolve, reject) => {
1061cb0ef41Sopenharmony_ci        this.destroy(err, (err, data) => {
1071cb0ef41Sopenharmony_ci          return err ? /* istanbul ignore next: should never error */ reject(err) : resolve(data)
1081cb0ef41Sopenharmony_ci        })
1091cb0ef41Sopenharmony_ci      })
1101cb0ef41Sopenharmony_ci    }
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci    if (typeof callback !== 'function') {
1131cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('invalid callback')
1141cb0ef41Sopenharmony_ci    }
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci    if (this[kDestroyed]) {
1171cb0ef41Sopenharmony_ci      if (this[kOnDestroyed]) {
1181cb0ef41Sopenharmony_ci        this[kOnDestroyed].push(callback)
1191cb0ef41Sopenharmony_ci      } else {
1201cb0ef41Sopenharmony_ci        queueMicrotask(() => callback(null, null))
1211cb0ef41Sopenharmony_ci      }
1221cb0ef41Sopenharmony_ci      return
1231cb0ef41Sopenharmony_ci    }
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci    if (!err) {
1261cb0ef41Sopenharmony_ci      err = new ClientDestroyedError()
1271cb0ef41Sopenharmony_ci    }
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci    this[kDestroyed] = true
1301cb0ef41Sopenharmony_ci    this[kOnDestroyed] = this[kOnDestroyed] || []
1311cb0ef41Sopenharmony_ci    this[kOnDestroyed].push(callback)
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci    const onDestroyed = () => {
1341cb0ef41Sopenharmony_ci      const callbacks = this[kOnDestroyed]
1351cb0ef41Sopenharmony_ci      this[kOnDestroyed] = null
1361cb0ef41Sopenharmony_ci      for (let i = 0; i < callbacks.length; i++) {
1371cb0ef41Sopenharmony_ci        callbacks[i](null, null)
1381cb0ef41Sopenharmony_ci      }
1391cb0ef41Sopenharmony_ci    }
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci    // Should not error.
1421cb0ef41Sopenharmony_ci    this[kDestroy](err).then(() => {
1431cb0ef41Sopenharmony_ci      queueMicrotask(onDestroyed)
1441cb0ef41Sopenharmony_ci    })
1451cb0ef41Sopenharmony_ci  }
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci  [kInterceptedDispatch] (opts, handler) {
1481cb0ef41Sopenharmony_ci    if (!this[kInterceptors] || this[kInterceptors].length === 0) {
1491cb0ef41Sopenharmony_ci      this[kInterceptedDispatch] = this[kDispatch]
1501cb0ef41Sopenharmony_ci      return this[kDispatch](opts, handler)
1511cb0ef41Sopenharmony_ci    }
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci    let dispatch = this[kDispatch].bind(this)
1541cb0ef41Sopenharmony_ci    for (let i = this[kInterceptors].length - 1; i >= 0; i--) {
1551cb0ef41Sopenharmony_ci      dispatch = this[kInterceptors][i](dispatch)
1561cb0ef41Sopenharmony_ci    }
1571cb0ef41Sopenharmony_ci    this[kInterceptedDispatch] = dispatch
1581cb0ef41Sopenharmony_ci    return dispatch(opts, handler)
1591cb0ef41Sopenharmony_ci  }
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  dispatch (opts, handler) {
1621cb0ef41Sopenharmony_ci    if (!handler || typeof handler !== 'object') {
1631cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('handler must be an object')
1641cb0ef41Sopenharmony_ci    }
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci    try {
1671cb0ef41Sopenharmony_ci      if (!opts || typeof opts !== 'object') {
1681cb0ef41Sopenharmony_ci        throw new InvalidArgumentError('opts must be an object.')
1691cb0ef41Sopenharmony_ci      }
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci      if (this[kDestroyed] || this[kOnDestroyed]) {
1721cb0ef41Sopenharmony_ci        throw new ClientDestroyedError()
1731cb0ef41Sopenharmony_ci      }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci      if (this[kClosed]) {
1761cb0ef41Sopenharmony_ci        throw new ClientClosedError()
1771cb0ef41Sopenharmony_ci      }
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci      return this[kInterceptedDispatch](opts, handler)
1801cb0ef41Sopenharmony_ci    } catch (err) {
1811cb0ef41Sopenharmony_ci      if (typeof handler.onError !== 'function') {
1821cb0ef41Sopenharmony_ci        throw new InvalidArgumentError('invalid onError method')
1831cb0ef41Sopenharmony_ci      }
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci      handler.onError(err)
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci      return false
1881cb0ef41Sopenharmony_ci    }
1891cb0ef41Sopenharmony_ci  }
1901cb0ef41Sopenharmony_ci}
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_cimodule.exports = DispatcherBase
193