1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-25 17:48:07 +02:00

Doesn't traverse cyclic references in Dict.getAll; reduces empty-Dict garbage

This commit is contained in:
Yury Delendik 2014-03-26 09:07:38 -05:00
parent 9a36184dfa
commit 31f081ae17
7 changed files with 93 additions and 18 deletions

View file

@ -62,11 +62,30 @@ var Dict = (function DictClosure() {
return nonSerializable; // creating closure on some variable
};
var GETALL_DICTIONARY_TYPES_WHITELIST = {
'Background': true,
'ExtGState': true,
'Halftone': true,
'Layout': true,
'Mask': true,
'Pagination': true,
'Printing': true
};
function isRecursionAllowedFor(dict) {
if (!isName(dict.Type)) {
return true;
}
var dictType = dict.Type.name;
return GETALL_DICTIONARY_TYPES_WHITELIST[dictType] === true;
}
// xref is optional
function Dict(xref) {
// Map should only be used internally, use functions below to access.
this.map = Object.create(null);
this.xref = xref;
this.objId = null;
this.__nonSerializable__ = nonSerializable; // disable cloning of the Dict
}
@ -130,10 +149,51 @@ var Dict = (function DictClosure() {
// creates new map and dereferences all Refs
getAll: function Dict_getAll() {
var all = {};
var all = Object.create(null);
var queue = null;
for (var key in this.map) {
var obj = this.get(key);
all[key] = (obj instanceof Dict ? obj.getAll() : obj);
if (obj instanceof Dict) {
if (isRecursionAllowedFor(obj)) {
(queue || (queue = [])).push({target: all, key: key, obj: obj});
} else {
all[key] = this.getRaw(key);
}
} else {
all[key] = obj;
}
}
if (!queue) {
return all;
}
// trying to take cyclic references into the account
var processed = Object.create(null);
while (queue.length > 0) {
var item = queue.shift();
var itemObj = item.obj;
var objId = itemObj.objId;
if (objId && objId in processed) {
item.target[item.key] = processed[objId];
continue;
}
var dereferenced = Object.create(null);
for (var key in itemObj.map) {
var obj = itemObj.get(key);
if (obj instanceof Dict) {
if (isRecursionAllowedFor(obj)) {
queue.push({target: dereferenced, key: key, obj: obj});
} else {
dereferenced[key] = itemObj.getRaw(key);
}
} else {
dereferenced[key] = obj;
}
}
if (objId) {
processed[objId] = dereferenced;
}
item.target[item.key] = dereferenced;
}
return all;
},
@ -153,6 +213,8 @@ var Dict = (function DictClosure() {
}
};
Dict.empty = new Dict(null);
return Dict;
})();
@ -1061,10 +1123,15 @@ var XRef = (function XRefClosure() {
}
if (xrefEntry.uncompressed) {
return this.fetchUncompressed(ref, xrefEntry, suppressEncryption);
xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption);
} else {
return this.fetchCompressed(xrefEntry, suppressEncryption);
xrefEntry = this.fetchCompressed(xrefEntry, suppressEncryption);
}
if (isDict(xrefEntry)) {
xrefEntry.objId = 'R' + ref.num + '.' + ref.gen;
}
return xrefEntry;
},
fetchUncompressed: function XRef_fetchUncompressed(ref, xrefEntry,