fix: ended page scopes start no timers; SSH transfers keep their connection from the idle sweep; linked files download whole; only the sent item unpacks on an SSH host, replace and skip as on a machine

This commit is contained in:
redtea committed 2026-10-15 22:05:04 +03:00
1 parent e05ff05015
commit 64ce8f2b72
7 files changed
+175 -52

No files matched your search

+23 -1
View File
@@ -22,6 +22,28 @@
if (n < 1073741824) return (n / 1048576).toFixed(1) + ' M';
return (n / 1073741824).toFixed(1) + ' G';
}
const api = {shellQuote, shellQuoteAll, dropAction, fmtSize};
// scope gives a module timers, requests and listeners that end with it;
// once ended it starts nothing new (a request's late answer cannot set a
// timer going again).
function scope() {
let ended = false;
const timers = new Set(), offs = [], ac = new AbortController();
return {
timeout(fn, ms) { if (ended) return 0; const id = setTimeout(() => { timers.delete(id); fn(); }, ms); timers.add(id); return id; },
interval(fn, ms) { if (ended) return 0; const id = setInterval(fn, ms); timers.add(id); return id; },
clear(id) { clearTimeout(id); clearInterval(id); timers.delete(id); },
fetch(url, opt) {
const o = Object.assign({credentials: 'same-origin'}, opt || {});
// A request with its own signal ends on either.
o.signal = o.signal && AbortSignal.any ? AbortSignal.any([o.signal, ac.signal]) : (o.signal || ac.signal);
return fetch(url, o);
},
on(target, ev, fn, opt) { target.addEventListener(ev, fn, opt); offs.push(() => target.removeEventListener(ev, fn, opt)); },
signal: ac.signal,
end() { ended = true; timers.forEach(id => { clearTimeout(id); clearInterval(id); }); timers.clear(); offs.forEach(f => f()); ac.abort(); }
};
}
const api = {shellQuote, shellQuoteAll, dropAction, fmtSize, scope};
if (typeof module !== 'undefined') module.exports = api; else root.WSUtil = api;
})(this);