feat(patcher): Grouped replacements (#2009)

Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Co-authored-by: V <vendicated@riseup.net>
This commit is contained in:
Jack 2023-11-22 01:23:21 -05:00 committed by GitHub
parent 7b24c8ac69
commit 93a95b6d56
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 6 deletions

View file

@ -41,6 +41,8 @@ export interface Patch {
all?: boolean; all?: boolean;
/** Do not warn if this patch did no changes */ /** Do not warn if this patch did no changes */
noWarn?: boolean; noWarn?: boolean;
/** Only apply this set of replacements if all of them succeed. Use this if your replacements depend on each other */
group?: boolean;
predicate?(): boolean; predicate?(): boolean;
} }

View file

@ -204,6 +204,9 @@ function patchFactories(factories: Record<string | number, (module: { exports: a
if (code.includes(patch.find)) { if (code.includes(patch.find)) {
patchedBy.add(patch.plugin); patchedBy.add(patch.plugin);
const previousMod = mod;
const previousCode = code;
// we change all patch.replacement to array in plugins/index // we change all patch.replacement to array in plugins/index
for (const replacement of patch.replacement as PatchReplacement[]) { for (const replacement of patch.replacement as PatchReplacement[]) {
if (replacement.predicate && !replacement.predicate()) continue; if (replacement.predicate && !replacement.predicate()) continue;
@ -214,12 +217,22 @@ function patchFactories(factories: Record<string | number, (module: { exports: a
try { try {
const newCode = executePatch(replacement.match, replacement.replace as string); const newCode = executePatch(replacement.match, replacement.replace as string);
if (newCode === code && !patch.noWarn) { if (newCode === code) {
if (!patch.noWarn) {
(window.explosivePlugins ??= new Set<string>()).add(patch.plugin); (window.explosivePlugins ??= new Set<string>()).add(patch.plugin);
logger.warn(`Patch by ${patch.plugin} had no effect (Module id is ${id}): ${replacement.match}`); logger.warn(`Patch by ${patch.plugin} had no effect (Module id is ${id}): ${replacement.match}`);
if (IS_DEV) { if (IS_DEV) {
logger.debug("Function Source:\n", code); logger.debug("Function Source:\n", code);
} }
}
if (patch.group) {
logger.warn(`Undoing patch ${patch.find} by ${patch.plugin} because replacement ${replacement.match} had no effect`);
code = previousCode;
mod = previousMod;
patchedBy.delete(patch.plugin);
break;
}
} else { } else {
code = newCode; code = newCode;
mod = (0, eval)(`// Webpack Module ${id} - Patched by ${[...patchedBy].join(", ")}\n${newCode}\n//# sourceURL=WebpackModule${id}`); mod = (0, eval)(`// Webpack Module ${id} - Patched by ${[...patchedBy].join(", ")}\n${newCode}\n//# sourceURL=WebpackModule${id}`);
@ -259,9 +272,17 @@ function patchFactories(factories: Record<string | number, (module: { exports: a
const [titleFmt, ...titleElements] = Logger.makeTitle("white", "Diff"); const [titleFmt, ...titleElements] = Logger.makeTitle("white", "Diff");
logger.errorCustomFmt(titleFmt + fmt, ...titleElements, ...elements); logger.errorCustomFmt(titleFmt + fmt, ...titleElements, ...elements);
} }
patchedBy.delete(patch.plugin);
if (patch.group) {
logger.warn(`Undoing patch ${patch.find} by ${patch.plugin} because replacement ${replacement.match} errored`);
code = previousCode;
mod = previousMod;
break;
}
code = lastCode; code = lastCode;
mod = lastMod; mod = lastMod;
patchedBy.delete(patch.plugin);
} }
} }