From 61e1eada0174b18476d371ba5028dff199301555 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 1 Jun 2024 19:38:01 -0300 Subject: [PATCH] Fix not restoring some original factories --- src/debug/loadLazyChunks.ts | 4 +-- src/webpack/patchWebpack.ts | 51 +++++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/debug/loadLazyChunks.ts b/src/debug/loadLazyChunks.ts index 91946c373..f4f7f88b3 100644 --- a/src/debug/loadLazyChunks.ts +++ b/src/debug/loadLazyChunks.ts @@ -111,14 +111,14 @@ export async function loadLazyChunks() { Webpack.factoryListeners.add(factory => { let isResolved = false; - searchAndLoadLazyChunks(factory.toString()).then(() => isResolved = true); + searchAndLoadLazyChunks(String(factory)).then(() => isResolved = true); chunksSearchPromises.push(() => isResolved); }); for (const factoryId in wreq.m) { let isResolved = false; - searchAndLoadLazyChunks(wreq.m[factoryId].toString()).then(() => isResolved = true); + searchAndLoadLazyChunks(String(wreq.m[factoryId])).then(() => isResolved = true); chunksSearchPromises.push(() => isResolved); } diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index bf4efa5f1..c147d1ad0 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -88,6 +88,10 @@ define(Function.prototype, "O", { // Patch the pre-populated factories for (const id in this.m) { + if (updateExistingFactory(this.m, id, this.m[id])) { + continue; + } + defineModulesFactoryGetter(id, Settings.eagerPatches ? patchFactory(id, this.m[id]) : this.m[id]); } @@ -140,6 +144,35 @@ function defineModulesFactoryGetter(id: PropertyKey, factory: PatchedModuleFacto } } +/** + * Update a factory that exists in any Webpack instance with a new original factory. + * + * @target The module factories where this new original factory is being set + * @param id The id of the module + * @param newFactory The new original factory + * @returns Whether the original factory was updated, or false if it doesn't exist in any Webpack instance + */ +function updateExistingFactory(target: AnyWebpackRequire["m"], id: PropertyKey, newFactory: ModuleFactory) { + let existingFactory: TypedPropertyDescriptor | undefined; + for (const wreq of allWebpackInstances) { + if (Reflect.getOwnPropertyDescriptor(wreq.m, id) != null) { + existingFactory = Reflect.getOwnPropertyDescriptor(wreq.m, id); + break; + } + } + + if (existingFactory != null) { + // If existingFactory exists in any Webpack instance, its either wrapped in defineModuleFactoryGetter, or it has already been required. + // So define the descriptor of it on this current Webpack instance, call Reflect.set with the new original, + // and let the correct logic apply (normal set, or defineModuleFactoryGetter setter) + + Reflect.defineProperty(target, id, existingFactory); + return Reflect.set(target, id, newFactory, target); + } + + return false; +} + const moduleFactoriesHandler: ProxyHandler = { /* If Discord ever decides to set module factories using the variable of the modules object directly instead of wreq.m, we need to switch the proxy to the prototype @@ -163,23 +196,13 @@ const moduleFactoriesHandler: ProxyHandler = { return define(target, p, { value: newValue }); } - const existingFactory = Reflect.get(target, p, receiver); - - if (!Settings.eagerPatches) { - // If existingFactory exists, its either wrapped in defineModuleFactoryGetter, or it has already been required - // so call Reflect.set with the new original and let the correct logic apply (normal set, or defineModuleFactoryGetter setter) - if (existingFactory != null) { - return Reflect.set(target, p, newValue, receiver); - } - - // eagerPatches are disabled, so the factory argument should be the original - defineModulesFactoryGetter(p, newValue); + if (updateExistingFactory(target, p, newValue)) { return true; } - // Check if this factory is already patched - if (existingFactory?.$$vencordOriginal != null) { - existingFactory.$$vencordOriginal = newValue; + if (!Settings.eagerPatches) { + // eagerPatches are disabled, so the factory argument should be the original + defineModulesFactoryGetter(p, newValue); return true; }