From 5ca4e58fad70fcf1fa6a13e798245d85049c9af3 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 23 May 2024 03:36:53 -0300 Subject: [PATCH] Clean up WebpackRequire typings --- scripts/generateReport.ts | 12 ++++++------ src/webpack/patchWebpack.ts | 17 ++++++++++------- src/webpack/webpack.ts | 22 +++++++++++----------- src/webpack/wreq.d.ts | 18 ++++++++---------- 4 files changed, 35 insertions(+), 34 deletions(-) diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 5808b4585..4ed44f7b4 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -41,7 +41,7 @@ const browser = await pup.launch({ 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"); -function maybeGetError(handle: JSHandle) { +async function maybeGetError(handle: JSHandle) { return (handle as JSHandle)?.getProperty("message") .then(m => m.jsonValue()); } @@ -383,7 +383,7 @@ async function runtime(token: string) { await Promise.all( Array.from(validChunkGroups) .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; } - if (wreq.m[entryPoint]) wreq(entryPoint as any); + if (wreq.m[entryPoint]) wreq(entryPoint); } catch (err) { console.error(err); } @@ -460,7 +460,7 @@ async function runtime(token: string) { // Require deferred entry points 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 @@ -488,8 +488,8 @@ async function runtime(token: string) { // Loads and requires a chunk if (!isWasm) { - await wreq.e(id as any); - if (wreq.m[id]) wreq(id as any); + await wreq.e(id); + if (wreq.m[id]) wreq(id); } })); diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index a08d74c96..b57b21aa0 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -24,6 +24,7 @@ const modulesProxyhandler: ProxyHandler = { const mod = Reflect.get(target, p); // 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; const patchedMod = patchFactory(p, mod); @@ -90,12 +91,14 @@ Object.defineProperty(Function.prototype, "O", { // Returns whether a chunk has been loaded Object.defineProperty(onChunksLoaded, "j", { + configurable: true, + set(v) { + // @ts-ignore delete onChunksLoaded.j; onChunksLoaded.j = v; originalOnChunksLoaded.j = v; - }, - configurable: true + } }); } @@ -113,7 +116,7 @@ Object.defineProperty(Function.prototype, "O", { Object.defineProperty(Function.prototype, "m", { configurable: true, - set(originalModules: any) { + set(originalModules: WebpackRequire["m"]) { // When using react devtools or other extensions, we may also catch their webpack here. // This ensures we actually got the right one const { stack } = new Error(); @@ -140,7 +143,7 @@ Object.defineProperty(Function.prototype, "m", { let webpackNotInitializedLogged = false; -function patchFactory(id: string | number, mod: ModuleFactory) { +function patchFactory(id: PropertyKey, mod: ModuleFactory) { for (const factoryListener of factoryListeners) { try { factoryListener(mod); @@ -192,7 +195,7 @@ function patchFactory(id: string | number, mod: ModuleFactory) { const newCode = executePatch(replacement.match, replacement.replace as string); if (newCode === code) { 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) { logger.debug("Function Source:\n", code); } @@ -210,9 +213,9 @@ function patchFactory(id: string | number, mod: ModuleFactory) { } 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) { - 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) { const changeSize = code.length - lastCode.length; diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts index 7cd28866e..052351b79 100644 --- a/src/webpack/webpack.ts +++ b/src/webpack/webpack.ts @@ -36,7 +36,7 @@ export const onceReady = new Promise(r => _resolveReady = r); export let wreq: WebpackRequire; export let cache: WebpackRequire["c"]; -export type FilterFn = (mod: any) => boolean; +export type FilterFn = (module: ModuleExports) => boolean; export const filters = { byProps: (...props: string[]): FilterFn => @@ -129,7 +129,7 @@ export function findAll(filter: FilterFn) { if (typeof filter !== "function") throw new Error("Invalid filter. Expected a function got " + typeof filter); - const ret = [] as any[]; + const ret: ModuleExports[] = []; for (const key in cache) { const mod = cache[key]; if (!mod?.exports) continue; @@ -169,7 +169,7 @@ export const findBulk = traceFunction("findBulk", function findBulk(...filterFns const filters = filterFns as Array; let found = 0; - const results = Array(length); + const results: ModuleExports[] = Array(length); outer: for (const key in cache) { @@ -496,12 +496,12 @@ export function waitFor(filter: string | string[] | FilterFn, callback: Callback * @returns Mapping of found modules */ export function search(...filters: Array) { - const results = {} as Record; + const results: WebpackRequire["m"] = {}; const factories = wreq.m; outer: for (const id in factories) { // @ts-ignore - const factory = factories[id].original ?? factories[id]; + const factory = factories[id].$$vencordOriginal ?? factories[id]; const str: string = factory.toString(); for (const filter of filters) { if (typeof filter === "string" && !str.includes(filter)) continue outer; @@ -521,18 +521,18 @@ export function search(...filters: Array) { * so putting breakpoints or similar will have no effect. * @param id The id of the module to extract */ -export function extract(id: string | number) { - const mod = wreq.m[id] as Function; +export function extract(id: PropertyKey) { + const mod = wreq.m[id]; if (!mod) return null; const code = ` -// [EXTRACTED] WebpackModule${id} +// [EXTRACTED] WebpackModule${String(id)} // 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()} -//# sourceURL=ExtractedWebpackModule${id} +//# sourceURL=ExtractedWebpackModule${String(id)} `; - const extracted = (0, eval)(code); - return extracted as Function; + const extracted: ModuleFactory = (0, eval)(code); + return extracted; } diff --git a/src/webpack/wreq.d.ts b/src/webpack/wreq.d.ts index d3d38127f..c86fa1c49 100644 --- a/src/webpack/wreq.d.ts +++ b/src/webpack/wreq.d.ts @@ -4,8 +4,6 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -export type AnyRecord = Record; - export type ModuleExports = any; export type Module = { @@ -14,8 +12,8 @@ export type Module = { exports: ModuleExports; }; -/** exports ({@link ModuleExports}) can be anything, however initially it is always an empty object */ -export type ModuleFactory = (module: Module, exports: AnyRecord, require: WebpackRequire) => void; +/** exports can be anything, however initially it is always an empty object */ +export type ModuleFactory = (module: Module, exports: ModuleExports, require: WebpackRequire) => void; export type AsyncModuleBody = ( handleDependencies: (deps: Promise[]) => Promise & (() => 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) & { /** Check if a chunk has been loaded */ - j: (chunkId: PropertyKey) => boolean; + j: (this: OnChunksLoaded, chunkId: PropertyKey) => boolean; }; export type WebpackRequire = ((moduleId: PropertyKey) => Module) & { @@ -57,7 +55,7 @@ export type WebpackRequire = ((moduleId: PropertyKey) => Module) & { * }); * @returns fromObject */ - es: (this: WebpackRequire, fromObject: AnyRecord, toObject: AnyRecord) => AnyRecord; + es: (this: WebpackRequire, fromObject: Record, toObject: Record) => Record; /** * Creates an async module. The body function must be a async function. * "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] } * } */ - d: (this: WebpackRequire, exports: AnyRecord, definiton: AnyRecord) => void; + d: (this: WebpackRequire, exports: Record, definiton: Record) => void; /** The chunk handlers, which are used to ensure the files of the chunks are loaded, or load if necessary */ f: ChunkHandlers; /** @@ -100,7 +98,7 @@ export type WebpackRequire = ((moduleId: PropertyKey) => Module) & { */ e: (this: WebpackRequire, chunkId: PropertyKey) => Promise; /** 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 */ u: (this: WebpackRequire, chunkId: PropertyKey) => string; /** 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; /** 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 */ 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" * @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; + v: (this: WebpackRequire, exports: ModuleExports, wasmModuleId: any, wasmModuleHash: string, importsObj?: WebAssembly.Imports) => Promise; /** Bundle public path, where chunk files are stored. Used by other methods which load chunks to obtain the full asset url */ p: string; /** Document baseURI or WebWorker location.href */