Merge pull request #13945 from Snuffleupagus/network-onError

Implement `PDFNetworkStreamRangeRequestReader._onError`, to handle range request errors with XMLHttpRequest (issue 9883)
This commit is contained in:
Tim van der Meij 2021-09-01 21:18:07 +02:00 committed by GitHub
commit 2ed133bd99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -43,11 +43,10 @@ function getArrayBuffer(xhr) {
} }
class NetworkManager { class NetworkManager {
constructor(url, args) { constructor(url, args = {}) {
this.url = url; this.url = url;
args = args || {};
this.isHttp = /^https?:/i.test(url); this.isHttp = /^https?:/i.test(url);
this.httpHeaders = (this.isHttp && args.httpHeaders) || {}; this.httpHeaders = (this.isHttp && args.httpHeaders) || Object.create(null);
this.withCredentials = args.withCredentials || false; this.withCredentials = args.withCredentials || false;
this.getXhr = this.getXhr =
args.getXhr || args.getXhr ||
@ -77,9 +76,7 @@ class NetworkManager {
request(args) { request(args) {
const xhr = this.getXhr(); const xhr = this.getXhr();
const xhrId = this.currXhrId++; const xhrId = this.currXhrId++;
const pendingRequest = (this.pendingRequests[xhrId] = { const pendingRequest = (this.pendingRequests[xhrId] = { xhr });
xhr,
});
xhr.open("GET", this.url); xhr.open("GET", this.url);
xhr.withCredentials = this.withCredentials; xhr.withCredentials = this.withCredentials;
@ -119,20 +116,15 @@ class NetworkManager {
onProgress(xhrId, evt) { onProgress(xhrId, evt) {
const pendingRequest = this.pendingRequests[xhrId]; const pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) { if (!pendingRequest) {
// Maybe abortRequest was called... return; // Maybe abortRequest was called...
return;
}
if (pendingRequest.onProgress) {
pendingRequest.onProgress(evt);
} }
pendingRequest.onProgress?.(evt);
} }
onStateChange(xhrId, evt) { onStateChange(xhrId, evt) {
const pendingRequest = this.pendingRequests[xhrId]; const pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) { if (!pendingRequest) {
// Maybe abortRequest was called... return; // Maybe abortRequest was called...
return;
} }
const xhr = pendingRequest.xhr; const xhr = pendingRequest.xhr;
@ -155,9 +147,7 @@ class NetworkManager {
// 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 (xhr.status === 0 && this.isHttp) {
if (pendingRequest.onError) { pendingRequest.onError?.(xhr.status);
pendingRequest.onError(xhr.status);
}
return; return;
} }
const xhrStatus = xhr.status || OK_RESPONSE; const xhrStatus = xhr.status || OK_RESPONSE;
@ -173,9 +163,7 @@ class NetworkManager {
!ok_response_on_range_request && !ok_response_on_range_request &&
xhrStatus !== pendingRequest.expectedStatus xhrStatus !== pendingRequest.expectedStatus
) { ) {
if (pendingRequest.onError) { pendingRequest.onError?.(xhr.status);
pendingRequest.onError(xhr.status);
}
return; return;
} }
@ -192,8 +180,8 @@ class NetworkManager {
begin: 0, begin: 0,
chunk, chunk,
}); });
} else if (pendingRequest.onError) { } else {
pendingRequest.onError(xhr.status); pendingRequest.onError?.(xhr.status);
} }
} }
@ -256,9 +244,8 @@ class PDFNetworkStream {
} }
cancelAllRequests(reason) { cancelAllRequests(reason) {
if (this._fullRequestReader) { this._fullRequestReader?.cancel(reason);
this._fullRequestReader.cancel(reason);
}
for (const reader of this._rangeRequestReaders.slice(0)) { for (const reader of this._rangeRequestReaders.slice(0)) {
reader.cancel(reason); reader.cancel(reason);
} }
@ -332,13 +319,13 @@ class PDFNetworkStreamFullRequestReader {
this._headersReceivedCapability.resolve(); this._headersReceivedCapability.resolve();
} }
_onDone(args) { _onDone(data) {
if (args) { if (data) {
if (this._requests.length > 0) { if (this._requests.length > 0) {
const requestCapability = this._requests.shift(); const requestCapability = this._requests.shift();
requestCapability.resolve({ value: args.chunk, done: false }); requestCapability.resolve({ value: data.chunk, done: false });
} else { } else {
this._cachedChunks.push(args.chunk); this._cachedChunks.push(data.chunk);
} }
} }
this._done = true; this._done = true;
@ -352,24 +339,20 @@ class PDFNetworkStreamFullRequestReader {
} }
_onError(status) { _onError(status) {
const url = this._url; this._storedError = createResponseStatusError(status, this._url);
const exception = createResponseStatusError(status, url); this._headersReceivedCapability.reject(this._storedError);
this._storedError = exception;
this._headersReceivedCapability.reject(exception);
for (const requestCapability of this._requests) { for (const requestCapability of this._requests) {
requestCapability.reject(exception); requestCapability.reject(this._storedError);
} }
this._requests.length = 0; this._requests.length = 0;
this._cachedChunks.length = 0; this._cachedChunks.length = 0;
} }
_onProgress(data) { _onProgress(evt) {
if (this.onProgress) { this.onProgress?.({
this.onProgress({ loaded: evt.loaded,
loaded: data.loaded, total: evt.lengthComputable ? evt.total : this._contentLength,
total: data.lengthComputable ? data.total : this._contentLength, });
});
}
} }
get filename() { get filename() {
@ -426,23 +409,25 @@ class PDFNetworkStreamFullRequestReader {
class PDFNetworkStreamRangeRequestReader { class PDFNetworkStreamRangeRequestReader {
constructor(manager, begin, end) { constructor(manager, begin, end) {
this._manager = manager; this._manager = manager;
const args = { const args = {
onDone: this._onDone.bind(this), onDone: this._onDone.bind(this),
onError: this._onError.bind(this),
onProgress: this._onProgress.bind(this), onProgress: this._onProgress.bind(this),
}; };
this._url = manager.url;
this._requestId = manager.requestRange(begin, end, args); this._requestId = manager.requestRange(begin, end, args);
this._requests = []; this._requests = [];
this._queuedChunk = null; this._queuedChunk = null;
this._done = false; this._done = false;
this._storedError = undefined;
this.onProgress = null; this.onProgress = null;
this.onClosed = null; this.onClosed = null;
} }
_close() { _close() {
if (this.onClosed) { this.onClosed?.(this);
this.onClosed(this);
}
} }
_onDone(data) { _onDone(data) {
@ -461,11 +446,18 @@ class PDFNetworkStreamRangeRequestReader {
this._close(); this._close();
} }
_onError(status) {
this._storedError = createResponseStatusError(status, this._url);
for (const requestCapability of this._requests) {
requestCapability.reject(this._storedError);
}
this._requests.length = 0;
this._queuedChunk = null;
}
_onProgress(evt) { _onProgress(evt) {
if (!this.isStreamingSupported && this.onProgress) { if (!this.isStreamingSupported) {
this.onProgress({ this.onProgress?.({ loaded: evt.loaded });
loaded: evt.loaded,
});
} }
} }
@ -474,6 +466,9 @@ class PDFNetworkStreamRangeRequestReader {
} }
async read() { async read() {
if (this._storedError) {
throw this._storedError;
}
if (this._queuedChunk !== null) { if (this._queuedChunk !== null) {
const chunk = this._queuedChunk; const chunk = this._queuedChunk;
this._queuedChunk = null; this._queuedChunk = null;