Merge branch 'modules-proxy-patches' into immediate-finds-modules-proxy

This commit is contained in:
Nuckyz 2024-05-24 00:00:36 -03:00
commit aa9be97f83
No known key found for this signature in database
GPG key ID: 440BF8296E1C4AD9
6 changed files with 42 additions and 34 deletions

View file

@ -386,7 +386,7 @@ async function runtime(token: string) {
await Promise.all(
Array.from(validChunkGroups)
.map(([chunkIds]) =>
Promise.all(chunkIds.map(id => wreq.e(id).catch(() => { })))
Promise.all(chunkIds.map(id => wreq.e(id)))
)
);
@ -440,10 +440,13 @@ async function runtime(token: string) {
wreq = webpackRequire;
Vencord.Webpack.factoryListeners.add(factory => {
let isResolved = false;
searchAndLoadLazyChunks(factory.toString()).then(() => isResolved = true);
// setImmediate to avoid blocking the factory patching execution while checking for lazy chunks
setTimeout(() => {
let isResolved = false;
searchAndLoadLazyChunks(String(factory)).then(() => isResolved = true);
chunksSearchPromises.push(() => isResolved);
chunksSearchPromises.push(() => isResolved);
}, 0);
});
// setImmediate to only search the initial factories after Discord initialized the app
@ -451,7 +454,7 @@ async function runtime(token: string) {
setTimeout(() => {
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);
}
@ -470,7 +473,7 @@ async function runtime(token: string) {
const allChunks = [] as string[];
// Matches "id" or id:
for (const currentMatch of wreq.u.toString().matchAll(/(?:"(\d+?)")|(?:(\d+?):)/g)) {
for (const currentMatch of String(wreq.u).matchAll(/(?:"(\d+?)")|(?:(\d+?):)/g)) {
const id = currentMatch[1] ?? currentMatch[2];
if (id == null) continue;
@ -523,7 +526,7 @@ async function runtime(token: string) {
const module = Vencord.Webpack.findModuleFactory(...code);
if (module) {
result = module.toString().match(Vencord.Util.canonicalizeMatch(matcher));
result = String(module).match(Vencord.Util.canonicalizeMatch(matcher));
}
break;
@ -572,7 +575,7 @@ async function runtime(token: string) {
parsedArgs === args &&
["waitFor", "find", "findComponent", "webpackDependantLazy", "webpackDependantLazyComponent"].includes(searchType)
) {
let filter = parsedArgs[0].toString();
let filter = String(parsedArgs[0]);
if (filter.length > 150) {
filter = filter.slice(0, 147) + "...";
}
@ -583,7 +586,7 @@ async function runtime(token: string) {
if (parsedArgs[1] === Vencord.Webpack.DefaultExtractAndLoadChunksRegex) {
regexStr = "DefaultExtractAndLoadChunksRegex";
} else {
regexStr = parsedArgs[1].toString();
regexStr = String(parsedArgs[1]);
}
logMessage += `([${parsedArgs[0].map((arg: any) => `"${arg}"`).join(", ")}], ${regexStr})`;

View file

@ -56,7 +56,7 @@ function ReplacementComponent({ module, match, replacement, setReplacementError
const [compileResult, setCompileResult] = React.useState<[boolean, string]>();
const [patchedCode, matchResult, diff] = React.useMemo(() => {
const src: string = fact.toString().replaceAll("\n", "");
const src: string = String(fact).replaceAll("\n", "");
try {
new RegExp(match);

View file

@ -66,11 +66,6 @@ function VencordSettings() {
title: "Enable React Developer Tools",
note: "Requires a full restart"
},
{
key: "eagerPatches",
title: "Apply Vencord patches before they are needed",
note: "Increases startup timing, but may make app usage more fluid. Note that the difference of having this on or off is minimal."
},
!IS_WEB && (!IS_DISCORD_DESKTOP || !isWindows ? {
key: "frameless",
title: "Disable the window frame",

View file

@ -160,7 +160,7 @@ function initWs(isManual = false) {
return reply("Expected exactly one 'find' matches, found " + keys.length);
const mod = candidates[keys[0]];
let src = mod.toString().replaceAll("\n", "");
let src = String(mod).replaceAll("\n", "");
if (src.startsWith("function(")) {
src = "0," + src;

View file

@ -24,7 +24,7 @@ const modulesProxyHandler: ProxyHandler<WebpackRequire["m"]> = {
[propName, (...args: any[]) => Reflect[propName](...args)]
)),
get: (target, p) => {
const propValue = Reflect.get(target, p);
const propValue = Reflect.get(target, p, target);
// If the property is not a number, we are not dealing with a module factory
// $$vencordOriginal means the factory is already patched, $$vencordRequired means it has already been required
@ -36,7 +36,7 @@ const modulesProxyHandler: ProxyHandler<WebpackRequire["m"]> = {
// This patches factories if eagerPatches are disabled
const patchedFactory = patchFactory(p, propValue);
Reflect.set(target, p, patchedFactory);
Reflect.set(target, p, patchedFactory, target);
return patchedFactory;
},
@ -44,10 +44,10 @@ const modulesProxyHandler: ProxyHandler<WebpackRequire["m"]> = {
// $$vencordRequired means we are resetting the factory to its original after being required
// If the property is not a number, we are not dealing with a module factory
if (!Settings.eagerPatches || newValue?.$$vencordRequired === true || Number.isNaN(Number(p))) {
return Reflect.set(target, p, newValue);
return Reflect.set(target, p, newValue, target);
}
const existingFactory = Reflect.get(target, p);
const existingFactory = Reflect.get(target, p, target);
// Check if this factory is already patched
// @ts-ignore
@ -59,7 +59,7 @@ const modulesProxyHandler: ProxyHandler<WebpackRequire["m"]> = {
// Modules are only patched once, so we need to set the patched factory on all the modules
for (const proxiedModules of allProxiedModules) {
Reflect.set(proxiedModules, p, patchedFactory);
Reflect.set(proxiedModules, p, patchedFactory, proxiedModules);
}
return true;
@ -91,7 +91,7 @@ Object.defineProperty(Function.prototype, "O", {
const originalOnChunksLoaded = onChunksLoaded;
onChunksLoaded = function (result, chunkIds, callback, priority) {
if (callback != null && initCallbackRegex.test(callback.toString())) {
if (callback != null && initCallbackRegex.test(String(callback))) {
Object.defineProperty(this, "O", {
value: originalOnChunksLoaded,
configurable: true,
@ -127,10 +127,17 @@ Object.defineProperty(Function.prototype, "O", {
configurable: true,
set(v: OnChunksLoaded["j"]) {
// @ts-ignore
delete onChunksLoaded.j;
onChunksLoaded.j = v;
originalOnChunksLoaded.j = v;
function setValue(target: any) {
Object.defineProperty(target, "j", {
value: v,
configurable: true,
enumerable: true,
writable: true
});
}
setValue(onChunksLoaded);
setValue(originalOnChunksLoaded);
}
});
}
@ -160,6 +167,8 @@ Object.defineProperty(Function.prototype, "m", {
// The new object which will contain the factories
const proxiedModules: WebpackRequire["m"] = {};
// @ts-ignore
proxiedModules[Symbol.toStringTag] = "ProxiedModules";
for (const id in originalModules) {
// If we have eagerPatches enabled we have to patch the pre-populated factories
@ -173,9 +182,10 @@ Object.defineProperty(Function.prototype, "m", {
delete originalModules[id];
}
// @ts-ignore
originalModules.$$proxiedModules = proxiedModules;
allProxiedModules.add(proxiedModules);
// @ts-ignore
originalModules[Symbol.toStringTag] = "OriginalModules";
Object.setPrototypeOf(originalModules, new Proxy(proxiedModules, modulesProxyHandler));
}
@ -211,7 +221,7 @@ function patchFactory(id: PropertyKey, factory: ModuleFactory) {
// cause issues.
//
// 0, prefix is to turn it into an expression: 0,function(){} would be invalid syntax without the 0,
let code: string = "0," + factory.toString().replaceAll("\n", "");
let code: string = "0," + String(factory).replaceAll("\n", "");
for (let i = 0; i < patches.length; i++) {
const patch = patches[i];
@ -318,7 +328,7 @@ function patchFactory(id: PropertyKey, factory: ModuleFactory) {
// @ts-ignore
originalFactory.$$vencordRequired = true;
for (const proxiedModules of allProxiedModules) {
proxiedModules[id] = originalFactory;
Reflect.set(proxiedModules, id, originalFactory, proxiedModules);
}
if (wreq == null && IS_DEV) {

View file

@ -480,7 +480,7 @@ export const cacheFindBulk = traceFunction("cacheFindBulk", function cacheFindBu
export const findModuleId = traceFunction("findModuleId", function findModuleId(...code: string[]) {
outer:
for (const id in wreq.m) {
const str = wreq.m[id].toString();
const str = String(wreq.m[id]);
for (const c of code) {
if (!str.includes(c)) continue outer;
@ -672,7 +672,7 @@ export async function extractAndLoadChunks(code: string[], matcher: RegExp = Def
return;
}
const match = module.toString().match(canonicalizeMatch(matcher));
const match = String(module).match(canonicalizeMatch(matcher));
if (!match) {
const err = new Error("extractAndLoadChunks: Couldn't find chunk loading in module factory code");
logger.warn(err, "Code:", code, "Matcher:", matcher);
@ -731,7 +731,7 @@ export function search(...filters: Array<string | RegExp>) {
outer:
for (const id in factories) {
const factory = factories[id];
const str: string = factory.toString();
const str: string = String(factory);
for (const filter of filters) {
if (typeof filter === "string" && !str.includes(filter)) continue outer;
if (filter instanceof RegExp && !filter.test(str)) continue outer;
@ -759,7 +759,7 @@ export function extract(id: PropertyKey) {
// WARNING: This module was extracted to be more easily readable.
// This module is NOT ACTUALLY USED! This means putting breakpoints will have NO EFFECT!!
0,${mod.toString()}
0,${String(mod)}
//# sourceURL=ExtractedWebpackModule${String(id)}
`;
const extracted: ModuleFactory = (0, eval)(code);