您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Defers setTimeout calls if no user input has been received for 15 seconds. Useful for stopping background tabs from continuing to use CPU cycles.
// ==UserScript== // @name Background tab setTimeout muffler // @namespace BSP // @description Defers setTimeout calls if no user input has been received for 15 seconds. Useful for stopping background tabs from continuing to use CPU cycles. // @include http://* // @include https://* // @exclude http://*.google.tld/* // @exclude https://*.google.tld/* // @exclude http://irc.lc/* // @exclude https://irc.lc/* // @exclude http://www.newsblur.com/* // @exclude https://www.newsblur.com/* // @exclude http://steamcommunity.com/id* // @exclude https://www.duolingo.com/* // @version 1 // @run-at document-start // ==/UserScript== var setInterval_old = unsafeWindow.setInterval; var setTimeout_old = unsafeWindow.setTimeout; var clearInterval_old = unsafeWindow.clearInterval; var clearTimeout_old = unsafeWindow.clearTimeout; var startDate = new Date; //QueuedTimer format: {ID: [startTime, repeat, func, delay, args]} var queuedTimers = null; //ActiveTimer format: {ID: [repeat, func, delay, args, browserTimerID]} var activeTimers = {}; var nextID = 1000000; var lastUserInteraction = Date.now(); function debugLog() { false && console && console.log && console.log(Array.slice(arguments, 0)); } function muffleTimers() { return (Date.now() - lastUserInteraction) > 15000; } function addTimer(ID, repeat, func, delay, args, isNew) { if(typeof func != "function" && typeof func != "string") { debugLog("addTimer", "invalid func", arguments); throw Error("setInterval/setTimeout: invalid func"); } delay = +(delay || 0); //coerce to number if(isNaN(delay)) { //check for NaN (results from non-number strings/objects, etc.) debugLog("addTimer", "invalid delay", arguments); throw Error("setInterval/setTimeout: invalid delay"); } //if(Object.keys(queuedTimers || {}).length + Object.keys(activeTimers).length > 500 && new Date - startDate > 15000) { // debugLog("addTimer", "More than 100 timers!? Fuck that!", arguments); // throw Error("STFU PLZ"); //} if(muffleTimers()) { if(!queuedTimers) queuedTimers = {}; isNew && debugLog("addTimer", "Deferred", [ID, repeat, delay, func]); queuedTimers[ID] = [Date.now(), repeat, func, delay, args]; } else { var browserTimerID = setTimeout_old(execTimer, delay, ID, repeat, func, delay, args); isNew && debugLog("addTimer", "Scheduled", [ID, repeat, delay, func]); activeTimers[ID] = [repeat, func, delay, args, browserTimerID]; } return ID; } function execTimer(ID, repeat, func, delay, args) { delete activeTimers[ID]; debugLog("execTimer", "Executing", ID, repeat); //Re-add to the list so it can be cleared while in progress if(repeat) { addTimer(ID, repeat, func, delay, args, false); } try { if(typeof func == "string") { (function() { unsafeWindow.eval(func); }).apply(unsafeWindow); } else { func.apply(unsafeWindow, args); } } catch(ex) { /* Silence it like JS normally does */ debugLog("execTimer", "Error", arguments, ex); } } function onUserInteraction(event) { lastUserInteraction = Date.now(); //If any timers are queued, restart them if(queuedTimers) { debugLog("onUserInteraction", "Processing deferred timers", arguments, queuedTimers); try { for(var ID in queuedTimers) { //QueuedTimer format: {ID: [startTime, repeat, func, delay, args]} var timer = queuedTimers[ID]; var delay = Math.max(0, timer[0] + timer[3] - Date.now()); var browserTimerID = setTimeout_old(execTimer, delay, ID, timer[1], timer[2], timer[3], timer[4]); //ActiveTimer format: {ID: [repeat, func, delay, args, browserTimerID]} activeTimers[ID] = [timer[1], timer[2], timer[3], timer[4], browserTimerID]; delete queuedTimers[ID]; } } catch(ex) { debugLog("onUserInteraction", "Error", ex); } queuedTimers = null; } removeEventListener("mousemove", onUserInteraction); removeEventListener("keydown", onUserInteraction); setTimeout_old(function() { addEventListener("mousemove", onUserInteraction); addEventListener("keydown", onUserInteraction); }, 5000); } addEventListener("mousemove", onUserInteraction); addEventListener("keydown", onUserInteraction); unsafeWindow.setInterval = function setInterval() { var func = arguments[0]; var delay = arguments[1]; var args = Array.slice(arguments, 2); return addTimer(nextID++, true, func, delay, args, true); }; unsafeWindow.setTimeout = function setTimeout() { var func = arguments[0]; var delay = arguments[1]; var args = Array.slice(arguments, 2); return addTimer(nextID++, false, func, delay, args, true); }; function clearTimer(ID) { if(queuedTimers && typeof(queuedTimers[ID]) != "undefined") { debugLog("clearTimer", "Clearing deferred timer", arguments); delete queuedTimers[ID]; } if(typeof(activeTimers[ID]) != "undefined") { debugLog("clearTimer", "Clearing active timer", arguments); clearTimeout(activeTimers[ID][4]); delete activeTimers[ID]; } }; unsafeWindow.clearTimeout = clearTimer; unsafeWindow.clearInterval = clearTimer;