[api-minor] Change PDFDocumentProxy.cleanup
/PDFPageProxy.cleanup
to return data
This patch makes the following changes, to improve these API methods: - Let `PDFPageProxy.cleanup` return a boolean indicating if clean-up actually happened, since ongoing rendering will block clean-up. Besides being used in other parts of this patch, it seems that an API user may also be interested in the return value given that clean-up isn't *guaranteed* to happen. - Let `PDFDocumentProxy.cleanup` return the promise indicating when clean-up is finished. - Improve the JSDoc comment for `PDFDocumentProxy.cleanup` to mention that clean-up is triggered on *both* threads (without going into unnecessary specifics regarding what *exactly* said data actually is). Add a note in the JSDoc comment about not calling this method when rendering is ongoing. - Change `WorkerTransport.startCleanup` to throw an `Error` if it's called when rendering is ongoing, to prevent rendering from breaking. Please note that this won't stop *worker-thread* clean-up from happening (since there's no general "something is rendering"-flag), however I'm not sure if that's really a problem; but please don't quote me on that :-) All of the caches that's being cleared in `Catalog.cleanup`, on the worker-thread, *should* be re-filled automatically even if cleared *during* parsing/rendering, and the only thing that probably happens is that e.g. font data would have to be re-parsed. On the main-thread, on the other hand, clearing the caches is more-or-less guaranteed to cause rendering errors, since the rendering code in `src/display/canvas.js` isn't able to re-request any image/font data that's suddenly being pulled out from under it. - Last, but not least, add a couple of basic unit-tests for the clean-up functionality.
This commit is contained in:
parent
a5fec297c0
commit
7117ee03d6
@ -758,10 +758,16 @@ class PDFDocumentProxy {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up resources allocated by the document, e.g. created `@font-face`.
|
||||
* Cleans up resources allocated by the document, on both the main- and
|
||||
* worker-threads.
|
||||
*
|
||||
* NOTE: Do not, under any circumstances, call this method when rendering is
|
||||
* currently ongoing since that may lead to rendering errors.
|
||||
*
|
||||
* @returns {Promise} A promise that is resolved when clean-up has finished.
|
||||
*/
|
||||
cleanup() {
|
||||
this._transport.startCleanup();
|
||||
return this._transport.startCleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1269,10 +1275,11 @@ class PDFPageProxy {
|
||||
* Cleans up resources allocated by the page.
|
||||
* @param {boolean} [resetStats] - Reset page stats, if enabled.
|
||||
* The default value is `false`.
|
||||
* @returns {boolean} Indicating if clean-up was successfully run.
|
||||
*/
|
||||
cleanup(resetStats = false) {
|
||||
this.pendingCleanup = true;
|
||||
this._tryCleanup(resetStats);
|
||||
return this._tryCleanup(resetStats);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1290,7 +1297,7 @@ class PDFPageProxy {
|
||||
);
|
||||
})
|
||||
) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
Object.keys(this.intentStates).forEach(intent => {
|
||||
@ -1302,6 +1309,7 @@ class PDFPageProxy {
|
||||
this._stats = new StatTimer();
|
||||
}
|
||||
this.pendingCleanup = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2555,11 +2563,17 @@ class WorkerTransport {
|
||||
}
|
||||
|
||||
startCleanup() {
|
||||
this.messageHandler.sendWithPromise("Cleanup", null).then(() => {
|
||||
return this.messageHandler.sendWithPromise("Cleanup", null).then(() => {
|
||||
for (let i = 0, ii = this.pageCache.length; i < ii; i++) {
|
||||
const page = this.pageCache[i];
|
||||
if (page) {
|
||||
page.cleanup();
|
||||
const cleanupSuccessful = page.cleanup();
|
||||
|
||||
if (!cleanupSuccessful) {
|
||||
throw new Error(
|
||||
`startCleanup: Page ${i + 1} is currently rendering.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.commonObjs.clear();
|
||||
|
@ -1151,6 +1151,14 @@ describe("api", function() {
|
||||
.catch(done.fail);
|
||||
});
|
||||
|
||||
it("cleans up document resources", function(done) {
|
||||
const promise = doc.cleanup();
|
||||
promise.then(function() {
|
||||
expect(true).toEqual(true);
|
||||
done();
|
||||
}, done.fail);
|
||||
});
|
||||
|
||||
it("checks that fingerprints are unique", function(done) {
|
||||
const loadingTask1 = getDocument(
|
||||
buildGetDocumentParams("issue4436r.pdf")
|
||||
@ -1764,6 +1772,83 @@ describe("api", function() {
|
||||
),
|
||||
]).then(done);
|
||||
});
|
||||
|
||||
it("cleans up document resources after rendering of page", function(done) {
|
||||
const loadingTask = getDocument(buildGetDocumentParams(basicApiFileName));
|
||||
let canvasAndCtx;
|
||||
|
||||
loadingTask.promise
|
||||
.then(pdfDoc => {
|
||||
return pdfDoc.getPage(1).then(pdfPage => {
|
||||
const viewport = pdfPage.getViewport({ scale: 1 });
|
||||
canvasAndCtx = CanvasFactory.create(
|
||||
viewport.width,
|
||||
viewport.height
|
||||
);
|
||||
|
||||
const renderTask = pdfPage.render({
|
||||
canvasContext: canvasAndCtx.context,
|
||||
canvasFactory: CanvasFactory,
|
||||
viewport,
|
||||
});
|
||||
return renderTask.promise.then(() => {
|
||||
return pdfDoc.cleanup();
|
||||
});
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
expect(true).toEqual(true);
|
||||
|
||||
CanvasFactory.destroy(canvasAndCtx);
|
||||
loadingTask.destroy().then(done);
|
||||
}, done.fail);
|
||||
});
|
||||
|
||||
it("cleans up document resources during rendering of page", function(done) {
|
||||
const loadingTask = getDocument(
|
||||
buildGetDocumentParams("tracemonkey.pdf")
|
||||
);
|
||||
let canvasAndCtx;
|
||||
|
||||
loadingTask.promise
|
||||
.then(pdfDoc => {
|
||||
return pdfDoc.getPage(1).then(pdfPage => {
|
||||
const viewport = pdfPage.getViewport({ scale: 1 });
|
||||
canvasAndCtx = CanvasFactory.create(
|
||||
viewport.width,
|
||||
viewport.height
|
||||
);
|
||||
|
||||
const renderTask = pdfPage.render({
|
||||
canvasContext: canvasAndCtx.context,
|
||||
canvasFactory: CanvasFactory,
|
||||
viewport,
|
||||
});
|
||||
|
||||
pdfDoc
|
||||
.cleanup()
|
||||
.then(
|
||||
() => {
|
||||
throw new Error("shall fail cleanup");
|
||||
},
|
||||
reason => {
|
||||
expect(reason instanceof Error).toEqual(true);
|
||||
expect(reason.message).toEqual(
|
||||
"startCleanup: Page 1 is currently rendering."
|
||||
);
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
return renderTask.promise;
|
||||
})
|
||||
.then(() => {
|
||||
CanvasFactory.destroy(canvasAndCtx);
|
||||
loadingTask.destroy().then(done);
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(done.fail);
|
||||
});
|
||||
});
|
||||
describe("Multiple `getDocument` instances", function() {
|
||||
// Regression test for https://github.com/mozilla/pdf.js/issues/6205
|
||||
|
Loading…
Reference in New Issue
Block a user