* Load and build the field tree from an AcroForm. * * This performs async resolution of all field references and widget references, * then returns a FieldTree that can be iterated synchronously. * * @param acroForm The AcroForm to load fields from * @param registry The object regis
(acroForm: FieldTreeSource, registry: ObjectRegistry)
| 64 | * @returns A fully-loaded FieldTree |
| 65 | */ |
| 66 | static load(acroForm: FieldTreeSource, registry: ObjectRegistry): FieldTree { |
| 67 | const dict = acroForm.getDict(); |
| 68 | const resolve = registry.resolve.bind(registry); |
| 69 | const fieldsArray = dict.getArray("Fields", resolve); |
| 70 | |
| 71 | if (!fieldsArray) { |
| 72 | return new FieldTree([]); |
| 73 | } |
| 74 | |
| 75 | const visited = new Set<string>(); |
| 76 | const fields: FormField[] = []; |
| 77 | |
| 78 | // Process root fields breadth-first |
| 79 | const queue: Array<{ |
| 80 | item: unknown; |
| 81 | parentName: string; |
| 82 | parent: FormField | null; |
| 83 | }> = []; |
| 84 | |
| 85 | // Initialize queue with root fields |
| 86 | for (let i = 0; i < fieldsArray.length; i++) { |
| 87 | queue.push({ |
| 88 | item: fieldsArray.at(i), |
| 89 | parentName: "", |
| 90 | parent: null, |
| 91 | }); |
| 92 | } |
| 93 | |
| 94 | // Process queue breadth-first |
| 95 | while (queue.length > 0) { |
| 96 | const entry = queue.shift(); |
| 97 | |
| 98 | if (!entry) { |
| 99 | continue; |
| 100 | } |
| 101 | |
| 102 | const { parentName, parent } = entry; |
| 103 | let { item } = entry; |
| 104 | |
| 105 | const ref = item instanceof PdfRef ? item : null; |
| 106 | const refKey = ref ? `${ref.objectNumber}:${ref.generation}` : ""; |
| 107 | |
| 108 | // Cycle detection |
| 109 | if (refKey && visited.has(refKey)) { |
| 110 | registry.addWarning(`Circular reference in form field tree: ${refKey}`); |
| 111 | continue; |
| 112 | } |
| 113 | |
| 114 | if (refKey) { |
| 115 | visited.add(refKey); |
| 116 | } |
| 117 | |
| 118 | // Resolve field dictionary |
| 119 | let fieldDict: PdfDict | null = null; |
| 120 | |
| 121 | if (item instanceof PdfRef) { |
| 122 | item = registry.resolve(item) ?? undefined; |
| 123 | } |
nothing calls this directly
no test coverage detected