Skip to content

fix: request the CSS width for Retina srcset entries and use it in sizes - #1177

Open
selul wants to merge 2 commits into
developmentfrom
bugfix/1111
Open

selul wants to merge 2 commits into
developmentfrom
bugfix/1111

Conversation

@selul

@selul selul commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Related issues: #1111, #1113

With Retina images on, the page profiler's 2x srcset candidates delivered twice their advertised width, and the sizes attribute got a second, doubled condition for the same breakpoint. Both came from the same value: the 2x entry carries its delivered width (for example 824, advertised as 824w) together with dpr: 2, and that width was used both as the URL's w and as the sizes slot.

What changed

Note

Only sites with Retina images on (off by default) and only profiler-generated 2x candidates are affected. Their URLs change once, so the CDN fetches those variants again. Fixing it in PHP also corrects the profiles already stored (they last up to 7 days), with no JS change.

Not in this PR: when a page already has a sizes attribute, enhance_existing_sizes() sorts the merged conditions by breakpoint descending, so the first max-width condition matches every smaller viewport and the rest are never used. That changes sizes on most profiled pages and deserves its own issue.

Tests

  • tests/test-srcset.php: with Retina on, a 2x entry's URL is w:412/dpr:2/h:300 … 824w (no w:824); two breakpoints with 1x and 2x entries give one condition each, (max-width: 480px) 300px, (max-width: 768px) 412px. Both fail on development. Mutations (URL or sizes with the delivered width, height not divided) each fail a test.

QA

  1. Turn on Retina images in WP Admin → Optimole → Settings, and keep the page profiler on.

  2. Open a page with large content images on a desktop browser, then reload it once the profile is stored.

  3. View the source of an image that got a generated srcset.

    Expect: each 2x-sized candidate URL has w:<half the descriptor>/dpr:2 (for example w:412/dpr:2 … 824w), and sizes has one max-width condition per breakpoint.

Verification (head 13fb6a0d)

Check Result
PHPUnit, full suite, PHP 8.4 (WP 7.1.3) PASS: 366 tests (baseline 364 + 2 new)
tests/test-srcset.php run alone PASS: 37 tests
New tests on the development source FAIL (2 of 2)
Mutations: URL with the delivered width / sizes slot with the delivered width / height not divided Each one fails a test
phpcs, phpstan (build-only include errors excluded locally; CI builds assets first) PASS
CI on 13fb6a0d (PHPUnit on PHP 8.0–8.3, PHPStan, phpcs, ESLint, Jest, e2e, build) PASS
Codex review (gpt-6-astra, high), 335e1b4d and the follow-up on 13fb6a0d No findings
pirate-bot Round 1 (335e1b4d): changes requested, native return types on the new tests and one shared settings mock (fixed). Round 2 (13fb6a0d): approved

Not proven

  • The delivered pixel size against the live CDN (the multiplier is inferred from the plugin's own dpr:2 / 2x usage).

🤖 Generated with Claude Code

With Retina images on, the page profiler stores a 1x and a 2x entry per
breakpoint. The 2x entry carries its delivered width (e.g. 824, advertised
as "824w") and dpr 2, and the CDN multiplies w by dpr, so the URL asked for
w:824/dpr:2 and delivered 1648px for an 824w candidate (#1111). The sizes
attribute also used that doubled width, so a breakpoint got two max-width
conditions, one with the 2x width (#1113).

The URL now asks for the CSS width (width / dpr) with the dpr, and the
sizes slot uses the CSS width, so the 1x and 2x entries give the same
condition and array_unique() keeps one. Doing this in PHP also corrects
profiles already stored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pirate-bot

pirate-bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

Plugin build for 13fb6a0 is ready 🛎️!

@selul
selul requested a review from pirate-bot October 11, 2026 12:53

@pirate-bot pirate-bot left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes requested

The Retina srcset fix looks correct, but the new test code needs native return types and a shared settings mock helper.

Validation details
  • Files reviewed: 2/2 changed files.
  • I ran sandbox-phpunit-ab.sh /repo pr-base --filter 'Test_Srcset_Functionality::' on PHP 8.3 with the WordPress 7.1.3 test library. The harness did not record this run.
  • On HEAD, the output was OK (37 tests, 100 assertions).
  • On the base code, both new tests failed with sizes="(max-width: 768px) 412px, (max-width: 768px) 824px" in the output.
  • A source trace showed that the profiler sends only dpr 1 and 2, with even 2x widths. The existing-sizes path reuses the fixed entries.
  • The security pass found no new trust-boundary exposure.
Untested areas
  • I did not check the pixel size the live CDN delivers for w:412/dpr:2.
  • I did not check page rendering in a browser.

🤖 Automated review · run code-review-agent_6acb86b0e6bb52.54393413.


🤖 Review agent — review posted ✅ on 335e1b4d · changes requested · 2 findings · 13 min

Run code-review-agent_6acb86b0e6bb52.54393413 · trail

Comment thread tests/test-srcset.php Outdated
Comment thread tests/test-srcset.php Outdated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@selul
selul requested a review from pirate-bot October 11, 2026 14:07

@pirate-bot pirate-bot left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approved

The PR passes. Both earlier test findings are fixed, and the new tests fail on the base code.

Validation details
  • Files reviewed: 2/2 changed files.
  • The new commit 13fb6a0 adds native return types and a parameterized retina_settings() helper. The Retina-disabled test now uses the helper.
  • I ran sandbox-phpunit-ab.sh /repo pr-base --filter 'Test_Srcset_Functionality::' on PHP 8.3. The harness did not record this run.
  • On HEAD, the output was OK (37 tests, 100 assertions).
  • On the base code, both new tests failed with Tests: 37, Assertions: 97, Failures: 2.
  • The profiler trace and security pass come from run code-review-agent_6acb86b0e6bb52.54393413, not rerun.
Untested areas
  • I did not check the pixel size the live CDN delivers for w:412/dpr:2.
  • I did not check page rendering in a browser.

🤖 Automated review · run code-review-agent_6acb98135bd374.96561950.


🤖 Review agent — review posted ✅ on 13fb6a0d · approved · 0 findings · 1 min

Run code-review-agent_6acb98135bd374.96561950 · trail

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants