Stop tracking progressiveDataLength in the ChunkedStreamManager class

Currently this property is essentially "duplicated", so let's instead use the identical one that's availble on the `ChunkedStream` instance.
This commit is contained in:
Jonas Jenwald 2026-01-30 07:55:27 +01:00
parent 814df09e21
commit 62d5408cf0

View File

@ -18,6 +18,12 @@ import { assert } from "../shared/util.js";
import { Stream } from "./stream.js"; import { Stream } from "./stream.js";
class ChunkedStream extends Stream { class ChunkedStream extends Stream {
progressiveDataLength = 0;
_lastSuccessfulEnsureByteChunk = -1; // Single-entry cache
_loadedChunks = new Set();
constructor(length, chunkSize, manager) { constructor(length, chunkSize, manager) {
super( super(
/* arrayBuffer = */ new Uint8Array(length), /* arrayBuffer = */ new Uint8Array(length),
@ -27,11 +33,8 @@ class ChunkedStream extends Stream {
); );
this.chunkSize = chunkSize; this.chunkSize = chunkSize;
this._loadedChunks = new Set();
this.numChunks = Math.ceil(length / chunkSize); this.numChunks = Math.ceil(length / chunkSize);
this.manager = manager; this.manager = manager;
this.progressiveDataLength = 0;
this.lastSuccessfulEnsureByteChunk = -1; // Single-entry cache
} }
// If a particular stream does not implement one or more of these methods, // If a particular stream does not implement one or more of these methods,
@ -106,14 +109,14 @@ class ChunkedStream extends Stream {
if (chunk > this.numChunks) { if (chunk > this.numChunks) {
return; return;
} }
if (chunk === this.lastSuccessfulEnsureByteChunk) { if (chunk === this._lastSuccessfulEnsureByteChunk) {
return; return;
} }
if (!this._loadedChunks.has(chunk)) { if (!this._loadedChunks.has(chunk)) {
throw new MissingDataException(pos, pos + 1); throw new MissingDataException(pos, pos + 1);
} }
this.lastSuccessfulEnsureByteChunk = chunk; this._lastSuccessfulEnsureByteChunk = chunk;
} }
ensureRange(begin, end) { ensureRange(begin, end) {
@ -257,6 +260,18 @@ class ChunkedStream extends Stream {
} }
class ChunkedStreamManager { class ChunkedStreamManager {
aborted = false;
currRequestId = 0;
_chunksNeededByRequest = new Map();
_loadedStreamCapability = Promise.withResolvers();
_promisesByRequest = new Map();
_requestsByChunk = new Map();
constructor(pdfNetworkStream, args) { constructor(pdfNetworkStream, args) {
this.length = args.length; this.length = args.length;
this.chunkSize = args.rangeChunkSize; this.chunkSize = args.rangeChunkSize;
@ -264,16 +279,6 @@ class ChunkedStreamManager {
this.pdfNetworkStream = pdfNetworkStream; this.pdfNetworkStream = pdfNetworkStream;
this.disableAutoFetch = args.disableAutoFetch; this.disableAutoFetch = args.disableAutoFetch;
this.msgHandler = args.msgHandler; this.msgHandler = args.msgHandler;
this.currRequestId = 0;
this._chunksNeededByRequest = new Map();
this._requestsByChunk = new Map();
this._promisesByRequest = new Map();
this.progressiveDataLength = 0;
this.aborted = false;
this._loadedStreamCapability = Promise.withResolvers();
} }
sendRequest(begin, end) { sendRequest(begin, end) {
@ -454,26 +459,25 @@ class ChunkedStreamManager {
} }
onReceiveData(args) { onReceiveData(args) {
const { chunkSize, length, stream } = this;
const chunk = args.chunk; const chunk = args.chunk;
const isProgressive = args.begin === undefined; const isProgressive = args.begin === undefined;
const begin = isProgressive ? this.progressiveDataLength : args.begin; const begin = isProgressive ? stream.progressiveDataLength : args.begin;
const end = begin + chunk.byteLength; const end = begin + chunk.byteLength;
const beginChunk = Math.floor(begin / this.chunkSize); const beginChunk = Math.floor(begin / chunkSize);
const endChunk = const endChunk =
end < this.length end < length ? Math.floor(end / chunkSize) : Math.ceil(end / chunkSize);
? Math.floor(end / this.chunkSize)
: Math.ceil(end / this.chunkSize);
if (isProgressive) { if (isProgressive) {
this.stream.onReceiveProgressiveData(chunk); stream.onReceiveProgressiveData(chunk);
this.progressiveDataLength = end;
} else { } else {
this.stream.onReceiveData(begin, chunk); stream.onReceiveData(begin, chunk);
} }
if (this.stream.isDataLoaded) { if (stream.isDataLoaded) {
this._loadedStreamCapability.resolve(this.stream); this._loadedStreamCapability.resolve(stream);
} }
const loadedRequests = []; const loadedRequests = [];
@ -502,16 +506,16 @@ class ChunkedStreamManager {
// unfetched chunk of the PDF file. // unfetched chunk of the PDF file.
if (!this.disableAutoFetch && this._requestsByChunk.size === 0) { if (!this.disableAutoFetch && this._requestsByChunk.size === 0) {
let nextEmptyChunk; let nextEmptyChunk;
if (this.stream.numChunksLoaded === 1) { if (stream.numChunksLoaded === 1) {
// This is a special optimization so that after fetching the first // This is a special optimization so that after fetching the first
// chunk, rather than fetching the second chunk, we fetch the last // chunk, rather than fetching the second chunk, we fetch the last
// chunk. // chunk.
const lastChunk = this.stream.numChunks - 1; const lastChunk = stream.numChunks - 1;
if (!this.stream.hasChunk(lastChunk)) { if (!stream.hasChunk(lastChunk)) {
nextEmptyChunk = lastChunk; nextEmptyChunk = lastChunk;
} }
} else { } else {
nextEmptyChunk = this.stream.nextEmptyChunk(endChunk); nextEmptyChunk = stream.nextEmptyChunk(endChunk);
} }
if (Number.isInteger(nextEmptyChunk)) { if (Number.isInteger(nextEmptyChunk)) {
this._requestChunks([nextEmptyChunk]); this._requestChunks([nextEmptyChunk]);
@ -525,8 +529,8 @@ class ChunkedStreamManager {
} }
this.msgHandler.send("DocProgress", { this.msgHandler.send("DocProgress", {
loaded: this.stream.numChunksLoaded * this.chunkSize, loaded: stream.numChunksLoaded * chunkSize,
total: this.length, total: length,
}); });
} }