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, 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 @@ + + + + + + Prefetch: Limit and throttle + + + + + + Link 1 + Link 2 + Link 3 + Link 4 + + + + + diff --git a/test/quicklink.spec.js b/test/quicklink.spec.js index 72b0f5d9..19d2d2aa 100644 --- a/test/quicklink.spec.js +++ b/test/quicklink.spec.js @@ -317,6 +317,24 @@ mainSuite('should not exceed the `limit` total', async context => { assert.ok(ours.includes(`${server}/1.html`)); }); +mainSuite('should not exceed the `limit` when `throttle` is also set', async context => { + const URLs = []; + + context.handleRequest = async req => { + const url = req.url(); + if (/test\/fixtures\/\d+\.html$/i.test(url)) { + URLs.push(url); + return req.respond({status: 200}); + } + + return req.continue(); + }; + + await context.page.goto(`${server}/test-limit-throttle.html`); + await sleep(); + assert.is(URLs.length, 2); +}); + mainSuite('should respect the `throttle` concurrency', async context => { const URLs = []; // Note: Page makes 4 requests