decky frontend lib patcher.js

Created Diff never expires
6 删除
总计
删除
单词
总计
删除
要继续使用此功能,请升级到
Diffchecker logo
Diffchecker Pro
104
6 添加
总计
添加
单词
总计
添加
要继续使用此功能,请升级到
Diffchecker logo
Diffchecker Pro
104
export let callOriginal = Symbol('DECKY_CALL_ORIGINAL');
export let callOriginal = Symbol('DECKY_CALL_ORIGINAL');
export function beforePatch(object, property, handler, options = {}) {
export function beforePatch(object, property, handler, options = {}) {
const orig = object[property];
const orig = object[property];
object[property] = function (...args) {
object[property] = (function (...args) {
handler.call(this, args);
handler.call(this, args);
const ret = patch.original.call(this, ...args);
const ret = patch.original.call(this, ...args);
if (options.singleShot) {
if (options.singleShot) {
patch.unpatch();
patch.unpatch();
}
}
return ret;
return ret;
};
});
const patch = processPatch(object, property, handler, object[property], orig);
const patch = processPatch(object, property, handler, object[property], orig);
return patch;
return patch;
}
}
export function afterPatch(object, property, handler, options = {}) {
export function afterPatch(object, property, handler, options = {}) {
const orig = object[property];
const orig = object[property];
object[property] = function (...args) {
object[property] = (function (...args) {
let ret = patch.original.call(this, ...args);
let ret = patch.original.call(this, ...args);
ret = handler.call(this, args, ret);
ret = handler.call(this, args, ret);
if (options.singleShot) {
if (options.singleShot) {
patch.unpatch();
patch.unpatch();
}
}
return ret;
return ret;
};
});
const patch = processPatch(object, property, handler, object[property], orig);
const patch = processPatch(object, property, handler, object[property], orig);
return patch;
return patch;
}
}
export function replacePatch(object, property, handler, options = {}) {
export function replacePatch(object, property, handler, options = {}) {
const orig = object[property];
const orig = object[property];
object[property] = function (...args) {
object[property] = (function (...args) {
const ret = handler.call(this, args);
const ret = handler.call(this, args);
if (ret == callOriginal)
if (ret == callOriginal)
return patch.original.call(this, ...args);
return patch.original.call(this, ...args);
if (options.singleShot) {
if (options.singleShot) {
patch.unpatch();
patch.unpatch();
}
}
return ret;
return ret;
};
});
const patch = processPatch(object, property, handler, object[property], orig);
const patch = processPatch(object, property, handler, object[property], orig);
return patch;
return patch;
}
}
function processPatch(object, property, handler, patchedFunction, original) {
function processPatch(object, property, handler, patchedFunction, original) {
Object.assign(object[property], original);
Object.assign(object[property], original);
object[property].toString = () => original.toString();
object[property].toString = () => original.toString();
Object.defineProperty(object[property], '__deckyOrig', {
Object.defineProperty(object[property], '__deckyOrig', {
get: () => patch.original,
get: () => patch.original,
set: (val) => (patch.original = val),
set: (val) => (patch.original = val),
});
});
const patch = {
const patch = {
object,
object,
property,
property,
handler,
handler,
patchedFunction,
patchedFunction,
original,
original,
hasUnpatched: false,
hasUnpatched: false,
unpatch: () => unpatch(patch),
unpatch: () => unpatch(patch),
};
};
object[property].__deckyPatch = patch;
object[property].__deckyPatch = patch;
return patch;
return patch;
}
}
function unpatch(patch) {
function unpatch(patch) {
const { object, property, handler, patchedFunction, original } = patch;
const { object, property, handler, patchedFunction, original } = patch;
if (patch.hasUnpatched)
if (patch.hasUnpatched)
throw new Error('Function is already unpatched.');
throw new Error('Function is already unpatched.');
let realProp = property;
let realProp = property;
let realObject = object;
let realObject = object;
console.debug('[Patcher] unpatching', {
console.debug('[Patcher] unpatching', {
realObject,
realObject,
realProp,
realProp,
object,
object,
property,
property,
handler,
handler,
patchedFunction,
patchedFunction,
original,
original,
isEqual: realObject[realProp] === patchedFunction,
isEqual: realObject[realProp] === patchedFunction,
});
});
while (realObject[realProp] && realObject[realProp] !== patchedFunction) {
while (realObject[realProp] && realObject[realProp] !== patchedFunction) {
realObject = realObject[realProp].__deckyPatch;
realObject = realObject[realProp].__deckyPatch;
realProp = 'original';
realProp = 'original';
console.debug('[Patcher] moved to next', {
console.debug('[Patcher] moved to next', {
realObject,
realObject,
realProp,
realProp,
object,
object,
property,
property,
handler,
handler,
patchedFunction,
patchedFunction,
original,
original,
isEqual: realObject[realProp] === patchedFunction,
isEqual: realObject[realProp] === patchedFunction,
});
});
}
}
realObject[realProp] = realObject[realProp].__deckyPatch.original;
realObject[realProp] = realObject[realProp].__deckyPatch.original;
patch.hasUnpatched = true;
patch.hasUnpatched = true;
console.debug('[Patcher] unpatched', {
console.debug('[Patcher] unpatched', {
realObject,
realObject,
realProp,
realProp,
object,
object,
property,
property,
handler,
handler,
patchedFunction,
patchedFunction,
original,
original,
isEqual: realObject[realProp] === patchedFunction,
isEqual: realObject[realProp] === patchedFunction,
});
});
}
}