- // ==UserScript==
- // @name MonkeyDebugger
- // @namespace https://github.com/JiyuShao/greasyfork-scripts
- // @version 2024-07-18
- // @description Debug js using monkey patch
- // @author Jiyu Shao <jiyu.shao@gmail.com>
- // @license MIT
- // @match *://*/*
- // @run-at document-start
- // @grant unsafeWindow
- // @grant GM_registerMenuCommand
- // @grant GM_unregisterMenuCommand
- // @grant GM_setValue
- // @grant GM_getValue
- // @grant GM_addValueChangeListener
- // @require https://update.gf.qytechs.cn/scripts/496315/1392531/QuickMenu.js
- // ==/UserScript==
-
- /* eslint-disable no-eval */
- (function () {
- 'use strict';
-
- // 定义通用的补丁代码给 new Function 与 eval 使用
- const patchCode = `
- debugger;
- `;
-
- // 保存原始的 Function 构造器
- const originalFunction = unsafeWindow.Function.prototype.constructor;
- const addFnPatchCode = function (fn) {
- const finalFn = function (...args) {
- if (!args.length) return fn.apply(this, args);
- args[args.length - 1] = `${patchCode}; ${args[args.length - 1]}`;
- return fn.apply(this, args);
- };
- finalFn.prototype = originalFunction.prototype;
- Object.defineProperty(finalFn.prototype, 'constructor', {
- value: finalFn,
- writable: true,
- configurable: true,
- });
- return finalFn;
- };
- const removeFnDebugger = function () {
- const finalFn = function (...args) {
- if (!args.length) return originalFunction.apply(this, args);
- args[args.length - 1] = args[args.length - 1].replace(/debugger/g, '');
- return originalFunction.apply(this, args);
- };
- finalFn.prototype = originalFunction.prototype;
- Object.defineProperty(finalFn.prototype, 'constructor', {
- value: finalFn,
- writable: true,
- configurable: true,
- });
- return finalFn;
- };
- QuickMenu.add({
- name: '开启 Function 调试',
- type: 'toggle',
- shouldInitRun: true,
- shouldAddMenu: () => {
- return unsafeWindow === unsafeWindow.top;
- },
- callback: (value) => {
- if (value === 'on') {
- // 替换全局的 Function constructor
- unsafeWindow.Function = addFnPatchCode();
- } else if (value === 'off') {
- // 替换全局的 Function constructor
- unsafeWindow.Function = removeFnDebugger();
- }
- },
- });
-
- // 保存原始的 eval 函数
- const originalEval = unsafeWindow.eval;
- const addEvalPatchCode = function () {
- return function (...args) {
- if (!args.length) return originalEval.apply(this, args);
- args[0] = `${patchCode}; ${args[0]}`;
- return originalEval.apply(this, args);
- };
- };
- const removeEvalDebugger = function () {
- return function (...args) {
- if (!args.length) return originalEval.apply(this, args);
- args[0] = args[0].replace(/debugger/g, '');
- return originalEval.apply(this, args);
- };
- };
- QuickMenu.add({
- name: '开启 eval 调试',
- type: 'toggle',
- shouldInitRun: true,
- shouldAddMenu: () => {
- return unsafeWindow === unsafeWindow.top;
- },
- callback: (value) => {
- if (value === 'on') {
- // 替换全局的 eval 函数
- unsafeWindow.eval = addEvalPatchCode();
- } else if (value === 'off') {
- unsafeWindow.eval = removeEvalDebugger();
- }
- },
- });
-
- const originalDefineProperty = unsafeWindow.Object.defineProperty;
- // 覆盖 `Error` 对象的 `message` 属性的 getter
- const removeErrorMessageGetter = () => {
- return function (obj, prop, descriptor) {
- if (obj instanceof Error && prop === 'message') {
- delete descriptor.get;
- delete descriptor.set;
- }
- return originalDefineProperty.call(Object, obj, prop, descriptor);
- };
- };
- // https://github.com/fz6m/console-ban/tree/master
- QuickMenu.add({
- name: '解除 console-ban 限制',
- type: 'toggle',
- shouldInitRun: true,
- shouldAddMenu: () => {
- return unsafeWindow === unsafeWindow.top;
- },
- callback: (value) => {
- if (value === 'on') {
- unsafeWindow.Object.defineProperty = removeErrorMessageGetter();
- } else if (value === 'off') {
- unsafeWindow.Object.defineProperty = originalDefineProperty;
- }
- },
- });
-
- const originalFetch = unsafeWindow.fetch;
- QuickMenu.add({
- name: 'Fetch with credentials',
- type: 'toggle',
- shouldInitRun: true,
- shouldAddMenu: () => {
- return true;
- },
- callback: (value) => {
- if (value === 'on') {
- unsafeWindow.fetch = function (input, init) {
- init = init || {};
- init.credentials = 'include';
- return originalFetch(input, init);
- };
- } else if (value === 'off') {
- unsafeWindow.fetch = originalFetch;
- }
- },
- });
-
- QuickMenu.add({
- name: '清空菜单缓存',
- type: 'button',
- shouldInitRun: false,
- shouldAddMenu: () => {
- return unsafeWindow === unsafeWindow.top;
- },
- callback: () => {
- QuickMenu.clearStore();
- },
- });
- })();