From 4d8c56689cc1647b2c9810906625de4b25119641 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 1 Jun 2024 01:40:33 -0300 Subject: [PATCH 1/2] Future proof against array modules --- src/webpack/patchWebpack.ts | 41 ++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index 373433166..944d83e86 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -42,20 +42,29 @@ const define: Define = (target, p, attributes) => { }); }; -// wreq.m is the Webpack object containing module factories. -// We wrap it with our proxy, which is responsible for patching the module factories when they are set, or definining getters for the patched versions. -// If this is the main Webpack, we also set up the internal references to WebpackRequire. +// wreq.O is the Webpack onChunksLoaded function. +// It is pretty likely that all important Discord Webpack instances will have this property set, +// because Discord bundled code is chunked. +// As of the time of writing, only the main and sentry Webpack instances have this property, and they are the only ones we care about. + +// We use this setter to intercept when wreq.O is defined, and apply the patching in the modules factories (wreq.m). // wreq.m is pre-populated with module factories, and is also populated via webpackGlobal.push // The sentry module also has their own Webpack with a pre-populated wreq.m, so this also patches the sentry module factories. -define(Function.prototype, "m", { +// We wrap wreq.m with our proxy, which is responsible for patching the module factories when they are set, or definining getters for the patched versions. + +// If this is the main Webpack, we also set up the internal references to WebpackRequire. +define(Function.prototype, "O", { enumerable: false, - set(this: WebpackRequire, moduleFactories: PatchedModuleFactories) { - // When using React DevTools or other extensions, we may also catch their Webpack here. - // This ensures we actually got the right ones. + set(this: WebpackRequire, onChunksLoaded: WebpackRequire["O"]) { + define(this, "O", { value: onChunksLoaded }); + const { stack } = new Error(); - if (!(stack?.includes("discord.com") || stack?.includes("discordapp.com")) || Array.isArray(moduleFactories)) { - define(this, "m", { value: moduleFactories }); + if (!stack?.includes("discord.com") && !stack?.includes("discordapp.com")) { + return; + } + + if (this.m == null) { return; } @@ -81,24 +90,24 @@ define(Function.prototype, "m", { // If this is the main Webpack, wreq.m will always be set before the timeout runs. const setterTimeout = setTimeout(() => Reflect.deleteProperty(this, "p"), 0); - define(moduleFactories, Symbol.toStringTag, { + // Patch the pre-populated factories + for (const id in this.m) { + defineModulesFactoryGetter(id, Settings.eagerPatches ? patchFactory(id, this.m[id]) : this.m[id]); + } + + define(this.m, Symbol.toStringTag, { value: "ModuleFactories", enumerable: false }); // The proxy responsible for patching the module factories when they are set, or definining getters for the patched versions - const proxiedModuleFactories = new Proxy(moduleFactories, moduleFactoriesHandler); + const proxiedModuleFactories = new Proxy(this.m, moduleFactoriesHandler); /* If Discord ever decides to set module factories using the variable of the modules object directly, instead of wreq.m, switch the proxy to the prototype Reflect.setPrototypeOf(moduleFactories, new Proxy(moduleFactories, moduleFactoriesHandler)); */ define(this, "m", { value: proxiedModuleFactories }); - - // Patch the pre-populated factories - for (const id in moduleFactories) { - defineModulesFactoryGetter(id, Settings.eagerPatches ? patchFactory(id, moduleFactories[id]) : moduleFactories[id]); - } } }); From 8580332c8222f68804141718038487a769250628 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 1 Jun 2024 01:44:18 -0300 Subject: [PATCH 2/2] cleanup --- src/webpack/patchWebpack.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index 944d83e86..d3d722b7a 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -60,11 +60,7 @@ define(Function.prototype, "O", { define(this, "O", { value: onChunksLoaded }); const { stack } = new Error(); - if (!stack?.includes("discord.com") && !stack?.includes("discordapp.com")) { - return; - } - - if (this.m == null) { + if (this.m == null || !(stack?.includes("discord.com") || stack?.includes("discordapp.com"))) { return; }