From f64d97f46256381cf4ea591c21bbb42e7352637d Mon Sep 17 00:00:00 2001 From: rootkiller6788 <221446036+rootkiller6788@users.noreply.github.com> Date: Thu, 17 Sep 2026 14:21:08 +0800 Subject: [PATCH 1/2] respect `limit` when `throttle` is also set The limit was only checked against `toPrefetch.size` at the moment a link was scheduled, but that set only grows once a task actually runs. With a throttle set, tasks pile up in the throttler queue, the set stays where it is, and every remaining link in the same observer callback passes the check and gets queued. Setting limit: 4 with throttle: 3 prefetched all 20 links in the page from issue #235. Count the tasks that are queued but not started yet and reserve a slot for them at scheduling time. The unthrottled path is unaffected: the task body runs synchronously, so the count is back to zero before the next link is looked at. --- src/index.mjs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/index.mjs b/src/index.mjs index d8cbe639..0c81ea9a 100644 --- a/src/index.mjs +++ b/src/index.mjs @@ -111,6 +111,9 @@ export function listen(options = {}) { const delay = options.delay || 0; const hrefsInViewport = new Map(); const specRulesInViewport = new Map(); + // Prefetches handed to the throttler that haven't started yet. `toPrefetch` + // only grows once a task runs, so queued work has to be reserved separately. + let scheduled = 0; const timeoutFn = options.timeoutFn || requestIdleCallback; const hrefFn = typeof options.hrefFn === 'function' && options.hrefFn; @@ -174,8 +177,10 @@ export function listen(options = {}) { } // Do not prefetch if will match/exceed limit and user has not switched to shouldOnlyPrerender mode - if (toPrefetch.size < limit && !shouldOnlyPrerender) { + if (toPrefetch.size + scheduled < limit && !shouldOnlyPrerender) { + scheduled++; toAdd(() => { + scheduled--; prefetch( hrefFn ? hrefFn(entry) : entry.href, options.priority, From e16723123712e96424d860568f14c56d20990219 Mon Sep 17 00:00:00 2001 From: rootkiller6788 <221446036+rootkiller6788@users.noreply.github.com> Date: Thu, 17 Sep 2026 14:21:12 +0800 Subject: [PATCH 2/2] add a regression test for limit + throttle 4 links in view, limit: 2, throttle: 1. All four land in the same observer callback, so the queue keeps the second half from starting until the first half is done. Before the fix this prefetched all 4 links. I used limit 2 / throttle 1 instead of the 4 / 3 from the issue because it reproduces the same thing with fewer moving parts, and the suite already has a test-throttle fixture that shows the pattern. --- test/fixtures/test-limit-throttle.html | 25 +++++++++++++++++++++++++ test/quicklink.spec.js | 18 ++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 test/fixtures/test-limit-throttle.html diff --git a/test/fixtures/test-limit-throttle.html b/test/fixtures/test-limit-throttle.html new file mode 100644 index 00000000..02ff55bc --- /dev/null +++ b/test/fixtures/test-limit-throttle.html @@ -0,0 +1,25 @@ + + + +
+ +