Remove old monkey patch
This commit is contained in:
parent
68af931128
commit
74d78f4bca
|
@ -83,14 +83,13 @@ export default class PluginApi {
|
|||
get Utils() {
|
||||
return {
|
||||
overload: () => Utils.overload.apply(Utils, arguments),
|
||||
monkeyPatch: () => Utils.monkeyPatch.apply(Utils, arguments),
|
||||
monkeyPatchOnce: () => Utils.monkeyPatchOnce.apply(Utils, arguments),
|
||||
compatibleMonkeyPatch: () => Utils.monkeyPatchOnce.apply(Utils, arguments),
|
||||
tryParseJson: () => Utils.tryParseJson.apply(Utils, arguments),
|
||||
toCamelCase: () => Utils.toCamelCase.apply(Utils, arguments),
|
||||
compare: () => Utils.compare.apply(Utils, arguments),
|
||||
deepclone: () => Utils.deepclone.apply(Utils, arguments),
|
||||
deepfreeze: () => Utils.deepfreeze.apply(Utils, arguments)
|
||||
deepfreeze: () => Utils.deepfreeze.apply(Utils, arguments),
|
||||
removeFromArray: () => Utils.removeFromArray.apply(Utils, arguments),
|
||||
defineSoftGetter: () => Utils.defineSoftGetter.apply(Utils, arguments)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,169 +0,0 @@
|
|||
/**
|
||||
* BetterDiscord Monkeypatch
|
||||
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
|
||||
* All rights reserved.
|
||||
* https://betterdiscord.net
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import { ClientLogger as Logger } from './logger';
|
||||
|
||||
const patchedFunctions = new WeakMap();
|
||||
|
||||
export class PatchedFunction {
|
||||
constructor(object, methodName, replaceOriginal = true) {
|
||||
if (patchedFunctions.has(object[methodName])) {
|
||||
const patchedFunction = patchedFunctions.get(object[methodName]);
|
||||
if (replaceOriginal) patchedFunction.replaceOriginal();
|
||||
return patchedFunction;
|
||||
}
|
||||
|
||||
this.object = object;
|
||||
this.methodName = methodName;
|
||||
this.patches = [];
|
||||
this.originalMethod = object[methodName];
|
||||
this.replaced = false;
|
||||
|
||||
const patchedFunction = this;
|
||||
this.replace = function(...args) {
|
||||
patchedFunction.call(this, arguments);
|
||||
};
|
||||
|
||||
patchedFunctions.set(object[methodName], this);
|
||||
patchedFunctions.set(this.replace, this);
|
||||
|
||||
if (replaceOriginal)
|
||||
this.replaceOriginal();
|
||||
}
|
||||
|
||||
addPatch(patch) {
|
||||
if (!this.patches.includes(patch))
|
||||
this.patches.push(patch);
|
||||
}
|
||||
|
||||
removePatch(patch, restoreOriginal = true) {
|
||||
let i = 0;
|
||||
while (this.patches[i]) {
|
||||
if (this.patches[i] !== patch) i++;
|
||||
else this.patches.splice(i, 1);
|
||||
}
|
||||
|
||||
if (!this.patches.length && restoreOriginal)
|
||||
this.restoreOriginal();
|
||||
}
|
||||
|
||||
replaceOriginal() {
|
||||
if (this.replaced) return;
|
||||
this.object[this.methodName] = Object.assign(this.replace, this.object[this.methodName]);
|
||||
this.replaced = true;
|
||||
}
|
||||
|
||||
restoreOriginal() {
|
||||
if (!this.replaced) return;
|
||||
this.object[this.methodName] = Object.assign(this.object[this.methodName], this.replace);
|
||||
this.replaced = false;
|
||||
}
|
||||
|
||||
call(_this, args) {
|
||||
const data = {
|
||||
this: _this,
|
||||
arguments: args,
|
||||
return: undefined,
|
||||
originalMethod: this.originalMethod,
|
||||
callOriginalMethod: () => {
|
||||
Logger.log('MonkeyPatch', [`Calling original method`, this, data]);
|
||||
data.return = this.originalMethod.apply(data.this, data.arguments);
|
||||
}
|
||||
};
|
||||
|
||||
// Work through the patches calling each patch's hooks as if each patch had overridden the previous patch
|
||||
for (let patch of this.patches) {
|
||||
let callOriginalMethod = data.callOriginalMethod;
|
||||
data.callOriginalMethod = () => {
|
||||
const patch_data = Object.assign({}, data, {
|
||||
callOriginalMethod, patch
|
||||
});
|
||||
patch.call(patch_data);
|
||||
data.arguments = patch_data.arguments;
|
||||
data.return = patch_data.return;
|
||||
};
|
||||
}
|
||||
|
||||
data.callOriginalMethod();
|
||||
return data.return;
|
||||
}
|
||||
}
|
||||
|
||||
export class Patch {
|
||||
constructor(patchedFunction, options, f) {
|
||||
this.patchedFunction = patchedFunction;
|
||||
|
||||
if (options instanceof Function) {
|
||||
f = options;
|
||||
options = {
|
||||
instead: data => {
|
||||
f.call(this, data, ...data.arguments);
|
||||
}
|
||||
};
|
||||
} else if (options === 'before') {
|
||||
options = {
|
||||
before: data => {
|
||||
f.call(this, data, ...data.arguments);
|
||||
}
|
||||
};
|
||||
} else if (options === 'after') {
|
||||
options = {
|
||||
after: data => {
|
||||
f.call(this, data, ...data.arguments);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
this.before = options.before || undefined;
|
||||
this.instead = options.instead || undefined;
|
||||
this.after = options.after || undefined;
|
||||
this.once = options.once || false;
|
||||
this.silent = options.silent || false;
|
||||
this.suppressErrors = typeof options.suppressErrors === 'boolean' ? options.suppressErrors : true;
|
||||
}
|
||||
|
||||
call(data) {
|
||||
if (this.once)
|
||||
this.cancel();
|
||||
|
||||
this.callBefore(data);
|
||||
this.callInstead(data);
|
||||
this.callAfter(data);
|
||||
}
|
||||
|
||||
callBefore(data) {
|
||||
if (this.before)
|
||||
this.callHook('before', this.before, data);
|
||||
}
|
||||
|
||||
callInstead(data) {
|
||||
if (this.instead)
|
||||
this.callHook('instead', this.instead, data);
|
||||
else data.callOriginalMethod();
|
||||
}
|
||||
|
||||
callAfter(data) {
|
||||
if (this.after)
|
||||
this.callHook('after', this.after, data);
|
||||
}
|
||||
|
||||
callHook(hook, f, data) {
|
||||
try {
|
||||
f.call(this, data, ...data.arguments);
|
||||
} catch (err) {
|
||||
Logger.log('MonkeyPatch', [`Error thrown in ${hook} hook of`, this, '- :', err]);
|
||||
if (!this.suppressErrors) throw err;
|
||||
}
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.patchedFunction.removePatch(this);
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import { PatchedFunction, Patch } from './monkeypatch';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import _ from 'lodash';
|
||||
|
@ -23,90 +22,6 @@ export class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Monkey-patches an object's method.
|
||||
* @param {Object} object The object containing the function to monkey patch
|
||||
* @param {String} methodName The name of the method to monkey patch
|
||||
* @param {Object|String|Function} options Options to pass to the Patch constructor
|
||||
* @param {Function} function If {options} is either "before" or "after", this function will be used as that hook
|
||||
*/
|
||||
static monkeyPatch(object, methodName, options, f) {
|
||||
const patchedFunction = new PatchedFunction(object, methodName);
|
||||
const patch = new Patch(patchedFunction, options, f);
|
||||
patchedFunction.addPatch(patch);
|
||||
return patch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Monkey-patches an object's method and returns a promise that will be resolved with the data object when the method is called.
|
||||
* This can only be used to get the arguments and return data. If you want to change anything, call Utils.monkeyPatch with the once option set to true.
|
||||
*/
|
||||
static monkeyPatchOnce(object, methodName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.monkeyPatch(object, methodName, 'after', data => {
|
||||
data.patch.cancel();
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Monkey-patches an object's method and returns a promise that will be resolved with the data object when the method is called.
|
||||
* You will have to call data.callOriginalMethod() if you wants the original method to be called.
|
||||
*/
|
||||
static monkeyPatchAsync(object, methodName, callback) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.monkeyPatch(object, methodName, data => {
|
||||
data.patch.cancel();
|
||||
|
||||
data.promise = data.return = callback ? Promise.all(callback.call(global, data, ...data.arguments)) : new Promise((resolve, reject) => {
|
||||
data.resolve = resolve;
|
||||
data.reject = reject;
|
||||
});
|
||||
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Monkeypatch function that is compatible with samogot's Lib Discord Internals.
|
||||
* Don't use this for writing new plugins as it will eventually be removed!
|
||||
*/
|
||||
static compatibleMonkeyPatch(what, methodName, options) {
|
||||
const { before, instead, after, once = false, silent = false } = options;
|
||||
const cancelPatch = () => patch.cancel();
|
||||
|
||||
const compatible_function = _function => data => {
|
||||
const compatible_data = {
|
||||
thisObject: data.this,
|
||||
methodArguments: data.arguments,
|
||||
returnValue: data.return,
|
||||
cancelPatch,
|
||||
originalMethod: data.originalMethod,
|
||||
callOriginalMethod: () => data.callOriginalMethod()
|
||||
};
|
||||
try {
|
||||
_function(compatible_data);
|
||||
data.arguments = compatible_data.methodArguments;
|
||||
data.return = compatible_data.returnValue;
|
||||
} catch (err) {
|
||||
data.arguments = compatible_data.methodArguments;
|
||||
data.return = compatible_data.returnValue;
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
const patch = this.monkeyPatch(what, methodName, {
|
||||
before: !instead && before ? compatible_function(before) : undefined,
|
||||
instead: instead ? compatible_function(instead) : undefined,
|
||||
after: !instead && after ? compatible_function(after) : undefined,
|
||||
once
|
||||
});
|
||||
|
||||
return cancelPatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to parse a string as JSON.
|
||||
* @param {String} json The string to parse
|
||||
|
|
Loading…
Reference in New Issue