hook 过debugger

// 定义一个闭包函数,用来创建拦截函数的钩子
function Closure(injectFunction) {
    // 返回一个新函数,用于处理输入参数并调用原始函数
    return function() {
        // 如果没有传入参数,直接调用原始的 injectFunction
        if (!arguments.length)
            return injectFunction.apply(this, arguments);
        
        // 获取参数的最后一个值,并替换掉 "debugger" 字符串
        arguments[arguments.length - 1] = arguments[arguments.length - 1].replace(/debugger/g, "");

        // 调用原始函数并返回结果
        return injectFunction.apply(this, arguments);
    }
}

// --- 拦截 Function.prototype.constructor ---
// 备份原始的 Function 构造器
var oldFunctionConstructor = window.Function.prototype.constructor;

// 使用 Closure 包装 Function 构造器,并拦截 debugger
window.Function.prototype.constructor = Closure(oldFunctionConstructor);

// 为了保持代码一致性,绑定原始的 toString 方法到新构造器
// 这样可以让 toString 方法输出原始代码
window.Function.prototype.constructor.toString = oldFunctionConstructor.toString.bind(oldFunctionConstructor);


// --- 拦截 Function ---
// 备份原始 Function 对象
var oldFunction = Function;

// 替换全局 Function 对象,并拦截 debugger
window.Function = Closure(oldFunction);

// 同样,为了保持一致性,绑定原始的 toString 方法到新的 Function 对象
window.Function.toString = oldFunction.toString.bind(oldFunction);


// --- 拦截 eval ---
// 备份原始 eval 函数
var oldEval = eval;

// 使用 Closure 包装 eval 函数
window.eval = Closure(oldEval);

// 同样绑定原始的 toString 方法,以便 eval.toString() 返回原始代码
window.eval.toString = oldEval.toString.bind(oldEval);


// --- 拦截 GeneratorFunction ---
// 获取生成器函数的原型构造器(通常为 GeneratorFunction)
var oldGeneratorFunctionConstructor = Object.getPrototypeOf(function*() {}).constructor;

// 使用 Closure 包装生成器函数构造器
var newGeneratorFunctionConstructor = Closure(oldGeneratorFunctionConstructor);

// 绑定原始 toString 方法
newGeneratorFunctionConstructor.toString = oldGeneratorFunctionConstructor.toString.bind(oldGeneratorFunctionConstructor);

// 将拦截后的构造器重新定义为 GeneratorFunction 的构造器
Object.defineProperty(oldGeneratorFunctionConstructor.prototype, "constructor", {
    value: newGeneratorFunctionConstructor,
    writable: false, // 不允许修改
    configurable: true // 允许重新配置
});


// --- 拦截 AsyncFunction ---
// 获取异步函数的原型构造器(通常为 AsyncFunction)
var oldAsyncFunctionConstructor = Object.getPrototypeOf(async function() {}).constructor;

// 使用 Closure 包装异步函数构造器
var newAsyncFunctionConstructor = Closure(oldAsyncFunctionConstructor);

// 绑定原始 toString 方法
newAsyncFunctionConstructor.toString = oldAsyncFunctionConstructor.toString.bind(oldAsyncFunctionConstructor);

// 将拦截后的构造器重新定义为 AsyncFunction 的构造器
Object.defineProperty(oldAsyncFunctionConstructor.prototype, "constructor", {
    value: newAsyncFunctionConstructor,
    writable: false, // 不允许修改
    configurable: true // 允许重新配置
});

代码解释和用法

这个代码片段可以作为一个整体直接引入 JavaScript 项目中,用于检测和移除代码中的 debugger 关键字。其核心在于定义 Closure 函数,并利用该闭包创建钩子来拦截多个 JavaScript 构造器。

主要用途

  1. 移除 debugger:自动去除动态生成的 JavaScript 代码(例如通过 FunctionevalGeneratorFunctionAsyncFunction 创建的代码)中的 debugger 关键字,防止调试断点。
  2. 兼容多种函数类型:覆盖了普通函数、生成器函数和异步函数,确保不同类型的函数构造行为统一。
  3. 保留原始行为:虽然代码拦截了构造过程,但调用 .toString() 依然返回原始函数的内容,不会影响外部代码逻辑。

如何使用

可以将整个代码片段直接粘贴到 JavaScript 文件中,执行后环境中的 FunctionevalGeneratorFunctionAsyncFunction 的构造器都会自动去除 debugger

posted @ 2024-11-04 14:18  *感悟人生*  阅读(20)  评论(0编辑  收藏  举报