Skip to content

Commit 8593c31

Browse files
authored
Fix null XHR response handling (#6842)
* Prevent Inivalid State exception thrown by reading xhr.responseText when xhr.response is null and responseType is not text or empty
1 parent 4b61208 commit 8593c31

File tree

1 file changed

+52
-49
lines changed

1 file changed

+52
-49
lines changed

src/utils/xhr-loader.ts

Lines changed: 52 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -204,59 +204,62 @@ class XhrLoader implements Loader<LoaderContext> {
204204
xhr.onprogress = null;
205205
const status = xhr.status;
206206
// http status between 200 to 299 are all successful
207-
const useResponse = xhr.responseType !== 'text';
208-
if (
209-
status >= 200 &&
210-
status < 300 &&
211-
((useResponse && xhr.response) || xhr.responseText !== null)
212-
) {
213-
stats.loading.end = Math.max(
214-
self.performance.now(),
215-
stats.loading.first,
216-
);
217-
const data = useResponse ? xhr.response : xhr.responseText;
218-
const len =
219-
xhr.responseType === 'arraybuffer' ? data.byteLength : data.length;
220-
stats.loaded = stats.total = len;
221-
stats.bwEstimate =
222-
(stats.total * 8000) / (stats.loading.end - stats.loading.first);
223-
if (!this.callbacks) {
224-
return;
225-
}
226-
const onProgress = this.callbacks.onProgress;
227-
if (onProgress) {
228-
onProgress(stats, context, data, xhr);
229-
}
230-
if (!this.callbacks) {
207+
const useResponseText =
208+
xhr.responseType === 'text' ? xhr.responseText : null;
209+
if (status >= 200 && status < 300) {
210+
const data = useResponseText ?? xhr.response;
211+
if (data != null) {
212+
stats.loading.end = Math.max(
213+
self.performance.now(),
214+
stats.loading.first,
215+
);
216+
const len =
217+
xhr.responseType === 'arraybuffer'
218+
? data.byteLength
219+
: data.length;
220+
stats.loaded = stats.total = len;
221+
stats.bwEstimate =
222+
(stats.total * 8000) / (stats.loading.end - stats.loading.first);
223+
if (!this.callbacks) {
224+
return;
225+
}
226+
const onProgress = this.callbacks.onProgress;
227+
if (onProgress) {
228+
onProgress(stats, context, data, xhr);
229+
}
230+
if (!this.callbacks) {
231+
return;
232+
}
233+
const response: LoaderResponse = {
234+
url: xhr.responseURL,
235+
data: data,
236+
code: status,
237+
};
238+
239+
this.callbacks.onSuccess(response, stats, context, xhr);
231240
return;
232241
}
233-
const response: LoaderResponse = {
234-
url: xhr.responseURL,
235-
data: data,
236-
code: status,
237-
};
242+
}
238243

239-
this.callbacks.onSuccess(response, stats, context, xhr);
244+
// Handle bad status or nullish response
245+
const retryConfig = config.loadPolicy.errorRetry;
246+
const retryCount = stats.retry;
247+
// if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error
248+
const response: LoaderResponse = {
249+
url: context.url,
250+
data: undefined,
251+
code: status,
252+
};
253+
if (shouldRetry(retryConfig, retryCount, false, response)) {
254+
this.retry(retryConfig);
240255
} else {
241-
const retryConfig = config.loadPolicy.errorRetry;
242-
const retryCount = stats.retry;
243-
// if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error
244-
const response: LoaderResponse = {
245-
url: context.url,
246-
data: undefined,
247-
code: status,
248-
};
249-
if (shouldRetry(retryConfig, retryCount, false, response)) {
250-
this.retry(retryConfig);
251-
} else {
252-
logger.error(`${status} while loading ${context.url}`);
253-
this.callbacks!.onError(
254-
{ code: status, text: xhr.statusText },
255-
context,
256-
xhr,
257-
stats,
258-
);
259-
}
256+
logger.error(`${status} while loading ${context.url}`);
257+
this.callbacks!.onError(
258+
{ code: status, text: xhr.statusText },
259+
context,
260+
xhr,
261+
stats,
262+
);
260263
}
261264
}
262265
}

0 commit comments

Comments
 (0)