vite-node 3.2.0-beta.2 → 3.2.0-beta.3
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/chunk-hmr.cjs +19 -3
- package/dist/chunk-hmr.mjs +19 -3
- package/dist/cli.cjs +5 -2
- package/dist/cli.mjs +5 -2
- package/dist/client.cjs +29 -0
- package/dist/client.mjs +29 -0
- package/dist/hmr.d.ts +3 -0
- package/dist/server.cjs +22 -1
- package/dist/server.mjs +22 -1
- package/dist/source-map.cjs +84 -3
- package/dist/source-map.mjs +84 -3
- package/dist/utils.cjs +9 -0
- package/dist/utils.mjs +9 -0
- package/package.json +3 -3
package/dist/server.mjs
CHANGED
|
@@ -13,6 +13,7 @@ import { withInlineSourcemap } from './source-map.mjs';
|
|
|
13
13
|
import 'node:module';
|
|
14
14
|
import 'node:path';
|
|
15
15
|
|
|
16
|
+
/* eslint-disable no-console */
|
|
16
17
|
function hashCode(s) {
|
|
17
18
|
return s.split("").reduce((a, b) => {
|
|
18
19
|
a = (a << 5) - a + b.charCodeAt(0);
|
|
@@ -107,6 +108,7 @@ function guessCJSversion(id) {
|
|
|
107
108
|
]) if (existsSync(i)) return i;
|
|
108
109
|
}
|
|
109
110
|
}
|
|
111
|
+
// The code from https://github.com/unjs/mlly/blob/c5bcca0cda175921344fd6de1bc0c499e73e5dac/src/syntax.ts#L51-L98
|
|
110
112
|
async function isValidNodeImport(id) {
|
|
111
113
|
const extension = extname(id);
|
|
112
114
|
if (BUILTIN_EXTENSIONS.has(extension)) return true;
|
|
@@ -131,12 +133,17 @@ async function shouldExternalize(id, options, cache = _defaultExternalizeCache)
|
|
|
131
133
|
}
|
|
132
134
|
async function _shouldExternalize(id, options) {
|
|
133
135
|
if (isNodeBuiltin(id)) return id;
|
|
136
|
+
// data: should be processed by native import,
|
|
137
|
+
// since it is a feature of ESM.
|
|
138
|
+
// also externalize network imports since nodejs allows it when --experimental-network-imports
|
|
134
139
|
if (id.startsWith("data:") || /^(?:https?:)?\/\//.test(id)) return id;
|
|
135
140
|
id = patchWindowsImportPath(id);
|
|
136
141
|
const moduleDirectories = (options === null || options === void 0 ? void 0 : options.moduleDirectories) || ["/node_modules/"];
|
|
137
142
|
if (matchExternalizePattern(id, moduleDirectories, options === null || options === void 0 ? void 0 : options.inline)) return false;
|
|
138
143
|
if ((options === null || options === void 0 ? void 0 : options.inlineFiles) && (options === null || options === void 0 ? void 0 : options.inlineFiles.includes(id))) return false;
|
|
139
144
|
if (matchExternalizePattern(id, moduleDirectories, options === null || options === void 0 ? void 0 : options.external)) return id;
|
|
145
|
+
// Unless the user explicitly opted to inline them, externalize Vite deps.
|
|
146
|
+
// They are too big to inline by default.
|
|
140
147
|
if ((options === null || options === void 0 ? void 0 : options.cacheDir) && id.includes(options.cacheDir)) return id;
|
|
141
148
|
const isLibraryModule = moduleDirectories.some((dir) => id.includes(dir));
|
|
142
149
|
const guessCJS = isLibraryModule && (options === null || options === void 0 ? void 0 : options.fallbackCJS);
|
|
@@ -183,13 +190,18 @@ class ViteNodeServer {
|
|
|
183
190
|
externalizeCache = new Map();
|
|
184
191
|
debugger;
|
|
185
192
|
constructor(server, options = {}) {
|
|
193
|
+
var _options$deps3;
|
|
186
194
|
this.server = server;
|
|
187
195
|
this.options = options;
|
|
188
|
-
var _options$deps3;
|
|
189
196
|
const ssrOptions = server.config.ssr;
|
|
190
197
|
options.deps ?? (options.deps = {});
|
|
191
198
|
options.deps.cacheDir = relative(server.config.root, options.deps.cacheDir || server.config.cacheDir);
|
|
192
199
|
if (ssrOptions) {
|
|
200
|
+
// we don't externalize ssr, because it has different semantics in Vite
|
|
201
|
+
// if (ssrOptions.external) {
|
|
202
|
+
// options.deps.external ??= []
|
|
203
|
+
// options.deps.external.push(...ssrOptions.external)
|
|
204
|
+
// }
|
|
193
205
|
if (ssrOptions.noExternal === true) {
|
|
194
206
|
var _options$deps;
|
|
195
207
|
(_options$deps = options.deps).inline ?? (_options$deps.inline = true);
|
|
@@ -219,6 +231,7 @@ class ViteNodeServer {
|
|
|
219
231
|
if (!dir.endsWith("/")) dir += "/";
|
|
220
232
|
return normalize(dir);
|
|
221
233
|
});
|
|
234
|
+
// always add node_modules as a module directory
|
|
222
235
|
if (!options.deps.moduleDirectories.includes("/node_modules/")) options.deps.moduleDirectories.push("/node_modules/");
|
|
223
236
|
}
|
|
224
237
|
shouldExternalize(id) {
|
|
@@ -272,6 +285,7 @@ class ViteNodeServer {
|
|
|
272
285
|
const moduleId = normalizeModuleId(id);
|
|
273
286
|
this.assertMode(mode);
|
|
274
287
|
const promiseMap = this.fetchPromiseMap[mode];
|
|
288
|
+
// reuse transform for concurrent requests
|
|
275
289
|
if (!promiseMap.has(moduleId)) promiseMap.set(moduleId, this._fetchModule(moduleId, mode).finally(() => {
|
|
276
290
|
promiseMap.delete(moduleId);
|
|
277
291
|
}));
|
|
@@ -281,6 +295,7 @@ class ViteNodeServer {
|
|
|
281
295
|
const mode = transformMode || this.getTransformMode(id);
|
|
282
296
|
this.assertMode(mode);
|
|
283
297
|
const promiseMap = this.transformPromiseMap[mode];
|
|
298
|
+
// reuse transform for concurrent requests
|
|
284
299
|
if (!promiseMap.has(id)) promiseMap.set(id, this._transformRequest(id, filepath, mode).finally(() => {
|
|
285
300
|
promiseMap.delete(id);
|
|
286
301
|
}));
|
|
@@ -306,6 +321,7 @@ class ViteNodeServer {
|
|
|
306
321
|
if (module) return module;
|
|
307
322
|
const _modules = this.server.moduleGraph.getModulesByFile(file);
|
|
308
323
|
if (!_modules || !_modules.size) return null;
|
|
324
|
+
// find the latest changed module
|
|
309
325
|
const modules = [..._modules];
|
|
310
326
|
let mod = modules[0];
|
|
311
327
|
let latestMax = -1;
|
|
@@ -333,6 +349,9 @@ class ViteNodeServer {
|
|
|
333
349
|
const { path: filePath } = toFilePath(id, this.server.config.root);
|
|
334
350
|
const moduleNode = this.getChangedModule(id, filePath);
|
|
335
351
|
const cache = this.fetchCaches[transformMode].get(filePath);
|
|
352
|
+
// lastUpdateTimestamp is the timestamp that marks the last time the module was changed
|
|
353
|
+
// if lastUpdateTimestamp is 0, then the module was not changed since the server started
|
|
354
|
+
// we test "timestamp === 0" for expressiveness, but it's not necessary
|
|
336
355
|
const timestamp = moduleNode ? Math.max(moduleNode.lastHMRTimestamp, moduleNode.lastInvalidationTimestamp) : 0;
|
|
337
356
|
if (cache && (timestamp === 0 || cache.timestamp >= timestamp)) return cache.result;
|
|
338
357
|
const time = Date.now();
|
|
@@ -380,6 +399,8 @@ class ViteNodeServer {
|
|
|
380
399
|
if (result) return result;
|
|
381
400
|
}
|
|
382
401
|
if (transformMode === "web") {
|
|
402
|
+
// for components like Vue, we want to use the client side
|
|
403
|
+
// plugins but then convert the code to be consumed by the server
|
|
383
404
|
result = await this.server.transformRequest(id);
|
|
384
405
|
if (result) result = await this.server.ssrTransform(result.code, result.map, id);
|
|
385
406
|
} else result = await this.server.transformRequest(id, { ssr: true });
|
package/dist/source-map.cjs
CHANGED
|
@@ -583,10 +583,15 @@ function traceSegmentInternal(segments, memo, line, column, bias) {
|
|
|
583
583
|
return index;
|
|
584
584
|
}
|
|
585
585
|
|
|
586
|
+
// Only install once if called multiple times
|
|
586
587
|
let errorFormatterInstalled = false;
|
|
588
|
+
// Maps a file path to a string containing the file contents
|
|
587
589
|
const fileContentsCache = {};
|
|
590
|
+
// Maps a file path to a source map for that file
|
|
588
591
|
const sourceMapCache = {};
|
|
592
|
+
// Regex for detecting source maps
|
|
589
593
|
const reSourceMap = /^data:application\/json[^,]+base64,/;
|
|
594
|
+
// Priority list of retrieve handlers
|
|
590
595
|
let retrieveFileHandlers = [];
|
|
591
596
|
let retrieveMapHandlers = [];
|
|
592
597
|
function globalProcessVersion() {
|
|
@@ -604,8 +609,11 @@ function handlerExec(list) {
|
|
|
604
609
|
}
|
|
605
610
|
let retrieveFile = handlerExec(retrieveFileHandlers);
|
|
606
611
|
retrieveFileHandlers.push((path) => {
|
|
612
|
+
// Trim the path to make sure there is no extra whitespace.
|
|
607
613
|
path = path.trim();
|
|
608
|
-
if (path.startsWith("file:"))
|
|
614
|
+
if (path.startsWith("file:"))
|
|
615
|
+
// existsSync/readFileSync can't handle file protocol, but once stripped, it works
|
|
616
|
+
path = path.replace(/file:\/\/\/(\w:)?/, (protocol, drive) => {
|
|
609
617
|
return drive ? "" : "/";
|
|
610
618
|
});
|
|
611
619
|
if (path in fileContentsCache) return fileContentsCache[path];
|
|
@@ -615,6 +623,7 @@ retrieveFileHandlers.push((path) => {
|
|
|
615
623
|
} catch {}
|
|
616
624
|
return fileContentsCache[path] = contents;
|
|
617
625
|
});
|
|
626
|
+
// Support URLs relative to a directory, but be careful about a protocol prefix
|
|
618
627
|
function supportRelativeURL(file, url) {
|
|
619
628
|
if (!file) return url;
|
|
620
629
|
const dir = path.dirname(file);
|
|
@@ -622,30 +631,43 @@ function supportRelativeURL(file, url) {
|
|
|
622
631
|
let protocol = match ? match[0] : "";
|
|
623
632
|
const startPath = dir.slice(protocol.length);
|
|
624
633
|
if (protocol && /^\/\w:/.test(startPath)) {
|
|
634
|
+
// handle file:///C:/ paths
|
|
625
635
|
protocol += "/";
|
|
626
636
|
return protocol + path.resolve(dir.slice(protocol.length), url).replace(/\\/g, "/");
|
|
627
637
|
}
|
|
628
638
|
return protocol + path.resolve(dir.slice(protocol.length), url);
|
|
629
639
|
}
|
|
630
640
|
function retrieveSourceMapURL(source) {
|
|
641
|
+
// Get the URL of the source map
|
|
631
642
|
const fileData = retrieveFile(source);
|
|
632
643
|
if (!fileData) return null;
|
|
633
644
|
const re = /\/\/[@#]\s*sourceMappingURL=([^\s'"]+)\s*$|\/\*[@#]\s*sourceMappingURL=[^\s*'"]+\s*\*\/\s*$/gm;
|
|
645
|
+
// Keep executing the search to find the *last* sourceMappingURL to avoid
|
|
646
|
+
// picking up sourceMappingURLs from comments, strings, etc.
|
|
634
647
|
let lastMatch, match;
|
|
648
|
+
// eslint-disable-next-line no-cond-assign
|
|
635
649
|
while (match = re.exec(fileData)) lastMatch = match;
|
|
636
650
|
if (!lastMatch) return null;
|
|
637
651
|
return lastMatch[1];
|
|
638
652
|
}
|
|
653
|
+
// Can be overridden by the retrieveSourceMap option to install. Takes a
|
|
654
|
+
// generated source filename; returns a {map, optional url} object, or null if
|
|
655
|
+
// there is no source map. The map field may be either a string or the parsed
|
|
656
|
+
// JSON object (ie, it must be a valid argument to the SourceMapConsumer
|
|
657
|
+
// constructor).
|
|
639
658
|
let retrieveSourceMap = handlerExec(retrieveMapHandlers);
|
|
640
659
|
retrieveMapHandlers.push((source) => {
|
|
641
660
|
let sourceMappingURL = retrieveSourceMapURL(source);
|
|
642
661
|
if (!sourceMappingURL) return null;
|
|
662
|
+
// Read the contents of the source map
|
|
643
663
|
let sourceMapData;
|
|
644
664
|
if (reSourceMap.test(sourceMappingURL)) {
|
|
665
|
+
// Support source map URL as a data url
|
|
645
666
|
const rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(",") + 1);
|
|
646
667
|
sourceMapData = Buffer.from(rawData, "base64").toString();
|
|
647
668
|
sourceMappingURL = source;
|
|
648
669
|
} else {
|
|
670
|
+
// Support source map URLs relative to the source URL
|
|
649
671
|
sourceMappingURL = supportRelativeURL(source, sourceMappingURL);
|
|
650
672
|
sourceMapData = retrieveFile(sourceMappingURL);
|
|
651
673
|
}
|
|
@@ -655,10 +677,16 @@ retrieveMapHandlers.push((source) => {
|
|
|
655
677
|
map: sourceMapData
|
|
656
678
|
};
|
|
657
679
|
});
|
|
680
|
+
// interface Position {
|
|
681
|
+
// source: string
|
|
682
|
+
// line: number
|
|
683
|
+
// column: number
|
|
684
|
+
// }
|
|
658
685
|
function mapSourcePosition(position) {
|
|
659
686
|
if (!position.source) return position;
|
|
660
687
|
let sourceMap = sourceMapCache[position.source];
|
|
661
688
|
if (!sourceMap) {
|
|
689
|
+
// Call the (overridable) retrieveSourceMap function to get the source map.
|
|
662
690
|
const urlAndMap = retrieveSourceMap(position.source);
|
|
663
691
|
if (urlAndMap && urlAndMap.map) {
|
|
664
692
|
var _sourceMap$map;
|
|
@@ -666,6 +694,8 @@ function mapSourcePosition(position) {
|
|
|
666
694
|
url: urlAndMap.url,
|
|
667
695
|
map: new TraceMap(urlAndMap.map)
|
|
668
696
|
};
|
|
697
|
+
// Load all sources stored inline with the source map into the file cache
|
|
698
|
+
// to pretend like they are already loaded. They may not exist on disk.
|
|
669
699
|
if ((_sourceMap$map = sourceMap.map) === null || _sourceMap$map === void 0 ? void 0 : _sourceMap$map.sourcesContent) sourceMap.map.sources.forEach((source, i) => {
|
|
670
700
|
var _sourceMap$map2;
|
|
671
701
|
const contents = (_sourceMap$map2 = sourceMap.map) === null || _sourceMap$map2 === void 0 || (_sourceMap$map2 = _sourceMap$map2.sourcesContent) === null || _sourceMap$map2 === void 0 ? void 0 : _sourceMap$map2[i];
|
|
@@ -679,8 +709,14 @@ function mapSourcePosition(position) {
|
|
|
679
709
|
map: null
|
|
680
710
|
};
|
|
681
711
|
}
|
|
712
|
+
// Resolve the source URL relative to the URL of the source map
|
|
682
713
|
if (sourceMap && sourceMap.map && sourceMap.url) {
|
|
683
714
|
const originalPosition = originalPositionFor(sourceMap.map, position);
|
|
715
|
+
// Only return the original position if a matching line was found. If no
|
|
716
|
+
// matching line is found then we return position instead, which will cause
|
|
717
|
+
// the stack trace to print the path and line for the compiled file. It is
|
|
718
|
+
// better to give a precise location in the compiled file than a vague
|
|
719
|
+
// location in the original file.
|
|
684
720
|
if (originalPosition.source !== null) {
|
|
685
721
|
originalPosition.source = supportRelativeURL(sourceMap.url, originalPosition.source);
|
|
686
722
|
return originalPosition;
|
|
@@ -688,7 +724,10 @@ function mapSourcePosition(position) {
|
|
|
688
724
|
}
|
|
689
725
|
return position;
|
|
690
726
|
}
|
|
727
|
+
// Parses code generated by FormatEvalOrigin(), a function inside V8:
|
|
728
|
+
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js
|
|
691
729
|
function mapEvalOrigin(origin) {
|
|
730
|
+
// Most eval() calls are in this format
|
|
692
731
|
let match = /^eval at ([^(]+) \((.+):(\d+):(\d+)\)$/.exec(origin);
|
|
693
732
|
if (match) {
|
|
694
733
|
const position = mapSourcePosition({
|
|
@@ -699,10 +738,18 @@ function mapEvalOrigin(origin) {
|
|
|
699
738
|
});
|
|
700
739
|
return `eval at ${match[1]} (${position.source}:${position.line}:${position.column + 1})`;
|
|
701
740
|
}
|
|
741
|
+
// Parse nested eval() calls using recursion
|
|
702
742
|
match = /^eval at ([^(]+) \((.+)\)$/.exec(origin);
|
|
703
743
|
if (match) return `eval at ${match[1]} (${mapEvalOrigin(match[2])})`;
|
|
744
|
+
// Make sure we still return useful information if we didn't find anything
|
|
704
745
|
return origin;
|
|
705
746
|
}
|
|
747
|
+
// This is copied almost verbatim from the V8 source code at
|
|
748
|
+
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js. The
|
|
749
|
+
// implementation of wrapCallSite() used to just forward to the actual source
|
|
750
|
+
// code of CallSite.prototype.toString but unfortunately a new release of V8
|
|
751
|
+
// did something to the prototype chain and broke the shim. The only fix I
|
|
752
|
+
// could find was copy/paste.
|
|
706
753
|
function CallSiteToString() {
|
|
707
754
|
let fileName;
|
|
708
755
|
let fileLocation = "";
|
|
@@ -714,7 +761,11 @@ function CallSiteToString() {
|
|
|
714
761
|
fileLocation += ", ";
|
|
715
762
|
}
|
|
716
763
|
if (fileName) fileLocation += fileName;
|
|
717
|
-
else
|
|
764
|
+
else
|
|
765
|
+
// Source code does not originate from a file and is not native, but we
|
|
766
|
+
// can still get the source position inside the source string, e.g. in
|
|
767
|
+
// an eval string.
|
|
768
|
+
fileLocation += "<anonymous>";
|
|
718
769
|
const lineNumber = this.getLineNumber();
|
|
719
770
|
if (lineNumber != null) {
|
|
720
771
|
fileLocation += `:${lineNumber}`;
|
|
@@ -729,6 +780,7 @@ function CallSiteToString() {
|
|
|
729
780
|
const isMethodCall = !(this.isToplevel() || isConstructor);
|
|
730
781
|
if (isMethodCall) {
|
|
731
782
|
let typeName = this.getTypeName();
|
|
783
|
+
// Fixes shim to be backward compatible with Node v0 to v4
|
|
732
784
|
if (typeName === "[object Object]") typeName = "null";
|
|
733
785
|
const methodName = this.getMethodName();
|
|
734
786
|
if (functionName) {
|
|
@@ -749,7 +801,9 @@ function cloneCallSite(frame) {
|
|
|
749
801
|
const object = {};
|
|
750
802
|
Object.getOwnPropertyNames(Object.getPrototypeOf(frame)).forEach((name) => {
|
|
751
803
|
const key = name;
|
|
804
|
+
// @ts-expect-error difficult to type
|
|
752
805
|
object[key] = /^(?:is|get)/.test(name) ? function() {
|
|
806
|
+
// eslint-disable-next-line no-useless-call
|
|
753
807
|
return frame[key].call(frame);
|
|
754
808
|
} : frame[key];
|
|
755
809
|
});
|
|
@@ -757,6 +811,7 @@ function cloneCallSite(frame) {
|
|
|
757
811
|
return object;
|
|
758
812
|
}
|
|
759
813
|
function wrapCallSite(frame, state) {
|
|
814
|
+
// provides interface backward compatibility
|
|
760
815
|
if (state === void 0) state = {
|
|
761
816
|
nextPosition: null,
|
|
762
817
|
curPosition: null
|
|
@@ -765,10 +820,18 @@ function wrapCallSite(frame, state) {
|
|
|
765
820
|
state.curPosition = null;
|
|
766
821
|
return frame;
|
|
767
822
|
}
|
|
823
|
+
// Most call sites will return the source file from getFileName(), but code
|
|
824
|
+
// passed to eval() ending in "//# sourceURL=..." will return the source file
|
|
825
|
+
// from getScriptNameOrSourceURL() instead
|
|
768
826
|
const source = frame.getFileName() || frame.getScriptNameOrSourceURL();
|
|
769
827
|
if (source) {
|
|
770
828
|
const line = frame.getLineNumber();
|
|
771
829
|
let column = frame.getColumnNumber() - 1;
|
|
830
|
+
// Fix position in Node where some (internal) code is prepended.
|
|
831
|
+
// See https://github.com/evanw/node-source-map-support/issues/36
|
|
832
|
+
// Header removed in node at ^10.16 || >=11.11.0
|
|
833
|
+
// v11 is not an LTS candidate, we can just test the one version with it.
|
|
834
|
+
// Test node versions for: 10.16-19, 10.20+, 12-19, 20-99, 100+, or 11.11
|
|
772
835
|
const noHeader = /^v(?:10\.1[6-9]|10\.[2-9]\d|10\.\d{3,}|1[2-9]\d*|[2-9]\d|\d{3,}|11\.11)/;
|
|
773
836
|
const headerLength = noHeader.test(globalProcessVersion()) ? 0 : 62;
|
|
774
837
|
if (line === 1 && column > headerLength && !frame.isEval()) column -= headerLength;
|
|
@@ -786,7 +849,7 @@ function wrapCallSite(frame, state) {
|
|
|
786
849
|
return state.nextPosition.name || originalFunctionName();
|
|
787
850
|
};
|
|
788
851
|
frame.getFileName = function() {
|
|
789
|
-
return position.source ??
|
|
852
|
+
return position.source ?? null;
|
|
790
853
|
};
|
|
791
854
|
frame.getLineNumber = function() {
|
|
792
855
|
return position.line;
|
|
@@ -799,6 +862,7 @@ function wrapCallSite(frame, state) {
|
|
|
799
862
|
};
|
|
800
863
|
return frame;
|
|
801
864
|
}
|
|
865
|
+
// Code called using eval() needs special handling
|
|
802
866
|
let origin = frame.isEval() && frame.getEvalOrigin();
|
|
803
867
|
if (origin) {
|
|
804
868
|
origin = mapEvalOrigin(origin);
|
|
@@ -808,8 +872,11 @@ function wrapCallSite(frame, state) {
|
|
|
808
872
|
};
|
|
809
873
|
return frame;
|
|
810
874
|
}
|
|
875
|
+
// If we get here then we were unable to change the source position
|
|
811
876
|
return frame;
|
|
812
877
|
}
|
|
878
|
+
// This function is part of the V8 stack trace API, for more info see:
|
|
879
|
+
// https://v8.dev/docs/stack-trace-api
|
|
813
880
|
function prepareStackTrace(error, stack) {
|
|
814
881
|
const name = error.name || "Error";
|
|
815
882
|
const message = error.message || "";
|
|
@@ -830,14 +897,19 @@ retrieveFileHandlers.slice(0);
|
|
|
830
897
|
retrieveMapHandlers.slice(0);
|
|
831
898
|
function install(options) {
|
|
832
899
|
options = options || {};
|
|
900
|
+
// Allow sources to be found by methods other than reading the files
|
|
901
|
+
// directly from disk.
|
|
833
902
|
if (options.retrieveFile) {
|
|
834
903
|
if (options.overrideRetrieveFile) retrieveFileHandlers.length = 0;
|
|
835
904
|
retrieveFileHandlers.unshift(options.retrieveFile);
|
|
836
905
|
}
|
|
906
|
+
// Allow source maps to be found by methods other than reading the files
|
|
907
|
+
// directly from disk.
|
|
837
908
|
if (options.retrieveSourceMap) {
|
|
838
909
|
if (options.overrideRetrieveSourceMap) retrieveMapHandlers.length = 0;
|
|
839
910
|
retrieveMapHandlers.unshift(options.retrieveSourceMap);
|
|
840
911
|
}
|
|
912
|
+
// Install the error reformatter
|
|
841
913
|
if (!errorFormatterInstalled) {
|
|
842
914
|
errorFormatterInstalled = true;
|
|
843
915
|
Error.prepareStackTrace = prepareStackTrace;
|
|
@@ -857,6 +929,10 @@ function withInlineSourcemap(result, options) {
|
|
|
857
929
|
var _map$sources;
|
|
858
930
|
map.sources = (_map$sources = map.sources) === null || _map$sources === void 0 ? void 0 : _map$sources.map((source) => {
|
|
859
931
|
if (!source) return source;
|
|
932
|
+
// sometimes files here are absolute,
|
|
933
|
+
// but they are considered absolute to the server url, not the file system
|
|
934
|
+
// this is a bug in Vite
|
|
935
|
+
// all files should be either absolute to the file system or relative to the source map file
|
|
860
936
|
if (pathe.isAbsolute(source)) {
|
|
861
937
|
const actualPath = !source.startsWith(utils.withTrailingSlash(options.root)) && source.startsWith("/") ? pathe.resolve(options.root, source.slice(1)) : source;
|
|
862
938
|
return pathe.relative(pathe.dirname(options.filepath), actualPath);
|
|
@@ -864,8 +940,13 @@ function withInlineSourcemap(result, options) {
|
|
|
864
940
|
return source;
|
|
865
941
|
});
|
|
866
942
|
}
|
|
943
|
+
// to reduce the payload size, we only inline vite node source map, because it's also the only one we use
|
|
867
944
|
const OTHER_SOURCE_MAP_REGEXP = new RegExp(`//# ${SOURCEMAPPING_URL}=data:application/json[^,]+base64,([A-Za-z0-9+/=]+)$`, "gm");
|
|
868
945
|
while (OTHER_SOURCE_MAP_REGEXP.test(code)) code = code.replace(OTHER_SOURCE_MAP_REGEXP, "");
|
|
946
|
+
// If the first line is not present on source maps, add simple 1:1 mapping ([0,0,0,0], [1,0,0,0])
|
|
947
|
+
// so that debuggers can be set to break on first line
|
|
948
|
+
// Since Vite 6, import statements at the top of the file are preserved correctly,
|
|
949
|
+
// so we don't need to add this mapping anymore.
|
|
869
950
|
if (!options.noFirstLineMapping && map.mappings.startsWith(";")) map.mappings = `AAAA,CAAA${map.mappings}`;
|
|
870
951
|
const sourceMap = Buffer.from(JSON.stringify(map), "utf-8").toString("base64");
|
|
871
952
|
result.code = `${code.trimEnd()}\n\n${VITE_NODE_SOURCEMAPPING_SOURCE}\n//# ${VITE_NODE_SOURCEMAPPING_URL};base64,${sourceMap}\n`;
|
package/dist/source-map.mjs
CHANGED
|
@@ -581,10 +581,15 @@ function traceSegmentInternal(segments, memo, line, column, bias) {
|
|
|
581
581
|
return index;
|
|
582
582
|
}
|
|
583
583
|
|
|
584
|
+
// Only install once if called multiple times
|
|
584
585
|
let errorFormatterInstalled = false;
|
|
586
|
+
// Maps a file path to a string containing the file contents
|
|
585
587
|
const fileContentsCache = {};
|
|
588
|
+
// Maps a file path to a source map for that file
|
|
586
589
|
const sourceMapCache = {};
|
|
590
|
+
// Regex for detecting source maps
|
|
587
591
|
const reSourceMap = /^data:application\/json[^,]+base64,/;
|
|
592
|
+
// Priority list of retrieve handlers
|
|
588
593
|
let retrieveFileHandlers = [];
|
|
589
594
|
let retrieveMapHandlers = [];
|
|
590
595
|
function globalProcessVersion() {
|
|
@@ -602,8 +607,11 @@ function handlerExec(list) {
|
|
|
602
607
|
}
|
|
603
608
|
let retrieveFile = handlerExec(retrieveFileHandlers);
|
|
604
609
|
retrieveFileHandlers.push((path) => {
|
|
610
|
+
// Trim the path to make sure there is no extra whitespace.
|
|
605
611
|
path = path.trim();
|
|
606
|
-
if (path.startsWith("file:"))
|
|
612
|
+
if (path.startsWith("file:"))
|
|
613
|
+
// existsSync/readFileSync can't handle file protocol, but once stripped, it works
|
|
614
|
+
path = path.replace(/file:\/\/\/(\w:)?/, (protocol, drive) => {
|
|
607
615
|
return drive ? "" : "/";
|
|
608
616
|
});
|
|
609
617
|
if (path in fileContentsCache) return fileContentsCache[path];
|
|
@@ -613,6 +621,7 @@ retrieveFileHandlers.push((path) => {
|
|
|
613
621
|
} catch {}
|
|
614
622
|
return fileContentsCache[path] = contents;
|
|
615
623
|
});
|
|
624
|
+
// Support URLs relative to a directory, but be careful about a protocol prefix
|
|
616
625
|
function supportRelativeURL(file, url) {
|
|
617
626
|
if (!file) return url;
|
|
618
627
|
const dir = path.dirname(file);
|
|
@@ -620,30 +629,43 @@ function supportRelativeURL(file, url) {
|
|
|
620
629
|
let protocol = match ? match[0] : "";
|
|
621
630
|
const startPath = dir.slice(protocol.length);
|
|
622
631
|
if (protocol && /^\/\w:/.test(startPath)) {
|
|
632
|
+
// handle file:///C:/ paths
|
|
623
633
|
protocol += "/";
|
|
624
634
|
return protocol + path.resolve(dir.slice(protocol.length), url).replace(/\\/g, "/");
|
|
625
635
|
}
|
|
626
636
|
return protocol + path.resolve(dir.slice(protocol.length), url);
|
|
627
637
|
}
|
|
628
638
|
function retrieveSourceMapURL(source) {
|
|
639
|
+
// Get the URL of the source map
|
|
629
640
|
const fileData = retrieveFile(source);
|
|
630
641
|
if (!fileData) return null;
|
|
631
642
|
const re = /\/\/[@#]\s*sourceMappingURL=([^\s'"]+)\s*$|\/\*[@#]\s*sourceMappingURL=[^\s*'"]+\s*\*\/\s*$/gm;
|
|
643
|
+
// Keep executing the search to find the *last* sourceMappingURL to avoid
|
|
644
|
+
// picking up sourceMappingURLs from comments, strings, etc.
|
|
632
645
|
let lastMatch, match;
|
|
646
|
+
// eslint-disable-next-line no-cond-assign
|
|
633
647
|
while (match = re.exec(fileData)) lastMatch = match;
|
|
634
648
|
if (!lastMatch) return null;
|
|
635
649
|
return lastMatch[1];
|
|
636
650
|
}
|
|
651
|
+
// Can be overridden by the retrieveSourceMap option to install. Takes a
|
|
652
|
+
// generated source filename; returns a {map, optional url} object, or null if
|
|
653
|
+
// there is no source map. The map field may be either a string or the parsed
|
|
654
|
+
// JSON object (ie, it must be a valid argument to the SourceMapConsumer
|
|
655
|
+
// constructor).
|
|
637
656
|
let retrieveSourceMap = handlerExec(retrieveMapHandlers);
|
|
638
657
|
retrieveMapHandlers.push((source) => {
|
|
639
658
|
let sourceMappingURL = retrieveSourceMapURL(source);
|
|
640
659
|
if (!sourceMappingURL) return null;
|
|
660
|
+
// Read the contents of the source map
|
|
641
661
|
let sourceMapData;
|
|
642
662
|
if (reSourceMap.test(sourceMappingURL)) {
|
|
663
|
+
// Support source map URL as a data url
|
|
643
664
|
const rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(",") + 1);
|
|
644
665
|
sourceMapData = Buffer.from(rawData, "base64").toString();
|
|
645
666
|
sourceMappingURL = source;
|
|
646
667
|
} else {
|
|
668
|
+
// Support source map URLs relative to the source URL
|
|
647
669
|
sourceMappingURL = supportRelativeURL(source, sourceMappingURL);
|
|
648
670
|
sourceMapData = retrieveFile(sourceMappingURL);
|
|
649
671
|
}
|
|
@@ -653,10 +675,16 @@ retrieveMapHandlers.push((source) => {
|
|
|
653
675
|
map: sourceMapData
|
|
654
676
|
};
|
|
655
677
|
});
|
|
678
|
+
// interface Position {
|
|
679
|
+
// source: string
|
|
680
|
+
// line: number
|
|
681
|
+
// column: number
|
|
682
|
+
// }
|
|
656
683
|
function mapSourcePosition(position) {
|
|
657
684
|
if (!position.source) return position;
|
|
658
685
|
let sourceMap = sourceMapCache[position.source];
|
|
659
686
|
if (!sourceMap) {
|
|
687
|
+
// Call the (overridable) retrieveSourceMap function to get the source map.
|
|
660
688
|
const urlAndMap = retrieveSourceMap(position.source);
|
|
661
689
|
if (urlAndMap && urlAndMap.map) {
|
|
662
690
|
var _sourceMap$map;
|
|
@@ -664,6 +692,8 @@ function mapSourcePosition(position) {
|
|
|
664
692
|
url: urlAndMap.url,
|
|
665
693
|
map: new TraceMap(urlAndMap.map)
|
|
666
694
|
};
|
|
695
|
+
// Load all sources stored inline with the source map into the file cache
|
|
696
|
+
// to pretend like they are already loaded. They may not exist on disk.
|
|
667
697
|
if ((_sourceMap$map = sourceMap.map) === null || _sourceMap$map === void 0 ? void 0 : _sourceMap$map.sourcesContent) sourceMap.map.sources.forEach((source, i) => {
|
|
668
698
|
var _sourceMap$map2;
|
|
669
699
|
const contents = (_sourceMap$map2 = sourceMap.map) === null || _sourceMap$map2 === void 0 || (_sourceMap$map2 = _sourceMap$map2.sourcesContent) === null || _sourceMap$map2 === void 0 ? void 0 : _sourceMap$map2[i];
|
|
@@ -677,8 +707,14 @@ function mapSourcePosition(position) {
|
|
|
677
707
|
map: null
|
|
678
708
|
};
|
|
679
709
|
}
|
|
710
|
+
// Resolve the source URL relative to the URL of the source map
|
|
680
711
|
if (sourceMap && sourceMap.map && sourceMap.url) {
|
|
681
712
|
const originalPosition = originalPositionFor(sourceMap.map, position);
|
|
713
|
+
// Only return the original position if a matching line was found. If no
|
|
714
|
+
// matching line is found then we return position instead, which will cause
|
|
715
|
+
// the stack trace to print the path and line for the compiled file. It is
|
|
716
|
+
// better to give a precise location in the compiled file than a vague
|
|
717
|
+
// location in the original file.
|
|
682
718
|
if (originalPosition.source !== null) {
|
|
683
719
|
originalPosition.source = supportRelativeURL(sourceMap.url, originalPosition.source);
|
|
684
720
|
return originalPosition;
|
|
@@ -686,7 +722,10 @@ function mapSourcePosition(position) {
|
|
|
686
722
|
}
|
|
687
723
|
return position;
|
|
688
724
|
}
|
|
725
|
+
// Parses code generated by FormatEvalOrigin(), a function inside V8:
|
|
726
|
+
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js
|
|
689
727
|
function mapEvalOrigin(origin) {
|
|
728
|
+
// Most eval() calls are in this format
|
|
690
729
|
let match = /^eval at ([^(]+) \((.+):(\d+):(\d+)\)$/.exec(origin);
|
|
691
730
|
if (match) {
|
|
692
731
|
const position = mapSourcePosition({
|
|
@@ -697,10 +736,18 @@ function mapEvalOrigin(origin) {
|
|
|
697
736
|
});
|
|
698
737
|
return `eval at ${match[1]} (${position.source}:${position.line}:${position.column + 1})`;
|
|
699
738
|
}
|
|
739
|
+
// Parse nested eval() calls using recursion
|
|
700
740
|
match = /^eval at ([^(]+) \((.+)\)$/.exec(origin);
|
|
701
741
|
if (match) return `eval at ${match[1]} (${mapEvalOrigin(match[2])})`;
|
|
742
|
+
// Make sure we still return useful information if we didn't find anything
|
|
702
743
|
return origin;
|
|
703
744
|
}
|
|
745
|
+
// This is copied almost verbatim from the V8 source code at
|
|
746
|
+
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js. The
|
|
747
|
+
// implementation of wrapCallSite() used to just forward to the actual source
|
|
748
|
+
// code of CallSite.prototype.toString but unfortunately a new release of V8
|
|
749
|
+
// did something to the prototype chain and broke the shim. The only fix I
|
|
750
|
+
// could find was copy/paste.
|
|
704
751
|
function CallSiteToString() {
|
|
705
752
|
let fileName;
|
|
706
753
|
let fileLocation = "";
|
|
@@ -712,7 +759,11 @@ function CallSiteToString() {
|
|
|
712
759
|
fileLocation += ", ";
|
|
713
760
|
}
|
|
714
761
|
if (fileName) fileLocation += fileName;
|
|
715
|
-
else
|
|
762
|
+
else
|
|
763
|
+
// Source code does not originate from a file and is not native, but we
|
|
764
|
+
// can still get the source position inside the source string, e.g. in
|
|
765
|
+
// an eval string.
|
|
766
|
+
fileLocation += "<anonymous>";
|
|
716
767
|
const lineNumber = this.getLineNumber();
|
|
717
768
|
if (lineNumber != null) {
|
|
718
769
|
fileLocation += `:${lineNumber}`;
|
|
@@ -727,6 +778,7 @@ function CallSiteToString() {
|
|
|
727
778
|
const isMethodCall = !(this.isToplevel() || isConstructor);
|
|
728
779
|
if (isMethodCall) {
|
|
729
780
|
let typeName = this.getTypeName();
|
|
781
|
+
// Fixes shim to be backward compatible with Node v0 to v4
|
|
730
782
|
if (typeName === "[object Object]") typeName = "null";
|
|
731
783
|
const methodName = this.getMethodName();
|
|
732
784
|
if (functionName) {
|
|
@@ -747,7 +799,9 @@ function cloneCallSite(frame) {
|
|
|
747
799
|
const object = {};
|
|
748
800
|
Object.getOwnPropertyNames(Object.getPrototypeOf(frame)).forEach((name) => {
|
|
749
801
|
const key = name;
|
|
802
|
+
// @ts-expect-error difficult to type
|
|
750
803
|
object[key] = /^(?:is|get)/.test(name) ? function() {
|
|
804
|
+
// eslint-disable-next-line no-useless-call
|
|
751
805
|
return frame[key].call(frame);
|
|
752
806
|
} : frame[key];
|
|
753
807
|
});
|
|
@@ -755,6 +809,7 @@ function cloneCallSite(frame) {
|
|
|
755
809
|
return object;
|
|
756
810
|
}
|
|
757
811
|
function wrapCallSite(frame, state) {
|
|
812
|
+
// provides interface backward compatibility
|
|
758
813
|
if (state === void 0) state = {
|
|
759
814
|
nextPosition: null,
|
|
760
815
|
curPosition: null
|
|
@@ -763,10 +818,18 @@ function wrapCallSite(frame, state) {
|
|
|
763
818
|
state.curPosition = null;
|
|
764
819
|
return frame;
|
|
765
820
|
}
|
|
821
|
+
// Most call sites will return the source file from getFileName(), but code
|
|
822
|
+
// passed to eval() ending in "//# sourceURL=..." will return the source file
|
|
823
|
+
// from getScriptNameOrSourceURL() instead
|
|
766
824
|
const source = frame.getFileName() || frame.getScriptNameOrSourceURL();
|
|
767
825
|
if (source) {
|
|
768
826
|
const line = frame.getLineNumber();
|
|
769
827
|
let column = frame.getColumnNumber() - 1;
|
|
828
|
+
// Fix position in Node where some (internal) code is prepended.
|
|
829
|
+
// See https://github.com/evanw/node-source-map-support/issues/36
|
|
830
|
+
// Header removed in node at ^10.16 || >=11.11.0
|
|
831
|
+
// v11 is not an LTS candidate, we can just test the one version with it.
|
|
832
|
+
// Test node versions for: 10.16-19, 10.20+, 12-19, 20-99, 100+, or 11.11
|
|
770
833
|
const noHeader = /^v(?:10\.1[6-9]|10\.[2-9]\d|10\.\d{3,}|1[2-9]\d*|[2-9]\d|\d{3,}|11\.11)/;
|
|
771
834
|
const headerLength = noHeader.test(globalProcessVersion()) ? 0 : 62;
|
|
772
835
|
if (line === 1 && column > headerLength && !frame.isEval()) column -= headerLength;
|
|
@@ -784,7 +847,7 @@ function wrapCallSite(frame, state) {
|
|
|
784
847
|
return state.nextPosition.name || originalFunctionName();
|
|
785
848
|
};
|
|
786
849
|
frame.getFileName = function() {
|
|
787
|
-
return position.source ??
|
|
850
|
+
return position.source ?? null;
|
|
788
851
|
};
|
|
789
852
|
frame.getLineNumber = function() {
|
|
790
853
|
return position.line;
|
|
@@ -797,6 +860,7 @@ function wrapCallSite(frame, state) {
|
|
|
797
860
|
};
|
|
798
861
|
return frame;
|
|
799
862
|
}
|
|
863
|
+
// Code called using eval() needs special handling
|
|
800
864
|
let origin = frame.isEval() && frame.getEvalOrigin();
|
|
801
865
|
if (origin) {
|
|
802
866
|
origin = mapEvalOrigin(origin);
|
|
@@ -806,8 +870,11 @@ function wrapCallSite(frame, state) {
|
|
|
806
870
|
};
|
|
807
871
|
return frame;
|
|
808
872
|
}
|
|
873
|
+
// If we get here then we were unable to change the source position
|
|
809
874
|
return frame;
|
|
810
875
|
}
|
|
876
|
+
// This function is part of the V8 stack trace API, for more info see:
|
|
877
|
+
// https://v8.dev/docs/stack-trace-api
|
|
811
878
|
function prepareStackTrace(error, stack) {
|
|
812
879
|
const name = error.name || "Error";
|
|
813
880
|
const message = error.message || "";
|
|
@@ -828,14 +895,19 @@ retrieveFileHandlers.slice(0);
|
|
|
828
895
|
retrieveMapHandlers.slice(0);
|
|
829
896
|
function install(options) {
|
|
830
897
|
options = options || {};
|
|
898
|
+
// Allow sources to be found by methods other than reading the files
|
|
899
|
+
// directly from disk.
|
|
831
900
|
if (options.retrieveFile) {
|
|
832
901
|
if (options.overrideRetrieveFile) retrieveFileHandlers.length = 0;
|
|
833
902
|
retrieveFileHandlers.unshift(options.retrieveFile);
|
|
834
903
|
}
|
|
904
|
+
// Allow source maps to be found by methods other than reading the files
|
|
905
|
+
// directly from disk.
|
|
835
906
|
if (options.retrieveSourceMap) {
|
|
836
907
|
if (options.overrideRetrieveSourceMap) retrieveMapHandlers.length = 0;
|
|
837
908
|
retrieveMapHandlers.unshift(options.retrieveSourceMap);
|
|
838
909
|
}
|
|
910
|
+
// Install the error reformatter
|
|
839
911
|
if (!errorFormatterInstalled) {
|
|
840
912
|
errorFormatterInstalled = true;
|
|
841
913
|
Error.prepareStackTrace = prepareStackTrace;
|
|
@@ -855,6 +927,10 @@ function withInlineSourcemap(result, options) {
|
|
|
855
927
|
var _map$sources;
|
|
856
928
|
map.sources = (_map$sources = map.sources) === null || _map$sources === void 0 ? void 0 : _map$sources.map((source) => {
|
|
857
929
|
if (!source) return source;
|
|
930
|
+
// sometimes files here are absolute,
|
|
931
|
+
// but they are considered absolute to the server url, not the file system
|
|
932
|
+
// this is a bug in Vite
|
|
933
|
+
// all files should be either absolute to the file system or relative to the source map file
|
|
858
934
|
if (isAbsolute(source)) {
|
|
859
935
|
const actualPath = !source.startsWith(withTrailingSlash(options.root)) && source.startsWith("/") ? resolve$2(options.root, source.slice(1)) : source;
|
|
860
936
|
return relative(dirname(options.filepath), actualPath);
|
|
@@ -862,8 +938,13 @@ function withInlineSourcemap(result, options) {
|
|
|
862
938
|
return source;
|
|
863
939
|
});
|
|
864
940
|
}
|
|
941
|
+
// to reduce the payload size, we only inline vite node source map, because it's also the only one we use
|
|
865
942
|
const OTHER_SOURCE_MAP_REGEXP = new RegExp(`//# ${SOURCEMAPPING_URL}=data:application/json[^,]+base64,([A-Za-z0-9+/=]+)$`, "gm");
|
|
866
943
|
while (OTHER_SOURCE_MAP_REGEXP.test(code)) code = code.replace(OTHER_SOURCE_MAP_REGEXP, "");
|
|
944
|
+
// If the first line is not present on source maps, add simple 1:1 mapping ([0,0,0,0], [1,0,0,0])
|
|
945
|
+
// so that debuggers can be set to break on first line
|
|
946
|
+
// Since Vite 6, import statements at the top of the file are preserved correctly,
|
|
947
|
+
// so we don't need to add this mapping anymore.
|
|
867
948
|
if (!options.noFirstLineMapping && map.mappings.startsWith(";")) map.mappings = `AAAA,CAAA${map.mappings}`;
|
|
868
949
|
const sourceMap = Buffer.from(JSON.stringify(map), "utf-8").toString("base64");
|
|
869
950
|
result.code = `${code.trimEnd()}\n\n${VITE_NODE_SOURCEMAPPING_SOURCE}\n//# ${VITE_NODE_SOURCEMAPPING_URL};base64,${sourceMap}\n`;
|