Skip to content

Commit

Permalink
XFA - Handle correctly subformSet
Browse files Browse the repository at this point in the history
  - it aims to avoid to loop forever when opening pdf in mozilla#13213;
  - the idea is to consider subformSet as inexistent when running in the tree. So if we've subformA > subformSet > subformB then subformB will be visited as a direct child of subformA.
  • Loading branch information
calixteman authored and bh213 committed Jun 3, 2022
1 parent 6643042 commit ac0d913
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 21 deletions.
3 changes: 2 additions & 1 deletion src/core/xfa/html_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import {
$extra,
$getParent,
$getSubformParent,
$nodeName,
$toStyle,
XFAObject,
Expand Down Expand Up @@ -296,7 +297,7 @@ function computeBbox(node, html, availableSpace) {
}

function fixDimensions(node) {
const parent = node[$getParent]();
const parent = node[$getSubformParent]();
if (parent.layout && parent.layout.includes("row")) {
const extra = parent[$extra];
const colSpan = node.colSpan;
Expand Down
57 changes: 38 additions & 19 deletions src/core/xfa/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ import {
$flushHTML,
$getAvailableSpace,
$getChildren,
$getContainedChildren,
$getNextPage,
$getParent,
$getSubformParent,
$hasItem,
$hasSettableValue,
$ids,
Expand Down Expand Up @@ -106,6 +108,16 @@ function getRoot(node) {
return parent;
}

function* getContainedChildren(node) {
for (const child of node[$getChildren]()) {
if (child instanceof SubformSet) {
yield* child[$getContainedChildren]();
continue;
}
yield child;
}
}

function valueToHtml(value) {
return HTMLResult.success({
name: "span",
Expand Down Expand Up @@ -338,6 +350,12 @@ class Area extends XFAObject {
this.subformSet = new XFAObjectArray();
}

*[$getContainedChildren]() {
// This function is overriden in order to fake that subforms under
// this set are in fact under parent subform.
yield* getContainedChildren(this);
}

[$isTransparent]() {
return true;
}
Expand Down Expand Up @@ -4079,6 +4097,12 @@ class Subform extends XFAObject {
this.subformSet = new XFAObjectArray();
}

*[$getContainedChildren]() {
// This function is overriden in order to fake that subforms under
// this set are in fact under parent subform.
yield* getContainedChildren(this);
}

[$flushHTML]() {
return flushHTML(this);
}
Expand Down Expand Up @@ -4163,7 +4187,7 @@ class Subform extends XFAObject {
]);

if (this.layout.includes("row")) {
const columnWidths = this[$getParent]().columnWidths;
const columnWidths = this[$getSubformParent]().columnWidths;
if (Array.isArray(columnWidths) && columnWidths.length > 0) {
this[$extra].columnWidths = columnWidths;
this[$extra].currentColumn = 0;
Expand Down Expand Up @@ -4294,27 +4318,22 @@ class SubformSet extends XFAObject {
this.breakBefore = new XFAObjectArray();
this.subform = new XFAObjectArray();
this.subformSet = new XFAObjectArray();
}

[$toHTML]() {
const children = [];
if (!this[$extra]) {
this[$extra] = Object.create(null);
}
this[$extra].children = children;
// TODO: need to handle break stuff and relation.
}

this[$childrenToHTML]({
filter: new Set(["subform", "subformSet"]),
include: true,
});
*[$getContainedChildren]() {
// This function is overriden in order to fake that subforms under
// this set are in fact under parent subform.
yield* getContainedChildren(this);
}

return HTMLResult.success({
name: "div",
children,
attributes: {
id: this[$uid],
},
});
[$getSubformParent]() {
let parent = this[$getParent]();
while (!(parent instanceof Subform)) {
parent = parent[$getParent]();
}
return parent;
}
}

Expand Down
17 changes: 16 additions & 1 deletion src/core/xfa/xfa_object.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ const $getChildrenByNameIt = Symbol();
const $getDataValue = Symbol();
const $getRealChildrenByNameIt = Symbol();
const $getChildren = Symbol();
const $getContainedChildren = Symbol();
const $getNextPage = Symbol();
const $getSubformParent = Symbol();
const $getParent = Symbol();
const $global = Symbol();
const $hasItem = Symbol();
Expand Down Expand Up @@ -255,6 +257,10 @@ class XFAObject {
return this[_parent];
}

[$getSubformParent]() {
return this[$getParent]();
}

[$getChildren](name = null) {
if (!name) {
return this[_children];
Expand Down Expand Up @@ -296,8 +302,15 @@ class XFAObject {
return HTMLResult.EMPTY;
}

*[_filteredChildrenGenerator](filter, include) {
*[$getContainedChildren]() {
// This function is overriden in Subform and SubformSet.
for (const node of this[$getChildren]()) {
yield node;
}
}

*[_filteredChildrenGenerator](filter, include) {
for (const node of this[$getContainedChildren]()) {
if (!filter || include === filter.has(node[$nodeName])) {
const availableSpace = this[$getAvailableSpace]();
const res = node[$toHTML](availableSpace);
Expand Down Expand Up @@ -965,10 +978,12 @@ export {
$getChildrenByClass,
$getChildrenByName,
$getChildrenByNameIt,
$getContainedChildren,
$getDataValue,
$getNextPage,
$getParent,
$getRealChildrenByNameIt,
$getSubformParent,
$global,
$hasItem,
$hasSettableValue,
Expand Down
1 change: 1 addition & 0 deletions test/pdfs/xfa_issue13213.pdf.link
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://github.com/mozilla/pdf.js/files/6290046/cerfa_12156-05.pdf
8 changes: 8 additions & 0 deletions test/test_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,14 @@
"enableXfa": true,
"type": "eq"
},
{ "id": "xfa_issue13213",
"file": "pdfs/xfa_issue13213.pdf",
"md5": "8a0e3179bffbac721589d1b1df863b49",
"link": true,
"rounds": 1,
"enableXfa": true,
"type": "eq"
},
{ "id": "issue10272",
"file": "pdfs/issue10272.pdf",
"md5": "bf3b2f74c6878d38a70dc0825f1b9a02",
Expand Down

0 comments on commit ac0d913

Please sign in to comment.