XFA - Handle correctly subformSet
- it aims to avoid to loop forever when opening pdf in #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.
This commit is contained in:
parent
7b4fa0a038
commit
d1e945998b
@ -16,6 +16,7 @@
|
|||||||
import {
|
import {
|
||||||
$extra,
|
$extra,
|
||||||
$getParent,
|
$getParent,
|
||||||
|
$getSubformParent,
|
||||||
$nodeName,
|
$nodeName,
|
||||||
$toStyle,
|
$toStyle,
|
||||||
XFAObject,
|
XFAObject,
|
||||||
@ -296,7 +297,7 @@ function computeBbox(node, html, availableSpace) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fixDimensions(node) {
|
function fixDimensions(node) {
|
||||||
const parent = node[$getParent]();
|
const parent = node[$getSubformParent]();
|
||||||
if (parent.layout && parent.layout.includes("row")) {
|
if (parent.layout && parent.layout.includes("row")) {
|
||||||
const extra = parent[$extra];
|
const extra = parent[$extra];
|
||||||
const colSpan = node.colSpan;
|
const colSpan = node.colSpan;
|
||||||
|
@ -25,8 +25,10 @@ import {
|
|||||||
$flushHTML,
|
$flushHTML,
|
||||||
$getAvailableSpace,
|
$getAvailableSpace,
|
||||||
$getChildren,
|
$getChildren,
|
||||||
|
$getContainedChildren,
|
||||||
$getNextPage,
|
$getNextPage,
|
||||||
$getParent,
|
$getParent,
|
||||||
|
$getSubformParent,
|
||||||
$hasItem,
|
$hasItem,
|
||||||
$hasSettableValue,
|
$hasSettableValue,
|
||||||
$ids,
|
$ids,
|
||||||
@ -106,6 +108,16 @@ function getRoot(node) {
|
|||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function* getContainedChildren(node) {
|
||||||
|
for (const child of node[$getChildren]()) {
|
||||||
|
if (child instanceof SubformSet) {
|
||||||
|
yield* child[$getContainedChildren]();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
yield child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function valueToHtml(value) {
|
function valueToHtml(value) {
|
||||||
return HTMLResult.success({
|
return HTMLResult.success({
|
||||||
name: "span",
|
name: "span",
|
||||||
@ -338,6 +350,12 @@ class Area extends XFAObject {
|
|||||||
this.subformSet = new XFAObjectArray();
|
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]() {
|
[$isTransparent]() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -4077,6 +4095,12 @@ class Subform extends XFAObject {
|
|||||||
this.subformSet = new XFAObjectArray();
|
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]() {
|
[$flushHTML]() {
|
||||||
return flushHTML(this);
|
return flushHTML(this);
|
||||||
}
|
}
|
||||||
@ -4161,7 +4185,7 @@ class Subform extends XFAObject {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
if (this.layout.includes("row")) {
|
if (this.layout.includes("row")) {
|
||||||
const columnWidths = this[$getParent]().columnWidths;
|
const columnWidths = this[$getSubformParent]().columnWidths;
|
||||||
if (Array.isArray(columnWidths) && columnWidths.length > 0) {
|
if (Array.isArray(columnWidths) && columnWidths.length > 0) {
|
||||||
this[$extra].columnWidths = columnWidths;
|
this[$extra].columnWidths = columnWidths;
|
||||||
this[$extra].currentColumn = 0;
|
this[$extra].currentColumn = 0;
|
||||||
@ -4292,27 +4316,22 @@ class SubformSet extends XFAObject {
|
|||||||
this.breakBefore = new XFAObjectArray();
|
this.breakBefore = new XFAObjectArray();
|
||||||
this.subform = new XFAObjectArray();
|
this.subform = new XFAObjectArray();
|
||||||
this.subformSet = new XFAObjectArray();
|
this.subformSet = new XFAObjectArray();
|
||||||
|
|
||||||
|
// TODO: need to handle break stuff and relation.
|
||||||
}
|
}
|
||||||
|
|
||||||
[$toHTML]() {
|
*[$getContainedChildren]() {
|
||||||
const children = [];
|
// This function is overriden in order to fake that subforms under
|
||||||
if (!this[$extra]) {
|
// this set are in fact under parent subform.
|
||||||
this[$extra] = Object.create(null);
|
yield* getContainedChildren(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
[$getSubformParent]() {
|
||||||
|
let parent = this[$getParent]();
|
||||||
|
while (!(parent instanceof Subform)) {
|
||||||
|
parent = parent[$getParent]();
|
||||||
}
|
}
|
||||||
this[$extra].children = children;
|
return parent;
|
||||||
|
|
||||||
this[$childrenToHTML]({
|
|
||||||
filter: new Set(["subform", "subformSet"]),
|
|
||||||
include: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
return HTMLResult.success({
|
|
||||||
name: "div",
|
|
||||||
children,
|
|
||||||
attributes: {
|
|
||||||
id: this[$uid],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,9 @@ const $getChildrenByNameIt = Symbol();
|
|||||||
const $getDataValue = Symbol();
|
const $getDataValue = Symbol();
|
||||||
const $getRealChildrenByNameIt = Symbol();
|
const $getRealChildrenByNameIt = Symbol();
|
||||||
const $getChildren = Symbol();
|
const $getChildren = Symbol();
|
||||||
|
const $getContainedChildren = Symbol();
|
||||||
const $getNextPage = Symbol();
|
const $getNextPage = Symbol();
|
||||||
|
const $getSubformParent = Symbol();
|
||||||
const $getParent = Symbol();
|
const $getParent = Symbol();
|
||||||
const $global = Symbol();
|
const $global = Symbol();
|
||||||
const $hasItem = Symbol();
|
const $hasItem = Symbol();
|
||||||
@ -255,6 +257,10 @@ class XFAObject {
|
|||||||
return this[_parent];
|
return this[_parent];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[$getSubformParent]() {
|
||||||
|
return this[$getParent]();
|
||||||
|
}
|
||||||
|
|
||||||
[$getChildren](name = null) {
|
[$getChildren](name = null) {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
return this[_children];
|
return this[_children];
|
||||||
@ -296,8 +302,15 @@ class XFAObject {
|
|||||||
return HTMLResult.EMPTY;
|
return HTMLResult.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
*[_filteredChildrenGenerator](filter, include) {
|
*[$getContainedChildren]() {
|
||||||
|
// This function is overriden in Subform and SubformSet.
|
||||||
for (const node of this[$getChildren]()) {
|
for (const node of this[$getChildren]()) {
|
||||||
|
yield node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*[_filteredChildrenGenerator](filter, include) {
|
||||||
|
for (const node of this[$getContainedChildren]()) {
|
||||||
if (!filter || include === filter.has(node[$nodeName])) {
|
if (!filter || include === filter.has(node[$nodeName])) {
|
||||||
const availableSpace = this[$getAvailableSpace]();
|
const availableSpace = this[$getAvailableSpace]();
|
||||||
const res = node[$toHTML](availableSpace);
|
const res = node[$toHTML](availableSpace);
|
||||||
@ -965,10 +978,12 @@ export {
|
|||||||
$getChildrenByClass,
|
$getChildrenByClass,
|
||||||
$getChildrenByName,
|
$getChildrenByName,
|
||||||
$getChildrenByNameIt,
|
$getChildrenByNameIt,
|
||||||
|
$getContainedChildren,
|
||||||
$getDataValue,
|
$getDataValue,
|
||||||
$getNextPage,
|
$getNextPage,
|
||||||
$getParent,
|
$getParent,
|
||||||
$getRealChildrenByNameIt,
|
$getRealChildrenByNameIt,
|
||||||
|
$getSubformParent,
|
||||||
$global,
|
$global,
|
||||||
$hasItem,
|
$hasItem,
|
||||||
$hasSettableValue,
|
$hasSettableValue,
|
||||||
|
1
test/pdfs/xfa_issue13213.pdf.link
Normal file
1
test/pdfs/xfa_issue13213.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://github.com/mozilla/pdf.js/files/6290046/cerfa_12156-05.pdf
|
@ -938,6 +938,14 @@
|
|||||||
"enableXfa": true,
|
"enableXfa": true,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "xfa_issue13213",
|
||||||
|
"file": "pdfs/xfa_issue13213.pdf",
|
||||||
|
"md5": "8a0e3179bffbac721589d1b1df863b49",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "issue10272",
|
{ "id": "issue10272",
|
||||||
"file": "pdfs/issue10272.pdf",
|
"file": "pdfs/issue10272.pdf",
|
||||||
"md5": "bf3b2f74c6878d38a70dc0825f1b9a02",
|
"md5": "bf3b2f74c6878d38a70dc0825f1b9a02",
|
||||||
|
Loading…
Reference in New Issue
Block a user