js代理函数

const hook = true, compress = true

delete process
delete global
delete require
delete module
delete Buffer
delete __dirname
delete __file__

const hook_funcs = ['toString', 'hasOwnProperty']
const constructor_excepts = [Date, RegExp]

const $toString = Function.toString;
const myFunction_toString_symbol = Symbol('('.concat('', ')_', (Math.random() + '').toString(36)));
const myToString = function () {
    return typeof this == 'function' && this[myFunction_toString_symbol] || (result = $toString.call(this), compress ? result.replace(/\n/g, '').replace(/ /g, '') : result);
};

function set_native(func, key, value) {
    return Object.defineProperty(func, key, {
        "enumerable": false,
        "configurable": true,
        "writable": true,
        "value": value
    })
};
delete Function.prototype['toString'];
set_native(Function.prototype, "toString", myToString);
set_native(Function.prototype.toString, myFunction_toString_symbol, "function toString() { [native code] }");
function func_set_natvie(func) {
    return set_native(func, myFunction_toString_symbol, `function ${myFunction_toString_symbol, func.name || ''}() { [native code] }`);
}

let _origin_string_idx_of = String.prototype.indexOf
String.prototype.indexOf = function () {
    let result = _origin_string_idx_of.apply(this, arguments)
    console.log(`[string ${this}].indexOf`, arguments, result)
    return result
}
func_set_natvie(String.prototype.indexOf)

let _origin_regexp_test = RegExp.prototype.test
RegExp.prototype.test = function () {
    let result = _origin_regexp_test.apply(this, arguments)
    console.log(`[regexp ${this}].test`, arguments, result)
    return result
}
func_set_natvie(RegExp.prototype.test)

let _stringify_prototypes = []

function _stringify(e) {
    let ret = _stringify_prototypes.find(k => e instanceof k)
    return ret ? `[object ${ret.name}]` : e
}

function common_proxy(obj, opts = {}) {
    let {
        identifier,
        prototype,
        stringify,
        native
    } = opts
    if (native) {
        func_set_natvie(obj)
    }
    if (!hook) return obj
    let obj_type = typeof obj
    if (obj_type != "object" && obj_type != "function") return

    if (!identifier) {
        if (prototype) {
            identifier = prototype.name + '.prototype.' + obj.name
        } else {
            identifier = obj instanceof Function ? `[function ${obj.name}]` : obj.toString()
        }
    }
    if (!identifier.startsWith('[')) {
        identifier = `[` + identifier + ']'
    }
    if (stringify) {
        _stringify_prototypes.push(obj)
    }
    return new Proxy(obj, {
        construct() {
            let result = Reflect.construct.apply(this, arguments);
            console.log(`${identifier}.new => `, arguments, result);
            return constructor_excepts.find(e => result instanceof e) ? result : common_proxy(result)
        },
        apply() {
            try {
                let result = Reflect.apply.apply(this, arguments);
                console.log(`${identifier}.apply => `, _stringify(arguments[1]), arguments[2].map(e => _stringify(e)), result);
                return result
            } catch (e) {
                console.log(`${identifier}.apply => `, _stringify(arguments[1]), arguments[2].map(e => _stringify(e)), e.message);
                throw e
            }
        },
        // 代理这个对象的属性设置  a.b , a["b"]
        get: function () {
            let result = Reflect.get.apply(this, arguments)
            if (typeof arguments[1] == "string" && !arguments[1].startsWith("_")) {
                if (hook_funcs.includes(arguments[1])) {
                    result = common_proxy(result, {
                        identifier: identifier + `.` + arguments[1]
                    })
                }
                console.log(
                    `${identifier}.get => `, arguments[1], _stringify(result)
                )
            }
            return result
        },
        // 代理这个对象的属性设置  a.b = 1, a["b"]  1
        set: function () {
            let result = Reflect.set.apply(this, arguments)
            if (typeof arguments[1] == "string" && !arguments[1].startsWith("_")) {
                console.log(`${identifier}.set => `, arguments[1], _stringify(arguments[2]));
            }
            return result
        },
        // in 操作符的捕捉器  "xx" in a
        has: function () {
            let result = Reflect.has.apply(this, arguments)
            console.log(`${identifier}.has => `, arguments[1], result);
            return result
        },
        // Object.getOwnPropertyNames(a) 方法和 Object.getOwnPropertySymbols(a) 方法的捕捉器。
        ownKeys: function () {
            let result = Reflect.ownKeys.apply(this, arguments)
            console.log(`${identifier}.ownKeys => `, result.length);
            return result
        },
        // delete a.xxx
        deleteProperty: function () {
            let result = Reflect.deleteProperty.apply(this, arguments)
            console.log(`${identifier}.delete => `, arguments, result);
            return result
        },
    })
}

class Window {
    constructor() {}
    get[Symbol.toStringTag]() {
        return "Window"
    }
}

window = common_proxy(new Window)
window.Window = common_proxy(Window, {
    native: true,
    stringify: true
})

window.self = window.window = window;
posted @ 2024-09-12 09:24  anyiya  阅读(4)  评论(0编辑  收藏  举报