[Pkg-javascript-commits] [pdf.js] 79/174: Adds destroy method to the document loading task.
David Prévot
taffit at moszumanska.debian.org
Thu Nov 19 18:45:17 UTC 2015
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository pdf.js.
commit 59c13b32aa3f57740cdc9548c11d38667c8b8a98
Author: Yury Delendik <ydelendik at mozilla.com>
Date: Tue Oct 20 17:45:55 2015 -0500
Adds destroy method to the document loading task.
Also renames PDFPageProxy.destroy method to cleanup.
---
extensions/firefox/content/PdfStreamConverter.jsm | 33 +++++--
src/core/chunked_stream.js | 49 ++++-----
src/core/obj.js | 15 +--
src/core/pdf_manager.js | 11 +--
src/core/worker.js | 52 ++++++++--
src/display/api.js | 115 ++++++++++++++++++----
test/unit/api_spec.js | 38 +++++--
test/unit/unit_test.html | 1 +
web/pdf_page_view.js | 2 +-
web/viewer.js | 5 +
10 files changed, 243 insertions(+), 78 deletions(-)
diff --git a/extensions/firefox/content/PdfStreamConverter.jsm b/extensions/firefox/content/PdfStreamConverter.jsm
index b331444..9e12f10 100644
--- a/extensions/firefox/content/PdfStreamConverter.jsm
+++ b/extensions/firefox/content/PdfStreamConverter.jsm
@@ -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) {
diff --git a/src/core/chunked_stream.js b/src/core/chunked_stream.js
index b0a7b46..de20ba1 100644
--- a/src/core/chunked_stream.js
+++ b/src/core/chunked_stream.js
@@ -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'));
+ }
}
};
diff --git a/src/core/obj.js b/src/core/obj.js
index fe5135f..ef8766e 100644
--- a/src/core/obj.js
+++ b/src/core/obj.js
@@ -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.
diff --git a/src/core/pdf_manager.js b/src/core/pdf_manager.js
index 3101e4e..b264fde 100644
--- a/src/core/pdf_manager.js
+++ b/src/core/pdf_manager.js
@@ -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;
diff --git a/src/core/worker.js b/src/core/worker.js
index 40d7d89..9fc3ea4 100644
--- a/src/core/worker.js
+++ b/src/core/worker.js
@@ -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();
+ }
});
}
};
diff --git a/src/display/api.js b/src/display/api.js
index c89c931..08b02ca 100644
--- a/src/display/api.js
+++ b/src/display/api.js
@@ -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();
diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js
index b183b97..36f97ab 100644
--- a/test/unit/api_spec.js
+++ b/test/unit/api_spec.js
@@ -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() {
diff --git a/test/unit/unit_test.html b/test/unit/unit_test.html
index 9193dbc..5fe1f25 100644
--- a/test/unit/unit_test.html
+++ b/test/unit/unit_test.html
@@ -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>
diff --git a/web/pdf_page_view.js b/web/pdf_page_view.js
index bec6d1d..d3f2d9a 100644
--- a/web/pdf_page_view.js
+++ b/web/pdf_page_view.js
@@ -101,7 +101,7 @@ var PDFPageView = (function PDFPageViewClosure() {
this.zoomLayer = null;
this.reset();
if (this.pdfPage) {
- this.pdfPage.destroy();
+ this.pdfPage.cleanup();
}
},
diff --git a/web/viewer.js b/web/viewer.js
index 4b25ffe..bb53afa 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -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;
--
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