iOS Safari XHR has gone deaf;

workaround for iPhone bug in
iOS 18.6.2, 26.6, 26.6.1, ...

safari devtools has the full response,
it just never bothers calling xhr.onload
and xhr.readystate is unusably racey
(final value is any of 1..3)
This commit is contained in:
ed
2026-09-02 22:21:07 +00:00
parent f792a9529c
commit 3ea671ff9a
+58 -4
View File
@@ -979,6 +979,7 @@ function up2k_init(subtle) {
"u": 0, "u": 0,
"t": 0 "t": 0
}, },
"xhr": [],
"car": 0, "car": 0,
"nre": 0, "nre": 0,
"slow_io": null, "slow_io": null,
@@ -1913,6 +1914,32 @@ function up2k_init(subtle) {
} }
} }
for (var a = st.xhr.length - 1; a >= 0; a--) {
var xhr = st.xhr[a];
if (!xhr.status || !xhr.responseText)
continue;
if (xhr.is_js)
try {
JSON.parse(xhr.responseText);
}
catch (ex) {
continue;
}
xhr.tdeaf = xhr.tdeaf || now;
if (!st.deaf && now - xhr.tdeaf < 3000)
continue;
if (!st.deaf)
console.log('xhr: bad apple');
xhr.onerror = xhr.ontimeout = null;
xhr.onload();
xhr.abort();
st.deaf = true;
}
if (st.bytes.inflight && (st.bytes.inflight < 0 || !st.busy.upload.length)) { if (st.bytes.inflight && (st.bytes.inflight < 0 || !st.busy.upload.length)) {
console.log('insane inflight ' + st.bytes.inflight); console.log('insane inflight ' + st.bytes.inflight);
st.bytes.inflight = 0; st.bytes.inflight = 0;
@@ -2465,16 +2492,18 @@ function up2k_init(subtle) {
st.busy.head.push(t); st.busy.head.push(t);
var xhr = new XMLHttpRequest(); var xhr = new XHR();
xhr.onerror = xhr.ontimeout = function () { xhr.onerror = xhr.ontimeout = function () {
console.log('head onerror, retrying', t.name, t); console.log('head onerror, retrying', t.name, t);
if (!toast.visible) if (!toast.visible)
toast.warn(9.98, L.u_enethd + "\n\nfile: " + esc(t.name), t); toast.warn(9.98, L.u_enethd + "\n\nfile: " + esc(t.name), t);
apop(st.xhr, xhr);
apop(st.busy.head, t); apop(st.busy.head, t);
st.todo.head.unshift(t); st.todo.head.unshift(t);
}; };
function orz(e) { function orz(e) {
apop(st.xhr, xhr);
if (t.done) if (t.done)
return console.log('done; skip head2', t.name, t); return console.log('done; skip head2', t.name, t);
@@ -2513,6 +2542,7 @@ function up2k_init(subtle) {
xhr.open('HEAD', t.purl + uricom_enc(t.name), true); xhr.open('HEAD', t.purl + uricom_enc(t.name), true);
xhr.timeout = 34000; xhr.timeout = 34000;
xhr.send(); xhr.send();
st.xhr.push(xhr);
} }
///// /////
@@ -2539,8 +2569,9 @@ function up2k_init(subtle) {
if (!t.srch && !t.t_handshake) if (!t.srch && !t.t_handshake)
pvis.seth(t.n, 2, L.u_hs); pvis.seth(t.n, 2, L.u_hs);
var xhr = new XMLHttpRequest(); var xhr = new XHR();
xhr.onerror = xhr.ontimeout = function () { xhr.onerror = xhr.ontimeout = function () {
apop(st.xhr, xhr);
if (t.t_busied != me) // t.done ok if (t.t_busied != me) // t.done ok
return console.log('zombie handshake onerror', t.name, t); return console.log('zombie handshake onerror', t.name, t);
@@ -2553,6 +2584,7 @@ function up2k_init(subtle) {
t.keepalive = keepalive; t.keepalive = keepalive;
}; };
var orz = function (e) { var orz = function (e) {
apop(st.xhr, xhr);
if (t.t_busied != me || t.done) if (t.t_busied != me || t.done)
return console.log('zombie handshake onload', t.name, t); return console.log('zombie handshake onload', t.name, t);
@@ -2838,9 +2870,11 @@ function up2k_init(subtle) {
xhr.open('POST', t.purl, true); xhr.open('POST', t.purl, true);
xhr.responseType = 'text'; xhr.responseType = 'text';
xhr.is_js = true;
xhr.timeout = 42000 + (t.srch || t.t_uploaded ? 0 : xhr.timeout = 42000 + (t.srch || t.t_uploaded ? 0 :
(t.size / (1048 * 20))); // safededup 20M/s hdd (t.size / (1048 * 20))); // safededup 20M/s hdd
xhr.send(JSON.stringify(req)); xhr.send(JSON.stringify(req));
st.xhr.push(xhr);
} }
///// /////
@@ -2929,6 +2963,7 @@ function up2k_init(subtle) {
pcar == pcdr ? pcar : ('' + pcar + '~' + pcdr); pcar == pcdr ? pcar : ('' + pcar + '~' + pcdr);
var orz = function (xhr) { var orz = function (xhr) {
apop(st.xhr, xhr);
st.bytes.inflight -= xhr.bsent; st.bytes.inflight -= xhr.bsent;
var txt = unpre((xhr.response && xhr.response.err) || xhr.responseText); var txt = unpre((xhr.response && xhr.response.err) || xhr.responseText);
if (txt.indexOf('upload blocked by x') + 1) { if (txt.indexOf('upload blocked by x') + 1) {
@@ -2979,6 +3014,7 @@ function up2k_init(subtle) {
orz2(xhr); orz2(xhr);
} }
var orz2 = function (xhr) { var orz2 = function (xhr) {
apop(st.xhr, xhr);
apop(st.busy.upload, upt); apop(st.busy.upload, upt);
for (var a = pcar; a <= pcdr; a++) for (var a = pcar; a <= pcdr; a++)
apop(t.postlist, a); apop(t.postlist, a);
@@ -2992,7 +3028,7 @@ function up2k_init(subtle) {
tasker(); tasker();
} }
function do_send() { function do_send() {
var xhr = new XMLHttpRequest(), var xhr = new XHR(),
bfin = Math.floor(st.bytes.finished / 1024 / 1024), bfin = Math.floor(st.bytes.finished / 1024 / 1024),
btot = Math.floor(st.bytes.total / 1024 / 1024); btot = Math.floor(st.bytes.total / 1024 / 1024);
@@ -3005,8 +3041,13 @@ function up2k_init(subtle) {
st.bytes.inflight += db; st.bytes.inflight += db;
xhr.bsent = nb; xhr.bsent = nb;
var n = 64;
if (nb == xhr.bsize)
n = st.deaf ? 5 : 9;
if (!IE) if (!IE)
xhr.timeout = 64000 + Date.now() - xhr.t0; xhr.timeout = n * 1000 + Date.now() - xhr.t0;
pvis.prog(t, pcar, nb); pvis.prog(t, pcar, nb);
}; };
xhr.onload = function (xev) { xhr.onload = function (xev) {
@@ -3019,6 +3060,9 @@ function up2k_init(subtle) {
st.bytes.inflight -= (xhr.bsent || 0); st.bytes.inflight -= (xhr.bsent || 0);
xhr.bsent = 0; xhr.bsent = 0;
if (st.deaf)
t.cooldown = t.coolmul = 0;
if (!toast.visible) if (!toast.visible)
toast.warn(9.98, L.u_cuerr.format(snpart, Math.ceil(t.size / chunksize), esc(t.name)), t); toast.warn(9.98, L.u_cuerr.format(snpart, Math.ceil(t.size / chunksize), esc(t.name)), t);
@@ -3053,11 +3097,21 @@ function up2k_init(subtle) {
if (xhr.overrideMimeType) if (xhr.overrideMimeType)
xhr.overrideMimeType('Content-Type', 'application/octet-stream'); xhr.overrideMimeType('Content-Type', 'application/octet-stream');
if (st.deaf)
xhr.onreadystatechange = function (xev) {
if (xhr.status == 200) {
xhr.onreadystatechange = null;
xhr.onload(xev);
}
};
xhr.bsent = 0; xhr.bsent = 0;
xhr.bsize = cdr - car;
xhr.t0 = Date.now(); xhr.t0 = Date.now();
xhr.timeout = 1000 * (IE ? 1234 : 42); xhr.timeout = 1000 * (IE ? 1234 : 42);
xhr.responseType = 'text'; xhr.responseType = 'text';
xhr.send(t.fobj.slice(car, cdr)); xhr.send(t.fobj.slice(car, cdr));
st.xhr.push(xhr);
} }
do_send(); do_send();
} }