Skip to content

Commit 552d1e4

Browse files
committed
fix: dedupe extracted comments in linear time
The default comment-extraction path checked each preserved comment with Array.prototype.includes against a growing array, making deduplication O(n^2) in the number of distinct preserved comments. A crafted asset with many distinct comments could cause superlinear, CPU-bound build slowdown (GHSA-8cjx-vvr8-p635). Track membership with a Set for O(1) lookups while preserving output order. https://claude.ai/code/session_01XE82o4oLA4FdUP8r7yGd4r
1 parent 39fd982 commit 552d1e4

3 files changed

Lines changed: 15 additions & 3 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"minimizer-webpack-plugin": patch
3+
---
4+
5+
fix quadratic slowdown when deduplicating extracted comments (GHSA-8cjx-vvr8-p635); membership is now tracked with a `Set` so build time scales linearly with the number of distinct preserved comments

.cspell.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@
4646
"lightningcss",
4747
"sourcefile",
4848
"stringifier",
49-
"sourcesContent"
49+
"sourcesContent",
50+
"GHSA"
5051
],
5152
"ignorePaths": [
5253
"CHANGELOG.md",

src/utils.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ async function terserMinify(
223223

224224
// Redefine the comments function to extract and preserve
225225
// comments according to the two conditions
226+
const seenComments = new Set(extractedComments);
227+
226228
return (astNode, comment) => {
227229
if (
228230
/** @type {{ extract: ExtractCommentsFunction }} */
@@ -234,7 +236,8 @@ async function terserMinify(
234236
: `//${comment.value}`;
235237

236238
// Don't include duplicate comments
237-
if (!extractedComments.includes(commentText)) {
239+
if (!seenComments.has(commentText)) {
240+
seenComments.add(commentText);
238241
extractedComments.push(commentText);
239242
}
240243
}
@@ -477,6 +480,8 @@ async function uglifyJsMinify(
477480

478481
// Redefine the comments function to extract and preserve
479482
// comments according to the two conditions
483+
const seenComments = new Set(extractedComments);
484+
480485
return (astNode, comment) => {
481486
if (
482487
/** @type {{ extract: ExtractCommentsFunction }} */
@@ -488,7 +493,8 @@ async function uglifyJsMinify(
488493
: `//${comment.value}`;
489494

490495
// Don't include duplicate comments
491-
if (!extractedComments.includes(commentText)) {
496+
if (!seenComments.has(commentText)) {
497+
seenComments.add(commentText);
492498
extractedComments.push(commentText);
493499
}
494500
}

0 commit comments

Comments
 (0)