|
|
|
@ -1616,32 +1616,32 @@ var FileSpec = (function FileSpecClosure() {
@@ -1616,32 +1616,32 @@ var FileSpec = (function FileSpecClosure() {
|
|
|
|
|
* missing data requests and then resume from the nodes that weren't ready. |
|
|
|
|
* |
|
|
|
|
* NOTE: It provides protection from circular references by keeping track of |
|
|
|
|
* of loaded references. However, you must be careful not to load any graphs |
|
|
|
|
* loaded references. However, you must be careful not to load any graphs |
|
|
|
|
* that have references to the catalog or other pages since that will cause the |
|
|
|
|
* entire PDF document object graph to be traversed. |
|
|
|
|
*/ |
|
|
|
|
var ObjectLoader = (function() { |
|
|
|
|
let ObjectLoader = (function() { |
|
|
|
|
function mayHaveChildren(value) { |
|
|
|
|
return isRef(value) || isDict(value) || isArray(value) || isStream(value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function addChildren(node, nodesToVisit) { |
|
|
|
|
var value; |
|
|
|
|
let value; |
|
|
|
|
if (isDict(node) || isStream(node)) { |
|
|
|
|
var map; |
|
|
|
|
let map; |
|
|
|
|
if (isDict(node)) { |
|
|
|
|
map = node.map; |
|
|
|
|
} else { |
|
|
|
|
map = node.dict.map; |
|
|
|
|
} |
|
|
|
|
for (var key in map) { |
|
|
|
|
for (let key in map) { |
|
|
|
|
value = map[key]; |
|
|
|
|
if (mayHaveChildren(value)) { |
|
|
|
|
nodesToVisit.push(value); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (isArray(node)) { |
|
|
|
|
for (var i = 0, ii = node.length; i < ii; i++) { |
|
|
|
|
for (let i = 0, ii = node.length; i < ii; i++) { |
|
|
|
|
value = node[i]; |
|
|
|
|
if (mayHaveChildren(value)) { |
|
|
|
|
nodesToVisit.push(value); |
|
|
|
@ -1659,8 +1659,7 @@ var ObjectLoader = (function() {
@@ -1659,8 +1659,7 @@ var ObjectLoader = (function() {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ObjectLoader.prototype = { |
|
|
|
|
load: function ObjectLoader_load() { |
|
|
|
|
var keys = this.keys; |
|
|
|
|
load() { |
|
|
|
|
this.capability = createPromiseCapability(); |
|
|
|
|
// Don't walk the graph if all the data is already loaded.
|
|
|
|
|
if (!(this.xref.stream instanceof ChunkedStream) || |
|
|
|
@ -1669,10 +1668,11 @@ var ObjectLoader = (function() {
@@ -1669,10 +1668,11 @@ var ObjectLoader = (function() {
|
|
|
|
|
return this.capability.promise; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let keys = this.keys; |
|
|
|
|
this.refSet = new RefSet(); |
|
|
|
|
// Setup the initial nodes to visit.
|
|
|
|
|
var nodesToVisit = []; |
|
|
|
|
for (var i = 0; i < keys.length; i++) { |
|
|
|
|
let nodesToVisit = []; |
|
|
|
|
for (let i = 0, ii = keys.length; i < ii; i++) { |
|
|
|
|
nodesToVisit.push(this.obj[keys[i]]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1680,12 +1680,12 @@ var ObjectLoader = (function() {
@@ -1680,12 +1680,12 @@ var ObjectLoader = (function() {
|
|
|
|
|
return this.capability.promise; |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
_walk: function ObjectLoader_walk(nodesToVisit) { |
|
|
|
|
var nodesToRevisit = []; |
|
|
|
|
var pendingRequests = []; |
|
|
|
|
_walk(nodesToVisit) { |
|
|
|
|
let nodesToRevisit = []; |
|
|
|
|
let pendingRequests = []; |
|
|
|
|
// DFS walk of the object graph.
|
|
|
|
|
while (nodesToVisit.length) { |
|
|
|
|
var currentNode = nodesToVisit.pop(); |
|
|
|
|
let currentNode = nodesToVisit.pop(); |
|
|
|
|
|
|
|
|
|
// Only references or chunked streams can cause missing data exceptions.
|
|
|
|
|
if (isRef(currentNode)) { |
|
|
|
@ -1694,28 +1694,24 @@ var ObjectLoader = (function() {
@@ -1694,28 +1694,24 @@ var ObjectLoader = (function() {
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
try { |
|
|
|
|
var ref = currentNode; |
|
|
|
|
this.refSet.put(ref); |
|
|
|
|
this.refSet.put(currentNode); |
|
|
|
|
currentNode = this.xref.fetch(currentNode); |
|
|
|
|
} catch (e) { |
|
|
|
|
if (!(e instanceof MissingDataException)) { |
|
|
|
|
throw e; |
|
|
|
|
} catch (ex) { |
|
|
|
|
if (!(ex instanceof MissingDataException)) { |
|
|
|
|
throw ex; |
|
|
|
|
} |
|
|
|
|
nodesToRevisit.push(currentNode); |
|
|
|
|
pendingRequests.push({ begin: e.begin, end: e.end, }); |
|
|
|
|
pendingRequests.push({ begin: ex.begin, end: ex.end, }); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (currentNode && currentNode.getBaseStreams) { |
|
|
|
|
var baseStreams = currentNode.getBaseStreams(); |
|
|
|
|
var foundMissingData = false; |
|
|
|
|
for (var i = 0; i < baseStreams.length; i++) { |
|
|
|
|
var stream = baseStreams[i]; |
|
|
|
|
let baseStreams = currentNode.getBaseStreams(); |
|
|
|
|
let foundMissingData = false; |
|
|
|
|
for (let i = 0, ii = baseStreams.length; i < ii; i++) { |
|
|
|
|
let stream = baseStreams[i]; |
|
|
|
|
if (stream.getMissingChunks && stream.getMissingChunks().length) { |
|
|
|
|
foundMissingData = true; |
|
|
|
|
pendingRequests.push({ |
|
|
|
|
begin: stream.start, |
|
|
|
|
end: stream.end, |
|
|
|
|
}); |
|
|
|
|
pendingRequests.push({ begin: stream.start, end: stream.end, }); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (foundMissingData) { |
|
|
|
@ -1728,16 +1724,15 @@ var ObjectLoader = (function() {
@@ -1728,16 +1724,15 @@ var ObjectLoader = (function() {
|
|
|
|
|
|
|
|
|
|
if (pendingRequests.length) { |
|
|
|
|
this.xref.stream.manager.requestRanges(pendingRequests).then(() => { |
|
|
|
|
nodesToVisit = nodesToRevisit; |
|
|
|
|
for (var i = 0; i < nodesToRevisit.length; i++) { |
|
|
|
|
var node = nodesToRevisit[i]; |
|
|
|
|
// Remove any reference nodes from the currrent refset so they
|
|
|
|
|
for (let i = 0, ii = nodesToRevisit.length; i < ii; i++) { |
|
|
|
|
let node = nodesToRevisit[i]; |
|
|
|
|
// Remove any reference nodes from the current `RefSet` so they
|
|
|
|
|
// aren't skipped when we revist them.
|
|
|
|
|
if (isRef(node)) { |
|
|
|
|
this.refSet.remove(node); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
this._walk(nodesToVisit); |
|
|
|
|
this._walk(nodesToRevisit); |
|
|
|
|
}, this.capability.reject); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|