Merge pull request #20673 from Snuffleupagus/PDFObjects-Map

Convert the `PDFObjects` class to use a `Map` internally
This commit is contained in:
Jonas Jenwald 2026-02-17 13:54:48 +01:00 committed by GitHub
commit fe44bac6ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 15 additions and 20 deletions

View File

@ -21,7 +21,7 @@ const INITIAL_DATA = Symbol("INITIAL_DATA");
* a worker. This class implements some basic methods to manage these objects. * a worker. This class implements some basic methods to manage these objects.
*/ */
class PDFObjects { class PDFObjects {
#objs = Object.create(null); #objs = new Map();
/** /**
* Ensures there is an object defined for `objId`. * Ensures there is an object defined for `objId`.
@ -30,10 +30,10 @@ class PDFObjects {
* @returns {Object} * @returns {Object}
*/ */
#ensureObj(objId) { #ensureObj(objId) {
return (this.#objs[objId] ||= { return this.#objs.getOrInsertComputed(objId, () => ({
...Promise.withResolvers(), ...Promise.withResolvers(),
data: INITIAL_DATA, data: INITIAL_DATA,
}); }));
} }
/** /**
@ -58,7 +58,7 @@ class PDFObjects {
} }
// If there isn't a callback, the user expects to get the resolved data // If there isn't a callback, the user expects to get the resolved data
// directly. // directly.
const obj = this.#objs[objId]; const obj = this.#objs.get(objId);
// If there isn't an object yet or the object isn't resolved, then the // If there isn't an object yet or the object isn't resolved, then the
// data isn't ready yet! // data isn't ready yet!
if (!obj || obj.data === INITIAL_DATA) { if (!obj || obj.data === INITIAL_DATA) {
@ -72,7 +72,7 @@ class PDFObjects {
* @returns {boolean} * @returns {boolean}
*/ */
has(objId) { has(objId) {
const obj = this.#objs[objId]; const obj = this.#objs.get(objId);
return !!obj && obj.data !== INITIAL_DATA; return !!obj && obj.data !== INITIAL_DATA;
} }
@ -81,12 +81,12 @@ class PDFObjects {
* @returns {boolean} * @returns {boolean}
*/ */
delete(objId) { delete(objId) {
const obj = this.#objs[objId]; const obj = this.#objs.get(objId);
if (!obj || obj.data === INITIAL_DATA) { if (!obj || obj.data === INITIAL_DATA) {
// Only allow removing the object *after* it's been resolved. // Only allow removing the object *after* it's been resolved.
return false; return false;
} }
delete this.#objs[objId]; this.#objs.delete(objId);
return true; return true;
} }
@ -103,23 +103,19 @@ class PDFObjects {
} }
clear() { clear() {
for (const objId in this.#objs) { for (const { data } of this.#objs.values()) {
const { data } = this.#objs[objId];
data?.bitmap?.close(); // Release any `ImageBitmap` data. data?.bitmap?.close(); // Release any `ImageBitmap` data.
} }
this.#objs = Object.create(null); this.#objs.clear();
} }
*[Symbol.iterator]() { *[Symbol.iterator]() {
for (const objId in this.#objs) { for (const [objId, { data }] of this.#objs) {
const { data } = this.#objs[objId]; if (data !== INITIAL_DATA) {
if (data === INITIAL_DATA) {
continue;
}
yield [objId, data]; yield [objId, data];
} }
} }
}
} }
export { PDFObjects }; export { PDFObjects };

View File

@ -64,11 +64,10 @@ class BaseDownloadManager {
const contentType = isPdfData ? "application/pdf" : ""; const contentType = isPdfData ? "application/pdf" : "";
if (isPdfData) { if (isPdfData) {
let blobUrl; const blobUrl = this.#openBlobUrls.getOrInsertComputed(data, () =>
try {
blobUrl = this.#openBlobUrls.getOrInsertComputed(data, () =>
URL.createObjectURL(new Blob([data], { type: contentType })) URL.createObjectURL(new Blob([data], { type: contentType }))
); );
try {
const viewerUrl = this._getOpenDataUrl(blobUrl, filename, dest); const viewerUrl = this._getOpenDataUrl(blobUrl, filename, dest);
window.open(viewerUrl); window.open(viewerUrl);