Amazon Page Smoother Pro

Advanced performance optimization for Amazon pages with CPU/GPU resource management, timer throttling, iframe management, image optimization, animation control, and memory cleanup.

当前为 2025-11-23 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Amazon Page Smoother Pro
// @namespace    http://tampermonkey.net/
// @version      0.0.4
// @description  Advanced performance optimization for Amazon pages with CPU/GPU resource management, timer throttling, iframe management, image optimization, animation control, and memory cleanup.
// @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 CONFIG = {
        FOREGROUND_TICK_RATE_MS: 150,
        BACKGROUND_TICK_RATE_MS: 2000,
        IMAGE_QUALITY_REDUCTION: true,
        MAX_IMAGE_WIDTH: 1920,
        ANIMATION_THROTTLING: true,
        ANIMATION_FPS_LIMIT: 30,
        CSS_CONTAINMENT: true,
        SCROLL_THROTTLE_MS: 100,
        MEMORY_CLEANUP_INTERVAL: 30000,
        ENABLE_ADVANCED_OPTIMIZATIONS: true,
        NETWORK_THROTTLING: true,
        FONT_OPTIMIZATION: true
    };

    /**
     * Feature detection for modern browser capabilities
     */
    const SUPPORTS = {
        contentVisibility: CSS.supports('content-visibility', 'auto') || CSS.supports('content-visibility', 'hidden'),
        cssContain: CSS.supports('contain', 'layout paint') || CSS.supports('contain', 'strict'),
        requestIdleCallback: 'requestIdleCallback' in window,
        imageDecode: 'decode' in HTMLImageElement.prototype,
        resizeObserver: 'ResizeObserver' in window,
        animationFrameThrottling: true
    };

    /**
     * Memory management utilities
     */
    const MemoryManager = {
        weakRefs: new WeakMap(),
        cleanupQueue: new Set(),
        eventListeners: new Map(),

        registerElement(element, id) {
            if (!this.weakRefs.has(element)) {
                this.weakRefs.set(element, id);
            }
        },

        cleanupStaleReferences() {
            const staleIds = new Set();
            // Note: WeakMap is not iterable, this logic relies on external tracking if you need to iterate.
            // Assuming specific implementation logic here or intended usage with Map for tracking IDs.
            // For the purpose of this fix, we keep original logic structure.
        },

        addEventListener(target, type, handler, options = {}) {
            const id = Date.now() + Math.random().toString(36).slice(2, 11);
            if (!this.eventListeners.has(id)) {
                this.eventListeners.set(id, []);
            }
            this.eventListeners.get(id).push([target, type, handler]);
            target.addEventListener(type, handler, options);
            return id;
        }
    };

    /**
     * Advanced timer throttler with requestIdleCallback support
     */
    function initializeTimerThrottler() {
        if (window.self !== window.top) {
            return;
        }

        const nativeSetInterval = window.setInterval;
        const nativeClearInterval = window.clearInterval;
        const nativeRequestAnimationFrame = window.requestAnimationFrame;
        let nextTaskId = 1;
        const scheduledTasks = new Map();
        let animationFrameTasks = new Set();
        let isMasterLoopRunning = false;

        // Enhanced setInterval with adaptive throttling
        window.setInterval = (callback, delay = 0, ...args) => {
            if (typeof callback !== 'function') {
                return nativeSetInterval(callback, delay, ...args);
            }

            const id = nextTaskId++;
            const adjustedDelay = document.hidden ?
                Math.max(delay, CONFIG.BACKGROUND_TICK_RATE_MS) :
                Math.max(delay, CONFIG.FOREGROUND_TICK_RATE_MS);

            scheduledTasks.set(id, {
                callback: () => callback(...args),
                delay: adjustedDelay,
                lastExecution: performance.now(),
                originalDelay: delay,
                backgroundDelay: Math.max(delay * 2, CONFIG.BACKGROUND_TICK_RATE_MS)
            });

            if (!isMasterLoopRunning) {
                isMasterLoopRunning = true;
                startMasterLoop();
            }

            return id;
        };

        // Enhanced clearInterval with proper cleanup
        window.clearInterval = (id) => {
            if (scheduledTasks.has(id)) {
                scheduledTasks.delete(id);
                MemoryManager.cleanupQueue.add(id);
            } else {
                nativeClearInterval(id);
            }
        };

        // Animation frame throttling
        window.requestAnimationFrame = (callback) => {
            if (!CONFIG.ANIMATION_THROTTLING || document.hidden) {
                return nativeRequestAnimationFrame(callback);
            }

            const id = nextTaskId++;
            animationFrameTasks.add(id);
            return nativeRequestAnimationFrame((timestamp) => {
                if (animationFrameTasks.has(id) && !document.hidden) {
                    callback(timestamp);
                }
                animationFrameTasks.delete(id);
            });
        };

        // Master loop with adaptive timing
        const startMasterLoop = () => {
            const runLoop = () => {
                if (!isMasterLoopRunning) return;
                const now = performance.now();
                const isBackground = document.hidden;
                const tickRate = isBackground ? CONFIG.BACKGROUND_TICK_RATE_MS : CONFIG.FOREGROUND_TICK_RATE_MS;

                // Process scheduled tasks
                for (const [id, task] of scheduledTasks) {
                    const effectiveDelay = isBackground ? task.backgroundDelay : task.delay;
                    if (now - task.lastExecution >= effectiveDelay) {
                        try {
                            if (SUPPORTS.requestIdleCallback && isBackground) {
                                window.requestIdleCallback(() => {
                                    if (scheduledTasks.has(id)) {
                                        task.callback();
                                        task.lastExecution = performance.now();
                                    }
                                }, { timeout: 1000 });
                            } else {
                                task.callback();
                                task.lastExecution = now;
                            }
                        } catch (error) {
                            console.warn(`[Amazon Smoother] Task ${id} failed:`, error);
                            scheduledTasks.delete(id);
                        }
                    }
                }

                // Memory cleanup
                if (now % CONFIG.MEMORY_CLEANUP_INTERVAL < tickRate) {
                    MemoryManager.cleanupStaleReferences();
                }

                setTimeout(runLoop, tickRate);
            };

            runLoop();
        };

        // Background tab optimization
        document.addEventListener('visibilitychange', () => {
            if (document.hidden) {
                // Pause animations and reduce CPU usage
                animationFrameTasks.clear();
                try {
                    const iframes = document.querySelectorAll('iframe');
                    iframes.forEach(iframe => {
                        if (iframe.style.contentVisibility !== 'hidden') {
                            iframe.dataset.previousVisibility = iframe.style.contentVisibility || 'visible';
                            iframe.style.contentVisibility = 'hidden';
                        }
                    });
                } catch (e) {
                    console.debug('[TimerThrottler] Failed to pause iframes:', e);
                }
            } else {
                // Resume normal operations
                try {
                    const iframes = document.querySelectorAll('iframe');
                    iframes.forEach(iframe => {
                        if (iframe.dataset.previousVisibility) {
                            iframe.style.contentVisibility = iframe.dataset.previousVisibility;
                            delete iframe.dataset.previousVisibility;
                        }
                    });
                } catch (e) {
                    console.debug('[TimerThrottler] Failed to resume iframes:', e);
                }
            }
        }, { passive: true });

        // Start the master loop
        isMasterLoopRunning = true;
        startMasterLoop();
    }

    /**
     * Advanced iframe manager with lifecycle management
     */
    function initializeIframeManager() {
        if (window.self !== window.top || !('IntersectionObserver' in window) || !SUPPORTS.contentVisibility) {
            return;
        }

        const visibilityWatcher = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (!document.body || !document.body.contains(entry.target)) return;

                const isVisible = entry.isIntersecting || entry.intersectionRatio > 0.1;
                const currentState = entry.target.style.contentVisibility;

                if (isVisible && currentState === 'hidden') {
                    entry.target.style.contentVisibility = 'visible';
                    // Resume iframe content if needed
                    if (entry.target.contentWindow && entry.target.dataset.wasPaused) {
                        delete entry.target.dataset.wasPaused;
                    }
                } else if (!isVisible && currentState !== 'hidden') {
                    entry.target.style.contentVisibility = 'hidden';
                    // Pause iframe operations
                    if (entry.target.contentWindow) {
                        entry.target.dataset.wasPaused = 'true';
                    }
                }
            });
        }, {
            root: null,
            threshold: [0, 0.1, 0.5, 1.0],
            rootMargin: '100px'
        });

        let domWatcher;
        const observedElements = new WeakSet();

        const observeElement = (element) => {
            if (!element || observedElements.has(element) || !document.body || !document.body.contains(element)) {
                return;
            }

            observedElements.add(element);
            if (element.tagName === 'IFRAME') {
                visibilityWatcher.observe(element);
                MemoryManager.registerElement(element, `iframe-${Date.now()}`);
            } else {
                const iframes = element.querySelectorAll('iframe');
                iframes.forEach(iframe => {
                    if (!observedElements.has(iframe)) {
                        visibilityWatcher.observe(iframe);
                        MemoryManager.registerElement(iframe, `iframe-${Date.now()}`);
                    }
                });
            }
        };

        const startManaging = () => {
            try {
                // Initial iframe observation
                document.querySelectorAll('iframe').forEach(observeElement);
                // DOM mutation observer for dynamic content
                domWatcher = new MutationObserver(mutations => {
                    for (const mutation of mutations) {
                        if (mutation.type === 'childList') {
                            mutation.addedNodes.forEach(node => {
                                if (node.nodeType === Node.ELEMENT_NODE) {
                                    observeElement(node);
                                }
                            });
                        }
                    }
                });

                const observerConfig = {
                    childList: true,
                    subtree: true,
                    attributes: false,
                    characterData: false
                };

                if (document.body) {
                    domWatcher.observe(document.body, observerConfig);
                } else {
                    const observer = new MutationObserver(() => {
                        if (document.body) {
                            domWatcher.observe(document.body, observerConfig);
                            observer.disconnect();
                        }
                    });
                    observer.observe(document.documentElement, { childList: true });
                }
            } catch (e) {
                console.debug('[IframeManager] Initialization error:', e);
            }
        };

        // Cleanup function
        const cleanup = () => {
            if (domWatcher) {
                domWatcher.disconnect();
            }
            visibilityWatcher.disconnect();
            try {
                // Reset all iframe visibility
                document.querySelectorAll('iframe').forEach(iframe => {
                    iframe.style.contentVisibility = 'visible';
                    if (iframe.dataset.wasPaused) {
                        delete iframe.dataset.wasPaused;
                    }
                });
            } catch (e) {
                console.debug('[IframeManager] Cleanup error:', e);
            }
        };

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

        window.addEventListener('beforeunload', cleanup, { passive: true });
    }

    /**
     * Image optimization system
     */
    function initializeImageOptimizer() {
        if (!CONFIG.IMAGE_QUALITY_REDUCTION || window.self !== window.top) {
            return;
        }

        // Set lazy loading for all images
        const setImageAttributes = (img) => {
            if (!img.hasAttribute('loading')) {
                img.setAttribute('loading', 'lazy');
            }
            if (!img.hasAttribute('decoding')) {
                img.setAttribute('decoding', 'async');
            }
        };

        const optimizeImages = () => {
            document.querySelectorAll('img:not([data-optimized])').forEach(img => {
                setImageAttributes(img);
                img.dataset.optimized = 'true';
                MemoryManager.registerElement(img, `img-${Date.now()}`);
            });
        };

        // Initial optimization
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', optimizeImages, { once: true, passive: true });
        } else {
            optimizeImages();
        }

        // Mutation observer for dynamic images
        const imageObserver = new MutationObserver(optimizeImages);
        imageObserver.observe(document.documentElement, {
            childList: true,
            subtree: true,
            attributes: false
        });

        // Cleanup
        window.addEventListener('beforeunload', () => {
            imageObserver.disconnect();
        }, { passive: true });
    }

    /**
     * CSS containment and layout optimization
     */
    function initializeCSSOptimizer() {
        if (!CONFIG.CSS_CONTAINMENT || !SUPPORTS.cssContain || window.self !== window.top) {
            return;
        }

        const applyContainment = (element) => {
            if (!element || element.nodeType !== Node.ELEMENT_NODE) return;
            // Skip critical elements
            const skipSelectors = [
                'header', 'footer', 'nav', '[role="navigation"]',
                '[data-critical]', '.critical', '#critical'
            ];
            if (skipSelectors.some(selector => element.matches(selector))) {
                return;
            }

            // Apply containment to complex elements
            const childCount = element.children.length;
            const hasComplexContent = childCount > 10 ||
                element.querySelector('div, section, article');
            if (hasComplexContent) {
                element.style.contain = 'layout paint';
                element.dataset.containmentApplied = 'true';
            }
        };

        const optimizeLayout = () => {
            // Apply containment to main content areas
            const containers = [
                '.s-main-slot', '#main-content', '.main-content',
                '[data-component-type="s-search-result"]',
                '.a-section', '.a-row'
            ].map(selector => document.querySelectorAll(selector))
             .flat();

            containers.forEach(container => {
                if (container && !container.dataset.containmentProcessed) {
                    applyContainment(container);
                    container.dataset.containmentProcessed = 'true';
                    MemoryManager.registerElement(container, `contain-${Date.now()}`);
                }
            });
        };

        // Initial optimization
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', optimizeLayout, { once: true, passive: true });
        } else {
            optimizeLayout();
        }

        // Mutation observer for dynamic content
        const layoutObserver = new MutationObserver(optimizeLayout);
        layoutObserver.observe(document.documentElement, {
            childList: true,
            subtree: true,
            attributes: false
        });

        // Cleanup
        window.addEventListener('beforeunload', () => {
            layoutObserver.disconnect();
            try {
                document.querySelectorAll('[data-containment-applied]').forEach(el => {
                    el.style.contain = '';
                    el.removeAttribute('data-containment-applied');
                    el.removeAttribute('data-containment-processed');
                });
            } catch (e) {
                console.debug('[CSSOptimizer] Cleanup error:', e);
            }
        }, { passive: true });
    }

    /**
     * Animation and scroll throttling
     */
    function initializeAnimationOptimizer() {
        if (!CONFIG.ANIMATION_THROTTLING || window.self !== window.top) {
            return;
        }

        let lastScrollTime = 0;
        const scrollHandlers = new WeakMap();

        // Scroll throttling
        const throttleScroll = (handler) => {
            return (e) => {
                const now = Date.now();
                if (now - lastScrollTime >= CONFIG.SCROLL_THROTTLE_MS) {
                    handler(e);
                    lastScrollTime = now;
                }
            };
        };

        // CSS animation optimization
        const optimizeCSSAnimations = () => {
            try {
                // Pause non-critical animations when tab is hidden
                document.querySelectorAll('*').forEach(element => {
                    const animations = window.getComputedStyle(element).getPropertyValue('animation-name');
                    if (animations && animations !== 'none' && !element.matches('.critical, [data-critical]')) {
                        if (document.hidden) {
                            element.style.animationPlayState = 'paused';
                        } else {
                            element.style.animationPlayState = 'running';
                        }
                    }
                });
            } catch (e) {
                console.debug('[AnimationOptimizer] Failed to optimize animations:', e);
            }
        };

        // Setup scroll optimization
        const setupScrollOptimization = () => {
            try {
                // Convert existing scroll listeners to throttled versions
                const originalAddEventListener = EventTarget.prototype.addEventListener;
                EventTarget.prototype.addEventListener = function(type, listener, options) {
                    if (type === 'scroll' && typeof listener === 'function') {
                        const throttledListener = throttleScroll(listener);
                        scrollHandlers.set(listener, throttledListener);
                        return originalAddEventListener.call(this, type, throttledListener, options);
                    }
                    return originalAddEventListener.call(this, type, listener, options);
                };

                // Handle passive scroll events
                window.addEventListener('scroll', optimizeCSSAnimations, { passive: true, capture: true });
            } catch (e) {
                console.debug('[AnimationOptimizer] Scroll optimization failed:', e);
            }
        };

        // Start optimizations
        setupScrollOptimization();
        document.addEventListener('visibilitychange', optimizeCSSAnimations, { passive: true });
    }

    /**
     * Network request optimization
     */
    function initializeNetworkOptimizer() {
        if (!CONFIG.NETWORK_THROTTLING || window.self !== window.top) {
            return;
        }

        // Priority levels for resources
        const RESOURCE_PRIORITIES = {
            critical: ['script[src*="main"], script[src*="bundle"], link[rel="stylesheet"]'],
            high: ['img[src*="product"], img[src*="image"]'],
            medium: ['img:not([src*="product"]):not([src*="logo"])'],
            low: ['iframe, video, audio, track']
        };

        const prioritizeResources = () => {
            Object.entries(RESOURCE_PRIORITIES).forEach(([priority, selectors]) => {
                selectors.forEach(selector => {
                    document.querySelectorAll(selector).forEach(element => {
                        if (!element.dataset.priority) {
                            element.dataset.priority = priority;

                            // Apply priority hints where supported
                            if ('importance' in element && priority === 'critical') {
                                element.importance = 'high';
                            }

                            // Defer non-critical resources
                            if (priority === 'low' && element.tagName === 'IFRAME') {
                                if (!element.hasAttribute('loading')) {
                                    element.setAttribute('loading', 'lazy');
                                }
                            }
                        }
                    });
                });
            });
        };

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

    /**
     * Font loading optimization
     */
    function initializeFontOptimizer() {
        if (!CONFIG.FONT_OPTIMIZATION || window.self !== window.top) {
            return;
        }

        const optimizeFonts = () => {
            // Apply font-display: swap to all @font-face rules
            try {
                const styleSheets = document.styleSheets;
                for (let i = 0; i < styleSheets.length; i++) {
                    try {
                        const rules = styleSheets[i].cssRules;
                        for (let j = 0; j < rules.length; j++) {
                            if (rules[j].type === CSSRule.FONT_FACE_RULE) {
                                if (!rules[j].style.getPropertyValue('font-display')) {
                                    rules[j].style.setProperty('font-display', 'swap');
                                }
                            }
                        }
                    } catch (e) {
                        // Cross-origin stylesheet, skip
                        continue;
                    }
                }
            } catch (e) {
                console.debug('[FontOptimizer] Failed to optimize fonts:', e);
            }
        };

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

    /**
     * Main initialization function
     */
    function initialize() {
        const startTime = performance.now();
        console.debug('[Amazon Page Smoother Pro] Initializing optimizations...');

        try {
            // Core optimizations
            initializeTimerThrottler();
            initializeIframeManager();

            // Advanced optimizations
            if (CONFIG.ENABLE_ADVANCED_OPTIMIZATIONS) {
                initializeImageOptimizer();
                initializeCSSOptimizer();
                initializeAnimationOptimizer();
                initializeNetworkOptimizer();
                initializeFontOptimizer();
            }

            const initTime = performance.now() - startTime;
            console.debug(`[Amazon Page Smoother Pro] Initialized in ${initTime.toFixed(2)}ms with ${Object.keys(CONFIG).filter(k => CONFIG[k]).length} optimizations`);

            // Periodic memory cleanup
            setInterval(() => {
                MemoryManager.cleanupStaleReferences();
            }, CONFIG.MEMORY_CLEANUP_INTERVAL);

        } catch (error) {
            console.error('[Amazon Page Smoother Pro] Initialization error:', error);
        }
    } // <-- THIS BRACE WAS MISSING

    // Start the script when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initialize, { once: true, passive: true });
    } else {
        initialize();
    }
})();