Clean up WebpackRequire typings

This commit is contained in:
Nuckyz 2024-05-23 03:36:53 -03:00
parent deb0f7b9c6
commit 5ca4e58fad
No known key found for this signature in database
GPG key ID: 440BF8296E1C4AD9
4 changed files with 35 additions and 34 deletions

View file

@ -41,7 +41,7 @@ const browser = await pup.launch({
const page = await browser.newPage(); const page = await browser.newPage();
await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"); await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36");
function maybeGetError(handle: JSHandle) { async function maybeGetError(handle: JSHandle) {
return (handle as JSHandle<Error>)?.getProperty("message") return (handle as JSHandle<Error>)?.getProperty("message")
.then(m => m.jsonValue()); .then(m => m.jsonValue());
} }
@ -383,7 +383,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 as any).catch(() => { }))) Promise.all(chunkIds.map(id => wreq.e(id).catch(() => { })))
) )
); );
@ -395,7 +395,7 @@ async function runtime(token: string) {
continue; continue;
} }
if (wreq.m[entryPoint]) wreq(entryPoint as any); if (wreq.m[entryPoint]) wreq(entryPoint);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
@ -460,7 +460,7 @@ async function runtime(token: string) {
// Require deferred entry points // Require deferred entry points
for (const deferredRequire of deferredRequires) { for (const deferredRequire of deferredRequires) {
wreq(deferredRequire as any); wreq(deferredRequire);
} }
// All chunks Discord has mapped to asset files, even if they are not used anymore // All chunks Discord has mapped to asset files, even if they are not used anymore
@ -488,8 +488,8 @@ async function runtime(token: string) {
// Loads and requires a chunk // Loads and requires a chunk
if (!isWasm) { if (!isWasm) {
await wreq.e(id as any); await wreq.e(id);
if (wreq.m[id]) wreq(id as any); if (wreq.m[id]) wreq(id);
} }
})); }));

View file

@ -24,6 +24,7 @@ const modulesProxyhandler: ProxyHandler<WebpackRequire["m"]> = {
const mod = Reflect.get(target, p); const mod = Reflect.get(target, p);
// If the property is not a module id, return the value of it without trying to patch // If the property is not a module id, return the value of it without trying to patch
// @ts-ignore
if (mod == null || mod.$$vencordOriginal != null || Number.isNaN(Number(p))) return mod; if (mod == null || mod.$$vencordOriginal != null || Number.isNaN(Number(p))) return mod;
const patchedMod = patchFactory(p, mod); const patchedMod = patchFactory(p, mod);
@ -90,12 +91,14 @@ Object.defineProperty(Function.prototype, "O", {
// Returns whether a chunk has been loaded // Returns whether a chunk has been loaded
Object.defineProperty(onChunksLoaded, "j", { Object.defineProperty(onChunksLoaded, "j", {
configurable: true,
set(v) { set(v) {
// @ts-ignore
delete onChunksLoaded.j; delete onChunksLoaded.j;
onChunksLoaded.j = v; onChunksLoaded.j = v;
originalOnChunksLoaded.j = v; originalOnChunksLoaded.j = v;
}, }
configurable: true
}); });
} }
@ -113,7 +116,7 @@ Object.defineProperty(Function.prototype, "O", {
Object.defineProperty(Function.prototype, "m", { Object.defineProperty(Function.prototype, "m", {
configurable: true, configurable: true,
set(originalModules: any) { set(originalModules: WebpackRequire["m"]) {
// When using react devtools or other extensions, we may also catch their webpack here. // When using react devtools or other extensions, we may also catch their webpack here.
// This ensures we actually got the right one // This ensures we actually got the right one
const { stack } = new Error(); const { stack } = new Error();
@ -140,7 +143,7 @@ Object.defineProperty(Function.prototype, "m", {
let webpackNotInitializedLogged = false; let webpackNotInitializedLogged = false;
function patchFactory(id: string | number, mod: ModuleFactory) { function patchFactory(id: PropertyKey, mod: ModuleFactory) {
for (const factoryListener of factoryListeners) { for (const factoryListener of factoryListeners) {
try { try {
factoryListener(mod); factoryListener(mod);
@ -192,7 +195,7 @@ function patchFactory(id: string | number, mod: ModuleFactory) {
const newCode = executePatch(replacement.match, replacement.replace as string); const newCode = executePatch(replacement.match, replacement.replace as string);
if (newCode === code) { if (newCode === code) {
if (!patch.noWarn) { if (!patch.noWarn) {
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 ${String(id)}): ${replacement.match}`);
if (IS_DEV) { if (IS_DEV) {
logger.debug("Function Source:\n", code); logger.debug("Function Source:\n", code);
} }
@ -210,9 +213,9 @@ function patchFactory(id: string | number, mod: ModuleFactory) {
} }
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 ${String(id)} - Patched by ${[...patchedBy].join(", ")}\n${newCode}\n//# sourceURL=WebpackModule${String(id)}`);
} catch (err) { } catch (err) {
logger.error(`Patch by ${patch.plugin} errored (Module id is ${id}): ${replacement.match}\n`, err); logger.error(`Patch by ${patch.plugin} errored (Module id is ${String(id)}): ${replacement.match}\n`, err);
if (IS_DEV) { if (IS_DEV) {
const changeSize = code.length - lastCode.length; const changeSize = code.length - lastCode.length;

View file

@ -36,7 +36,7 @@ export const onceReady = new Promise<void>(r => _resolveReady = r);
export let wreq: WebpackRequire; export let wreq: WebpackRequire;
export let cache: WebpackRequire["c"]; export let cache: WebpackRequire["c"];
export type FilterFn = (mod: any) => boolean; export type FilterFn = (module: ModuleExports) => boolean;
export const filters = { export const filters = {
byProps: (...props: string[]): FilterFn => byProps: (...props: string[]): FilterFn =>
@ -129,7 +129,7 @@ export function findAll(filter: FilterFn) {
if (typeof filter !== "function") if (typeof filter !== "function")
throw new Error("Invalid filter. Expected a function got " + typeof filter); throw new Error("Invalid filter. Expected a function got " + typeof filter);
const ret = [] as any[]; const ret: ModuleExports[] = [];
for (const key in cache) { for (const key in cache) {
const mod = cache[key]; const mod = cache[key];
if (!mod?.exports) continue; if (!mod?.exports) continue;
@ -169,7 +169,7 @@ export const findBulk = traceFunction("findBulk", function findBulk(...filterFns
const filters = filterFns as Array<FilterFn | undefined>; const filters = filterFns as Array<FilterFn | undefined>;
let found = 0; let found = 0;
const results = Array(length); const results: ModuleExports[] = Array(length);
outer: outer:
for (const key in cache) { for (const key in cache) {
@ -496,12 +496,12 @@ export function waitFor(filter: string | string[] | FilterFn, callback: Callback
* @returns Mapping of found modules * @returns Mapping of found modules
*/ */
export function search(...filters: Array<string | RegExp>) { export function search(...filters: Array<string | RegExp>) {
const results = {} as Record<number, Function>; const results: WebpackRequire["m"] = {};
const factories = wreq.m; const factories = wreq.m;
outer: outer:
for (const id in factories) { for (const id in factories) {
// @ts-ignore // @ts-ignore
const factory = factories[id].original ?? factories[id]; const factory = factories[id].$$vencordOriginal ?? factories[id];
const str: string = factory.toString(); const str: string = factory.toString();
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;
@ -521,18 +521,18 @@ export function search(...filters: Array<string | RegExp>) {
* so putting breakpoints or similar will have no effect. * so putting breakpoints or similar will have no effect.
* @param id The id of the module to extract * @param id The id of the module to extract
*/ */
export function extract(id: string | number) { export function extract(id: PropertyKey) {
const mod = wreq.m[id] as Function; const mod = wreq.m[id];
if (!mod) return null; if (!mod) return null;
const code = ` const code = `
// [EXTRACTED] WebpackModule${id} // [EXTRACTED] WebpackModule${String(id)}
// 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,${mod.toString()}
//# sourceURL=ExtractedWebpackModule${id} //# sourceURL=ExtractedWebpackModule${String(id)}
`; `;
const extracted = (0, eval)(code); const extracted: ModuleFactory = (0, eval)(code);
return extracted as Function; return extracted;
} }

18
src/webpack/wreq.d.ts vendored
View file

@ -4,8 +4,6 @@
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
*/ */
export type AnyRecord = Record<PropertyKey, any>;
export type ModuleExports = any; export type ModuleExports = any;
export type Module = { export type Module = {
@ -14,8 +12,8 @@ export type Module = {
exports: ModuleExports; exports: ModuleExports;
}; };
/** exports ({@link ModuleExports}) can be anything, however initially it is always an empty object */ /** exports can be anything, however initially it is always an empty object */
export type ModuleFactory = (module: Module, exports: AnyRecord, require: WebpackRequire) => void; export type ModuleFactory = (module: Module, exports: ModuleExports, require: WebpackRequire) => void;
export type AsyncModuleBody = ( export type AsyncModuleBody = (
handleDependencies: (deps: Promise<any>[]) => Promise<any[]> & (() => void) handleDependencies: (deps: Promise<any>[]) => Promise<any[]> & (() => void)
@ -40,7 +38,7 @@ export type ScriptLoadDone = (event: Event) => void;
export type OnChunksLoaded = ((this: WebpackRequire, result: any, chunkIds: PropertyKey[] | undefined | null, callback: () => any, priority: number) => any) & { export type OnChunksLoaded = ((this: WebpackRequire, result: any, chunkIds: PropertyKey[] | undefined | null, callback: () => any, priority: number) => any) & {
/** Check if a chunk has been loaded */ /** Check if a chunk has been loaded */
j: (chunkId: PropertyKey) => boolean; j: (this: OnChunksLoaded, chunkId: PropertyKey) => boolean;
}; };
export type WebpackRequire = ((moduleId: PropertyKey) => Module) & { export type WebpackRequire = ((moduleId: PropertyKey) => Module) & {
@ -57,7 +55,7 @@ export type WebpackRequire = ((moduleId: PropertyKey) => Module) & {
* }); * });
* @returns fromObject * @returns fromObject
*/ */
es: (this: WebpackRequire, fromObject: AnyRecord, toObject: AnyRecord) => AnyRecord; es: (this: WebpackRequire, fromObject: Record<PropertyKey, any>, toObject: Record<PropertyKey, any>) => Record<PropertyKey, any>;
/** /**
* Creates an async module. The body function must be a async function. * Creates an async module. The body function must be a async function.
* "module.exports" will be decorated with an AsyncModulePromise. * "module.exports" will be decorated with an AsyncModulePromise.
@ -91,7 +89,7 @@ export type WebpackRequire = ((moduleId: PropertyKey) => Module) & {
* Object.defineProperty(exports, key, { get: definition[key] } * Object.defineProperty(exports, key, { get: definition[key] }
* } * }
*/ */
d: (this: WebpackRequire, exports: AnyRecord, definiton: AnyRecord) => void; d: (this: WebpackRequire, exports: Record<PropertyKey, any>, definiton: Record<PropertyKey, any>) => void;
/** The chunk handlers, which are used to ensure the files of the chunks are loaded, or load if necessary */ /** The chunk handlers, which are used to ensure the files of the chunks are loaded, or load if necessary */
f: ChunkHandlers; f: ChunkHandlers;
/** /**
@ -100,7 +98,7 @@ export type WebpackRequire = ((moduleId: PropertyKey) => Module) & {
*/ */
e: (this: WebpackRequire, chunkId: PropertyKey) => Promise<void[]>; e: (this: WebpackRequire, chunkId: PropertyKey) => Promise<void[]>;
/** Get the filename name for the css part of a chunk */ /** Get the filename name for the css part of a chunk */
k: (this: WebpackRequire, chunkId: PropertyKey) => `${chunkId}.css`; k: (this: WebpackRequire, chunkId: PropertyKey) => string;
/** Get the filename for the js part of a chunk */ /** Get the filename for the js part of a chunk */
u: (this: WebpackRequire, chunkId: PropertyKey) => string; u: (this: WebpackRequire, chunkId: PropertyKey) => string;
/** The global object, will likely always be the window */ /** The global object, will likely always be the window */
@ -116,7 +114,7 @@ export type WebpackRequire = ((moduleId: PropertyKey) => Module) & {
*/ */
l: (this: WebpackRequire, url: string, done: ScriptLoadDone, key?: string | number, chunkId?: PropertyKey) => void; l: (this: WebpackRequire, url: string, done: ScriptLoadDone, key?: string | number, chunkId?: PropertyKey) => void;
/** Defines __esModule on the exports, marking ES Modules compatibility as true */ /** Defines __esModule on the exports, marking ES Modules compatibility as true */
r: (this: WebpackRequire, exports: AnyRecord) => void; r: (this: WebpackRequire, exports: ModuleExports) => void;
/** Node.js module decorator. Decorates a module as a Node.js module */ /** Node.js module decorator. Decorates a module as a Node.js module */
nmd: (this: WebpackRequire, module: Module) => any; nmd: (this: WebpackRequire, module: Module) => any;
/** /**
@ -135,7 +133,7 @@ export type WebpackRequire = ((moduleId: PropertyKey) => Module) & {
* Instantiate a wasm instance with source using "wasmModuleHash", and importObject "importsObj", and then assign the exports of its instance to "exports" * Instantiate a wasm instance with source using "wasmModuleHash", and importObject "importsObj", and then assign the exports of its instance to "exports"
* @returns The exports argument, but now assigned with the exports of the wasm instance * @returns The exports argument, but now assigned with the exports of the wasm instance
*/ */
v: (this: WebpackRequire, exports: AnyRecord, wasmModuleId: any, wasmModuleHash: string, importsObj?: WebAssembly.Imports) => Promise<any>; v: (this: WebpackRequire, exports: ModuleExports, wasmModuleId: any, wasmModuleHash: string, importsObj?: WebAssembly.Imports) => Promise<any>;
/** Bundle public path, where chunk files are stored. Used by other methods which load chunks to obtain the full asset url */ /** Bundle public path, where chunk files are stored. Used by other methods which load chunks to obtain the full asset url */
p: string; p: string;
/** Document baseURI or WebWorker location.href */ /** Document baseURI or WebWorker location.href */