@vitest/browser 4.0.5 → 4.0.6

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.
@@ -13,7 +13,7 @@
13
13
  ]
14
14
  },
15
15
  "tester/tester.html": {
16
- "file": "__vitest_browser__/tester-BNxij3za.js",
16
+ "file": "__vitest_browser__/tester-CQlWpWwO.js",
17
17
  "name": "tester",
18
18
  "src": "tester/tester.html",
19
19
  "isEntry": true,
@@ -996,7 +996,7 @@ function createBrowserRunner(runnerClass, mocker, state, coverageModule) {
996
996
  };
997
997
  importFile = async (filepath, mode) => {
998
998
  let hash = this.hashMap.get(filepath);
999
- if (!hash) {
999
+ if (mode === "setup" || !hash) {
1000
1000
  hash = Date.now().toString();
1001
1001
  this.hashMap.set(filepath, hash);
1002
1002
  }
@@ -1,26 +1,37 @@
1
1
  (() => {
2
- const moduleCache = new Map();
3
-
4
- function wrapModule(module) {
5
- if (typeof module === "function") {
6
- const promise = new Promise((resolve, reject) => {
7
- if (typeof __vitest_mocker__ === "undefined")
8
- return module().then(resolve, reject);
9
- __vitest_mocker__.prepare().finally(() => {
10
- module().then(resolve, reject);
11
- });
12
- });
13
- moduleCache.set(promise, { promise, evaluated: false });
14
- return promise.finally(() => moduleCache.delete(promise));
2
+ function wrapModule(moduleCallback) {
3
+ if (typeof moduleCallback !== "function") {
4
+ return moduleCallback
5
+ }
6
+
7
+ if (typeof __vitest_mocker__ === "undefined" || typeof __vitest_worker__ === 'undefined') {
8
+ return moduleCallback()
15
9
  }
16
- return module;
10
+
11
+ const { evaluatedModules } = __vitest_worker__
12
+ const moduleId = crypto.randomUUID()
13
+ const viteModule = evaluatedModules.ensureModule(moduleId, moduleId)
14
+
15
+ viteModule.evaluated = false
16
+ viteModule.promise = new Promise((resolve, reject) => {
17
+ __vitest_mocker__.prepare().finally(() => {
18
+ moduleCallback().then(resolve, reject)
19
+ });
20
+ });
21
+ return viteModule.promise.finally(() => {
22
+ viteModule.evaluated = true
23
+ viteModule.promise = undefined
24
+
25
+ evaluatedModules.idToModuleMap.delete(viteModule.id)
26
+ evaluatedModules.fileToModulesMap.delete(viteModule.file)
27
+ evaluatedModules.urlToIdModuleMap.delete(viteModule.url)
28
+ });
17
29
  }
18
30
 
19
31
  window.__vitest_browser_runner__ = {
20
32
  wrapModule,
21
33
  wrapDynamicImport: wrapModule,
22
34
  disposeExceptionTracker: () => {},
23
- moduleCache,
24
35
  cleanups: [],
25
36
  config: { __VITEST_CONFIG__ },
26
37
  viteConfig: { __VITEST_VITE_CONFIG__ },
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" href="{__VITEST_FAVICON__}" type="image/svg+xml">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Vitest Browser Tester</title>
8
- <script type="module" crossorigin src="/__vitest_browser__/tester-BNxij3za.js"></script>
8
+ <script type="module" crossorigin src="/__vitest_browser__/tester-CQlWpWwO.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-uxqdqUz8.js">
10
10
  </head>
11
11
  <body>
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import { PNG } from 'pngjs';
18
18
  import pm from 'pixelmatch';
19
19
  import { WebSocketServer } from 'ws';
20
20
 
21
- var version = "4.0.5";
21
+ var version = "4.0.6";
22
22
 
23
23
  const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
24
24
  function normalizeWindowsPath(input = "") {
package/dist/state.js CHANGED
@@ -1,111 +1,279 @@
1
1
  (function () {
2
- 'use strict';
2
+ 'use strict';
3
3
 
4
- /* @__NO_SIDE_EFFECTS__ */
5
- function getBrowserState() {
6
- // @ts-expect-error not typed global
7
- return window.__vitest_browser_runner__;
8
- }
4
+ let SOURCEMAPPING_URL = "sourceMa";
5
+ SOURCEMAPPING_URL += "ppingURL";
6
+ const isWindows = typeof process < "u" && process.platform === "win32";
7
+ function unwrapId(id) {
8
+ return id.startsWith("/@id/") ? id.slice(5).replace("__x00__", "\0") : id;
9
+ }
10
+ const windowsSlashRE = /\\/g;
11
+ function slash(p) {
12
+ return p.replace(windowsSlashRE, "/");
13
+ }
14
+ const postfixRE = /[?#].*$/;
15
+ function cleanUrl(url) {
16
+ return url.replace(postfixRE, "");
17
+ }
18
+ const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
19
+ function normalizeWindowsPath(input = "") {
20
+ return input && input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
21
+ }
22
+ const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
23
+ function cwd() {
24
+ return typeof process < "u" && typeof process.cwd == "function" ? process.cwd().replace(/\\/g, "/") : "/";
25
+ }
26
+ const resolve = function(...arguments_) {
27
+ arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
28
+ let resolvedPath = "", resolvedAbsolute = false;
29
+ for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
30
+ let path = index >= 0 ? arguments_[index] : cwd();
31
+ !path || path.length === 0 || (resolvedPath = `${path}/${resolvedPath}`, resolvedAbsolute = isAbsolute(path));
32
+ }
33
+ return resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute), resolvedAbsolute && !isAbsolute(resolvedPath) ? `/${resolvedPath}` : resolvedPath.length > 0 ? resolvedPath : ".";
34
+ };
35
+ function normalizeString(path, allowAboveRoot) {
36
+ let res = "", lastSegmentLength = 0, lastSlash = -1, dots = 0, char = null;
37
+ for (let index = 0; index <= path.length; ++index) {
38
+ if (index < path.length) char = path[index];
39
+ else if (char === "/") break;
40
+ else char = "/";
41
+ if (char === "/") {
42
+ if (!(lastSlash === index - 1 || dots === 1)) if (dots === 2) {
43
+ if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
44
+ if (res.length > 2) {
45
+ let lastSlashIndex = res.lastIndexOf("/");
46
+ lastSlashIndex === -1 ? (res = "", lastSegmentLength = 0) : (res = res.slice(0, lastSlashIndex), lastSegmentLength = res.length - 1 - res.lastIndexOf("/")), lastSlash = index, dots = 0;
47
+ continue;
48
+ } else if (res.length > 0) {
49
+ res = "", lastSegmentLength = 0, lastSlash = index, dots = 0;
50
+ continue;
51
+ }
52
+ }
53
+ allowAboveRoot && (res += res.length > 0 ? "/.." : "..", lastSegmentLength = 2);
54
+ } else res.length > 0 ? res += `/${path.slice(lastSlash + 1, index)}` : res = path.slice(lastSlash + 1, index), lastSegmentLength = index - lastSlash - 1;
55
+ lastSlash = index, dots = 0;
56
+ } else char === "." && dots !== -1 ? ++dots : dots = -1;
57
+ }
58
+ return res;
59
+ }
60
+ const isAbsolute = function(p) {
61
+ return _IS_ABSOLUTE_RE.test(p);
62
+ }, decodeBase64 = typeof atob < "u" ? atob : (str) => Buffer.from(str, "base64").toString("utf-8");
63
+ const posixResolve = resolve;
64
+ const intToChar = new Uint8Array(64), charToInt = new Uint8Array(128);
65
+ for (let i = 0; i < 64; i++) {
66
+ let c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charCodeAt(i);
67
+ intToChar[i] = c, charToInt[c] = i;
68
+ }
69
+ var DecodedMap = class {
70
+ _encoded;
71
+ _decoded;
72
+ _decodedMemo;
73
+ url;
74
+ version;
75
+ names = [];
76
+ resolvedSources;
77
+ constructor(map, from) {
78
+ this.map = map;
79
+ let { mappings, names, sources } = map;
80
+ this.version = map.version, this.names = names || [], this._encoded = mappings || "", this._decodedMemo = memoizedState(), this.url = from, this.resolvedSources = (sources || []).map((s) => posixResolve(s || "", from));
81
+ }
82
+ };
83
+ function memoizedState() {
84
+ return {
85
+ lastKey: -1,
86
+ lastNeedle: -1,
87
+ lastIndex: -1
88
+ };
89
+ }
90
+ const MODULE_RUNNER_SOURCEMAPPING_REGEXP = /* @__PURE__ */ RegExp(`//# ${SOURCEMAPPING_URL}=data:application/json;base64,(.+)`);
91
+ var EvaluatedModuleNode = class {
92
+ importers = /* @__PURE__ */ new Set();
93
+ imports = /* @__PURE__ */ new Set();
94
+ evaluated = false;
95
+ meta;
96
+ promise;
97
+ exports;
98
+ file;
99
+ map;
100
+ constructor(id, url) {
101
+ this.id = id, this.url = url, this.file = cleanUrl(id);
102
+ }
103
+ }, EvaluatedModules = class {
104
+ idToModuleMap = /* @__PURE__ */ new Map();
105
+ fileToModulesMap = /* @__PURE__ */ new Map();
106
+ urlToIdModuleMap = /* @__PURE__ */ new Map();
107
+ getModuleById(id) {
108
+ return this.idToModuleMap.get(id);
109
+ }
110
+ getModulesByFile(file) {
111
+ return this.fileToModulesMap.get(file);
112
+ }
113
+ getModuleByUrl(url) {
114
+ return this.urlToIdModuleMap.get(unwrapId(url));
115
+ }
116
+ ensureModule(id, url) {
117
+ if (id = normalizeModuleId(id), this.idToModuleMap.has(id)) {
118
+ let moduleNode$1 = this.idToModuleMap.get(id);
119
+ return this.urlToIdModuleMap.set(url, moduleNode$1), moduleNode$1;
120
+ }
121
+ let moduleNode = new EvaluatedModuleNode(id, url);
122
+ this.idToModuleMap.set(id, moduleNode), this.urlToIdModuleMap.set(url, moduleNode);
123
+ let fileModules = this.fileToModulesMap.get(moduleNode.file) || /* @__PURE__ */ new Set();
124
+ return fileModules.add(moduleNode), this.fileToModulesMap.set(moduleNode.file, fileModules), moduleNode;
125
+ }
126
+ invalidateModule(node) {
127
+ node.evaluated = false, node.meta = void 0, node.map = void 0, node.promise = void 0, node.exports = void 0, node.imports.clear();
128
+ }
129
+ getModuleSourceMapById(id) {
130
+ let mod = this.getModuleById(id);
131
+ if (!mod) return null;
132
+ if (mod.map) return mod.map;
133
+ if (!mod.meta || !("code" in mod.meta)) return null;
134
+ let pattern = `//# ${SOURCEMAPPING_URL}=data:application/json;base64,`, lastIndex = mod.meta.code.lastIndexOf(pattern);
135
+ if (lastIndex === -1) return null;
136
+ let mapString = MODULE_RUNNER_SOURCEMAPPING_REGEXP.exec(mod.meta.code.slice(lastIndex))?.[1];
137
+ return mapString ? (mod.map = new DecodedMap(JSON.parse(decodeBase64(mapString)), mod.file), mod.map) : null;
138
+ }
139
+ clear() {
140
+ this.idToModuleMap.clear(), this.fileToModulesMap.clear(), this.urlToIdModuleMap.clear();
141
+ }
142
+ };
143
+ const prefixedBuiltins = new Set([
144
+ "node:sea",
145
+ "node:sqlite",
146
+ "node:test",
147
+ "node:test/reporters"
148
+ ]);
149
+ function normalizeModuleId(file) {
150
+ if (prefixedBuiltins.has(file)) return file;
151
+ let unixFile = slash(file).replace(/^\/@fs\//, isWindows ? "" : "/").replace(/^node:/, "").replace(/^\/+/, "/");
152
+ return unixFile.replace(/^file:\/+/, isWindows ? "" : "/");
153
+ }
154
+ const customizationHookNamespace = "vite-module-runner:import-meta-resolve/v1/"; `
9
155
 
10
- const config = getBrowserState().config;
11
- const sessionId = getBrowserState().sessionId;
12
- const state = {
13
- ctx: {
14
- pool: "browser",
15
- workerId: 1,
16
- config,
17
- projectName: config.name || "",
18
- files: [],
19
- environment: {
20
- name: "browser",
21
- options: null
22
- },
23
- providedContext: {},
24
- invalidates: []
25
- },
26
- onCancel: null,
27
- config,
28
- environment: {
29
- name: "browser",
30
- viteEnvironment: "client",
31
- setup() {
32
- throw new Error("Not called in the browser");
33
- }
34
- },
35
- onCleanup: (fn) => getBrowserState().cleanups.push(fn),
36
- evaluatedModules: getBrowserState().evaluatedModules,
37
- resolvingModules: getBrowserState().resolvingModules,
38
- moduleExecutionInfo: new Map(),
39
- metaEnv: null,
40
- rpc: null,
41
- durations: {
42
- environment: 0,
43
- prepare: performance.now()
44
- },
45
- providedContext: {}
46
- };
47
- // @ts-expect-error not typed global
48
- globalThis.__vitest_browser__ = true;
49
- // @ts-expect-error not typed global
50
- globalThis.__vitest_worker__ = state;
51
- getBrowserState().cdp = createCdp();
52
- function rpc() {
53
- return state.rpc;
54
- }
55
- function createCdp() {
56
- const listenersMap = new WeakMap();
57
- function getId(listener) {
58
- const id = listenersMap.get(listener) || crypto.randomUUID();
59
- listenersMap.set(listener, id);
60
- return id;
61
- }
62
- const listeners = {};
63
- const cdp = {
64
- send(method, params) {
65
- return rpc().sendCdpEvent(sessionId, method, params);
66
- },
67
- on(event, listener) {
68
- const listenerId = getId(listener);
69
- listeners[event] = listeners[event] || [];
70
- listeners[event].push(listener);
71
- rpc().trackCdpEvent(sessionId, "on", event, listenerId).catch(error);
72
- return cdp;
73
- },
74
- once(event, listener) {
75
- const listenerId = getId(listener);
76
- const handler = (data) => {
77
- listener(data);
78
- cdp.off(event, listener);
79
- };
80
- listeners[event] = listeners[event] || [];
81
- listeners[event].push(handler);
82
- rpc().trackCdpEvent(sessionId, "once", event, listenerId).catch(error);
83
- return cdp;
84
- },
85
- off(event, listener) {
86
- const listenerId = getId(listener);
87
- if (listeners[event]) {
88
- listeners[event] = listeners[event].filter((l) => l !== listener);
89
- }
90
- rpc().trackCdpEvent(sessionId, "off", event, listenerId).catch(error);
91
- return cdp;
92
- },
93
- emit(event, payload) {
94
- if (listeners[event]) {
95
- listeners[event].forEach((l) => {
96
- try {
97
- l(payload);
98
- } catch (err) {
99
- error(err);
100
- }
101
- });
102
- }
103
- }
104
- };
105
- return cdp;
106
- }
107
- function error(err) {
108
- window.dispatchEvent(new ErrorEvent("error", { error: err }));
156
+ export async function resolve(specifier, context, nextResolve) {
157
+ if (specifier.startsWith(${JSON.stringify(customizationHookNamespace)})) {
158
+ const data = specifier.slice(${JSON.stringify(customizationHookNamespace)}.length)
159
+ const [parsedSpecifier, parsedImporter] = JSON.parse(data)
160
+ specifier = parsedSpecifier
161
+ context.parentURL = parsedImporter
109
162
  }
110
163
 
164
+ return nextResolve(specifier, context)
165
+ }
166
+
167
+ `;
168
+ new Proxy({}, { get(_, p) {
169
+ throw Error(`[module runner] Dynamic access of "import.meta.env" is not supported. Please, use "import.meta.env.${String(p)}" instead.`);
170
+ } });
171
+
172
+ /* @__NO_SIDE_EFFECTS__ */
173
+ function getBrowserState() {
174
+ // @ts-expect-error not typed global
175
+ return window.__vitest_browser_runner__;
176
+ }
177
+
178
+ const config = getBrowserState().config;
179
+ const sessionId = getBrowserState().sessionId;
180
+ const state = {
181
+ ctx: {
182
+ pool: "browser",
183
+ workerId: 1,
184
+ config,
185
+ projectName: config.name || "",
186
+ files: [],
187
+ environment: {
188
+ name: "browser",
189
+ options: null
190
+ },
191
+ providedContext: {},
192
+ invalidates: []
193
+ },
194
+ onCancel: null,
195
+ config,
196
+ environment: {
197
+ name: "browser",
198
+ viteEnvironment: "client",
199
+ setup() {
200
+ throw new Error("Not called in the browser");
201
+ }
202
+ },
203
+ onCleanup: (fn) => getBrowserState().cleanups.push(fn),
204
+ evaluatedModules: new EvaluatedModules(),
205
+ resolvingModules: new Set(),
206
+ moduleExecutionInfo: new Map(),
207
+ metaEnv: null,
208
+ rpc: null,
209
+ durations: {
210
+ environment: 0,
211
+ prepare: performance.now()
212
+ },
213
+ providedContext: {}
214
+ };
215
+ // @ts-expect-error not typed global
216
+ globalThis.__vitest_browser__ = true;
217
+ // @ts-expect-error not typed global
218
+ globalThis.__vitest_worker__ = state;
219
+ getBrowserState().cdp = createCdp();
220
+ function rpc() {
221
+ return state.rpc;
222
+ }
223
+ function createCdp() {
224
+ const listenersMap = new WeakMap();
225
+ function getId(listener) {
226
+ const id = listenersMap.get(listener) || crypto.randomUUID();
227
+ listenersMap.set(listener, id);
228
+ return id;
229
+ }
230
+ const listeners = {};
231
+ const cdp = {
232
+ send(method, params) {
233
+ return rpc().sendCdpEvent(sessionId, method, params);
234
+ },
235
+ on(event, listener) {
236
+ const listenerId = getId(listener);
237
+ listeners[event] = listeners[event] || [];
238
+ listeners[event].push(listener);
239
+ rpc().trackCdpEvent(sessionId, "on", event, listenerId).catch(error);
240
+ return cdp;
241
+ },
242
+ once(event, listener) {
243
+ const listenerId = getId(listener);
244
+ const handler = (data) => {
245
+ listener(data);
246
+ cdp.off(event, listener);
247
+ };
248
+ listeners[event] = listeners[event] || [];
249
+ listeners[event].push(handler);
250
+ rpc().trackCdpEvent(sessionId, "once", event, listenerId).catch(error);
251
+ return cdp;
252
+ },
253
+ off(event, listener) {
254
+ const listenerId = getId(listener);
255
+ if (listeners[event]) {
256
+ listeners[event] = listeners[event].filter((l) => l !== listener);
257
+ }
258
+ rpc().trackCdpEvent(sessionId, "off", event, listenerId).catch(error);
259
+ return cdp;
260
+ },
261
+ emit(event, payload) {
262
+ if (listeners[event]) {
263
+ listeners[event].forEach((l) => {
264
+ try {
265
+ l(payload);
266
+ } catch (err) {
267
+ error(err);
268
+ }
269
+ });
270
+ }
271
+ }
272
+ };
273
+ return cdp;
274
+ }
275
+ function error(err) {
276
+ window.dispatchEvent(new ErrorEvent("error", { error: err }));
277
+ }
278
+
111
279
  })();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/browser",
3
3
  "type": "module",
4
- "version": "4.0.5",
4
+ "version": "4.0.6",
5
5
  "description": "Browser running for Vitest",
6
6
  "license": "MIT",
7
7
  "funding": "https://opencollective.com/vitest",
@@ -51,7 +51,7 @@
51
51
  "providers"
52
52
  ],
53
53
  "peerDependencies": {
54
- "vitest": "4.0.5"
54
+ "vitest": "4.0.6"
55
55
  },
56
56
  "dependencies": {
57
57
  "magic-string": "^0.30.19",
@@ -60,8 +60,8 @@
60
60
  "sirv": "^3.0.2",
61
61
  "tinyrainbow": "^3.0.3",
62
62
  "ws": "^8.18.3",
63
- "@vitest/mocker": "4.0.5",
64
- "@vitest/utils": "4.0.5"
63
+ "@vitest/mocker": "4.0.6",
64
+ "@vitest/utils": "4.0.6"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@testing-library/user-event": "^14.6.1",
@@ -72,8 +72,8 @@
72
72
  "ivya": "^1.7.0",
73
73
  "mime": "^4.1.0",
74
74
  "pathe": "^2.0.3",
75
- "@vitest/runner": "4.0.5",
76
- "vitest": "4.0.5"
75
+ "@vitest/runner": "4.0.6",
76
+ "vitest": "4.0.6"
77
77
  },
78
78
  "scripts": {
79
79
  "typecheck": "tsc -p ./src/client/tsconfig.json --noEmit",