vite-node 3.2.0-beta.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);
@@ -22,7 +23,7 @@ function hashCode(s) {
22
23
  class Debugger {
23
24
  dumpDir;
24
25
  initPromise;
25
- externalizeMap = new Map();
26
+ externalizeMap = /* @__PURE__ */ new Map();
26
27
  constructor(root, options) {
27
28
  this.options = options;
28
29
  if (options.dumpModules) this.dumpDir = resolve(root, options.dumpModules === true ? ".vite-node/dump" : options.dumpModules);
@@ -67,7 +68,7 @@ class Debugger {
67
68
  async writeInfo() {
68
69
  if (!this.dumpDir) return;
69
70
  const info = JSON.stringify({
70
- time: new Date().toLocaleString(),
71
+ time: (/* @__PURE__ */ new Date()).toLocaleString(),
71
72
  externalize: Object.fromEntries(this.externalizeMap.entries())
72
73
  }, null, 2);
73
74
  return promises.writeFile(join(this.dumpDir, "info.json"), info, "utf-8");
@@ -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;
@@ -124,19 +126,24 @@ async function isValidNodeImport(id) {
124
126
  return false;
125
127
  }
126
128
  }
127
- const _defaultExternalizeCache = new Map();
129
+ const _defaultExternalizeCache = /* @__PURE__ */ new Map();
128
130
  async function shouldExternalize(id, options, cache = _defaultExternalizeCache) {
129
131
  if (!cache.has(id)) cache.set(id, _shouldExternalize(id, options));
130
132
  return cache.get(id);
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);
@@ -163,33 +170,38 @@ function patchWindowsImportPath(path) {
163
170
  const debugRequest = createDebug("vite-node:server:request");
164
171
  class ViteNodeServer {
165
172
  fetchPromiseMap = {
166
- ssr: new Map(),
167
- web: new Map()
173
+ ssr: /* @__PURE__ */ new Map(),
174
+ web: /* @__PURE__ */ new Map()
168
175
  };
169
176
  transformPromiseMap = {
170
- ssr: new Map(),
171
- web: new Map()
177
+ ssr: /* @__PURE__ */ new Map(),
178
+ web: /* @__PURE__ */ new Map()
172
179
  };
173
180
  durations = {
174
- ssr: new Map(),
175
- web: new Map()
181
+ ssr: /* @__PURE__ */ new Map(),
182
+ web: /* @__PURE__ */ new Map()
176
183
  };
177
- existingOptimizedDeps = new Set();
184
+ existingOptimizedDeps = /* @__PURE__ */ new Set();
178
185
  fetchCaches = {
179
- ssr: new Map(),
180
- web: new Map()
186
+ ssr: /* @__PURE__ */ new Map(),
187
+ web: /* @__PURE__ */ new Map()
181
188
  };
182
- fetchCache = new Map();
183
- externalizeCache = new Map();
189
+ fetchCache = /* @__PURE__ */ new Map();
190
+ externalizeCache = /* @__PURE__ */ 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 });
@@ -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:")) path = path.replace(/file:\/\/\/(\w:)?/, (protocol, drive) => {
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 fileLocation += "<anonymous>";
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 ?? void 0;
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;
@@ -848,7 +920,6 @@ let SOURCEMAPPING_URL = "sourceMa";
848
920
  SOURCEMAPPING_URL += "ppingURL";
849
921
  const VITE_NODE_SOURCEMAPPING_SOURCE = "//# sourceMappingSource=vite-node";
850
922
  const VITE_NODE_SOURCEMAPPING_URL = `${SOURCEMAPPING_URL}=data:application/json;charset=utf-8`;
851
- const VITE_NODE_SOURCEMAPPING_REGEXP = new RegExp(`//# ${VITE_NODE_SOURCEMAPPING_URL};base64,(.+)`);
852
923
  function withInlineSourcemap(result, options) {
853
924
  const map = result.map;
854
925
  let code = result.code;
@@ -857,6 +928,10 @@ function withInlineSourcemap(result, options) {
857
928
  var _map$sources;
858
929
  map.sources = (_map$sources = map.sources) === null || _map$sources === void 0 ? void 0 : _map$sources.map((source) => {
859
930
  if (!source) return source;
931
+ // sometimes files here are absolute,
932
+ // but they are considered absolute to the server url, not the file system
933
+ // this is a bug in Vite
934
+ // all files should be either absolute to the file system or relative to the source map file
860
935
  if (pathe.isAbsolute(source)) {
861
936
  const actualPath = !source.startsWith(utils.withTrailingSlash(options.root)) && source.startsWith("/") ? pathe.resolve(options.root, source.slice(1)) : source;
862
937
  return pathe.relative(pathe.dirname(options.filepath), actualPath);
@@ -864,17 +939,25 @@ function withInlineSourcemap(result, options) {
864
939
  return source;
865
940
  });
866
941
  }
942
+ // to reduce the payload size, we only inline vite node source map, because it's also the only one we use
867
943
  const OTHER_SOURCE_MAP_REGEXP = new RegExp(`//# ${SOURCEMAPPING_URL}=data:application/json[^,]+base64,([A-Za-z0-9+/=]+)$`, "gm");
868
944
  while (OTHER_SOURCE_MAP_REGEXP.test(code)) code = code.replace(OTHER_SOURCE_MAP_REGEXP, "");
945
+ // If the first line is not present on source maps, add simple 1:1 mapping ([0,0,0,0], [1,0,0,0])
946
+ // so that debuggers can be set to break on first line
947
+ // Since Vite 6, import statements at the top of the file are preserved correctly,
948
+ // so we don't need to add this mapping anymore.
869
949
  if (!options.noFirstLineMapping && map.mappings.startsWith(";")) map.mappings = `AAAA,CAAA${map.mappings}`;
870
950
  const sourceMap = Buffer.from(JSON.stringify(map), "utf-8").toString("base64");
871
951
  result.code = `${code.trimEnd()}\n\n${VITE_NODE_SOURCEMAPPING_SOURCE}\n//# ${VITE_NODE_SOURCEMAPPING_URL};base64,${sourceMap}\n`;
872
952
  return result;
873
953
  }
874
954
  function extractSourceMap(code) {
875
- var _code$match;
876
- const mapString = (_code$match = code.match(VITE_NODE_SOURCEMAPPING_REGEXP)) === null || _code$match === void 0 ? void 0 : _code$match[1];
877
- if (mapString) return JSON.parse(Buffer.from(mapString, "base64").toString("utf-8"));
955
+ const regexp = new RegExp(`//# ${VITE_NODE_SOURCEMAPPING_URL};base64,(.+)`, "gm");
956
+ let lastMatch, match;
957
+ // eslint-disable-next-line no-cond-assign
958
+ while (match = regexp.exec(code)) lastMatch = match;
959
+ // pick only the last source map keeping user strings that look like maps
960
+ if (lastMatch) return JSON.parse(Buffer.from(lastMatch[1], "base64").toString("utf-8"));
878
961
  return null;
879
962
  }
880
963
  function installSourcemapsSupport(options) {