From d8924c62303928b54cffc290f84423b23a468976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Roma=C5=84czyk?= Date: Fri, 2 Aug 2024 15:47:35 +0200 Subject: [PATCH] fix: infinite loop when traversing the chunk graph in `OutputPlugin` (#679) * fix: ifinite recursion in output plugin * chore: add changeset * refactor: typings --- .changeset/fast-cats-think.md | 5 +++++ .../repack/src/webpack/plugins/OutputPlugin.ts | 16 ++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 .changeset/fast-cats-think.md diff --git a/.changeset/fast-cats-think.md b/.changeset/fast-cats-think.md new file mode 100644 index 000000000..d4f03c283 --- /dev/null +++ b/.changeset/fast-cats-think.md @@ -0,0 +1,5 @@ +--- +"@callstack/repack": patch +--- + +fix infinite loop when traversing the chunk graph in OutputPlugin diff --git a/packages/repack/src/webpack/plugins/OutputPlugin.ts b/packages/repack/src/webpack/plugins/OutputPlugin.ts index 3eb697197..dfdf37bcd 100644 --- a/packages/repack/src/webpack/plugins/OutputPlugin.ts +++ b/packages/repack/src/webpack/plugins/OutputPlugin.ts @@ -4,6 +4,7 @@ import { Rule, WebpackPlugin } from '../../types'; import { AssetsCopyProcessor } from './utils/AssetsCopyProcessor'; import { AuxiliaryAssetsCopyProcessor } from './utils/AuxiliaryAssetsCopyProcessor'; +type ChunkId = Exclude; /** * Matching options to check if given {@link DestinationConfig} should be used. */ @@ -227,19 +228,22 @@ export class OutputPlugin implements WebpackPlugin { const getAllInitialChunks = ( chunk: webpack.StatsChunk, - chunks: Map + chunks: Map, + visited = new Set() ): Array => { - if (!chunk.parents?.length) { - return [chunk]; + // Prevent cycles when traversing chunks graph + if (visited.has(chunk.id!)) { + return []; } + visited.add(chunk.id!); - // Chunk might reference itself as a parent (and/or child) - if (chunk.parents.length === 1 && chunk.parents[0] === chunk.id) { + // If chunk has no parents, it's an initial chunk + if (!chunk.parents?.length) { return [chunk]; } return chunk.parents.flatMap((parent) => { - return getAllInitialChunks(chunks.get(parent)!, chunks); + return getAllInitialChunks(chunks.get(parent)!, chunks, visited); }); };