Merge pull request #13172 from Snuffleupagus/cleanup-keepFonts
[api-minor] Add an option, in `PDFDocumentProxy.cleanup`, to allow fonts to remain attached to the DOM
This commit is contained in:
commit
228adbf673
@ -921,10 +921,13 @@ class PDFDocumentProxy {
|
|||||||
* NOTE: Do not, under any circumstances, call this method when rendering is
|
* NOTE: Do not, under any circumstances, call this method when rendering is
|
||||||
* currently ongoing since that may lead to rendering errors.
|
* currently ongoing since that may lead to rendering errors.
|
||||||
*
|
*
|
||||||
|
* @param {boolean} [keepLoadedFonts] - Let fonts remain attached to the DOM.
|
||||||
|
* NOTE: This will increase persistent memory usage, hence don't use this
|
||||||
|
* option unless absolutely necessary. The default value is `false`.
|
||||||
* @returns {Promise} A promise that is resolved when clean-up has finished.
|
* @returns {Promise} A promise that is resolved when clean-up has finished.
|
||||||
*/
|
*/
|
||||||
cleanup() {
|
cleanup(keepLoadedFonts = false) {
|
||||||
return this._transport.startCleanup();
|
return this._transport.startCleanup(keepLoadedFonts || this.isPureXfa);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1180,14 +1183,14 @@ class PDFPageProxy {
|
|||||||
* {Array} of the annotation objects.
|
* {Array} of the annotation objects.
|
||||||
*/
|
*/
|
||||||
getAnnotations({ intent = null } = {}) {
|
getAnnotations({ intent = null } = {}) {
|
||||||
if (!this.annotationsPromise || this.annotationsIntent !== intent) {
|
if (!this._annotationsPromise || this._annotationsIntent !== intent) {
|
||||||
this.annotationsPromise = this._transport.getAnnotations(
|
this._annotationsPromise = this._transport.getAnnotations(
|
||||||
this._pageIndex,
|
this._pageIndex,
|
||||||
intent
|
intent
|
||||||
);
|
);
|
||||||
this.annotationsIntent = intent;
|
this._annotationsIntent = intent;
|
||||||
}
|
}
|
||||||
return this.annotationsPromise;
|
return this._annotationsPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1480,7 +1483,7 @@ class PDFPageProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.objs.clear();
|
this.objs.clear();
|
||||||
this.annotationsPromise = null;
|
this._annotationsPromise = null;
|
||||||
this._jsActionsPromise = null;
|
this._jsActionsPromise = null;
|
||||||
this._xfaPromise = null;
|
this._xfaPromise = null;
|
||||||
this.pendingCleanup = false;
|
this.pendingCleanup = false;
|
||||||
@ -1515,7 +1518,7 @@ class PDFPageProxy {
|
|||||||
|
|
||||||
this._intentStates.clear();
|
this._intentStates.clear();
|
||||||
this.objs.clear();
|
this.objs.clear();
|
||||||
this.annotationsPromise = null;
|
this._annotationsPromise = null;
|
||||||
this._jsActionsPromise = null;
|
this._jsActionsPromise = null;
|
||||||
this._xfaPromise = null;
|
this._xfaPromise = null;
|
||||||
if (resetStats && this._stats) {
|
if (resetStats && this._stats) {
|
||||||
@ -2789,24 +2792,28 @@ class WorkerTransport {
|
|||||||
return this.messageHandler.sendWithPromise("GetStats", null);
|
return this.messageHandler.sendWithPromise("GetStats", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
startCleanup() {
|
async startCleanup(keepLoadedFonts = false) {
|
||||||
return this.messageHandler.sendWithPromise("Cleanup", null).then(() => {
|
await this.messageHandler.sendWithPromise("Cleanup", null);
|
||||||
for (let i = 0, ii = this.pageCache.length; i < ii; i++) {
|
|
||||||
const page = this.pageCache[i];
|
|
||||||
if (page) {
|
|
||||||
const cleanupSuccessful = page.cleanup();
|
|
||||||
|
|
||||||
if (!cleanupSuccessful) {
|
if (this.destroyed) {
|
||||||
throw new Error(
|
return; // No need to manually clean-up when destruction has started.
|
||||||
`startCleanup: Page ${i + 1} is currently rendering.`
|
}
|
||||||
);
|
for (let i = 0, ii = this.pageCache.length; i < ii; i++) {
|
||||||
}
|
const page = this.pageCache[i];
|
||||||
}
|
if (!page) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
this.commonObjs.clear();
|
const cleanupSuccessful = page.cleanup();
|
||||||
|
|
||||||
|
if (!cleanupSuccessful) {
|
||||||
|
throw new Error(`startCleanup: Page ${i + 1} is currently rendering.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.commonObjs.clear();
|
||||||
|
if (!keepLoadedFonts) {
|
||||||
this.fontLoader.clear();
|
this.fontLoader.clear();
|
||||||
this._hasJSActionsPromise = null;
|
}
|
||||||
});
|
this._hasJSActionsPromise = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get loadingParams() {
|
get loadingParams() {
|
||||||
|
@ -1339,12 +1339,10 @@ describe("api", function () {
|
|||||||
.catch(done.fail);
|
.catch(done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("cleans up document resources", function (done) {
|
it("cleans up document resources", async function () {
|
||||||
const promise = pdfDocument.cleanup();
|
await pdfDocument.cleanup();
|
||||||
promise.then(function () {
|
|
||||||
expect(true).toEqual(true);
|
expect(true).toEqual(true);
|
||||||
done();
|
|
||||||
}, done.fail);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("checks that fingerprints are unique", function (done) {
|
it("checks that fingerprints are unique", function (done) {
|
||||||
@ -1982,85 +1980,69 @@ describe("api", function () {
|
|||||||
]).then(done);
|
]).then(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("cleans up document resources after rendering of page", function (done) {
|
it("cleans up document resources after rendering of page", async function () {
|
||||||
const loadingTask = getDocument(buildGetDocumentParams(basicApiFileName));
|
const loadingTask = getDocument(buildGetDocumentParams(basicApiFileName));
|
||||||
let canvasAndCtx;
|
const pdfDoc = await loadingTask.promise;
|
||||||
|
const pdfPage = await pdfDoc.getPage(1);
|
||||||
|
|
||||||
loadingTask.promise
|
const viewport = pdfPage.getViewport({ scale: 1 });
|
||||||
.then(pdfDoc => {
|
const canvasAndCtx = CanvasFactory.create(
|
||||||
return pdfDoc.getPage(1).then(pdfPage => {
|
viewport.width,
|
||||||
const viewport = pdfPage.getViewport({ scale: 1 });
|
viewport.height
|
||||||
canvasAndCtx = CanvasFactory.create(
|
);
|
||||||
viewport.width,
|
|
||||||
viewport.height
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderTask = pdfPage.render({
|
const renderTask = pdfPage.render({
|
||||||
canvasContext: canvasAndCtx.context,
|
canvasContext: canvasAndCtx.context,
|
||||||
canvasFactory: CanvasFactory,
|
canvasFactory: CanvasFactory,
|
||||||
viewport,
|
viewport,
|
||||||
});
|
});
|
||||||
return renderTask.promise.then(() => {
|
await renderTask.promise;
|
||||||
return pdfDoc.cleanup();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
expect(true).toEqual(true);
|
|
||||||
|
|
||||||
CanvasFactory.destroy(canvasAndCtx);
|
await pdfDoc.cleanup();
|
||||||
loadingTask.destroy().then(done);
|
|
||||||
}, done.fail);
|
expect(true).toEqual(true);
|
||||||
|
|
||||||
|
CanvasFactory.destroy(canvasAndCtx);
|
||||||
|
await loadingTask.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("cleans up document resources during rendering of page", function (done) {
|
it("cleans up document resources during rendering of page", async function () {
|
||||||
const loadingTask = getDocument(
|
const loadingTask = getDocument(
|
||||||
buildGetDocumentParams("tracemonkey.pdf")
|
buildGetDocumentParams("tracemonkey.pdf")
|
||||||
);
|
);
|
||||||
let canvasAndCtx;
|
const pdfDoc = await loadingTask.promise;
|
||||||
|
const pdfPage = await pdfDoc.getPage(1);
|
||||||
|
|
||||||
loadingTask.promise
|
const viewport = pdfPage.getViewport({ scale: 1 });
|
||||||
.then(pdfDoc => {
|
const canvasAndCtx = CanvasFactory.create(
|
||||||
return pdfDoc.getPage(1).then(pdfPage => {
|
viewport.width,
|
||||||
const viewport = pdfPage.getViewport({ scale: 1 });
|
viewport.height
|
||||||
canvasAndCtx = CanvasFactory.create(
|
);
|
||||||
viewport.width,
|
|
||||||
viewport.height
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderTask = pdfPage.render({
|
const renderTask = pdfPage.render({
|
||||||
canvasContext: canvasAndCtx.context,
|
canvasContext: canvasAndCtx.context,
|
||||||
canvasFactory: CanvasFactory,
|
canvasFactory: CanvasFactory,
|
||||||
viewport,
|
viewport,
|
||||||
});
|
});
|
||||||
|
// Ensure that clean-up runs during rendering.
|
||||||
|
renderTask.onContinue = function (cont) {
|
||||||
|
waitSome(cont);
|
||||||
|
};
|
||||||
|
|
||||||
renderTask.onContinue = function (cont) {
|
try {
|
||||||
waitSome(cont);
|
await pdfDoc.cleanup();
|
||||||
};
|
|
||||||
|
|
||||||
return pdfDoc
|
throw new Error("shall fail cleanup");
|
||||||
.cleanup()
|
} catch (reason) {
|
||||||
.then(
|
expect(reason instanceof Error).toEqual(true);
|
||||||
() => {
|
expect(reason.message).toEqual(
|
||||||
throw new Error("shall fail cleanup");
|
"startCleanup: Page 1 is currently rendering."
|
||||||
},
|
);
|
||||||
reason => {
|
}
|
||||||
expect(reason instanceof Error).toEqual(true);
|
await renderTask.promise;
|
||||||
expect(reason.message).toEqual(
|
|
||||||
"startCleanup: Page 1 is currently rendering."
|
CanvasFactory.destroy(canvasAndCtx);
|
||||||
);
|
await loadingTask.destroy();
|
||||||
}
|
|
||||||
)
|
|
||||||
.then(() => {
|
|
||||||
return renderTask.promise;
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
CanvasFactory.destroy(canvasAndCtx);
|
|
||||||
loadingTask.destroy().then(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(done.fail);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("caches image resources at the document/page level as expected (issue 11878)", async function () {
|
it("caches image resources at the document/page level as expected (issue 11878)", async function () {
|
||||||
|
13
web/app.js
13
web/app.js
@ -465,7 +465,7 @@ const PDFViewerApplication = {
|
|||||||
this.overlayManager = new OverlayManager();
|
this.overlayManager = new OverlayManager();
|
||||||
|
|
||||||
const pdfRenderingQueue = new PDFRenderingQueue();
|
const pdfRenderingQueue = new PDFRenderingQueue();
|
||||||
pdfRenderingQueue.onIdle = this.cleanup.bind(this);
|
pdfRenderingQueue.onIdle = this._cleanup.bind(this);
|
||||||
this.pdfRenderingQueue = pdfRenderingQueue;
|
this.pdfRenderingQueue = pdfRenderingQueue;
|
||||||
|
|
||||||
const pdfLinkService = new PDFLinkService({
|
const pdfLinkService = new PDFLinkService({
|
||||||
@ -1782,7 +1782,10 @@ const PDFViewerApplication = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
cleanup() {
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_cleanup() {
|
||||||
if (!this.pdfDocument) {
|
if (!this.pdfDocument) {
|
||||||
return; // run cleanup when document is loaded
|
return; // run cleanup when document is loaded
|
||||||
}
|
}
|
||||||
@ -1790,9 +1793,9 @@ const PDFViewerApplication = {
|
|||||||
this.pdfThumbnailViewer.cleanup();
|
this.pdfThumbnailViewer.cleanup();
|
||||||
|
|
||||||
// We don't want to remove fonts used by active page SVGs.
|
// We don't want to remove fonts used by active page SVGs.
|
||||||
if (this.pdfViewer.renderer !== RendererType.SVG) {
|
this.pdfDocument.cleanup(
|
||||||
this.pdfDocument.cleanup();
|
/* keepLoadedFonts = */ this.pdfViewer.renderer === RendererType.SVG
|
||||||
}
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
forceRendering() {
|
forceRendering() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user