Adds destroy method to the document loading task.
Also renames PDFPageProxy.destroy method to cleanup.
This commit is contained in:
parent
ef85685803
commit
59c13b32aa
@ -662,8 +662,8 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
|
||||
// If we are in range request mode, this means we manually issued xhr
|
||||
// requests, which we need to abort when we leave the page
|
||||
domWindow.addEventListener('unload', function unload(e) {
|
||||
self.networkManager.abortAllRequests();
|
||||
domWindow.removeEventListener(e.type, unload);
|
||||
self.abortLoading();
|
||||
});
|
||||
}
|
||||
|
||||
@ -691,7 +691,7 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
|
||||
}, '*');
|
||||
};
|
||||
this.dataListener.oncomplete = function () {
|
||||
delete self.dataListener;
|
||||
self.dataListener = null;
|
||||
};
|
||||
}
|
||||
|
||||
@ -735,6 +735,15 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
|
||||
});
|
||||
};
|
||||
|
||||
proto.abortLoading = function RangedChromeActions_abortLoading() {
|
||||
this.networkManager.abortAllRequests();
|
||||
if (this.originalRequest) {
|
||||
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||
this.originalRequest = null;
|
||||
}
|
||||
this.dataListener = null;
|
||||
};
|
||||
|
||||
return RangedChromeActions;
|
||||
})();
|
||||
|
||||
@ -744,9 +753,10 @@ var StandardChromeActions = (function StandardChromeActionsClosure() {
|
||||
* This is for a single network stream
|
||||
*/
|
||||
function StandardChromeActions(domWindow, contentDispositionFilename,
|
||||
dataListener) {
|
||||
originalRequest, dataListener) {
|
||||
|
||||
ChromeActions.call(this, domWindow, contentDispositionFilename);
|
||||
this.originalRequest = originalRequest;
|
||||
this.dataListener = dataListener;
|
||||
}
|
||||
|
||||
@ -772,20 +782,29 @@ var StandardChromeActions = (function StandardChromeActionsClosure() {
|
||||
}, '*');
|
||||
};
|
||||
|
||||
this.dataListener.oncomplete = function ChromeActions_dataListenerComplete(
|
||||
data, errorCode) {
|
||||
this.dataListener.oncomplete =
|
||||
function StandardChromeActions_dataListenerComplete(data, errorCode) {
|
||||
self.domWindow.postMessage({
|
||||
pdfjsLoadAction: 'complete',
|
||||
data: data,
|
||||
errorCode: errorCode
|
||||
}, '*');
|
||||
|
||||
delete self.dataListener;
|
||||
self.dataListener = null;
|
||||
self.originalRequest = null;
|
||||
};
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
proto.abortLoading = function StandardChromeActions_abortLoading() {
|
||||
if (this.originalRequest) {
|
||||
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||
this.originalRequest = null;
|
||||
}
|
||||
this.dataListener = null;
|
||||
};
|
||||
|
||||
return StandardChromeActions;
|
||||
})();
|
||||
|
||||
@ -1029,7 +1048,7 @@ PdfStreamConverter.prototype = {
|
||||
rangeRequest, streamRequest, dataListener);
|
||||
} else {
|
||||
actions = new StandardChromeActions(
|
||||
domWindow, contentDispositionFilename, dataListener);
|
||||
domWindow, contentDispositionFilename, aRequest, dataListener);
|
||||
}
|
||||
var requestListener = new RequestListener(actions);
|
||||
domWindow.addEventListener(PDFJS_EVENT_ID, function(event) {
|
||||
|
@ -301,7 +301,7 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
|
||||
|
||||
this.chunksNeededByRequest = {};
|
||||
this.requestsByChunk = {};
|
||||
this.callbacksByRequest = {};
|
||||
this.promisesByRequest = {};
|
||||
this.progressiveDataLength = 0;
|
||||
|
||||
this._loadedStreamCapability = createPromiseCapability();
|
||||
@ -320,12 +320,11 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
|
||||
// contiguous ranges to load in as few requests as possible
|
||||
requestAllChunks: function ChunkedStreamManager_requestAllChunks() {
|
||||
var missingChunks = this.stream.getMissingChunks();
|
||||
this.requestChunks(missingChunks);
|
||||
this._requestChunks(missingChunks);
|
||||
return this._loadedStreamCapability.promise;
|
||||
},
|
||||
|
||||
requestChunks: function ChunkedStreamManager_requestChunks(chunks,
|
||||
callback) {
|
||||
_requestChunks: function ChunkedStreamManager_requestChunks(chunks) {
|
||||
var requestId = this.currRequestId++;
|
||||
|
||||
var chunksNeeded;
|
||||
@ -338,13 +337,11 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
|
||||
}
|
||||
|
||||
if (isEmptyObj(chunksNeeded)) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
return;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
this.callbacksByRequest[requestId] = callback;
|
||||
var capability = createPromiseCapability();
|
||||
this.promisesByRequest[requestId] = capability;
|
||||
|
||||
var chunksToRequest = [];
|
||||
for (var chunk in chunksNeeded) {
|
||||
@ -357,7 +354,7 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
|
||||
}
|
||||
|
||||
if (!chunksToRequest.length) {
|
||||
return;
|
||||
return capability.promise;
|
||||
}
|
||||
|
||||
var groupedChunksToRequest = this.groupChunks(chunksToRequest);
|
||||
@ -368,6 +365,8 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
|
||||
var end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length);
|
||||
this.sendRequest(begin, end);
|
||||
}
|
||||
|
||||
return capability.promise;
|
||||
},
|
||||
|
||||
getStream: function ChunkedStreamManager_getStream() {
|
||||
@ -375,8 +374,7 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
|
||||
},
|
||||
|
||||
// Loads any chunks in the requested range that are not yet loaded
|
||||
requestRange: function ChunkedStreamManager_requestRange(
|
||||
begin, end, callback) {
|
||||
requestRange: function ChunkedStreamManager_requestRange(begin, end) {
|
||||
|
||||
end = Math.min(end, this.length);
|
||||
|
||||
@ -388,11 +386,10 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
|
||||
chunks.push(chunk);
|
||||
}
|
||||
|
||||
this.requestChunks(chunks, callback);
|
||||
return this._requestChunks(chunks);
|
||||
},
|
||||
|
||||
requestRanges: function ChunkedStreamManager_requestRanges(ranges,
|
||||
callback) {
|
||||
requestRanges: function ChunkedStreamManager_requestRanges(ranges) {
|
||||
ranges = ranges || [];
|
||||
var chunksToRequest = [];
|
||||
|
||||
@ -407,7 +404,7 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
|
||||
}
|
||||
|
||||
chunksToRequest.sort(function(a, b) { return a - b; });
|
||||
this.requestChunks(chunksToRequest, callback);
|
||||
return this._requestChunks(chunksToRequest);
|
||||
},
|
||||
|
||||
// Groups a sorted array of chunks into as few contiguous larger
|
||||
@ -506,17 +503,15 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
|
||||
nextEmptyChunk = this.stream.nextEmptyChunk(endChunk);
|
||||
}
|
||||
if (isInt(nextEmptyChunk)) {
|
||||
this.requestChunks([nextEmptyChunk]);
|
||||
this._requestChunks([nextEmptyChunk]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < loadedRequests.length; ++i) {
|
||||
requestId = loadedRequests[i];
|
||||
var callback = this.callbacksByRequest[requestId];
|
||||
delete this.callbacksByRequest[requestId];
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
var capability = this.promisesByRequest[requestId];
|
||||
delete this.promisesByRequest[requestId];
|
||||
capability.resolve();
|
||||
}
|
||||
|
||||
this.msgHandler.send('DocProgress', {
|
||||
@ -537,6 +532,16 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
|
||||
getEndChunk: function ChunkedStreamManager_getEndChunk(end) {
|
||||
var chunk = Math.floor((end - 1) / this.chunkSize) + 1;
|
||||
return chunk;
|
||||
},
|
||||
|
||||
abort: function ChunkedStreamManager_abort() {
|
||||
if (this.networkManager) {
|
||||
this.networkManager.abortAllRequests();
|
||||
}
|
||||
for(var requestId in this.promisesByRequest) {
|
||||
var capability = this.promisesByRequest[requestId];
|
||||
capability.reject(new Error('Request was aborted'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1378,9 +1378,9 @@ var XRef = (function XRefClosure() {
|
||||
resolve(xref.fetch(ref, suppressEncryption));
|
||||
} catch (e) {
|
||||
if (e instanceof MissingDataException) {
|
||||
streamManager.requestRange(e.begin, e.end, function () {
|
||||
streamManager.requestRange(e.begin, e.end).then(function () {
|
||||
tryFetch(resolve, reject);
|
||||
});
|
||||
}, reject);
|
||||
return;
|
||||
}
|
||||
reject(e);
|
||||
@ -1656,6 +1656,7 @@ var ObjectLoader = (function() {
|
||||
this.keys = keys;
|
||||
this.xref = xref;
|
||||
this.refSet = null;
|
||||
this.capability = null;
|
||||
}
|
||||
|
||||
ObjectLoader.prototype = {
|
||||
@ -1676,11 +1677,11 @@ var ObjectLoader = (function() {
|
||||
nodesToVisit.push(this.obj[keys[i]]);
|
||||
}
|
||||
|
||||
this.walk(nodesToVisit);
|
||||
this._walk(nodesToVisit);
|
||||
return this.capability.promise;
|
||||
},
|
||||
|
||||
walk: function ObjectLoader_walk(nodesToVisit) {
|
||||
_walk: function ObjectLoader_walk(nodesToVisit) {
|
||||
var nodesToRevisit = [];
|
||||
var pendingRequests = [];
|
||||
// DFS walk of the object graph.
|
||||
@ -1727,7 +1728,7 @@ var ObjectLoader = (function() {
|
||||
}
|
||||
|
||||
if (pendingRequests.length) {
|
||||
this.xref.stream.manager.requestRanges(pendingRequests,
|
||||
this.xref.stream.manager.requestRanges(pendingRequests).then(
|
||||
function pendingRequestCallback() {
|
||||
nodesToVisit = nodesToRevisit;
|
||||
for (var i = 0; i < nodesToRevisit.length; i++) {
|
||||
@ -1738,8 +1739,8 @@ var ObjectLoader = (function() {
|
||||
this.refSet.remove(node);
|
||||
}
|
||||
}
|
||||
this.walk(nodesToVisit);
|
||||
}.bind(this));
|
||||
this._walk(nodesToVisit);
|
||||
}.bind(this), this.capability.reject);
|
||||
return;
|
||||
}
|
||||
// Everything is loaded.
|
||||
|
@ -183,7 +183,8 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
|
||||
reject(e);
|
||||
return;
|
||||
}
|
||||
pdfManager.streamManager.requestRange(e.begin, e.end, ensureHelper);
|
||||
pdfManager.streamManager.requestRange(e.begin, e.end).
|
||||
then(ensureHelper, reject);
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,11 +194,7 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
|
||||
|
||||
NetworkPdfManager.prototype.requestRange =
|
||||
function NetworkPdfManager_requestRange(begin, end) {
|
||||
return new Promise(function (resolve) {
|
||||
this.streamManager.requestRange(begin, end, function() {
|
||||
resolve();
|
||||
});
|
||||
}.bind(this));
|
||||
return this.streamManager.requestRange(begin, end);
|
||||
};
|
||||
|
||||
NetworkPdfManager.prototype.requestLoadedStream =
|
||||
@ -217,7 +214,7 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
|
||||
|
||||
NetworkPdfManager.prototype.terminate =
|
||||
function NetworkPdfManager_terminate() {
|
||||
this.streamManager.networkManager.abortAllRequests();
|
||||
this.streamManager.abort();
|
||||
};
|
||||
|
||||
return NetworkPdfManager;
|
||||
|
@ -25,6 +25,14 @@
|
||||
var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
setup: function wphSetup(handler) {
|
||||
var pdfManager;
|
||||
var terminated = false;
|
||||
var cancelXHRs = null;
|
||||
|
||||
function ensureNotTerminated() {
|
||||
if (terminated) {
|
||||
throw new Error('Worker was terminated');
|
||||
}
|
||||
}
|
||||
|
||||
function loadDocument(recoveryMode) {
|
||||
var loadDocumentCapability = createPromiseCapability();
|
||||
@ -61,13 +69,14 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
|
||||
function getPdfManager(data) {
|
||||
var pdfManagerCapability = createPromiseCapability();
|
||||
var pdfManager;
|
||||
|
||||
var source = data.source;
|
||||
var disableRange = data.disableRange;
|
||||
if (source.data) {
|
||||
try {
|
||||
pdfManager = new LocalPdfManager(source.data, source.password);
|
||||
pdfManagerCapability.resolve();
|
||||
pdfManagerCapability.resolve(pdfManager);
|
||||
} catch (ex) {
|
||||
pdfManagerCapability.reject(ex);
|
||||
}
|
||||
@ -75,7 +84,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
} else if (source.chunkedViewerLoading) {
|
||||
try {
|
||||
pdfManager = new NetworkPdfManager(source, handler);
|
||||
pdfManagerCapability.resolve();
|
||||
pdfManagerCapability.resolve(pdfManager);
|
||||
} catch (ex) {
|
||||
pdfManagerCapability.reject(ex);
|
||||
}
|
||||
@ -136,6 +145,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
} catch (ex) {
|
||||
pdfManagerCapability.reject(ex);
|
||||
}
|
||||
cancelXHRs = null;
|
||||
},
|
||||
|
||||
onProgressiveData: source.disableStream ? null :
|
||||
@ -176,10 +186,11 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
// the data is array, instantiating directly from it
|
||||
try {
|
||||
pdfManager = new LocalPdfManager(pdfFile, source.password);
|
||||
pdfManagerCapability.resolve();
|
||||
pdfManagerCapability.resolve(pdfManager);
|
||||
} catch (ex) {
|
||||
pdfManagerCapability.reject(ex);
|
||||
}
|
||||
cancelXHRs = null;
|
||||
},
|
||||
|
||||
onError: function onError(status) {
|
||||
@ -194,6 +205,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
') while retrieving PDF "' + source.url + '".', status);
|
||||
handler.send('UnexpectedResponse', exception);
|
||||
}
|
||||
cancelXHRs = null;
|
||||
},
|
||||
|
||||
onProgress: function onProgress(evt) {
|
||||
@ -204,6 +216,10 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
}
|
||||
});
|
||||
|
||||
cancelXHRs = function () {
|
||||
networkManager.abortRequest(fullRequestXhrId);
|
||||
};
|
||||
|
||||
return pdfManagerCapability.promise;
|
||||
}
|
||||
|
||||
@ -236,8 +252,8 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
});
|
||||
|
||||
handler.on('GetDocRequest', function wphSetupDoc(data) {
|
||||
|
||||
var onSuccess = function(doc) {
|
||||
ensureNotTerminated();
|
||||
handler.send('GetDoc', { pdfInfo: doc });
|
||||
};
|
||||
|
||||
@ -260,6 +276,8 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
}
|
||||
};
|
||||
|
||||
ensureNotTerminated();
|
||||
|
||||
PDFJS.maxImageSize = data.maxImageSize === undefined ?
|
||||
-1 : data.maxImageSize;
|
||||
PDFJS.disableFontFace = data.disableFontFace;
|
||||
@ -269,13 +287,26 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
null : data.cMapUrl;
|
||||
PDFJS.cMapPacked = data.cMapPacked === true;
|
||||
|
||||
getPdfManager(data).then(function () {
|
||||
getPdfManager(data).then(function (newPdfManager) {
|
||||
if (terminated) {
|
||||
// We were in a process of setting up the manager, but it got
|
||||
// terminated in the middle.
|
||||
newPdfManager.terminate();
|
||||
throw new Error('Worker was terminated');
|
||||
}
|
||||
|
||||
pdfManager = newPdfManager;
|
||||
|
||||
handler.send('PDFManagerReady', null);
|
||||
pdfManager.onLoadedStream().then(function(stream) {
|
||||
handler.send('DataLoaded', { length: stream.bytes.byteLength });
|
||||
});
|
||||
}).then(function pdfManagerReady() {
|
||||
ensureNotTerminated();
|
||||
|
||||
loadDocument(false).then(onSuccess, function loadFailure(ex) {
|
||||
ensureNotTerminated();
|
||||
|
||||
// Try again with recoveryMode == true
|
||||
if (!(ex instanceof XRefParseException)) {
|
||||
if (ex instanceof PasswordException) {
|
||||
@ -290,6 +321,8 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
|
||||
pdfManager.requestLoadedStream();
|
||||
pdfManager.onLoadedStream().then(function() {
|
||||
ensureNotTerminated();
|
||||
|
||||
loadDocument(true).then(onSuccess, onFailure);
|
||||
});
|
||||
}, onFailure);
|
||||
@ -441,7 +474,14 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
});
|
||||
|
||||
handler.on('Terminate', function wphTerminate(data) {
|
||||
pdfManager.terminate();
|
||||
terminated = true;
|
||||
if (pdfManager) {
|
||||
pdfManager.terminate();
|
||||
pdfManager = null;
|
||||
}
|
||||
if (cancelXHRs) {
|
||||
cancelXHRs();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -265,6 +265,9 @@ PDFJS.getDocument = function getDocument(src,
|
||||
pdfDataRangeTransport = Object.create(pdfDataRangeTransport);
|
||||
pdfDataRangeTransport.length = src.length;
|
||||
pdfDataRangeTransport.initialData = src.initialData;
|
||||
if (!pdfDataRangeTransport.abort) {
|
||||
pdfDataRangeTransport.abort = function () {};
|
||||
}
|
||||
}
|
||||
src = Object.create(src);
|
||||
src.range = pdfDataRangeTransport;
|
||||
@ -324,6 +327,7 @@ PDFJS.getDocument = function getDocument(src,
|
||||
workerInitializedCapability.promise.then(function transportInitialized() {
|
||||
transport.fetchDocument(task, params);
|
||||
});
|
||||
task._transport = transport;
|
||||
|
||||
return task;
|
||||
};
|
||||
@ -336,6 +340,7 @@ var PDFDocumentLoadingTask = (function PDFDocumentLoadingTaskClosure() {
|
||||
/** @constructs PDFDocumentLoadingTask */
|
||||
function PDFDocumentLoadingTask() {
|
||||
this._capability = createPromiseCapability();
|
||||
this._transport = null;
|
||||
|
||||
/**
|
||||
* Callback to request a password if wrong or no password was provided.
|
||||
@ -361,7 +366,14 @@ var PDFDocumentLoadingTask = (function PDFDocumentLoadingTaskClosure() {
|
||||
return this._capability.promise;
|
||||
},
|
||||
|
||||
// TODO add cancel or abort method
|
||||
/**
|
||||
* Aborts all network requests and destroys worker.
|
||||
* @return {Promise} A promise that is resolved after destruction activity
|
||||
* is completed.
|
||||
*/
|
||||
destroy: function () {
|
||||
return this._transport.destroy();
|
||||
},
|
||||
|
||||
/**
|
||||
* Registers callbacks to indicate the document loading completion.
|
||||
@ -448,6 +460,9 @@ var PDFDataRangeTransport = (function pdfDataRangeTransportClosure() {
|
||||
requestDataRange:
|
||||
function PDFDataRangeTransport_requestDataRange(begin, end) {
|
||||
throw new Error('Abstract method PDFDataRangeTransport.requestDataRange');
|
||||
},
|
||||
|
||||
abort: function PDFDataRangeTransport_abort() {
|
||||
}
|
||||
};
|
||||
return PDFDataRangeTransport;
|
||||
@ -461,9 +476,10 @@ PDFJS.PDFDataRangeTransport = PDFDataRangeTransport;
|
||||
* @class
|
||||
*/
|
||||
var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
|
||||
function PDFDocumentProxy(pdfInfo, transport) {
|
||||
function PDFDocumentProxy(pdfInfo, transport, loadingTask) {
|
||||
this.pdfInfo = pdfInfo;
|
||||
this.transport = transport;
|
||||
this.loadingTask = loadingTask;
|
||||
}
|
||||
PDFDocumentProxy.prototype = /** @lends PDFDocumentProxy.prototype */ {
|
||||
/**
|
||||
@ -586,7 +602,7 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
|
||||
* Destroys current document instance and terminates worker.
|
||||
*/
|
||||
destroy: function PDFDocumentProxy_destroy() {
|
||||
this.transport.destroy();
|
||||
return this.transport.destroy();
|
||||
}
|
||||
};
|
||||
return PDFDocumentProxy;
|
||||
@ -663,8 +679,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
this.commonObjs = transport.commonObjs;
|
||||
this.objs = new PDFObjects();
|
||||
this.cleanupAfterRender = false;
|
||||
this.pendingDestroy = false;
|
||||
this.pendingCleanup = false;
|
||||
this.intentStates = {};
|
||||
this.destroyed = false;
|
||||
}
|
||||
PDFPageProxy.prototype = /** @lends PDFPageProxy.prototype */ {
|
||||
/**
|
||||
@ -728,7 +745,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
|
||||
// If there was a pending destroy cancel it so no cleanup happens during
|
||||
// this call to render.
|
||||
this.pendingDestroy = false;
|
||||
this.pendingCleanup = false;
|
||||
|
||||
var renderingIntent = (params.intent === 'print' ? 'print' : 'display');
|
||||
|
||||
@ -775,7 +792,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
var self = this;
|
||||
intentState.displayReadyCapability.promise.then(
|
||||
function pageDisplayReadyPromise(transparency) {
|
||||
if (self.pendingDestroy) {
|
||||
if (self.pendingCleanup) {
|
||||
complete();
|
||||
return;
|
||||
}
|
||||
@ -795,9 +812,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
}
|
||||
|
||||
if (self.cleanupAfterRender) {
|
||||
self.pendingDestroy = true;
|
||||
self.pendingCleanup = true;
|
||||
}
|
||||
self._tryDestroy();
|
||||
self._tryCleanup();
|
||||
|
||||
if (error) {
|
||||
internalRenderTask.capability.reject(error);
|
||||
@ -858,20 +875,47 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
pageIndex: this.pageNumber - 1
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroys resources allocated by the page.
|
||||
* Destroys page object.
|
||||
*/
|
||||
destroy: function PDFPageProxy_destroy() {
|
||||
this.pendingDestroy = true;
|
||||
this._tryDestroy();
|
||||
_destroy: function PDFPageProxy_destroy() {
|
||||
this.destroyed = true;
|
||||
this.transport.pageCache[this.pageIndex] = null;
|
||||
|
||||
Object.keys(this.intentStates).forEach(function(intent) {
|
||||
var intentState = this.intentStates[intent];
|
||||
intentState.renderTasks.forEach(function(renderTask) {
|
||||
renderTask.cancel();
|
||||
});
|
||||
}, this);
|
||||
this.objs.clear();
|
||||
this.annotationsPromise = null;
|
||||
this.pendingCleanup = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Cleans up resources allocated by the page.
|
||||
* Deprecated, use cleanup() instead.
|
||||
*/
|
||||
destroy: function() {
|
||||
this.cleanup();
|
||||
},
|
||||
|
||||
/**
|
||||
* Cleans up resources allocated by the page.
|
||||
*/
|
||||
cleanup: function PDFPageProxy_cleanup() {
|
||||
this.pendingCleanup = true;
|
||||
this._tryCleanup();
|
||||
},
|
||||
/**
|
||||
* For internal use only. Attempts to clean up if rendering is in a state
|
||||
* where that's possible.
|
||||
* @ignore
|
||||
*/
|
||||
_tryDestroy: function PDFPageProxy__destroy() {
|
||||
if (!this.pendingDestroy ||
|
||||
_tryCleanup: function PDFPageProxy_tryCleanup() {
|
||||
if (!this.pendingCleanup ||
|
||||
Object.keys(this.intentStates).some(function(intent) {
|
||||
var intentState = this.intentStates[intent];
|
||||
return (intentState.renderTasks.length !== 0 ||
|
||||
@ -885,7 +929,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
}, this);
|
||||
this.objs.clear();
|
||||
this.annotationsPromise = null;
|
||||
this.pendingDestroy = false;
|
||||
this.pendingCleanup = false;
|
||||
},
|
||||
/**
|
||||
* For internal use only.
|
||||
@ -923,7 +967,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
|
||||
if (operatorListChunk.lastChunk) {
|
||||
intentState.receivingOperatorList = false;
|
||||
this._tryDestroy();
|
||||
this._tryCleanup();
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -941,6 +985,8 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
this.commonObjs = new PDFObjects();
|
||||
|
||||
this.loadingTask = null;
|
||||
this.destroyed = false;
|
||||
this.destroyCapability = null;
|
||||
|
||||
this.pageCache = [];
|
||||
this.pagePromises = [];
|
||||
@ -1001,6 +1047,18 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
}
|
||||
WorkerTransport.prototype = {
|
||||
destroy: function WorkerTransport_destroy() {
|
||||
if (this.destroyCapability) {
|
||||
return this.destroyCapability.promise;
|
||||
}
|
||||
|
||||
this.destroyed = true;
|
||||
this.destroyCapability = createPromiseCapability();
|
||||
|
||||
this.pageCache.forEach(function (page) {
|
||||
if (page) {
|
||||
page._destroy();
|
||||
}
|
||||
});
|
||||
this.pageCache = [];
|
||||
this.pagePromises = [];
|
||||
var self = this;
|
||||
@ -1009,7 +1067,14 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
if (self.worker) {
|
||||
self.worker.terminate();
|
||||
}
|
||||
});
|
||||
if (self.pdfDataRangeTransport) {
|
||||
self.pdfDataRangeTransport.abort();
|
||||
self.pdfDataRangeTransport = null;
|
||||
}
|
||||
self.messageHandler = null;
|
||||
self.destroyCapability.resolve();
|
||||
}, this.destroyCapability.reject);
|
||||
return this.destroyCapability.promise;
|
||||
},
|
||||
|
||||
setupFakeWorker: function WorkerTransport_setupFakeWorker() {
|
||||
@ -1091,9 +1156,10 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
messageHandler.on('GetDoc', function transportDoc(data) {
|
||||
var pdfInfo = data.pdfInfo;
|
||||
this.numPages = data.pdfInfo.numPages;
|
||||
var pdfDocument = new PDFDocumentProxy(pdfInfo, this);
|
||||
var loadingTask = this.loadingTask;
|
||||
var pdfDocument = new PDFDocumentProxy(pdfInfo, this, loadingTask);
|
||||
this.pdfDocument = pdfDocument;
|
||||
this.loadingTask._capability.resolve(pdfDocument);
|
||||
loadingTask._capability.resolve(pdfDocument);
|
||||
}, this);
|
||||
|
||||
messageHandler.on('NeedPassword',
|
||||
@ -1294,6 +1360,12 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
},
|
||||
|
||||
fetchDocument: function WorkerTransport_fetchDocument(loadingTask, source) {
|
||||
if (this.destroyed) {
|
||||
loadingTask._capability.reject(new Error('Loading aborted'));
|
||||
this.destroyCapability.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadingTask = loadingTask;
|
||||
|
||||
source.disableAutoFetch = PDFJS.disableAutoFetch;
|
||||
@ -1332,6 +1404,9 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
var promise = this.messageHandler.sendWithPromise('GetPage', {
|
||||
pageIndex: pageIndex
|
||||
}).then(function (pageInfo) {
|
||||
if (this.destroyed) {
|
||||
throw new Error('Transport destroyed');
|
||||
}
|
||||
var page = new PDFPageProxy(pageIndex, pageInfo, this);
|
||||
this.pageCache[pageIndex] = page;
|
||||
return page;
|
||||
@ -1389,7 +1464,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
for (var i = 0, ii = this.pageCache.length; i < ii; i++) {
|
||||
var page = this.pageCache[i];
|
||||
if (page) {
|
||||
page.destroy();
|
||||
page.cleanup();
|
||||
}
|
||||
}
|
||||
this.commonObjs.clear();
|
||||
|
@ -11,31 +11,31 @@ describe('api', function() {
|
||||
var basicApiUrl = combineUrl(window.location.href, '../pdfs/basicapi.pdf');
|
||||
var basicApiFileLength = 105779; // bytes
|
||||
function waitsForPromiseResolved(promise, successCallback) {
|
||||
var data;
|
||||
var resolved = false;
|
||||
promise.then(function(val) {
|
||||
data = val;
|
||||
successCallback(data);
|
||||
resolved = true;
|
||||
successCallback(val);
|
||||
},
|
||||
function(error) {
|
||||
// Shouldn't get here.
|
||||
expect(false).toEqual(true);
|
||||
});
|
||||
waitsFor(function() {
|
||||
return data !== undefined;
|
||||
return resolved;
|
||||
}, 20000);
|
||||
}
|
||||
function waitsForPromiseRejected(promise, failureCallback) {
|
||||
var data;
|
||||
var rejected = false;
|
||||
promise.then(function(val) {
|
||||
// Shouldn't get here.
|
||||
expect(false).toEqual(true);
|
||||
},
|
||||
function(error) {
|
||||
data = error;
|
||||
failureCallback(data);
|
||||
rejected = true;
|
||||
failureCallback(error);
|
||||
});
|
||||
waitsFor(function() {
|
||||
return data !== undefined;
|
||||
return rejected;
|
||||
}, 20000);
|
||||
}
|
||||
|
||||
@ -63,6 +63,28 @@ describe('api', function() {
|
||||
waitsForPromiseResolved(Promise.all(promises), function (data) {
|
||||
expect((data[0].loaded / data[0].total) > 0).toEqual(true);
|
||||
expect(data[1] instanceof PDFDocumentProxy).toEqual(true);
|
||||
expect(loadingTask).toEqual(data[1].loadingTask);
|
||||
});
|
||||
});
|
||||
it('creates pdf doc from URL and aborts before worker initialized',
|
||||
function() {
|
||||
var loadingTask = PDFJS.getDocument(basicApiUrl);
|
||||
loadingTask.destroy();
|
||||
waitsForPromiseRejected(loadingTask.promise, function(reason) {
|
||||
expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
it('creates pdf doc from URL and aborts loading after worker initialized',
|
||||
function() {
|
||||
var loadingTask = PDFJS.getDocument(basicApiUrl);
|
||||
// This can be somewhat random -- we cannot guarantee perfect
|
||||
// 'Terminate' message to the worker before/after setting up pdfManager.
|
||||
var destroyed = loadingTask._transport.workerInitializedCapability.
|
||||
promise.then(function () {
|
||||
return loadingTask.destroy();
|
||||
});
|
||||
waitsForPromiseResolved(destroyed, function (data) {
|
||||
expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
it('creates pdf doc from typed array', function() {
|
||||
|
@ -35,6 +35,7 @@
|
||||
<script src="../../src/core/parser.js"></script>
|
||||
<script src="../../src/core/ps_parser.js"></script>
|
||||
<script src="../../src/display/pattern_helper.js"></script>
|
||||
<script src="../../src/display/font_loader.js"></script>
|
||||
<script src="../../src/display/annotation_helper.js"></script>
|
||||
<script src="../../src/core/stream.js"></script>
|
||||
<script src="../../src/core/worker.js"></script>
|
||||
|
@ -101,7 +101,7 @@ var PDFPageView = (function PDFPageViewClosure() {
|
||||
this.zoomLayer = null;
|
||||
this.reset();
|
||||
if (this.pdfPage) {
|
||||
this.pdfPage.destroy();
|
||||
this.pdfPage.cleanup();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -410,6 +410,11 @@ var PDFViewerApplication = {
|
||||
function FirefoxComDataRangeTransport_requestDataRange(begin, end) {
|
||||
FirefoxCom.request('requestDataRange', { begin: begin, end: end });
|
||||
};
|
||||
FirefoxComDataRangeTransport.prototype.abort =
|
||||
function FirefoxComDataRangeTransport_abort() {
|
||||
// Sync call to ensure abort is really started.
|
||||
FirefoxCom.requestSync('abortLoading', null);
|
||||
};
|
||||
|
||||
var pdfDataRangeTransport;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user