Greasy Fork

Amazon Page Smoother

Improves performance on Amazon pages by throttling background tasks and pausing off-screen iframe rendering.

// ==UserScript==
// @name         Amazon Page Smoother
// @namespace    http://tampermonkey.net/
// @version      0.0.1
// @description  Improves performance on Amazon pages by throttling background tasks and pausing off-screen iframe rendering.
// @license      Unlicense
// @author       VeleSila
// @match        https://www.amazon.com/*
// @match        https://www.amazon.co.jp/*
// @match        https://www.amazon.co.uk/*
// @match        https://www.amazon.es/*
// @match        https://www.amazon.fr/*
// @match        https://www.amazon.de/*
// @match        https://www.amazon.it/*
// @match        https://www.amazon.ca/*
// @match        https://www.amazon.com.au/*
// @exclude      */cart/*
// @exclude      */buy/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // --- Configuration ---
    const FOREGROUND_TICK_RATE_MS = 150;
    const BACKGROUND_TICK_RATE_MS = 2000;

    /**
     * Consolidates multiple setInterval calls into a single, more efficient loop.
     */
    function initializeTimerThrottler() {
        if (window.self !== window.top) {
            return; // Only run in the top-level window
        }

        const nativeSetInterval = window.setInterval;
        const nativeClearInterval = window.clearInterval;

        let nextTaskId = 1;
        const scheduledTasks = {}; // Using a plain object for the task queue

        // Override the browser's default setInterval function
        window.setInterval = (callback, delay, ...args) => {
            if (typeof callback !== 'function') {
                // For non-function callbacks (e.g., strings), use the native function
                return nativeSetInterval(callback, delay, ...args);
            }

            const id = nextTaskId++;
            scheduledTasks[id] = {
                callback: () => callback(...args),
                delay: Math.max(delay || 0, FOREGROUND_TICK_RATE_MS),
                lastExecution: 0,
            };
            return id;
        };

        // Override the corresponding clearInterval function
        window.clearInterval = (id) => {
            if (scheduledTasks[id]) {
                delete scheduledTasks[id];
            } else {
                nativeClearInterval(id);
            }
        };

        const masterLoop = () => {
            const now = performance.now();
            const tickRate = document.hidden ? BACKGROUND_TICK_RATE_MS : FOREGROUND_TICK_RATE_MS;

            for (const id in scheduledTasks) {
                const task = scheduledTasks[id];
                if (now - task.lastExecution >= task.delay) {
                    try {
                        task.callback();
                        task.lastExecution = now;
                    } catch (error) {
                        console.error("Error in throttled task:", error);
                        delete scheduledTasks[id]; // Remove faulty task
                    }
                }
            }
            setTimeout(masterLoop, tickRate);
        };

        // Start the master loop
        setTimeout(masterLoop, FOREGROUND_TICK_RATE_MS);
    }

    /**
     * Pauses rendering for iframes that are not currently visible on screen.
     */
    function initializeIframeManager() {
        if (window.self !== window.top) {
            return;
        }

        const visibilityWatcher = new IntersectionObserver(
            (entries) => {
                for (const entry of entries) {
                    entry.target.style.contentVisibility = entry.isIntersecting ? 'visible' : 'hidden';
                }
            }, { root: null, threshold: 0 }
        );

        const domWatcher = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                for (const node of mutation.addedNodes) {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        if (node.tagName === 'IFRAME') {
                            visibilityWatcher.observe(node);
                        } else {
                            node.querySelectorAll('iframe').forEach(iframe => visibilityWatcher.observe(iframe));
                        }
                    }
                }
            }
        });

        const startManaging = () => {
            document.querySelectorAll('iframe').forEach(iframe => visibilityWatcher.observe(iframe));
            domWatcher.observe(document.body, { childList: true, subtree: true });
        };

        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', startManaging, { once: true });
        } else {
            startManaging();
        }
    }

    // --- Script Execution ---
    initializeTimerThrottler();
    initializeIframeManager();

})();