msw 2.11.1 → 2.11.2

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 (65) hide show
  1. package/lib/browser/index.d.mts +0 -3
  2. package/lib/browser/index.d.ts +0 -3
  3. package/lib/browser/index.js +503 -294
  4. package/lib/browser/index.js.map +1 -1
  5. package/lib/browser/index.mjs +503 -294
  6. package/lib/browser/index.mjs.map +1 -1
  7. package/lib/core/handlers/GraphQLHandler.js.map +1 -1
  8. package/lib/core/handlers/GraphQLHandler.mjs.map +1 -1
  9. package/lib/core/handlers/HttpHandler.js.map +1 -1
  10. package/lib/core/handlers/HttpHandler.mjs.map +1 -1
  11. package/lib/core/utils/internal/devUtils.js.map +1 -1
  12. package/lib/core/utils/internal/devUtils.mjs.map +1 -1
  13. package/lib/core/utils/internal/getCallFrame.js +2 -2
  14. package/lib/core/utils/internal/getCallFrame.js.map +1 -1
  15. package/lib/core/utils/internal/getCallFrame.mjs +2 -2
  16. package/lib/core/utils/internal/getCallFrame.mjs.map +1 -1
  17. package/lib/core/utils/internal/parseGraphQLRequest.js +1 -0
  18. package/lib/core/utils/internal/parseGraphQLRequest.js.map +1 -1
  19. package/lib/core/utils/internal/parseGraphQLRequest.mjs +1 -0
  20. package/lib/core/utils/internal/parseGraphQLRequest.mjs.map +1 -1
  21. package/lib/core/utils/matching/matchRequestUrl.js +1 -1
  22. package/lib/core/utils/matching/matchRequestUrl.js.map +1 -1
  23. package/lib/core/utils/matching/matchRequestUrl.mjs +1 -1
  24. package/lib/core/utils/matching/matchRequestUrl.mjs.map +1 -1
  25. package/lib/core/utils/url/cleanUrl.js +1 -1
  26. package/lib/core/utils/url/cleanUrl.js.map +1 -1
  27. package/lib/core/utils/url/cleanUrl.mjs +1 -1
  28. package/lib/core/utils/url/cleanUrl.mjs.map +1 -1
  29. package/lib/core/utils/url/isAbsoluteUrl.js +1 -1
  30. package/lib/core/utils/url/isAbsoluteUrl.js.map +1 -1
  31. package/lib/core/utils/url/isAbsoluteUrl.mjs +1 -1
  32. package/lib/core/utils/url/isAbsoluteUrl.mjs.map +1 -1
  33. package/lib/core/ws/WebSocketIndexedDBClientStore.js.map +1 -1
  34. package/lib/core/ws/WebSocketIndexedDBClientStore.mjs.map +1 -1
  35. package/lib/core/ws/utils/attachWebSocketLogger.js.map +1 -1
  36. package/lib/core/ws/utils/attachWebSocketLogger.mjs.map +1 -1
  37. package/lib/iife/index.js +2494 -2281
  38. package/lib/iife/index.js.map +1 -1
  39. package/lib/mockServiceWorker.js +16 -12
  40. package/package.json +20 -13
  41. package/src/browser/setupWorker/glossary.ts +9 -114
  42. package/src/browser/setupWorker/setupWorker.ts +82 -119
  43. package/src/browser/setupWorker/start/createRequestListener.ts +20 -24
  44. package/src/browser/setupWorker/start/createResponseListener.ts +15 -22
  45. package/src/browser/setupWorker/start/createStartHandler.ts +24 -18
  46. package/src/browser/setupWorker/start/utils/enableMocking.ts +18 -21
  47. package/src/browser/setupWorker/start/utils/printStartMessage.ts +0 -2
  48. package/src/browser/utils/checkWorkerIntegrity.ts +22 -14
  49. package/src/browser/utils/workerChannel.ts +146 -0
  50. package/src/core/handlers/GraphQLHandler.ts +0 -3
  51. package/src/core/handlers/HttpHandler.ts +0 -2
  52. package/src/core/utils/internal/devUtils.ts +0 -2
  53. package/src/core/utils/internal/getCallFrame.ts +2 -2
  54. package/src/core/utils/internal/parseGraphQLRequest.ts +1 -0
  55. package/src/core/utils/matching/matchRequestUrl.ts +2 -2
  56. package/src/core/utils/request/onUnhandledRequest.test.ts +1 -1
  57. package/src/core/utils/url/cleanUrl.ts +1 -1
  58. package/src/core/utils/url/isAbsoluteUrl.ts +1 -1
  59. package/src/core/ws/WebSocketIndexedDBClientStore.ts +0 -4
  60. package/src/core/ws/utils/attachWebSocketLogger.ts +0 -14
  61. package/src/mockServiceWorker.js +14 -10
  62. package/src/browser/setupWorker/start/createFallbackStart.ts +0 -21
  63. package/src/browser/setupWorker/start/utils/createMessageChannel.ts +0 -32
  64. package/src/browser/setupWorker/stop/createFallbackStop.ts +0 -11
  65. package/src/browser/setupWorker/stop/createStop.ts +0 -35
@@ -97,8 +97,23 @@ function isNodeProcess() {
97
97
  return false;
98
98
  }
99
99
 
100
+ // src/browser/setupWorker/start/utils/prepareStartHandler.ts
101
+ import { mergeRight } from '../core/utils/internal/mergeRight.mjs';
102
+ var DEFAULT_START_OPTIONS = {
103
+ serviceWorker: {
104
+ url: "/mockServiceWorker.js",
105
+ options: null
106
+ },
107
+ quiet: false,
108
+ waitUntilReady: true,
109
+ onUnhandledRequest: "warn",
110
+ findWorker(scriptURL, mockServiceWorkerUrl) {
111
+ return scriptURL === mockServiceWorkerUrl;
112
+ }
113
+ };
114
+
100
115
  // src/browser/setupWorker/start/createStartHandler.ts
101
- import { devUtils as devUtils7 } from '../core/utils/internal/devUtils.mjs';
116
+ import { devUtils as devUtils6 } from '../core/utils/internal/devUtils.mjs';
102
117
 
103
118
  // node_modules/.pnpm/@open-draft+until@2.1.0/node_modules/@open-draft/until/lib/index.mjs
104
119
  var until = async (promise) => {
@@ -192,8 +207,71 @@ Learn more about creating the Service Worker script: https://mswjs.io/docs/cli/i
192
207
  return registrationResult.data;
193
208
  };
194
209
 
195
- // src/browser/setupWorker/start/utils/enableMocking.ts
196
- import { devUtils as devUtils3 } from '../core/utils/internal/devUtils.mjs';
210
+ // node_modules/.pnpm/@open-draft+deferred-promise@2.2.0/node_modules/@open-draft/deferred-promise/build/index.mjs
211
+ function createDeferredExecutor() {
212
+ const executor = (resolve, reject) => {
213
+ executor.state = "pending";
214
+ executor.resolve = (data) => {
215
+ if (executor.state !== "pending") {
216
+ return;
217
+ }
218
+ executor.result = data;
219
+ const onFulfilled = (value) => {
220
+ executor.state = "fulfilled";
221
+ return value;
222
+ };
223
+ return resolve(
224
+ data instanceof Promise ? data : Promise.resolve(data).then(onFulfilled)
225
+ );
226
+ };
227
+ executor.reject = (reason) => {
228
+ if (executor.state !== "pending") {
229
+ return;
230
+ }
231
+ queueMicrotask(() => {
232
+ executor.state = "rejected";
233
+ });
234
+ return reject(executor.rejectionReason = reason);
235
+ };
236
+ };
237
+ return executor;
238
+ }
239
+ var DeferredPromise = class extends Promise {
240
+ #executor;
241
+ resolve;
242
+ reject;
243
+ constructor(executor = null) {
244
+ const deferredExecutor = createDeferredExecutor();
245
+ super((originalResolve, originalReject) => {
246
+ deferredExecutor(originalResolve, originalReject);
247
+ executor?.(deferredExecutor.resolve, deferredExecutor.reject);
248
+ });
249
+ this.#executor = deferredExecutor;
250
+ this.resolve = this.#executor.resolve;
251
+ this.reject = this.#executor.reject;
252
+ }
253
+ get state() {
254
+ return this.#executor.state;
255
+ }
256
+ get rejectionReason() {
257
+ return this.#executor.rejectionReason;
258
+ }
259
+ then(onFulfilled, onRejected) {
260
+ return this.#decorate(super.then(onFulfilled, onRejected));
261
+ }
262
+ catch(onRejected) {
263
+ return this.#decorate(super.catch(onRejected));
264
+ }
265
+ finally(onfinally) {
266
+ return this.#decorate(super.finally(onfinally));
267
+ }
268
+ #decorate(promise) {
269
+ return Object.defineProperties(promise, {
270
+ resolve: { configurable: true, value: this.resolve },
271
+ reject: { configurable: true, value: this.reject }
272
+ });
273
+ }
274
+ };
197
275
 
198
276
  // src/browser/setupWorker/start/utils/printStartMessage.ts
199
277
  import { devUtils as devUtils2 } from '../core/utils/internal/devUtils.mjs';
@@ -225,35 +303,23 @@ function printStartMessage(args = {}) {
225
303
  }
226
304
 
227
305
  // src/browser/setupWorker/start/utils/enableMocking.ts
228
- async function enableMocking(context, options) {
229
- context.workerChannel.send("MOCK_ACTIVATE");
230
- const { payload } = await context.events.once("MOCKING_ENABLED");
231
- if (context.isMockingEnabled) {
232
- devUtils3.warn(
233
- `Found a redundant "worker.start()" call. Note that starting the worker while mocking is already enabled will have no effect. Consider removing this "worker.start()" call.`
234
- );
235
- return;
236
- }
237
- context.isMockingEnabled = true;
238
- printStartMessage({
239
- quiet: options.quiet,
240
- workerScope: context.registration?.scope,
241
- workerUrl: context.worker?.scriptURL,
242
- client: payload.client
306
+ function enableMocking(context, options) {
307
+ const mockingEnabledPromise = new DeferredPromise();
308
+ context.workerChannel.postMessage("MOCK_ACTIVATE");
309
+ context.workerChannel.once("MOCKING_ENABLED", async (event) => {
310
+ context.isMockingEnabled = true;
311
+ const worker = await context.workerPromise;
312
+ printStartMessage({
313
+ quiet: options.quiet,
314
+ workerScope: context.registration?.scope,
315
+ workerUrl: worker.scriptURL,
316
+ client: event.data.client
317
+ });
318
+ mockingEnabledPromise.resolve(true);
243
319
  });
320
+ return mockingEnabledPromise;
244
321
  }
245
322
 
246
- // src/browser/setupWorker/start/utils/createMessageChannel.ts
247
- var WorkerChannel = class {
248
- constructor(port) {
249
- this.port = port;
250
- }
251
- postMessage(event, ...rest) {
252
- const [data, transfer] = rest;
253
- this.port.postMessage({ type: event, data }, { transfer });
254
- }
255
- };
256
-
257
323
  // src/browser/utils/pruneGetRequestBody.ts
258
324
  function pruneGetRequestBody(request) {
259
325
  if (["HEAD", "GET"].includes(request.method)) {
@@ -273,14 +339,17 @@ function deserializeRequest(serializedRequest) {
273
339
  // src/browser/setupWorker/start/createRequestListener.ts
274
340
  import { RequestHandler } from '../core/handlers/RequestHandler.mjs';
275
341
  import { handleRequest } from '../core/utils/handleRequest.mjs';
276
- import { devUtils as devUtils4 } from '../core/utils/internal/devUtils.mjs';
342
+ import { devUtils as devUtils3 } from '../core/utils/internal/devUtils.mjs';
277
343
  import { toResponseInit } from '../core/utils/toResponseInit.mjs';
278
344
  import { isHandlerKind } from '../core/utils/internal/isHandlerKind.mjs';
279
345
  var createRequestListener = (context, options) => {
280
- return async (event, message) => {
281
- const messageChannel = new WorkerChannel(event.ports[0]);
282
- const requestId = message.payload.id;
283
- const request = deserializeRequest(message.payload);
346
+ return async (event) => {
347
+ if (!context.isMockingEnabled && context.workerStoppedAt && event.data.interceptedAt > context.workerStoppedAt) {
348
+ event.postMessage("PASSTHROUGH");
349
+ return;
350
+ }
351
+ const requestId = event.data.id;
352
+ const request = deserializeRequest(event.data);
284
353
  const requestCloneForLogs = request.clone();
285
354
  const requestClone = request.clone();
286
355
  RequestHandler.cache.set(request, requestClone);
@@ -293,7 +362,7 @@ var createRequestListener = (context, options) => {
293
362
  context.emitter,
294
363
  {
295
364
  onPassthroughResponse() {
296
- messageChannel.postMessage("PASSTHROUGH");
365
+ event.postMessage("PASSTHROUGH");
297
366
  },
298
367
  async onMockedResponse(response, { handler, parsedResult }) {
299
368
  const responseClone = response.clone();
@@ -301,7 +370,7 @@ var createRequestListener = (context, options) => {
301
370
  const responseInit = toResponseInit(response);
302
371
  if (context.supports.readableStreamTransfer) {
303
372
  const responseStreamOrNull = response.body;
304
- messageChannel.postMessage(
373
+ event.postMessage(
305
374
  "MOCK_RESPONSE",
306
375
  {
307
376
  ...responseInit,
@@ -311,7 +380,7 @@ var createRequestListener = (context, options) => {
311
380
  );
312
381
  } else {
313
382
  const responseBufferOrNull = response.body === null ? null : await responseClone.arrayBuffer();
314
- messageChannel.postMessage("MOCK_RESPONSE", {
383
+ event.postMessage("MOCK_RESPONSE", {
315
384
  ...responseInit,
316
385
  body: responseBufferOrNull
317
386
  });
@@ -330,7 +399,7 @@ var createRequestListener = (context, options) => {
330
399
  );
331
400
  } catch (error2) {
332
401
  if (error2 instanceof Error) {
333
- devUtils4.error(
402
+ devUtils3.error(
334
403
  `Uncaught exception in the request handler for "%s %s":
335
404
 
336
405
  %s
@@ -340,7 +409,7 @@ This exception has been gracefully handled as a 500 response, however, it's stro
340
409
  request.url,
341
410
  error2.stack ?? error2
342
411
  );
343
- messageChannel.postMessage("MOCK_RESPONSE", {
412
+ event.postMessage("MOCK_RESPONSE", {
344
413
  status: 500,
345
414
  statusText: "Request Handler Error",
346
415
  headers: {
@@ -358,21 +427,26 @@ This exception has been gracefully handled as a 500 response, however, it's stro
358
427
  };
359
428
 
360
429
  // src/browser/utils/checkWorkerIntegrity.ts
361
- import { devUtils as devUtils5 } from '../core/utils/internal/devUtils.mjs';
362
- async function checkWorkerIntegrity(context) {
363
- context.workerChannel.send("INTEGRITY_CHECK_REQUEST");
364
- const { payload } = await context.events.once("INTEGRITY_CHECK_RESPONSE");
365
- if (payload.checksum !== "f5825c521429caf22a4dd13b66e243af") {
366
- devUtils5.warn(
367
- `The currently registered Service Worker has been generated by a different version of MSW (${payload.packageVersion}) and may not be fully compatible with the installed version.
430
+ import { devUtils as devUtils4 } from '../core/utils/internal/devUtils.mjs';
431
+ function checkWorkerIntegrity(context) {
432
+ const integrityCheckPromise = new DeferredPromise();
433
+ context.workerChannel.postMessage("INTEGRITY_CHECK_REQUEST");
434
+ context.workerChannel.once("INTEGRITY_CHECK_RESPONSE", (event) => {
435
+ const { checksum, packageVersion } = event.data;
436
+ if (checksum !== "4db4a41e972cec1b64cc569c66952d82") {
437
+ devUtils4.warn(
438
+ `The currently registered Service Worker has been generated by a different version of MSW (${packageVersion}) and may not be fully compatible with the installed version.
368
439
 
369
440
  It's recommended you update your worker script by running this command:
370
441
 
371
442
  \u2022 npx msw init <PUBLIC_DIR>
372
443
 
373
444
  You can also automate this process and make the worker script update automatically upon the library installations. Read more: https://mswjs.io/docs/cli/init.`
374
- );
375
- }
445
+ );
446
+ }
447
+ integrityCheckPromise.resolve();
448
+ });
449
+ return integrityCheckPromise;
376
450
  }
377
451
 
378
452
  // node_modules/.pnpm/@mswjs+interceptors@0.39.1/node_modules/@mswjs/interceptors/lib/browser/chunk-6HYIRFX2.mjs
@@ -1115,22 +1189,22 @@ var BatchInterceptor = class extends Interceptor {
1115
1189
 
1116
1190
  // src/browser/setupWorker/start/createResponseListener.ts
1117
1191
  function createResponseListener(context) {
1118
- return (_, message) => {
1119
- const { payload: responseJson } = message;
1120
- const request = deserializeRequest(responseJson.request);
1121
- if (responseJson.response.type?.includes("opaque")) {
1192
+ return (event) => {
1193
+ const responseMessage = event.data;
1194
+ const request = deserializeRequest(responseMessage.request);
1195
+ if (responseMessage.response.type?.includes("opaque")) {
1122
1196
  return;
1123
1197
  }
1124
- const response = responseJson.response.status === 0 ? Response.error() : new FetchResponse(
1198
+ const response = responseMessage.response.status === 0 ? Response.error() : new FetchResponse(
1125
1199
  /**
1126
1200
  * Responses may be streams here, but when we create a response object
1127
1201
  * with null-body status codes, like 204, 205, 304 Response will
1128
1202
  * throw when passed a non-null body, so ensure it's null here
1129
1203
  * for those codes
1130
1204
  */
1131
- FetchResponse.isResponseWithBody(responseJson.response.status) ? responseJson.response.body : null,
1205
+ FetchResponse.isResponseWithBody(responseMessage.response.status) ? responseMessage.response.body : null,
1132
1206
  {
1133
- ...responseJson,
1207
+ ...responseMessage,
1134
1208
  /**
1135
1209
  * Set response URL if it's not set already.
1136
1210
  * @see https://github.com/mswjs/msw/issues/2030
@@ -1140,9 +1214,9 @@ function createResponseListener(context) {
1140
1214
  }
1141
1215
  );
1142
1216
  context.emitter.emit(
1143
- responseJson.isMockedResponse ? "response:mocked" : "response:bypass",
1217
+ responseMessage.isMockedResponse ? "response:mocked" : "response:bypass",
1144
1218
  {
1145
- requestId: responseJson.request.id,
1219
+ requestId: responseMessage.request.id,
1146
1220
  request,
1147
1221
  response
1148
1222
  }
@@ -1151,10 +1225,10 @@ function createResponseListener(context) {
1151
1225
  }
1152
1226
 
1153
1227
  // src/browser/setupWorker/start/utils/validateWorkerScope.ts
1154
- import { devUtils as devUtils6 } from '../core/utils/internal/devUtils.mjs';
1228
+ import { devUtils as devUtils5 } from '../core/utils/internal/devUtils.mjs';
1155
1229
  function validateWorkerScope(registration, options) {
1156
1230
  if (!options?.quiet && !location.href.startsWith(registration.scope)) {
1157
- devUtils6.warn(
1231
+ devUtils5.warn(
1158
1232
  `Cannot intercept requests on this page because it's outside of the worker's scope ("${registration.scope}"). If you wish to mock API requests on this page, you must resolve this scope issue.
1159
1233
 
1160
1234
  - (Recommended) Register the worker at the root level ("/") of your application.
@@ -1167,7 +1241,7 @@ function validateWorkerScope(registration, options) {
1167
1241
  var createStartHandler = (context) => {
1168
1242
  return function start(options, customOptions) {
1169
1243
  const startWorkerInstance = async () => {
1170
- context.events.removeAllListeners();
1244
+ context.workerChannel.removeAllListeners();
1171
1245
  context.workerChannel.on(
1172
1246
  "REQUEST",
1173
1247
  createRequestListener(context, options)
@@ -1180,14 +1254,14 @@ var createStartHandler = (context) => {
1180
1254
  );
1181
1255
  const [worker, registration] = instance;
1182
1256
  if (!worker) {
1183
- const missingWorkerMessage = customOptions?.findWorker ? devUtils7.formatMessage(
1257
+ const missingWorkerMessage = customOptions?.findWorker ? devUtils6.formatMessage(
1184
1258
  `Failed to locate the Service Worker registration using a custom "findWorker" predicate.
1185
1259
 
1186
1260
  Please ensure that the custom predicate properly locates the Service Worker registration at "%s".
1187
1261
  More details: https://mswjs.io/docs/api/setup-worker/start#findworker
1188
1262
  `,
1189
1263
  options.serviceWorker.url
1190
- ) : devUtils7.formatMessage(
1264
+ ) : devUtils6.formatMessage(
1191
1265
  `Failed to locate the Service Worker registration.
1192
1266
 
1193
1267
  This most likely means that the worker script URL "%s" cannot resolve against the actual public hostname (%s). This may happen if your application runs behind a proxy, or has a dynamic hostname.
@@ -1198,23 +1272,23 @@ Please consider using a custom "serviceWorker.url" option to point to the actual
1198
1272
  );
1199
1273
  throw new Error(missingWorkerMessage);
1200
1274
  }
1201
- context.worker = worker;
1275
+ context.workerPromise.resolve(worker);
1202
1276
  context.registration = registration;
1203
- context.events.addListener(window, "beforeunload", () => {
1277
+ window.addEventListener("beforeunload", () => {
1204
1278
  if (worker.state !== "redundant") {
1205
- context.workerChannel.send("CLIENT_CLOSED");
1279
+ context.workerChannel.postMessage("CLIENT_CLOSED");
1206
1280
  }
1207
1281
  window.clearInterval(context.keepAliveInterval);
1208
1282
  window.postMessage({ type: "msw/worker:stop" });
1209
1283
  });
1210
1284
  await checkWorkerIntegrity(context).catch((error2) => {
1211
- devUtils7.error(
1212
- "Error while checking the worker script integrity. Please report this on GitHub (https://github.com/mswjs/msw/issues), including the original error below."
1285
+ devUtils6.error(
1286
+ "Error while checking the worker script integrity. Please report this on GitHub (https://github.com/mswjs/msw/issues) and include the original error below."
1213
1287
  );
1214
1288
  console.error(error2);
1215
1289
  });
1216
1290
  context.keepAliveInterval = window.setInterval(
1217
- () => context.workerChannel.send("KEEPALIVE_REQUEST"),
1291
+ () => context.workerChannel.postMessage("KEEPALIVE_REQUEST"),
1218
1292
  5e3
1219
1293
  );
1220
1294
  validateWorkerScope(registration, context.startOptions);
@@ -1224,16 +1298,19 @@ Please consider using a custom "serviceWorker.url" option to point to the actual
1224
1298
  async (registration) => {
1225
1299
  const pendingInstance = registration.installing || registration.waiting;
1226
1300
  if (pendingInstance) {
1227
- await new Promise((resolve) => {
1228
- pendingInstance.addEventListener("statechange", () => {
1229
- if (pendingInstance.state === "activated") {
1230
- return resolve();
1231
- }
1232
- });
1301
+ const activationPromise = new DeferredPromise();
1302
+ pendingInstance.addEventListener("statechange", () => {
1303
+ if (pendingInstance.state === "activated") {
1304
+ activationPromise.resolve();
1305
+ }
1233
1306
  });
1307
+ await activationPromise;
1234
1308
  }
1235
1309
  await enableMocking(context, options).catch((error2) => {
1236
- throw new Error(`Failed to enable mocking: ${error2?.message}`);
1310
+ devUtils6.error(
1311
+ "Failed to enable mocking. Please report this on GitHub (https://github.com/mswjs/msw/issues) and include the original error below."
1312
+ );
1313
+ throw error2;
1237
1314
  });
1238
1315
  return registration;
1239
1316
  }
@@ -1242,115 +1319,311 @@ Please consider using a custom "serviceWorker.url" option to point to the actual
1242
1319
  };
1243
1320
  };
1244
1321
 
1245
- // src/browser/setupWorker/stop/createStop.ts
1246
- import { devUtils as devUtils9 } from '../core/utils/internal/devUtils.mjs';
1247
-
1248
- // src/browser/setupWorker/stop/utils/printStopMessage.ts
1322
+ // src/browser/setupWorker/setupWorker.ts
1249
1323
  import { devUtils as devUtils8 } from '../core/utils/internal/devUtils.mjs';
1250
- function printStopMessage(args = {}) {
1251
- if (args.quiet) {
1252
- return;
1324
+ import { SetupApi } from '../core/SetupApi.mjs';
1325
+ import { mergeRight as mergeRight2 } from '../core/utils/internal/mergeRight.mjs';
1326
+
1327
+ // src/browser/utils/supportsReadableStreamTransfer.ts
1328
+ function supportsReadableStreamTransfer() {
1329
+ try {
1330
+ const stream = new ReadableStream({
1331
+ start: (controller) => controller.close()
1332
+ });
1333
+ const message = new MessageChannel();
1334
+ message.port1.postMessage(stream, [stream]);
1335
+ return true;
1336
+ } catch {
1337
+ return false;
1253
1338
  }
1254
- console.log(
1255
- `%c${devUtils8.formatMessage("Mocking disabled.")}`,
1256
- "color:orangered;font-weight:bold;"
1257
- );
1258
1339
  }
1259
1340
 
1260
- // src/browser/setupWorker/stop/createStop.ts
1261
- var createStop = (context) => {
1262
- return function stop() {
1263
- if (!context.isMockingEnabled) {
1264
- devUtils9.warn(
1265
- 'Found a redundant "worker.stop()" call. Note that stopping the worker while mocking already stopped has no effect. Consider removing this "worker.stop()" call.'
1266
- );
1267
- return;
1268
- }
1269
- context.workerChannel.send("MOCK_DEACTIVATE");
1270
- context.isMockingEnabled = false;
1271
- window.clearInterval(context.keepAliveInterval);
1272
- window.postMessage({ type: "msw/worker:stop" });
1273
- printStopMessage({ quiet: context.startOptions?.quiet });
1274
- };
1275
- };
1341
+ // src/browser/setupWorker/setupWorker.ts
1342
+ import { webSocketInterceptor } from '../core/ws/webSocketInterceptor.mjs';
1343
+ import { handleWebSocketEvent } from '../core/ws/handleWebSocketEvent.mjs';
1344
+ import { attachWebSocketLogger } from '../core/ws/utils/attachWebSocketLogger.mjs';
1276
1345
 
1277
- // src/browser/setupWorker/start/utils/prepareStartHandler.ts
1278
- import { mergeRight } from '../core/utils/internal/mergeRight.mjs';
1279
- var DEFAULT_START_OPTIONS = {
1280
- serviceWorker: {
1281
- url: "/mockServiceWorker.js",
1282
- options: null
1283
- },
1284
- quiet: false,
1285
- waitUntilReady: true,
1286
- onUnhandledRequest: "warn",
1287
- findWorker(scriptURL, mockServiceWorkerUrl) {
1288
- return scriptURL === mockServiceWorkerUrl;
1346
+ // node_modules/.pnpm/rettime@0.7.0/node_modules/rettime/build/index.js
1347
+ var kDefaultPrevented = Symbol("kDefaultPrevented");
1348
+ var kPropagationStopped = Symbol("kPropagationStopped");
1349
+ var kImmediatePropagationStopped = Symbol("kImmediatePropagationStopped");
1350
+ var TypedEvent = class extends MessageEvent {
1351
+ /**
1352
+ * @note Keep a placeholder property with the return type
1353
+ * because the type must be set somewhere in order to be
1354
+ * correctly associated and inferred from the event.
1355
+ */
1356
+ #returnType;
1357
+ [kDefaultPrevented];
1358
+ [kPropagationStopped];
1359
+ [kImmediatePropagationStopped];
1360
+ constructor(...args) {
1361
+ super(args[0], args[1]);
1362
+ this[kDefaultPrevented] = false;
1363
+ }
1364
+ get defaultPrevented() {
1365
+ return this[kDefaultPrevented];
1366
+ }
1367
+ preventDefault() {
1368
+ super.preventDefault();
1369
+ this[kDefaultPrevented] = true;
1370
+ }
1371
+ stopImmediatePropagation() {
1372
+ super.stopImmediatePropagation();
1373
+ this[kImmediatePropagationStopped] = true;
1289
1374
  }
1290
1375
  };
1291
-
1292
- // node_modules/.pnpm/@open-draft+deferred-promise@2.2.0/node_modules/@open-draft/deferred-promise/build/index.mjs
1293
- function createDeferredExecutor() {
1294
- const executor = (resolve, reject) => {
1295
- executor.state = "pending";
1296
- executor.resolve = (data) => {
1297
- if (executor.state !== "pending") {
1298
- return;
1376
+ var kListenerOptions = Symbol("kListenerOptions");
1377
+ var Emitter2 = class {
1378
+ #listeners;
1379
+ constructor() {
1380
+ this.#listeners = {};
1381
+ }
1382
+ /**
1383
+ * Adds a listener for the given event type.
1384
+ *
1385
+ * @returns {AbortController} An `AbortController` that can be used to remove the listener.
1386
+ */
1387
+ on(type, listener, options) {
1388
+ return this.#addListener(type, listener, options);
1389
+ }
1390
+ /**
1391
+ * Adds a one-time listener for the given event type.
1392
+ *
1393
+ * @returns {AbortController} An `AbortController` that can be used to remove the listener.
1394
+ */
1395
+ once(type, listener, options) {
1396
+ return this.on(type, listener, { ...options || {}, once: true });
1397
+ }
1398
+ /**
1399
+ * Prepends a listener for the given event type.
1400
+ *
1401
+ * @returns {AbortController} An `AbortController` that can be used to remove the listener.
1402
+ */
1403
+ earlyOn(type, listener, options) {
1404
+ return this.#addListener(type, listener, options, "prepend");
1405
+ }
1406
+ /**
1407
+ * Prepends a one-time listener for the given event type.
1408
+ */
1409
+ earlyOnce(type, listener, options) {
1410
+ return this.earlyOn(type, listener, { ...options || {}, once: true });
1411
+ }
1412
+ /**
1413
+ * Emits the given typed event.
1414
+ *
1415
+ * @returns {boolean} Returns `true` if the event had any listeners, `false` otherwise.
1416
+ */
1417
+ emit(event) {
1418
+ if (this.listenerCount(event.type) === 0) {
1419
+ return false;
1420
+ }
1421
+ const proxiedEvent = this.#proxyEvent(event);
1422
+ for (const listener of this.#listeners[event.type]) {
1423
+ if (proxiedEvent.event[kPropagationStopped] != null && proxiedEvent.event[kPropagationStopped] !== this) {
1424
+ return false;
1299
1425
  }
1300
- executor.result = data;
1301
- const onFulfilled = (value) => {
1302
- executor.state = "fulfilled";
1303
- return value;
1304
- };
1305
- return resolve(
1306
- data instanceof Promise ? data : Promise.resolve(data).then(onFulfilled)
1426
+ if (proxiedEvent.event[kImmediatePropagationStopped]) {
1427
+ break;
1428
+ }
1429
+ this.#callListener(proxiedEvent.event, listener);
1430
+ }
1431
+ proxiedEvent.revoke();
1432
+ return true;
1433
+ }
1434
+ /**
1435
+ * Emits the given typed event and returns a promise that resolves
1436
+ * when all the listeners for that event have settled.
1437
+ *
1438
+ * @returns {Promise<Array<Emitter.ListenerReturnType>>} A promise that resolves
1439
+ * with the return values of all listeners.
1440
+ */
1441
+ async emitAsPromise(event) {
1442
+ if (this.listenerCount(event.type) === 0) {
1443
+ return [];
1444
+ }
1445
+ const pendingListeners = [];
1446
+ const proxiedEvent = this.#proxyEvent(event);
1447
+ for (const listener of this.#listeners[event.type]) {
1448
+ if (proxiedEvent.event[kPropagationStopped] != null && proxiedEvent.event[kPropagationStopped] !== this) {
1449
+ return [];
1450
+ }
1451
+ if (proxiedEvent.event[kImmediatePropagationStopped]) {
1452
+ break;
1453
+ }
1454
+ pendingListeners.push(
1455
+ // Awaiting individual listeners guarantees their call order.
1456
+ await Promise.resolve(this.#callListener(proxiedEvent.event, listener))
1307
1457
  );
1308
- };
1309
- executor.reject = (reason) => {
1310
- if (executor.state !== "pending") {
1458
+ }
1459
+ proxiedEvent.revoke();
1460
+ return Promise.allSettled(pendingListeners).then((results) => {
1461
+ return results.map(
1462
+ (result) => result.status === "fulfilled" ? result.value : result.reason
1463
+ );
1464
+ });
1465
+ }
1466
+ /**
1467
+ * Emits the given event and returns a generator that yields
1468
+ * the result of each listener in the order of their registration.
1469
+ * This way, you stop exhausting the listeners once you get the expected value.
1470
+ */
1471
+ *emitAsGenerator(event) {
1472
+ if (this.listenerCount(event.type) === 0) {
1473
+ return;
1474
+ }
1475
+ const proxiedEvent = this.#proxyEvent(event);
1476
+ for (const listener of this.#listeners[event.type]) {
1477
+ if (proxiedEvent.event[kPropagationStopped] != null && proxiedEvent.event[kPropagationStopped] !== this) {
1311
1478
  return;
1312
1479
  }
1313
- queueMicrotask(() => {
1314
- executor.state = "rejected";
1480
+ if (proxiedEvent.event[kImmediatePropagationStopped]) {
1481
+ break;
1482
+ }
1483
+ yield this.#callListener(proxiedEvent.event, listener);
1484
+ }
1485
+ proxiedEvent.revoke();
1486
+ }
1487
+ /**
1488
+ * Removes a listener for the given event type.
1489
+ */
1490
+ removeListener(type, listener) {
1491
+ if (this.listenerCount(type) === 0) {
1492
+ return;
1493
+ }
1494
+ const nextListeners = [];
1495
+ for (const existingListener of this.#listeners[type]) {
1496
+ if (existingListener !== listener) {
1497
+ nextListeners.push(existingListener);
1498
+ }
1499
+ }
1500
+ this.#listeners[type] = nextListeners;
1501
+ }
1502
+ /**
1503
+ * Removes all listeners for the given event type.
1504
+ * If no event type is provided, removes all existing listeners.
1505
+ */
1506
+ removeAllListeners(type) {
1507
+ if (type == null) {
1508
+ this.#listeners = {};
1509
+ return;
1510
+ }
1511
+ this.#listeners[type] = [];
1512
+ }
1513
+ /**
1514
+ * Returns the list of listeners for the given event type.
1515
+ * If no even type is provided, returns all listeners.
1516
+ */
1517
+ listeners(type) {
1518
+ if (type == null) {
1519
+ return Object.values(this.#listeners).flat();
1520
+ }
1521
+ return this.#listeners[type] || [];
1522
+ }
1523
+ /**
1524
+ * Returns the number of listeners for the given event type.
1525
+ * If no even type is provided, returns the total number of listeners.
1526
+ */
1527
+ listenerCount(type) {
1528
+ return this.listeners(type).length;
1529
+ }
1530
+ #addListener(type, listener, options, insertMode = "append") {
1531
+ this.#listeners[type] ??= [];
1532
+ if (insertMode === "prepend") {
1533
+ this.#listeners[type].unshift(listener);
1534
+ } else {
1535
+ this.#listeners[type].push(listener);
1536
+ }
1537
+ if (options) {
1538
+ Object.defineProperty(listener, kListenerOptions, {
1539
+ value: options,
1540
+ enumerable: false,
1541
+ writable: false
1315
1542
  });
1316
- return reject(executor.rejectionReason = reason);
1317
- };
1318
- };
1319
- return executor;
1320
- }
1321
- var DeferredPromise = class extends Promise {
1322
- #executor;
1323
- resolve;
1324
- reject;
1325
- constructor(executor = null) {
1326
- const deferredExecutor = createDeferredExecutor();
1327
- super((originalResolve, originalReject) => {
1328
- deferredExecutor(originalResolve, originalReject);
1329
- executor?.(deferredExecutor.resolve, deferredExecutor.reject);
1543
+ if (options.signal) {
1544
+ options.signal.addEventListener(
1545
+ "abort",
1546
+ () => {
1547
+ this.removeListener(type, listener);
1548
+ },
1549
+ { once: true }
1550
+ );
1551
+ }
1552
+ }
1553
+ return this;
1554
+ }
1555
+ #proxyEvent(event) {
1556
+ const { stopPropagation } = event;
1557
+ event.stopPropagation = new Proxy(event.stopPropagation, {
1558
+ apply: (target, thisArg, argArray) => {
1559
+ event[kPropagationStopped] = this;
1560
+ return Reflect.apply(target, thisArg, argArray);
1561
+ }
1330
1562
  });
1331
- this.#executor = deferredExecutor;
1332
- this.resolve = this.#executor.resolve;
1333
- this.reject = this.#executor.reject;
1563
+ return {
1564
+ event,
1565
+ revoke() {
1566
+ event.stopPropagation = stopPropagation;
1567
+ }
1568
+ };
1334
1569
  }
1335
- get state() {
1336
- return this.#executor.state;
1570
+ #callListener(event, listener) {
1571
+ const returnValue = listener.call(this, event);
1572
+ if (listener[kListenerOptions]?.once) {
1573
+ this.removeListener(event.type, listener);
1574
+ }
1575
+ return returnValue;
1337
1576
  }
1338
- get rejectionReason() {
1339
- return this.#executor.rejectionReason;
1577
+ };
1578
+
1579
+ // src/browser/utils/workerChannel.ts
1580
+ import { isObject } from '../core/utils/internal/isObject.mjs';
1581
+ var WorkerEvent = class extends TypedEvent {
1582
+ #workerEvent;
1583
+ constructor(workerEvent) {
1584
+ const type = workerEvent.data.type;
1585
+ const data = workerEvent.data.payload;
1586
+ super(
1587
+ // @ts-expect-error Troublesome `TypedEvent` extension.
1588
+ type,
1589
+ { data }
1590
+ );
1591
+ this.#workerEvent = workerEvent;
1340
1592
  }
1341
- then(onFulfilled, onRejected) {
1342
- return this.#decorate(super.then(onFulfilled, onRejected));
1593
+ get ports() {
1594
+ return this.#workerEvent.ports;
1343
1595
  }
1344
- catch(onRejected) {
1345
- return this.#decorate(super.catch(onRejected));
1596
+ /**
1597
+ * Reply directly to this event using its `MessagePort`.
1598
+ */
1599
+ postMessage(type, ...rest) {
1600
+ this.#workerEvent.ports[0].postMessage(
1601
+ { type, data: rest[0] },
1602
+ { transfer: rest[1] }
1603
+ );
1346
1604
  }
1347
- finally(onfinally) {
1348
- return this.#decorate(super.finally(onfinally));
1605
+ };
1606
+ var WorkerChannel = class extends Emitter2 {
1607
+ constructor(options) {
1608
+ super();
1609
+ this.options = options;
1610
+ navigator.serviceWorker.addEventListener("message", async (event) => {
1611
+ const worker = await this.options.worker;
1612
+ if (event.source != null && event.source !== worker) {
1613
+ return;
1614
+ }
1615
+ if (event.data && isObject(event.data) && "type" in event.data) {
1616
+ this.emit(new WorkerEvent(event));
1617
+ }
1618
+ });
1349
1619
  }
1350
- #decorate(promise) {
1351
- return Object.defineProperties(promise, {
1352
- resolve: { configurable: true, value: this.resolve },
1353
- reject: { configurable: true, value: this.reject }
1620
+ /**
1621
+ * Send data to the Service Worker controlling this client.
1622
+ * This triggers the `message` event listener on ServiceWorkerGlobalScope.
1623
+ */
1624
+ postMessage(type) {
1625
+ this.options.worker.then((worker) => {
1626
+ worker.postMessage(type);
1354
1627
  });
1355
1628
  }
1356
1629
  };
@@ -1418,7 +1691,7 @@ async function emitAsync(emitter, eventName, ...data) {
1418
1691
  await listener.apply(emitter, data);
1419
1692
  }
1420
1693
  }
1421
- function isObject(value, loose = false) {
1694
+ function isObject2(value, loose = false) {
1422
1695
  return loose ? Object.prototype.toString.call(value).startsWith("[object ") : Object.prototype.toString.call(value) === "[object Object]";
1423
1696
  }
1424
1697
  function isPropertyAccessible(obj, key) {
@@ -1451,7 +1724,7 @@ function isResponseError(response) {
1451
1724
  return response != null && response instanceof Response && isPropertyAccessible(response, "type") && response.type === "error";
1452
1725
  }
1453
1726
  function isResponseLike(value) {
1454
- return isObject(value, true) && isPropertyAccessible(value, "status") && isPropertyAccessible(value, "statusText") && isPropertyAccessible(value, "bodyUsed");
1727
+ return isObject2(value, true) && isPropertyAccessible(value, "status") && isPropertyAccessible(value, "statusText") && isPropertyAccessible(value, "bodyUsed");
1455
1728
  }
1456
1729
  function isNodeLikeError(error2) {
1457
1730
  if (error2 == null) {
@@ -1476,7 +1749,7 @@ async function handleRequest2(options) {
1476
1749
  await options.onResponse(response);
1477
1750
  return true;
1478
1751
  }
1479
- if (isObject(response)) {
1752
+ if (isObject2(response)) {
1480
1753
  options.onError(response);
1481
1754
  return true;
1482
1755
  }
@@ -2687,162 +2960,66 @@ function createFallbackRequestListener(context, options) {
2687
2960
  return interceptor;
2688
2961
  }
2689
2962
 
2690
- // src/browser/setupWorker/start/createFallbackStart.ts
2691
- function createFallbackStart(context) {
2692
- return async function start(options) {
2693
- context.fallbackInterceptor = createFallbackRequestListener(
2694
- context,
2695
- options
2696
- );
2697
- printStartMessage({
2698
- message: "Mocking enabled (fallback mode).",
2699
- quiet: options.quiet
2700
- });
2701
- return void 0;
2702
- };
2703
- }
2704
-
2705
- // src/browser/setupWorker/stop/createFallbackStop.ts
2706
- function createFallbackStop(context) {
2707
- return function stop() {
2708
- context.fallbackInterceptor?.dispose();
2709
- printStopMessage({ quiet: context.startOptions?.quiet });
2710
- };
2711
- }
2712
-
2713
- // src/browser/setupWorker/setupWorker.ts
2714
- import { devUtils as devUtils10 } from '../core/utils/internal/devUtils.mjs';
2715
- import { SetupApi } from '../core/SetupApi.mjs';
2716
- import { mergeRight as mergeRight2 } from '../core/utils/internal/mergeRight.mjs';
2717
-
2718
- // src/browser/utils/supportsReadableStreamTransfer.ts
2719
- function supportsReadableStreamTransfer() {
2720
- try {
2721
- const stream = new ReadableStream({
2722
- start: (controller) => controller.close()
2723
- });
2724
- const message = new MessageChannel();
2725
- message.port1.postMessage(stream, [stream]);
2726
- return true;
2727
- } catch {
2728
- return false;
2963
+ // src/browser/setupWorker/stop/utils/printStopMessage.ts
2964
+ import { devUtils as devUtils7 } from '../core/utils/internal/devUtils.mjs';
2965
+ function printStopMessage(args = {}) {
2966
+ if (args.quiet) {
2967
+ return;
2729
2968
  }
2969
+ console.log(
2970
+ `%c${devUtils7.formatMessage("Mocking disabled.")}`,
2971
+ "color:orangered;font-weight:bold;"
2972
+ );
2730
2973
  }
2731
2974
 
2732
2975
  // src/browser/setupWorker/setupWorker.ts
2733
- import { webSocketInterceptor } from '../core/ws/webSocketInterceptor.mjs';
2734
- import { handleWebSocketEvent } from '../core/ws/handleWebSocketEvent.mjs';
2735
- import { attachWebSocketLogger } from '../core/ws/utils/attachWebSocketLogger.mjs';
2736
2976
  var SetupWorkerApi = class extends SetupApi {
2737
2977
  context;
2738
- startHandler = null;
2739
- stopHandler = null;
2740
- listeners;
2741
2978
  constructor(...handlers) {
2742
2979
  super(...handlers);
2743
2980
  invariant(
2744
2981
  !isNodeProcess(),
2745
- devUtils10.formatMessage(
2982
+ devUtils8.formatMessage(
2746
2983
  "Failed to execute `setupWorker` in a non-browser environment. Consider using `setupServer` for Node.js environment instead."
2747
2984
  )
2748
2985
  );
2749
- this.listeners = [];
2750
2986
  this.context = this.createWorkerContext();
2751
2987
  }
2752
2988
  createWorkerContext() {
2753
- const context = {
2989
+ const workerPromise = new DeferredPromise();
2990
+ return {
2754
2991
  // Mocking is not considered enabled until the worker
2755
2992
  // signals back the successful activation event.
2756
2993
  isMockingEnabled: false,
2757
2994
  startOptions: null,
2758
- worker: null,
2995
+ workerPromise,
2996
+ registration: void 0,
2759
2997
  getRequestHandlers: () => {
2760
2998
  return this.handlersController.currentHandlers();
2761
2999
  },
2762
- registration: null,
2763
3000
  emitter: this.emitter,
2764
- workerChannel: {
2765
- on: (eventType, callback) => {
2766
- this.context.events.addListener(navigator.serviceWorker, "message", (event) => {
2767
- if (event.source !== this.context.worker) {
2768
- return;
2769
- }
2770
- const message = event.data;
2771
- if (!message) {
2772
- return;
2773
- }
2774
- if (message.type === eventType) {
2775
- callback(event, message);
2776
- }
2777
- });
2778
- },
2779
- send: (type) => {
2780
- this.context.worker?.postMessage(type);
2781
- }
2782
- },
2783
- events: {
2784
- addListener: (target, eventType, callback) => {
2785
- target.addEventListener(eventType, callback);
2786
- this.listeners.push({
2787
- eventType,
2788
- target,
2789
- callback
2790
- });
2791
- return () => {
2792
- target.removeEventListener(eventType, callback);
2793
- };
2794
- },
2795
- removeAllListeners: () => {
2796
- for (const { target, eventType, callback } of this.listeners) {
2797
- target.removeEventListener(eventType, callback);
2798
- }
2799
- this.listeners = [];
2800
- },
2801
- once: (eventType) => {
2802
- const bindings = [];
2803
- return new Promise((resolve, reject) => {
2804
- const handleIncomingMessage = (event) => {
2805
- try {
2806
- const message = event.data;
2807
- if (message.type === eventType) {
2808
- resolve(message);
2809
- }
2810
- } catch (error2) {
2811
- reject(error2);
2812
- }
2813
- };
2814
- bindings.push(
2815
- this.context.events.addListener(
2816
- navigator.serviceWorker,
2817
- "message",
2818
- handleIncomingMessage
2819
- ),
2820
- this.context.events.addListener(
2821
- navigator.serviceWorker,
2822
- "messageerror",
2823
- reject
2824
- )
2825
- );
2826
- }).finally(() => {
2827
- bindings.forEach((unbind) => unbind());
2828
- });
2829
- }
2830
- },
3001
+ workerChannel: new WorkerChannel({
3002
+ worker: workerPromise
3003
+ }),
2831
3004
  supports: {
2832
- serviceWorkerApi: !("serviceWorker" in navigator) || location.protocol === "file:",
3005
+ serviceWorkerApi: "serviceWorker" in navigator && location.protocol !== "file:",
2833
3006
  readableStreamTransfer: supportsReadableStreamTransfer()
2834
3007
  }
2835
3008
  };
2836
- this.startHandler = context.supports.serviceWorkerApi ? createFallbackStart(context) : createStartHandler(context);
2837
- this.stopHandler = context.supports.serviceWorkerApi ? createFallbackStop(context) : createStop(context);
2838
- return context;
2839
3009
  }
2840
3010
  async start(options = {}) {
2841
- if (options.waitUntilReady === true) {
2842
- devUtils10.warn(
3011
+ if ("waitUntilReady" in options) {
3012
+ devUtils8.warn(
2843
3013
  'The "waitUntilReady" option has been deprecated. Please remove it from this "worker.start()" call. Follow the recommended Browser integration (https://mswjs.io/docs/integrations/browser) to eliminate any race conditions between the Service Worker registration and any requests made by your application on initial render.'
2844
3014
  );
2845
3015
  }
3016
+ if (this.context.isMockingEnabled) {
3017
+ devUtils8.warn(
3018
+ `Found a redundant "worker.start()" call. Note that starting the worker while mocking is already enabled will have no effect. Consider removing this "worker.start()" call.`
3019
+ );
3020
+ return this.context.registration;
3021
+ }
3022
+ this.context.workerStoppedAt = void 0;
2846
3023
  this.context.startOptions = mergeRight2(
2847
3024
  DEFAULT_START_OPTIONS,
2848
3025
  options
@@ -2866,13 +3043,45 @@ var SetupWorkerApi = class extends SetupApi {
2866
3043
  this.subscriptions.push(() => {
2867
3044
  webSocketInterceptor.dispose();
2868
3045
  });
2869
- return await this.startHandler(this.context.startOptions, options);
3046
+ if (!this.context.supports.serviceWorkerApi) {
3047
+ const fallbackInterceptor = createFallbackRequestListener(
3048
+ this.context,
3049
+ this.context.startOptions
3050
+ );
3051
+ this.subscriptions.push(() => {
3052
+ fallbackInterceptor.dispose();
3053
+ });
3054
+ this.context.isMockingEnabled = true;
3055
+ printStartMessage({
3056
+ message: "Mocking enabled (fallback mode).",
3057
+ quiet: this.context.startOptions.quiet
3058
+ });
3059
+ return void 0;
3060
+ }
3061
+ const startHandler = createStartHandler(this.context);
3062
+ const registration = await startHandler(this.context.startOptions, options);
3063
+ this.context.isMockingEnabled = true;
3064
+ return registration;
2870
3065
  }
2871
3066
  stop() {
2872
3067
  super.dispose();
2873
- this.context.events.removeAllListeners();
3068
+ if (!this.context.isMockingEnabled) {
3069
+ devUtils8.warn(
3070
+ 'Found a redundant "worker.stop()" call. Notice that stopping the worker after it has already been stopped has no effect. Consider removing this "worker.stop()" call.'
3071
+ );
3072
+ return;
3073
+ }
3074
+ this.context.isMockingEnabled = false;
3075
+ this.context.workerStoppedAt = Date.now();
2874
3076
  this.context.emitter.removeAllListeners();
2875
- this.stopHandler();
3077
+ if (this.context.supports.serviceWorkerApi) {
3078
+ this.context.workerChannel.removeAllListeners("RESPONSE");
3079
+ window.clearInterval(this.context.keepAliveInterval);
3080
+ }
3081
+ window.postMessage({ type: "msw/worker:stop" });
3082
+ printStopMessage({
3083
+ quiet: this.context.startOptions?.quiet
3084
+ });
2876
3085
  }
2877
3086
  };
2878
3087
  function setupWorker(...handlers) {