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.6.4 '
12- const INTEGRITY_CHECKSUM = 'ca7800994cc8bfb5eb961e037c877074 '
10+ const PACKAGE_VERSION = '2.11.2 '
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,16 @@ 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+ * @returns {Promise<Response> }
209+ */
210+ async function getResponse ( event , client , requestId , requestInterceptedAt ) {
190211 // Clone the request because it might've been already used
191212 // (i.e. its body has been read and sent to the client).
192- const requestClone = request . clone ( )
213+ const requestClone = event . request . clone ( )
193214
194215 function passthrough ( ) {
195216 // Cast the request headers to a new Headers instance
@@ -199,7 +220,19 @@ async function getResponse(event, client, requestId) {
199220 // Remove the "accept" header value that marked this request as passthrough.
200221 // This prevents request alteration and also keeps it compliant with the
201222 // user-defined CORS policies.
202- headers . delete ( 'accept' , 'msw/passthrough' )
223+ const acceptHeader = headers . get ( 'accept' )
224+ if ( acceptHeader ) {
225+ const values = acceptHeader . split ( ',' ) . map ( ( value ) => value . trim ( ) )
226+ const filteredValues = values . filter (
227+ ( value ) => value !== 'msw/passthrough' ,
228+ )
229+
230+ if ( filteredValues . length > 0 ) {
231+ headers . set ( 'accept' , filteredValues . join ( ', ' ) )
232+ } else {
233+ headers . delete ( 'accept' )
234+ }
235+ }
203236
204237 return fetch ( requestClone , { headers } )
205238 }
@@ -218,29 +251,18 @@ async function getResponse(event, client, requestId) {
218251 }
219252
220253 // Notify the client that a request has been intercepted.
221- const requestBuffer = await request . arrayBuffer ( )
254+ const serializedRequest = await serializeRequest ( event . request )
222255 const clientMessage = await sendToClient (
223256 client ,
224257 {
225258 type : 'REQUEST' ,
226259 payload : {
227260 id : requestId ,
228- url : request . url ,
229- mode : request . mode ,
230- method : request . method ,
231- headers : Object . fromEntries ( request . headers . entries ( ) ) ,
232- cache : request . cache ,
233- credentials : request . credentials ,
234- destination : request . destination ,
235- integrity : request . integrity ,
236- redirect : request . redirect ,
237- referrer : request . referrer ,
238- referrerPolicy : request . referrerPolicy ,
239- body : requestBuffer ,
240- keepalive : request . keepalive ,
261+ interceptedAt : requestInterceptedAt ,
262+ ...serializedRequest ,
241263 } ,
242264 } ,
243- [ requestBuffer ] ,
265+ [ serializedRequest . body ] ,
244266 )
245267
246268 switch ( clientMessage . type ) {
@@ -256,6 +278,12 @@ async function getResponse(event, client, requestId) {
256278 return passthrough ( )
257279}
258280
281+ /**
282+ * @param {Client } client
283+ * @param {any } message
284+ * @param {Array<Transferable> } transferrables
285+ * @returns {Promise<any> }
286+ */
259287function sendToClient ( client , message , transferrables = [ ] ) {
260288 return new Promise ( ( resolve , reject ) => {
261289 const channel = new MessageChannel ( )
@@ -268,14 +296,18 @@ function sendToClient(client, message, transferrables = []) {
268296 resolve ( event . data )
269297 }
270298
271- client . postMessage (
272- message ,
273- [ channel . port2 ] . concat ( transferrables . filter ( Boolean ) ) ,
274- )
299+ client . postMessage ( message , [
300+ channel . port2 ,
301+ ... transferrables . filter ( Boolean ) ,
302+ ] )
275303 } )
276304}
277305
278- async function respondWithMock ( response ) {
306+ /**
307+ * @param {Response } response
308+ * @returns {Response }
309+ */
310+ function respondWithMock ( response ) {
279311 // Setting response status code to 0 is a no-op.
280312 // However, when responding with a "Response.error()", the produced Response
281313 // instance will have status code set to 0. Since it's not possible to create
@@ -293,3 +325,24 @@ async function respondWithMock(response) {
293325
294326 return mockedResponse
295327}
328+
329+ /**
330+ * @param {Request } request
331+ */
332+ async function serializeRequest ( request ) {
333+ return {
334+ url : request . url ,
335+ mode : request . mode ,
336+ method : request . method ,
337+ headers : Object . fromEntries ( request . headers . entries ( ) ) ,
338+ cache : request . cache ,
339+ credentials : request . credentials ,
340+ destination : request . destination ,
341+ integrity : request . integrity ,
342+ redirect : request . redirect ,
343+ referrer : request . referrer ,
344+ referrerPolicy : request . referrerPolicy ,
345+ body : await request . arrayBuffer ( ) ,
346+ keepalive : request . keepalive ,
347+ }
348+ }
0 commit comments