Skip to content

Instantly share code, notes, and snippets.

@MicroCBer
Last active July 18, 2023 12:52
Show Gist options
  • Save MicroCBer/02b6aeb584601f718f43b8c9fca0df32 to your computer and use it in GitHub Desktop.
Save MicroCBer/02b6aeb584601f718f43b8c9fca0df32 to your computer and use it in GitHub Desktop.
Inspect operations on an object
const apiMap = {}
function make_proxy(obj, path = '') {
if (typeof obj === "object" || typeof obj === "function")
return new Proxy(obj, {
get(target, prop) {
if (prop === '_origin_') return obj._origin_ ?? obj;
const fullPath = path ? `${path}.${String(prop)}` : String(prop);
const value = target[prop];
if (prop === 'prototype') return value;
if (typeof value === 'function') {
return make_proxy(value, fullPath);
} else if (typeof value === 'object' && value !== null) {
return make_proxy(value, fullPath);
}
console.log(`[GET] ${fullPath}:`, value);
return value;
},
apply(target, thisArg, args) {
const fullPath = path ? `${path}()` : '()';
console.log(`[CALL] ${fullPath}`, args);
const ret = make_proxy(target.apply(thisArg._origin_, args), fullPath);
apiMap[fullPath] = ret;
console.log(` - ${fullPath}`, ret);
return ret;
}
});
return obj;
}
globalThis.apiMap = apiMap
const lowee = {
_name: 'LOWII',
hook:{
func(origin){
if(!origin[lowee._name]) {
const hookObj = {
origin, hooked: function(...args){
for(const proc of hookObj._processorBefore){
let returnFlag = false, returnValue;
const ctx = {
args,
return(v){
returnFlag = true;
returnValue=v;
},
removeSelf(){
hookObj._processorBefore.delete(proc)
}
}
proc.call(this, ...args, ctx)
if(returnFlag) return returnValue;
if(proc.__once__) ctx.removeSelf();
}
let returnValue = hookObj.origin.call(this, ...args);
for(const proc of hookObj._processorAfter){
const ctx = {
args, returnValue,
return(v){
returnValue=v;
},
removeSelf(){
hookObj._processorAfter.delete(proc)
}
}
proc.call(this, ...args, ctx)
if(proc.__once__) ctx.removeSelf();
}
return returnValue;
}, _processorBefore: new Set(), _processorAfter: new Set(),
before(func){
hookObj._processorBefore.add(func);
return hookObj;
},
after(func){
hookObj._processorAfter.add(func);
return hookObj;
},
beforeOnce(func){
hookObj._processorBefore.add(func);
func.__once__=true;
return hookObj;
},
afterOnce(func){
hookObj._processorAfter.add(func);
func.__once__=true;
return hookObj;
},
removeBefore(func){
hookObj._processorBefore.delete(index);
return hookObj;
},
removeAfter(func){
hookObj._processorAfter.delete(index);
return hookObj;
}
};
hookObj.hook = hookObj;
hookObj.hooked[lowee._name] = hookObj;
return hookObj
} else {
return origin[lowee._name];
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment