Skip to content

Commit 4ca205b

Browse files
committed
Add an abstract BasePDFStreamRangeReader class, that all the old IPDFStreamRangeReader implementations inherit from
Given that there's no less than *five* different, but very similar, implementations this helps reduce code duplication and simplifies maintenance.
1 parent 54d8c5e commit 4ca205b

File tree

8 files changed

+115
-100
lines changed

8 files changed

+115
-100
lines changed

src/core/worker_stream.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import {
1717
BasePDFStream,
18+
BasePDFStreamRangeReader,
1819
BasePDFStreamReader,
1920
} from "../shared/base_pdf_stream.js";
2021

@@ -58,9 +59,11 @@ class PDFWorkerStreamReader extends BasePDFStreamReader {
5859
}
5960
}
6061

61-
/** @implements {IPDFStreamRangeReader} */
62-
class PDFWorkerStreamRangeReader {
62+
class PDFWorkerStreamRangeReader extends BasePDFStreamRangeReader {
63+
_reader = null;
64+
6365
constructor(stream, begin, end) {
66+
super(stream, begin, end);
6467
const { msgHandler } = stream._source;
6568

6669
const readableStream = msgHandler.sendWithStream("GetRangeReader", {

src/display/fetch_stream.js

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,16 @@
1616
import { AbortException, warn } from "../shared/util.js";
1717
import {
1818
BasePDFStream,
19+
BasePDFStreamRangeReader,
1920
BasePDFStreamReader,
2021
} from "../shared/base_pdf_stream.js";
2122
import {
2223
createHeaders,
2324
createResponseError,
25+
ensureResponseOrigin,
2426
extractFilenameFromHeader,
2527
getResponseOrigin,
2628
validateRangeRequestCapabilities,
27-
validateResponseStatus,
2829
} from "./network_utils.js";
2930

3031
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
@@ -44,6 +45,12 @@ function fetchUrl(url, headers, withCredentials, abortController) {
4445
});
4546
}
4647

48+
function ensureResponseStatus(status, url) {
49+
if (status !== 200 && status !== 206) {
50+
throw createResponseError(status, url);
51+
}
52+
}
53+
4754
function getArrayBuffer(val) {
4855
if (val instanceof Uint8Array) {
4956
return val.buffer;
@@ -91,9 +98,7 @@ class PDFFetchStreamReader extends BasePDFStreamReader {
9198
.then(response => {
9299
stream._responseOrigin = getResponseOrigin(response.url);
93100

94-
if (!validateResponseStatus(response.status)) {
95-
throw createResponseError(response.status, url);
96-
}
101+
ensureResponseStatus(response.status, url);
97102
this._reader = response.body.getReader();
98103

99104
const responseHeaders = response.headers;
@@ -144,35 +149,30 @@ class PDFFetchStreamReader extends BasePDFStreamReader {
144149
}
145150
}
146151

147-
/** @implements {IPDFStreamRangeReader} */
148-
class PDFFetchStreamRangeReader {
152+
class PDFFetchStreamRangeReader extends BasePDFStreamRangeReader {
153+
_abortController = new AbortController();
154+
155+
_readCapability = Promise.withResolvers();
156+
157+
_reader = null;
158+
149159
constructor(stream, begin, end) {
150-
this._stream = stream;
151-
this._reader = null;
152-
const source = stream._source;
153-
this._withCredentials = source.withCredentials || false;
154-
this._readCapability = Promise.withResolvers();
160+
super(stream, begin, end);
161+
const { url, withCredentials } = stream._source;
155162

156-
this._abortController = new AbortController();
157163
// Always create a copy of the headers.
158164
const headers = new Headers(stream.headers);
159165
headers.append("Range", `bytes=${begin}-${end - 1}`);
160166

161-
const url = source.url;
162-
fetchUrl(url, headers, this._withCredentials, this._abortController)
167+
fetchUrl(url, headers, withCredentials, this._abortController)
163168
.then(response => {
164169
const responseOrigin = getResponseOrigin(response.url);
165170

166-
if (responseOrigin !== stream._responseOrigin) {
167-
throw new Error(
168-
`Expected range response-origin "${responseOrigin}" to match "${stream._responseOrigin}".`
169-
);
170-
}
171-
if (!validateResponseStatus(response.status)) {
172-
throw createResponseError(response.status, url);
173-
}
174-
this._readCapability.resolve();
171+
ensureResponseOrigin(responseOrigin, stream._responseOrigin);
172+
ensureResponseStatus(response.status, url);
175173
this._reader = response.body.getReader();
174+
175+
this._readCapability.resolve();
176176
})
177177
.catch(this._readCapability.reject);
178178
}

src/display/network.js

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
import { assert, stringToBytes, warn } from "../shared/util.js";
1717
import {
1818
BasePDFStream,
19+
BasePDFStreamRangeReader,
1920
BasePDFStreamReader,
2021
} from "../shared/base_pdf_stream.js";
2122
import {
2223
createHeaders,
2324
createResponseError,
25+
ensureResponseOrigin,
2426
extractFilenameFromHeader,
2527
getResponseOrigin,
2628
validateRangeRequestCapabilities,
@@ -307,57 +309,59 @@ class PDFNetworkStreamReader extends BasePDFStreamReader {
307309
}
308310
}
309311

310-
/** @implements {IPDFStreamRangeReader} */
311-
class PDFNetworkStreamRangeReader {
312+
class PDFNetworkStreamRangeReader extends BasePDFStreamRangeReader {
312313
onClosed = null;
313314

315+
_done = false;
316+
317+
_queuedChunk = null;
318+
319+
_requests = [];
320+
321+
_storedError = null;
322+
314323
constructor(stream, begin, end) {
315-
this._stream = stream;
324+
super(stream, begin, end);
316325

317326
this._requestXhr = stream._request({
318327
begin,
319328
end,
320-
onHeadersReceived: this._onHeadersReceived.bind(this),
321-
onDone: this._onDone.bind(this),
322-
onError: this._onError.bind(this),
329+
onHeadersReceived: this.#onHeadersReceived.bind(this),
330+
onDone: this.#onDone.bind(this),
331+
onError: this.#onError.bind(this),
323332
onProgress: null,
324333
});
325-
this._requests = [];
326-
this._queuedChunk = null;
327-
this._done = false;
328-
this._storedError = undefined;
329334
}
330335

331-
_onHeadersReceived() {
336+
#onHeadersReceived() {
332337
const responseOrigin = getResponseOrigin(this._requestXhr?.responseURL);
333-
334-
if (responseOrigin !== this._stream._responseOrigin) {
335-
this._storedError = new Error(
336-
`Expected range response-origin "${responseOrigin}" to match "${this._stream._responseOrigin}".`
337-
);
338-
this._onError(0);
338+
try {
339+
ensureResponseOrigin(responseOrigin, this._stream._responseOrigin);
340+
} catch (ex) {
341+
this._storedError = ex;
342+
this.#onError(0);
339343
}
340344
}
341345

342-
_onDone(chunk) {
346+
#onDone(chunk) {
343347
if (this._requests.length > 0) {
344-
const requestCapability = this._requests.shift();
345-
requestCapability.resolve({ value: chunk, done: false });
348+
const capability = this._requests.shift();
349+
capability.resolve({ value: chunk, done: false });
346350
} else {
347351
this._queuedChunk = chunk;
348352
}
349353
this._done = true;
350-
for (const requestCapability of this._requests) {
351-
requestCapability.resolve({ value: undefined, done: true });
354+
for (const capability of this._requests) {
355+
capability.resolve({ value: undefined, done: true });
352356
}
353357
this._requests.length = 0;
354358
this.onClosed?.();
355359
}
356360

357-
_onError(status) {
361+
#onError(status) {
358362
this._storedError ??= createResponseError(status, this._stream.url);
359-
for (const requestCapability of this._requests) {
360-
requestCapability.reject(this._storedError);
363+
for (const capability of this._requests) {
364+
capability.reject(this._storedError);
361365
}
362366
this._requests.length = 0;
363367
this._queuedChunk = null;
@@ -375,15 +379,15 @@ class PDFNetworkStreamRangeReader {
375379
if (this._done) {
376380
return { value: undefined, done: true };
377381
}
378-
const requestCapability = Promise.withResolvers();
379-
this._requests.push(requestCapability);
380-
return requestCapability.promise;
382+
const capability = Promise.withResolvers();
383+
this._requests.push(capability);
384+
return capability.promise;
381385
}
382386

383387
cancel(reason) {
384388
this._done = true;
385-
for (const requestCapability of this._requests) {
386-
requestCapability.resolve({ value: undefined, done: true });
389+
for (const capability of this._requests) {
390+
capability.resolve({ value: undefined, done: true });
387391
}
388392
this._requests.length = 0;
389393

src/display/network_utils.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,19 @@ function createResponseError(status, url) {
107107
);
108108
}
109109

110-
function validateResponseStatus(status) {
111-
return status === 200 || status === 206;
110+
function ensureResponseOrigin(rangeOrigin, origin) {
111+
if (rangeOrigin !== origin) {
112+
throw new Error(
113+
`Expected range response-origin "${rangeOrigin}" to match "${origin}".`
114+
);
115+
}
112116
}
113117

114118
export {
115119
createHeaders,
116120
createResponseError,
121+
ensureResponseOrigin,
117122
extractFilenameFromHeader,
118123
getResponseOrigin,
119124
validateRangeRequestCapabilities,
120-
validateResponseStatus,
121125
};

src/display/node_stream.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import { AbortException, assert, warn } from "../shared/util.js";
1818
import {
1919
BasePDFStream,
20+
BasePDFStreamRangeReader,
2021
BasePDFStreamReader,
2122
} from "../shared/base_pdf_stream.js";
2223
import { createResponseError } from "./network_utils.js";
@@ -66,7 +67,7 @@ function getArrayBuffer(val) {
6667

6768
class PDFNodeStream extends BasePDFStream {
6869
constructor(source) {
69-
super(source, PDFNodeStreamReader, PDFNodeStreamFsRangeReader);
70+
super(source, PDFNodeStreamReader, PDFNodeStreamRangeReader);
7071
this.url = parseUrlOrPath(source.url);
7172
assert(
7273
this.url.protocol === "file:",
@@ -142,12 +143,14 @@ class PDFNodeStreamReader extends BasePDFStreamReader {
142143
}
143144
}
144145

145-
class PDFNodeStreamFsRangeReader {
146+
class PDFNodeStreamRangeReader extends BasePDFStreamRangeReader {
146147
_readCapability = Promise.withResolvers();
147148

148149
_reader = null;
149150

150151
constructor(stream, begin, end) {
152+
super(stream, begin, end);
153+
151154
const url = stream.url;
152155
const fs = process.getBuiltinModule("fs");
153156
try {

src/display/transport_stream.js

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

16-
// eslint-disable-next-line max-len
17-
/** @typedef {import("../interfaces").IPDFStreamRangeReader} IPDFStreamRangeReader */
18-
1916
import {
2017
BasePDFStream,
18+
BasePDFStreamRangeReader,
2119
BasePDFStreamReader,
2220
} from "../shared/base_pdf_stream.js";
2321
import { assert } from "../shared/util.js";
@@ -187,17 +185,20 @@ class PDFDataTransportStreamReader extends BasePDFStreamReader {
187185
}
188186
}
189187

190-
/** @implements {IPDFStreamRangeReader} */
191-
class PDFDataTransportStreamRangeReader {
188+
class PDFDataTransportStreamRangeReader extends BasePDFStreamRangeReader {
192189
onDone = null;
193190

191+
_begin = -1;
192+
193+
_done = false;
194+
195+
_queuedChunk = null;
196+
197+
_requests = [];
198+
194199
constructor(stream, begin, end) {
195-
this._stream = stream;
200+
super(stream, begin, end);
196201
this._begin = begin;
197-
this._end = end;
198-
this._queuedChunk = null;
199-
this._requests = [];
200-
this._done = false;
201202
}
202203

203204
_enqueue(chunk) {
@@ -207,10 +208,11 @@ class PDFDataTransportStreamRangeReader {
207208
if (this._requests.length === 0) {
208209
this._queuedChunk = chunk;
209210
} else {
210-
const requestsCapability = this._requests.shift();
211-
requestsCapability.resolve({ value: chunk, done: false });
212-
for (const requestCapability of this._requests) {
213-
requestCapability.resolve({ value: undefined, done: true });
211+
const firstCapability = this._requests.shift();
212+
firstCapability.resolve({ value: chunk, done: false });
213+
214+
for (const capability of this._requests) {
215+
capability.resolve({ value: undefined, done: true });
214216
}
215217
this._requests.length = 0;
216218
}
@@ -227,15 +229,15 @@ class PDFDataTransportStreamRangeReader {
227229
if (this._done) {
228230
return { value: undefined, done: true };
229231
}
230-
const requestCapability = Promise.withResolvers();
231-
this._requests.push(requestCapability);
232-
return requestCapability.promise;
232+
const capability = Promise.withResolvers();
233+
this._requests.push(capability);
234+
return capability.promise;
233235
}
234236

235237
cancel(reason) {
236238
this._done = true;
237-
for (const requestCapability of this._requests) {
238-
requestCapability.resolve({ value: undefined, done: true });
239+
for (const capability of this._requests) {
240+
capability.resolve({ value: undefined, done: true });
239241
}
240242
this._requests.length = 0;
241243
this.onDone?.();

0 commit comments

Comments
 (0)