vite 8.2.1 → 8.3.0-beta.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/bin/vite.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { performance } from 'node:perf_hooks'
3
2
  import module from 'node:module'
3
+ import { performance } from 'node:perf_hooks'
4
4
 
5
5
  if (!import.meta.url.includes('node_modules')) {
6
6
  if (!process.env.DEBUG_DISABLE_SOURCE_MAP) {
@@ -20,7 +20,9 @@ const debugIndex = process.argv.findIndex((arg) => /^(?:-d|--debug)$/.test(arg))
20
20
  const filterIndex = process.argv.findIndex((arg) =>
21
21
  /^(?:-f|--filter)$/.test(arg),
22
22
  )
23
- const profileIndex = process.argv.indexOf('--profile')
23
+ const profileIndex = process.argv.findIndex(
24
+ (arg) => arg === '--profile' || arg.startsWith('--profile='),
25
+ )
24
26
 
25
27
  if (debugIndex > 0) {
26
28
  let value = process.argv[debugIndex + 1]
@@ -63,10 +65,19 @@ function start() {
63
65
  }
64
66
 
65
67
  if (profileIndex > 0) {
66
- process.argv.splice(profileIndex, 1)
67
- const next = process.argv[profileIndex]
68
- if (next && next[0] !== '-') {
69
- process.argv.splice(profileIndex, 1)
68
+ const [profileArg] = process.argv.splice(profileIndex, 1)
69
+ // `--profile [name]` writes the profile to `<name>.cpuprofile`. The value is
70
+ // optional and consumed like cac does for other `[optional]` value flags.
71
+ let profileName = profileArg.slice('--profile='.length)
72
+ if (!profileName) {
73
+ const next = process.argv[profileIndex]
74
+ if (next && next[0] !== '-') {
75
+ process.argv.splice(profileIndex, 1)
76
+ profileName = next
77
+ }
78
+ }
79
+ if (profileName) {
80
+ global.__vite_profile_name = profileName
70
81
  }
71
82
  const inspector = await import('node:inspector').then((r) => r.default)
72
83
  const session = (global.__vite_profile_session = new inspector.Session())
@@ -8,7 +8,7 @@ let nanoid = (size = 21) => {
8
8
  return id;
9
9
  };
10
10
  //#endregion
11
- //#region ../../node_modules/.pnpm/rolldown@1.2.1/node_modules/rolldown/dist/experimental-runtime-base.mjs
11
+ //#region ../../node_modules/.pnpm/rolldown@1.2.6/node_modules/rolldown/dist/experimental-runtime-base.mjs
12
12
  var __create = Object.create;
13
13
  var __defProp = Object.defineProperty;
14
14
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -41,7 +41,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
41
41
  }) : target, mod));
42
42
  var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
43
43
  //#endregion
44
- //#region \0@oxc-project+runtime@0.142.0/helpers/esm/typeof.js
44
+ //#region \0@oxc-project+runtime@0.147.0/helpers/esm/typeof.js
45
45
  function _typeof(o) {
46
46
  "@babel/helpers - typeof";
47
47
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -51,7 +51,7 @@ function _typeof(o) {
51
51
  }, _typeof(o);
52
52
  }
53
53
  //#endregion
54
- //#region \0@oxc-project+runtime@0.142.0/helpers/esm/toPrimitive.js
54
+ //#region \0@oxc-project+runtime@0.147.0/helpers/esm/toPrimitive.js
55
55
  function toPrimitive(t, r) {
56
56
  if ("object" != _typeof(t) || !t) return t;
57
57
  var e = t[Symbol.toPrimitive];
@@ -63,13 +63,13 @@ function toPrimitive(t, r) {
63
63
  return ("string" === r ? String : Number)(t);
64
64
  }
65
65
  //#endregion
66
- //#region \0@oxc-project+runtime@0.142.0/helpers/esm/toPropertyKey.js
66
+ //#region \0@oxc-project+runtime@0.147.0/helpers/esm/toPropertyKey.js
67
67
  function toPropertyKey(t) {
68
68
  var i = toPrimitive(t, "string");
69
69
  return "symbol" == _typeof(i) ? i : i + "";
70
70
  }
71
71
  //#endregion
72
- //#region \0@oxc-project+runtime@0.142.0/helpers/esm/defineProperty.js
72
+ //#region \0@oxc-project+runtime@0.147.0/helpers/esm/defineProperty.js
73
73
  function _defineProperty(e, r, t) {
74
74
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
75
75
  value: t,
@@ -79,7 +79,7 @@ function _defineProperty(e, r, t) {
79
79
  }) : e[r] = t, e;
80
80
  }
81
81
  //#endregion
82
- //#region ../../node_modules/.pnpm/rolldown@1.2.1/node_modules/rolldown/dist/experimental-runtime.mjs
82
+ //#region ../../node_modules/.pnpm/rolldown@1.2.6/node_modules/rolldown/dist/experimental-runtime.mjs
83
83
  var Module = class {
84
84
  /**
85
85
  * @param {string} id
@@ -287,9 +287,9 @@ var DevRuntime = class {
287
287
  }
288
288
  /**
289
289
  * @param {string} id
290
- * @param {{ exports: any }} exportsHolder
290
+ * @param {{ exports: any }} [exportsHolder]
291
291
  */
292
- registerModule(id, exportsHolder) {
292
+ registerModule(id, exportsHolder = { exports: {} }) {
293
293
  const module = new Module(id);
294
294
  module.exportsHolder = exportsHolder;
295
295
  this.moduleCache.set(id, module);
@@ -585,7 +585,11 @@ var BundledDevHMRClient = class extends HMRClient {
585
585
  reason: `update propagated back to ${firstInvalidatedBy}, which already called \`import.meta.hot.invalidate()\``
586
586
  };
587
587
  if (this.isSelfAccepted(id)) {
588
- boundaries.push([id, id]);
588
+ boundaries.push({
589
+ boundary: id,
590
+ acceptedVia: id,
591
+ isWithinCircularImport: this.isNodeWithinCircularImports(id, stack)
592
+ });
589
593
  return;
590
594
  }
591
595
  const parents = this.runtime.getImporters(id).filter((p) => this.runtime.isExecuted(p));
@@ -594,17 +598,52 @@ var BundledDevHMRClient = class extends HMRClient {
594
598
  reason: `no hmr boundary found for module \`${id}\``
595
599
  };
596
600
  for (const parent of parents) {
601
+ const subChain = [...stack, parent];
597
602
  if (this.acceptsDep(parent, id)) {
598
- boundaries.push([parent, id]);
603
+ boundaries.push({
604
+ boundary: parent,
605
+ acceptedVia: id,
606
+ isWithinCircularImport: this.isNodeWithinCircularImports(parent, subChain)
607
+ });
599
608
  continue;
600
609
  }
601
- if (stack.includes(parent)) return {
602
- type: "full-reload",
603
- reason: `circular import chain between \`${id}\` and \`${parent}\``
604
- };
605
- const fullReload = this.bubble(parent, [...stack, parent], updateSet, boundaries, firstInvalidatedBy, traversedModules);
606
- if (fullReload) return fullReload;
610
+ if (!stack.includes(parent)) {
611
+ const fullReload = this.bubble(parent, subChain, updateSet, boundaries, firstInvalidatedBy, traversedModules);
612
+ if (fullReload) return fullReload;
613
+ }
614
+ }
615
+ }
616
+ /**
617
+ * Check importers recursively if it's an import loop. An accepted module within
618
+ * an import loop cannot recover its execution order and should be reloaded.
619
+ *
620
+ * @param node The node that accepts HMR and is a boundary
621
+ * @param nodeChain The chain of nodes/imports that lead to the node.
622
+ * (The last node in the chain imports the `node` parameter)
623
+ * @param currentChain The current chain tracked from the `node` parameter
624
+ * @param traversedModules The set of modules that have traversed
625
+ */
626
+ isNodeWithinCircularImports(node, nodeChain, currentChain = [node], traversedModules = /* @__PURE__ */ new Set()) {
627
+ if (traversedModules.has(node)) return false;
628
+ traversedModules.add(node);
629
+ for (const importer of this.runtime.getImporters(node)) {
630
+ if (importer === node) continue;
631
+ const importerIndex = nodeChain.indexOf(importer);
632
+ if (importerIndex > -1) {
633
+ const importChain = [
634
+ importer,
635
+ ...[...currentChain].reverse(),
636
+ ...nodeChain.slice(importerIndex, -1).reverse()
637
+ ];
638
+ this.logger.debug(`circular imports detected: ${importChain.join(" -> ")}`);
639
+ return true;
640
+ }
641
+ if (!currentChain.includes(importer)) {
642
+ const result = this.isNodeWithinCircularImports(importer, nodeChain, currentChain.concat(importer), traversedModules);
643
+ if (result) return result;
644
+ }
607
645
  }
646
+ return false;
608
647
  }
609
648
  handlePush(payload) {
610
649
  this.applyQueue = this.applyQueue.then(() => this.applyPush(payload)).catch((err) => {
@@ -674,15 +713,25 @@ var BundledDevHMRClient = class extends HMRClient {
674
713
  this.requestFullReload(`no factory for module \`${id}\``);
675
714
  return;
676
715
  }
677
- const applies = update.boundaries.map(([boundary, acceptedVia]) => ({
716
+ const applies = update.boundaries.map(({ boundary, acceptedVia, isWithinCircularImport }) => ({
678
717
  boundary,
679
718
  acceptedVia,
719
+ isWithinCircularImport,
680
720
  callbacks: this.hotModulesMap.get(boundary)?.callbacks.filter((c) => c.deps.includes(acceptedVia)) ?? []
681
721
  }));
682
722
  for (const id of update.updateSet) this.runtime.removeModuleCache(id);
683
- for (const { boundary, acceptedVia, callbacks } of applies) {
684
- this.runtime.initModule(acceptedVia);
685
- const fresh = this.runtime.loadExports(acceptedVia);
723
+ for (const { boundary, acceptedVia, isWithinCircularImport, callbacks } of applies) {
724
+ let fresh;
725
+ try {
726
+ this.runtime.initModule(acceptedVia);
727
+ fresh = this.runtime.loadExports(acceptedVia);
728
+ } catch (err) {
729
+ if (isWithinCircularImport) {
730
+ this.requestFullReload(`${acceptedVia} failed to apply HMR as it's within a circular import. Reloading page to reset the execution order.`);
731
+ return;
732
+ }
733
+ throw err;
734
+ }
686
735
  try {
687
736
  this.currentFirstInvalidatedBy = firstInvalidatedBy;
688
737
  for (const { deps, fn } of callbacks) fn(deps.map((dep) => dep === acceptedVia ? fresh : void 0));
@@ -695,11 +744,12 @@ var BundledDevHMRClient = class extends HMRClient {
695
744
  toUpdatePayload(boundaries, firstInvalidatedBy) {
696
745
  return {
697
746
  type: "update",
698
- updates: boundaries.map(([boundary, acceptedVia]) => ({
747
+ updates: boundaries.map(({ boundary, acceptedVia, isWithinCircularImport }) => ({
699
748
  type: "js-update",
700
749
  path: boundary,
701
750
  acceptedPath: acceptedVia,
702
751
  timestamp: Date.now(),
752
+ isWithinCircularImport,
703
753
  firstInvalidatedBy
704
754
  }))
705
755
  };
@@ -732,9 +782,33 @@ var BundledDevHMRContext = class extends HMRContext {
732
782
  };
733
783
  //#endregion
734
784
  //#region src/shared/constants.ts
785
+ /**
786
+ * Prefix for resolved Ids that are not valid browser import specifiers
787
+ */
788
+ const VALID_ID_PREFIX = `/@id/`;
789
+ /**
790
+ * Plugins that use 'virtual modules' (e.g. for helper functions), prefix the
791
+ * module ID with `\0`, a convention from the rollup ecosystem.
792
+ * This prevents other plugins from trying to process the id (like node resolution),
793
+ * and core features like sourcemaps can use this info to differentiate between
794
+ * virtual modules and regular files.
795
+ * `\0` is not a permitted char in import URLs so we have to replace them during
796
+ * import analysis. The id will be decoded back before entering the plugins pipeline.
797
+ * These encoded virtual ids are also prefixed by the VALID_ID_PREFIX, so virtual
798
+ * modules in the browser end up encoded as `/@id/__x00__{id}`
799
+ */
800
+ const NULL_BYTE_PLACEHOLDER = `__x00__`;
735
801
  let SOURCEMAPPING_URL = "sourceMa";
736
802
  SOURCEMAPPING_URL += "ppingURL";
737
803
  typeof process !== "undefined" && process.platform;
804
+ /**
805
+ * Prepend `/@id/` and replace null byte so the id is URL-safe.
806
+ * This is prepended to resolved ids that are not valid browser
807
+ * import specifiers by the importAnalysis plugin.
808
+ */
809
+ function wrapId(id) {
810
+ return id.startsWith(VALID_ID_PREFIX) ? id : VALID_ID_PREFIX + id.replace("\0", NULL_BYTE_PLACEHOLDER);
811
+ }
738
812
  (async function() {}).constructor;
739
813
  function promiseWithResolvers() {
740
814
  let resolve;
@@ -882,13 +956,17 @@ const normalizeModuleRunnerTransport = (transport) => {
882
956
  } } : {},
883
957
  async send(data) {
884
958
  if (!invokeableTransport.send) return;
885
- if (!isConnected) if (connectingPromise) await connectingPromise;
886
- else throw new SendBeforeConnectError("send was called before connect");
959
+ if (!isConnected) {
960
+ if (connectingPromise) await connectingPromise;
961
+ else throw new SendBeforeConnectError("send was called before connect");
962
+ }
887
963
  await invokeableTransport.send(data);
888
964
  },
889
965
  async invoke(name, data) {
890
- if (!isConnected) if (connectingPromise) await connectingPromise;
891
- else throw new SendBeforeConnectError("invoke was called before connect");
966
+ if (!isConnected) {
967
+ if (connectingPromise) await connectingPromise;
968
+ else throw new SendBeforeConnectError("invoke was called before connect");
969
+ }
892
970
  return invokeableTransport.invoke(name, data);
893
971
  }
894
972
  };
@@ -948,39 +1026,6 @@ const createWebSocketModuleRunnerTransport = (options) => {
948
1026
  };
949
1027
  };
950
1028
  //#endregion
951
- //#region src/shared/hmrHandler.ts
952
- function createHMRHandler(handler) {
953
- const queue = new Queue();
954
- return (payload) => queue.enqueue(() => handler(payload));
955
- }
956
- var Queue = class {
957
- constructor() {
958
- _defineProperty(this, "queue", []);
959
- _defineProperty(this, "pending", false);
960
- }
961
- enqueue(promise) {
962
- return new Promise((resolve, reject) => {
963
- this.queue.push({
964
- promise,
965
- resolve,
966
- reject
967
- });
968
- this.dequeue();
969
- });
970
- }
971
- dequeue() {
972
- if (this.pending) return false;
973
- const item = this.queue.shift();
974
- if (!item) return false;
975
- this.pending = true;
976
- item.promise().then(item.resolve).catch(item.reject).finally(() => {
977
- this.pending = false;
978
- this.dequeue();
979
- });
980
- return true;
981
- }
982
- };
983
- //#endregion
984
1029
  //#region src/shared/forwardConsole.ts
985
1030
  function setupForwardConsoleHandler(transport, options, console = globalThis.console) {
986
1031
  if (!options.enabled) return;
@@ -1109,6 +1154,39 @@ function stringifyConsoleArg(value) {
1109
1154
  }
1110
1155
  }
1111
1156
  //#endregion
1157
+ //#region src/shared/hmrHandler.ts
1158
+ function createHMRHandler(handler) {
1159
+ const queue = new Queue();
1160
+ return (payload) => queue.enqueue(() => handler(payload));
1161
+ }
1162
+ var Queue = class {
1163
+ constructor() {
1164
+ _defineProperty(this, "queue", []);
1165
+ _defineProperty(this, "pending", false);
1166
+ }
1167
+ enqueue(promise) {
1168
+ return new Promise((resolve, reject) => {
1169
+ this.queue.push({
1170
+ promise,
1171
+ resolve,
1172
+ reject
1173
+ });
1174
+ this.dequeue();
1175
+ });
1176
+ }
1177
+ dequeue() {
1178
+ if (this.pending) return false;
1179
+ const item = this.queue.shift();
1180
+ if (!item) return false;
1181
+ this.pending = true;
1182
+ item.promise().then(item.resolve).catch(item.reject).finally(() => {
1183
+ this.pending = false;
1184
+ this.dequeue();
1185
+ });
1186
+ return true;
1187
+ }
1188
+ };
1189
+ //#endregion
1112
1190
  //#region src/client/overlay.ts
1113
1191
  const hmrConfigName = __HMR_CONFIG_NAME__;
1114
1192
  const base$1 = __BASE__ || "/";
@@ -1426,14 +1504,18 @@ const debounceReload = (time) => {
1426
1504
  };
1427
1505
  };
1428
1506
  const pageReload = debounceReload(20);
1507
+ function wrapIdIfNeeded(id) {
1508
+ return id[0] === "." || id[0] === "/" ? id : wrapId(id);
1509
+ }
1429
1510
  const hmrClient = new HMRClient({
1430
1511
  error: (err) => console.error("[vite]", err),
1431
1512
  debug: (...msg) => console.debug("[vite]", ...msg)
1432
1513
  }, transport, async function importUpdatedModule({ acceptedPath, timestamp, explicitImportRequired, isWithinCircularImport }) {
1433
1514
  const [acceptedPathWithoutQuery, query] = acceptedPath.split(`?`);
1515
+ const browserPath = wrapIdIfNeeded(acceptedPathWithoutQuery);
1434
1516
  const importPromise = import(
1435
1517
  /* @vite-ignore */
1436
- base + acceptedPathWithoutQuery.slice(1) + `?${explicitImportRequired ? "import&" : ""}t=${timestamp}${query ? `&${query}` : ""}`
1518
+ base + browserPath.slice(1) + `?${explicitImportRequired ? "import&" : ""}t=${timestamp}${query ? `&${query}` : ""}`
1437
1519
  );
1438
1520
  if (isWithinCircularImport) importPromise.catch(() => {
1439
1521
  console.info(`[hmr] ${acceptedPath} failed to apply HMR as it's within a circular import. Reloading page to reset the execution order. To debug and break the circular import, you can run \`vite --debug hmr\` to log the circular dependency path if a file change triggered it.`);
@@ -1509,12 +1591,14 @@ async function handleMessage(payload) {
1509
1591
  case "full-reload":
1510
1592
  if (payload.ifFallback && !globalThis.__vite_is_fallback_page__) break;
1511
1593
  await activeHmrClient.notifyListeners("vite:beforeFullReload", payload);
1512
- if (hasDocument) if (payload.path && payload.path.endsWith(".html")) {
1513
- const pagePath = decodeURI(location.pathname);
1514
- const payloadPath = base + payload.path.slice(1);
1515
- if (pagePath === payloadPath || payload.path === "/index.html" || pagePath.endsWith("/") && pagePath + "index.html" === payloadPath) pageReload();
1516
- return;
1517
- } else pageReload();
1594
+ if (hasDocument) {
1595
+ if (payload.path && payload.path.endsWith(".html")) {
1596
+ const pagePath = decodeURI(location.pathname);
1597
+ const payloadPath = base + payload.path.slice(1);
1598
+ if (pagePath === payloadPath || payload.path === "/index.html" || pagePath.endsWith("/") && pagePath + "index.html" === payloadPath) pageReload();
1599
+ return;
1600
+ } else pageReload();
1601
+ }
1518
1602
  break;
1519
1603
  case "prune":
1520
1604
  await activeHmrClient.notifyListeners("vite:beforePrune", payload);