55 * Mock Service Worker.
66 * @see https://github.com/mswjs/msw
77 * - Please do NOT modify this file.
8- * - Please do NOT serve this file on production.
98 */
109
11- const PACKAGE_VERSION = '2.8.0 '
12- const INTEGRITY_CHECKSUM = '00729d72e3b82faf54ca8b9621dbb96f '
10+ const PACKAGE_VERSION = '2.12.3 '
11+ const INTEGRITY_CHECKSUM = '4db4a41e972cec1b64cc569c66952d82 '
1312const IS_MOCKED_RESPONSE = Symbol ( 'isMockedResponse' )
1413const activeClientIds = new Set ( )
1514
16- self . addEventListener ( 'install' , function ( ) {
15+ addEventListener ( 'install' , function ( ) {
1716 self . skipWaiting ( )
1817} )
1918
20- self . addEventListener ( 'activate' , function ( event ) {
19+ addEventListener ( 'activate' , function ( event ) {
2120 event . waitUntil ( self . clients . claim ( ) )
2221} )
2322
24- self . addEventListener ( 'message' , async function ( event ) {
25- const clientId = event . source . id
23+ addEventListener ( 'message' , async function ( event ) {
24+ const clientId = Reflect . get ( event . source || { } , 'id' )
2625
2726 if ( ! clientId || ! self . clients ) {
2827 return
@@ -72,11 +71,6 @@ self.addEventListener('message', async function (event) {
7271 break
7372 }
7473
75- case 'MOCK_DEACTIVATE' : {
76- activeClientIds . delete ( clientId )
77- break
78- }
79-
8074 case 'CLIENT_CLOSED' : {
8175 activeClientIds . delete ( clientId )
8276
@@ -94,69 +88,92 @@ self.addEventListener('message', async function (event) {
9488 }
9589} )
9690
97- self . addEventListener ( 'fetch' , function ( event ) {
98- const { request } = event
91+ addEventListener ( 'fetch' , function ( event ) {
92+ const requestInterceptedAt = Date . now ( )
9993
10094 // Bypass navigation requests.
101- if ( request . mode === 'navigate' ) {
95+ if ( event . request . mode === 'navigate' ) {
10296 return
10397 }
10498
10599 // Opening the DevTools triggers the "only-if-cached" request
106100 // that cannot be handled by the worker. Bypass such requests.
107- if ( request . cache === 'only-if-cached' && request . mode !== 'same-origin' ) {
101+ if (
102+ event . request . cache === 'only-if-cached' &&
103+ event . request . mode !== 'same-origin'
104+ ) {
108105 return
109106 }
110107
111108 // Bypass all requests when there are no active clients.
112109 // Prevents the self-unregistered worked from handling requests
113- // after it's been deleted (still remains active until the next reload).
110+ // after it's been terminated (still remains active until the next reload).
114111 if ( activeClientIds . size === 0 ) {
115112 return
116113 }
117114
118- // Generate unique request ID.
119115 const requestId = crypto . randomUUID ( )
120- event . respondWith ( handleRequest ( event , requestId ) )
116+ event . respondWith ( handleRequest ( event , requestId , requestInterceptedAt ) )
121117} )
122118
123- async function handleRequest ( event , requestId ) {
119+ /**
120+ * @param {FetchEvent } event
121+ * @param {string } requestId
122+ * @param {number } requestInterceptedAt
123+ */
124+ async function handleRequest ( event , requestId , requestInterceptedAt ) {
124125 const client = await resolveMainClient ( event )
125- const response = await getResponse ( event , client , requestId )
126+ const requestCloneForEvents = event . request . clone ( )
127+ const response = await getResponse (
128+ event ,
129+ client ,
130+ requestId ,
131+ requestInterceptedAt ,
132+ )
126133
127134 // Send back the response clone for the "response:*" life-cycle events.
128135 // Ensure MSW is active and ready to handle the message, otherwise
129136 // this message will pend indefinitely.
130137 if ( client && activeClientIds . has ( client . id ) ) {
131- ; ( async function ( ) {
132- const responseClone = response . clone ( )
133-
134- sendToClient (
135- client ,
136- {
137- type : 'RESPONSE' ,
138- payload : {
139- requestId,
140- isMockedResponse : IS_MOCKED_RESPONSE in response ,
138+ const serializedRequest = await serializeRequest ( requestCloneForEvents )
139+
140+ // Clone the response so both the client and the library could consume it.
141+ const responseClone = response . clone ( )
142+
143+ sendToClient (
144+ client ,
145+ {
146+ type : 'RESPONSE' ,
147+ payload : {
148+ isMockedResponse : IS_MOCKED_RESPONSE in response ,
149+ request : {
150+ id : requestId ,
151+ ...serializedRequest ,
152+ } ,
153+ response : {
141154 type : responseClone . type ,
142155 status : responseClone . status ,
143156 statusText : responseClone . statusText ,
144- body : responseClone . body ,
145157 headers : Object . fromEntries ( responseClone . headers . entries ( ) ) ,
158+ body : responseClone . body ,
146159 } ,
147160 } ,
148- [ responseClone . body ] ,
149- )
150- } ) ( )
161+ } ,
162+ responseClone . body ? [ serializedRequest . body , responseClone . body ] : [ ] ,
163+ )
151164 }
152165
153166 return response
154167}
155168
156- // Resolve the main client for the given event.
157- // Client that issues a request doesn't necessarily equal the client
158- // that registered the worker. It's with the latter the worker should
159- // communicate with during the response resolving phase.
169+ /**
170+ * Resolve the main client for the given event.
171+ * Client that issues a request doesn't necessarily equal the client
172+ * that registered the worker. It's with the latter the worker should
173+ * communicate with during the response resolving phase.
174+ * @param {FetchEvent } event
175+ * @returns {Promise<Client | undefined> }
176+ */
160177async function resolveMainClient ( event ) {
161178 const client = await self . clients . get ( event . clientId )
162179
@@ -184,12 +201,17 @@ async function resolveMainClient(event) {
184201 } )
185202}
186203
187- async function getResponse ( event , client , requestId ) {
188- const { request } = event
189-
204+ /**
205+ * @param {FetchEvent } event
206+ * @param {Client | undefined } client
207+ * @param {string } requestId
208+ * @param {number } requestInterceptedAt
209+ * @returns {Promise<Response> }
210+ */
211+ async function getResponse ( event , client , requestId , requestInterceptedAt ) {
190212 // Clone the request because it might've been already used
191213 // (i.e. its body has been read and sent to the client).
192- const requestClone = request . clone ( )
214+ const requestClone = event . request . clone ( )
193215
194216 function passthrough ( ) {
195217 // Cast the request headers to a new Headers instance
@@ -230,29 +252,18 @@ async function getResponse(event, client, requestId) {
230252 }
231253
232254 // Notify the client that a request has been intercepted.
233- const requestBuffer = await request . arrayBuffer ( )
255+ const serializedRequest = await serializeRequest ( event . request )
234256 const clientMessage = await sendToClient (
235257 client ,
236258 {
237259 type : 'REQUEST' ,
238260 payload : {
239261 id : requestId ,
240- url : request . url ,
241- mode : request . mode ,
242- method : request . method ,
243- headers : Object . fromEntries ( request . headers . entries ( ) ) ,
244- cache : request . cache ,
245- credentials : request . credentials ,
246- destination : request . destination ,
247- integrity : request . integrity ,
248- redirect : request . redirect ,
249- referrer : request . referrer ,
250- referrerPolicy : request . referrerPolicy ,
251- body : requestBuffer ,
252- keepalive : request . keepalive ,
262+ interceptedAt : requestInterceptedAt ,
263+ ...serializedRequest ,
253264 } ,
254265 } ,
255- [ requestBuffer ] ,
266+ [ serializedRequest . body ] ,
256267 )
257268
258269 switch ( clientMessage . type ) {
@@ -268,6 +279,12 @@ async function getResponse(event, client, requestId) {
268279 return passthrough ( )
269280}
270281
282+ /**
283+ * @param {Client } client
284+ * @param {any } message
285+ * @param {Array<Transferable> } transferrables
286+ * @returns {Promise<any> }
287+ */
271288function sendToClient ( client , message , transferrables = [ ] ) {
272289 return new Promise ( ( resolve , reject ) => {
273290 const channel = new MessageChannel ( )
@@ -280,14 +297,18 @@ function sendToClient(client, message, transferrables = []) {
280297 resolve ( event . data )
281298 }
282299
283- client . postMessage (
284- message ,
285- [ channel . port2 ] . concat ( transferrables . filter ( Boolean ) ) ,
286- )
300+ client . postMessage ( message , [
301+ channel . port2 ,
302+ ... transferrables . filter ( Boolean ) ,
303+ ] )
287304 } )
288305}
289306
290- async function respondWithMock ( response ) {
307+ /**
308+ * @param {Response } response
309+ * @returns {Response }
310+ */
311+ function respondWithMock ( response ) {
291312 // Setting response status code to 0 is a no-op.
292313 // However, when responding with a "Response.error()", the produced Response
293314 // instance will have status code set to 0. Since it's not possible to create
@@ -305,3 +326,24 @@ async function respondWithMock(response) {
305326
306327 return mockedResponse
307328}
329+
330+ /**
331+ * @param {Request } request
332+ */
333+ async function serializeRequest ( request ) {
334+ return {
335+ url : request . url ,
336+ mode : request . mode ,
337+ method : request . method ,
338+ headers : Object . fromEntries ( request . headers . entries ( ) ) ,
339+ cache : request . cache ,
340+ credentials : request . credentials ,
341+ destination : request . destination ,
342+ integrity : request . integrity ,
343+ redirect : request . redirect ,
344+ referrer : request . referrer ,
345+ referrerPolicy : request . referrerPolicy ,
346+ body : await request . arrayBuffer ( ) ,
347+ keepalive : request . keepalive ,
348+ }
349+ }
0 commit comments