Skip to content

Instantly share code, notes, and snippets.

@notmike101
Last active May 2, 2023 02:35
Show Gist options
  • Save notmike101/55e3e4b64a35de3fb2ab8894744c6d2b to your computer and use it in GitHub Desktop.
Save notmike101/55e3e4b64a35de3fb2ab8894744c6d2b to your computer and use it in GitHub Desktop.
JavaScript - General Monkeypatch
import { patch } from './monkeyPatch';
(() => {
patch(EventTarget, 'dispatchEvent', function() {
const args = Array.from(arguments);
const customEvent = new CustomEvent('GLOBAL_LOGGER', {
details: args[0],
});
this.original.apply(this.sender, [customEvent, args.slice(0, 1)]);
this.original.apply(this.sender, arguments);
});
patch(EventTarget, 'dispatchEvent', function() {
const args = Array.from(arguments);
console.log('called dispatchEvent w/ args', args);
});
document.addEventListener('GLOBAL_LOGGER', (event) => {
console.log('GLOBAL_LOGGER_EVENT', event);
});
document.addEventListener('hello', (event) => {
console.log('hello event listener', event);
});
document.dispatchEvent(new CustomEvent('hello', {
detail: 'world',
}));
})();
/**
* Patch a function on a class with a new function
*
* @param targetClass - Class to patch
* @param targetFunctionName - Function to patch
* @param patchFunction - Function to patch with
*/
export const patch = function (targetClass, targetFunctionName, patchFunction) {
targetClass.prototype._originalFunctions ??= new Map();
targetClass.prototype._patches ??= new Map();
if (!targetClass.prototype._originalFunctions.has(targetFunctionName)) {
targetClass.prototype._originalFunctions.set(targetFunctionName, targetClass.prototype[targetFunctionName]);
}
if (!targetClass.prototype._patches.has(targetFunctionName)) {
targetClass.prototype._patches.set(targetFunctionName, new Set());
}
targetClass.prototype._patches.get(targetFunctionName).add(patchFunction);
const proxy = new Proxy(targetClass.prototype[targetFunctionName], {
apply: function (target, thisArg, argumentsList) {
const context = { sender: thisArg, original: targetClass.prototype._originalFunctions.get(targetFunctionName) };
targetClass.prototype._patches.get(targetFunctionName).forEach((patchFunction) => {
patchFunction.apply(context, argumentsList);
});
}
});
targetClass.prototype[targetFunctionName] = proxy;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment