) are rare * in real post content; we leave those alone with a pre-pass that * stubs out script / style / pre blocks before rewriting. * * @package XSpeed */ declare(strict_types=1); namespace XSpeed; defined( 'ABSPATH' ) || exit; final class Lazy_Loader { /** * In-process counter for above-the-fold skipping. Reset by * process_html on every call so a fresh post starts at 0. * * @var int */ private static $image_counter = 0; /** * Whether an image on this page already holds fetchpriority="high". * * One per page. Every eager image used to get it, so with eager_first_n * at 3 an accordion's hidden images fetched at High alongside the * render-blocking CSS and the real LCP image. (#558) * * @var bool */ private static $priority_claimed = false; /** * Byte spans of markup that is hidden on arrival in the chunk the image * pass is walking, and whether the current tag sits in one. * * @var array */ private static $hidden_ranges = array(); /** @var bool */ private static $in_hidden = false; /** * Whether a visible excluded image is still to come, so the eager budget * must not take the high slot first. * * @var bool */ private static $priority_reserved = false; /** * Eager budget for inline-style backgrounds. Separate from images: a * hero is either an or a background, and the passes run one after * the other, so one shared counter would hand the budget to whichever * pass runs first rather than to what sits first on the page. * * @var int */ private static $background_counter = 0; /** * Settings cache (one read per request). * * @var array|null */ private static $opts = null; /** * Per-URL dimension cache (md5(src) => [w,h] | 0 for known-failure), * hydrated from the `xspeed_img_dims` transient once per request. * * @var array|null */ private static $src_dims_cache = null; /** * True while a background pass is resolving dimensions. * * Front-end renders read the cache and never fetch; a warm pass is the * one thing allowed to pay the network cost, because no visitor is * waiting on it. * * @var bool */ private static $warming = false; /** * Main entry point: take rendered HTML, return rewritten HTML. * Pure function aside from the static counters. */ public static function process_html( string $html ): string { if ( '' === $html ) { return $html; } $opts = self::opts(); // NOTE: the eager-load budget counter is NOT reset here. process_html // runs once per filter pass — the_content, post_thumbnail_html, and // once per get_avatar — so resetting per call let the featured image, // the first content image, AND every comment avatar each claim an // "eager" slot, defeating the budget. The counter is reset once per // page render via reset_state() on template_redirect, so it now // accumulates across all passes as intended. (FBS-82172 Bug 1) // Stub out