From 999d6c812f9e5537297d9fc1648a191956f4f6ab Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 25 May 2024 23:51:59 -0300 Subject: [PATCH] better types? no ts-ignore, also filters.componentByCode is recursive now --- .eslintrc.json | 12 +++++- scripts/generateReport.ts | 6 +-- src/plugins/messageLinkEmbeds/index.tsx | 5 +-- src/utils/lazy.ts | 12 ++++-- src/utils/lazyReact.tsx | 2 - src/webpack/webpack.tsx | 57 +++++++++++++------------ 6 files changed, 54 insertions(+), 40 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 2ee24e8b3..ab78ac85b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,6 +1,9 @@ { "root": true, "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "./tsconfig.json" + }, "ignorePatterns": ["dist", "browser"], "plugins": [ "@typescript-eslint", @@ -62,7 +65,14 @@ "no-constant-condition": ["error", { "checkLoops": false }], "no-duplicate-imports": "error", "no-extra-semi": "error", - "dot-notation": "error", + "dot-notation": "off", + "@typescript-eslint/dot-notation": [ + "error", + { + "allowPrivateClassPropertyAccess": true, + "allowProtectedClassPropertyAccess": true + } + ], "no-useless-escape": [ "error", { diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 2f21033bb..86305a6fc 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -289,10 +289,8 @@ async function runtime(token: string) { }); // Monkey patch Logger to not log with custom css - // @ts-ignore - const originalLog = Vencord.Util.Logger.prototype._log; - // @ts-ignore - Vencord.Util.Logger.prototype._log = function (level, levelColor, args) { + const originalLog = Vencord.Util.Logger.prototype["_log"]; + Vencord.Util.Logger.prototype["_log"] = function (level, levelColor, args) { if (level === "warn" || level === "error") return console[level]("[Vencord]", this.name + ":", ...args); diff --git a/src/plugins/messageLinkEmbeds/index.tsx b/src/plugins/messageLinkEmbeds/index.tsx index 726fd79cd..6659a1285 100644 --- a/src/plugins/messageLinkEmbeds/index.tsx +++ b/src/plugins/messageLinkEmbeds/index.tsx @@ -212,10 +212,9 @@ function computeWidthAndHeight(width: number, height: number) { function withEmbeddedBy(message: Message, embeddedBy: string[]) { return new Proxy(message, { - get(_, prop) { + get(target, prop, receiver) { if (prop === "vencordEmbeddedBy") return embeddedBy; - // @ts-ignore ts so bad - return Reflect.get(...arguments); + return Reflect.get(target, prop, receiver); } }); } diff --git a/src/utils/lazy.ts b/src/utils/lazy.ts index 57e68398f..179b7d982 100644 --- a/src/utils/lazy.ts +++ b/src/utils/lazy.ts @@ -14,7 +14,11 @@ export type ProxyLazy = T & { export const proxyLazyGet = Symbol.for("vencord.lazy.get"); export const proxyLazyCache = Symbol.for("vencord.lazy.cached"); -export function makeLazy(factory: () => T, attempts = 5, { isIndirect = false }: { isIndirect?: boolean; } = {}): () => T { +export type LazyFunction = (() => T) & { + $$vencordLazyFailed: () => boolean; +}; + +export function makeLazy(factory: () => T, attempts = 5, { isIndirect = false }: { isIndirect?: boolean; } = {}): LazyFunction { let tries = 0; let cache: T; @@ -82,7 +86,6 @@ export function proxyLazy(factory: () => T, attempts = 5, isChild Object.assign(proxyDummy, { [proxyLazyGet]() { if (!proxyDummy[proxyLazyCache]) { - // @ts-ignore if (!get.$$vencordLazyFailed()) { proxyDummy[proxyLazyCache] = get(); } @@ -113,7 +116,10 @@ export function proxyLazy(factory: () => T, attempts = 5, isChild // `const { meow } = proxyLazy(() => ({ meow: [] }));` if (!isChild && isSameTick) { return proxyLazy( - () => Reflect.get(target[proxyLazyGet](), p, target[proxyLazyGet]()), + () => { + const lazyTarget = target[proxyLazyGet](); + return Reflect.get(lazyTarget, p, lazyTarget); + }, attempts, true ); diff --git a/src/utils/lazyReact.tsx b/src/utils/lazyReact.tsx index 719ce4262..74c7832d2 100644 --- a/src/utils/lazyReact.tsx +++ b/src/utils/lazyReact.tsx @@ -27,7 +27,6 @@ export function LazyComponent(factory: () => React.Compo let lazyFailedLogged = false; const LazyComponent = (props: T) => { - // @ts-ignore if (!get.$$vencordLazyFailed()) { const ResultComponent = get(); if (ResultComponent != null) { @@ -36,7 +35,6 @@ export function LazyComponent(factory: () => React.Compo } if (InnerComponent === null && !lazyFailedLogged) { - // @ts-ignore if (get.$$vencordLazyFailed()) { lazyFailedLogged = true; } diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index d0ca6609b..d79e1e0e4 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -27,21 +27,22 @@ export const onceReady = new Promise(r => _resolveReady = r); export let wreq: WebpackInstance; export let cache: WebpackInstance["c"]; -export type FilterFn = (mod: any) => boolean; +export type FilterFn = ((mod: any) => boolean) & { + $$vencordProps?: string[]; +}; export const filters = { byProps: (...props: string[]): FilterFn => { - const filter = props.length === 1 + const filter: FilterFn = props.length === 1 ? m => m?.[props[0]] !== void 0 : m => props.every(p => m?.[p] !== void 0); - // @ts-ignore filter.$$vencordProps = ["byProps", ...props]; return filter; }, byCode: (...code: string[]): FilterFn => { - const filter = m => { + const filter: FilterFn = m => { if (typeof m !== "function") return false; const s = Function.prototype.toString.call(m); for (const c of code) { @@ -55,29 +56,36 @@ export const filters = { }, byStoreName: (name: string): FilterFn => { - const filter = m => m?.constructor?.displayName === name; + const filter: FilterFn = m => m?.constructor?.displayName === name; filter.$$vencordProps = ["byStoreName", name]; return filter; }, componentByCode: (...code: string[]): FilterFn => { - const filter = filters.byCode(...code); - const wrapper = m => { - if (filter(m)) return true; - if (!m?.$$typeof) return false; - if (m?.type && m.type.render) return filter(m.type.render); // memo + forwardRef - if (m?.type) return filter(m.type); // memos - if (m?.render) return filter(m.render); // forwardRefs + const byCodeFilter = filters.byCode(...code); + const filter: FilterFn = m => { + let inner = m; + + while (inner != null) { + if (byCodeFilter(inner)) return true; + else if (!inner.$$typeof) return false; + else if (inner.type) inner = inner.type; // memos + else if (inner.render) inner = inner.render; // forwardRefs + else return false; + } + return false; }; - wrapper.$$vencordProps = ["componentByCode", ...code]; - return wrapper; + filter.$$vencordProps = ["componentByCode", ...code]; + return filter; } }; -export type ModCallbackFn = (mod: any) => void; +export type ModCallbackFn = ((mod: any) => void) & { + $$vencordCallbackCalled?: () => boolean; +}; export type ModCallbackFnWithId = (mod: any, id: string) => void; export const waitForSubscriptions = new Map(); @@ -94,15 +102,15 @@ let devToolsOpen = false; if (IS_DEV && IS_DISCORD_DESKTOP) { // At this point in time, DiscordNative has not been exposed yet, so setImmediate is needed setTimeout(() => { - DiscordNative/* just to make sure */?.window.setDevtoolsCallbacks(() => devToolsOpen = true, () => devToolsOpen = false); + DiscordNative?.window.setDevtoolsCallbacks(() => devToolsOpen = true, () => devToolsOpen = false); }, 0); } export const webpackSearchHistory = [] as Array<["waitFor" | "find" | "findComponent" | "findExportedComponent" | "findComponentByCode" | "findByProps" | "findByCode" | "findStore" | "extractAndLoadChunks" | "webpackDependantLazy" | "webpackDependantLazyComponent", any[]]>; function printFilter(filter: FilterFn) { - if ("$$vencordProps" in filter) { - const props = filter.$$vencordProps as string[]; + if (filter.$$vencordProps != null) { + const props = filter.$$vencordProps; return `${props[0]}(${props.slice(1).map(arg => `"${arg}"`).join(", ")})`; } @@ -127,16 +135,13 @@ export function waitFor(filter: FilterFn, callback: ModCallbackFn, { isIndirect const originalCallback = callback; let callbackCalled = false; - callback = function () { + callback = function (this: unknown) { callbackCalled = true; - // @ts-ignore - originalCallback(...arguments); + Reflect.apply(originalCallback, this, arguments); }; - // @ts-ignore callback.$$vencordCallbackCalled = () => callbackCalled; - webpackSearchHistory.push(["waitFor", [callback, filter]]); } @@ -277,7 +282,7 @@ export function findExportedComponent(...props: string[] if (IS_DEV) { WrapperComponent.$$vencordInner = () => InnerComponent; - webpackSearchHistory.push(["findExportedComponent", [WrapperComponent, ...props]]); + webpackSearchHistory.push(["findExportedComponent", [WrapperComponent, ...newProps]]); } if (InnerComponent !== null) return InnerComponent; @@ -309,7 +314,7 @@ export function findComponentByCode(...code: string[] | const ComponentResult = findComponent(filters.componentByCode(...newCode), parse, { isIndirect: true }); if (IS_DEV) { - webpackSearchHistory.push(["findComponentByCode", [ComponentResult, ...code]]); + webpackSearchHistory.push(["findComponentByCode", [ComponentResult, ...newCode]]); } return ComponentResult; @@ -475,7 +480,6 @@ export const cacheFindBulk = traceFunction("cacheFindBulk", function cacheFindBu /** * Find the id of the first module factory that includes all the given code. - * @returns string or null */ export const findModuleId = traceFunction("findModuleId", function findModuleId(...code: string[]) { outer: @@ -503,7 +507,6 @@ export const findModuleId = traceFunction("findModuleId", function findModuleId( /** * Find the first module factory that includes all the given code. - * @returns The module factory or null */ export function findModuleFactory(...code: string[]) { const id = findModuleId(...code);