Skip to content

Commit 4a8fb4d

Browse files
committed
Add an abstract BasePDFStream class, that all the old IPDFStream implementations inherit from
Given that there's no less than *five* different, but very similar, implementations this helps reduce code duplication and simplifies maintenance. Also, spotted during rebasing, pass the `enableHWA` option "correctly" (i.e. as part of the existing `transportParams`) to the `WorkerTransport`-class to keep the constructor simpler.
1 parent a80f10f commit 4a8fb4d

File tree

10 files changed

+194
-314
lines changed

10 files changed

+194
-314
lines changed

src/core/chunked_stream.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,17 +272,17 @@ class ChunkedStreamManager {
272272

273273
_requestsByChunk = new Map();
274274

275-
constructor(pdfNetworkStream, args) {
275+
constructor(pdfStream, args) {
276276
this.length = args.length;
277277
this.chunkSize = args.rangeChunkSize;
278278
this.stream = new ChunkedStream(this.length, this.chunkSize, this);
279-
this.pdfNetworkStream = pdfNetworkStream;
279+
this.pdfStream = pdfStream;
280280
this.disableAutoFetch = args.disableAutoFetch;
281281
this.msgHandler = args.msgHandler;
282282
}
283283

284284
sendRequest(begin, end) {
285-
const rangeReader = this.pdfNetworkStream.getRangeReader(begin, end);
285+
const rangeReader = this.pdfStream.getRangeReader(begin, end);
286286

287287
let chunks = [];
288288
return new Promise((resolve, reject) => {
@@ -530,7 +530,7 @@ class ChunkedStreamManager {
530530

531531
abort(reason) {
532532
this.aborted = true;
533-
this.pdfNetworkStream?.cancelAllRequests(reason);
533+
this.pdfStream?.cancelAllRequests(reason);
534534

535535
for (const capability of this._promisesByRequest.values()) {
536536
capability.reject(reason);

src/core/worker.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -219,23 +219,23 @@ class WorkerMessageHandler {
219219

220220
return new LocalPdfManager(pdfManagerArgs);
221221
}
222-
const pdfStream = new PDFWorkerStream(handler),
223-
fullRequest = pdfStream.getFullReader();
222+
const pdfStream = new PDFWorkerStream({ msgHandler: handler }),
223+
fullReader = pdfStream.getFullReader();
224224

225225
const pdfManagerCapability = Promise.withResolvers();
226226
let newPdfManager,
227227
cachedChunks = [],
228228
loaded = 0;
229229

230-
fullRequest.headersReady
230+
fullReader.headersReady
231231
.then(function () {
232-
if (!fullRequest.isRangeSupported) {
232+
if (!fullReader.isRangeSupported) {
233233
return;
234234
}
235235
pdfManagerArgs.source = pdfStream;
236-
pdfManagerArgs.length = fullRequest.contentLength;
236+
pdfManagerArgs.length = fullReader.contentLength;
237237
// We don't need auto-fetch when streaming is enabled.
238-
pdfManagerArgs.disableAutoFetch ||= fullRequest.isStreamingSupported;
238+
pdfManagerArgs.disableAutoFetch ||= fullReader.isStreamingSupported;
239239

240240
newPdfManager = new NetworkPdfManager(pdfManagerArgs);
241241
// There may be a chance that `newPdfManager` is not initialized for
@@ -282,10 +282,10 @@ class WorkerMessageHandler {
282282
}
283283
loaded += value.byteLength;
284284

285-
if (!fullRequest.isStreamingSupported) {
285+
if (!fullReader.isStreamingSupported) {
286286
handler.send("DocProgress", {
287287
loaded,
288-
total: Math.max(loaded, fullRequest.contentLength || 0),
288+
total: Math.max(loaded, fullReader.contentLength || 0),
289289
});
290290
}
291291

@@ -294,12 +294,12 @@ class WorkerMessageHandler {
294294
} else {
295295
cachedChunks.push(value);
296296
}
297-
fullRequest.read().then(readChunk, reject);
297+
fullReader.read().then(readChunk, reject);
298298
} catch (e) {
299299
reject(e);
300300
}
301301
};
302-
fullRequest.read().then(readChunk, reject);
302+
fullReader.read().then(readChunk, reject);
303303
}).catch(function (e) {
304304
pdfManagerCapability.reject(e);
305305
cancelXHRs = null;

src/core/worker_stream.js

Lines changed: 11 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,55 +13,28 @@
1313
* limitations under the License.
1414
*/
1515

16-
import { assert } from "../shared/util.js";
16+
import { BasePDFStream } from "../shared/base_pdf_stream.js";
1717

18-
/** @implements {IPDFStream} */
19-
class PDFWorkerStream {
20-
constructor(msgHandler) {
21-
this._msgHandler = msgHandler;
22-
this._contentLength = null;
23-
this._fullRequestReader = null;
24-
this._rangeRequestReaders = [];
25-
}
26-
27-
getFullReader() {
28-
assert(
29-
!this._fullRequestReader,
30-
"PDFWorkerStream.getFullReader can only be called once."
31-
);
32-
this._fullRequestReader = new PDFWorkerStreamReader(this._msgHandler);
33-
return this._fullRequestReader;
34-
}
35-
36-
getRangeReader(begin, end) {
37-
const reader = new PDFWorkerStreamRangeReader(begin, end, this._msgHandler);
38-
this._rangeRequestReaders.push(reader);
39-
return reader;
40-
}
41-
42-
cancelAllRequests(reason) {
43-
this._fullRequestReader?.cancel(reason);
44-
45-
for (const reader of this._rangeRequestReaders.slice(0)) {
46-
reader.cancel(reason);
47-
}
18+
class PDFWorkerStream extends BasePDFStream {
19+
constructor(source) {
20+
super(source, PDFWorkerStreamReader, PDFWorkerStreamRangeReader);
4821
}
4922
}
5023

5124
/** @implements {IPDFStreamReader} */
5225
class PDFWorkerStreamReader {
53-
constructor(msgHandler) {
54-
this._msgHandler = msgHandler;
26+
constructor(stream) {
27+
const { msgHandler } = stream._source;
5528
this.onProgress = null;
5629

5730
this._contentLength = null;
5831
this._isRangeSupported = false;
5932
this._isStreamingSupported = false;
6033

61-
const readableStream = this._msgHandler.sendWithStream("GetReader");
34+
const readableStream = msgHandler.sendWithStream("GetReader");
6235
this._reader = readableStream.getReader();
6336

64-
this._headersReady = this._msgHandler
37+
this._headersReady = msgHandler
6538
.sendWithPromise("ReaderHeadersReady")
6639
.then(data => {
6740
this._isStreamingSupported = data.isStreamingSupported;
@@ -103,10 +76,10 @@ class PDFWorkerStreamReader {
10376

10477
/** @implements {IPDFStreamRangeReader} */
10578
class PDFWorkerStreamRangeReader {
106-
constructor(begin, end, msgHandler) {
107-
this._msgHandler = msgHandler;
79+
constructor(stream, begin, end) {
80+
const { msgHandler } = stream._source;
10881

109-
const readableStream = this._msgHandler.sendWithStream("GetRangeReader", {
82+
const readableStream = msgHandler.sendWithStream("GetRangeReader", {
11083
begin,
11184
end,
11285
});

src/display/api.js

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ function getDocument(src = {}) {
440440
ownerDocument,
441441
pdfBug,
442442
styleElement,
443+
enableHWA,
443444
loadingParams: {
444445
disableAutoFetch,
445446
enableXfa,
@@ -463,7 +464,8 @@ function getDocument(src = {}) {
463464

464465
let networkStream;
465466
if (rangeTransport) {
466-
networkStream = new PDFDataTransportStream(rangeTransport, {
467+
networkStream = new PDFDataTransportStream({
468+
pdfDataRangeTransport: rangeTransport,
467469
disableRange,
468470
disableStream,
469471
});
@@ -508,8 +510,7 @@ function getDocument(src = {}) {
508510
task,
509511
networkStream,
510512
transportParams,
511-
transportFactory,
512-
enableHWA
513+
transportFactory
513514
);
514515
task._transport = transport;
515516
messageHandler.send("Ready", null);
@@ -2391,8 +2392,16 @@ class PDFWorker {
23912392
* @ignore
23922393
*/
23932394
class WorkerTransport {
2395+
downloadInfoCapability = Promise.withResolvers();
2396+
2397+
#fullReader = null;
2398+
2399+
#lastProgress = null;
2400+
23942401
#methodPromises = new Map();
23952402

2403+
#networkStream = null;
2404+
23962405
#pageCache = new Map();
23972406

23982407
#pagePromises = new Map();
@@ -2403,21 +2412,17 @@ class WorkerTransport {
24032412

24042413
#pagesMapper = PagesMapper.instance;
24052414

2406-
constructor(
2407-
messageHandler,
2408-
loadingTask,
2409-
networkStream,
2410-
params,
2411-
factory,
2412-
enableHWA
2413-
) {
2415+
constructor(messageHandler, loadingTask, networkStream, params, factory) {
24142416
this.messageHandler = messageHandler;
24152417
this.loadingTask = loadingTask;
2418+
this.#networkStream = networkStream;
2419+
24162420
this.commonObjs = new PDFObjects();
24172421
this.fontLoader = new FontLoader({
24182422
ownerDocument: params.ownerDocument,
24192423
styleElement: params.styleElement,
24202424
});
2425+
this.enableHWA = params.enableHWA;
24212426
this.loadingParams = params.loadingParams;
24222427
this._params = params;
24232428

@@ -2430,12 +2435,6 @@ class WorkerTransport {
24302435
this.destroyed = false;
24312436
this.destroyCapability = null;
24322437

2433-
this._networkStream = networkStream;
2434-
this._fullReader = null;
2435-
this._lastProgress = null;
2436-
this.downloadInfoCapability = Promise.withResolvers();
2437-
this.enableHWA = enableHWA;
2438-
24392438
this.setupMessageHandler();
24402439

24412440
this.#pagesMapper.addListener(this.#updateCaches.bind(this));
@@ -2604,7 +2603,7 @@ class WorkerTransport {
26042603
this.filterFactory.destroy();
26052604
TextLayer.cleanup();
26062605

2607-
this._networkStream?.cancelAllRequests(
2606+
this.#networkStream?.cancelAllRequests(
26082607
new AbortException("Worker was terminated.")
26092608
);
26102609

@@ -2621,18 +2620,18 @@ class WorkerTransport {
26212620

26222621
messageHandler.on("GetReader", (data, sink) => {
26232622
assert(
2624-
this._networkStream,
2625-
"GetReader - no `IPDFStream` instance available."
2623+
this.#networkStream,
2624+
"GetReader - no `BasePDFStream` instance available."
26262625
);
2627-
this._fullReader = this._networkStream.getFullReader();
2628-
this._fullReader.onProgress = evt => {
2629-
this._lastProgress = {
2626+
this.#fullReader = this.#networkStream.getFullReader();
2627+
this.#fullReader.onProgress = evt => {
2628+
this.#lastProgress = {
26302629
loaded: evt.loaded,
26312630
total: evt.total,
26322631
};
26332632
};
26342633
sink.onPull = () => {
2635-
this._fullReader
2634+
this.#fullReader
26362635
.read()
26372636
.then(function ({ value, done }) {
26382637
if (done) {
@@ -2653,7 +2652,7 @@ class WorkerTransport {
26532652
};
26542653

26552654
sink.onCancel = reason => {
2656-
this._fullReader.cancel(reason);
2655+
this.#fullReader.cancel(reason);
26572656

26582657
sink.ready.catch(readyReason => {
26592658
if (this.destroyed) {
@@ -2665,18 +2664,18 @@ class WorkerTransport {
26652664
});
26662665

26672666
messageHandler.on("ReaderHeadersReady", async data => {
2668-
await this._fullReader.headersReady;
2667+
await this.#fullReader.headersReady;
26692668

26702669
const { isStreamingSupported, isRangeSupported, contentLength } =
2671-
this._fullReader;
2670+
this.#fullReader;
26722671

26732672
// If stream or range are disabled, it's our only way to report
26742673
// loading progress.
26752674
if (!isStreamingSupported || !isRangeSupported) {
2676-
if (this._lastProgress) {
2677-
loadingTask.onProgress?.(this._lastProgress);
2675+
if (this.#lastProgress) {
2676+
loadingTask.onProgress?.(this.#lastProgress);
26782677
}
2679-
this._fullReader.onProgress = evt => {
2678+
this.#fullReader.onProgress = evt => {
26802679
loadingTask.onProgress?.({
26812680
loaded: evt.loaded,
26822681
total: evt.total,
@@ -2689,24 +2688,24 @@ class WorkerTransport {
26892688

26902689
messageHandler.on("GetRangeReader", (data, sink) => {
26912690
assert(
2692-
this._networkStream,
2693-
"GetRangeReader - no `IPDFStream` instance available."
2691+
this.#networkStream,
2692+
"GetRangeReader - no `BasePDFStream` instance available."
26942693
);
2695-
const rangeReader = this._networkStream.getRangeReader(
2694+
const rangeReader = this.#networkStream.getRangeReader(
26962695
data.begin,
26972696
data.end
26982697
);
26992698

27002699
// When streaming is enabled, it's possible that the data requested here
2701-
// has already been fetched via the `_fullRequestReader` implementation.
2700+
// has already been fetched via the `#fullReader` implementation.
27022701
// However, given that the PDF data is loaded asynchronously on the
27032702
// main-thread and then sent via `postMessage` to the worker-thread,
27042703
// it may not have been available during parsing (hence the attempt to
27052704
// use range requests here).
27062705
//
27072706
// To avoid wasting time and resources here, we'll thus *not* dispatch
27082707
// range requests if the data was already loaded but has not been sent to
2709-
// the worker-thread yet (which will happen via the `_fullRequestReader`).
2708+
// the worker-thread yet (which will happen via the `#fullReader`).
27102709
if (!rangeReader) {
27112710
sink.close();
27122711
return;
@@ -2950,7 +2949,7 @@ class WorkerTransport {
29502949
isPureXfa: !!this._htmlForXfa,
29512950
numPages: this._numPages,
29522951
annotationStorage: map,
2953-
filename: this._fullReader?.filename ?? null,
2952+
filename: this.#fullReader?.filename ?? null,
29542953
},
29552954
transfer
29562955
)
@@ -3118,8 +3117,8 @@ class WorkerTransport {
31183117
.then(results => ({
31193118
info: results[0],
31203119
metadata: results[1] ? new Metadata(results[1]) : null,
3121-
contentDispositionFilename: this._fullReader?.filename ?? null,
3122-
contentLength: this._fullReader?.contentLength ?? null,
3120+
contentDispositionFilename: this.#fullReader?.filename ?? null,
3121+
contentLength: this.#fullReader?.contentLength ?? null,
31233122
hasStructTree: results[2],
31243123
}));
31253124
this.#methodPromises.set(name, promise);

0 commit comments

Comments
 (0)