Merge pull request #10644 from Snuffleupagus/revokeObjectURL

Ensure that `blob:` URLs will be revoked when pages are cleaned-up/destroyed (JPEG memory usage)
This commit is contained in:
Tim van der Meij 2019-03-16 19:29:23 +01:00 committed by GitHub
commit 7c9f1cc518
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 2 deletions

View File

@ -23,7 +23,8 @@ import {
} from '../shared/util';
import {
deprecated, DOMCanvasFactory, DOMCMapReaderFactory, DummyStatTimer,
loadScript, PageViewport, RenderingCancelledException, StatTimer
loadScript, PageViewport, releaseImageResources, RenderingCancelledException,
StatTimer
} from './display_utils';
import { FontFaceObject, FontLoader } from './font_loader';
import { apiCompatibilityParams } from './api_compatibility';
@ -1988,11 +1989,14 @@ class WorkerTransport {
resolve(img);
};
img.onerror = function() {
reject(new Error('Error during JPEG image loading'));
// Note that when the browser image loading/decoding fails,
// we'll fallback to the built-in PDF.js JPEG decoder; see
// `PartialEvaluator.buildPaintImageXObject` in the
// `src/core/evaluator.js` file.
reject(new Error('Error during JPEG image loading'));
// Always remember to release the image data if errors occurred.
releaseImageResources(img);
};
img.src = imageData;
}).then((img) => {
@ -2095,6 +2099,8 @@ class WorkerTransport {
}
resolve({ data: buf, width, height, });
// Immediately release the image data once decoding has finished.
releaseImageResources(img);
// Zeroing the width and height cause Firefox to release graphics
// resources immediately, which can greatly reduce memory consumption.
tmpCanvas.width = 0;
@ -2104,6 +2110,9 @@ class WorkerTransport {
};
img.onerror = function() {
reject(new Error('JpegDecode failed to load image'));
// Always remember to release the image data if errors occurred.
releaseImageResources(img);
};
img.src = imageUrl;
});
@ -2323,6 +2332,14 @@ class PDFObjects {
}
clear() {
for (const objId in this._objs) {
const { data, } = this._objs[objId];
if (typeof Image !== 'undefined' && data instanceof Image) {
// Always release the image data when clearing out the cached objects.
releaseImageResources(data);
}
}
this._objs = Object.create(null);
}
}

View File

@ -480,6 +480,17 @@ function deprecated(details) {
console.log('Deprecated API usage: ' + details);
}
function releaseImageResources(img) {
assert(img instanceof Image, 'Invalid `img` parameter.');
const url = img.src;
if (typeof url === 'string' && url.startsWith('blob:') &&
URL.revokeObjectURL) {
URL.revokeObjectURL(url);
}
img.removeAttribute('src');
}
export {
PageViewport,
RenderingCancelledException,
@ -496,4 +507,5 @@ export {
isValidFetchUrl,
loadScript,
deprecated,
releaseImageResources,
};