@vitest/web-worker 3.1.0-beta.1 → 3.1.0

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 (2) hide show
  1. package/dist/pure.js +341 -386
  2. package/package.json +2 -2
package/dist/pure.js CHANGED
@@ -4,23 +4,19 @@ import { readFileSync as readFileSync$1 } from 'node:fs';
4
4
  import createDebug from 'debug';
5
5
 
6
6
  class InlineWorkerRunner extends VitestExecutor {
7
- constructor(options, context) {
8
- const mocker = globalThis.__vitest_mocker__;
9
- super(options);
10
- this.context = context;
11
- this.mocker = globalThis.__vitest_mocker__ = mocker;
12
- }
13
- prepareContext(context) {
14
- const ctx = super.prepareContext(context);
15
- return Object.assign(ctx, this.context, {
16
- importScripts
17
- });
18
- }
7
+ constructor(options, context) {
8
+ const mocker = globalThis.__vitest_mocker__;
9
+ super(options);
10
+ this.context = context;
11
+ this.mocker = globalThis.__vitest_mocker__ = mocker;
12
+ }
13
+ prepareContext(context) {
14
+ const ctx = super.prepareContext(context);
15
+ return Object.assign(ctx, this.context, { importScripts });
16
+ }
19
17
  }
20
18
  function importScripts() {
21
- throw new Error(
22
- "[vitest] `importScripts` is not supported in Vite workers. Please, consider using `import` instead."
23
- );
19
+ throw new Error("[vitest] `importScripts` is not supported in Vite workers. Please, consider using `import` instead.");
24
20
  }
25
21
 
26
22
  const VOID = -1;
@@ -302,400 +298,359 @@ var ponyfillStructuredClone = typeof structuredClone === "function" ?
302
298
  const readFileSync = readFileSync$1;
303
299
  const debug = createDebug("vitest:web-worker");
304
300
  function getWorkerState() {
305
- return globalThis.__vitest_worker__;
301
+ return globalThis.__vitest_worker__;
306
302
  }
307
303
  function assertGlobalExists(name) {
308
- if (!(name in globalThis)) {
309
- throw new Error(
310
- `[@vitest/web-worker] Cannot initiate a custom Web Worker. "${name}" is not supported in this environment. Please, consider using jsdom or happy-dom environment.`
311
- );
312
- }
304
+ if (!(name in globalThis)) {
305
+ throw new Error(`[@vitest/web-worker] Cannot initiate a custom Web Worker. "${name}" is not supported in this environment. Please, consider using jsdom or happy-dom environment.`);
306
+ }
313
307
  }
314
308
  function createClonedMessageEvent(data, transferOrOptions, clone) {
315
- const transfer = Array.isArray(transferOrOptions) ? transferOrOptions : transferOrOptions?.transfer;
316
- debug("clone worker message %o", data);
317
- const origin = typeof location === "undefined" ? void 0 : location.origin;
318
- if (typeof structuredClone === "function" && clone === "native") {
319
- debug("create message event, using native structured clone");
320
- return new MessageEvent("message", {
321
- data: structuredClone(data, { transfer }),
322
- origin
323
- });
324
- }
325
- if (clone !== "none") {
326
- debug("create message event, using polyfilled structured clone");
327
- if (transfer?.length) {
328
- console.warn(
329
- '[@vitest/web-worker] `structuredClone` is not supported in this environment. Falling back to polyfill, your transferable options will be lost. Set `VITEST_WEB_WORKER_CLONE` environmental variable to "none", if you don\'t want to loose it,or update to Node 17+.'
330
- );
331
- }
332
- return new MessageEvent("message", {
333
- data: ponyfillStructuredClone(data, { lossy: true }),
334
- origin
335
- });
336
- }
337
- debug("create message event without cloning an object");
338
- return new MessageEvent("message", {
339
- data,
340
- origin
341
- });
309
+ const transfer = Array.isArray(transferOrOptions) ? transferOrOptions : transferOrOptions?.transfer;
310
+ debug("clone worker message %o", data);
311
+ const origin = typeof location === "undefined" ? undefined : location.origin;
312
+ if (typeof structuredClone === "function" && clone === "native") {
313
+ debug("create message event, using native structured clone");
314
+ return new MessageEvent("message", {
315
+ data: structuredClone(data, { transfer }),
316
+ origin
317
+ });
318
+ }
319
+ if (clone !== "none") {
320
+ debug("create message event, using polyfilled structured clone");
321
+ if (transfer?.length) {
322
+ console.warn("[@vitest/web-worker] `structuredClone` is not supported in this environment. " + "Falling back to polyfill, your transferable options will be lost. " + "Set `VITEST_WEB_WORKER_CLONE` environmental variable to \"none\", if you don't want to loose it," + "or update to Node 17+.");
323
+ }
324
+ return new MessageEvent("message", {
325
+ data: ponyfillStructuredClone(data, { lossy: true }),
326
+ origin
327
+ });
328
+ }
329
+ debug("create message event without cloning an object");
330
+ return new MessageEvent("message", {
331
+ data,
332
+ origin
333
+ });
342
334
  }
343
335
  function createMessageEvent(data, transferOrOptions, clone) {
344
- try {
345
- return createClonedMessageEvent(data, transferOrOptions, clone);
346
- } catch (error) {
347
- debug('failed to clone message, dispatch "messageerror" event: %o', error);
348
- return new MessageEvent("messageerror", {
349
- data: error
350
- });
351
- }
336
+ try {
337
+ return createClonedMessageEvent(data, transferOrOptions, clone);
338
+ } catch (error) {
339
+ debug("failed to clone message, dispatch \"messageerror\" event: %o", error);
340
+ return new MessageEvent("messageerror", { data: error });
341
+ }
352
342
  }
353
343
  function getRunnerOptions() {
354
- const state = getWorkerState();
355
- const { config, rpc, moduleCache, moduleExecutionInfo } = state;
356
- return {
357
- async fetchModule(id) {
358
- const result = await rpc.fetch(id, "web");
359
- if (result.id && !result.externalize) {
360
- const code = readFileSync(result.id, "utf-8");
361
- return { code };
362
- }
363
- return result;
364
- },
365
- resolveId(id, importer) {
366
- return rpc.resolveId(id, importer, "web");
367
- },
368
- moduleCache,
369
- moduleExecutionInfo,
370
- interopDefault: config.deps.interopDefault ?? true,
371
- moduleDirectories: config.deps.moduleDirectories,
372
- root: config.root,
373
- base: config.base,
374
- state
375
- };
344
+ const state = getWorkerState();
345
+ const { config, rpc, moduleCache, moduleExecutionInfo } = state;
346
+ return {
347
+ async fetchModule(id) {
348
+ const result = await rpc.fetch(id, "web");
349
+ if (result.id && !result.externalize) {
350
+ const code = readFileSync(result.id, "utf-8");
351
+ return { code };
352
+ }
353
+ return result;
354
+ },
355
+ resolveId(id, importer) {
356
+ return rpc.resolveId(id, importer, "web");
357
+ },
358
+ moduleCache,
359
+ moduleExecutionInfo,
360
+ interopDefault: config.deps.interopDefault ?? true,
361
+ moduleDirectories: config.deps.moduleDirectories,
362
+ root: config.root,
363
+ base: config.base,
364
+ state
365
+ };
376
366
  }
377
367
  function stripProtocol(url) {
378
- return url.toString().replace(/^file:\/+/, "/");
368
+ return url.toString().replace(/^file:\/+/, "/");
379
369
  }
380
370
  function getFileIdFromUrl(url) {
381
- if (typeof self === "undefined") {
382
- return stripProtocol(url);
383
- }
384
- if (!(url instanceof URL)) {
385
- url = new URL(url, self.location.origin);
386
- }
387
- if (url.protocol === "http:" || url.protocol === "https:") {
388
- return url.pathname;
389
- }
390
- return stripProtocol(url);
371
+ if (typeof self === "undefined") {
372
+ return stripProtocol(url);
373
+ }
374
+ if (!(url instanceof URL)) {
375
+ url = new URL(url, self.location.origin);
376
+ }
377
+ if (url.protocol === "http:" || url.protocol === "https:") {
378
+ return url.pathname;
379
+ }
380
+ return stripProtocol(url);
391
381
  }
392
382
 
393
383
  function convertNodePortToWebPort(port) {
394
- if (!("addEventListener" in port)) {
395
- Object.defineProperty(port, "addEventListener", {
396
- value(...args) {
397
- return this.addListener(...args);
398
- },
399
- configurable: true,
400
- enumerable: true
401
- });
402
- }
403
- if (!("removeEventListener" in port)) {
404
- Object.defineProperty(port, "removeEventListener", {
405
- value(...args) {
406
- return this.removeListener(...args);
407
- },
408
- configurable: true,
409
- enumerable: true
410
- });
411
- }
412
- if (!("dispatchEvent" in port)) {
413
- const emit = port.emit.bind(port);
414
- Object.defineProperty(port, "emit", {
415
- value(event) {
416
- if (event.name === "message") {
417
- port.onmessage?.(event);
418
- }
419
- if (event.name === "messageerror") {
420
- port.onmessageerror?.(event);
421
- }
422
- return emit(event);
423
- },
424
- configurable: true,
425
- enumerable: true
426
- });
427
- Object.defineProperty(port, "dispatchEvent", {
428
- value(event) {
429
- return this.emit(event);
430
- },
431
- configurable: true,
432
- enumerable: true
433
- });
434
- }
435
- return port;
384
+ if (!("addEventListener" in port)) {
385
+ Object.defineProperty(port, "addEventListener", {
386
+ value(...args) {
387
+ return this.addListener(...args);
388
+ },
389
+ configurable: true,
390
+ enumerable: true
391
+ });
392
+ }
393
+ if (!("removeEventListener" in port)) {
394
+ Object.defineProperty(port, "removeEventListener", {
395
+ value(...args) {
396
+ return this.removeListener(...args);
397
+ },
398
+ configurable: true,
399
+ enumerable: true
400
+ });
401
+ }
402
+ if (!("dispatchEvent" in port)) {
403
+ const emit = port.emit.bind(port);
404
+ Object.defineProperty(port, "emit", {
405
+ value(event) {
406
+ if (event.name === "message") {
407
+ port.onmessage?.(event);
408
+ }
409
+ if (event.name === "messageerror") {
410
+ port.onmessageerror?.(event);
411
+ }
412
+ return emit(event);
413
+ },
414
+ configurable: true,
415
+ enumerable: true
416
+ });
417
+ Object.defineProperty(port, "dispatchEvent", {
418
+ value(event) {
419
+ return this.emit(event);
420
+ },
421
+ configurable: true,
422
+ enumerable: true
423
+ });
424
+ }
425
+ return port;
436
426
  }
437
427
  function createSharedWorkerConstructor() {
438
- const runnerOptions = getRunnerOptions();
439
- return class SharedWorker extends EventTarget {
440
- static __VITEST_WEB_WORKER__ = true;
441
- _vw_workerTarget = new EventTarget();
442
- _vw_name;
443
- _vw_workerPort;
444
- onerror = null;
445
- port;
446
- constructor(url, options) {
447
- super();
448
- const name = typeof options === "string" ? options : options?.name;
449
- let selfProxy;
450
- const context = {
451
- onmessage: null,
452
- onmessageerror: null,
453
- onerror: null,
454
- onlanguagechange: null,
455
- onoffline: null,
456
- ononline: null,
457
- onrejectionhandled: null,
458
- onrtctransform: null,
459
- onunhandledrejection: null,
460
- origin: typeof location !== "undefined" ? location.origin : "http://localhost:3000",
461
- importScripts: () => {
462
- throw new Error(
463
- "[vitest] `importScripts` is not supported in Vite workers. Please, consider using `import` instead."
464
- );
465
- },
466
- crossOriginIsolated: false,
467
- onconnect: null,
468
- name: name || "",
469
- close: () => this.port.close(),
470
- dispatchEvent: (event) => {
471
- return this._vw_workerTarget.dispatchEvent(event);
472
- },
473
- addEventListener: (...args) => {
474
- return this._vw_workerTarget.addEventListener(...args);
475
- },
476
- removeEventListener: (...args) => {
477
- return this._vw_workerTarget.removeEventListener(...args);
478
- },
479
- get self() {
480
- return selfProxy;
481
- }
482
- };
483
- selfProxy = new Proxy(context, {
484
- get(target, prop, receiver) {
485
- if (Reflect.has(target, prop)) {
486
- return Reflect.get(target, prop, receiver);
487
- }
488
- return Reflect.get(globalThis, prop, receiver);
489
- }
490
- });
491
- const channel = new MessageChannel();
492
- this.port = convertNodePortToWebPort(channel.port1);
493
- this._vw_workerPort = convertNodePortToWebPort(channel.port2);
494
- this._vw_workerTarget.addEventListener("connect", (e) => {
495
- context.onconnect?.(e);
496
- });
497
- const runner = new InlineWorkerRunner(runnerOptions, context);
498
- const id = getFileIdFromUrl(url);
499
- this._vw_name = id;
500
- runner.resolveUrl(id).then(([, fsPath]) => {
501
- this._vw_name = name ?? fsPath;
502
- debug("initialize shared worker %s", this._vw_name);
503
- return runner.executeFile(fsPath).then(() => {
504
- runnerOptions.moduleCache.invalidateSubDepTree([
505
- fsPath,
506
- runner.mocker.getMockPath(fsPath)
507
- ]);
508
- this._vw_workerTarget.dispatchEvent(
509
- new MessageEvent("connect", {
510
- ports: [this._vw_workerPort]
511
- })
512
- );
513
- debug("shared worker %s successfully initialized", this._vw_name);
514
- });
515
- }).catch((e) => {
516
- debug("shared worker %s failed to initialize: %o", this._vw_name, e);
517
- const EventConstructor = globalThis.ErrorEvent || globalThis.Event;
518
- const error = new EventConstructor("error", {
519
- error: e,
520
- message: e.message
521
- });
522
- this.dispatchEvent(error);
523
- this.onerror?.(error);
524
- console.error(e);
525
- });
526
- }
527
- };
428
+ const runnerOptions = getRunnerOptions();
429
+ return class SharedWorker extends EventTarget {
430
+ static __VITEST_WEB_WORKER__ = true;
431
+ _vw_workerTarget = new EventTarget();
432
+ _vw_name;
433
+ _vw_workerPort;
434
+ onerror = null;
435
+ port;
436
+ constructor(url, options) {
437
+ super();
438
+ const name = typeof options === "string" ? options : options?.name;
439
+ let selfProxy;
440
+ const context = {
441
+ onmessage: null,
442
+ onmessageerror: null,
443
+ onerror: null,
444
+ onlanguagechange: null,
445
+ onoffline: null,
446
+ ononline: null,
447
+ onrejectionhandled: null,
448
+ onrtctransform: null,
449
+ onunhandledrejection: null,
450
+ origin: typeof location !== "undefined" ? location.origin : "http://localhost:3000",
451
+ importScripts: () => {
452
+ throw new Error("[vitest] `importScripts` is not supported in Vite workers. Please, consider using `import` instead.");
453
+ },
454
+ crossOriginIsolated: false,
455
+ onconnect: null,
456
+ name: name || "",
457
+ close: () => this.port.close(),
458
+ dispatchEvent: (event) => {
459
+ return this._vw_workerTarget.dispatchEvent(event);
460
+ },
461
+ addEventListener: (...args) => {
462
+ return this._vw_workerTarget.addEventListener(...args);
463
+ },
464
+ removeEventListener: (...args) => {
465
+ return this._vw_workerTarget.removeEventListener(...args);
466
+ },
467
+ get self() {
468
+ return selfProxy;
469
+ }
470
+ };
471
+ selfProxy = new Proxy(context, { get(target, prop, receiver) {
472
+ if (Reflect.has(target, prop)) {
473
+ return Reflect.get(target, prop, receiver);
474
+ }
475
+ return Reflect.get(globalThis, prop, receiver);
476
+ } });
477
+ const channel = new MessageChannel();
478
+ this.port = convertNodePortToWebPort(channel.port1);
479
+ this._vw_workerPort = convertNodePortToWebPort(channel.port2);
480
+ this._vw_workerTarget.addEventListener("connect", (e) => {
481
+ context.onconnect?.(e);
482
+ });
483
+ const runner = new InlineWorkerRunner(runnerOptions, context);
484
+ const id = getFileIdFromUrl(url);
485
+ this._vw_name = id;
486
+ runner.resolveUrl(id).then(([, fsPath]) => {
487
+ this._vw_name = name ?? fsPath;
488
+ debug("initialize shared worker %s", this._vw_name);
489
+ return runner.executeFile(fsPath).then(() => {
490
+ runnerOptions.moduleCache.invalidateSubDepTree([fsPath, runner.mocker.getMockPath(fsPath)]);
491
+ this._vw_workerTarget.dispatchEvent(new MessageEvent("connect", { ports: [this._vw_workerPort] }));
492
+ debug("shared worker %s successfully initialized", this._vw_name);
493
+ });
494
+ }).catch((e) => {
495
+ debug("shared worker %s failed to initialize: %o", this._vw_name, e);
496
+ const EventConstructor = globalThis.ErrorEvent || globalThis.Event;
497
+ const error = new EventConstructor("error", {
498
+ error: e,
499
+ message: e.message
500
+ });
501
+ this.dispatchEvent(error);
502
+ this.onerror?.(error);
503
+ console.error(e);
504
+ });
505
+ }
506
+ };
528
507
  }
529
508
 
530
509
  function createWorkerConstructor(options) {
531
- const runnerOptions = getRunnerOptions();
532
- const cloneType = () => options?.clone ?? process.env.VITEST_WEB_WORKER_CLONE ?? "native";
533
- return class Worker extends EventTarget {
534
- static __VITEST_WEB_WORKER__ = true;
535
- _vw_workerTarget = new EventTarget();
536
- _vw_insideListeners = /* @__PURE__ */ new Map();
537
- _vw_outsideListeners = /* @__PURE__ */ new Map();
538
- _vw_name;
539
- _vw_messageQueue = [];
540
- onmessage = null;
541
- onmessageerror = null;
542
- onerror = null;
543
- constructor(url, options2) {
544
- super();
545
- let selfProxy;
546
- const context = {
547
- onmessage: null,
548
- onmessageerror: null,
549
- onerror: null,
550
- onlanguagechange: null,
551
- onoffline: null,
552
- ononline: null,
553
- onrejectionhandled: null,
554
- onrtctransform: null,
555
- onunhandledrejection: null,
556
- origin: typeof location !== "undefined" ? location.origin : "http://localhost:3000",
557
- importScripts: () => {
558
- throw new Error(
559
- "[vitest] `importScripts` is not supported in Vite workers. Please, consider using `import` instead."
560
- );
561
- },
562
- crossOriginIsolated: false,
563
- name: options2?.name || "",
564
- close: () => this.terminate(),
565
- dispatchEvent: (event) => {
566
- return this._vw_workerTarget.dispatchEvent(event);
567
- },
568
- addEventListener: (...args) => {
569
- if (args[1]) {
570
- this._vw_insideListeners.set(args[0], args[1]);
571
- }
572
- return this._vw_workerTarget.addEventListener(...args);
573
- },
574
- removeEventListener: (...args) => {
575
- return this._vw_workerTarget.removeEventListener(...args);
576
- },
577
- postMessage: (...args) => {
578
- if (!args.length) {
579
- throw new SyntaxError(
580
- '"postMessage" requires at least one argument.'
581
- );
582
- }
583
- debug(
584
- "posting message %o from the worker %s to the main thread",
585
- args[0],
586
- this._vw_name
587
- );
588
- const event = createMessageEvent(args[0], args[1], cloneType());
589
- this.dispatchEvent(event);
590
- },
591
- get self() {
592
- return selfProxy;
593
- }
594
- };
595
- selfProxy = new Proxy(context, {
596
- get(target, prop, receiver) {
597
- if (Reflect.has(target, prop)) {
598
- return Reflect.get(target, prop, receiver);
599
- }
600
- return globalThis[prop];
601
- }
602
- });
603
- this._vw_workerTarget.addEventListener("message", (e) => {
604
- context.onmessage?.(e);
605
- });
606
- this.addEventListener("message", (e) => {
607
- this.onmessage?.(e);
608
- });
609
- this.addEventListener("messageerror", (e) => {
610
- this.onmessageerror?.(e);
611
- });
612
- const runner = new InlineWorkerRunner(runnerOptions, context);
613
- const id = getFileIdFromUrl(url);
614
- this._vw_name = id;
615
- runner.resolveUrl(id).then(([, fsPath]) => {
616
- this._vw_name = options2?.name ?? fsPath;
617
- debug("initialize worker %s", this._vw_name);
618
- return runner.executeFile(fsPath).then(() => {
619
- runnerOptions.moduleCache.invalidateSubDepTree([
620
- fsPath,
621
- runner.mocker.getMockPath(fsPath)
622
- ]);
623
- const q = this._vw_messageQueue;
624
- this._vw_messageQueue = null;
625
- if (q) {
626
- q.forEach(
627
- ([data, transfer]) => this.postMessage(data, transfer),
628
- this
629
- );
630
- }
631
- debug("worker %s successfully initialized", this._vw_name);
632
- });
633
- }).catch((e) => {
634
- debug("worker %s failed to initialize: %o", this._vw_name, e);
635
- const EventConstructor = globalThis.ErrorEvent || globalThis.Event;
636
- const error = new EventConstructor("error", {
637
- error: e,
638
- message: e.message
639
- });
640
- this.dispatchEvent(error);
641
- this.onerror?.(error);
642
- console.error(e);
643
- });
644
- }
645
- addEventListener(type, callback, options2) {
646
- if (callback) {
647
- this._vw_outsideListeners.set(type, callback);
648
- }
649
- return super.addEventListener(type, callback, options2);
650
- }
651
- postMessage(...args) {
652
- if (!args.length) {
653
- throw new SyntaxError('"postMessage" requires at least one argument.');
654
- }
655
- const [data, transferOrOptions] = args;
656
- if (this._vw_messageQueue != null) {
657
- debug(
658
- "worker %s is not yet initialized, queue message %s",
659
- this._vw_name,
660
- data
661
- );
662
- this._vw_messageQueue.push([data, transferOrOptions]);
663
- return;
664
- }
665
- debug(
666
- "posting message %o from the main thread to the worker %s",
667
- data,
668
- this._vw_name
669
- );
670
- const event = createMessageEvent(data, transferOrOptions, cloneType());
671
- if (event.type === "messageerror") {
672
- this.dispatchEvent(event);
673
- } else {
674
- this._vw_workerTarget.dispatchEvent(event);
675
- }
676
- }
677
- terminate() {
678
- debug("terminating worker %s", this._vw_name);
679
- this._vw_outsideListeners.forEach((fn, type) => {
680
- this.removeEventListener(type, fn);
681
- });
682
- this._vw_insideListeners.forEach((fn, type) => {
683
- this._vw_workerTarget.removeEventListener(type, fn);
684
- });
685
- }
686
- };
510
+ const runnerOptions = getRunnerOptions();
511
+ const cloneType = () => options?.clone ?? process.env.VITEST_WEB_WORKER_CLONE ?? "native";
512
+ return class Worker extends EventTarget {
513
+ static __VITEST_WEB_WORKER__ = true;
514
+ _vw_workerTarget = new EventTarget();
515
+ _vw_insideListeners = new Map();
516
+ _vw_outsideListeners = new Map();
517
+ _vw_name;
518
+ _vw_messageQueue = [];
519
+ onmessage = null;
520
+ onmessageerror = null;
521
+ onerror = null;
522
+ constructor(url, options) {
523
+ super();
524
+ let selfProxy;
525
+ const context = {
526
+ onmessage: null,
527
+ onmessageerror: null,
528
+ onerror: null,
529
+ onlanguagechange: null,
530
+ onoffline: null,
531
+ ononline: null,
532
+ onrejectionhandled: null,
533
+ onrtctransform: null,
534
+ onunhandledrejection: null,
535
+ origin: typeof location !== "undefined" ? location.origin : "http://localhost:3000",
536
+ importScripts: () => {
537
+ throw new Error("[vitest] `importScripts` is not supported in Vite workers. Please, consider using `import` instead.");
538
+ },
539
+ crossOriginIsolated: false,
540
+ name: options?.name || "",
541
+ close: () => this.terminate(),
542
+ dispatchEvent: (event) => {
543
+ return this._vw_workerTarget.dispatchEvent(event);
544
+ },
545
+ addEventListener: (...args) => {
546
+ if (args[1]) {
547
+ this._vw_insideListeners.set(args[0], args[1]);
548
+ }
549
+ return this._vw_workerTarget.addEventListener(...args);
550
+ },
551
+ removeEventListener: (...args) => {
552
+ return this._vw_workerTarget.removeEventListener(...args);
553
+ },
554
+ postMessage: (...args) => {
555
+ if (!args.length) {
556
+ throw new SyntaxError("\"postMessage\" requires at least one argument.");
557
+ }
558
+ debug("posting message %o from the worker %s to the main thread", args[0], this._vw_name);
559
+ const event = createMessageEvent(args[0], args[1], cloneType());
560
+ this.dispatchEvent(event);
561
+ },
562
+ get self() {
563
+ return selfProxy;
564
+ }
565
+ };
566
+ selfProxy = new Proxy(context, { get(target, prop, receiver) {
567
+ if (Reflect.has(target, prop)) {
568
+ return Reflect.get(target, prop, receiver);
569
+ }
570
+ return globalThis[prop];
571
+ } });
572
+ this._vw_workerTarget.addEventListener("message", (e) => {
573
+ context.onmessage?.(e);
574
+ });
575
+ this.addEventListener("message", (e) => {
576
+ this.onmessage?.(e);
577
+ });
578
+ this.addEventListener("messageerror", (e) => {
579
+ this.onmessageerror?.(e);
580
+ });
581
+ const runner = new InlineWorkerRunner(runnerOptions, context);
582
+ const id = getFileIdFromUrl(url);
583
+ this._vw_name = id;
584
+ runner.resolveUrl(id).then(([, fsPath]) => {
585
+ this._vw_name = options?.name ?? fsPath;
586
+ debug("initialize worker %s", this._vw_name);
587
+ return runner.executeFile(fsPath).then(() => {
588
+ runnerOptions.moduleCache.invalidateSubDepTree([fsPath, runner.mocker.getMockPath(fsPath)]);
589
+ const q = this._vw_messageQueue;
590
+ this._vw_messageQueue = null;
591
+ if (q) {
592
+ q.forEach(([data, transfer]) => this.postMessage(data, transfer), this);
593
+ }
594
+ debug("worker %s successfully initialized", this._vw_name);
595
+ });
596
+ }).catch((e) => {
597
+ debug("worker %s failed to initialize: %o", this._vw_name, e);
598
+ const EventConstructor = globalThis.ErrorEvent || globalThis.Event;
599
+ const error = new EventConstructor("error", {
600
+ error: e,
601
+ message: e.message
602
+ });
603
+ this.dispatchEvent(error);
604
+ this.onerror?.(error);
605
+ console.error(e);
606
+ });
607
+ }
608
+ addEventListener(type, callback, options) {
609
+ if (callback) {
610
+ this._vw_outsideListeners.set(type, callback);
611
+ }
612
+ return super.addEventListener(type, callback, options);
613
+ }
614
+ postMessage(...args) {
615
+ if (!args.length) {
616
+ throw new SyntaxError("\"postMessage\" requires at least one argument.");
617
+ }
618
+ const [data, transferOrOptions] = args;
619
+ if (this._vw_messageQueue != null) {
620
+ debug("worker %s is not yet initialized, queue message %s", this._vw_name, data);
621
+ this._vw_messageQueue.push([data, transferOrOptions]);
622
+ return;
623
+ }
624
+ debug("posting message %o from the main thread to the worker %s", data, this._vw_name);
625
+ const event = createMessageEvent(data, transferOrOptions, cloneType());
626
+ if (event.type === "messageerror") {
627
+ this.dispatchEvent(event);
628
+ } else {
629
+ this._vw_workerTarget.dispatchEvent(event);
630
+ }
631
+ }
632
+ terminate() {
633
+ debug("terminating worker %s", this._vw_name);
634
+ this._vw_outsideListeners.forEach((fn, type) => {
635
+ this.removeEventListener(type, fn);
636
+ });
637
+ this._vw_insideListeners.forEach((fn, type) => {
638
+ this._vw_workerTarget.removeEventListener(type, fn);
639
+ });
640
+ }
641
+ };
687
642
  }
688
643
 
689
644
  function defineWebWorkers(options) {
690
- if (typeof Worker === "undefined" || !("__VITEST_WEB_WORKER__" in globalThis.Worker)) {
691
- assertGlobalExists("EventTarget");
692
- assertGlobalExists("MessageEvent");
693
- globalThis.Worker = createWorkerConstructor(options);
694
- }
695
- if (typeof SharedWorker === "undefined" || !("__VITEST_WEB_WORKER__" in globalThis.SharedWorker)) {
696
- assertGlobalExists("EventTarget");
697
- globalThis.SharedWorker = createSharedWorkerConstructor();
698
- }
645
+ if (typeof Worker === "undefined" || !("__VITEST_WEB_WORKER__" in globalThis.Worker)) {
646
+ assertGlobalExists("EventTarget");
647
+ assertGlobalExists("MessageEvent");
648
+ globalThis.Worker = createWorkerConstructor(options);
649
+ }
650
+ if (typeof SharedWorker === "undefined" || !("__VITEST_WEB_WORKER__" in globalThis.SharedWorker)) {
651
+ assertGlobalExists("EventTarget");
652
+ globalThis.SharedWorker = createSharedWorkerConstructor();
653
+ }
699
654
  }
700
655
 
701
656
  export { defineWebWorkers };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/web-worker",
3
3
  "type": "module",
4
- "version": "3.1.0-beta.1",
4
+ "version": "3.1.0",
5
5
  "description": "Web Worker support for testing in Vitest",
6
6
  "license": "MIT",
7
7
  "funding": "https://opencollective.com/vitest",
@@ -33,7 +33,7 @@
33
33
  "dist"
34
34
  ],
35
35
  "peerDependencies": {
36
- "vitest": "3.1.0-beta.1"
36
+ "vitest": "3.1.0"
37
37
  },
38
38
  "dependencies": {
39
39
  "debug": "^4.4.0"