util.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. 'use strict'
  2. const bufferModule = require('buffer')
  3. const { format, inspect } = require('./util/inspect')
  4. const {
  5. codes: { ERR_INVALID_ARG_TYPE }
  6. } = require('./errors')
  7. const { kResistStopPropagation, AggregateError, SymbolDispose } = require('./primordials')
  8. const AbortSignal = globalThis.AbortSignal || require('abort-controller').AbortSignal
  9. const AbortController = globalThis.AbortController || require('abort-controller').AbortController
  10. const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
  11. const Blob = globalThis.Blob || bufferModule.Blob
  12. /* eslint-disable indent */
  13. const isBlob =
  14. typeof Blob !== 'undefined'
  15. ? function isBlob(b) {
  16. // eslint-disable-next-line indent
  17. return b instanceof Blob
  18. }
  19. : function isBlob(b) {
  20. return false
  21. }
  22. /* eslint-enable indent */
  23. const validateAbortSignal = (signal, name) => {
  24. if (signal !== undefined && (signal === null || typeof signal !== 'object' || !('aborted' in signal))) {
  25. throw new ERR_INVALID_ARG_TYPE(name, 'AbortSignal', signal)
  26. }
  27. }
  28. const validateFunction = (value, name) => {
  29. if (typeof value !== 'function') {
  30. throw new ERR_INVALID_ARG_TYPE(name, 'Function', value)
  31. }
  32. }
  33. module.exports = {
  34. AggregateError,
  35. kEmptyObject: Object.freeze({}),
  36. once(callback) {
  37. let called = false
  38. return function (...args) {
  39. if (called) {
  40. return
  41. }
  42. called = true
  43. callback.apply(this, args)
  44. }
  45. },
  46. createDeferredPromise: function () {
  47. let resolve
  48. let reject
  49. // eslint-disable-next-line promise/param-names
  50. const promise = new Promise((res, rej) => {
  51. resolve = res
  52. reject = rej
  53. })
  54. return {
  55. promise,
  56. resolve,
  57. reject
  58. }
  59. },
  60. promisify(fn) {
  61. return new Promise((resolve, reject) => {
  62. fn((err, ...args) => {
  63. if (err) {
  64. return reject(err)
  65. }
  66. return resolve(...args)
  67. })
  68. })
  69. },
  70. debuglog() {
  71. return function () {}
  72. },
  73. format,
  74. inspect,
  75. types: {
  76. isAsyncFunction(fn) {
  77. return fn instanceof AsyncFunction
  78. },
  79. isArrayBufferView(arr) {
  80. return ArrayBuffer.isView(arr)
  81. }
  82. },
  83. isBlob,
  84. deprecate(fn, message) {
  85. return fn
  86. },
  87. addAbortListener:
  88. require('events').addAbortListener ||
  89. function addAbortListener(signal, listener) {
  90. if (signal === undefined) {
  91. throw new ERR_INVALID_ARG_TYPE('signal', 'AbortSignal', signal)
  92. }
  93. validateAbortSignal(signal, 'signal')
  94. validateFunction(listener, 'listener')
  95. let removeEventListener
  96. if (signal.aborted) {
  97. queueMicrotask(() => listener())
  98. } else {
  99. signal.addEventListener('abort', listener, {
  100. __proto__: null,
  101. once: true,
  102. [kResistStopPropagation]: true
  103. })
  104. removeEventListener = () => {
  105. signal.removeEventListener('abort', listener)
  106. }
  107. }
  108. return {
  109. __proto__: null,
  110. [SymbolDispose]() {
  111. var _removeEventListener
  112. ;(_removeEventListener = removeEventListener) === null || _removeEventListener === undefined
  113. ? undefined
  114. : _removeEventListener()
  115. }
  116. }
  117. },
  118. AbortSignalAny:
  119. AbortSignal.any ||
  120. function AbortSignalAny(signals) {
  121. // Fast path if there is only one signal.
  122. if (signals.length === 1) {
  123. return signals[0]
  124. }
  125. const ac = new AbortController()
  126. const abort = () => ac.abort()
  127. signals.forEach((signal) => {
  128. validateAbortSignal(signal, 'signals')
  129. signal.addEventListener('abort', abort, {
  130. once: true
  131. })
  132. })
  133. ac.signal.addEventListener(
  134. 'abort',
  135. () => {
  136. signals.forEach((signal) => signal.removeEventListener('abort', abort))
  137. },
  138. {
  139. once: true
  140. }
  141. )
  142. return ac.signal
  143. }
  144. }
  145. module.exports.promisify.custom = Symbol.for('nodejs.util.promisify.custom')