diff --git a/.changeset/early-moles-drum.md b/.changeset/early-moles-drum.md new file mode 100644 index 0000000000..57f19d6004 --- /dev/null +++ b/.changeset/early-moles-drum.md @@ -0,0 +1,5 @@ +--- +"@react-router/dev": patch +--- + +Fix `Maximum call stack size exceeded` errors when HMR is triggered against code with cyclic imports diff --git a/contributors.yml b/contributors.yml index c98ad34092..309efa1b0b 100644 --- a/contributors.yml +++ b/contributors.yml @@ -55,6 +55,7 @@ - bilalk711 - bjohn465 - black5box +- BlankParticle - bmsuseluda - bobziroll - bravo-kernel diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index 6a77987977..4d11d253af 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -2445,10 +2445,8 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { return; } - let clientModules = uniqueNodes( - modules.flatMap((mod) => - getParentClientNodes(server.environments.client.moduleGraph, mod), - ), + let clientModules = modules.flatMap((mod) => + getParentClientNodes(server.environments.client.moduleGraph, mod), ); for (let clientModule of clientModules) { @@ -2464,10 +2462,15 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { function getParentClientNodes( clientModuleGraph: Vite.EnvironmentModuleGraph, module: Vite.EnvironmentModuleNode, + seenNodes: Set = new Set(), ): Vite.EnvironmentModuleNode[] { if (!module.id) { return []; } + if (seenNodes.has(module.url)) { + return []; + } + seenNodes.add(module.url); let clientModule = clientModuleGraph.getModuleById(module.id); if (clientModule) { @@ -2475,25 +2478,10 @@ function getParentClientNodes( } return [...module.importers].flatMap((importer) => - getParentClientNodes(clientModuleGraph, importer), + getParentClientNodes(clientModuleGraph, importer, seenNodes), ); } -function uniqueNodes( - nodes: Vite.EnvironmentModuleNode[], -): Vite.EnvironmentModuleNode[] { - let nodeUrls = new Set(); - let unique: Vite.EnvironmentModuleNode[] = []; - for (let node of nodes) { - if (nodeUrls.has(node.url)) { - continue; - } - nodeUrls.add(node.url); - unique.push(node); - } - return unique; -} - function addRefreshWrapper( reactRouterConfig: ResolvedReactRouterConfig, code: string,