From 76eac04bf3670b3131d96558221df663f4f085e8 Mon Sep 17 00:00:00 2001 From: Bart Nagel Date: Wed, 4 Nov 2020 07:03:05 -0800 Subject: [PATCH] fix(buildSrcSet): ensure largest size can't be repeated The largest size was being repeated in certain conditions, since the value stored in `prev` was exact (possibly fractional) while the number saved in the list of resolutions is rounded to an even number, but the value stored in `prev` was the one being compared to `maxWidth`. In this fix we remove the code which pushes `maxWidth` to the list *after* the loop finishes and compare the last value in the list to `maxWidth` rather than the running exact fractional width value. These together eliminate the areas where the bug can subtly appear. It is then necessary to refactor the loop, by initializing the list to already contain the `minWidth` and then exiting early if `maxWidth` is equal (which has the side benefit that the cache won't be polluted with trivial cases) and then in the loop body push the *new* rather than previous value to the list, after rounding and clamping. --- src/imgix-core-js.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/imgix-core-js.js b/src/imgix-core-js.js index 56398af9b..2f9bf01f5 100644 --- a/src/imgix-core-js.js +++ b/src/imgix-core-js.js @@ -224,10 +224,15 @@ // returns an array of width values used during scrset generation ImgixClient.prototype._generateTargetWidths = function(widthTolerance, minWidth, maxWidth) { - var resolutions = []; + var resolutions = [minWidth]; var INCREMENT_PERCENTAGE = widthTolerance; var minWidth = Math.floor(minWidth); var maxWidth = Math.floor(maxWidth); + + if (minWidth === maxWidth) { + return resolutions; + } + var cacheKey = INCREMENT_PERCENTAGE + '/' + minWidth + '/' + maxWidth; if (cacheKey in this.targetWidthsCache) { @@ -238,14 +243,12 @@ return 2 * Math.round(n / 2); }; - var prev = minWidth; - while (prev < maxWidth) { - resolutions.push(ensureEven(prev)); - prev *= 1 + (INCREMENT_PERCENTAGE * 2); + var exact = minWidth; + while (resolutions[resolutions.length - 1] < maxWidth) { + exact *= 1 + (INCREMENT_PERCENTAGE * 2); + resolutions.push(Math.min(ensureEven(exact), maxWidth)); } - resolutions.push(maxWidth); - this.targetWidthsCache[cacheKey] = resolutions; return resolutions;