@depup/msw 2.13.2-depup.0 → 2.15.0-depup.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/README.md +9 -12
  2. package/changes.json +14 -26
  3. package/cli/init.js +1 -1
  4. package/lib/browser/index.js +547 -177
  5. package/lib/browser/index.js.map +1 -1
  6. package/lib/browser/index.mjs +547 -177
  7. package/lib/browser/index.mjs.map +1 -1
  8. package/lib/core/{HttpResponse-DlRR1D-f.d.mts → HttpResponse-BE_Y2Ak9.d.mts} +52 -1
  9. package/lib/core/{HttpResponse-CksOMVAa.d.ts → HttpResponse-DL-P1EeG.d.ts} +52 -1
  10. package/lib/core/HttpResponse.d.mts +1 -1
  11. package/lib/core/HttpResponse.d.ts +1 -1
  12. package/lib/core/HttpResponse.js +2 -2
  13. package/lib/core/HttpResponse.js.map +1 -1
  14. package/lib/core/HttpResponse.mjs +2 -2
  15. package/lib/core/HttpResponse.mjs.map +1 -1
  16. package/lib/core/experimental/compat.d.mts +2 -2
  17. package/lib/core/experimental/compat.d.ts +2 -2
  18. package/lib/core/experimental/compat.js +1 -0
  19. package/lib/core/experimental/compat.js.map +1 -1
  20. package/lib/core/experimental/compat.mjs +1 -0
  21. package/lib/core/experimental/compat.mjs.map +1 -1
  22. package/lib/core/experimental/define-network.d.mts +2 -2
  23. package/lib/core/experimental/define-network.d.ts +2 -2
  24. package/lib/core/experimental/define-network.js +21 -11
  25. package/lib/core/experimental/define-network.js.map +1 -1
  26. package/lib/core/experimental/define-network.mjs +23 -11
  27. package/lib/core/experimental/define-network.mjs.map +1 -1
  28. package/lib/core/experimental/frames/http-frame.d.mts +2 -2
  29. package/lib/core/experimental/frames/http-frame.d.ts +2 -2
  30. package/lib/core/experimental/frames/http-frame.js +5 -2
  31. package/lib/core/experimental/frames/http-frame.js.map +1 -1
  32. package/lib/core/experimental/frames/http-frame.mjs +8 -3
  33. package/lib/core/experimental/frames/http-frame.mjs.map +1 -1
  34. package/lib/core/experimental/frames/network-frame.d.mts +2 -2
  35. package/lib/core/experimental/frames/network-frame.d.ts +2 -2
  36. package/lib/core/experimental/frames/network-frame.js +2 -0
  37. package/lib/core/experimental/frames/network-frame.js.map +1 -1
  38. package/lib/core/experimental/frames/network-frame.mjs +2 -0
  39. package/lib/core/experimental/frames/network-frame.mjs.map +1 -1
  40. package/lib/core/experimental/frames/websocket-frame.d.mts +2 -2
  41. package/lib/core/experimental/frames/websocket-frame.d.ts +2 -2
  42. package/lib/core/experimental/frames/websocket-frame.js +2 -0
  43. package/lib/core/experimental/frames/websocket-frame.js.map +1 -1
  44. package/lib/core/experimental/frames/websocket-frame.mjs +2 -0
  45. package/lib/core/experimental/frames/websocket-frame.mjs.map +1 -1
  46. package/lib/core/experimental/handlers-controller.d.mts +2 -1
  47. package/lib/core/experimental/handlers-controller.d.ts +2 -1
  48. package/lib/core/experimental/handlers-controller.js +31 -6
  49. package/lib/core/experimental/handlers-controller.js.map +1 -1
  50. package/lib/core/experimental/handlers-controller.mjs +31 -6
  51. package/lib/core/experimental/handlers-controller.mjs.map +1 -1
  52. package/lib/core/experimental/index.d.mts +5 -5
  53. package/lib/core/experimental/index.d.ts +5 -5
  54. package/lib/core/experimental/index.js +3 -1
  55. package/lib/core/experimental/index.js.map +1 -1
  56. package/lib/core/experimental/index.mjs +9 -2
  57. package/lib/core/experimental/index.mjs.map +1 -1
  58. package/lib/core/experimental/on-unhandled-frame.d.mts +2 -2
  59. package/lib/core/experimental/on-unhandled-frame.d.ts +2 -2
  60. package/lib/core/experimental/on-unhandled-frame.js +1 -0
  61. package/lib/core/experimental/on-unhandled-frame.js.map +1 -1
  62. package/lib/core/experimental/on-unhandled-frame.mjs +1 -0
  63. package/lib/core/experimental/on-unhandled-frame.mjs.map +1 -1
  64. package/lib/core/experimental/setup-api.d.mts +1 -1
  65. package/lib/core/experimental/setup-api.d.ts +1 -1
  66. package/lib/core/experimental/setup-api.js +2 -5
  67. package/lib/core/experimental/setup-api.js.map +1 -1
  68. package/lib/core/experimental/setup-api.mjs +2 -5
  69. package/lib/core/experimental/setup-api.mjs.map +1 -1
  70. package/lib/core/experimental/sources/interceptor-source.d.mts +2 -2
  71. package/lib/core/experimental/sources/interceptor-source.d.ts +2 -2
  72. package/lib/core/experimental/sources/interceptor-source.js +23 -10
  73. package/lib/core/experimental/sources/interceptor-source.js.map +1 -1
  74. package/lib/core/experimental/sources/interceptor-source.mjs +24 -13
  75. package/lib/core/experimental/sources/interceptor-source.mjs.map +1 -1
  76. package/lib/core/experimental/sources/network-source.d.mts +3 -3
  77. package/lib/core/experimental/sources/network-source.d.ts +3 -3
  78. package/lib/core/experimental/sources/network-source.js +1 -0
  79. package/lib/core/experimental/sources/network-source.js.map +1 -1
  80. package/lib/core/experimental/sources/network-source.mjs +2 -0
  81. package/lib/core/experimental/sources/network-source.mjs.map +1 -1
  82. package/lib/core/getResponse.d.mts +1 -1
  83. package/lib/core/getResponse.d.ts +1 -1
  84. package/lib/core/graphql.d.mts +1 -1
  85. package/lib/core/graphql.d.ts +1 -1
  86. package/lib/core/graphql.js +1 -0
  87. package/lib/core/graphql.js.map +1 -1
  88. package/lib/core/graphql.mjs +2 -0
  89. package/lib/core/graphql.mjs.map +1 -1
  90. package/lib/core/handlers/GraphQLHandler.d.mts +1 -1
  91. package/lib/core/handlers/GraphQLHandler.d.ts +1 -1
  92. package/lib/core/handlers/GraphQLHandler.js +1 -0
  93. package/lib/core/handlers/GraphQLHandler.js.map +1 -1
  94. package/lib/core/handlers/GraphQLHandler.mjs +4 -1
  95. package/lib/core/handlers/GraphQLHandler.mjs.map +1 -1
  96. package/lib/core/handlers/HttpHandler.d.mts +1 -1
  97. package/lib/core/handlers/HttpHandler.d.ts +1 -1
  98. package/lib/core/handlers/HttpHandler.js +1 -0
  99. package/lib/core/handlers/HttpHandler.js.map +1 -1
  100. package/lib/core/handlers/HttpHandler.mjs +1 -0
  101. package/lib/core/handlers/HttpHandler.mjs.map +1 -1
  102. package/lib/core/handlers/RequestHandler.d.mts +1 -1
  103. package/lib/core/handlers/RequestHandler.d.ts +1 -1
  104. package/lib/core/handlers/RequestHandler.js +197 -4
  105. package/lib/core/handlers/RequestHandler.js.map +1 -1
  106. package/lib/core/handlers/RequestHandler.mjs +198 -4
  107. package/lib/core/handlers/RequestHandler.mjs.map +1 -1
  108. package/lib/core/handlers/WebSocketHandler.d.mts +5 -2
  109. package/lib/core/handlers/WebSocketHandler.d.ts +5 -2
  110. package/lib/core/handlers/WebSocketHandler.js +30 -12
  111. package/lib/core/handlers/WebSocketHandler.js.map +1 -1
  112. package/lib/core/handlers/WebSocketHandler.mjs +30 -12
  113. package/lib/core/handlers/WebSocketHandler.mjs.map +1 -1
  114. package/lib/core/http.d.mts +1 -1
  115. package/lib/core/http.d.ts +1 -1
  116. package/lib/core/http.js +1 -0
  117. package/lib/core/http.js.map +1 -1
  118. package/lib/core/http.mjs +2 -0
  119. package/lib/core/http.mjs.map +1 -1
  120. package/lib/core/index.d.mts +1 -1
  121. package/lib/core/index.d.ts +1 -1
  122. package/lib/core/{network-frame-usYiHS0K.d.ts → on-unhandled-frame-0KmwUmeV.d.ts} +13 -13
  123. package/lib/core/{network-frame-B7A0ggXE.d.mts → on-unhandled-frame-gkokW4Rr.d.mts} +13 -13
  124. package/lib/core/passthrough.d.mts +1 -1
  125. package/lib/core/passthrough.d.ts +1 -1
  126. package/lib/core/sse.d.mts +4 -18
  127. package/lib/core/sse.d.ts +4 -18
  128. package/lib/core/sse.js +149 -66
  129. package/lib/core/sse.js.map +1 -1
  130. package/lib/core/sse.mjs +149 -66
  131. package/lib/core/sse.mjs.map +1 -1
  132. package/lib/core/utils/HttpResponse/decorators.d.mts +9 -4
  133. package/lib/core/utils/HttpResponse/decorators.d.ts +9 -4
  134. package/lib/core/utils/HttpResponse/decorators.js +18 -11
  135. package/lib/core/utils/HttpResponse/decorators.js.map +1 -1
  136. package/lib/core/utils/HttpResponse/decorators.mjs +18 -11
  137. package/lib/core/utils/HttpResponse/decorators.mjs.map +1 -1
  138. package/lib/core/utils/cookieStore.js.map +1 -1
  139. package/lib/core/utils/cookieStore.mjs.map +1 -1
  140. package/lib/core/utils/executeHandlers.d.mts +1 -1
  141. package/lib/core/utils/executeHandlers.d.ts +1 -1
  142. package/lib/core/utils/executeHandlers.js +1 -0
  143. package/lib/core/utils/executeHandlers.js.map +1 -1
  144. package/lib/core/utils/executeHandlers.mjs +1 -0
  145. package/lib/core/utils/executeHandlers.mjs.map +1 -1
  146. package/lib/core/utils/handleRequest.d.mts +1 -1
  147. package/lib/core/utils/handleRequest.d.ts +1 -1
  148. package/lib/core/utils/handleRequest.js.map +1 -1
  149. package/lib/core/utils/handleRequest.mjs.map +1 -1
  150. package/lib/core/utils/internal/Disposable.js +19 -1
  151. package/lib/core/utils/internal/Disposable.js.map +1 -1
  152. package/lib/core/utils/internal/Disposable.mjs +19 -1
  153. package/lib/core/utils/internal/Disposable.mjs.map +1 -1
  154. package/lib/core/utils/internal/attachSiblingHandlers.d.mts +15 -0
  155. package/lib/core/utils/internal/attachSiblingHandlers.d.ts +15 -0
  156. package/lib/core/utils/internal/attachSiblingHandlers.js +44 -0
  157. package/lib/core/utils/internal/attachSiblingHandlers.js.map +1 -0
  158. package/lib/core/utils/internal/attachSiblingHandlers.mjs +24 -0
  159. package/lib/core/utils/internal/attachSiblingHandlers.mjs.map +1 -0
  160. package/lib/core/utils/internal/isHandlerKind.d.mts +1 -1
  161. package/lib/core/utils/internal/isHandlerKind.d.ts +1 -1
  162. package/lib/core/utils/internal/observe-response-body-stream.d.mts +18 -0
  163. package/lib/core/utils/internal/observe-response-body-stream.d.ts +18 -0
  164. package/lib/core/utils/internal/observe-response-body-stream.js +64 -0
  165. package/lib/core/utils/internal/observe-response-body-stream.js.map +1 -0
  166. package/lib/core/utils/internal/observe-response-body-stream.mjs +44 -0
  167. package/lib/core/utils/internal/observe-response-body-stream.mjs.map +1 -0
  168. package/lib/core/utils/internal/parseGraphQLRequest.d.mts +1 -1
  169. package/lib/core/utils/internal/parseGraphQLRequest.d.ts +1 -1
  170. package/lib/core/utils/internal/parseMultipartData.d.mts +1 -1
  171. package/lib/core/utils/internal/parseMultipartData.d.ts +1 -1
  172. package/lib/core/utils/internal/parseMultipartData.js +1 -0
  173. package/lib/core/utils/internal/parseMultipartData.js.map +1 -1
  174. package/lib/core/utils/internal/parseMultipartData.mjs +1 -0
  175. package/lib/core/utils/internal/parseMultipartData.mjs.map +1 -1
  176. package/lib/core/utils/internal/pipeEvents.js +1 -0
  177. package/lib/core/utils/internal/pipeEvents.js.map +1 -1
  178. package/lib/core/utils/internal/pipeEvents.mjs +1 -0
  179. package/lib/core/utils/internal/pipeEvents.mjs.map +1 -1
  180. package/lib/core/utils/request/storeResponseCookies.js +1 -1
  181. package/lib/core/utils/request/storeResponseCookies.js.map +1 -1
  182. package/lib/core/utils/request/storeResponseCookies.mjs +2 -2
  183. package/lib/core/utils/request/storeResponseCookies.mjs.map +1 -1
  184. package/lib/core/ws/WebSocketClientManager.js +4 -0
  185. package/lib/core/ws/WebSocketClientManager.js.map +1 -1
  186. package/lib/core/ws/WebSocketClientManager.mjs +4 -0
  187. package/lib/core/ws/WebSocketClientManager.mjs.map +1 -1
  188. package/lib/core/ws/WebSocketIndexedDBClientStore.js +1 -0
  189. package/lib/core/ws/WebSocketIndexedDBClientStore.js.map +1 -1
  190. package/lib/core/ws/WebSocketIndexedDBClientStore.mjs +1 -0
  191. package/lib/core/ws/WebSocketIndexedDBClientStore.mjs.map +1 -1
  192. package/lib/core/ws/WebSocketMemoryClientStore.js +1 -0
  193. package/lib/core/ws/WebSocketMemoryClientStore.js.map +1 -1
  194. package/lib/core/ws/WebSocketMemoryClientStore.mjs +1 -0
  195. package/lib/core/ws/WebSocketMemoryClientStore.mjs.map +1 -1
  196. package/lib/core/ws/handleWebSocketEvent.d.mts +1 -1
  197. package/lib/core/ws/handleWebSocketEvent.d.ts +1 -1
  198. package/lib/core/ws/handleWebSocketEvent.js.map +1 -1
  199. package/lib/core/ws/handleWebSocketEvent.mjs.map +1 -1
  200. package/lib/core/ws.d.mts +17 -4
  201. package/lib/core/ws.d.ts +17 -4
  202. package/lib/core/ws.js +30 -5
  203. package/lib/core/ws.js.map +1 -1
  204. package/lib/core/ws.mjs +34 -6
  205. package/lib/core/ws.mjs.map +1 -1
  206. package/lib/iife/index.js +10138 -6034
  207. package/lib/iife/index.js.map +1 -1
  208. package/lib/mockServiceWorker.js +21 -9
  209. package/lib/native/index.js.map +1 -1
  210. package/lib/native/index.mjs.map +1 -1
  211. package/lib/node/index.d.mts +1 -1
  212. package/lib/node/index.d.ts +1 -1
  213. package/lib/node/index.js +2 -0
  214. package/lib/node/index.js.map +1 -1
  215. package/lib/node/index.mjs +1 -0
  216. package/lib/node/index.mjs.map +1 -1
  217. package/lib/shims/cookie.js +152 -62
  218. package/lib/shims/cookie.mjs +152 -62
  219. package/package.json +50 -69
  220. package/src/browser/glossary.ts +1 -1
  221. package/src/browser/setup-worker.ts +2 -2
  222. package/src/browser/sources/service-worker-source.ts +142 -40
  223. package/src/browser/utils/deserializeRequest.ts +2 -2
  224. package/src/browser/utils/pruneGetRequestBody.ts +3 -3
  225. package/src/browser/utils/should-invalidate-worker.test.ts +122 -0
  226. package/src/browser/utils/should-invalidate-worker.ts +13 -0
  227. package/src/browser/utils/workerChannel.ts +43 -21
  228. package/src/core/experimental/define-network.ts +44 -15
  229. package/src/core/experimental/frames/http-frame.test.ts +8 -2
  230. package/src/core/experimental/frames/http-frame.ts +12 -4
  231. package/src/core/experimental/frames/websocket-frame.test.ts +2 -4
  232. package/src/core/experimental/frames/websocket-frame.ts +3 -2
  233. package/src/core/experimental/handlers-controller.test.ts +139 -5
  234. package/src/core/experimental/handlers-controller.ts +39 -10
  235. package/src/core/experimental/index.ts +11 -1
  236. package/src/core/experimental/on-unhandled-frame.test.ts +2 -4
  237. package/src/core/experimental/setup-api.ts +4 -8
  238. package/src/core/experimental/sources/interceptor-source.ts +36 -16
  239. package/src/core/experimental/sources/network-source.ts +1 -1
  240. package/src/core/graphql.ts +8 -8
  241. package/src/core/handlers/GraphQLHandler.test.ts +3 -4
  242. package/src/core/handlers/GraphQLHandler.ts +15 -11
  243. package/src/core/handlers/HttpHandler.test.ts +92 -2
  244. package/src/core/handlers/HttpHandler.ts +7 -7
  245. package/src/core/handlers/RequestHandler.ts +329 -22
  246. package/src/core/handlers/WebSocketHandler.test.ts +58 -0
  247. package/src/core/handlers/WebSocketHandler.ts +37 -8
  248. package/src/core/http.ts +5 -5
  249. package/src/core/sse.ts +217 -73
  250. package/src/core/utils/HttpResponse/decorators.ts +28 -22
  251. package/src/core/utils/cookieStore.ts +1 -1
  252. package/src/core/utils/executeHandlers.ts +2 -4
  253. package/src/core/utils/handleRequest.test.ts +5 -4
  254. package/src/core/utils/handleRequest.ts +3 -3
  255. package/src/core/utils/internal/Disposable.ts +22 -1
  256. package/src/core/utils/internal/attachSiblingHandlers.ts +28 -0
  257. package/src/core/utils/internal/observe-response-body-stream.test.ts +64 -0
  258. package/src/core/utils/internal/observe-response-body-stream.ts +77 -0
  259. package/src/core/utils/internal/parseGraphQLRequest.test.ts +2 -4
  260. package/src/core/utils/internal/parseMultipartData.ts +1 -1
  261. package/src/core/utils/internal/pipeEvents.ts +2 -1
  262. package/src/core/utils/request/onUnhandledRequest.test.ts +2 -4
  263. package/src/core/utils/request/storeResponseCookies.ts +2 -4
  264. package/src/core/ws/WebSocketClientManager.test.ts +2 -4
  265. package/src/core/ws/WebSocketClientManager.ts +1 -1
  266. package/src/core/ws/WebSocketIndexedDBClientStore.ts +3 -5
  267. package/src/core/ws/WebSocketMemoryClientStore.ts +3 -5
  268. package/src/core/ws/handleWebSocketEvent.ts +3 -3
  269. package/src/core/ws.ts +66 -7
  270. package/src/mockServiceWorker.js +19 -7
  271. package/src/native/index.ts +2 -2
  272. package/src/node/async-handlers-controller.ts +2 -2
  273. package/src/node/index.ts +1 -0
  274. package/src/node/setup-server-common.ts +4 -4
  275. package/src/node/setup-server.ts +2 -2
  276. package/lib/core/utils/internal/requestHandlerUtils.d.mts +0 -12
  277. package/lib/core/utils/internal/requestHandlerUtils.d.ts +0 -12
  278. package/lib/core/utils/internal/requestHandlerUtils.js +0 -37
  279. package/lib/core/utils/internal/requestHandlerUtils.js.map +0 -1
  280. package/lib/core/utils/internal/requestHandlerUtils.mjs +0 -17
  281. package/lib/core/utils/internal/requestHandlerUtils.mjs.map +0 -1
  282. package/src/core/utils/internal/requestHandlerUtils.ts +0 -21
@@ -1,17 +1,18 @@
1
1
  import { invariant } from 'outvariant'
2
2
  import { Emitter, type DefaultEventMap } from 'rettime'
3
3
  import {
4
- type NetworkSource,
4
+ NetworkSource,
5
5
  type ExtractSourceEvents,
6
6
  } from './sources/network-source'
7
7
  import { type NetworkFrameResolutionContext } from './frames/network-frame'
8
8
  import { type UnhandledFrameHandle } from './on-unhandled-frame'
9
9
  import {
10
- AnyHandler,
11
10
  HandlersController,
12
11
  InMemoryHandlersController,
12
+ type AnyHandler,
13
13
  } from './handlers-controller'
14
14
  import { toReadonlyArray } from '../utils/internal/toReadonlyArray'
15
+ import { Disposable } from '../utils/internal/Disposable'
15
16
 
16
17
  type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
17
18
  k: infer I,
@@ -47,8 +48,9 @@ export interface DefineNetworkOptions<
47
48
  onUnhandledFrame?: UnhandledFrameHandle
48
49
  }
49
50
 
50
- export interface NetworkApi<Sources extends Array<NetworkSource<any>>>
51
- extends NetworkHandlersApi {
51
+ export interface NetworkApi<
52
+ Sources extends Array<NetworkSource<any>>,
53
+ > extends NetworkHandlersApi {
52
54
  readyState: NetworkReadyState
53
55
  /**
54
56
  * Enable the network interception and handling.
@@ -111,6 +113,7 @@ export function defineNetwork<Sources extends Array<NetworkSource<any>>>(
111
113
  ): NetworkApi<Sources> {
112
114
  let readyState: NetworkReadyState = NetworkReadyState.DISABLED
113
115
  const events = new Emitter<MergeEventMaps<Sources>>()
116
+ const disposable = new Disposable()
114
117
 
115
118
  const deriveHandlersController = (
116
119
  handlers: DefineNetworkOptions<Sources>['handlers'],
@@ -129,7 +132,6 @@ export function defineNetwork<Sources extends Array<NetworkSource<any>>>(
129
132
  * certain setup APIs, like `setupServer`, don't await `.enable` (`.listen`).
130
133
  */
131
134
  let handlersController = deriveHandlersController(resolvedOptions.handlers)
132
- let listenersController: AbortController
133
135
 
134
136
  return {
135
137
  get readyState() {
@@ -137,7 +139,10 @@ export function defineNetwork<Sources extends Array<NetworkSource<any>>>(
137
139
  },
138
140
  events,
139
141
  configure(options) {
140
- invariant(readyState === NetworkReadyState.DISABLED, '')
142
+ invariant(
143
+ readyState === NetworkReadyState.DISABLED,
144
+ 'Failed to call "configure()" on the network: cannot configure an already enabled network.',
145
+ )
141
146
 
142
147
  if (
143
148
  options.handlers &&
@@ -157,13 +162,41 @@ export function defineNetwork<Sources extends Array<NetworkSource<any>>>(
157
162
  'Failed to call "enable" on the network: already enabled',
158
163
  )
159
164
 
160
- listenersController = new AbortController()
161
165
  readyState = NetworkReadyState.ENABLED
162
166
 
167
+ /**
168
+ * @note Use a session object scoped to the current "enable()"
169
+ * to prevent "frame.events" listeners from surviving across enable/disable cycles.
170
+ * @see The note about `AbortController` below.
171
+ */
172
+ const session = { active: true }
173
+ disposable['subscriptions'].push(() => {
174
+ session.active = false
175
+ })
176
+
163
177
  const result = resolvedOptions.sources.map((source) => {
178
+ /**
179
+ * @note Preemptively disable the network source before enabling.
180
+ * This intentionally calls only the prototype method that clears the
181
+ * event listeners and nothing else. This prevents the "frame" listeners
182
+ * from accumulating across enable/disable in case the source is a singleton.
183
+ */
184
+ NetworkSource.prototype.disable.call(source)
185
+
164
186
  source.on('frame', async ({ frame }) => {
165
- frame.events.on('*', (event) => events.emit(event), {
166
- signal: listenersController.signal,
187
+ frame.events.on('*', (event) => {
188
+ /**
189
+ * @note Prevent event forwarding manually and not via an AbortController
190
+ * because certain runtimes, like Cloudflare, throw when referencing an
191
+ * AbortController created in a different context. Bear in mind that the frame
192
+ * events run in the patched request client context while the AbortController
193
+ * is created outside, in the "defineNetwork" closure, which is a test context.
194
+ */
195
+ if (!session.active) {
196
+ return
197
+ }
198
+
199
+ events.emit(event)
167
200
  })
168
201
 
169
202
  const handlers = frame.getHandlers(handlersController)
@@ -188,8 +221,8 @@ export function defineNetwork<Sources extends Array<NetworkSource<any>>>(
188
221
  'Failed to call "disable" on the network: already disabled',
189
222
  )
190
223
 
191
- listenersController.abort()
192
224
  readyState = NetworkReadyState.DISABLED
225
+ disposable.dispose()
193
226
 
194
227
  return colorlessPromiseAll(
195
228
  resolvedOptions.sources.map((source) => source.disable()),
@@ -202,11 +235,7 @@ export function defineNetwork<Sources extends Array<NetworkSource<any>>>(
202
235
  handlersController.reset(handlers)
203
236
  },
204
237
  restoreHandlers() {
205
- for (const handler of handlersController.currentHandlers()) {
206
- if ('isUsed' in handler) {
207
- handler.isUsed = false
208
- }
209
- }
238
+ handlersController.restore()
210
239
  },
211
240
  listHandlers() {
212
241
  return toReadonlyArray(handlersController.currentHandlers())
@@ -2,8 +2,10 @@ import { http } from '../../http'
2
2
  import { graphql } from '../../graphql'
3
3
  import { ws } from '../../ws'
4
4
  import { bypass } from '../../bypass'
5
- import { HttpNetworkFrame, HttpNetworkFrameEventMap } from './http-frame'
6
- import { InMemoryHandlersController } from '#core/experimental/handlers-controller'
5
+ import type { HttpNetworkFrameEventMap } from './http-frame'
6
+ import { HttpNetworkFrame } from './http-frame'
7
+ import { InMemoryHandlersController } from '../../experimental/handlers-controller'
8
+ import { getSiblingHandlers } from '../../utils/internal/attachSiblingHandlers'
7
9
 
8
10
  beforeAll(() => {
9
11
  vi.spyOn(console, 'error').mockImplementation(() => {})
@@ -45,6 +47,9 @@ it('filters only request type handlers', async () => {
45
47
  const webSocketHandlers = [
46
48
  ws.link('ws://localhost').addEventListener('connection', () => {}),
47
49
  ]
50
+ const webSocketSiblingHandlers = webSocketHandlers.flatMap((handler) =>
51
+ getSiblingHandlers(handler),
52
+ )
48
53
 
49
54
  const controller = new InMemoryHandlersController([
50
55
  ...httpHandlers,
@@ -54,6 +59,7 @@ it('filters only request type handlers', async () => {
54
59
 
55
60
  expect(frame.getHandlers(controller)).toEqual([
56
61
  ...httpHandlers,
62
+ ...webSocketSiblingHandlers,
57
63
  ...graphqlHandlers,
58
64
  ])
59
65
  expect(frame.getHandlers(new InMemoryHandlersController([]))).toEqual([])
@@ -1,7 +1,10 @@
1
1
  import { TypedEvent } from 'rettime'
2
2
  import { until } from 'until-async'
3
3
  import { createRequestId } from '@mswjs/interceptors'
4
- import { NetworkFrame, NetworkFrameResolutionContext } from './network-frame'
4
+ import {
5
+ NetworkFrame,
6
+ type NetworkFrameResolutionContext,
7
+ } from './network-frame'
5
8
  import { toPublicUrl } from '../../utils/request/toPublicUrl'
6
9
  import { executeHandlers } from '../../utils/executeHandlers'
7
10
  import { storeResponseCookies } from '../../utils/request/storeResponseCookies'
@@ -11,7 +14,8 @@ import {
11
14
  executeUnhandledFrameHandle,
12
15
  type UnhandledFrameHandle,
13
16
  } from '../on-unhandled-frame'
14
- import { HandlersController, AnyHandler } from '../handlers-controller'
17
+ import type { HandlersController } from '../handlers-controller'
18
+ import { type AnyHandler } from '../handlers-controller'
15
19
  import { type RequestHandler } from '../../handlers/RequestHandler'
16
20
 
17
21
  interface HttpNetworkFrameOptions {
@@ -247,9 +251,13 @@ export abstract class HttpNetworkFrame extends NetworkFrame<
247
251
  return null
248
252
  }
249
253
 
254
+ const responseCloneForLogs = resolutionContext?.quiet
255
+ ? null
256
+ : response.clone()
257
+
250
258
  await storeResponseCookies(request, response)
251
259
 
252
- this.respondWith(response.clone())
260
+ this.respondWith(response)
253
261
 
254
262
  this.events.emit(
255
263
  new RequestEvent('request:end', {
@@ -261,7 +269,7 @@ export abstract class HttpNetworkFrame extends NetworkFrame<
261
269
  if (!resolutionContext?.quiet) {
262
270
  handler.log({
263
271
  request: requestCloneForLogs!,
264
- response,
272
+ response: responseCloneForLogs!,
265
273
  parsedResult,
266
274
  })
267
275
  }
@@ -1,10 +1,8 @@
1
1
  import { http } from '../../http'
2
2
  import { graphql } from '../../graphql'
3
3
  import { ws } from '../../ws'
4
- import {
5
- WebSocketNetworkFrame,
6
- WebSocketNetworkFrameEventMap,
7
- } from './websocket-frame'
4
+ import type { WebSocketNetworkFrameEventMap } from './websocket-frame'
5
+ import { WebSocketNetworkFrame } from './websocket-frame'
8
6
  import { createTestWebSocketConnection } from '../../../../test/support/ws-test-utils'
9
7
  import { InMemoryHandlersController } from '#core/experimental/handlers-controller'
10
8
 
@@ -11,10 +11,11 @@ import {
11
11
  } from './network-frame'
12
12
  import {
13
13
  executeUnhandledFrameHandle,
14
- UnhandledFrameHandle,
14
+ type UnhandledFrameHandle,
15
15
  } from '../on-unhandled-frame'
16
16
  import { devUtils } from '../../utils/internal/devUtils'
17
- import { HandlersController, AnyHandler } from '../handlers-controller'
17
+ import type { HandlersController } from '../handlers-controller'
18
+ import { type AnyHandler } from '../handlers-controller'
18
19
 
19
20
  export interface WebSocketNetworkFrameOptions {
20
21
  connection: WebSocketConnectionData
@@ -1,8 +1,68 @@
1
1
  import { http } from '../http'
2
2
  import { graphql } from '../graphql'
3
3
  import { ws } from '../ws'
4
+ import { getSiblingHandlers } from '../utils/internal/attachSiblingHandlers'
4
5
  import { InMemoryHandlersController } from './handlers-controller'
5
6
 
7
+ describe('constructor', () => {
8
+ it('places the sibling in its own kind bucket', () => {
9
+ const wsHandler = ws.link('*').addEventListener('connection', () => {})
10
+ const [upgradeHandler] = getSiblingHandlers(wsHandler)
11
+
12
+ const controller = new InMemoryHandlersController([wsHandler])
13
+
14
+ expect(controller.getHandlersByKind('websocket')).toEqual([wsHandler])
15
+ expect(controller.getHandlersByKind('request')).toEqual([upgradeHandler])
16
+ })
17
+
18
+ it('interleaves the sibling at the owner position when grouping by kind', () => {
19
+ const httpOne = http.get('/', () => {})
20
+ const wsHandler = ws.link('*').addEventListener('connection', () => {})
21
+ const [upgradeHandler] = getSiblingHandlers(wsHandler)
22
+ const httpTwo = http.get('/', () => {})
23
+
24
+ const controller = new InMemoryHandlersController([
25
+ httpOne,
26
+ wsHandler,
27
+ httpTwo,
28
+ ])
29
+
30
+ expect(controller.getHandlersByKind('request')).toEqual([
31
+ httpOne,
32
+ upgradeHandler,
33
+ httpTwo,
34
+ ])
35
+ expect(controller.getHandlersByKind('websocket')).toEqual([wsHandler])
36
+ })
37
+
38
+ it('extracts siblings from every owner in the input list', () => {
39
+ const wsOne = ws.link('*').addEventListener('connection', () => {})
40
+ const wsTwo = ws.link('*').addEventListener('connection', () => {})
41
+ const [upgradeOne] = getSiblingHandlers(wsOne)
42
+ const [upgradeTwo] = getSiblingHandlers(wsTwo)
43
+
44
+ const controller = new InMemoryHandlersController([wsOne, wsTwo])
45
+
46
+ expect(controller.getHandlersByKind('websocket')).toEqual([wsOne, wsTwo])
47
+ expect(controller.getHandlersByKind('request')).toEqual([
48
+ upgradeOne,
49
+ upgradeTwo,
50
+ ])
51
+ })
52
+
53
+ it('dedupes the shared upgrade sibling across multiple handlers from the same link', () => {
54
+ const chat = ws.link('*')
55
+ const wsOne = chat.addEventListener('connection', () => {})
56
+ const wsTwo = chat.addEventListener('connection', () => {})
57
+ const [upgradeHandler] = getSiblingHandlers(wsOne)
58
+
59
+ const controller = new InMemoryHandlersController([wsOne, wsTwo])
60
+
61
+ expect(controller.getHandlersByKind('websocket')).toEqual([wsOne, wsTwo])
62
+ expect(controller.getHandlersByKind('request')).toEqual([upgradeHandler])
63
+ })
64
+ })
65
+
6
66
  describe(InMemoryHandlersController.prototype.use, () => {
7
67
  it('prepends a handler to an empty controller', () => {
8
68
  const controller = new InMemoryHandlersController([])
@@ -51,6 +111,44 @@ describe(InMemoryHandlersController.prototype.use, () => {
51
111
 
52
112
  expect(controller.currentHandlers()).toEqual([graphqlOne, httpTwo, httpOne])
53
113
  })
114
+
115
+ it('propagates siblings to their kind buckets at runtime', () => {
116
+ const controller = new InMemoryHandlersController([])
117
+ const wsHandler = ws.link('*').addEventListener('connection', () => {})
118
+ const [upgradeHandler] = getSiblingHandlers(wsHandler)
119
+
120
+ controller.use([wsHandler])
121
+
122
+ expect(controller.getHandlersByKind('websocket')).toEqual([wsHandler])
123
+ expect(controller.getHandlersByKind('request')).toEqual([upgradeHandler])
124
+ })
125
+
126
+ it('prepends incoming siblings before existing handlers of the same kind', () => {
127
+ const existingHttp = http.get('/existing', () => {})
128
+ const controller = new InMemoryHandlersController([existingHttp])
129
+ const wsHandler = ws.link('*').addEventListener('connection', () => {})
130
+ const [upgradeHandler] = getSiblingHandlers(wsHandler)
131
+
132
+ controller.use([wsHandler])
133
+
134
+ expect(controller.getHandlersByKind('request')).toEqual([
135
+ upgradeHandler,
136
+ existingHttp,
137
+ ])
138
+ })
139
+
140
+ it('dedupes the shared upgrade sibling when called with multiple handlers from the same link', () => {
141
+ const chat = ws.link('*')
142
+ const wsOne = chat.addEventListener('connection', () => {})
143
+ const wsTwo = chat.addEventListener('connection', () => {})
144
+ const [upgradeHandler] = getSiblingHandlers(wsOne)
145
+
146
+ const controller = new InMemoryHandlersController([])
147
+ controller.use([wsOne, wsTwo])
148
+
149
+ expect(controller.getHandlersByKind('websocket')).toEqual([wsOne, wsTwo])
150
+ expect(controller.getHandlersByKind('request')).toEqual([upgradeHandler])
151
+ })
54
152
  })
55
153
 
56
154
  describe(InMemoryHandlersController.prototype.reset, () => {
@@ -96,6 +194,42 @@ describe(InMemoryHandlersController.prototype.reset, () => {
96
194
  */
97
195
  expect(controller.currentHandlers()).toEqual([httpTwo])
98
196
  })
197
+
198
+ it('places siblings into their kind buckets when resetting to next handlers', () => {
199
+ const controller = new InMemoryHandlersController([])
200
+ const wsHandler = ws.link('*').addEventListener('connection', () => {})
201
+ const [upgradeHandler] = getSiblingHandlers(wsHandler)
202
+
203
+ controller.reset([wsHandler])
204
+
205
+ expect(controller.getHandlersByKind('websocket')).toEqual([wsHandler])
206
+ expect(controller.getHandlersByKind('request')).toEqual([upgradeHandler])
207
+ })
208
+
209
+ it('restores siblings when resetting to the initial handlers', () => {
210
+ const wsHandler = ws.link('*').addEventListener('connection', () => {})
211
+ const [upgradeHandler] = getSiblingHandlers(wsHandler)
212
+ const controller = new InMemoryHandlersController([wsHandler])
213
+
214
+ controller.use([http.get('/runtime', () => {})])
215
+ controller.reset([])
216
+
217
+ expect(controller.getHandlersByKind('websocket')).toEqual([wsHandler])
218
+ expect(controller.getHandlersByKind('request')).toEqual([upgradeHandler])
219
+ })
220
+
221
+ it('dedupes the shared upgrade sibling when reset with multiple handlers from the same link', () => {
222
+ const chat = ws.link('*')
223
+ const wsOne = chat.addEventListener('connection', () => {})
224
+ const wsTwo = chat.addEventListener('connection', () => {})
225
+ const [upgradeHandler] = getSiblingHandlers(wsOne)
226
+
227
+ const controller = new InMemoryHandlersController([])
228
+ controller.reset([wsOne, wsTwo])
229
+
230
+ expect(controller.getHandlersByKind('websocket')).toEqual([wsOne, wsTwo])
231
+ expect(controller.getHandlersByKind('request')).toEqual([upgradeHandler])
232
+ })
99
233
  })
100
234
 
101
235
  describe(InMemoryHandlersController.prototype.getHandlersByKind, () => {
@@ -112,11 +246,10 @@ describe(InMemoryHandlersController.prototype.getHandlersByKind, () => {
112
246
  ]).getHandlersByKind('websocket'),
113
247
  ).toEqual([])
114
248
 
249
+ const wsHandler = ws.link('*').addEventListener('connection', () => {})
115
250
  expect(
116
- new InMemoryHandlersController([
117
- ws.link('*').addEventListener('connection', () => {}),
118
- ]).getHandlersByKind('request'),
119
- ).toEqual([])
251
+ new InMemoryHandlersController([wsHandler]).getHandlersByKind('request'),
252
+ ).toEqual(getSiblingHandlers(wsHandler))
120
253
  })
121
254
 
122
255
  it('returns all handlers if they all match', () => {
@@ -142,6 +275,7 @@ describe(InMemoryHandlersController.prototype.getHandlersByKind, () => {
142
275
  const httpHandler = http.get('/', () => {})
143
276
  const graphqlHandler = graphql.query('', () => {})
144
277
  const wsHandler = ws.link('*').addEventListener('connection', () => {})
278
+ const wsHandlerSiblings = getSiblingHandlers(wsHandler)
145
279
 
146
280
  expect(
147
281
  new InMemoryHandlersController([
@@ -149,7 +283,7 @@ describe(InMemoryHandlersController.prototype.getHandlersByKind, () => {
149
283
  graphqlHandler,
150
284
  wsHandler,
151
285
  ]).getHandlersByKind('request'),
152
- ).toEqual([httpHandler, graphqlHandler])
286
+ ).toEqual([httpHandler, graphqlHandler, ...wsHandlerSiblings])
153
287
 
154
288
  expect(
155
289
  new InMemoryHandlersController([
@@ -2,6 +2,7 @@ import { invariant } from 'outvariant'
2
2
  import { type RequestHandler } from '../handlers/RequestHandler'
3
3
  import { type WebSocketHandler } from '../handlers/WebSocketHandler'
4
4
  import { devUtils } from '../utils/internal/devUtils'
5
+ import { getSiblingHandlers } from '../utils/internal/attachSiblingHandlers'
5
6
 
6
7
  export type AnyHandler = RequestHandler | WebSocketHandler
7
8
  export type HandlersMap = Partial<Record<AnyHandler['kind'], Array<AnyHandler>>>
@@ -9,11 +10,23 @@ export type HandlersMap = Partial<Record<AnyHandler['kind'], Array<AnyHandler>>>
9
10
  export function groupHandlersByKind(handlers: Array<AnyHandler>): HandlersMap {
10
11
  const groups: HandlersMap = {}
11
12
 
13
+ const pushUnique = (kind: AnyHandler['kind'], handler: AnyHandler) => {
14
+ const bucket = (groups[kind] ||= [])
15
+
16
+ if (!bucket.includes(handler)) {
17
+ bucket.push(handler)
18
+ }
19
+ }
20
+
12
21
  /**
13
22
  * @note `Object.groupBy` is not implemented in Node.js v20.
14
23
  */
15
24
  for (const handler of handlers) {
16
- ;(groups[handler.kind] ||= []).push(handler)
25
+ pushUnique(handler.kind, handler)
26
+
27
+ for (const sibling of getSiblingHandlers(handler)) {
28
+ pushUnique(sibling.kind, sibling)
29
+ }
17
30
  }
18
31
 
19
32
  return groups
@@ -31,7 +44,7 @@ export abstract class HandlersController {
31
44
  invariant(
32
45
  this.#validateHandlers(initialHandlers),
33
46
  devUtils.formatMessage(
34
- '[MSW] Failed to apply given request handlers: invalid input. Did you forget to spread the request handlers Array?',
47
+ 'Failed to apply given request handlers: invalid input. Did you forget to spread the request handlers Array?',
35
48
  ),
36
49
  )
37
50
 
@@ -69,14 +82,16 @@ export abstract class HandlersController {
69
82
  }
70
83
 
71
84
  const { handlers } = this.getState()
72
-
73
- // Iterate over next handlers and prepend them to their respective lists.
74
- // Iterate in a reverse order to the keep the order of the runtime handlers as provided.
75
- for (let i = nextHandlers.length - 1; i >= 0; i--) {
76
- const handler = nextHandlers[i]
77
- handlers[handler.kind] = handlers[handler.kind]
78
- ? [handler, ...handlers[handler.kind]!]
79
- : [handler]
85
+ const overrides = groupHandlersByKind(nextHandlers)
86
+
87
+ // Prepend overrides to their respective kind buckets so they take
88
+ // priority over existing handlers while preserving input order.
89
+ for (const kind in overrides) {
90
+ const overridesForKind = overrides[kind as AnyHandler['kind']]!
91
+ const existingForKind = handlers[kind as AnyHandler['kind']]
92
+ handlers[kind as AnyHandler['kind']] = existingForKind
93
+ ? [...overridesForKind, ...existingForKind]
94
+ : overridesForKind
80
95
  }
81
96
 
82
97
  this.setState({ handlers })
@@ -90,6 +105,12 @@ export abstract class HandlersController {
90
105
  ),
91
106
  )
92
107
 
108
+ for (const handler of this.currentHandlers()) {
109
+ if ('reset' in handler) {
110
+ handler['reset']()
111
+ }
112
+ }
113
+
93
114
  const { initialHandlers } = this.getState()
94
115
 
95
116
  if (nextHandlers.length === 0) {
@@ -108,6 +129,14 @@ export abstract class HandlersController {
108
129
  })
109
130
  }
110
131
 
132
+ public restore(): void {
133
+ for (const handler of this.currentHandlers()) {
134
+ if ('restore' in handler) {
135
+ handler['restore']()
136
+ }
137
+ }
138
+ }
139
+
111
140
  #validateHandlers(handlers: Array<AnyHandler>): boolean {
112
141
  return handlers.every((handler) => !Array.isArray(handler))
113
142
  }
@@ -1,4 +1,8 @@
1
- export { defineNetwork, DefineNetworkOptions } from './define-network'
1
+ export {
2
+ defineNetwork,
3
+ type DefineNetworkOptions,
4
+ type NetworkApi,
5
+ } from './define-network'
2
6
 
3
7
  /* Network sources */
4
8
  export { NetworkSource } from './sources/network-source'
@@ -14,3 +18,9 @@ export {
14
18
  WebSocketNetworkFrame,
15
19
  type WebSocketNetworkFrameEventMap,
16
20
  } from './frames/websocket-frame'
21
+
22
+ /* Handler controllers */
23
+ export {
24
+ HandlersController,
25
+ InMemoryHandlersController,
26
+ } from './handlers-controller'
@@ -5,10 +5,8 @@ import type {
5
5
  } from '@mswjs/interceptors/WebSocket'
6
6
  import { HttpNetworkFrame } from './frames/http-frame'
7
7
  import { WebSocketNetworkFrame } from './frames/websocket-frame'
8
- import {
9
- executeUnhandledFrameHandle,
10
- UnhandledFrameCallback,
11
- } from './on-unhandled-frame'
8
+ import type { UnhandledFrameCallback } from './on-unhandled-frame'
9
+ import { executeUnhandledFrameHandle } from './on-unhandled-frame'
12
10
 
13
11
  beforeAll(() => {
14
12
  vi.spyOn(console, 'warn').mockImplementation(() => void 0)
@@ -1,9 +1,9 @@
1
1
  import { type DefaultEventMap, Emitter } from 'rettime'
2
- import { LifeCycleEventEmitter } from '../sharedOptions'
2
+ import { type LifeCycleEventEmitter } from '../sharedOptions'
3
+ import type { HandlersController } from './handlers-controller'
3
4
  import {
4
- AnyHandler,
5
- HandlersController,
6
5
  InMemoryHandlersController,
6
+ type AnyHandler,
7
7
  } from './handlers-controller'
8
8
  import { Disposable } from '../utils/internal/Disposable'
9
9
  import { toReadonlyArray } from '../utils/internal/toReadonlyArray'
@@ -42,11 +42,7 @@ export abstract class SetupApi<
42
42
  }
43
43
 
44
44
  public restoreHandlers(): void {
45
- this.handlersController.currentHandlers().forEach((handler) => {
46
- if ('isUsed' in handler) {
47
- handler.isUsed = false
48
- }
49
- })
45
+ this.handlersController.restore()
50
46
  }
51
47
 
52
48
  public resetHandlers(...nextHandlers: Array<AnyHandler>): void {
@@ -1,9 +1,5 @@
1
- import {
2
- BatchInterceptor,
3
- Interceptor,
4
- RequestController,
5
- type HttpRequestEventMap,
6
- } from '@mswjs/interceptors'
1
+ import type { Interceptor, RequestController } from '@mswjs/interceptors'
2
+ import { BatchInterceptor, type HttpRequestEventMap } from '@mswjs/interceptors'
7
3
  import type {
8
4
  WebSocketConnectionData,
9
5
  WebSocketEventMap,
@@ -91,16 +87,26 @@ export class InterceptorSource extends NetworkSource {
91
87
  }
92
88
 
93
89
  queueMicrotask(() => {
94
- httpFrame.events.emit(
95
- new ResponseEvent(
96
- isMockedResponse ? 'response:mocked' : 'response:bypass',
97
- {
98
- requestId,
99
- request,
100
- response,
101
- },
102
- ),
103
- )
90
+ try {
91
+ httpFrame.events.emit(
92
+ new ResponseEvent(
93
+ isMockedResponse ? 'response:mocked' : 'response:bypass',
94
+ {
95
+ requestId,
96
+ request,
97
+ response,
98
+ },
99
+ ),
100
+ )
101
+ } finally {
102
+ /**
103
+ * @note Remove any listeners from this frame.
104
+ * Past this point, it won't emit anything. The removal is crucial
105
+ * to prevent "rettime" from keeping the abort cleanup listeners internally.
106
+ * @see https://github.com/mswjs/msw/issues/2735
107
+ */
108
+ httpFrame.events.removeAllListeners()
109
+ }
104
110
  })
105
111
  }
106
112
 
@@ -157,6 +163,20 @@ class InterceptorHttpNetworkFrame extends HttpNetworkFrame {
157
163
  class InterceptorWebSocketNetworkFrame extends WebSocketNetworkFrame {
158
164
  constructor(args: { connection: WebSocketConnectionData }) {
159
165
  super({ connection: args.connection })
166
+
167
+ /**
168
+ * @note Provide a similar frame listener cleanup as for HTTP.
169
+ * When the client connection closes, the handler can no longer be used.
170
+ */
171
+ args.connection.client.addEventListener(
172
+ 'close',
173
+ () => {
174
+ this.events.removeAllListeners()
175
+ },
176
+ {
177
+ once: true,
178
+ },
179
+ )
160
180
  }
161
181
 
162
182
  public errorWith(reason?: unknown): void {
@@ -44,7 +44,7 @@ export abstract class NetworkSource<
44
44
 
45
45
  public on<Type extends keyof NetworkSourceEventMap<Frame>>(
46
46
  type: Type,
47
- listener: Emitter.ListenerType<typeof this.emitter, Type>,
47
+ listener: Emitter.Listener<typeof this.emitter, Type>,
48
48
  options?: TypedListenerOptions,
49
49
  ): void {
50
50
  this.emitter.on(type, listener, options)