vitest 4.0.0-beta.8 → 4.0.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 (85) hide show
  1. package/LICENSE.md +86 -102
  2. package/browser/context.d.ts +7 -0
  3. package/browser/context.js +20 -0
  4. package/dist/browser.d.ts +26 -9
  5. package/dist/browser.js +17 -7
  6. package/dist/chunks/base.CtHM3ryk.js +128 -0
  7. package/dist/chunks/{benchmark.UW6Ezvxy.js → benchmark.DHKMYAts.js} +2 -2
  8. package/dist/chunks/{browser.d.DOMmqJQx.d.ts → browser.d.B9iJzZyn.d.ts} +3 -3
  9. package/dist/chunks/{cac.By1HvRIk.js → cac.B99MQg-w.js} +47 -91
  10. package/dist/chunks/{cli-api.C-JHgQgp.js → cli-api.PwHwIMss.js} +1544 -310
  11. package/dist/chunks/{config.d._GBBbReY.d.ts → config.d.u2CUDWwS.d.ts} +6 -19
  12. package/dist/chunks/{console.B0quX7yH.js → console.CTJL2nuH.js} +4 -6
  13. package/dist/chunks/{coverage.DarITf6U.js → coverage.FU3w4IrQ.js} +128 -1142
  14. package/dist/chunks/{creator.KEg6n5IC.js → creator.DucAaYBz.js} +10 -37
  15. package/dist/chunks/{defaults.CXFFjsi8.js → defaults.BOqNVLsY.js} +0 -1
  16. package/dist/chunks/environment.d.CrsxCzP1.d.ts +29 -0
  17. package/dist/chunks/evaluatedModules.Dg1zASAC.js +17 -0
  18. package/dist/chunks/{global.d.K6uBQHzY.d.ts → global.d.BgJSTpgQ.d.ts} +2 -17
  19. package/dist/chunks/{globals.lgsmH00r.js → globals.BGT_RUsD.js} +12 -9
  20. package/dist/chunks/{index.BuwjkI-q.js → index.BdSLhLDZ.js} +3 -3
  21. package/dist/chunks/{index.DfviD7lX.js → index.CbWINfS7.js} +49 -21
  22. package/dist/chunks/{index.AzwzFtyi.js → index.CcRZ6fUh.js} +1493 -114
  23. package/dist/chunks/{index.X0nbfr6-.js → index.Dc3xnDvT.js} +48 -289
  24. package/dist/chunks/{index.AR8aAkCC.js → index.RwjEGCQ0.js} +7 -8
  25. package/dist/chunks/init-forks.DSafeltJ.js +54 -0
  26. package/dist/chunks/init-threads.SUtZ-067.js +17 -0
  27. package/dist/chunks/init.B2EESLQM.js +213 -0
  28. package/dist/chunks/{inspector.CvQD-Nie.js → inspector.DLZxSeU3.js} +2 -6
  29. package/dist/chunks/{moduleRunner.d.CX4DuqOx.d.ts → moduleRunner.d.YtNsMIoJ.d.ts} +12 -14
  30. package/dist/chunks/{node.BOqcT2jW.js → node.BwAWWjHZ.js} +3 -4
  31. package/dist/chunks/{plugin.d.CHe6slQs.d.ts → plugin.d.DQU1R5px.d.ts} +1 -1
  32. package/dist/chunks/{reporters.d.37tJQ2uV.d.ts → reporters.d.BMKt7f6I.d.ts} +1066 -1030
  33. package/dist/chunks/{index.CsFXYRkW.js → resolveSnapshotEnvironment.DJJKMKxb.js} +18 -24
  34. package/dist/chunks/{rpc.RpPylpp0.js → rpc.cD77ENhU.js} +13 -14
  35. package/dist/chunks/{setup-common.hLGRxhC8.js → setup-common.DR1sucx6.js} +8 -8
  36. package/dist/chunks/{startModuleRunner.C8TW8zTN.js → startModuleRunner.C2tTvmF9.js} +131 -110
  37. package/dist/chunks/test.C3RPt8JR.js +214 -0
  38. package/dist/chunks/{utils.C7__0Iv5.js → utils.CG9h5ccR.js} +3 -15
  39. package/dist/chunks/{vi.BfdOiD4j.js → vi.BZvkKVkM.js} +73 -176
  40. package/dist/chunks/{vm.BHBje7cC.js → vm.DBeOXrP9.js} +29 -33
  41. package/dist/chunks/{worker.d.DYlqbejz.d.ts → worker.d.BFk-vvBU.d.ts} +42 -6
  42. package/dist/cli.js +12 -11
  43. package/dist/config.cjs +0 -1
  44. package/dist/config.d.ts +12 -14
  45. package/dist/config.js +1 -1
  46. package/dist/coverage.d.ts +8 -7
  47. package/dist/coverage.js +3 -14
  48. package/dist/environments.d.ts +3 -6
  49. package/dist/environments.js +1 -1
  50. package/dist/index.d.ts +24 -30
  51. package/dist/index.js +12 -11
  52. package/dist/module-evaluator.d.ts +6 -4
  53. package/dist/module-evaluator.js +14 -16
  54. package/dist/module-runner.js +5 -5
  55. package/dist/node.d.ts +83 -27
  56. package/dist/node.js +23 -20
  57. package/dist/reporters.d.ts +11 -10
  58. package/dist/reporters.js +12 -11
  59. package/dist/runners.d.ts +1 -1
  60. package/dist/runners.js +14 -216
  61. package/dist/snapshot.js +3 -3
  62. package/dist/suite.js +4 -3
  63. package/dist/worker.d.ts +26 -0
  64. package/dist/worker.js +45 -166
  65. package/dist/workers/forks.js +41 -35
  66. package/dist/workers/runVmTests.js +25 -22
  67. package/dist/workers/threads.js +41 -23
  68. package/dist/workers/vmForks.js +26 -39
  69. package/dist/workers/vmThreads.js +26 -29
  70. package/package.json +48 -35
  71. package/worker.d.ts +1 -0
  72. package/browser.d.ts +0 -1
  73. package/dist/chunks/base.BXI97p6t.js +0 -39
  74. package/dist/chunks/environment.d.2fYMoz3o.d.ts +0 -66
  75. package/dist/chunks/moduleTransport.I-bgQy0S.js +0 -19
  76. package/dist/chunks/resolver.Bx6lE0iq.js +0 -119
  77. package/dist/chunks/runBaseTests.D6sfuWBM.js +0 -99
  78. package/dist/chunks/typechecker.DSo_maXz.js +0 -762
  79. package/dist/chunks/utils.C2YI6McM.js +0 -52
  80. package/dist/chunks/worker.d.BKu8cnnX.d.ts +0 -8
  81. package/dist/workers.d.ts +0 -38
  82. package/dist/workers.js +0 -31
  83. package/execute.d.ts +0 -1
  84. package/utils.d.ts +0 -1
  85. package/workers.d.ts +0 -1
@@ -2,11 +2,12 @@ import { existsSync, writeFileSync, readFileSync } from 'node:fs';
2
2
  import { mkdir, writeFile } from 'node:fs/promises';
3
3
  import { resolve, dirname, relative } from 'node:path';
4
4
  import { detectPackageManager, installPackage } from './index.D3XRDfWc.js';
5
- import { p as prompt, f as findUp } from './index.X0nbfr6-.js';
5
+ import { p as prompt, a as any } from './index.Dc3xnDvT.js';
6
6
  import { x } from 'tinyexec';
7
7
  import c from 'tinyrainbow';
8
8
  import { c as configFiles } from './constants.D_Q9UYh-.js';
9
9
  import 'node:process';
10
+ import 'node:module';
10
11
  import 'node:url';
11
12
  import './_commonjsHelpers.BFTU3MAI.js';
12
13
  import 'readline';
@@ -38,7 +39,7 @@ import { render } from '@testing-library/jsx'
38
39
  import HelloWorld from './HelloWorld.jsx'
39
40
 
40
41
  test('renders name', async () => {
41
- const { getByText } = render(<HelloWorld name="Vitest" />)
42
+ const { getByText } = await render(<HelloWorld name="Vitest" />)
42
43
  await expect.element(getByText('Hello Vitest!')).toBeInTheDocument()
43
44
  })
44
45
  `
@@ -297,12 +298,11 @@ async function generateExampleFiles(framework, lang) {
297
298
  // eslint-disable-next-line no-console
298
299
  const log = console.log;
299
300
  function getProviderOptions() {
300
- const providers = {
301
+ return Object.entries({
301
302
  playwright: "Playwright relies on Chrome DevTools protocol. Read more: https://playwright.dev",
302
303
  webdriverio: "WebdriverIO uses WebDriver protocol. Read more: https://webdriver.io",
303
304
  preview: "Preview is useful to quickly run your tests in the browser, but not suitable for CI."
304
- };
305
- return Object.entries(providers).map(([provider, description]) => {
305
+ }).map(([provider, description]) => {
306
306
  return {
307
307
  title: provider,
308
308
  description,
@@ -330,23 +330,6 @@ function getBrowserNames(provider) {
330
330
  ];
331
331
  }
332
332
  }
333
- function getProviderPackageNames(provider) {
334
- switch (provider) {
335
- case "webdriverio": return {
336
- types: "@vitest/browser/providers/webdriverio",
337
- pkg: "webdriverio"
338
- };
339
- case "playwright": return {
340
- types: "@vitest/browser/providers/playwright",
341
- pkg: "playwright"
342
- };
343
- case "preview": return {
344
- types: "@vitest/browser/matchers",
345
- pkg: null
346
- };
347
- }
348
- throw new Error(`Unsupported provider: ${provider}`);
349
- }
350
333
  function getFramework() {
351
334
  return [
352
335
  {
@@ -422,11 +405,6 @@ function getFrameworkPluginPackage(framework) {
422
405
  }
423
406
  return null;
424
407
  }
425
- async function updateTsConfig(type) {
426
- if (type == null) return;
427
- const msg = `Add "${c.bold(type)}" to your tsconfig.json "${c.bold("compilerOptions.types")}" field to have better intellisense support.`;
428
- log(), log(c.yellow("◼"), c.yellow(msg));
429
- }
430
408
  function getLanguageOptions() {
431
409
  return [{
432
410
  title: "TypeScript",
@@ -476,9 +454,7 @@ function getProviderDocsLink(provider) {
476
454
  }
477
455
  function sort(choices, value) {
478
456
  const index = choices.findIndex((i) => i.value === value);
479
- if (index === -1) return choices;
480
- const item = choices.splice(index, 1)[0];
481
- return [item, ...choices];
457
+ return index === -1 ? choices : [choices.splice(index, 1)[0], ...choices];
482
458
  }
483
459
  function fail() {
484
460
  process.exitCode = 1;
@@ -502,6 +478,7 @@ function getFrameworkImportInfo(framework) {
502
478
  async function generateFrameworkConfigFile(options) {
503
479
  const { importName, isNamedExport } = getFrameworkImportInfo(options.framework), frameworkImport = isNamedExport ? `import { ${importName} } from '${options.frameworkPlugin}'` : `import ${importName} from '${options.frameworkPlugin}'`, configContent = [
504
480
  `import { defineConfig } from 'vitest/config'`,
481
+ `import { ${options.provider} } from '@vitest/browser-${options.provider}'`,
505
482
  options.frameworkPlugin ? frameworkImport : null,
506
483
  ``,
507
484
  "export default defineConfig({",
@@ -509,7 +486,7 @@ async function generateFrameworkConfigFile(options) {
509
486
  ` test: {`,
510
487
  ` browser: {`,
511
488
  ` enabled: true,`,
512
- ` provider: '${options.provider}',`,
489
+ ` provider: ${options.provider}(),`,
513
490
  options.provider !== "preview" && ` // ${getProviderDocsLink(options.provider)}`,
514
491
  ` instances: [`,
515
492
  ...options.browsers.map((browser) => ` { browser: '${browser}' },`),
@@ -594,15 +571,13 @@ async function create() {
594
571
  message: `Install Playwright browsers (can be done manually via 'pnpm exec playwright install')?`
595
572
  }));
596
573
  if (installPlaywright == null) return fail();
597
- const dependenciesToInstall = ["@vitest/browser"], frameworkPackage = getFrameworkTestPackage(framework);
574
+ const dependenciesToInstall = [`@vitest/browser-${provider}`], frameworkPackage = getFrameworkTestPackage(framework);
598
575
  if (frameworkPackage) dependenciesToInstall.push(frameworkPackage);
599
- const providerPkg = getProviderPackageNames(provider);
600
- if (providerPkg.pkg) dependenciesToInstall.push(providerPkg.pkg);
601
576
  const frameworkPlugin = getFrameworkPluginPackage(framework);
602
577
  if (frameworkPlugin) dependenciesToInstall.push(frameworkPlugin);
603
578
  const pkgManager = await detectPackageManager();
604
579
  log(), await installPackages(pkgManager, dependenciesToInstall.filter((pkg) => !dependencies[pkg]));
605
- const rootConfig = await findUp(configFiles, { cwd: process.cwd() });
580
+ const rootConfig = any(configFiles, { cwd: process.cwd() });
606
581
  let scriptCommand = "vitest";
607
582
  if (log(), rootConfig) {
608
583
  const configPath = resolve(dirname(rootConfig), `vitest.browser.config.${lang}`);
@@ -645,8 +620,6 @@ async function create() {
645
620
  "inherit"
646
621
  ] } });
647
622
  }
648
- // TODO: can we do this ourselves?
649
- if (lang === "ts") await updateTsConfig(providerPkg?.types);
650
623
  log();
651
624
  const exampleTestFile = await generateExampleFiles(framework, lang);
652
625
  log(c.green("✔"), "Created example test file in", c.bold(relative(process.cwd(), exampleTestFile))), log(c.dim(" You can safely delete this file once you have written your own tests.")), log(), log(c.cyan("◼"), "All done! Run your tests with", c.bold(getRunScript(pkgManager)));
@@ -40,7 +40,6 @@ const configDefaults = Object.freeze({
40
40
  watch: !isCI && process.stdin.isTTY,
41
41
  globals: false,
42
42
  environment: "node",
43
- pool: "forks",
44
43
  clearMocks: false,
45
44
  restoreMocks: false,
46
45
  mockReset: false,
@@ -0,0 +1,29 @@
1
+ import { Awaitable } from '@vitest/utils';
2
+
3
+ interface EnvironmentReturn {
4
+ teardown: (global: any) => Awaitable<void>;
5
+ }
6
+ interface VmEnvironmentReturn {
7
+ getVmContext: () => {
8
+ [key: string]: any;
9
+ };
10
+ teardown: () => Awaitable<void>;
11
+ }
12
+ interface Environment {
13
+ name: string;
14
+ /**
15
+ * @deprecated use `viteEnvironment` instead. Uses `name` by default
16
+ */
17
+ transformMode?: "web" | "ssr";
18
+ /**
19
+ * Environment initiated by the Vite server. It is usually available
20
+ * as `vite.server.environments.${name}`.
21
+ *
22
+ * By default, fallbacks to `name`.
23
+ */
24
+ viteEnvironment?: "client" | "ssr" | ({} & string);
25
+ setupVM?: (options: Record<string, any>) => Awaitable<VmEnvironmentReturn>;
26
+ setup: (global: any, options: Record<string, any>) => Awaitable<EnvironmentReturn>;
27
+ }
28
+
29
+ export type { Environment as E, VmEnvironmentReturn as V, EnvironmentReturn as a };
@@ -0,0 +1,17 @@
1
+ import { dirname, resolve } from 'pathe';
2
+ import { EvaluatedModules } from 'vite/module-runner';
3
+
4
+ // TODO: this is not needed in Vite 7.2+
5
+ class VitestEvaluatedModules extends EvaluatedModules {
6
+ getModuleSourceMapById(id) {
7
+ const map = super.getModuleSourceMapById(id);
8
+ if (map != null && !("_patched" in map)) {
9
+ map._patched = true;
10
+ const dir = dirname(map.url);
11
+ map.resolvedSources = (map.map.sources || []).map((s) => resolve(dir, s || ""));
12
+ }
13
+ return map;
14
+ }
15
+ }
16
+
17
+ export { VitestEvaluatedModules as V };
@@ -2,23 +2,8 @@ import { PromisifyAssertion, Tester, ExpectStatic } from '@vitest/expect';
2
2
  import { Plugin } from '@vitest/pretty-format';
3
3
  import { SnapshotState } from '@vitest/snapshot';
4
4
  import { B as BenchmarkResult } from './benchmark.d.DAaHLpsq.js';
5
- import { U as UserConsoleLog } from './environment.d.2fYMoz3o.js';
5
+ import { U as UserConsoleLog } from './worker.d.BFk-vvBU.js';
6
6
 
7
- declare global {
8
- // eslint-disable-next-line ts/no-namespace
9
- namespace Chai {
10
- interface ContainSubset {
11
- (expected: any): Assertion;
12
- }
13
- interface Assertion {
14
- containSubset: ContainSubset;
15
- }
16
- interface Assert {
17
- // eslint-disable-next-line ts/method-signature-style
18
- containSubset(val: any, exp: any, msg?: string): void;
19
- }
20
- }
21
- }
22
7
  interface SnapshotMatcher<T> {
23
8
  <U extends { [P in keyof T] : any }>(snapshot: Partial<U>, hint?: string): void;
24
9
  (hint?: string): void;
@@ -38,6 +23,7 @@ declare module "@vitest/expect" {
38
23
  message?: string;
39
24
  }
40
25
  interface ExpectStatic {
26
+ assert: Chai.AssertStatic;
41
27
  unreachable: (message?: string) => never;
42
28
  soft: <T>(actual: T, message?: string) => Assertion<T>;
43
29
  poll: <T>(actual: () => T, options?: ExpectPollOptions) => PromisifyAssertion<Awaited<T>>;
@@ -47,7 +33,6 @@ declare module "@vitest/expect" {
47
33
  addSnapshotSerializer: (plugin: Plugin) => void;
48
34
  }
49
35
  interface Assertion<T> {
50
- // Snapshots are extended in @vitest/snapshot and are not part of @vitest/expect
51
36
  matchSnapshot: SnapshotMatcher<T>;
52
37
  toMatchSnapshot: SnapshotMatcher<T>;
53
38
  toMatchInlineSnapshot: InlineSnapshotMatcher<T>;
@@ -1,26 +1,29 @@
1
1
  import { g as globalApis } from './constants.D_Q9UYh-.js';
2
- import { V as VitestIndex } from './index.AR8aAkCC.js';
3
- import './vi.BfdOiD4j.js';
2
+ import { i as index } from './index.RwjEGCQ0.js';
3
+ import './vi.BZvkKVkM.js';
4
4
  import '@vitest/expect';
5
5
  import '@vitest/runner';
6
6
  import '@vitest/runner/utils';
7
- import 'chai';
8
- import './utils.C7__0Iv5.js';
9
- import '@vitest/utils';
10
- import './_commonjsHelpers.BFTU3MAI.js';
7
+ import './utils.CG9h5ccR.js';
8
+ import '@vitest/utils/timers';
11
9
  import '@vitest/snapshot';
12
10
  import '@vitest/utils/error';
11
+ import '@vitest/utils/helpers';
13
12
  import '@vitest/spy';
13
+ import '@vitest/utils/offset';
14
14
  import '@vitest/utils/source-map';
15
+ import './_commonjsHelpers.BFTU3MAI.js';
15
16
  import './date.-jtEtIeV.js';
16
- import './benchmark.UW6Ezvxy.js';
17
- import 'expect-type';
17
+ import './benchmark.DHKMYAts.js';
18
+ import './evaluatedModules.Dg1zASAC.js';
19
+ import 'pathe';
18
20
  import 'vite/module-runner';
21
+ import 'expect-type';
19
22
 
20
23
  function registerApiGlobally() {
21
24
  globalApis.forEach((api) => {
22
25
  // @ts-expect-error I know what I am doing :P
23
- globalThis[api] = VitestIndex[api];
26
+ globalThis[api] = index[api];
24
27
  });
25
28
  }
26
29
 
@@ -2,9 +2,9 @@ import fs from 'node:fs';
2
2
  import { getTasks, getFullName, getTests } from '@vitest/runner/utils';
3
3
  import * as pathe from 'pathe';
4
4
  import c from 'tinyrainbow';
5
- import { g as getStateSymbol, t as truncateString, F as F_RIGHT, D as DefaultReporter, f as formatProjectName } from './index.AzwzFtyi.js';
5
+ import { g as getStateSymbol, t as truncateString, F as F_RIGHT, D as DefaultReporter, f as formatProjectName, s as separator } from './index.CcRZ6fUh.js';
6
6
  import { stripVTControlCharacters } from 'node:util';
7
- import { notNullish } from '@vitest/utils';
7
+ import { notNullish } from '@vitest/utils/helpers';
8
8
 
9
9
  function createBenchmarkJsonReport(files) {
10
10
  const report = { files: [] };
@@ -183,7 +183,7 @@ class BenchmarkReporter extends DefaultReporter {
183
183
  if (state === "pending" || state === "queued") return;
184
184
  const benches = testTask.task.tasks.filter((t) => t.meta.benchmark), duration = testTask.task.result?.duration || 0;
185
185
  if (benches.length > 0 && benches.every((t) => t.result?.state !== "run" && t.result?.state !== "queued")) {
186
- let title = `\n ${getStateSymbol(testTask.task)} ${formatProjectName(testTask.project)}${getFullName(testTask.task, c.dim(" > "))}`;
186
+ let title = `\n ${getStateSymbol(testTask.task)} ${formatProjectName(testTask.project)}${getFullName(testTask.task, separator)}`;
187
187
  if (duration != null && duration > this.ctx.config.slowTestThreshold) title += c.yellow(` ${Math.round(duration)}${c.dim("ms")}`);
188
188
  this.log(title), this.log(renderTable({
189
189
  tasks: benches,
@@ -238,10 +238,10 @@ const skipKeys = [
238
238
  "parent"
239
239
  ];
240
240
  function getWindowKeys(global, win, additionalKeys = []) {
241
- const keysArray = [...additionalKeys, ...KEYS], keys = new Set(keysArray.concat(Object.getOwnPropertyNames(win)).filter((k) => {
241
+ const keysArray = [...additionalKeys, ...KEYS];
242
+ return new Set(keysArray.concat(Object.getOwnPropertyNames(win)).filter((k) => {
242
243
  return skipKeys.includes(k) ? false : k in global ? keysArray.includes(k) : true;
243
244
  }));
244
- return keys;
245
245
  }
246
246
  function isClassLikeName(name) {
247
247
  return name[0] === name[0].toUpperCase();
@@ -391,25 +391,20 @@ var jsdom = {
391
391
  userAgent,
392
392
  ...restOptions
393
393
  });
394
- const clearWindowErrors = catchWindowErrors(dom.window);
394
+ const clearAddEventListenerPatch = patchAddEventListener(dom.window), clearWindowErrors = catchWindowErrors(dom.window);
395
395
  dom.window.Buffer = Buffer, dom.window.jsdom = dom;
396
- // inject web globals if they missing in JSDOM but otherwise available in Nodejs
397
- // https://nodejs.org/dist/latest/docs/api/globals.html
398
- const globalNames = [
396
+ for (const name of [
399
397
  "structuredClone",
400
398
  "BroadcastChannel",
401
399
  "MessageChannel",
402
400
  "MessagePort",
403
401
  "TextEncoder",
404
402
  "TextDecoder"
405
- ];
406
- for (const name of globalNames) {
403
+ ]) {
407
404
  const value = globalThis[name];
408
405
  if (typeof value !== "undefined" && typeof dom.window[name] === "undefined") dom.window[name] = value;
409
406
  }
410
- // since we are providing Node.js's Fetch API,
411
- // we also should override other APIs they use
412
- const overrideGlobals = [
407
+ for (const name of [
413
408
  "fetch",
414
409
  "Request",
415
410
  "Response",
@@ -418,8 +413,7 @@ var jsdom = {
418
413
  "AbortSignal",
419
414
  "URL",
420
415
  "URLSearchParams"
421
- ];
422
- for (const name of overrideGlobals) {
416
+ ]) {
423
417
  const value = globalThis[name];
424
418
  if (typeof value !== "undefined") dom.window[name] = value;
425
419
  }
@@ -428,7 +422,7 @@ var jsdom = {
428
422
  return dom.getInternalVMContext();
429
423
  },
430
424
  teardown() {
431
- clearWindowErrors(), dom.window.close(), dom = void 0;
425
+ clearAddEventListenerPatch(), clearWindowErrors(), dom.window.close(), dom = void 0;
432
426
  }
433
427
  };
434
428
  },
@@ -444,12 +438,37 @@ var jsdom = {
444
438
  contentType,
445
439
  userAgent,
446
440
  ...restOptions
447
- }), { keys, originals } = populateGlobal(global, dom.window, { bindFunctions: true }), clearWindowErrors = catchWindowErrors(global);
441
+ }), clearAddEventListenerPatch = patchAddEventListener(dom.window), { keys, originals } = populateGlobal(global, dom.window, { bindFunctions: true }), clearWindowErrors = catchWindowErrors(global);
448
442
  return global.jsdom = dom, { teardown(global) {
449
- clearWindowErrors(), dom.window.close(), delete global.jsdom, keys.forEach((key) => delete global[key]), originals.forEach((v, k) => global[k] = v);
443
+ clearAddEventListenerPatch(), clearWindowErrors(), dom.window.close(), delete global.jsdom, keys.forEach((key) => delete global[key]), originals.forEach((v, k) => global[k] = v);
450
444
  } };
451
445
  }
452
446
  };
447
+ function patchAddEventListener(window) {
448
+ const JSDOMAbortSignal = window.AbortSignal, JSDOMAbortController = window.AbortController, originalAddEventListener = window.EventTarget.prototype.addEventListener;
449
+ return window.EventTarget.prototype.addEventListener = function addEventListener(type, callback, options) {
450
+ if (typeof options === "object" && options.signal != null) {
451
+ const { signal,...otherOptions } = options;
452
+ // - this happens because AbortSignal is provided by Node.js,
453
+ // but jsdom APIs require jsdom's AbortSignal, while Node APIs
454
+ // (like fetch and Request) require a Node.js AbortSignal
455
+ // - disable narrow typing with "as any" because we need it later
456
+ if (!(signal instanceof JSDOMAbortSignal)) {
457
+ const jsdomCompatOptions = Object.create(null);
458
+ Object.assign(jsdomCompatOptions, otherOptions);
459
+ // use jsdom-native abort controller instead and forward the
460
+ // previous one with `addEventListener`
461
+ const jsdomAbortController = new JSDOMAbortController();
462
+ return signal.addEventListener("abort", () => {
463
+ jsdomAbortController.abort(signal.reason);
464
+ }), jsdomCompatOptions.signal = jsdomAbortController.signal, originalAddEventListener.call(this, type, callback, jsdomCompatOptions);
465
+ }
466
+ }
467
+ return originalAddEventListener.call(this, type, callback, options);
468
+ }, () => {
469
+ window.EventTarget.prototype.addEventListener = originalAddEventListener;
470
+ };
471
+ }
453
472
 
454
473
  // some globals we do not want, either because deprecated or we set it ourselves
455
474
  const denyList = new Set([
@@ -459,15 +478,24 @@ const denyList = new Set([
459
478
  "Buffer",
460
479
  "ArrayBuffer",
461
480
  "Uint8Array"
462
- ]), nodeGlobals = new Map(Object.getOwnPropertyNames(globalThis).filter((global) => !denyList.has(global)).map((nodeGlobalsKey) => {
463
- const descriptor = Object.getOwnPropertyDescriptor(globalThis, nodeGlobalsKey);
464
- if (!descriptor) throw new Error(`No property descriptor for ${nodeGlobalsKey}, this is a bug in Vitest.`);
465
- return [nodeGlobalsKey, descriptor];
466
- }));
481
+ ]), nodeGlobals = /* @__PURE__ */ new Map();
482
+ function populateNodeGlobals() {
483
+ if (nodeGlobals.size !== 0) return;
484
+ const names = Object.getOwnPropertyNames(globalThis), length = names.length;
485
+ for (let i = 0; i < length; i++) {
486
+ const globalName = names[i];
487
+ if (!denyList.has(globalName)) {
488
+ const descriptor = Object.getOwnPropertyDescriptor(globalThis, globalName);
489
+ if (!descriptor) throw new Error(`No property descriptor for ${globalName}, this is a bug in Vitest.`);
490
+ nodeGlobals.set(globalName, descriptor);
491
+ }
492
+ }
493
+ }
467
494
  var node = {
468
495
  name: "node",
469
496
  viteEnvironment: "ssr",
470
497
  async setupVM() {
498
+ populateNodeGlobals();
471
499
  const vm = await import('node:vm');
472
500
  let context = vm.createContext(), global = vm.runInContext("this", context);
473
501
  const contextGlobals = new Set(Object.getOwnPropertyNames(global));