Convert PDFPageViewBuffer to use a Set internally

This relies on the fact that `Set`s preserve the insertion order[1], which means that we can utilize an iterator to access the *first* stored view.

Note that in the `resize`-method, we can now move the visible pages to the back of the buffer using a single loop (hence we don't need to use the `moveToEndOfArray` helper function any more).

---
[1] This applies to `Map`s as well, although that's not entirely relevant here.
This commit is contained in:
Jonas Jenwald 2021-11-06 10:10:05 +01:00
parent 0eba15b43a
commit f55bf42398

View File

@ -31,7 +31,6 @@ import {
MAX_AUTO_SCALE, MAX_AUTO_SCALE,
MAX_SCALE, MAX_SCALE,
MIN_SCALE, MIN_SCALE,
moveToEndOfArray,
PresentationModeState, PresentationModeState,
RendererType, RendererType,
SCROLLBAR_PADDING, SCROLLBAR_PADDING,
@ -93,7 +92,8 @@ const DEFAULT_CACHE_SIZE = 10;
*/ */
class PDFPageViewBuffer { class PDFPageViewBuffer {
#data = []; // Here we rely on the fact that `Set`s preserve the insertion order.
#buf = new Set();
#size = 0; #size = 0;
@ -106,21 +106,21 @@ class PDFPageViewBuffer {
) { ) {
Object.defineProperty(this, "_buffer", { Object.defineProperty(this, "_buffer", {
get() { get() {
return this.#data.slice(); return [...this.#buf];
}, },
}); });
} }
} }
push(view) { push(view) {
const data = this.#data, const buf = this.#buf;
i = data.indexOf(view); if (buf.has(view)) {
if (i >= 0) { buf.delete(view); // Move the view to the "end" of the buffer.
data.splice(i, 1);
} }
data.push(view); buf.add(view);
if (data.length > this.#size) {
data.shift().destroy(); if (buf.size > this.#size) {
this.#destroyFirstView();
} }
} }
@ -134,19 +134,35 @@ class PDFPageViewBuffer {
resize(newSize, idsToKeep = null) { resize(newSize, idsToKeep = null) {
this.#size = newSize; this.#size = newSize;
const data = this.#data; const buf = this.#buf;
if (idsToKeep) { if (idsToKeep) {
moveToEndOfArray(data, function (page) { const ii = buf.size;
return idsToKeep.has(page.id); let i = 1;
}); for (const view of buf) {
if (idsToKeep.has(view.id)) {
buf.delete(view); // Move the view to the "end" of the buffer.
buf.add(view);
}
if (++i > ii) {
break;
}
}
} }
while (data.length > this.#size) {
data.shift().destroy(); while (buf.size > this.#size) {
this.#destroyFirstView();
} }
} }
has(view) { has(view) {
return this.#data.includes(view); return this.#buf.has(view);
}
#destroyFirstView() {
const firstView = this.#buf.keys().next().value;
firstView?.destroy();
this.#buf.delete(firstView);
} }
} }