您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Makes GM_xmlhttpRequest and GM_download queued
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/460385/1221394/GM%20web%20hooks.js
- /* eslint-disable no-multi-spaces */
- /* eslint-disable no-native-reassign */
- /* eslint-disable no-redeclare */
- // ==UserScript==
- // @name GM web hooks
- // @namespace GM-web-hooks
- // @version 0.1.2
- // @description Makes GM_xmlhttpRequest and GM_download queued
- // @author PY-DNG
- // @license GPL-v3
- // ==/UserScript==
- /* global LogLevel DoLog Err $ $All $CrE $AEL addStyle destroyEvent copyProp copyProps parseArgs escJsStr replaceText getUrlArgv dl_browser dl_GM AsyncManager */
- /* global GM_xmlhttpRequest GM_download */
- let [GMXHRHook, GMDLHook] = (function __MAIN__() {
- 'use strict';
- return [GMXHRHook, GMDLHook];
- // GM_XHR HOOK: The number of running GM_XHRs in a time must under maxXHR
- // Returns the abort function to stop the request anyway(no matter it's still waiting, or requesting)
- // (If the request is invalid, such as url === '', will return false and will NOT make this request)
- // If the abort function called on a request that is not running(still waiting or finished), there will be NO onabort event
- // Requires: function delItem(){...} & function uniqueIDMaker(){...}
- function GMXHRHook(maxXHR=5) {
- const GM_XHR = GM_xmlhttpRequest;
- const getID = function() {
- let id = 0;
- return () => id++;
- }();
- let todoList = [], ongoingList = [];
- GM_xmlhttpRequest = safeGMxhr;
- function safeGMxhr() {
- // Get an id for this request, arrange a request object for it.
- const id = getID();
- const request = {id: id, args: arguments, aborter: null};
- // Deal onload function first
- dealEndingEvents(request);
- /* DO NOT DO THIS! KEEP ITS ORIGINAL PROPERTIES!
- // Stop invalid requests
- if (!validCheck(request)) {
- return false;
- }
- */
- // Judge if we could start the request now or later?
- todoList.push(request);
- checkXHR();
- return makeAbortFunc(id);
- // Decrease activeXHRCount while GM_XHR onload;
- function dealEndingEvents(request) {
- const e = request.args[0];
- // onload event
- const oriOnload = e.onload;
- e.onload = function() {
- reqFinish(request.id);
- checkXHR();
- oriOnload ? oriOnload.apply(null, arguments) : function() {};
- }
- // onerror event
- const oriOnerror = e.onerror;
- e.onerror = function() {
- reqFinish(request.id);
- checkXHR();
- oriOnerror ? oriOnerror.apply(null, arguments) : function() {};
- }
- // ontimeout event
- const oriOntimeout = e.ontimeout;
- e.ontimeout = function() {
- reqFinish(request.id);
- checkXHR();
- oriOntimeout ? oriOntimeout.apply(null, arguments) : function() {};
- }
- // onabort event
- const oriOnabort = e.onabort;
- e.onabort = function() {
- reqFinish(request.id);
- checkXHR();
- oriOnabort ? oriOnabort.apply(null, arguments) : function() {};
- }
- }
- // Check if the request is invalid
- function validCheck(request) {
- const e = request.args[0];
- if (!e.url) {
- return false;
- }
- return true;
- }
- // Call a XHR from todoList and push the request object to ongoingList if called
- function checkXHR() {
- if (ongoingList.length >= maxXHR) {return false;};
- if (todoList.length === 0) {return false;};
- const req = todoList.shift();
- const reqArgs = req.args;
- const aborter = GM_XHR.apply(null, reqArgs);
- req.aborter = aborter;
- ongoingList.push(req);
- return req;
- }
- // Make a function that aborts a certain request
- function makeAbortFunc(id) {
- return function() {
- let i;
- // Check if the request haven't been called
- for (i = 0; i < todoList.length; i++) {
- const req = todoList[i];
- if (req.id === id) {
- // found this request: haven't been called
- todoList.splice(i, 1);
- return true;
- }
- }
- // Check if the request is running now
- for (i = 0; i < ongoingList.length; i++) {
- const req = todoList[i];
- if (req.id === id) {
- // found this request: running now
- req.aborter();
- reqFinish(id);
- checkXHR();
- }
- }
- // Oh no, this request is already finished...
- return false;
- }
- }
- // Remove a certain request from ongoingList
- function reqFinish(id) {
- let i;
- for (i = 0; i < ongoingList.length; i++) {
- const req = ongoingList[i];
- if (req.id === id) {
- ongoingList = ongoingList.splice(i, 1);
- return true;
- }
- }
- return false;
- }
- }
- }
- // GM_DL HOOK: The number of running GM_download in a time must under maxDL
- // Returns the abort function to stop the request anyway(no matter it's still waiting, or requesting)
- // (If the request is invalid, such as url === '', will return false and will NOT make this request)
- // If the abort function called on a request that is not running(still waiting or finished), there will be NO onabort event
- // Requires: function delItem(){...} & function uniqueIDMaker(){...}
- function GMDLHook(maxDL=5) {
- const GM_DL = GM_download;
- const getID = function() {
- let id = 0;
- return () => id++;
- }();
- let todoList = [], ongoingList = [];
- GM_download = safeGMdl;
- function safeGMdl() {
- // Get an id for this request, arrange a request object for it.
- const id = getID();
- const request = {id: id, args: arguments, aborter: null};
- // Deal onload function first
- dealEndingEvents(request);
- /* DO NOT DO THIS! KEEP ITS ORIGINAL PROPERTIES!
- // Stop invalid requests
- if (!validCheck(request)) {
- return false;
- }
- */
- // Judge if we could start the request now or later?
- todoList.push(request);
- checkDL();
- return makeAbortFunc(id);
- // Decrease activeXHRCount while GM_DL onload;
- function dealEndingEvents(request) {
- const e = request.args[0];
- // onload event
- const oriOnload = e.onload;
- e.onload = function() {
- reqFinish(request.id);
- checkDL();
- oriOnload ? oriOnload.apply(null, arguments) : function() {};
- }
- // onerror event
- const oriOnerror = e.onerror;
- e.onerror = function() {
- reqFinish(request.id);
- checkDL();
- oriOnerror ? oriOnerror.apply(null, arguments) : function() {};
- }
- // ontimeout event
- const oriOntimeout = e.ontimeout;
- e.ontimeout = function() {
- reqFinish(request.id);
- checkDL();
- oriOntimeout ? oriOntimeout.apply(null, arguments) : function() {};
- }
- // onabort event
- const oriOnabort = e.onabort;
- e.onabort = function() {
- reqFinish(request.id);
- checkDL();
- oriOnabort ? oriOnabort.apply(null, arguments) : function() {};
- }
- }
- // Check if the request is invalid
- function validCheck(request) {
- const e = request.args[0];
- if (!e.url) {
- return false;
- }
- return true;
- }
- // Call a XHR from todoList and push the request object to ongoingList if called
- function checkDL() {
- if (ongoingList.length >= maxDL) {return false;};
- if (todoList.length === 0) {return false;};
- const req = todoList.shift();
- const reqArgs = req.args;
- const aborter = GM_DL.apply(null, reqArgs);
- req.aborter = aborter;
- ongoingList.push(req);
- return req;
- }
- // Make a function that aborts a certain request
- function makeAbortFunc(id) {
- return function() {
- let i;
- // Check if the request haven't been called
- for (i = 0; i < todoList.length; i++) {
- const req = todoList[i];
- if (req.id === id) {
- // found this request: haven't been called
- todoList.splice(i, 1);
- return true;
- }
- }
- // Check if the request is running now
- for (i = 0; i < ongoingList.length; i++) {
- const req = todoList[i];
- if (req.id === id) {
- // found this request: running now
- req.aborter();
- reqFinish(id);
- checkDL();
- }
- }
- // Oh no, this request is already finished...
- return false;
- }
- }
- // Remove a certain request from ongoingList
- function reqFinish(id) {
- let i;
- for (i = 0; i < ongoingList.length; i++) {
- const req = ongoingList[i];
- if (req.id === id) {
- ongoingList = ongoingList.splice(i, 1);
- return true;
- }
- }
- return false;
- }
- }
- }
- })();