vite 5.1.0-beta.5 → 5.1.0-beta.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.
@@ -0,0 +1,1614 @@
1
+ class HMRContext {
2
+ hmrClient;
3
+ ownerPath;
4
+ newListeners;
5
+ constructor(hmrClient, ownerPath) {
6
+ this.hmrClient = hmrClient;
7
+ this.ownerPath = ownerPath;
8
+ if (!hmrClient.dataMap.has(ownerPath)) {
9
+ hmrClient.dataMap.set(ownerPath, {});
10
+ }
11
+ // when a file is hot updated, a new context is created
12
+ // clear its stale callbacks
13
+ const mod = hmrClient.hotModulesMap.get(ownerPath);
14
+ if (mod) {
15
+ mod.callbacks = [];
16
+ }
17
+ // clear stale custom event listeners
18
+ const staleListeners = hmrClient.ctxToListenersMap.get(ownerPath);
19
+ if (staleListeners) {
20
+ for (const [event, staleFns] of staleListeners) {
21
+ const listeners = hmrClient.customListenersMap.get(event);
22
+ if (listeners) {
23
+ hmrClient.customListenersMap.set(event, listeners.filter((l) => !staleFns.includes(l)));
24
+ }
25
+ }
26
+ }
27
+ this.newListeners = new Map();
28
+ hmrClient.ctxToListenersMap.set(ownerPath, this.newListeners);
29
+ }
30
+ get data() {
31
+ return this.hmrClient.dataMap.get(this.ownerPath);
32
+ }
33
+ accept(deps, callback) {
34
+ if (typeof deps === 'function' || !deps) {
35
+ // self-accept: hot.accept(() => {})
36
+ this.acceptDeps([this.ownerPath], ([mod]) => deps?.(mod));
37
+ }
38
+ else if (typeof deps === 'string') {
39
+ // explicit deps
40
+ this.acceptDeps([deps], ([mod]) => callback?.(mod));
41
+ }
42
+ else if (Array.isArray(deps)) {
43
+ this.acceptDeps(deps, callback);
44
+ }
45
+ else {
46
+ throw new Error(`invalid hot.accept() usage.`);
47
+ }
48
+ }
49
+ // export names (first arg) are irrelevant on the client side, they're
50
+ // extracted in the server for propagation
51
+ acceptExports(_, callback) {
52
+ this.acceptDeps([this.ownerPath], ([mod]) => callback?.(mod));
53
+ }
54
+ dispose(cb) {
55
+ this.hmrClient.disposeMap.set(this.ownerPath, cb);
56
+ }
57
+ prune(cb) {
58
+ this.hmrClient.pruneMap.set(this.ownerPath, cb);
59
+ }
60
+ // Kept for backward compatibility (#11036)
61
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
62
+ decline() { }
63
+ invalidate(message) {
64
+ this.hmrClient.notifyListeners('vite:invalidate', {
65
+ path: this.ownerPath,
66
+ message,
67
+ });
68
+ this.send('vite:invalidate', { path: this.ownerPath, message });
69
+ this.hmrClient.logger.debug(`[vite] invalidate ${this.ownerPath}${message ? `: ${message}` : ''}`);
70
+ }
71
+ on(event, cb) {
72
+ const addToMap = (map) => {
73
+ const existing = map.get(event) || [];
74
+ existing.push(cb);
75
+ map.set(event, existing);
76
+ };
77
+ addToMap(this.hmrClient.customListenersMap);
78
+ addToMap(this.newListeners);
79
+ }
80
+ off(event, cb) {
81
+ const removeFromMap = (map) => {
82
+ const existing = map.get(event);
83
+ if (existing === undefined) {
84
+ return;
85
+ }
86
+ const pruned = existing.filter((l) => l !== cb);
87
+ if (pruned.length === 0) {
88
+ map.delete(event);
89
+ return;
90
+ }
91
+ map.set(event, pruned);
92
+ };
93
+ removeFromMap(this.hmrClient.customListenersMap);
94
+ removeFromMap(this.newListeners);
95
+ }
96
+ send(event, data) {
97
+ this.hmrClient.messenger.send(JSON.stringify({ type: 'custom', event, data }));
98
+ }
99
+ acceptDeps(deps, callback = () => { }) {
100
+ const mod = this.hmrClient.hotModulesMap.get(this.ownerPath) || {
101
+ id: this.ownerPath,
102
+ callbacks: [],
103
+ };
104
+ mod.callbacks.push({
105
+ deps,
106
+ fn: callback,
107
+ });
108
+ this.hmrClient.hotModulesMap.set(this.ownerPath, mod);
109
+ }
110
+ }
111
+ class HMRMessenger {
112
+ connection;
113
+ constructor(connection) {
114
+ this.connection = connection;
115
+ }
116
+ queue = [];
117
+ send(message) {
118
+ this.queue.push(message);
119
+ this.flush();
120
+ }
121
+ flush() {
122
+ if (this.connection.isReady()) {
123
+ this.queue.forEach((msg) => this.connection.send(msg));
124
+ this.queue = [];
125
+ }
126
+ }
127
+ }
128
+ class HMRClient {
129
+ logger;
130
+ importUpdatedModule;
131
+ hotModulesMap = new Map();
132
+ disposeMap = new Map();
133
+ pruneMap = new Map();
134
+ dataMap = new Map();
135
+ customListenersMap = new Map();
136
+ ctxToListenersMap = new Map();
137
+ messenger;
138
+ constructor(logger, connection,
139
+ // This allows implementing reloading via different methods depending on the environment
140
+ importUpdatedModule) {
141
+ this.logger = logger;
142
+ this.importUpdatedModule = importUpdatedModule;
143
+ this.messenger = new HMRMessenger(connection);
144
+ }
145
+ async notifyListeners(event, data) {
146
+ const cbs = this.customListenersMap.get(event);
147
+ if (cbs) {
148
+ await Promise.allSettled(cbs.map((cb) => cb(data)));
149
+ }
150
+ }
151
+ clear() {
152
+ this.hotModulesMap.clear();
153
+ this.disposeMap.clear();
154
+ this.pruneMap.clear();
155
+ this.dataMap.clear();
156
+ this.customListenersMap.clear();
157
+ this.ctxToListenersMap.clear();
158
+ }
159
+ // After an HMR update, some modules are no longer imported on the page
160
+ // but they may have left behind side effects that need to be cleaned up
161
+ // (.e.g style injections)
162
+ // TODO Trigger their dispose callbacks.
163
+ prunePaths(paths) {
164
+ paths.forEach((path) => {
165
+ const fn = this.pruneMap.get(path);
166
+ if (fn) {
167
+ fn(this.dataMap.get(path));
168
+ }
169
+ });
170
+ }
171
+ warnFailedUpdate(err, path) {
172
+ if (!err.message.includes('fetch')) {
173
+ this.logger.error(err);
174
+ }
175
+ this.logger.error(`[hmr] Failed to reload ${path}. ` +
176
+ `This could be due to syntax errors or importing non-existent ` +
177
+ `modules. (see errors above)`);
178
+ }
179
+ updateQueue = [];
180
+ pendingUpdateQueue = false;
181
+ /**
182
+ * buffer multiple hot updates triggered by the same src change
183
+ * so that they are invoked in the same order they were sent.
184
+ * (otherwise the order may be inconsistent because of the http request round trip)
185
+ */
186
+ async queueUpdate(payload) {
187
+ this.updateQueue.push(this.fetchUpdate(payload));
188
+ if (!this.pendingUpdateQueue) {
189
+ this.pendingUpdateQueue = true;
190
+ await Promise.resolve();
191
+ this.pendingUpdateQueue = false;
192
+ const loading = [...this.updateQueue];
193
+ this.updateQueue = [];
194
+ (await Promise.all(loading)).forEach((fn) => fn && fn());
195
+ }
196
+ }
197
+ async fetchUpdate(update) {
198
+ const { path, acceptedPath } = update;
199
+ const mod = this.hotModulesMap.get(path);
200
+ if (!mod) {
201
+ // In a code-splitting project,
202
+ // it is common that the hot-updating module is not loaded yet.
203
+ // https://github.com/vitejs/vite/issues/721
204
+ return;
205
+ }
206
+ let fetchedModule;
207
+ const isSelfUpdate = path === acceptedPath;
208
+ // determine the qualified callbacks before we re-import the modules
209
+ const qualifiedCallbacks = mod.callbacks.filter(({ deps }) => deps.includes(acceptedPath));
210
+ if (isSelfUpdate || qualifiedCallbacks.length > 0) {
211
+ const disposer = this.disposeMap.get(acceptedPath);
212
+ if (disposer)
213
+ await disposer(this.dataMap.get(acceptedPath));
214
+ try {
215
+ fetchedModule = await this.importUpdatedModule(update);
216
+ }
217
+ catch (e) {
218
+ this.warnFailedUpdate(e, acceptedPath);
219
+ }
220
+ }
221
+ return () => {
222
+ for (const { deps, fn } of qualifiedCallbacks) {
223
+ fn(deps.map((dep) => (dep === acceptedPath ? fetchedModule : undefined)));
224
+ }
225
+ const loggedPath = isSelfUpdate ? path : `${acceptedPath} via ${path}`;
226
+ this.logger.debug(`[vite] hot updated: ${loggedPath}`);
227
+ };
228
+ }
229
+ }
230
+
231
+ const isWindows = typeof process !== 'undefined' && process.platform === 'win32';
232
+ const decodeBase64 = typeof atob !== 'undefined'
233
+ ? atob
234
+ : (str) => Buffer.from(str, 'base64').toString('utf-8');
235
+ // currently we copy this from '../../constants' - maybe we can inline it somewhow?
236
+ const NULL_BYTE_PLACEHOLDER = `__x00__`;
237
+ const VALID_ID_PREFIX = `/@id/`;
238
+ function wrapId(id) {
239
+ return id.startsWith(VALID_ID_PREFIX)
240
+ ? id
241
+ : VALID_ID_PREFIX + id.replace('\0', NULL_BYTE_PLACEHOLDER);
242
+ }
243
+ function unwrapId(id) {
244
+ return id.startsWith(VALID_ID_PREFIX)
245
+ ? id.slice(VALID_ID_PREFIX.length).replace(NULL_BYTE_PLACEHOLDER, '\0')
246
+ : id;
247
+ }
248
+ const windowsSlashRE = /\\/g;
249
+ function slash(p) {
250
+ return p.replace(windowsSlashRE, '/');
251
+ }
252
+ const postfixRE = /[?#].*$/s;
253
+ function cleanUrl(url) {
254
+ return url.replace(postfixRE, '');
255
+ }
256
+ function isPrimitive(value) {
257
+ return !value || (typeof value !== 'object' && typeof value !== 'function');
258
+ }
259
+ const CHAR_FORWARD_SLASH = 47;
260
+ const CHAR_BACKWARD_SLASH = 92;
261
+ const percentRegEx = /%/g;
262
+ const backslashRegEx = /\\/g;
263
+ const newlineRegEx = /\n/g;
264
+ const carriageReturnRegEx = /\r/g;
265
+ const tabRegEx = /\t/g;
266
+ const questionRegex = /\?/g;
267
+ const hashRegex = /#/g;
268
+ function encodePathChars(filepath) {
269
+ if (filepath.indexOf('%') !== -1)
270
+ filepath = filepath.replace(percentRegEx, '%25');
271
+ // In posix, backslash is a valid character in paths:
272
+ if (!isWindows && filepath.indexOf('\\') !== -1)
273
+ filepath = filepath.replace(backslashRegEx, '%5C');
274
+ if (filepath.indexOf('\n') !== -1)
275
+ filepath = filepath.replace(newlineRegEx, '%0A');
276
+ if (filepath.indexOf('\r') !== -1)
277
+ filepath = filepath.replace(carriageReturnRegEx, '%0D');
278
+ if (filepath.indexOf('\t') !== -1)
279
+ filepath = filepath.replace(tabRegEx, '%09');
280
+ return filepath;
281
+ }
282
+ function posixPathToFileHref(posixPath) {
283
+ let resolved = posixResolve(posixPath);
284
+ // path.resolve strips trailing slashes so we must add them back
285
+ const filePathLast = posixPath.charCodeAt(posixPath.length - 1);
286
+ if ((filePathLast === CHAR_FORWARD_SLASH ||
287
+ (isWindows && filePathLast === CHAR_BACKWARD_SLASH)) &&
288
+ resolved[resolved.length - 1] !== '/')
289
+ resolved += '/';
290
+ // Call encodePathChars first to avoid encoding % again for ? and #.
291
+ resolved = encodePathChars(resolved);
292
+ // Question and hash character should be included in pathname.
293
+ // Therefore, encoding is required to eliminate parsing them in different states.
294
+ // This is done as an optimization to not creating a URL instance and
295
+ // later triggering pathname setter, which impacts performance
296
+ if (resolved.indexOf('?') !== -1)
297
+ resolved = resolved.replace(questionRegex, '%3F');
298
+ if (resolved.indexOf('#') !== -1)
299
+ resolved = resolved.replace(hashRegex, '%23');
300
+ return new URL(`file://${resolved}`).href;
301
+ }
302
+ function posixDirname(filepath) {
303
+ const normalizedPath = filepath.endsWith('/')
304
+ ? filepath.substring(0, filepath.length - 1)
305
+ : filepath;
306
+ return normalizedPath.substring(0, normalizedPath.lastIndexOf('/')) || '/';
307
+ }
308
+ function toWindowsPath(path) {
309
+ return path.replace(/\//g, '\\');
310
+ }
311
+ // inlined from pathe to support environments without access to node:path
312
+ function cwd() {
313
+ if (typeof process !== 'undefined' && typeof process.cwd === 'function') {
314
+ return slash(process.cwd());
315
+ }
316
+ return '/';
317
+ }
318
+ function posixResolve(...segments) {
319
+ // Normalize windows arguments
320
+ segments = segments.map((argument) => slash(argument));
321
+ let resolvedPath = '';
322
+ let resolvedAbsolute = false;
323
+ for (let index = segments.length - 1; index >= -1 && !resolvedAbsolute; index--) {
324
+ const path = index >= 0 ? segments[index] : cwd();
325
+ // Skip empty entries
326
+ if (!path || path.length === 0) {
327
+ continue;
328
+ }
329
+ resolvedPath = `${path}/${resolvedPath}`;
330
+ resolvedAbsolute = isAbsolute(path);
331
+ }
332
+ // At this point the path should be resolved to a full absolute path, but
333
+ // handle relative paths to be safe (might happen when process.cwd() fails)
334
+ // Normalize the path
335
+ resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
336
+ if (resolvedAbsolute && !isAbsolute(resolvedPath)) {
337
+ return `/${resolvedPath}`;
338
+ }
339
+ return resolvedPath.length > 0 ? resolvedPath : '.';
340
+ }
341
+ const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
342
+ function isAbsolute(p) {
343
+ return _IS_ABSOLUTE_RE.test(p);
344
+ }
345
+ // Resolves . and .. elements in a path with directory names
346
+ function normalizeString(path, allowAboveRoot) {
347
+ let res = '';
348
+ let lastSegmentLength = 0;
349
+ let lastSlash = -1;
350
+ let dots = 0;
351
+ let char = null;
352
+ for (let index = 0; index <= path.length; ++index) {
353
+ if (index < path.length) {
354
+ char = path[index];
355
+ }
356
+ else if (char === '/') {
357
+ break;
358
+ }
359
+ else {
360
+ char = '/';
361
+ }
362
+ if (char === '/') {
363
+ if (lastSlash === index - 1 || dots === 1) ;
364
+ else if (dots === 2) {
365
+ if (res.length < 2 ||
366
+ lastSegmentLength !== 2 ||
367
+ res[res.length - 1] !== '.' ||
368
+ res[res.length - 2] !== '.') {
369
+ if (res.length > 2) {
370
+ const lastSlashIndex = res.lastIndexOf('/');
371
+ if (lastSlashIndex === -1) {
372
+ res = '';
373
+ lastSegmentLength = 0;
374
+ }
375
+ else {
376
+ res = res.slice(0, lastSlashIndex);
377
+ lastSegmentLength = res.length - 1 - res.lastIndexOf('/');
378
+ }
379
+ lastSlash = index;
380
+ dots = 0;
381
+ continue;
382
+ }
383
+ else if (res.length > 0) {
384
+ res = '';
385
+ lastSegmentLength = 0;
386
+ lastSlash = index;
387
+ dots = 0;
388
+ continue;
389
+ }
390
+ }
391
+ if (allowAboveRoot) {
392
+ res += res.length > 0 ? '/..' : '..';
393
+ lastSegmentLength = 2;
394
+ }
395
+ }
396
+ else {
397
+ if (res.length > 0) {
398
+ res += `/${path.slice(lastSlash + 1, index)}`;
399
+ }
400
+ else {
401
+ res = path.slice(lastSlash + 1, index);
402
+ }
403
+ lastSegmentLength = index - lastSlash - 1;
404
+ }
405
+ lastSlash = index;
406
+ dots = 0;
407
+ }
408
+ else if (char === '.' && dots !== -1) {
409
+ ++dots;
410
+ }
411
+ else {
412
+ dots = -1;
413
+ }
414
+ }
415
+ return res;
416
+ }
417
+
418
+ class DecodedMap {
419
+ map;
420
+ _encoded;
421
+ _decoded;
422
+ _decodedMemo;
423
+ url;
424
+ version;
425
+ names = [];
426
+ resolvedSources;
427
+ constructor(map, from) {
428
+ this.map = map;
429
+ const { mappings, names, sources } = map;
430
+ this.version = map.version;
431
+ this.names = names || [];
432
+ this._encoded = mappings || '';
433
+ this._decodedMemo = memoizedState();
434
+ this.url = from;
435
+ this.resolvedSources = (sources || []).map((s) => posixResolve(s || '', from));
436
+ }
437
+ }
438
+ // This is a copy of all methods that we need for decoding a source map from "@jridgewell/trace-mapping"
439
+ function indexOf(mappings, index) {
440
+ const idx = mappings.indexOf(';', index);
441
+ return idx === -1 ? mappings.length : idx;
442
+ }
443
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
444
+ const charToInt = new Uint8Array(128); // z is 122 in ASCII
445
+ for (let i = 0; i < chars.length; i++) {
446
+ const c = chars.charCodeAt(i);
447
+ charToInt[c] = i;
448
+ }
449
+ function decodeInteger(mappings, pos, state, j) {
450
+ let value = 0;
451
+ let shift = 0;
452
+ let integer = 0;
453
+ do {
454
+ const c = mappings.charCodeAt(pos++);
455
+ integer = charToInt[c];
456
+ value |= (integer & 31) << shift;
457
+ shift += 5;
458
+ } while (integer & 32);
459
+ const shouldNegate = value & 1;
460
+ value >>>= 1;
461
+ if (shouldNegate) {
462
+ value = -0x80000000 | -value;
463
+ }
464
+ state[j] += value;
465
+ return pos;
466
+ }
467
+ const comma = ','.charCodeAt(0);
468
+ function hasMoreVlq(mappings, i, length) {
469
+ if (i >= length)
470
+ return false;
471
+ return mappings.charCodeAt(i) !== comma;
472
+ }
473
+ function decode(mappings) {
474
+ const state = new Int32Array(5);
475
+ const decoded = [];
476
+ let index = 0;
477
+ do {
478
+ const semi = indexOf(mappings, index);
479
+ const line = [];
480
+ let sorted = true;
481
+ let lastCol = 0;
482
+ state[0] = 0;
483
+ for (let i = index; i < semi; i++) {
484
+ let seg;
485
+ i = decodeInteger(mappings, i, state, 0); // genColumn
486
+ const col = state[0];
487
+ if (col < lastCol)
488
+ sorted = false;
489
+ lastCol = col;
490
+ if (hasMoreVlq(mappings, i, semi)) {
491
+ i = decodeInteger(mappings, i, state, 1); // sourcesIndex
492
+ i = decodeInteger(mappings, i, state, 2); // sourceLine
493
+ i = decodeInteger(mappings, i, state, 3); // sourceColumn
494
+ if (hasMoreVlq(mappings, i, semi)) {
495
+ i = decodeInteger(mappings, i, state, 4); // namesIndex
496
+ seg = [col, state[1], state[2], state[3], state[4]];
497
+ }
498
+ else {
499
+ seg = [col, state[1], state[2], state[3]];
500
+ }
501
+ }
502
+ else {
503
+ seg = [col];
504
+ }
505
+ line.push(seg);
506
+ }
507
+ if (!sorted)
508
+ line.sort((a, b) => a[0] - b[0]);
509
+ decoded.push(line);
510
+ index = semi + 1;
511
+ } while (index <= mappings.length);
512
+ return decoded;
513
+ }
514
+ const LINE_GTR_ZERO = '`line` must be greater than 0 (lines start at line 1)';
515
+ const COL_GTR_EQ_ZERO = '`column` must be greater than or equal to 0 (columns start at column 0)';
516
+ const COLUMN = 0;
517
+ const SOURCES_INDEX = 1;
518
+ const SOURCE_LINE = 2;
519
+ const SOURCE_COLUMN = 3;
520
+ const NAMES_INDEX = 4;
521
+ function OMapping(source, line, column, name) {
522
+ return { source, line, column, name };
523
+ }
524
+ function decodedMappings(map) {
525
+ return map._decoded || (map._decoded = decode(map._encoded));
526
+ }
527
+ let found = false;
528
+ function binarySearch(haystack, needle, low, high) {
529
+ while (low <= high) {
530
+ const mid = low + ((high - low) >> 1);
531
+ const cmp = haystack[mid][COLUMN] - needle;
532
+ if (cmp === 0) {
533
+ found = true;
534
+ return mid;
535
+ }
536
+ if (cmp < 0) {
537
+ low = mid + 1;
538
+ }
539
+ else {
540
+ high = mid - 1;
541
+ }
542
+ }
543
+ found = false;
544
+ return low - 1;
545
+ }
546
+ function lowerBound(haystack, needle, index) {
547
+ for (let i = index - 1; i >= 0; index = i--) {
548
+ if (haystack[i][COLUMN] !== needle)
549
+ break;
550
+ }
551
+ return index;
552
+ }
553
+ function memoizedState() {
554
+ return {
555
+ lastKey: -1,
556
+ lastNeedle: -1,
557
+ lastIndex: -1,
558
+ };
559
+ }
560
+ function memoizedBinarySearch(haystack, needle, state, key) {
561
+ const { lastKey, lastNeedle, lastIndex } = state;
562
+ let low = 0;
563
+ let high = haystack.length - 1;
564
+ if (key === lastKey) {
565
+ if (needle === lastNeedle) {
566
+ found = lastIndex !== -1 && haystack[lastIndex][COLUMN] === needle;
567
+ return lastIndex;
568
+ }
569
+ if (needle >= lastNeedle) {
570
+ // lastIndex may be -1 if the previous needle was not found.
571
+ low = lastIndex === -1 ? 0 : lastIndex;
572
+ }
573
+ else {
574
+ high = lastIndex;
575
+ }
576
+ }
577
+ state.lastKey = key;
578
+ state.lastNeedle = needle;
579
+ return (state.lastIndex = binarySearch(haystack, needle, low, high));
580
+ }
581
+ function traceSegmentInternal(segments, memo, line, column) {
582
+ let index = memoizedBinarySearch(segments, column, memo, line);
583
+ if (found) {
584
+ index = lowerBound(segments, column, index);
585
+ }
586
+ if (index === -1 || index === segments.length)
587
+ return -1;
588
+ return index;
589
+ }
590
+ function getOriginalPosition(map, { line, column }) {
591
+ line--;
592
+ if (line < 0)
593
+ throw new Error(LINE_GTR_ZERO);
594
+ if (column < 0)
595
+ throw new Error(COL_GTR_EQ_ZERO);
596
+ map._decodedMemo ??= memoizedState();
597
+ const decoded = decodedMappings(map);
598
+ // It's common for parent source maps to have pointers to lines that have no
599
+ // mapping (like a "//# sourceMappingURL=") at the end of the child file.
600
+ if (line >= decoded.length)
601
+ return null;
602
+ const segments = decoded[line];
603
+ const index = traceSegmentInternal(segments, map._decodedMemo, line, column);
604
+ if (index === -1)
605
+ return null;
606
+ const segment = segments[index];
607
+ if (segment.length === 1)
608
+ return null;
609
+ const { names, resolvedSources } = map;
610
+ return OMapping(resolvedSources[segment[SOURCES_INDEX]], segment[SOURCE_LINE] + 1, segment[SOURCE_COLUMN], segment.length === 5 ? names[segment[NAMES_INDEX]] : null);
611
+ }
612
+
613
+ let SOURCEMAPPING_URL = 'sourceMa';
614
+ SOURCEMAPPING_URL += 'ppingURL';
615
+ const VITE_RUNTIME_SOURCEMAPPING_URL = `${SOURCEMAPPING_URL}=data:application/json;charset=utf-8`;
616
+ const VITE_RUNTIME_SOURCEMAPPING_REGEXP = new RegExp(`//# ${VITE_RUNTIME_SOURCEMAPPING_URL};base64,(.+)`);
617
+ class ModuleCacheMap extends Map {
618
+ root;
619
+ constructor(root, entries) {
620
+ super(entries);
621
+ this.root = withTrailingSlash(root);
622
+ }
623
+ normalize(fsPath) {
624
+ return normalizeModuleId(fsPath, this.root);
625
+ }
626
+ /**
627
+ * Assign partial data to the map
628
+ */
629
+ update(fsPath, mod) {
630
+ fsPath = this.normalize(fsPath);
631
+ if (!super.has(fsPath))
632
+ this.setByModuleId(fsPath, mod);
633
+ else
634
+ Object.assign(super.get(fsPath), mod);
635
+ return this;
636
+ }
637
+ setByModuleId(modulePath, mod) {
638
+ return super.set(modulePath, mod);
639
+ }
640
+ set(fsPath, mod) {
641
+ return this.setByModuleId(this.normalize(fsPath), mod);
642
+ }
643
+ getByModuleId(modulePath) {
644
+ if (!super.has(modulePath))
645
+ this.setByModuleId(modulePath, {});
646
+ const mod = super.get(modulePath);
647
+ if (!mod.imports) {
648
+ Object.assign(mod, {
649
+ imports: new Set(),
650
+ importers: new Set(),
651
+ });
652
+ }
653
+ return mod;
654
+ }
655
+ get(fsPath) {
656
+ return this.getByModuleId(this.normalize(fsPath));
657
+ }
658
+ deleteByModuleId(modulePath) {
659
+ return super.delete(modulePath);
660
+ }
661
+ delete(fsPath) {
662
+ return this.deleteByModuleId(this.normalize(fsPath));
663
+ }
664
+ /**
665
+ * Invalidate modules that dependent on the given modules, up to the main entry
666
+ */
667
+ invalidateDepTree(ids, invalidated = new Set()) {
668
+ for (const _id of ids) {
669
+ const id = this.normalize(_id);
670
+ if (invalidated.has(id))
671
+ continue;
672
+ invalidated.add(id);
673
+ const mod = super.get(id);
674
+ if (mod?.importers)
675
+ this.invalidateDepTree(mod.importers, invalidated);
676
+ super.delete(id);
677
+ }
678
+ return invalidated;
679
+ }
680
+ /**
681
+ * Invalidate dependency modules of the given modules, down to the bottom-level dependencies
682
+ */
683
+ invalidateSubDepTree(ids, invalidated = new Set()) {
684
+ for (const _id of ids) {
685
+ const id = this.normalize(_id);
686
+ if (invalidated.has(id))
687
+ continue;
688
+ invalidated.add(id);
689
+ const subIds = Array.from(super.entries())
690
+ .filter(([, mod]) => mod.importers?.has(id))
691
+ .map(([key]) => key);
692
+ subIds.length && this.invalidateSubDepTree(subIds, invalidated);
693
+ super.delete(id);
694
+ }
695
+ return invalidated;
696
+ }
697
+ getSourceMap(moduleId) {
698
+ const mod = this.get(moduleId);
699
+ if (mod.map)
700
+ return mod.map;
701
+ if (!mod.meta || !('code' in mod.meta))
702
+ return null;
703
+ const mapString = mod.meta.code.match(VITE_RUNTIME_SOURCEMAPPING_REGEXP)?.[1];
704
+ if (!mapString)
705
+ return null;
706
+ const baseFile = mod.meta.file || moduleId.split('?')[0];
707
+ mod.map = new DecodedMap(JSON.parse(decodeBase64(mapString)), baseFile);
708
+ return mod.map;
709
+ }
710
+ }
711
+ function withTrailingSlash(path) {
712
+ if (path[path.length - 1] !== '/') {
713
+ return `${path}/`;
714
+ }
715
+ return path;
716
+ }
717
+ // unique id that is not available as "$bare_import" like "test"
718
+ const prefixedBuiltins = new Set(['node:test']);
719
+ // transform file url to id
720
+ // virtual:custom -> virtual:custom
721
+ // \0custom -> \0custom
722
+ // /root/id -> /id
723
+ // /root/id.js -> /id.js
724
+ // C:/root/id.js -> /id.js
725
+ // C:\root\id.js -> /id.js
726
+ function normalizeModuleId(file, root) {
727
+ if (prefixedBuiltins.has(file))
728
+ return file;
729
+ // unix style, but Windows path still starts with the drive letter to check the root
730
+ let unixFile = file
731
+ .replace(/\\/g, '/')
732
+ .replace(/^\/@fs\//, isWindows ? '' : '/')
733
+ .replace(/^node:/, '')
734
+ .replace(/^\/+/, '/');
735
+ if (unixFile.startsWith(root)) {
736
+ // keep slash
737
+ unixFile = unixFile.slice(root.length - 1);
738
+ }
739
+ // if it's not in the root, keep it as a path, not a URL
740
+ return unixFile.replace(/^file:\//, '/');
741
+ }
742
+
743
+ // they are exported from ssrTransform plugin, but we can't import from there for performance reasons
744
+ const ssrModuleExportsKey = `__vite_ssr_exports__`;
745
+ const ssrImportKey = `__vite_ssr_import__`;
746
+ const ssrDynamicImportKey = `__vite_ssr_dynamic_import__`;
747
+ const ssrExportAllKey = `__vite_ssr_exportAll__`;
748
+ const ssrImportMetaKey = `__vite_ssr_import_meta__`;
749
+
750
+ const noop = () => { };
751
+ const silentConsole = {
752
+ debug: noop,
753
+ error: noop,
754
+ };
755
+
756
+ // updates to HMR should go one after another. It is possible to trigger another update during the invalidation for example.
757
+ function createHMRHandler(runtime) {
758
+ const queue = new Queue();
759
+ return (payload) => queue.enqueue(() => handleHMRPayload(runtime, payload));
760
+ }
761
+ async function handleHMRPayload(runtime, payload) {
762
+ const hmrClient = runtime.hmrClient;
763
+ if (!hmrClient || runtime.isDestroyed())
764
+ return;
765
+ switch (payload.type) {
766
+ case 'connected':
767
+ hmrClient.logger.debug(`[vite] connected.`);
768
+ hmrClient.messenger.flush();
769
+ break;
770
+ case 'update':
771
+ await hmrClient.notifyListeners('vite:beforeUpdate', payload);
772
+ await Promise.all(payload.updates.map(async (update) => {
773
+ if (update.type === 'js-update') {
774
+ // runtime always caches modules by their full path without /@id/ prefix
775
+ update.acceptedPath = unwrapId(update.acceptedPath);
776
+ update.path = unwrapId(update.path);
777
+ return hmrClient.queueUpdate(update);
778
+ }
779
+ hmrClient.logger.error('[vite] css hmr is not supported in runtime mode.');
780
+ }));
781
+ await hmrClient.notifyListeners('vite:afterUpdate', payload);
782
+ break;
783
+ case 'custom': {
784
+ await hmrClient.notifyListeners(payload.event, payload.data);
785
+ break;
786
+ }
787
+ case 'full-reload':
788
+ hmrClient.logger.debug(`[vite] program reload`);
789
+ await hmrClient.notifyListeners('vite:beforeFullReload', payload);
790
+ Array.from(runtime.moduleCache.keys()).forEach((id) => {
791
+ if (!id.includes('node_modules')) {
792
+ runtime.moduleCache.deleteByModuleId(id);
793
+ }
794
+ });
795
+ for (const id of runtime.entrypoints) {
796
+ await runtime.executeUrl(id);
797
+ }
798
+ break;
799
+ case 'prune':
800
+ await hmrClient.notifyListeners('vite:beforePrune', payload);
801
+ hmrClient.prunePaths(payload.paths);
802
+ break;
803
+ case 'error': {
804
+ await hmrClient.notifyListeners('vite:error', payload);
805
+ const err = payload.err;
806
+ hmrClient.logger.error(`[vite] Internal Server Error\n${err.message}\n${err.stack}`);
807
+ break;
808
+ }
809
+ default: {
810
+ const check = payload;
811
+ return check;
812
+ }
813
+ }
814
+ }
815
+ class Queue {
816
+ queue = [];
817
+ pending = false;
818
+ enqueue(promise) {
819
+ return new Promise((resolve, reject) => {
820
+ this.queue.push({
821
+ promise,
822
+ resolve,
823
+ reject,
824
+ });
825
+ this.dequeue();
826
+ });
827
+ }
828
+ dequeue() {
829
+ if (this.pending) {
830
+ return false;
831
+ }
832
+ const item = this.queue.shift();
833
+ if (!item) {
834
+ return false;
835
+ }
836
+ this.pending = true;
837
+ item
838
+ .promise()
839
+ .then(item.resolve)
840
+ .catch(item.reject)
841
+ .finally(() => {
842
+ this.pending = false;
843
+ this.dequeue();
844
+ });
845
+ return true;
846
+ }
847
+ }
848
+
849
+ const sourceMapCache = {};
850
+ const fileContentsCache = {};
851
+ const moduleGraphs = new Set();
852
+ const retrieveFileHandlers = new Set();
853
+ const retrieveSourceMapHandlers = new Set();
854
+ const createExecHandlers = (handlers) => {
855
+ return ((...args) => {
856
+ for (const handler of handlers) {
857
+ const result = handler(...args);
858
+ if (result)
859
+ return result;
860
+ }
861
+ return null;
862
+ });
863
+ };
864
+ const retrieveFileFromHandlers = createExecHandlers(retrieveFileHandlers);
865
+ const retrievSourceMapFromHandlers = createExecHandlers(retrieveSourceMapHandlers);
866
+ let overriden = false;
867
+ const originalPrepare = Error.prepareStackTrace;
868
+ function resetInterceptor(runtime, options) {
869
+ moduleGraphs.delete(runtime.moduleCache);
870
+ if (options.retrieveFile)
871
+ retrieveFileHandlers.delete(options.retrieveFile);
872
+ if (options.retrieveSourceMap)
873
+ retrieveSourceMapHandlers.delete(options.retrieveSourceMap);
874
+ if (moduleGraphs.size === 0) {
875
+ Error.prepareStackTrace = originalPrepare;
876
+ overriden = false;
877
+ }
878
+ }
879
+ function interceptStackTrace(runtime, options = {}) {
880
+ if (!overriden) {
881
+ Error.prepareStackTrace = prepareStackTrace;
882
+ overriden = true;
883
+ }
884
+ moduleGraphs.add(runtime.moduleCache);
885
+ if (options.retrieveFile)
886
+ retrieveFileHandlers.add(options.retrieveFile);
887
+ if (options.retrieveSourceMap)
888
+ retrieveSourceMapHandlers.add(options.retrieveSourceMap);
889
+ return () => resetInterceptor(runtime, options);
890
+ }
891
+ // Support URLs relative to a directory, but be careful about a protocol prefix
892
+ function supportRelativeURL(file, url) {
893
+ if (!file)
894
+ return url;
895
+ const dir = posixDirname(file.replace(/\\/g, '/'));
896
+ const match = /^\w+:\/\/[^/]*/.exec(dir);
897
+ let protocol = match ? match[0] : '';
898
+ const startPath = dir.slice(protocol.length);
899
+ if (protocol && /^\/\w:/.test(startPath)) {
900
+ // handle file:///C:/ paths
901
+ protocol += '/';
902
+ return (protocol +
903
+ posixResolve(dir.slice(protocol.length), url).replace(/\\/g, '/'));
904
+ }
905
+ return protocol + posixResolve(dir.slice(protocol.length), url);
906
+ }
907
+ function getRuntimeSourceMap(position) {
908
+ for (const moduleCache of moduleGraphs) {
909
+ const sourceMap = moduleCache.getSourceMap(position.source);
910
+ if (sourceMap) {
911
+ return {
912
+ url: position.source,
913
+ map: sourceMap,
914
+ vite: true,
915
+ };
916
+ }
917
+ }
918
+ return null;
919
+ }
920
+ function retrieveFile(path) {
921
+ if (path in fileContentsCache)
922
+ return fileContentsCache[path];
923
+ const content = retrieveFileFromHandlers(path);
924
+ if (typeof content === 'string') {
925
+ fileContentsCache[path] = content;
926
+ return content;
927
+ }
928
+ return null;
929
+ }
930
+ function retrieveSourceMapURL(source) {
931
+ // Get the URL of the source map
932
+ const fileData = retrieveFile(source);
933
+ if (!fileData)
934
+ return null;
935
+ const re = /\/\/[@#]\s*sourceMappingURL=([^\s'"]+)\s*$|\/\*[@#]\s*sourceMappingURL=[^\s*'"]+\s*\*\/\s*$/gm;
936
+ // Keep executing the search to find the *last* sourceMappingURL to avoid
937
+ // picking up sourceMappingURLs from comments, strings, etc.
938
+ let lastMatch, match;
939
+ while ((match = re.exec(fileData)))
940
+ lastMatch = match;
941
+ if (!lastMatch)
942
+ return null;
943
+ return lastMatch[1];
944
+ }
945
+ const reSourceMap = /^data:application\/json[^,]+base64,/;
946
+ function retrieveSourceMap(source) {
947
+ const urlAndMap = retrievSourceMapFromHandlers(source);
948
+ if (urlAndMap)
949
+ return urlAndMap;
950
+ let sourceMappingURL = retrieveSourceMapURL(source);
951
+ if (!sourceMappingURL)
952
+ return null;
953
+ // Read the contents of the source map
954
+ let sourceMapData;
955
+ if (reSourceMap.test(sourceMappingURL)) {
956
+ // Support source map URL as a data url
957
+ const rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(',') + 1);
958
+ sourceMapData = Buffer.from(rawData, 'base64').toString();
959
+ sourceMappingURL = source;
960
+ }
961
+ else {
962
+ // Support source map URLs relative to the source URL
963
+ sourceMappingURL = supportRelativeURL(source, sourceMappingURL);
964
+ sourceMapData = retrieveFile(sourceMappingURL);
965
+ }
966
+ if (!sourceMapData)
967
+ return null;
968
+ return {
969
+ url: sourceMappingURL,
970
+ map: sourceMapData,
971
+ };
972
+ }
973
+ function mapSourcePosition(position) {
974
+ if (!position.source)
975
+ return position;
976
+ let sourceMap = getRuntimeSourceMap(position);
977
+ if (!sourceMap)
978
+ sourceMap = sourceMapCache[position.source];
979
+ if (!sourceMap) {
980
+ // Call the (overrideable) retrieveSourceMap function to get the source map.
981
+ const urlAndMap = retrieveSourceMap(position.source);
982
+ if (urlAndMap && urlAndMap.map) {
983
+ const url = urlAndMap.url;
984
+ sourceMap = sourceMapCache[position.source] = {
985
+ url,
986
+ map: new DecodedMap(typeof urlAndMap.map === 'string'
987
+ ? JSON.parse(urlAndMap.map)
988
+ : urlAndMap.map, url),
989
+ };
990
+ const contents = sourceMap.map?.map.sourcesContent;
991
+ // Load all sources stored inline with the source map into the file cache
992
+ // to pretend like they are already loaded. They may not exist on disk.
993
+ if (sourceMap.map && contents) {
994
+ sourceMap.map.resolvedSources.forEach((source, i) => {
995
+ const content = contents[i];
996
+ if (content && source && url) {
997
+ const contentUrl = supportRelativeURL(url, source);
998
+ fileContentsCache[contentUrl] = content;
999
+ }
1000
+ });
1001
+ }
1002
+ }
1003
+ else {
1004
+ sourceMap = sourceMapCache[position.source] = {
1005
+ url: null,
1006
+ map: null,
1007
+ };
1008
+ }
1009
+ }
1010
+ // Resolve the source URL relative to the URL of the source map
1011
+ if (sourceMap && sourceMap.map && sourceMap.url) {
1012
+ const originalPosition = getOriginalPosition(sourceMap.map, position);
1013
+ // Only return the original position if a matching line was found. If no
1014
+ // matching line is found then we return position instead, which will cause
1015
+ // the stack trace to print the path and line for the compiled file. It is
1016
+ // better to give a precise location in the compiled file than a vague
1017
+ // location in the original file.
1018
+ if (originalPosition && originalPosition.source != null) {
1019
+ originalPosition.source = supportRelativeURL(sourceMap.url, originalPosition.source);
1020
+ if (sourceMap.vite) {
1021
+ // @ts-expect-error vite is not defined
1022
+ originalPosition._vite = true;
1023
+ }
1024
+ return originalPosition;
1025
+ }
1026
+ }
1027
+ return position;
1028
+ }
1029
+ // Parses code generated by FormatEvalOrigin(), a function inside V8:
1030
+ // https://code.google.com/p/v8/source/browse/trunk/src/messages.js
1031
+ function mapEvalOrigin(origin) {
1032
+ // Most eval() calls are in this format
1033
+ let match = /^eval at ([^(]+) \((.+):(\d+):(\d+)\)$/.exec(origin);
1034
+ if (match) {
1035
+ const position = mapSourcePosition({
1036
+ name: null,
1037
+ source: match[2],
1038
+ line: +match[3],
1039
+ column: +match[4] - 1,
1040
+ });
1041
+ return `eval at ${match[1]} (${position.source}:${position.line}:${position.column + 1})`;
1042
+ }
1043
+ // Parse nested eval() calls using recursion
1044
+ match = /^eval at ([^(]+) \((.+)\)$/.exec(origin);
1045
+ if (match)
1046
+ return `eval at ${match[1]} (${mapEvalOrigin(match[2])})`;
1047
+ // Make sure we still return useful information if we didn't find anything
1048
+ return origin;
1049
+ }
1050
+ // This is copied almost verbatim from the V8 source code at
1051
+ // https://code.google.com/p/v8/source/browse/trunk/src/messages.js. The
1052
+ // implementation of wrapCallSite() used to just forward to the actual source
1053
+ // code of CallSite.prototype.toString but unfortunately a new release of V8
1054
+ // did something to the prototype chain and broke the shim. The only fix I
1055
+ // could find was copy/paste.
1056
+ function CallSiteToString() {
1057
+ let fileName;
1058
+ let fileLocation = '';
1059
+ if (this.isNative()) {
1060
+ fileLocation = 'native';
1061
+ }
1062
+ else {
1063
+ fileName = this.getScriptNameOrSourceURL();
1064
+ if (!fileName && this.isEval()) {
1065
+ fileLocation = this.getEvalOrigin();
1066
+ fileLocation += ', '; // Expecting source position to follow.
1067
+ }
1068
+ if (fileName) {
1069
+ fileLocation += fileName;
1070
+ }
1071
+ else {
1072
+ // Source code does not originate from a file and is not native, but we
1073
+ // can still get the source position inside the source string, e.g. in
1074
+ // an eval string.
1075
+ fileLocation += '<anonymous>';
1076
+ }
1077
+ const lineNumber = this.getLineNumber();
1078
+ if (lineNumber != null) {
1079
+ fileLocation += `:${lineNumber}`;
1080
+ const columnNumber = this.getColumnNumber();
1081
+ if (columnNumber)
1082
+ fileLocation += `:${columnNumber}`;
1083
+ }
1084
+ }
1085
+ let line = '';
1086
+ const functionName = this.getFunctionName();
1087
+ let addSuffix = true;
1088
+ const isConstructor = this.isConstructor();
1089
+ const isMethodCall = !(this.isToplevel() || isConstructor);
1090
+ if (isMethodCall) {
1091
+ let typeName = this.getTypeName();
1092
+ // Fixes shim to be backward compatable with Node v0 to v4
1093
+ if (typeName === '[object Object]')
1094
+ typeName = 'null';
1095
+ const methodName = this.getMethodName();
1096
+ if (functionName) {
1097
+ if (typeName && functionName.indexOf(typeName) !== 0)
1098
+ line += `${typeName}.`;
1099
+ line += functionName;
1100
+ if (methodName &&
1101
+ functionName.indexOf(`.${methodName}`) !==
1102
+ functionName.length - methodName.length - 1)
1103
+ line += ` [as ${methodName}]`;
1104
+ }
1105
+ else {
1106
+ line += `${typeName}.${methodName || '<anonymous>'}`;
1107
+ }
1108
+ }
1109
+ else if (isConstructor) {
1110
+ line += `new ${functionName || '<anonymous>'}`;
1111
+ }
1112
+ else if (functionName) {
1113
+ line += functionName;
1114
+ }
1115
+ else {
1116
+ line += fileLocation;
1117
+ addSuffix = false;
1118
+ }
1119
+ if (addSuffix)
1120
+ line += ` (${fileLocation})`;
1121
+ return line;
1122
+ }
1123
+ function cloneCallSite(frame) {
1124
+ const object = {};
1125
+ Object.getOwnPropertyNames(Object.getPrototypeOf(frame)).forEach((name) => {
1126
+ const key = name;
1127
+ // @ts-expect-error difficult to type
1128
+ object[key] = /^(?:is|get)/.test(name)
1129
+ ? function () {
1130
+ return frame[key].call(frame);
1131
+ }
1132
+ : frame[key];
1133
+ });
1134
+ object.toString = CallSiteToString;
1135
+ return object;
1136
+ }
1137
+ function wrapCallSite(frame, state) {
1138
+ // provides interface backward compatibility
1139
+ if (state === undefined)
1140
+ state = { nextPosition: null, curPosition: null };
1141
+ if (frame.isNative()) {
1142
+ state.curPosition = null;
1143
+ return frame;
1144
+ }
1145
+ // Most call sites will return the source file from getFileName(), but code
1146
+ // passed to eval() ending in "//# sourceURL=..." will return the source file
1147
+ // from getScriptNameOrSourceURL() instead
1148
+ const source = frame.getFileName() || frame.getScriptNameOrSourceURL();
1149
+ if (source) {
1150
+ const line = frame.getLineNumber();
1151
+ let column = frame.getColumnNumber() - 1;
1152
+ // Fix position in Node where some (internal) code is prepended.
1153
+ // See https://github.com/evanw/node-source-map-support/issues/36
1154
+ // Header removed in node at ^10.16 || >=11.11.0
1155
+ // v11 is not an LTS candidate, we can just test the one version with it.
1156
+ // Test node versions for: 10.16-19, 10.20+, 12-19, 20-99, 100+, or 11.11
1157
+ const headerLength = 62;
1158
+ if (line === 1 && column > headerLength && !frame.isEval())
1159
+ column -= headerLength;
1160
+ const position = mapSourcePosition({
1161
+ name: null,
1162
+ source,
1163
+ line,
1164
+ column,
1165
+ });
1166
+ state.curPosition = position;
1167
+ frame = cloneCallSite(frame);
1168
+ const originalFunctionName = frame.getFunctionName;
1169
+ frame.getFunctionName = function () {
1170
+ const name = (() => {
1171
+ if (state.nextPosition == null)
1172
+ return originalFunctionName();
1173
+ return state.nextPosition.name || originalFunctionName();
1174
+ })();
1175
+ return name === 'eval' && '_vite' in position ? null : name;
1176
+ };
1177
+ frame.getFileName = function () {
1178
+ return position.source ?? undefined;
1179
+ };
1180
+ frame.getLineNumber = function () {
1181
+ return position.line;
1182
+ };
1183
+ frame.getColumnNumber = function () {
1184
+ return position.column + 1;
1185
+ };
1186
+ frame.getScriptNameOrSourceURL = function () {
1187
+ return position.source;
1188
+ };
1189
+ return frame;
1190
+ }
1191
+ // Code called using eval() needs special handling
1192
+ let origin = frame.isEval() && frame.getEvalOrigin();
1193
+ if (origin) {
1194
+ origin = mapEvalOrigin(origin);
1195
+ frame = cloneCallSite(frame);
1196
+ frame.getEvalOrigin = function () {
1197
+ return origin || undefined;
1198
+ };
1199
+ return frame;
1200
+ }
1201
+ // If we get here then we were unable to change the source position
1202
+ return frame;
1203
+ }
1204
+ function prepareStackTrace(error, stack) {
1205
+ const name = error.name || 'Error';
1206
+ const message = error.message || '';
1207
+ const errorString = `${name}: ${message}`;
1208
+ const state = { nextPosition: null, curPosition: null };
1209
+ const processedStack = [];
1210
+ for (let i = stack.length - 1; i >= 0; i--) {
1211
+ processedStack.push(`\n at ${wrapCallSite(stack[i], state)}`);
1212
+ state.nextPosition = state.curPosition;
1213
+ }
1214
+ state.curPosition = state.nextPosition = null;
1215
+ return errorString + processedStack.reverse().join('');
1216
+ }
1217
+
1218
+ function enableSourceMapSupport(runtime) {
1219
+ if (runtime.options.sourcemapInterceptor === 'node') {
1220
+ if (typeof process === 'undefined') {
1221
+ throw new TypeError(`Cannot use "sourcemapInterceptor: 'node'" because global "process" variable is not available.`);
1222
+ }
1223
+ if (typeof process.setSourceMapsEnabled !== 'function') {
1224
+ throw new TypeError(`Cannot use "sourcemapInterceptor: 'node'" because "process.setSourceMapsEnabled" function is not available. Please use Node >= 16.6.0.`);
1225
+ }
1226
+ const isEnabledAlready = process.sourceMapsEnabled ?? false;
1227
+ process.setSourceMapsEnabled(true);
1228
+ return () => !isEnabledAlready && process.setSourceMapsEnabled(false);
1229
+ }
1230
+ return interceptStackTrace(runtime, typeof runtime.options.sourcemapInterceptor === 'object'
1231
+ ? runtime.options.sourcemapInterceptor
1232
+ : undefined);
1233
+ }
1234
+
1235
+ class ViteRuntime {
1236
+ options;
1237
+ runner;
1238
+ debug;
1239
+ /**
1240
+ * Holds the cache of modules
1241
+ * Keys of the map are ids
1242
+ */
1243
+ moduleCache;
1244
+ hmrClient;
1245
+ entrypoints = new Set();
1246
+ idToUrlMap = new Map();
1247
+ fileToIdMap = new Map();
1248
+ envProxy = new Proxy({}, {
1249
+ get(_, p) {
1250
+ throw new Error(`[vite-runtime] Dynamic access of "import.meta.env" is not supported. Please, use "import.meta.env.${String(p)}" instead.`);
1251
+ },
1252
+ });
1253
+ _destroyed = false;
1254
+ _resetSourceMapSupport;
1255
+ constructor(options, runner, debug) {
1256
+ this.options = options;
1257
+ this.runner = runner;
1258
+ this.debug = debug;
1259
+ this.moduleCache = options.moduleCache ?? new ModuleCacheMap(options.root);
1260
+ if (typeof options.hmr === 'object') {
1261
+ this.hmrClient = new HMRClient(options.hmr.logger === false
1262
+ ? silentConsole
1263
+ : options.hmr.logger || console, options.hmr.connection, ({ acceptedPath, ssrInvalidates }) => {
1264
+ this.moduleCache.delete(acceptedPath);
1265
+ if (ssrInvalidates) {
1266
+ this.invalidateFiles(ssrInvalidates);
1267
+ }
1268
+ return this.executeUrl(acceptedPath);
1269
+ });
1270
+ options.hmr.connection.onUpdate(createHMRHandler(this));
1271
+ }
1272
+ if (options.sourcemapInterceptor !== false) {
1273
+ this._resetSourceMapSupport = enableSourceMapSupport(this);
1274
+ }
1275
+ }
1276
+ /**
1277
+ * URL to execute. Accepts file path, server path or id relative to the root.
1278
+ */
1279
+ async executeUrl(url) {
1280
+ url = this.normalizeEntryUrl(url);
1281
+ const fetchedModule = await this.cachedModule(url);
1282
+ return await this.cachedRequest(url, fetchedModule);
1283
+ }
1284
+ /**
1285
+ * Entrypoint URL to execute. Accepts file path, server path or id relative to the root.
1286
+ * In the case of a full reload triggered by HMR, this is the module that will be reloaded.
1287
+ * If this method is called multiple times, all entrypoints will be reloaded one at a time.
1288
+ */
1289
+ async executeEntrypoint(url) {
1290
+ url = this.normalizeEntryUrl(url);
1291
+ const fetchedModule = await this.cachedModule(url);
1292
+ return await this.cachedRequest(url, fetchedModule, [], {
1293
+ entrypoint: true,
1294
+ });
1295
+ }
1296
+ /**
1297
+ * Clear all caches including HMR listeners.
1298
+ */
1299
+ clearCache() {
1300
+ this.moduleCache.clear();
1301
+ this.idToUrlMap.clear();
1302
+ this.entrypoints.clear();
1303
+ this.hmrClient?.clear();
1304
+ }
1305
+ /**
1306
+ * Clears all caches, removes all HMR listeners, and resets source map support.
1307
+ * This method doesn't stop the HMR connection.
1308
+ */
1309
+ async destroy() {
1310
+ this._resetSourceMapSupport?.();
1311
+ this.clearCache();
1312
+ this.hmrClient = undefined;
1313
+ this._destroyed = true;
1314
+ }
1315
+ /**
1316
+ * Returns `true` if the runtime has been destroyed by calling `destroy()` method.
1317
+ */
1318
+ isDestroyed() {
1319
+ return this._destroyed;
1320
+ }
1321
+ invalidateFiles(files) {
1322
+ files.forEach((file) => {
1323
+ const ids = this.fileToIdMap.get(file);
1324
+ if (ids) {
1325
+ ids.forEach((id) => this.moduleCache.deleteByModuleId(id));
1326
+ }
1327
+ });
1328
+ }
1329
+ // we don't use moduleCache.normalize because this URL doesn't have to follow the same rules
1330
+ // this URL is something that user passes down manually, and is later resolved by fetchModule
1331
+ // moduleCache.normalize is used on resolved "file" property
1332
+ normalizeEntryUrl(url) {
1333
+ // expect fetchModule to resolve relative module correctly
1334
+ if (url[0] === '.') {
1335
+ return url;
1336
+ }
1337
+ // file:///C:/root/id.js -> C:/root/id.js
1338
+ if (url.startsWith('file://')) {
1339
+ // 8 is the length of "file:///"
1340
+ url = url.slice(isWindows ? 8 : 7);
1341
+ }
1342
+ url = url.replace(/\\/g, '/');
1343
+ const _root = this.options.root;
1344
+ const root = _root[_root.length - 1] === '/' ? _root : `${_root}/`;
1345
+ // strip root from the URL because fetchModule prefers a public served url path
1346
+ // packages/vite/src/node/server/moduleGraph.ts:17
1347
+ if (url.startsWith(root)) {
1348
+ // /root/id.js -> /id.js
1349
+ // C:/root/id.js -> /id.js
1350
+ // 1 is to keep the leading slash
1351
+ return url.slice(root.length - 1);
1352
+ }
1353
+ // if it's a server url (starts with a slash), keep it, otherwise assume a virtual module
1354
+ // /id.js -> /id.js
1355
+ // virtual:custom -> /@id/virtual:custom
1356
+ return url[0] === '/' ? url : wrapId(url);
1357
+ }
1358
+ processImport(exports, fetchResult, metadata) {
1359
+ if (!('externalize' in fetchResult)) {
1360
+ return exports;
1361
+ }
1362
+ const { id, type } = fetchResult;
1363
+ if (type !== 'module' && type !== 'commonjs')
1364
+ return exports;
1365
+ analyzeImportedModDifference(exports, id, type, metadata);
1366
+ return proxyGuardOnlyEsm(exports, id, metadata);
1367
+ }
1368
+ async cachedRequest(id, fetchedModule, callstack = [], metadata) {
1369
+ const moduleId = fetchedModule.id;
1370
+ if (metadata?.entrypoint) {
1371
+ this.entrypoints.add(moduleId);
1372
+ }
1373
+ const mod = this.moduleCache.getByModuleId(moduleId);
1374
+ const { imports, importers } = mod;
1375
+ const importee = callstack[callstack.length - 1];
1376
+ if (importee)
1377
+ importers.add(importee);
1378
+ // check circular dependency
1379
+ if (callstack.includes(moduleId) ||
1380
+ Array.from(imports.values()).some((i) => importers.has(i))) {
1381
+ if (mod.exports)
1382
+ return this.processImport(mod.exports, fetchedModule, metadata);
1383
+ }
1384
+ const getStack = () => `stack:\n${[...callstack, moduleId]
1385
+ .reverse()
1386
+ .map((p) => ` - ${p}`)
1387
+ .join('\n')}`;
1388
+ let debugTimer;
1389
+ if (this.debug)
1390
+ debugTimer = setTimeout(() => this.debug(`[vite-runtime] module ${moduleId} takes over 2s to load.\n${getStack()}`), 2000);
1391
+ try {
1392
+ // cached module
1393
+ if (mod.promise)
1394
+ return this.processImport(await mod.promise, fetchedModule, metadata);
1395
+ const promise = this.directRequest(id, fetchedModule, callstack);
1396
+ mod.promise = promise;
1397
+ mod.evaluated = false;
1398
+ return this.processImport(await promise, fetchedModule, metadata);
1399
+ }
1400
+ finally {
1401
+ mod.evaluated = true;
1402
+ if (debugTimer)
1403
+ clearTimeout(debugTimer);
1404
+ }
1405
+ }
1406
+ async cachedModule(id, importer) {
1407
+ if (this._destroyed) {
1408
+ throw new Error(`[vite] Vite runtime has been destroyed.`);
1409
+ }
1410
+ const normalized = this.idToUrlMap.get(id);
1411
+ if (normalized) {
1412
+ const mod = this.moduleCache.getByModuleId(normalized);
1413
+ if (mod.meta) {
1414
+ return mod.meta;
1415
+ }
1416
+ }
1417
+ this.debug?.('[vite-runtime] fetching', id);
1418
+ // fast return for established externalized patterns
1419
+ const fetchedModule = id.startsWith('data:')
1420
+ ? { externalize: id, type: 'builtin' }
1421
+ : await this.options.fetchModule(id, importer);
1422
+ // base moduleId on "file" and not on id
1423
+ // if `import(variable)` is called it's possible that it doesn't have an extension for example
1424
+ // if we used id for that, it's possible to have a duplicated module
1425
+ const idQuery = id.split('?')[1];
1426
+ const query = idQuery ? `?${idQuery}` : '';
1427
+ const file = 'file' in fetchedModule ? fetchedModule.file : undefined;
1428
+ const fullFile = file ? `${file}${query}` : id;
1429
+ const moduleId = this.moduleCache.normalize(fullFile);
1430
+ const mod = this.moduleCache.getByModuleId(moduleId);
1431
+ fetchedModule.id = moduleId;
1432
+ mod.meta = fetchedModule;
1433
+ if (file) {
1434
+ const fileModules = this.fileToIdMap.get(file) || [];
1435
+ fileModules.push(moduleId);
1436
+ this.fileToIdMap.set(file, fileModules);
1437
+ }
1438
+ this.idToUrlMap.set(id, moduleId);
1439
+ this.idToUrlMap.set(unwrapId(id), moduleId);
1440
+ return fetchedModule;
1441
+ }
1442
+ // override is allowed, consider this a public API
1443
+ async directRequest(id, fetchResult, _callstack) {
1444
+ const moduleId = fetchResult.id;
1445
+ const callstack = [..._callstack, moduleId];
1446
+ const mod = this.moduleCache.getByModuleId(moduleId);
1447
+ const request = async (dep, metadata) => {
1448
+ const fetchedModule = await this.cachedModule(dep, moduleId);
1449
+ const depMod = this.moduleCache.getByModuleId(fetchedModule.id);
1450
+ depMod.importers.add(moduleId);
1451
+ mod.imports.add(fetchedModule.id);
1452
+ return this.cachedRequest(dep, fetchedModule, callstack, metadata);
1453
+ };
1454
+ const dynamicRequest = async (dep) => {
1455
+ // it's possible to provide an object with toString() method inside import()
1456
+ dep = String(dep);
1457
+ if (dep[0] === '.') {
1458
+ dep = posixResolve(posixDirname(id), dep);
1459
+ }
1460
+ return request(dep, { isDynamicImport: true });
1461
+ };
1462
+ if ('externalize' in fetchResult) {
1463
+ const { externalize } = fetchResult;
1464
+ this.debug?.('[vite-runtime] externalizing', externalize);
1465
+ const exports = await this.runner.runExternalModule(externalize);
1466
+ mod.exports = exports;
1467
+ return exports;
1468
+ }
1469
+ const { code, file } = fetchResult;
1470
+ if (code == null) {
1471
+ const importer = callstack[callstack.length - 2];
1472
+ throw new Error(`[vite-runtime] Failed to load "${id}"${importer ? ` imported from ${importer}` : ''}`);
1473
+ }
1474
+ const modulePath = cleanUrl(file || moduleId);
1475
+ // disambiguate the `<UNIT>:/` on windows: see nodejs/node#31710
1476
+ const href = posixPathToFileHref(modulePath);
1477
+ const filename = modulePath;
1478
+ const dirname = posixDirname(modulePath);
1479
+ const meta = {
1480
+ filename: isWindows ? toWindowsPath(filename) : filename,
1481
+ dirname: isWindows ? toWindowsPath(dirname) : dirname,
1482
+ url: href,
1483
+ env: this.envProxy,
1484
+ resolve(id, parent) {
1485
+ throw new Error('[vite-runtime] "import.meta.resolve" is not supported.');
1486
+ },
1487
+ // should be replaced during transformation
1488
+ glob() {
1489
+ throw new Error('[vite-runtime] "import.meta.glob" is not supported.');
1490
+ },
1491
+ };
1492
+ const exports = Object.create(null);
1493
+ Object.defineProperty(exports, Symbol.toStringTag, {
1494
+ value: 'Module',
1495
+ enumerable: false,
1496
+ configurable: false,
1497
+ });
1498
+ mod.exports = exports;
1499
+ let hotContext;
1500
+ if (this.hmrClient) {
1501
+ Object.defineProperty(meta, 'hot', {
1502
+ enumerable: true,
1503
+ get: () => {
1504
+ if (!this.hmrClient) {
1505
+ throw new Error(`[vite-runtime] HMR client was destroyed.`);
1506
+ }
1507
+ this.debug?.('[vite-runtime] creating hmr context for', moduleId);
1508
+ hotContext ||= new HMRContext(this.hmrClient, moduleId);
1509
+ return hotContext;
1510
+ },
1511
+ set: (value) => {
1512
+ hotContext = value;
1513
+ },
1514
+ });
1515
+ }
1516
+ const context = {
1517
+ [ssrImportKey]: request,
1518
+ [ssrDynamicImportKey]: dynamicRequest,
1519
+ [ssrModuleExportsKey]: exports,
1520
+ [ssrExportAllKey]: (obj) => exportAll(exports, obj),
1521
+ [ssrImportMetaKey]: meta,
1522
+ };
1523
+ this.debug?.('[vite-runtime] executing', href);
1524
+ await this.runner.runViteModule(context, code, id);
1525
+ return exports;
1526
+ }
1527
+ }
1528
+ function exportAll(exports, sourceModule) {
1529
+ // when a module exports itself it causes
1530
+ // call stack error
1531
+ if (exports === sourceModule)
1532
+ return;
1533
+ if (isPrimitive(sourceModule) ||
1534
+ Array.isArray(sourceModule) ||
1535
+ sourceModule instanceof Promise)
1536
+ return;
1537
+ for (const key in sourceModule) {
1538
+ if (key !== 'default' && key !== '__esModule') {
1539
+ try {
1540
+ Object.defineProperty(exports, key, {
1541
+ enumerable: true,
1542
+ configurable: true,
1543
+ get: () => sourceModule[key],
1544
+ });
1545
+ }
1546
+ catch (_err) { }
1547
+ }
1548
+ }
1549
+ }
1550
+ /**
1551
+ * Vite converts `import { } from 'foo'` to `const _ = __vite_ssr_import__('foo')`.
1552
+ * Top-level imports and dynamic imports work slightly differently in Node.js.
1553
+ * This function normalizes the differences so it matches prod behaviour.
1554
+ */
1555
+ function analyzeImportedModDifference(mod, rawId, moduleType, metadata) {
1556
+ // No normalization needed if the user already dynamic imports this module
1557
+ if (metadata?.isDynamicImport)
1558
+ return;
1559
+ // If file path is ESM, everything should be fine
1560
+ if (moduleType === 'module')
1561
+ return;
1562
+ // For non-ESM, named imports is done via static analysis with cjs-module-lexer in Node.js.
1563
+ // If the user named imports a specifier that can't be analyzed, error.
1564
+ if (metadata?.importedNames?.length) {
1565
+ const missingBindings = metadata.importedNames.filter((s) => !(s in mod));
1566
+ if (missingBindings.length) {
1567
+ const lastBinding = missingBindings[missingBindings.length - 1];
1568
+ // Copied from Node.js
1569
+ throw new SyntaxError(`\
1570
+ [vite] Named export '${lastBinding}' not found. The requested module '${rawId}' is a CommonJS module, which may not support all module.exports as named exports.
1571
+ CommonJS modules can always be imported via the default export, for example using:
1572
+
1573
+ import pkg from '${rawId}';
1574
+ const {${missingBindings.join(', ')}} = pkg;
1575
+ `);
1576
+ }
1577
+ }
1578
+ }
1579
+ /**
1580
+ * Guard invalid named exports only, similar to how Node.js errors for top-level imports.
1581
+ * But since we transform as dynamic imports, we need to emulate the error manually.
1582
+ */
1583
+ function proxyGuardOnlyEsm(mod, rawId, metadata) {
1584
+ // If the module doesn't import anything explicitly, e.g. `import 'foo'` or
1585
+ // `import * as foo from 'foo'`, we can skip the proxy guard.
1586
+ if (!metadata?.importedNames?.length)
1587
+ return mod;
1588
+ return new Proxy(mod, {
1589
+ get(mod, prop) {
1590
+ if (prop !== 'then' && !(prop in mod)) {
1591
+ throw new SyntaxError(`[vite] The requested module '${rawId}' does not provide an export named '${prop.toString()}'`);
1592
+ }
1593
+ return mod[prop];
1594
+ },
1595
+ });
1596
+ }
1597
+
1598
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
1599
+ const AsyncFunction = async function () { }.constructor;
1600
+ class ESModulesRunner {
1601
+ async runViteModule(context, code) {
1602
+ // use AsyncFunction instead of vm module to support broader array of environments out of the box
1603
+ const initModule = new AsyncFunction(ssrModuleExportsKey, ssrImportMetaKey, ssrImportKey, ssrDynamicImportKey, ssrExportAllKey,
1604
+ // source map should already be inlined by Vite
1605
+ '"use strict";' + code);
1606
+ await initModule(context[ssrModuleExportsKey], context[ssrImportMetaKey], context[ssrImportKey], context[ssrDynamicImportKey], context[ssrExportAllKey]);
1607
+ Object.freeze(context[ssrModuleExportsKey]);
1608
+ }
1609
+ runExternalModule(filepath) {
1610
+ return import(filepath);
1611
+ }
1612
+ }
1613
+
1614
+ export { ESModulesRunner, ModuleCacheMap, ViteRuntime, ssrDynamicImportKey, ssrExportAllKey, ssrImportKey, ssrImportMetaKey, ssrModuleExportsKey };