Skip to content

Commit 8542e57

Browse files
committed
fix(pdf-server): re-render after seeding storage from AcroForm tree
buildFieldNameMap runs AFTER the first renderPage (perf: don't block the canvas on an O(numPages) scan). When it detects a widget/field-tree mismatch and pushes the field-tree value into annotationStorage, the form layer has already rendered the stale widget value. Re-render once when that happens so the input shows the AcroForm truth.
1 parent c6a51a3 commit 8542e57

File tree

1 file changed

+14
-3
lines changed

1 file changed

+14
-3
lines changed

examples/pdf-server/src/mcp-app.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2827,7 +2827,8 @@ function normaliseFieldValue(
28272827
*/
28282828
async function buildFieldNameMap(
28292829
doc: pdfjsLib.PDFDocumentProxy,
2830-
): Promise<void> {
2830+
): Promise<boolean> {
2831+
let pushedToStorage = false;
28312832
fieldNameToIds.clear();
28322833
radioButtonValues.clear();
28332834
fieldNameToPage.clear();
@@ -2945,6 +2946,7 @@ async function buildFieldNameMap(
29452946
// widget. (syncFormValuesToStorage skips baseline==current.)
29462947
if (fieldTreeRaw != null && fieldTreeRaw !== widgetRaw) {
29472948
setFieldInStorage(name, v);
2949+
pushedToStorage = true;
29482950
}
29492951
}
29502952

@@ -2960,6 +2962,7 @@ async function buildFieldNameMap(
29602962
}
29612963

29622964
log.info(`Built field name map: ${fieldNameToIds.size} fields`);
2965+
return pushedToStorage;
29632966
}
29642967

29652968
/**
@@ -4434,8 +4437,9 @@ async function reloadPdf(): Promise<void> {
44344437
await renderPage();
44354438

44364439
await loadBaselineAnnotations(document);
4437-
await buildFieldNameMap(document);
4440+
const seeded = await buildFieldNameMap(document);
44384441
syncFormValuesToStorage();
4442+
if (seeded) await renderPage();
44394443
updateAnnotationsBadge();
44404444
renderAnnotationPanel();
44414445

@@ -4660,9 +4664,16 @@ app.ontoolresult = async (result: CallToolResult) => {
46604664
restoreAnnotations();
46614665

46624666
// Build field name → annotation ID mapping for form filling
4663-
await buildFieldNameMap(document);
4667+
const seeded = await buildFieldNameMap(document);
46644668
// Pre-populate annotationStorage from restored formFieldValues
46654669
syncFormValuesToStorage();
4670+
// buildFieldNameMap may have pushed AcroForm-tree values into storage
4671+
// (when the page widget's /V is stale vs the field dict — pdf-lib's save
4672+
// can leave them split). The first renderPage above ran BEFORE that, so
4673+
// the form layer shows the stale widget value. Re-render so it picks up
4674+
// storage. Only when something was actually seeded — most PDFs don't hit
4675+
// this and the extra render would be pure waste.
4676+
if (seeded) await renderPage();
46664677

46674678
updateAnnotationsBadge();
46684679
// Save button visibility driven by setDirty()/updateSaveBtn();

0 commit comments

Comments
 (0)