You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
50 lines
1.4 KiB
50 lines
1.4 KiB
// @flow
|
|
function monkeyPatch(name: string, parentObj: Object, patches: Object): ()=>void {
|
|
const injId = Symbol()
|
|
const before = patches["before"];
|
|
const instead = patches["instead"];
|
|
const after = patches["after"];
|
|
const handler = {
|
|
apply: (target, thisArg, [ctx, args]) => {
|
|
if (before !== undefined) before.apply(ctx, args);
|
|
const res = (patches["instead"] !== undefined) ? instead.apply(ctx, [target.bind(ctx), ...args]) : target.apply(ctx, args)
|
|
if (after === undefined) return res
|
|
return after.apply(ctx, [res].concat(args));
|
|
}
|
|
};
|
|
const prox = new Proxy(parentObj[name], handler);
|
|
const orig = parentObj[name];
|
|
parentObj[name] = function() {
|
|
return prox(this, arguments);
|
|
};
|
|
const unpatch = () => {
|
|
parentObj[name] = orig;
|
|
}
|
|
parentObj[injId] = {
|
|
name: name,
|
|
orig: orig,
|
|
unpatch: unpatch
|
|
};
|
|
return unpatch;
|
|
}
|
|
|
|
function before(name: string, parentObj: Object, func: (...args: mixed[])=>void): ()=>void {
|
|
return monkeyPatch(name, parentObj, {before: func})
|
|
}
|
|
|
|
function instead(name: string, parentObj: Object, func: (orig: (any)=>any, ...args: mixed[])=>any): ()=>void {
|
|
return monkeyPatch(name, parentObj, {instead: func})
|
|
}
|
|
|
|
function after(name: string, parentObj: Object, func: (res: any, ...args: mixed[])=>any): ()=>void {
|
|
return monkeyPatch(name, parentObj, {after: func})
|
|
}
|
|
|
|
module.exports = {
|
|
monkeyPatch,
|
|
before,
|
|
instead,
|
|
after
|
|
}
|
|
|