diff --git a/src/display/fetch_stream.js b/src/display/fetch_stream.js index 7dcd3e537..f70ed1d54 100644 --- a/src/display/fetch_stream.js +++ b/src/display/fetch_stream.js @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* eslint no-var: error */ import { AbortException, assert, createPromiseCapability @@ -32,6 +33,7 @@ function createFetchOptions(headers, withCredentials, abortController) { }; } +/** @implements {IPDFStream} */ class PDFFetchStream { constructor(source) { this.source = source; @@ -56,7 +58,7 @@ class PDFFetchStream { if (end <= this._progressiveDataLength) { return null; } - let reader = new PDFFetchStreamRangeReader(this, begin, end); + const reader = new PDFFetchStreamRangeReader(this, begin, end); this._rangeRequestReaders.push(reader); return reader; } @@ -65,21 +67,22 @@ class PDFFetchStream { if (this._fullRequestReader) { this._fullRequestReader.cancel(reason); } - let readers = this._rangeRequestReaders.slice(0); + const readers = this._rangeRequestReaders.slice(0); readers.forEach(function(reader) { reader.cancel(reason); }); } } +/** @implements {IPDFStreamReader} */ class PDFFetchStreamReader { constructor(stream) { this._stream = stream; this._reader = null; this._loaded = 0; this._filename = null; - let source = stream.source; - this._withCredentials = source.withCredentials; + const source = stream.source; + this._withCredentials = source.withCredentials || false; this._contentLength = source.length; this._headersCapability = createPromiseCapability(); this._disableRange = source.disableRange || false; @@ -95,15 +98,15 @@ class PDFFetchStreamReader { this._isRangeSupported = !source.disableRange; this._headers = new Headers(); - for (let property in this._stream.httpHeaders) { - let value = this._stream.httpHeaders[property]; + for (const property in this._stream.httpHeaders) { + const value = this._stream.httpHeaders[property]; if (typeof value === 'undefined') { continue; } this._headers.append(property, value); } - let url = source.url; + const url = source.url; fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then((response) => { if (!validateResponseStatus(response.status)) { @@ -115,7 +118,7 @@ class PDFFetchStreamReader { const getResponseHeader = (name) => { return response.headers.get(name); }; - let { allowRangeRequests, suggestedLength, } = + const { allowRangeRequests, suggestedLength, } = validateRangeRequestCapabilities({ getResponseHeader, isHttp: this._stream.isHttp, @@ -132,7 +135,7 @@ class PDFFetchStreamReader { // We need to stop reading when range is supported and streaming is // disabled. if (!this._isStreamingSupported && this._isRangeSupported) { - this.cancel(new AbortException('streaming is disabled')); + this.cancel(new AbortException('Streaming is disabled.')); } }).catch(this._headersCapability.reject); @@ -172,7 +175,7 @@ class PDFFetchStreamReader { total: this._contentLength, }); } - let buffer = new Uint8Array(value).buffer; + const buffer = new Uint8Array(value).buffer; return { value: buffer, done: false, }; } @@ -186,13 +189,14 @@ class PDFFetchStreamReader { } } +/** @implements {IPDFStreamRangeReader} */ class PDFFetchStreamRangeReader { constructor(stream, begin, end) { this._stream = stream; this._reader = null; this._loaded = 0; - let source = stream.source; - this._withCredentials = source.withCredentials; + const source = stream.source; + this._withCredentials = source.withCredentials || false; this._readCapability = createPromiseCapability(); this._isStreamingSupported = !source.disableStream; @@ -201,17 +205,16 @@ class PDFFetchStreamRangeReader { } this._headers = new Headers(); - for (let property in this._stream.httpHeaders) { - let value = this._stream.httpHeaders[property]; + for (const property in this._stream.httpHeaders) { + const value = this._stream.httpHeaders[property]; if (typeof value === 'undefined') { continue; } this._headers.append(property, value); } + this._headers.append('Range', `bytes=${begin}-${end - 1}`); - let rangeStr = begin + '-' + (end - 1); - this._headers.append('Range', 'bytes=' + rangeStr); - let url = source.url; + const url = source.url; fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then((response) => { if (!validateResponseStatus(response.status)) { @@ -238,7 +241,7 @@ class PDFFetchStreamRangeReader { if (this.onProgress) { this.onProgress({ loaded: this._loaded, }); } - let buffer = new Uint8Array(value).buffer; + const buffer = new Uint8Array(value).buffer; return { value: buffer, done: false, }; } diff --git a/src/display/network.js b/src/display/network.js index 1f2dc8a80..8cc6b693b 100644 --- a/src/display/network.js +++ b/src/display/network.js @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* eslint no-var: error */ import { assert, createPromiseCapability, stringToBytes } from '../shared/util'; import { @@ -24,71 +25,70 @@ if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('FIREFOX || MOZCENTRAL')) { 'be used with FIREFOX or MOZCENTRAL build.'); } -var OK_RESPONSE = 200; -var PARTIAL_CONTENT_RESPONSE = 206; - -function NetworkManager(url, args) { - this.url = url; - args = args || {}; - this.isHttp = /^https?:/i.test(url); - this.httpHeaders = (this.isHttp && args.httpHeaders) || {}; - this.withCredentials = args.withCredentials || false; - this.getXhr = args.getXhr || - function NetworkManager_getXhr() { - return new XMLHttpRequest(); - }; - - this.currXhrId = 0; - this.pendingRequests = Object.create(null); -} +const OK_RESPONSE = 200; +const PARTIAL_CONTENT_RESPONSE = 206; function getArrayBuffer(xhr) { - var data = xhr.response; + const data = xhr.response; if (typeof data !== 'string') { return data; } - let array = stringToBytes(data); + const array = stringToBytes(data); return array.buffer; } -NetworkManager.prototype = { - requestRange: function NetworkManager_requestRange(begin, end, listeners) { - var args = { +class NetworkManager { + constructor(url, args) { + this.url = url; + args = args || {}; + this.isHttp = /^https?:/i.test(url); + this.httpHeaders = (this.isHttp && args.httpHeaders) || {}; + this.withCredentials = args.withCredentials || false; + this.getXhr = args.getXhr || + function NetworkManager_getXhr() { + return new XMLHttpRequest(); + }; + + this.currXhrId = 0; + this.pendingRequests = Object.create(null); + } + + requestRange(begin, end, listeners) { + const args = { begin, end, }; - for (var prop in listeners) { + for (const prop in listeners) { args[prop] = listeners[prop]; } return this.request(args); - }, + } - requestFull: function NetworkManager_requestFull(listeners) { + requestFull(listeners) { return this.request(listeners); - }, + } - request: function NetworkManager_request(args) { - var xhr = this.getXhr(); - var xhrId = this.currXhrId++; - var pendingRequest = this.pendingRequests[xhrId] = { + request(args) { + const xhr = this.getXhr(); + const xhrId = this.currXhrId++; + const pendingRequest = this.pendingRequests[xhrId] = { xhr, }; xhr.open('GET', this.url); xhr.withCredentials = this.withCredentials; - for (var property in this.httpHeaders) { - var value = this.httpHeaders[property]; + for (const property in this.httpHeaders) { + const value = this.httpHeaders[property]; if (typeof value === 'undefined') { continue; } xhr.setRequestHeader(property, value); } if (this.isHttp && 'begin' in args && 'end' in args) { - var rangeStr = args.begin + '-' + (args.end - 1); - xhr.setRequestHeader('Range', 'bytes=' + rangeStr); - pendingRequest.expectedStatus = 206; + xhr.setRequestHeader('Range', `bytes=${args.begin}-${args.end - 1}`); + pendingRequest.expectedStatus = PARTIAL_CONTENT_RESPONSE; } else { - pendingRequest.expectedStatus = 200; + pendingRequest.expectedStatus = OK_RESPONSE; } xhr.responseType = 'arraybuffer'; @@ -108,10 +108,10 @@ NetworkManager.prototype = { xhr.send(null); return xhrId; - }, + } - onProgress: function NetworkManager_onProgress(xhrId, evt) { - var pendingRequest = this.pendingRequests[xhrId]; + onProgress(xhrId, evt) { + const pendingRequest = this.pendingRequests[xhrId]; if (!pendingRequest) { // Maybe abortRequest was called... return; @@ -120,16 +120,16 @@ NetworkManager.prototype = { if (pendingRequest.onProgress) { pendingRequest.onProgress(evt); } - }, + } - onStateChange: function NetworkManager_onStateChange(xhrId, evt) { - var pendingRequest = this.pendingRequests[xhrId]; + onStateChange(xhrId, evt) { + const pendingRequest = this.pendingRequests[xhrId]; if (!pendingRequest) { // Maybe abortRequest was called... return; } - var xhr = pendingRequest.xhr; + const xhr = pendingRequest.xhr; if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) { pendingRequest.onHeadersReceived(); delete pendingRequest.onHeadersReceived; @@ -141,27 +141,27 @@ NetworkManager.prototype = { if (!(xhrId in this.pendingRequests)) { // The XHR request might have been aborted in onHeadersReceived() - // callback, in which case we should abort request + // callback, in which case we should abort request. return; } delete this.pendingRequests[xhrId]; - // success status == 0 can be on ftp, file and other protocols + // Success status == 0 can be on ftp, file and other protocols. if (xhr.status === 0 && this.isHttp) { if (pendingRequest.onError) { pendingRequest.onError(xhr.status); } return; } - var xhrStatus = xhr.status || OK_RESPONSE; + const xhrStatus = xhr.status || OK_RESPONSE; // From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2: // "A server MAY ignore the Range header". This means it's possible to // get a 200 rather than a 206 response from a range request. - var ok_response_on_range_request = - xhrStatus === OK_RESPONSE && - pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE; + const ok_response_on_range_request = + xhrStatus === OK_RESPONSE && + pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE; if (!ok_response_on_range_request && xhrStatus !== pendingRequest.expectedStatus) { @@ -171,13 +171,12 @@ NetworkManager.prototype = { return; } - var chunk = getArrayBuffer(xhr); + const chunk = getArrayBuffer(xhr); if (xhrStatus === PARTIAL_CONTENT_RESPONSE) { - var rangeHeader = xhr.getResponseHeader('Content-Range'); - var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader); - var begin = parseInt(matches[1], 10); + const rangeHeader = xhr.getResponseHeader('Content-Range'); + const matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader); pendingRequest.onDone({ - begin, + begin: parseInt(matches[1], 10), chunk, }); } else if (chunk) { @@ -188,125 +187,123 @@ NetworkManager.prototype = { } else if (pendingRequest.onError) { pendingRequest.onError(xhr.status); } - }, + } - hasPendingRequests: function NetworkManager_hasPendingRequests() { - for (var xhrId in this.pendingRequests) { + hasPendingRequests() { + for (const xhrId in this.pendingRequests) { return true; } return false; - }, + } - getRequestXhr: function NetworkManager_getXhr(xhrId) { + getRequestXhr(xhrId) { return this.pendingRequests[xhrId].xhr; - }, + } - isPendingRequest: function NetworkManager_isPendingRequest(xhrId) { + isPendingRequest(xhrId) { return xhrId in this.pendingRequests; - }, + } - abortAllRequests: function NetworkManager_abortAllRequests() { - for (var xhrId in this.pendingRequests) { + abortAllRequests() { + for (const xhrId in this.pendingRequests) { this.abortRequest(xhrId | 0); } - }, + } - abortRequest: function NetworkManager_abortRequest(xhrId) { - var xhr = this.pendingRequests[xhrId].xhr; + abortRequest(xhrId) { + const xhr = this.pendingRequests[xhrId].xhr; delete this.pendingRequests[xhrId]; xhr.abort(); - }, -}; - -/** @implements {IPDFStream} */ -function PDFNetworkStream(source) { - this._source = source; - this._manager = new NetworkManager(source.url, { - httpHeaders: source.httpHeaders, - withCredentials: source.withCredentials, - }); - this._rangeChunkSize = source.rangeChunkSize; - this._fullRequestReader = null; - this._rangeRequestReaders = []; + } } -PDFNetworkStream.prototype = { - _onRangeRequestReaderClosed: - function PDFNetworkStream_onRangeRequestReaderClosed(reader) { - var i = this._rangeRequestReaders.indexOf(reader); +/** @implements {IPDFStream} */ +class PDFNetworkStream { + constructor(source) { + this._source = source; + this._manager = new NetworkManager(source.url, { + httpHeaders: source.httpHeaders, + withCredentials: source.withCredentials, + }); + this._rangeChunkSize = source.rangeChunkSize; + this._fullRequestReader = null; + this._rangeRequestReaders = []; + } + + _onRangeRequestReaderClosed(reader) { + const i = this._rangeRequestReaders.indexOf(reader); if (i >= 0) { this._rangeRequestReaders.splice(i, 1); } - }, + } - getFullReader: function PDFNetworkStream_getFullReader() { + getFullReader() { assert(!this._fullRequestReader); this._fullRequestReader = new PDFNetworkStreamFullRequestReader(this._manager, this._source); return this._fullRequestReader; - }, + } - getRangeReader: function PDFNetworkStream_getRangeReader(begin, end) { - var reader = new PDFNetworkStreamRangeRequestReader(this._manager, - begin, end); + getRangeReader(begin, end) { + const reader = new PDFNetworkStreamRangeRequestReader(this._manager, + begin, end); reader.onClosed = this._onRangeRequestReaderClosed.bind(this); this._rangeRequestReaders.push(reader); return reader; - }, + } - cancelAllRequests: function PDFNetworkStream_cancelAllRequests(reason) { + cancelAllRequests(reason) { if (this._fullRequestReader) { this._fullRequestReader.cancel(reason); } - var readers = this._rangeRequestReaders.slice(0); - readers.forEach(function (reader) { + const readers = this._rangeRequestReaders.slice(0); + readers.forEach(function(reader) { reader.cancel(reason); }); - }, -}; - -/** @implements {IPDFStreamReader} */ -function PDFNetworkStreamFullRequestReader(manager, source) { - this._manager = manager; - - var args = { - onHeadersReceived: this._onHeadersReceived.bind(this), - onDone: this._onDone.bind(this), - onError: this._onError.bind(this), - onProgress: this._onProgress.bind(this), - }; - this._url = source.url; - this._fullRequestId = manager.requestFull(args); - this._headersReceivedCapability = createPromiseCapability(); - this._disableRange = source.disableRange || false; - this._contentLength = source.length; // optional - this._rangeChunkSize = source.rangeChunkSize; - if (!this._rangeChunkSize && !this._disableRange) { - this._disableRange = true; } - - this._isStreamingSupported = false; - this._isRangeSupported = false; - - this._cachedChunks = []; - this._requests = []; - this._done = false; - this._storedError = undefined; - this._filename = null; - - this.onProgress = null; } -PDFNetworkStreamFullRequestReader.prototype = { - _onHeadersReceived: - function PDFNetworkStreamFullRequestReader_onHeadersReceived() { - var fullRequestXhrId = this._fullRequestId; - var fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId); +/** @implements {IPDFStreamReader} */ +class PDFNetworkStreamFullRequestReader { + constructor(manager, source) { + this._manager = manager; + + const args = { + onHeadersReceived: this._onHeadersReceived.bind(this), + onDone: this._onDone.bind(this), + onError: this._onError.bind(this), + onProgress: this._onProgress.bind(this), + }; + this._url = source.url; + this._fullRequestId = manager.requestFull(args); + this._headersReceivedCapability = createPromiseCapability(); + this._disableRange = source.disableRange || false; + this._contentLength = source.length; // Optional + this._rangeChunkSize = source.rangeChunkSize; + if (!this._rangeChunkSize && !this._disableRange) { + this._disableRange = true; + } + + this._isStreamingSupported = false; + this._isRangeSupported = false; + + this._cachedChunks = []; + this._requests = []; + this._done = false; + this._storedError = undefined; + this._filename = null; + + this.onProgress = null; + } + + _onHeadersReceived() { + const fullRequestXhrId = this._fullRequestId; + const fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId); const getResponseHeader = (name) => { return fullRequestXhr.getResponseHeader(name); }; - let { allowRangeRequests, suggestedLength, } = + const { allowRangeRequests, suggestedLength, } = validateRangeRequestCapabilities({ getResponseHeader, isHttp: this._manager.isHttp, @@ -331,12 +328,12 @@ PDFNetworkStreamFullRequestReader.prototype = { } this._headersReceivedCapability.resolve(); - }, + } - _onDone: function PDFNetworkStreamFullRequestReader_onDone(args) { + _onDone(args) { if (args) { if (this._requests.length > 0) { - var requestCapability = this._requests.shift(); + const requestCapability = this._requests.shift(); requestCapability.resolve({ value: args.chunk, done: false, }); } else { this._cachedChunks.push(args.chunk); @@ -346,70 +343,70 @@ PDFNetworkStreamFullRequestReader.prototype = { if (this._cachedChunks.length > 0) { return; } - this._requests.forEach(function (requestCapability) { + this._requests.forEach(function(requestCapability) { requestCapability.resolve({ value: undefined, done: true, }); }); this._requests = []; - }, + } - _onError: function PDFNetworkStreamFullRequestReader_onError(status) { - var url = this._url; - var exception = createResponseStatusError(status, url); + _onError(status) { + const url = this._url; + const exception = createResponseStatusError(status, url); this._storedError = exception; this._headersReceivedCapability.reject(exception); - this._requests.forEach(function (requestCapability) { + this._requests.forEach(function(requestCapability) { requestCapability.reject(exception); }); this._requests = []; this._cachedChunks = []; - }, + } - _onProgress: function PDFNetworkStreamFullRequestReader_onProgress(data) { + _onProgress(data) { if (this.onProgress) { this.onProgress({ loaded: data.loaded, total: data.lengthComputable ? data.total : this._contentLength, }); } - }, + } get filename() { return this._filename; - }, + } get isRangeSupported() { return this._isRangeSupported; - }, + } get isStreamingSupported() { return this._isStreamingSupported; - }, + } get contentLength() { return this._contentLength; - }, + } get headersReady() { return this._headersReceivedCapability.promise; - }, + } async read() { if (this._storedError) { throw this._storedError; } if (this._cachedChunks.length > 0) { - var chunk = this._cachedChunks.shift(); + const chunk = this._cachedChunks.shift(); return { value: chunk, done: false, }; } if (this._done) { return { value: undefined, done: true, }; } - var requestCapability = createPromiseCapability(); + const requestCapability = createPromiseCapability(); this._requests.push(requestCapability); return requestCapability.promise; - }, + } - cancel: function PDFNetworkStreamFullRequestReader_cancel(reason) { + cancel(reason) { this._done = true; this._headersReceivedCapability.reject(reason); this._requests.forEach(function (requestCapability) { @@ -420,75 +417,75 @@ PDFNetworkStreamFullRequestReader.prototype = { this._manager.abortRequest(this._fullRequestId); } this._fullRequestReader = null; - }, -}; - -/** @implements {IPDFStreamRangeReader} */ -function PDFNetworkStreamRangeRequestReader(manager, begin, end) { - this._manager = manager; - var args = { - onDone: this._onDone.bind(this), - onProgress: this._onProgress.bind(this), - }; - this._requestId = manager.requestRange(begin, end, args); - this._requests = []; - this._queuedChunk = null; - this._done = false; - - this.onProgress = null; - this.onClosed = null; + } } -PDFNetworkStreamRangeRequestReader.prototype = { - _close: function PDFNetworkStreamRangeRequestReader_close() { +/** @implements {IPDFStreamRangeReader} */ +class PDFNetworkStreamRangeRequestReader { + constructor(manager, begin, end) { + this._manager = manager; + const args = { + onDone: this._onDone.bind(this), + onProgress: this._onProgress.bind(this), + }; + this._requestId = manager.requestRange(begin, end, args); + this._requests = []; + this._queuedChunk = null; + this._done = false; + + this.onProgress = null; + this.onClosed = null; + } + + _close() { if (this.onClosed) { this.onClosed(this); } - }, + } - _onDone: function PDFNetworkStreamRangeRequestReader_onDone(data) { - var chunk = data.chunk; + _onDone(data) { + const chunk = data.chunk; if (this._requests.length > 0) { - var requestCapability = this._requests.shift(); + const requestCapability = this._requests.shift(); requestCapability.resolve({ value: chunk, done: false, }); } else { this._queuedChunk = chunk; } this._done = true; - this._requests.forEach(function (requestCapability) { + this._requests.forEach(function(requestCapability) { requestCapability.resolve({ value: undefined, done: true, }); }); this._requests = []; this._close(); - }, + } - _onProgress: function PDFNetworkStreamRangeRequestReader_onProgress(evt) { + _onProgress(evt) { if (!this.isStreamingSupported && this.onProgress) { this.onProgress({ loaded: evt.loaded, }); } - }, + } get isStreamingSupported() { - return false; // TODO allow progressive range bytes loading - }, + return false; + } async read() { if (this._queuedChunk !== null) { - var chunk = this._queuedChunk; + const chunk = this._queuedChunk; this._queuedChunk = null; return { value: chunk, done: false, }; } if (this._done) { return { value: undefined, done: true, }; } - var requestCapability = createPromiseCapability(); + const requestCapability = createPromiseCapability(); this._requests.push(requestCapability); return requestCapability.promise; - }, + } - cancel: function PDFNetworkStreamRangeRequestReader_cancel(reason) { + cancel(reason) { this._done = true; this._requests.forEach(function (requestCapability) { requestCapability.resolve({ value: undefined, done: true, }); @@ -498,10 +495,9 @@ PDFNetworkStreamRangeRequestReader.prototype = { this._manager.abortRequest(this._requestId); } this._close(); - }, -}; + } +} export { PDFNetworkStream, - NetworkManager, }; diff --git a/src/display/transport_stream.js b/src/display/transport_stream.js index 32d916307..04b7a7c70 100644 --- a/src/display/transport_stream.js +++ b/src/display/transport_stream.js @@ -12,12 +12,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* eslint no-var: error */ import { assert, createPromiseCapability } from '../shared/util'; - /** @implements {IPDFStream} */ -var PDFDataTransportStream = (function PDFDataTransportStreamClosure() { - function PDFDataTransportStream(params, pdfDataRangeTransport) { +/** @implements {IPDFStream} */ +class PDFDataTransportStream { + constructor(params, pdfDataRangeTransport) { assert(pdfDataRangeTransport); this._queuedChunks = []; @@ -25,7 +26,7 @@ var PDFDataTransportStream = (function PDFDataTransportStreamClosure() { const initialData = params.initialData; if (initialData && initialData.length > 0) { - let buffer = new Uint8Array(initialData).buffer; + const buffer = new Uint8Array(initialData).buffer; this._queuedChunks.push(buffer); } @@ -55,95 +56,93 @@ var PDFDataTransportStream = (function PDFDataTransportStreamClosure() { this._pdfDataRangeTransport.transportReady(); } - PDFDataTransportStream.prototype = { - _onReceiveData: function PDFDataTransportStream_onReceiveData(args) { - let buffer = new Uint8Array(args.chunk).buffer; - if (args.begin === undefined) { - if (this._fullRequestReader) { - this._fullRequestReader._enqueue(buffer); - } else { - this._queuedChunks.push(buffer); - } - } else { - var found = this._rangeReaders.some(function (rangeReader) { - if (rangeReader._begin !== args.begin) { - return false; - } - rangeReader._enqueue(buffer); - return true; - }); - assert(found); - } - }, - get _progressiveDataLength() { - return (this._fullRequestReader ? this._fullRequestReader._loaded : 0); - }, - - _onProgress: function PDFDataTransportStream_onDataProgress(evt) { - if (evt.total === undefined) { - // Reporting to first range reader, if it exists. - let firstReader = this._rangeReaders[0]; - if (firstReader && firstReader.onProgress) { - firstReader.onProgress({ loaded: evt.loaded, }); - } + _onReceiveData(args) { + const buffer = new Uint8Array(args.chunk).buffer; + if (args.begin === undefined) { + if (this._fullRequestReader) { + this._fullRequestReader._enqueue(buffer); } else { - let fullReader = this._fullRequestReader; - if (fullReader && fullReader.onProgress) { - fullReader.onProgress({ loaded: evt.loaded, total: evt.total, }); + this._queuedChunks.push(buffer); + } + } else { + const found = this._rangeReaders.some(function(rangeReader) { + if (rangeReader._begin !== args.begin) { + return false; } - } - }, - - _onProgressiveDone() { - if (this._fullRequestReader) { - this._fullRequestReader.progressiveDone(); - } - this._progressiveDone = true; - }, - - _removeRangeReader: - function PDFDataTransportStream_removeRangeReader(reader) { - var i = this._rangeReaders.indexOf(reader); - if (i >= 0) { - this._rangeReaders.splice(i, 1); - } - }, - - getFullReader: function PDFDataTransportStream_getFullReader() { - assert(!this._fullRequestReader); - var queuedChunks = this._queuedChunks; - this._queuedChunks = null; - return new PDFDataTransportStreamReader(this, queuedChunks, - this._progressiveDone); - }, - - 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); - return reader; - }, - - cancelAllRequests: - function PDFDataTransportStream_cancelAllRequests(reason) { - if (this._fullRequestReader) { - this._fullRequestReader.cancel(reason); - } - var readers = this._rangeReaders.slice(0); - readers.forEach(function (rangeReader) { - rangeReader.cancel(reason); + rangeReader._enqueue(buffer); + return true; }); - this._pdfDataRangeTransport.abort(); - }, - }; + assert(found); + } + } - /** @implements {IPDFStreamReader} */ - function PDFDataTransportStreamReader(stream, queuedChunks, - progressiveDone = false) { + get _progressiveDataLength() { + return (this._fullRequestReader ? this._fullRequestReader._loaded : 0); + } + + _onProgress(evt) { + if (evt.total === undefined) { + // Reporting to first range reader, if it exists. + const firstReader = this._rangeReaders[0]; + if (firstReader && firstReader.onProgress) { + firstReader.onProgress({ loaded: evt.loaded, }); + } + } else { + const fullReader = this._fullRequestReader; + if (fullReader && fullReader.onProgress) { + fullReader.onProgress({ loaded: evt.loaded, total: evt.total, }); + } + } + } + + _onProgressiveDone() { + if (this._fullRequestReader) { + this._fullRequestReader.progressiveDone(); + } + this._progressiveDone = true; + } + + _removeRangeReader(reader) { + const i = this._rangeReaders.indexOf(reader); + if (i >= 0) { + this._rangeReaders.splice(i, 1); + } + } + + getFullReader() { + assert(!this._fullRequestReader); + const queuedChunks = this._queuedChunks; + this._queuedChunks = null; + return new PDFDataTransportStreamReader(this, queuedChunks, + this._progressiveDone); + } + + getRangeReader(begin, end) { + if (end <= this._progressiveDataLength) { + return null; + } + const reader = new PDFDataTransportStreamRangeReader(this, begin, end); + this._pdfDataRangeTransport.requestDataRange(begin, end); + this._rangeReaders.push(reader); + return reader; + } + + cancelAllRequests(reason) { + if (this._fullRequestReader) { + this._fullRequestReader.cancel(reason); + } + const readers = this._rangeReaders.slice(0); + readers.forEach(function(rangeReader) { + rangeReader.cancel(reason); + }); + this._pdfDataRangeTransport.abort(); + } +} + +/** @implements {IPDFStreamReader} */ +class PDFDataTransportStreamReader { + constructor(stream, queuedChunks, progressiveDone = false) { this._stream = stream; this._done = progressiveDone || false; this._filename = null; @@ -156,73 +155,74 @@ var PDFDataTransportStream = (function PDFDataTransportStreamClosure() { this._headersReady = Promise.resolve(); stream._fullRequestReader = this; - this.onProgress = null; // not used + this.onProgress = null; } - PDFDataTransportStreamReader.prototype = { - _enqueue: function PDFDataTransportStreamReader_enqueue(chunk) { - if (this._done) { - return; // ignore new data - } - if (this._requests.length > 0) { - var requestCapability = this._requests.shift(); - requestCapability.resolve({ value: chunk, done: false, }); - } else { - this._queuedChunks.push(chunk); - } - this._loaded += chunk.byteLength; - }, - get headersReady() { - return this._headersReady; - }, + _enqueue(chunk) { + if (this._done) { + return; // Ignore new data. + } + if (this._requests.length > 0) { + const requestCapability = this._requests.shift(); + requestCapability.resolve({ value: chunk, done: false, }); + } else { + this._queuedChunks.push(chunk); + } + this._loaded += chunk.byteLength; + } - get filename() { - return this._filename; - }, + get headersReady() { + return this._headersReady; + } - get isRangeSupported() { - return this._stream._isRangeSupported; - }, + get filename() { + return this._filename; + } - get isStreamingSupported() { - return this._stream._isStreamingSupported; - }, + get isRangeSupported() { + return this._stream._isRangeSupported; + } - get contentLength() { - return this._stream._contentLength; - }, + get isStreamingSupported() { + return this._stream._isStreamingSupported; + } - async read() { - if (this._queuedChunks.length > 0) { - var chunk = this._queuedChunks.shift(); - return { value: chunk, done: false, }; - } - if (this._done) { - return { value: undefined, done: true, }; - } - var requestCapability = createPromiseCapability(); - this._requests.push(requestCapability); - return requestCapability.promise; - }, + get contentLength() { + return this._stream._contentLength; + } - cancel: function PDFDataTransportStreamReader_cancel(reason) { - this._done = true; - this._requests.forEach(function (requestCapability) { - requestCapability.resolve({ value: undefined, done: true, }); - }); - this._requests = []; - }, + async read() { + if (this._queuedChunks.length > 0) { + const chunk = this._queuedChunks.shift(); + return { value: chunk, done: false, }; + } + if (this._done) { + return { value: undefined, done: true, }; + } + const requestCapability = createPromiseCapability(); + this._requests.push(requestCapability); + return requestCapability.promise; + } - progressiveDone() { - if (this._done) { - return; - } - this._done = true; - }, - }; + cancel(reason) { + this._done = true; + this._requests.forEach(function(requestCapability) { + requestCapability.resolve({ value: undefined, done: true, }); + }); + this._requests = []; + } - /** @implements {IPDFStreamRangeReader} */ - function PDFDataTransportStreamRangeReader(stream, begin, end) { + progressiveDone() { + if (this._done) { + return; + } + this._done = true; + } +} + +/** @implements {IPDFStreamRangeReader} */ +class PDFDataTransportStreamRangeReader { + constructor(stream, begin, end) { this._stream = stream; this._begin = begin; this._end = end; @@ -232,55 +232,52 @@ var PDFDataTransportStream = (function PDFDataTransportStreamClosure() { this.onProgress = null; } - PDFDataTransportStreamRangeReader.prototype = { - _enqueue: function PDFDataTransportStreamRangeReader_enqueue(chunk) { - if (this._done) { - return; // ignore new data - } - if (this._requests.length === 0) { - this._queuedChunk = chunk; - } else { - var requestsCapability = this._requests.shift(); - requestsCapability.resolve({ value: chunk, done: false, }); - this._requests.forEach(function (requestCapability) { - requestCapability.resolve({ value: undefined, done: true, }); - }); - this._requests = []; - } - this._done = true; - this._stream._removeRangeReader(this); - }, - get isStreamingSupported() { - return false; - }, - - async read() { - if (this._queuedChunk) { - let chunk = this._queuedChunk; - this._queuedChunk = null; - return { value: chunk, done: false, }; - } - if (this._done) { - return { value: undefined, done: true, }; - } - var requestCapability = createPromiseCapability(); - this._requests.push(requestCapability); - return requestCapability.promise; - }, - - cancel: function PDFDataTransportStreamRangeReader_cancel(reason) { - this._done = true; - this._requests.forEach(function (requestCapability) { + _enqueue(chunk) { + if (this._done) { + return; // ignore new data + } + if (this._requests.length === 0) { + this._queuedChunk = chunk; + } else { + const requestsCapability = this._requests.shift(); + requestsCapability.resolve({ value: chunk, done: false, }); + this._requests.forEach(function(requestCapability) { requestCapability.resolve({ value: undefined, done: true, }); }); this._requests = []; - this._stream._removeRangeReader(this); - }, - }; + } + this._done = true; + this._stream._removeRangeReader(this); + } - return PDFDataTransportStream; -})(); + get isStreamingSupported() { + return false; + } + + async read() { + if (this._queuedChunk) { + const chunk = this._queuedChunk; + this._queuedChunk = null; + return { value: chunk, done: false, }; + } + if (this._done) { + return { value: undefined, done: true, }; + } + const requestCapability = createPromiseCapability(); + this._requests.push(requestCapability); + return requestCapability.promise; + } + + cancel(reason) { + this._done = true; + this._requests.forEach(function(requestCapability) { + requestCapability.resolve({ value: undefined, done: true, }); + }); + this._requests = []; + this._stream._removeRangeReader(this); + } +} export { PDFDataTransportStream,