[Pkg-javascript-commits] [pdf.js] 02/141: Doesn't traverse cyclic references in Dict.getAll; reduces empty-Dict garbage
David Prévot
taffit at moszumanska.debian.org
Sat Apr 19 22:40:24 UTC 2014
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository pdf.js.
commit 31f081ae173497af1c6a6fd6064703bc9e64c622
Author: Yury Delendik <ydelendik at mozilla.com>
Date: Wed Mar 26 09:07:38 2014 -0500
Doesn't traverse cyclic references in Dict.getAll; reduces empty-Dict garbage
---
src/core/core.js | 2 +-
src/core/evaluator.js | 26 ++++++++++------
src/core/obj.js | 75 ++++++++++++++++++++++++++++++++++++++++++++---
src/core/parser.js | 2 +-
src/core/stream.js | 2 +-
src/shared/annotation.js | 2 +-
src/shared/fonts_utils.js | 2 +-
7 files changed, 93 insertions(+), 18 deletions(-)
diff --git a/src/core/core.js b/src/core/core.js
index 8ac43c8..7138ce0 100644
--- a/src/core/core.js
+++ b/src/core/core.js
@@ -68,7 +68,7 @@ var Page = (function PageClosure() {
// present, but can be empty. Some document omit it still. In this case
// return an empty dictionary:
if (value === undefined) {
- value = new Dict();
+ value = Dict.empty;
}
return shadow(this, 'resources', value);
},
diff --git a/src/core/evaluator.js b/src/core/evaluator.js
index 84a618a..d8ce942 100644
--- a/src/core/evaluator.js
+++ b/src/core/evaluator.js
@@ -48,6 +48,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
return false;
}
+ var processed = Object.create(null);
+ if (resources.objId) {
+ processed[resources.objId] = true;
+ }
+
var nodes = [resources];
while (nodes.length) {
var node = nodes.shift();
@@ -75,10 +80,13 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
continue;
}
var xResources = xObject.dict.get('Resources');
- // Only add the resource if it's different from the current one,
- // otherwise we can get stuck in an infinite loop.
- if (isDict(xResources) && xResources !== node) {
+ // Checking objId to detect an infinite loop.
+ if (isDict(xResources) &&
+ (!xResources.objId || !processed[xResources.objId])) {
nodes.push(xResources);
+ if (xResources.objId) {
+ processed[xResources.objId] = true;
+ }
}
}
}
@@ -466,9 +474,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
operatorList = (operatorList || new OperatorList());
- resources = (resources || new Dict());
- var xobjs = (resources.get('XObject') || new Dict());
- var patterns = (resources.get('Pattern') || new Dict());
+ resources = (resources || Dict.empty);
+ var xobjs = (resources.get('XObject') || Dict.empty);
+ var patterns = (resources.get('Pattern') || Dict.empty);
var preprocessor = new EvaluatorPreprocessor(stream, xref);
if (evaluatorState) {
preprocessor.setState(evaluatorState);
@@ -659,7 +667,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
return self.loadFont(fontName, fontRef, xref, resources, null);
}
- resources = (xref.fetchIfRef(resources) || new Dict());
+ resources = (xref.fetchIfRef(resources) || Dict.empty);
// The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd.
var xobjs = null;
var xobjsCache = {};
@@ -753,7 +761,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
}
if (!xobjs) {
- xobjs = (resources.get('XObject') || new Dict());
+ xobjs = (resources.get('XObject') || Dict.empty);
}
var name = args[0].name;
@@ -1147,7 +1155,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
if (type.name == 'Type3') {
// FontDescriptor is only required for Type3 fonts when the document
// is a tagged pdf. Create a barbebones one to get by.
- descriptor = new Dict();
+ descriptor = new Dict(null);
descriptor.set('FontName', Name.get(type.name));
} else {
// Before PDF 1.5 if the font was one of the base 14 fonts, having a
diff --git a/src/core/obj.js b/src/core/obj.js
index f9f197b..ab4bb04 100644
--- a/src/core/obj.js
+++ b/src/core/obj.js
@@ -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,
diff --git a/src/core/parser.js b/src/core/parser.js
index aff4608..acdb46b 100644
--- a/src/core/parser.js
+++ b/src/core/parser.js
@@ -131,7 +131,7 @@ var Parser = (function ParserClosure() {
var stream = lexer.stream;
// parse dictionary
- var dict = new Dict();
+ var dict = new Dict(null);
while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {
if (!isName(this.buf1)) {
error('Dictionary key must be a name object');
diff --git a/src/core/stream.js b/src/core/stream.js
index 0776c43..b2580f9 100644
--- a/src/core/stream.js
+++ b/src/core/stream.js
@@ -1744,7 +1744,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
this.str = str;
this.dict = str.dict;
- params = params || new Dict();
+ params = params || Dict.empty;
this.encoding = params.get('K') || 0;
this.eoline = params.get('EndOfLine') || false;
diff --git a/src/shared/annotation.js b/src/shared/annotation.js
index 4d34edf..0f48f0f 100644
--- a/src/shared/annotation.js
+++ b/src/shared/annotation.js
@@ -378,7 +378,7 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() {
var fieldType = Util.getInheritableProperty(dict, 'FT');
data.fieldType = isName(fieldType) ? fieldType.name : '';
data.fieldFlags = Util.getInheritableProperty(dict, 'Ff') || 0;
- this.fieldResources = Util.getInheritableProperty(dict, 'DR') || new Dict();
+ this.fieldResources = Util.getInheritableProperty(dict, 'DR') || Dict.empty;
// Building the full field name by collecting the field and
// its ancestors 'T' data and joining them using '.'.
diff --git a/src/shared/fonts_utils.js b/src/shared/fonts_utils.js
index bc2659a..a14d921 100644
--- a/src/shared/fonts_utils.js
+++ b/src/shared/fonts_utils.js
@@ -249,7 +249,7 @@ function readFontIndexData(aStream, aIsByte) {
}
var Type2Parser = function type2Parser(aFilePath) {
- var font = new Dict();
+ var font = new Dict(null);
var xhr = new XMLHttpRequest();
xhr.open('GET', aFilePath, false);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/pdf.js.git
More information about the Pkg-javascript-commits
mailing list