Fix performance regression in doc printer (#18342)

This commit is contained in:
fisker Cheung authored and GitHub committed 2025-11-27 19:24:17 +08:00
1 parent 1fe6a12557
commit d147f67ef1
2 files changed
+38 -22

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
#### Fix performance regression in doc printer (#18342 by @fisker)
Prettier main can be very slow when formatting big files, the regression has been fixed.
+35 -22
View File
@@ -187,13 +187,17 @@ function printDocToString(doc, options) {
// commands to the array instead of recursively calling `print`.
/** @type Command[] */
const commands = [{ indent: ROOT_INDENT, mode: MODE_BREAK, doc }];
/** @type string[] */
let out = [];
let output = "";
let shouldRemeasure = false;
/** @type Command[] */
const lineSuffix = [];
const cursorPositions = [];
/** @type string[] */
const settledOutput = [];
const settledCursorPositions = [];
let settledTextLength = 0;
propagateBreaks(doc);
while (commands.length > 0) {
@@ -204,7 +208,7 @@ function printDocToString(doc, options) {
newLine !== "\n" ? doc.replaceAll("\n", newLine) : doc;
// Plugins may print single string, should skip measure the width
if (formatted) {
out.push(formatted);
output += formatted;
if (commands.length > 0) {
position += getStringWidth(formatted);
}
@@ -218,15 +222,12 @@ function printDocToString(doc, options) {
}
break;
case DOC_TYPE_CURSOR: {
case DOC_TYPE_CURSOR:
if (cursorPositions.length >= 2) {
throw new Error("There are too many 'cursor' in doc.");
}
const text = out.join("");
out = [text];
cursorPositions.push(text.length - 1);
cursorPositions.push(settledTextLength + output.length);
break;
}
case DOC_TYPE_INDENT:
commands.push({
@@ -497,7 +498,7 @@ function printDocToString(doc, options) {
case MODE_FLAT:
if (!doc.hard) {
if (!doc.soft) {
out.push(" ");
output += " ";
position += 1;
}
@@ -522,17 +523,17 @@ function printDocToString(doc, options) {
}
if (doc.literal) {
out.push(newLine);
output += newLine;
position = 0;
if (indent.root) {
if (indent.root.value) {
out.push(indent.root.value);
output += indent.root.value;
}
position = indent.root.length;
}
} else {
trim();
out.push(newLine + indent.value);
output += newLine + indent.value;
position = indent.length;
}
break;
@@ -559,8 +560,10 @@ function printDocToString(doc, options) {
}
}
const formatted = out.join("");
if (cursorPositions.length !== 2) {
const formatted = settledOutput.join("") + output;
const finalCursorPositions = [...settledCursorPositions, ...cursorPositions];
if (finalCursorPositions.length !== 2) {
// If the doc contained ONE cursor command,
// instead of the expected zero or two. If the doc being printed was
// returned by printAstToDoc, then the only ways this can have happened
@@ -589,25 +592,35 @@ function printDocToString(doc, options) {
return { formatted };
}
const cursorNodeStart = cursorPositions[0] + 1;
const cursorNodeStart = finalCursorPositions[0];
return {
formatted,
cursorNodeStart,
cursorNodeText: formatted.slice(
cursorNodeStart,
cursorPositions.at(-1) + 1,
finalCursorPositions.at(-1),
),
};
function trim() {
const { text, count } = trimIndentation(out.join(""));
out = [text];
const { text: trimmed, count } = trimIndentation(output);
if (trimmed) {
settledOutput.push(trimmed);
settledTextLength += trimmed.length;
}
output = "";
position -= count;
for (let index = 0; index < cursorPositions.length; index++) {
cursorPositions[index] = Math.min(
cursorPositions[index],
text.length - 1,
if (cursorPositions.length > 0) {
settledCursorPositions.push(
...cursorPositions.map((position) =>
Math.min(position, settledTextLength),
),
);
cursorPositions.length = 0;
}
}
}