diff --git a/src/display/api.js b/src/display/api.js index e77cc6059..e73046361 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -1839,6 +1839,21 @@ class WorkerTransport { const rangeReader = this._networkStream.getRangeReader(data.begin, data.end); + // When streaming is enabled, it's possible that the data requested here + // has already been fetched via the `_fullRequestReader` implementation. + // However, given that the PDF data is loaded asynchronously on the + // main-thread and then sent via `postMessage` to the worker-thread, + // it may not have been available during parsing (hence the attempt to + // use range requests here). + // + // To avoid wasting time and resources here, we'll thus *not* dispatch + // range requests if the data was already loaded but has not been sent to + // the worker-thread yet (which will happen via the `_fullRequestReader`). + if (!rangeReader) { + sink.close(); + return; + } + sink.onPull = () => { rangeReader.read().then(function({ value, done, }) { if (done) { diff --git a/src/display/fetch_stream.js b/src/display/fetch_stream.js index 20ca3281f..7dcd3e537 100644 --- a/src/display/fetch_stream.js +++ b/src/display/fetch_stream.js @@ -42,6 +42,10 @@ class PDFFetchStream { this._rangeRequestReaders = []; } + get _progressiveDataLength() { + return (this._fullRequestReader ? this._fullRequestReader._loaded : 0); + } + getFullReader() { assert(!this._fullRequestReader); this._fullRequestReader = new PDFFetchStreamReader(this); @@ -49,6 +53,9 @@ class PDFFetchStream { } getRangeReader(begin, end) { + if (end <= this._progressiveDataLength) { + return null; + } let reader = new PDFFetchStreamRangeReader(this, begin, end); this._rangeRequestReaders.push(reader); return reader; diff --git a/src/display/node_stream.js b/src/display/node_stream.js index 5b744f867..a38b02bbd 100644 --- a/src/display/node_stream.js +++ b/src/display/node_stream.js @@ -54,19 +54,26 @@ class PDFNodeStream { this.isFsUrl = this.url.protocol === 'file:'; this.httpHeaders = (this.isHttp && source.httpHeaders) || {}; - this._fullRequest = null; + this._fullRequestReader = null; this._rangeRequestReaders = []; } + get _progressiveDataLength() { + return (this._fullRequestReader ? this._fullRequestReader._loaded : 0); + } + getFullReader() { - assert(!this._fullRequest); - this._fullRequest = this.isFsUrl ? + assert(!this._fullRequestReader); + this._fullRequestReader = this.isFsUrl ? new PDFNodeStreamFsFullReader(this) : new PDFNodeStreamFullReader(this); - return this._fullRequest; + return this._fullRequestReader; } getRangeReader(start, end) { + if (end <= this._progressiveDataLength) { + return null; + } let rangeReader = this.isFsUrl ? new PDFNodeStreamFsRangeReader(this, start, end) : new PDFNodeStreamRangeReader(this, start, end); @@ -75,8 +82,8 @@ class PDFNodeStream { } cancelAllRequests(reason) { - if (this._fullRequest) { - this._fullRequest.cancel(reason); + if (this._fullRequestReader) { + this._fullRequestReader.cancel(reason); } let readers = this._rangeRequestReaders.slice(0); diff --git a/src/display/transport_stream.js b/src/display/transport_stream.js index f21c070df..a1e2f91cd 100644 --- a/src/display/transport_stream.js +++ b/src/display/transport_stream.js @@ -76,6 +76,10 @@ var PDFDataTransportStream = (function PDFDataTransportStreamClosure() { } }, + get _progressiveDataLength() { + return (this._fullRequestReader ? this._fullRequestReader._loaded : 0); + }, + _onProgress: function PDFDataTransportStream_onDataProgress(evt) { if (evt.total === undefined && this._rangeReaders.length > 0) { // Reporting to first range reader. @@ -115,6 +119,9 @@ var PDFDataTransportStream = (function PDFDataTransportStreamClosure() { }, getRangeReader: function PDFDataTransportStream_getRangeReader(begin, end) { + if (end <= this._progressiveDataLength) { + return null; + } var reader = new PDFDataTransportStreamRangeReader(this, begin, end); this._pdfDataRangeTransport.requestDataRange(begin, end); this._rangeReaders.push(reader); @@ -141,6 +148,10 @@ var PDFDataTransportStream = (function PDFDataTransportStreamClosure() { this._done = progressiveDone || false; this._filename = null; this._queuedChunks = queuedChunks || []; + this._loaded = 0; + for (const chunk of this._queuedChunks) { + this._loaded += chunk.byteLength; + } this._requests = []; this._headersReady = Promise.resolve(); stream._fullRequestReader = this; @@ -155,9 +166,10 @@ var PDFDataTransportStream = (function PDFDataTransportStreamClosure() { if (this._requests.length > 0) { var requestCapability = this._requests.shift(); requestCapability.resolve({ value: chunk, done: false, }); - return; + } else { + this._queuedChunks.push(chunk); } - this._queuedChunks.push(chunk); + this._loaded += chunk.byteLength; }, get headersReady() {