Release Multi-Hoster Uploader 3.3.108
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
// Microtask-coalesced set. Adds are O(1); the apply callback runs once per
|
||||
// scheduler tick with every id collected since the last flush.
|
||||
//
|
||||
// Used by the renderer to merge a burst of done-jobs (e.g. 500 jobs all
|
||||
// finishing within milliseconds) into a single queueJobs.filter() pass —
|
||||
// without this each event was its own O(N) sweep, so 500 finishes were
|
||||
// O(N²) and visibly froze the UI on completion.
|
||||
//
|
||||
// Loaded both as a CommonJS module (Node tests) and as a browser global
|
||||
// (renderer/app.js via index.html script tag).
|
||||
|
||||
(function (root) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Build a coalesced set.
|
||||
* @param {{ apply: (Set) => void, scheduler?: (cb: () => void) => void }} opts
|
||||
* apply: called once per scheduler tick with the accumulated ids.
|
||||
* scheduler: defaults to queueMicrotask. Tests can pass a synchronous
|
||||
* stand-in to avoid async waits.
|
||||
*/
|
||||
function makeCoalescedSet(opts) {
|
||||
if (!opts || typeof opts.apply !== 'function') {
|
||||
throw new TypeError('makeCoalescedSet: { apply: fn } required');
|
||||
}
|
||||
const apply = opts.apply;
|
||||
const scheduler = typeof opts.scheduler === 'function'
|
||||
? opts.scheduler
|
||||
: (typeof queueMicrotask === 'function' ? queueMicrotask : (cb) => Promise.resolve().then(cb));
|
||||
let pending = new Set();
|
||||
let scheduled = false;
|
||||
|
||||
function flush() {
|
||||
scheduled = false;
|
||||
if (pending.size === 0) return;
|
||||
const drop = pending;
|
||||
pending = new Set();
|
||||
try { apply(drop); } catch (e) {
|
||||
// Don't let a failing apply lock out the next batch — surface it
|
||||
// but keep the coalescer usable.
|
||||
if (typeof console !== 'undefined' && console.error) console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
add(id) {
|
||||
pending.add(id);
|
||||
if (!scheduled) {
|
||||
scheduled = true;
|
||||
scheduler(flush);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Synchronously consume any pending ids. Used by beforeunload paths
|
||||
* where we can't wait for the next microtask before persisting.
|
||||
*/
|
||||
drainSync() {
|
||||
if (pending.size === 0) return;
|
||||
const drop = pending;
|
||||
pending = new Set();
|
||||
scheduled = false;
|
||||
apply(drop);
|
||||
},
|
||||
/** Introspection for tests + diagnostics. */
|
||||
pendingSize() { return pending.size; },
|
||||
isScheduled() { return scheduled; }
|
||||
};
|
||||
}
|
||||
|
||||
const api = { makeCoalescedSet };
|
||||
if (typeof module !== 'undefined' && module.exports) module.exports = api;
|
||||
else if (root) root.CoalescedSet = api;
|
||||
})(typeof window !== 'undefined' ? window : this);
|
||||
Reference in New Issue
Block a user