vite-node 3.2.0-beta.2 → 3.2.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.
@@ -14,6 +14,7 @@ function viteNodeHmrPlugin() {
14
14
  return {
15
15
  name: "vite-node:hmr",
16
16
  config() {
17
+ // chokidar fsevents is unstable on macos when emitting "ready" event
17
18
  if (process.platform === "darwin" && false);
18
19
  },
19
20
  configureServer(server) {
@@ -23,6 +24,8 @@ function viteNodeHmrPlugin() {
23
24
  _send(payload);
24
25
  emitter.emit("message", payload);
25
26
  };
27
+ // eslint-disable-next-line ts/ban-ts-comment
28
+ // @ts-ignore Vite 6 compat
26
29
  const environments = server.environments;
27
30
  if (environments) environments.ssr.hot.send = function(payload) {
28
31
  _send(payload);
@@ -33,15 +36,15 @@ function viteNodeHmrPlugin() {
33
36
  }
34
37
 
35
38
  const debugHmr = createDebug("vite-node:hmr");
36
- const cache = new WeakMap();
39
+ const cache = /* @__PURE__ */ new WeakMap();
37
40
  function getCache(runner) {
38
41
  if (!cache.has(runner)) cache.set(runner, {
39
- hotModulesMap: new Map(),
40
- dataMap: new Map(),
41
- disposeMap: new Map(),
42
- pruneMap: new Map(),
43
- customListenersMap: new Map(),
44
- ctxToListenersMap: new Map(),
42
+ hotModulesMap: /* @__PURE__ */ new Map(),
43
+ dataMap: /* @__PURE__ */ new Map(),
44
+ disposeMap: /* @__PURE__ */ new Map(),
45
+ pruneMap: /* @__PURE__ */ new Map(),
46
+ customListenersMap: /* @__PURE__ */ new Map(),
47
+ ctxToListenersMap: /* @__PURE__ */ new Map(),
45
48
  messageBuffer: [],
46
49
  isFirstUpdate: false,
47
50
  pending: false,
@@ -55,6 +58,7 @@ function sendMessageBuffer(runner, emitter) {
55
58
  maps.messageBuffer.length = 0;
56
59
  }
57
60
  async function reload(runner, files) {
61
+ // invalidate module cache but not node_modules
58
62
  Array.from(runner.moduleCache.keys()).forEach((fsPath) => {
59
63
  if (!fsPath.includes("node_modules")) runner.moduleCache.delete(fsPath);
60
64
  });
@@ -82,9 +86,14 @@ async function fetchUpdate(runner, { path, acceptedPath }) {
82
86
  acceptedPath = utils.normalizeRequestId(acceptedPath);
83
87
  const maps = getCache(runner);
84
88
  const mod = maps.hotModulesMap.get(path);
85
- if (!mod) return;
89
+ if (!mod)
90
+ // In a code-splitting project,
91
+ // it is common that the hot-updating module is not loaded yet.
92
+ // https://github.com/vitejs/vite/issues/721
93
+ return;
86
94
  const isSelfUpdate = path === acceptedPath;
87
95
  let fetchedModule;
96
+ // determine the qualified callbacks before we re-import the modules
88
97
  const qualifiedCallbacks = mod.callbacks.filter(({ deps }) => deps.includes(acceptedPath));
89
98
  if (isSelfUpdate || qualifiedCallbacks.length > 0) {
90
99
  const disposer = maps.disposeMap.get(acceptedPath);
@@ -115,6 +124,7 @@ async function handleMessage(runner, emitter, files, payload) {
115
124
  await notifyListeners(runner, "vite:beforeUpdate", payload);
116
125
  await Promise.all(payload.updates.map((update) => {
117
126
  if (update.type === "js-update") return queueUpdate(runner, fetchUpdate(runner, update));
127
+ // css-update
118
128
  console.error(`${browser.s.cyan("[vite-node]")} no support css hmr.}`);
119
129
  return null;
120
130
  }));
@@ -147,9 +157,11 @@ function createHotContext(runner, emitter, files, ownerPath) {
147
157
  debugHmr("createHotContext", ownerPath);
148
158
  const maps = getCache(runner);
149
159
  if (!maps.dataMap.has(ownerPath)) maps.dataMap.set(ownerPath, {});
160
+ // when a file is hot updated, a new context is created
161
+ // clear its stale callbacks
150
162
  const mod = maps.hotModulesMap.get(ownerPath);
151
163
  if (mod) mod.callbacks = [];
152
- const newListeners = new Map();
164
+ const newListeners = /* @__PURE__ */ new Map();
153
165
  maps.ctxToListenersMap.set(ownerPath, newListeners);
154
166
  function acceptDeps(deps, callback = () => {}) {
155
167
  const mod = maps.hotModulesMap.get(ownerPath) || {
@@ -170,8 +182,12 @@ function createHotContext(runner, emitter, files, ownerPath) {
170
182
  acceptDeps([ownerPath], callback && (([mod]) => callback(mod)));
171
183
  },
172
184
  accept(deps, callback) {
173
- if (typeof deps === "function" || !deps) acceptDeps([ownerPath], ([mod]) => deps && deps(mod));
174
- else if (typeof deps === "string") acceptDeps([deps], ([mod]) => callback && callback(mod));
185
+ if (typeof deps === "function" || !deps)
186
+ // self-accept: hot.accept(() => {})
187
+ acceptDeps([ownerPath], ([mod]) => deps && deps(mod));
188
+ else if (typeof deps === "string")
189
+ // explicit deps
190
+ acceptDeps([deps], ([mod]) => callback && callback(mod));
175
191
  else if (Array.isArray(deps)) acceptDeps(deps, callback);
176
192
  else throw new TypeError("invalid hot.accept() usage.");
177
193
  },
@@ -184,7 +200,8 @@ function createHotContext(runner, emitter, files, ownerPath) {
184
200
  invalidate() {
185
201
  notifyListeners(runner, "vite:invalidate", {
186
202
  path: ownerPath,
187
- message: void 0
203
+ message: void 0,
204
+ firstInvalidatedBy: ownerPath
188
205
  });
189
206
  return reload(runner, files);
190
207
  },
@@ -12,6 +12,7 @@ function viteNodeHmrPlugin() {
12
12
  return {
13
13
  name: "vite-node:hmr",
14
14
  config() {
15
+ // chokidar fsevents is unstable on macos when emitting "ready" event
15
16
  if (process.platform === "darwin" && false);
16
17
  },
17
18
  configureServer(server) {
@@ -21,6 +22,8 @@ function viteNodeHmrPlugin() {
21
22
  _send(payload);
22
23
  emitter.emit("message", payload);
23
24
  };
25
+ // eslint-disable-next-line ts/ban-ts-comment
26
+ // @ts-ignore Vite 6 compat
24
27
  const environments = server.environments;
25
28
  if (environments) environments.ssr.hot.send = function(payload) {
26
29
  _send(payload);
@@ -31,15 +34,15 @@ function viteNodeHmrPlugin() {
31
34
  }
32
35
 
33
36
  const debugHmr = createDebug("vite-node:hmr");
34
- const cache = new WeakMap();
37
+ const cache = /* @__PURE__ */ new WeakMap();
35
38
  function getCache(runner) {
36
39
  if (!cache.has(runner)) cache.set(runner, {
37
- hotModulesMap: new Map(),
38
- dataMap: new Map(),
39
- disposeMap: new Map(),
40
- pruneMap: new Map(),
41
- customListenersMap: new Map(),
42
- ctxToListenersMap: new Map(),
40
+ hotModulesMap: /* @__PURE__ */ new Map(),
41
+ dataMap: /* @__PURE__ */ new Map(),
42
+ disposeMap: /* @__PURE__ */ new Map(),
43
+ pruneMap: /* @__PURE__ */ new Map(),
44
+ customListenersMap: /* @__PURE__ */ new Map(),
45
+ ctxToListenersMap: /* @__PURE__ */ new Map(),
43
46
  messageBuffer: [],
44
47
  isFirstUpdate: false,
45
48
  pending: false,
@@ -53,6 +56,7 @@ function sendMessageBuffer(runner, emitter) {
53
56
  maps.messageBuffer.length = 0;
54
57
  }
55
58
  async function reload(runner, files) {
59
+ // invalidate module cache but not node_modules
56
60
  Array.from(runner.moduleCache.keys()).forEach((fsPath) => {
57
61
  if (!fsPath.includes("node_modules")) runner.moduleCache.delete(fsPath);
58
62
  });
@@ -80,9 +84,14 @@ async function fetchUpdate(runner, { path, acceptedPath }) {
80
84
  acceptedPath = normalizeRequestId(acceptedPath);
81
85
  const maps = getCache(runner);
82
86
  const mod = maps.hotModulesMap.get(path);
83
- if (!mod) return;
87
+ if (!mod)
88
+ // In a code-splitting project,
89
+ // it is common that the hot-updating module is not loaded yet.
90
+ // https://github.com/vitejs/vite/issues/721
91
+ return;
84
92
  const isSelfUpdate = path === acceptedPath;
85
93
  let fetchedModule;
94
+ // determine the qualified callbacks before we re-import the modules
86
95
  const qualifiedCallbacks = mod.callbacks.filter(({ deps }) => deps.includes(acceptedPath));
87
96
  if (isSelfUpdate || qualifiedCallbacks.length > 0) {
88
97
  const disposer = maps.disposeMap.get(acceptedPath);
@@ -113,6 +122,7 @@ async function handleMessage(runner, emitter, files, payload) {
113
122
  await notifyListeners(runner, "vite:beforeUpdate", payload);
114
123
  await Promise.all(payload.updates.map((update) => {
115
124
  if (update.type === "js-update") return queueUpdate(runner, fetchUpdate(runner, update));
125
+ // css-update
116
126
  console.error(`${s.cyan("[vite-node]")} no support css hmr.}`);
117
127
  return null;
118
128
  }));
@@ -145,9 +155,11 @@ function createHotContext(runner, emitter, files, ownerPath) {
145
155
  debugHmr("createHotContext", ownerPath);
146
156
  const maps = getCache(runner);
147
157
  if (!maps.dataMap.has(ownerPath)) maps.dataMap.set(ownerPath, {});
158
+ // when a file is hot updated, a new context is created
159
+ // clear its stale callbacks
148
160
  const mod = maps.hotModulesMap.get(ownerPath);
149
161
  if (mod) mod.callbacks = [];
150
- const newListeners = new Map();
162
+ const newListeners = /* @__PURE__ */ new Map();
151
163
  maps.ctxToListenersMap.set(ownerPath, newListeners);
152
164
  function acceptDeps(deps, callback = () => {}) {
153
165
  const mod = maps.hotModulesMap.get(ownerPath) || {
@@ -168,8 +180,12 @@ function createHotContext(runner, emitter, files, ownerPath) {
168
180
  acceptDeps([ownerPath], callback && (([mod]) => callback(mod)));
169
181
  },
170
182
  accept(deps, callback) {
171
- if (typeof deps === "function" || !deps) acceptDeps([ownerPath], ([mod]) => deps && deps(mod));
172
- else if (typeof deps === "string") acceptDeps([deps], ([mod]) => callback && callback(mod));
183
+ if (typeof deps === "function" || !deps)
184
+ // self-accept: hot.accept(() => {})
185
+ acceptDeps([ownerPath], ([mod]) => deps && deps(mod));
186
+ else if (typeof deps === "string")
187
+ // explicit deps
188
+ acceptDeps([deps], ([mod]) => callback && callback(mod));
173
189
  else if (Array.isArray(deps)) acceptDeps(deps, callback);
174
190
  else throw new TypeError("invalid hot.accept() usage.");
175
191
  },
@@ -182,7 +198,8 @@ function createHotContext(runner, emitter, files, ownerPath) {
182
198
  invalidate() {
183
199
  notifyListeners(runner, "vite:invalidate", {
184
200
  path: ownerPath,
185
- message: void 0
201
+ message: void 0,
202
+ firstInvalidatedBy: ownerPath
186
203
  });
187
204
  return reload(runner, files);
188
205
  },
package/dist/cli.cjs CHANGED
@@ -21,7 +21,7 @@ require('node:perf_hooks');
21
21
  require('es-module-lexer');
22
22
  require('./constants.cjs');
23
23
 
24
- var version = "3.2.0-beta.2";
24
+ var version = "3.2.0";
25
25
 
26
26
  const cli = cac("vite-node");
27
27
  cli.option("-r, --root <path>", "Use specified root directory").option("-c, --config <path>", "Use specified config file").option("-m, --mode <mode>", "Set env mode").option("-w, --watch", "Restart on file changes, similar to \"nodemon\"").option("--script", "Use vite-node as a script runner").option("--options <options>", "Use specified Vite server options").option("-v, --version", "Output the version number").option("-h, --help", "Display help for command");
@@ -76,7 +76,9 @@ async function run(files, options = {}) {
76
76
  plugins: [options.watch && hmr.viteNodeHmrPlugin()]
77
77
  });
78
78
  if (Number(vite.version.split(".")[0]) < 6) await server$1.pluginContainer.buildStart({});
79
- else await server$1.environments.client.pluginContainer.buildStart({});
79
+ else
80
+ // directly access client plugin container until https://github.com/vitejs/vite/issues/19607
81
+ await server$1.environments.client.pluginContainer.buildStart({});
80
82
  const env = vite.loadEnv(server$1.config.mode, server$1.config.envDir, "");
81
83
  for (const key in env) {
82
84
  var _process$env;
@@ -97,6 +99,7 @@ async function run(files, options = {}) {
97
99
  return hmr.createHotContext(runner, server$1.emitter, files, url);
98
100
  }
99
101
  });
102
+ // provide the vite define variable in this context
100
103
  await runner.executeId("/@vite/env");
101
104
  for (const file of files) await runner.executeFile(file);
102
105
  if (!options.watch) await server$1.close();
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { V as ViteNodeServerOptions } from './index.d-CWZbpOcv.js';
1
+ import { V as ViteNodeServerOptions } from './index.d-DGmxD2U7.js';
2
2
  import './trace-mapping.d-DLVdEqOp.js';
3
3
 
4
4
  interface CliOptions {
package/dist/cli.mjs CHANGED
@@ -3,23 +3,23 @@ import cac from 'cac';
3
3
  import { s } from './chunk-browser.mjs';
4
4
  import { createServer, version as version$1, loadEnv } from 'vite';
5
5
  import { ViteNodeRunner } from './client.mjs';
6
- import { v as viteNodeHmrPlugin, a as createHotContext, h as handleMessage } from './chunk-hmr.mjs';
7
6
  import { ViteNodeServer } from './server.mjs';
8
7
  import { installSourcemapsSupport } from './source-map.mjs';
9
8
  import { toArray } from './utils.mjs';
9
+ import { v as viteNodeHmrPlugin, a as createHotContext, h as handleMessage } from './chunk-hmr.mjs';
10
10
  import 'node:module';
11
11
  import 'node:url';
12
12
  import 'node:vm';
13
13
  import 'debug';
14
14
  import 'pathe';
15
15
  import 'node:fs';
16
- import 'node:events';
17
16
  import 'node:assert';
18
17
  import 'node:perf_hooks';
19
18
  import 'es-module-lexer';
20
19
  import './constants.mjs';
20
+ import 'node:events';
21
21
 
22
- var version = "3.2.0-beta.2";
22
+ var version = "3.2.0";
23
23
 
24
24
  const cli = cac("vite-node");
25
25
  cli.option("-r, --root <path>", "Use specified root directory").option("-c, --config <path>", "Use specified config file").option("-m, --mode <mode>", "Set env mode").option("-w, --watch", "Restart on file changes, similar to \"nodemon\"").option("--script", "Use vite-node as a script runner").option("--options <options>", "Use specified Vite server options").option("-v, --version", "Output the version number").option("-h, --help", "Display help for command");
@@ -74,7 +74,9 @@ async function run(files, options = {}) {
74
74
  plugins: [options.watch && viteNodeHmrPlugin()]
75
75
  });
76
76
  if (Number(version$1.split(".")[0]) < 6) await server.pluginContainer.buildStart({});
77
- else await server.environments.client.pluginContainer.buildStart({});
77
+ else
78
+ // directly access client plugin container until https://github.com/vitejs/vite/issues/19607
79
+ await server.environments.client.pluginContainer.buildStart({});
78
80
  const env = loadEnv(server.config.mode, server.config.envDir, "");
79
81
  for (const key in env) {
80
82
  var _process$env;
@@ -95,6 +97,7 @@ async function run(files, options = {}) {
95
97
  return createHotContext(runner, server.emitter, files, url);
96
98
  }
97
99
  });
100
+ // provide the vite define variable in this context
98
101
  await runner.executeId("/@vite/env");
99
102
  for (const file of files) await runner.executeFile(file);
100
103
  if (!options.watch) await server.close();
package/dist/client.cjs CHANGED
@@ -57,8 +57,8 @@ class ModuleCacheMap extends Map {
57
57
  if (!super.has(modulePath)) this.setByModuleId(modulePath, {});
58
58
  const mod = super.get(modulePath);
59
59
  if (!mod.imports) Object.assign(mod, {
60
- imports: new Set(),
61
- importers: new Set()
60
+ imports: /* @__PURE__ */ new Set(),
61
+ importers: /* @__PURE__ */ new Set()
62
62
  });
63
63
  return mod;
64
64
  }
@@ -84,7 +84,7 @@ class ModuleCacheMap extends Map {
84
84
  /**
85
85
  * Invalidate modules that dependent on the given modules, up to the main entry
86
86
  */
87
- invalidateDepTree(ids, invalidated = new Set()) {
87
+ invalidateDepTree(ids, invalidated = /* @__PURE__ */ new Set()) {
88
88
  for (const _id of ids) {
89
89
  const id = this.normalizePath(_id);
90
90
  if (invalidated.has(id)) continue;
@@ -98,7 +98,7 @@ class ModuleCacheMap extends Map {
98
98
  /**
99
99
  * Invalidate dependency modules of the given modules, down to the bottom-level dependencies
100
100
  */
101
- invalidateSubDepTree(ids, invalidated = new Set()) {
101
+ invalidateSubDepTree(ids, invalidated = /* @__PURE__ */ new Set()) {
102
102
  for (const _id of ids) {
103
103
  const id = this.normalizePath(_id);
104
104
  if (invalidated.has(id)) continue;
@@ -134,6 +134,25 @@ class ViteNodeRunner {
134
134
  * Keys of the map are filepaths, or plain package names
135
135
  */
136
136
  moduleCache;
137
+ /**
138
+ * Tracks the stack of modules being executed for the purpose of calculating import self-time.
139
+ *
140
+ * Note that while in most cases, imports are a linear stack of modules,
141
+ * this is occasionally not the case, for example when you have parallel top-level dynamic imports like so:
142
+ *
143
+ * ```ts
144
+ * await Promise.all([
145
+ * import('./module1'),
146
+ * import('./module2'),
147
+ * ]);
148
+ * ```
149
+ *
150
+ * In this case, the self time will be reported incorrectly for one of the modules (could go negative).
151
+ * As top-level awaits with dynamic imports like this are uncommon, we don't handle this case specifically.
152
+ */
153
+ executionStack = [];
154
+ // `performance` can be mocked, so make sure we're using the original function
155
+ performanceNow = performance.now.bind(performance);
137
156
  constructor(options) {
138
157
  this.options = options;
139
158
  this.root = options.root ?? process.cwd();
@@ -155,12 +174,14 @@ class ViteNodeRunner {
155
174
  const { imports, importers } = mod;
156
175
  if (importee) importers.add(importee);
157
176
  const getStack = () => `stack:\n${[...callstack, fsPath].reverse().map((p) => ` - ${p}`).join("\n")}`;
177
+ // check circular dependency
158
178
  if (callstack.includes(fsPath) || Array.from(imports.values()).some((i) => importers.has(i))) {
159
179
  if (mod.exports) return mod.exports;
160
180
  }
161
181
  let debugTimer;
162
182
  if (this.debug) debugTimer = setTimeout(() => console.warn(`[vite-node] module ${fsPath} takes over 2s to load.\n${getStack()}`), 2e3);
163
183
  try {
184
+ // cached module
164
185
  if (mod.promise) return await mod.promise;
165
186
  const promise = this.directRequest(id, fsPath, callstack);
166
187
  Object.assign(mod, {
@@ -183,6 +204,7 @@ class ViteNodeRunner {
183
204
  const { path, exists } = utils.toFilePath(dep, this.root);
184
205
  if (!this.options.resolveId || exists) return [dep, path];
185
206
  const resolved = await this.options.resolveId(dep, importer);
207
+ // supported since Vite 5-beta.19
186
208
  if (resolved === null || resolved === void 0 || (_resolved$meta = resolved.meta) === null || _resolved$meta === void 0 || (_resolved$meta = _resolved$meta["vite:alias"]) === null || _resolved$meta === void 0 ? void 0 : _resolved$meta.noResolved) {
187
209
  const error = new Error(`Cannot find module '${id}'${importer ? ` imported from '${importer}'` : ""}.
188
210
 
@@ -206,6 +228,7 @@ class ViteNodeRunner {
206
228
  }
207
229
  async resolveUrl(id, importee) {
208
230
  const resolveKey = `resolve:${id}`;
231
+ // put info about new import as soon as possible, so we can start tracking it
209
232
  this.moduleCache.setByModuleId(resolveKey, { resolving: true });
210
233
  try {
211
234
  return await this._resolveUrl(id, importee);
@@ -221,6 +244,7 @@ class ViteNodeRunner {
221
244
  try {
222
245
  return await this.options.fetchModule(id);
223
246
  } catch (cause) {
247
+ // rethrow vite error if it cannot load the module because it's not resolved
224
248
  if (typeof cause === "object" && cause.code === "ERR_LOAD_URL" || typeof (cause === null || cause === void 0 ? void 0 : cause.message) === "string" && cause.message.includes("Failed to load url")) {
225
249
  const error = new Error(`Cannot find ${utils.isBareImport(id) ? "package" : "module"} '${id}'${importer ? ` imported from '${importer}'` : ""}`, { cause });
226
250
  error.code = "ERR_MODULE_NOT_FOUND";
@@ -253,6 +277,7 @@ class ViteNodeRunner {
253
277
  if (transformed == null) throw new Error(`[vite-node] Failed to load "${id}" imported from ${callstack[callstack.length - 2]}`);
254
278
  const { Object, Reflect, Symbol } = this.getContextPrimitives();
255
279
  const modulePath = utils.cleanUrl(moduleId);
280
+ // disambiguate the `<UNIT>:/` on windows: see nodejs/node#31710
256
281
  const href = node_url.pathToFileURL(modulePath).href;
257
282
  const __filename = node_url.fileURLToPath(href);
258
283
  const __dirname = path.dirname(__filename);
@@ -270,6 +295,8 @@ class ViteNodeRunner {
270
295
  });
271
296
  const SYMBOL_NOT_DEFINED = Symbol("not defined");
272
297
  let moduleExports = SYMBOL_NOT_DEFINED;
298
+ // this proxy is triggered only on exports.{name} and module.exports access
299
+ // inside the module itself. imported module is always "exports"
273
300
  const cjsExports = new Proxy(exports, {
274
301
  get: (target, p, receiver) => {
275
302
  if (Reflect.has(target, p)) return Reflect.get(target, p, receiver);
@@ -277,12 +304,16 @@ class ViteNodeRunner {
277
304
  },
278
305
  getPrototypeOf: () => Object.prototype,
279
306
  set: (_, p, value) => {
307
+ // treat "module.exports =" the same as "exports.default =" to not have nested "default.default",
308
+ // so "exports.default" becomes the actual module
280
309
  if (p === "default" && this.shouldInterop(modulePath, { default: value }) && cjsExports !== value) {
281
310
  exportAll(cjsExports, value);
282
311
  exports.default = value;
283
312
  return true;
284
313
  }
285
314
  if (!Reflect.has(exports, "default")) exports.default = {};
315
+ // returns undefined, when accessing named exports, if default is not an object
316
+ // but is still present inside hasOwnKeys, this is Node behaviour for CJS
286
317
  if (moduleExports !== SYMBOL_NOT_DEFINED && utils.isPrimitive(moduleExports)) {
287
318
  defineExport(exports, p, () => void 0);
288
319
  return true;
@@ -306,6 +337,7 @@ class ViteNodeRunner {
306
337
  return cjsExports;
307
338
  }
308
339
  };
340
+ // Vite hot context
309
341
  let hotContext;
310
342
  if (this.options.createHotContext) Object.defineProperty(meta, "hot", {
311
343
  enumerable: true,
@@ -318,11 +350,20 @@ class ViteNodeRunner {
318
350
  hotContext = value;
319
351
  }
320
352
  });
353
+ // Be careful when changing this
354
+ // changing context will change amount of code added on line :114 (vm.runInThisContext)
355
+ // this messes up sourcemaps for coverage
356
+ // adjust `WRAPPER_LENGTH` variable in packages/coverage-v8/src/provider.ts if you do change this
321
357
  const context = this.prepareContext({
322
358
  __vite_ssr_import__: request,
323
359
  __vite_ssr_dynamic_import__: request,
324
360
  __vite_ssr_exports__: exports,
325
361
  __vite_ssr_exportAll__: (obj) => exportAll(exports, obj),
362
+ __vite_ssr_exportName__: (name, getter) => Object.defineProperty(exports, name, {
363
+ enumerable: true,
364
+ configurable: true,
365
+ get: getter
366
+ }),
326
367
  __vite_ssr_import_meta__: meta,
327
368
  require: node_module.createRequire(href),
328
369
  exports: cjsExports,
@@ -331,6 +372,7 @@ class ViteNodeRunner {
331
372
  __dirname
332
373
  });
333
374
  debugExecute(__filename);
375
+ // remove shebang
334
376
  if (transformed[0] === "#") transformed = transformed.replace(/^#!.*/, (s) => " ".repeat(s.length));
335
377
  await this.runModule(context, transformed);
336
378
  return exports;
@@ -343,7 +385,7 @@ class ViteNodeRunner {
343
385
  };
344
386
  }
345
387
  async runModule(context, transformed) {
346
- var _this$options$moduleE;
388
+ // add 'use strict' since ESM enables it by default
347
389
  const codeDefinition = `'use strict';async (${Object.keys(context).join(",")})=>{{`;
348
390
  const code = `${codeDefinition}${transformed}\n}}`;
349
391
  const options = {
@@ -351,9 +393,38 @@ class ViteNodeRunner {
351
393
  lineOffset: 0,
352
394
  columnOffset: -codeDefinition.length
353
395
  };
354
- (_this$options$moduleE = this.options.moduleExecutionInfo) === null || _this$options$moduleE === void 0 || _this$options$moduleE.set(options.filename, { startOffset: codeDefinition.length });
355
- const fn = vm.runInThisContext(code, options);
356
- await fn(...Object.values(context));
396
+ const finishModuleExecutionInfo = this.startCalculateModuleExecutionInfo(options.filename, codeDefinition.length);
397
+ try {
398
+ const fn = vm.runInThisContext(code, options);
399
+ await fn(...Object.values(context));
400
+ } finally {
401
+ var _this$options$moduleE;
402
+ (_this$options$moduleE = this.options.moduleExecutionInfo) === null || _this$options$moduleE === void 0 || _this$options$moduleE.set(options.filename, finishModuleExecutionInfo());
403
+ }
404
+ }
405
+ /**
406
+ * Starts calculating the module execution info such as the total duration and self time spent on executing the module.
407
+ * Returns a function to call once the module has finished executing.
408
+ */
409
+ startCalculateModuleExecutionInfo(filename, startOffset) {
410
+ const startTime = this.performanceNow();
411
+ this.executionStack.push({
412
+ filename,
413
+ startTime,
414
+ subImportTime: 0
415
+ });
416
+ return () => {
417
+ const duration = this.performanceNow() - startTime;
418
+ const currentExecution = this.executionStack.pop();
419
+ if (currentExecution == null) throw new Error("Execution stack is empty, this should never happen");
420
+ const selfTime = duration - currentExecution.subImportTime;
421
+ if (this.executionStack.length > 0) this.executionStack.at(-1).subImportTime += duration;
422
+ return {
423
+ startOffset,
424
+ duration,
425
+ selfTime
426
+ };
427
+ };
357
428
  }
358
429
  prepareContext(context) {
359
430
  return context;
@@ -364,6 +435,8 @@ class ViteNodeRunner {
364
435
  */
365
436
  shouldInterop(path, mod) {
366
437
  if (this.options.interopDefault === false) return false;
438
+ // never interop ESM modules
439
+ // TODO: should also skip for `.js` with `type="module"`
367
440
  return !path.endsWith(".mjs") && "default" in mod;
368
441
  }
369
442
  importExternalModule(path) {
@@ -415,6 +488,7 @@ function interopModule(mod) {
415
488
  defaultExport
416
489
  };
417
490
  }
491
+ // keep consistency with Vite on how exports are defined
418
492
  function defineExport(exports, key, value) {
419
493
  Object.defineProperty(exports, key, {
420
494
  enumerable: true,
@@ -423,6 +497,8 @@ function defineExport(exports, key, value) {
423
497
  });
424
498
  }
425
499
  function exportAll(exports, sourceModule) {
500
+ // #1120 when a module exports itself it causes
501
+ // call stack error
426
502
  if (exports === sourceModule) return;
427
503
  if (utils.isPrimitive(sourceModule) || Array.isArray(sourceModule) || sourceModule instanceof Promise) return;
428
504
  for (const key in sourceModule) if (key !== "default" && !(key in exports)) try {
package/dist/client.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  import './trace-mapping.d-DLVdEqOp.js';
2
- export { e as DEFAULT_REQUEST_STUBS, M as ModuleCacheMap, f as ModuleExecutionInfo, a as ViteNodeRunner } from './index.d-CWZbpOcv.js';
2
+ export { e as DEFAULT_REQUEST_STUBS, M as ModuleCacheMap, f as ModuleExecutionInfo, g as ModuleExecutionInfoEntry, a as ViteNodeRunner } from './index.d-DGmxD2U7.js';