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.
- package/dist/client/client.mjs +8 -0
- package/dist/client/client.mjs.map +1 -1
- package/dist/node/chunks/{dep-JW1Wr5se.js → dep-0ozvs92U.js} +1 -1
- package/dist/node/chunks/{dep-AgYU8wIQ.js → dep-4a4aOlj8.js} +1 -1
- package/dist/node/chunks/{dep-Y86Adl1p.js → dep-ZX7UfftI.js} +190 -27
- package/dist/node/cli.js +6 -6
- package/dist/node/index.d.ts +74 -1
- package/dist/node/index.js +110 -5
- package/dist/node/runtime.d.ts +12 -0
- package/dist/node/runtime.js +1614 -0
- package/dist/node/types.d-jgA8ss1A.d.ts +324 -0
- package/package.json +13 -2
- package/types/hmrPayload.d.ts +2 -0
@@ -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 };
|