fix(js): clear interval handles when polling stops
Keep data-slhx-every timers separate from debounce/throttle timers and delete the interval handle when a polling element leaves the document, so reinserted elements can start polling again without leaking stale timer state. req: convention/005
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
const pending = new WeakMap();
|
const pending = new WeakMap();
|
||||||
const queues = new WeakMap();
|
const queues = new WeakMap();
|
||||||
const timers = new WeakMap();
|
const timers = new WeakMap();
|
||||||
|
const everyTimers = new WeakMap();
|
||||||
const pendingClassStates = new WeakMap();
|
const pendingClassStates = new WeakMap();
|
||||||
const indicatorStates = new WeakMap();
|
const indicatorStates = new WeakMap();
|
||||||
const disabledStates = new WeakMap();
|
const disabledStates = new WeakMap();
|
||||||
@@ -621,13 +622,18 @@
|
|||||||
|
|
||||||
function bindPolling(root) {
|
function bindPolling(root) {
|
||||||
forEachElement(root, (el) => {
|
forEachElement(root, (el) => {
|
||||||
if (!el.hasAttribute("data-slhx-every") || timers.has(el)) return;
|
if (!el.hasAttribute("data-slhx-every") || everyTimers.has(el)) return;
|
||||||
const ms = duration(el.getAttribute("data-slhx-every"));
|
const ms = duration(el.getAttribute("data-slhx-every"));
|
||||||
if (!ms) return;
|
if (!ms) return;
|
||||||
timers.set(el, setInterval(() => document.contains(el) ? send(el, "every") : clearInterval(timers.get(el)), ms));
|
everyTimers.set(el, setInterval(() => document.contains(el) ? send(el, "every") : stopPolling(el), ms));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stopPolling(el) {
|
||||||
|
clearInterval(everyTimers.get(el));
|
||||||
|
everyTimers.delete(el);
|
||||||
|
}
|
||||||
|
|
||||||
function bindSse(root) {
|
function bindSse(root) {
|
||||||
const url = root.getAttribute("data-slhx-sse");
|
const url = root.getAttribute("data-slhx-sse");
|
||||||
if (!url || sseSources.has(root) || typeof EventSource === "undefined") return;
|
if (!url || sseSources.has(root) || typeof EventSource === "undefined") return;
|
||||||
|
|||||||
@@ -41,11 +41,14 @@ fn runtime_interval_dispatch_avoids_duplicate_timers() {
|
|||||||
// req: convention/005
|
// req: convention/005
|
||||||
let source = slhx_js::RUNTIME_JS;
|
let source = slhx_js::RUNTIME_JS;
|
||||||
|
|
||||||
|
assert!(source.contains("const everyTimers = new WeakMap()"));
|
||||||
assert!(source.contains("forEachElement(root, (el) =>"));
|
assert!(source.contains("forEachElement(root, (el) =>"));
|
||||||
assert!(source.contains("!el.hasAttribute(\"data-slhx-every\") || timers.has(el)"));
|
assert!(source.contains("!el.hasAttribute(\"data-slhx-every\") || everyTimers.has(el)"));
|
||||||
assert!(source.contains("if (!el.hasAttribute(\"data-slhx-every\") || timers.has(el)) return"));
|
assert!(source.contains("if (!el.hasAttribute(\"data-slhx-every\") || everyTimers.has(el)) return"));
|
||||||
assert!(source.contains("setInterval(() => document.contains(el) ? send(el, \"every\")"));
|
assert!(source.contains("setInterval(() => document.contains(el) ? send(el, \"every\") : stopPolling(el), ms)"));
|
||||||
assert!(source.contains("clearInterval(timers.get(el))"));
|
assert!(source.contains("function stopPolling(el)"));
|
||||||
|
assert!(source.contains("clearInterval(everyTimers.get(el))"));
|
||||||
|
assert!(source.contains("everyTimers.delete(el)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user