Merge branch 'modules-proxy-patches' into immediate-finds-modules-proxy
This commit is contained in:
commit
aa9be97f83
|
@ -386,7 +386,7 @@ async function runtime(token: string) {
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
Array.from(validChunkGroups)
|
Array.from(validChunkGroups)
|
||||||
.map(([chunkIds]) =>
|
.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;
|
wreq = webpackRequire;
|
||||||
|
|
||||||
Vencord.Webpack.factoryListeners.add(factory => {
|
Vencord.Webpack.factoryListeners.add(factory => {
|
||||||
|
// setImmediate to avoid blocking the factory patching execution while checking for lazy chunks
|
||||||
|
setTimeout(() => {
|
||||||
let isResolved = false;
|
let isResolved = false;
|
||||||
searchAndLoadLazyChunks(factory.toString()).then(() => isResolved = true);
|
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
|
// setImmediate to only search the initial factories after Discord initialized the app
|
||||||
|
@ -451,7 +454,7 @@ async function runtime(token: string) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
for (const factoryId in wreq.m) {
|
for (const factoryId in wreq.m) {
|
||||||
let isResolved = false;
|
let isResolved = false;
|
||||||
searchAndLoadLazyChunks(wreq.m[factoryId].toString()).then(() => isResolved = true);
|
searchAndLoadLazyChunks(String(wreq.m[factoryId])).then(() => isResolved = true);
|
||||||
|
|
||||||
chunksSearchPromises.push(() => isResolved);
|
chunksSearchPromises.push(() => isResolved);
|
||||||
}
|
}
|
||||||
|
@ -470,7 +473,7 @@ async function runtime(token: string) {
|
||||||
const allChunks = [] as string[];
|
const allChunks = [] as string[];
|
||||||
|
|
||||||
// Matches "id" or id:
|
// 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];
|
const id = currentMatch[1] ?? currentMatch[2];
|
||||||
if (id == null) continue;
|
if (id == null) continue;
|
||||||
|
|
||||||
|
@ -523,7 +526,7 @@ async function runtime(token: string) {
|
||||||
|
|
||||||
const module = Vencord.Webpack.findModuleFactory(...code);
|
const module = Vencord.Webpack.findModuleFactory(...code);
|
||||||
if (module) {
|
if (module) {
|
||||||
result = module.toString().match(Vencord.Util.canonicalizeMatch(matcher));
|
result = String(module).match(Vencord.Util.canonicalizeMatch(matcher));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -572,7 +575,7 @@ async function runtime(token: string) {
|
||||||
parsedArgs === args &&
|
parsedArgs === args &&
|
||||||
["waitFor", "find", "findComponent", "webpackDependantLazy", "webpackDependantLazyComponent"].includes(searchType)
|
["waitFor", "find", "findComponent", "webpackDependantLazy", "webpackDependantLazyComponent"].includes(searchType)
|
||||||
) {
|
) {
|
||||||
let filter = parsedArgs[0].toString();
|
let filter = String(parsedArgs[0]);
|
||||||
if (filter.length > 150) {
|
if (filter.length > 150) {
|
||||||
filter = filter.slice(0, 147) + "...";
|
filter = filter.slice(0, 147) + "...";
|
||||||
}
|
}
|
||||||
|
@ -583,7 +586,7 @@ async function runtime(token: string) {
|
||||||
if (parsedArgs[1] === Vencord.Webpack.DefaultExtractAndLoadChunksRegex) {
|
if (parsedArgs[1] === Vencord.Webpack.DefaultExtractAndLoadChunksRegex) {
|
||||||
regexStr = "DefaultExtractAndLoadChunksRegex";
|
regexStr = "DefaultExtractAndLoadChunksRegex";
|
||||||
} else {
|
} else {
|
||||||
regexStr = parsedArgs[1].toString();
|
regexStr = String(parsedArgs[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
logMessage += `([${parsedArgs[0].map((arg: any) => `"${arg}"`).join(", ")}], ${regexStr})`;
|
logMessage += `([${parsedArgs[0].map((arg: any) => `"${arg}"`).join(", ")}], ${regexStr})`;
|
||||||
|
|
|
@ -56,7 +56,7 @@ function ReplacementComponent({ module, match, replacement, setReplacementError
|
||||||
const [compileResult, setCompileResult] = React.useState<[boolean, string]>();
|
const [compileResult, setCompileResult] = React.useState<[boolean, string]>();
|
||||||
|
|
||||||
const [patchedCode, matchResult, diff] = React.useMemo(() => {
|
const [patchedCode, matchResult, diff] = React.useMemo(() => {
|
||||||
const src: string = fact.toString().replaceAll("\n", "");
|
const src: string = String(fact).replaceAll("\n", "");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new RegExp(match);
|
new RegExp(match);
|
||||||
|
|
|
@ -66,11 +66,6 @@ function VencordSettings() {
|
||||||
title: "Enable React Developer Tools",
|
title: "Enable React Developer Tools",
|
||||||
note: "Requires a full restart"
|
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 ? {
|
!IS_WEB && (!IS_DISCORD_DESKTOP || !isWindows ? {
|
||||||
key: "frameless",
|
key: "frameless",
|
||||||
title: "Disable the window frame",
|
title: "Disable the window frame",
|
||||||
|
|
|
@ -160,7 +160,7 @@ function initWs(isManual = false) {
|
||||||
return reply("Expected exactly one 'find' matches, found " + keys.length);
|
return reply("Expected exactly one 'find' matches, found " + keys.length);
|
||||||
|
|
||||||
const mod = candidates[keys[0]];
|
const mod = candidates[keys[0]];
|
||||||
let src = mod.toString().replaceAll("\n", "");
|
let src = String(mod).replaceAll("\n", "");
|
||||||
|
|
||||||
if (src.startsWith("function(")) {
|
if (src.startsWith("function(")) {
|
||||||
src = "0," + src;
|
src = "0," + src;
|
||||||
|
|
|
@ -24,7 +24,7 @@ const modulesProxyHandler: ProxyHandler<WebpackRequire["m"]> = {
|
||||||
[propName, (...args: any[]) => Reflect[propName](...args)]
|
[propName, (...args: any[]) => Reflect[propName](...args)]
|
||||||
)),
|
)),
|
||||||
get: (target, p) => {
|
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
|
// 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
|
// $$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
|
// This patches factories if eagerPatches are disabled
|
||||||
const patchedFactory = patchFactory(p, propValue);
|
const patchedFactory = patchFactory(p, propValue);
|
||||||
Reflect.set(target, p, patchedFactory);
|
Reflect.set(target, p, patchedFactory, target);
|
||||||
|
|
||||||
return patchedFactory;
|
return patchedFactory;
|
||||||
},
|
},
|
||||||
|
@ -44,10 +44,10 @@ const modulesProxyHandler: ProxyHandler<WebpackRequire["m"]> = {
|
||||||
// $$vencordRequired means we are resetting the factory to its original after being required
|
// $$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 the property is not a number, we are not dealing with a module factory
|
||||||
if (!Settings.eagerPatches || newValue?.$$vencordRequired === true || Number.isNaN(Number(p))) {
|
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
|
// Check if this factory is already patched
|
||||||
// @ts-ignore
|
// @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
|
// Modules are only patched once, so we need to set the patched factory on all the modules
|
||||||
for (const proxiedModules of allProxiedModules) {
|
for (const proxiedModules of allProxiedModules) {
|
||||||
Reflect.set(proxiedModules, p, patchedFactory);
|
Reflect.set(proxiedModules, p, patchedFactory, proxiedModules);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -91,7 +91,7 @@ Object.defineProperty(Function.prototype, "O", {
|
||||||
|
|
||||||
const originalOnChunksLoaded = onChunksLoaded;
|
const originalOnChunksLoaded = onChunksLoaded;
|
||||||
onChunksLoaded = function (result, chunkIds, callback, priority) {
|
onChunksLoaded = function (result, chunkIds, callback, priority) {
|
||||||
if (callback != null && initCallbackRegex.test(callback.toString())) {
|
if (callback != null && initCallbackRegex.test(String(callback))) {
|
||||||
Object.defineProperty(this, "O", {
|
Object.defineProperty(this, "O", {
|
||||||
value: originalOnChunksLoaded,
|
value: originalOnChunksLoaded,
|
||||||
configurable: true,
|
configurable: true,
|
||||||
|
@ -127,10 +127,17 @@ Object.defineProperty(Function.prototype, "O", {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
|
|
||||||
set(v: OnChunksLoaded["j"]) {
|
set(v: OnChunksLoaded["j"]) {
|
||||||
// @ts-ignore
|
function setValue(target: any) {
|
||||||
delete onChunksLoaded.j;
|
Object.defineProperty(target, "j", {
|
||||||
onChunksLoaded.j = v;
|
value: v,
|
||||||
originalOnChunksLoaded.j = 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
|
// The new object which will contain the factories
|
||||||
const proxiedModules: WebpackRequire["m"] = {};
|
const proxiedModules: WebpackRequire["m"] = {};
|
||||||
|
// @ts-ignore
|
||||||
|
proxiedModules[Symbol.toStringTag] = "ProxiedModules";
|
||||||
|
|
||||||
for (const id in originalModules) {
|
for (const id in originalModules) {
|
||||||
// If we have eagerPatches enabled we have to patch the pre-populated factories
|
// 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];
|
delete originalModules[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
originalModules.$$proxiedModules = proxiedModules;
|
|
||||||
allProxiedModules.add(proxiedModules);
|
allProxiedModules.add(proxiedModules);
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
originalModules[Symbol.toStringTag] = "OriginalModules";
|
||||||
Object.setPrototypeOf(originalModules, new Proxy(proxiedModules, modulesProxyHandler));
|
Object.setPrototypeOf(originalModules, new Proxy(proxiedModules, modulesProxyHandler));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +221,7 @@ function patchFactory(id: PropertyKey, factory: ModuleFactory) {
|
||||||
// cause issues.
|
// cause issues.
|
||||||
//
|
//
|
||||||
// 0, prefix is to turn it into an expression: 0,function(){} would be invalid syntax without the 0,
|
// 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++) {
|
for (let i = 0; i < patches.length; i++) {
|
||||||
const patch = patches[i];
|
const patch = patches[i];
|
||||||
|
@ -318,7 +328,7 @@ function patchFactory(id: PropertyKey, factory: ModuleFactory) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
originalFactory.$$vencordRequired = true;
|
originalFactory.$$vencordRequired = true;
|
||||||
for (const proxiedModules of allProxiedModules) {
|
for (const proxiedModules of allProxiedModules) {
|
||||||
proxiedModules[id] = originalFactory;
|
Reflect.set(proxiedModules, id, originalFactory, proxiedModules);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wreq == null && IS_DEV) {
|
if (wreq == null && IS_DEV) {
|
||||||
|
|
|
@ -480,7 +480,7 @@ export const cacheFindBulk = traceFunction("cacheFindBulk", function cacheFindBu
|
||||||
export const findModuleId = traceFunction("findModuleId", function findModuleId(...code: string[]) {
|
export const findModuleId = traceFunction("findModuleId", function findModuleId(...code: string[]) {
|
||||||
outer:
|
outer:
|
||||||
for (const id in wreq.m) {
|
for (const id in wreq.m) {
|
||||||
const str = wreq.m[id].toString();
|
const str = String(wreq.m[id]);
|
||||||
|
|
||||||
for (const c of code) {
|
for (const c of code) {
|
||||||
if (!str.includes(c)) continue outer;
|
if (!str.includes(c)) continue outer;
|
||||||
|
@ -672,7 +672,7 @@ export async function extractAndLoadChunks(code: string[], matcher: RegExp = Def
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const match = module.toString().match(canonicalizeMatch(matcher));
|
const match = String(module).match(canonicalizeMatch(matcher));
|
||||||
if (!match) {
|
if (!match) {
|
||||||
const err = new Error("extractAndLoadChunks: Couldn't find chunk loading in module factory code");
|
const err = new Error("extractAndLoadChunks: Couldn't find chunk loading in module factory code");
|
||||||
logger.warn(err, "Code:", code, "Matcher:", matcher);
|
logger.warn(err, "Code:", code, "Matcher:", matcher);
|
||||||
|
@ -731,7 +731,7 @@ export function search(...filters: Array<string | RegExp>) {
|
||||||
outer:
|
outer:
|
||||||
for (const id in factories) {
|
for (const id in factories) {
|
||||||
const factory = factories[id];
|
const factory = factories[id];
|
||||||
const str: string = factory.toString();
|
const str: string = String(factory);
|
||||||
for (const filter of filters) {
|
for (const filter of filters) {
|
||||||
if (typeof filter === "string" && !str.includes(filter)) continue outer;
|
if (typeof filter === "string" && !str.includes(filter)) continue outer;
|
||||||
if (filter instanceof RegExp && !filter.test(str)) 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.
|
// WARNING: This module was extracted to be more easily readable.
|
||||||
// This module is NOT ACTUALLY USED! This means putting breakpoints will have NO EFFECT!!
|
// This module is NOT ACTUALLY USED! This means putting breakpoints will have NO EFFECT!!
|
||||||
|
|
||||||
0,${mod.toString()}
|
0,${String(mod)}
|
||||||
//# sourceURL=ExtractedWebpackModule${String(id)}
|
//# sourceURL=ExtractedWebpackModule${String(id)}
|
||||||
`;
|
`;
|
||||||
const extracted: ModuleFactory = (0, eval)(code);
|
const extracted: ModuleFactory = (0, eval)(code);
|
||||||
|
|
Loading…
Reference in a new issue