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;