diff --git a/src/core/vendettaObject.ts b/src/core/vendettaObject.ts index e1d9813..5c166ae 100644 --- a/src/core/vendettaObject.ts +++ b/src/core/vendettaObject.ts @@ -8,8 +8,8 @@ import * as plugins from "@lib/managers/plugins"; import * as themes from "@lib/managers/themes"; import { loaderConfig, settings } from "@lib/settings"; import * as utils from "@lib/utils"; +import * as metro from "@metro"; import * as common from "@metro/common"; -import * as metro from "@metro/utils"; import * as alerts from "@ui/alerts"; import * as color from "@ui/color"; import * as components from "@ui/components"; @@ -17,6 +17,7 @@ import { Forms } from "@ui/components/discord/Forms"; import { CompatfulRedesign } from "@ui/components/discord/Redesign"; import { createThemedStyleSheet } from "@ui/styles"; import * as toasts from "@ui/toasts"; +import SparkMD5 from "spark-md5"; export const initVendettaObject = (): any => { const api = window.vendetta = { @@ -27,8 +28,20 @@ export const initVendettaObject = (): any => { }, metro: { modules: window.modules, - find: (filter: (m: any) => boolean) => metro.find(filter), - findAll: (filter: (m: any) => boolean) => metro.findAll(filter), + find: (filter: (m: any) => boolean) => { + const { stack } = new Error(); + return metro.find(metro.createSimpleFilter( + filter, + SparkMD5.hash(stack!) + )); + }, + findAll: (filter: (m: any) => boolean) => { + const { stack } = new Error(); + return metro.findAll(metro.createSimpleFilter( + filter, + SparkMD5.hash(stack!) + )); + }, findByProps: (...props: any) => { // Decor fix hack if (props.length === 1 && props[0] === "KeyboardAwareScrollView") { diff --git a/src/index.ts b/src/index.ts index 3044b96..2ac9b94 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ import initFixes from "@core/fixes"; import { initFetchI18nStrings } from "@core/i18n"; import { initCorePlugins } from "@core/plugins"; import initSettings from "@core/ui/settings"; +import { initVendettaObject } from "@core/vendettaObject"; import { patchCommands } from "@lib/api/commands"; import { injectFluxInterceptor } from "@lib/api/flux"; import { removeFile, writeFile } from "@lib/api/native/fs"; @@ -9,6 +10,7 @@ import { isPyonLoader, isThemeSupported } from "@lib/api/native/loader"; import { FileManager } from "@lib/api/native/modules"; import { patchLogHook } from "@lib/debug"; import { updateFonts } from "@lib/managers/fonts"; +import { initPlugins } from "@lib/managers/plugins"; import { initThemes, patchChatBackground } from "@lib/managers/themes"; import { logger } from "@lib/utils/logger"; import initSafeMode from "@ui/safeMode"; @@ -40,7 +42,7 @@ export default async () => { patchLogHook(), patchCommands(), patchChatBackground(), - // initVendettaObject(), + initVendettaObject(), initFetchI18nStrings(), initSettings(), initFixes(), @@ -55,7 +57,7 @@ export default async () => { window.bunny = lib; // Once done, load plugins - // lib.unload.push(await initPlugins()); + lib.unload.push(await initPlugins()); // Update the fonts updateFonts(); diff --git a/src/lib/index.ts b/src/lib/index.ts index 40c8644..056edde 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -4,15 +4,16 @@ import "../global.d.ts"; export * as api from "./api"; export * as debug from "./debug"; export * as managers from "./managers"; -// export * as metro from "./metro"; export * as settings from "./settings"; export * as ui from "./ui"; export * as utils from "./utils"; +export * as metro from "@metro"; const _disposer = new Array<() => unknown>; export function unload() { for (const d of _disposer) if (typeof d === "function") d(); + // @ts-expect-error delete window.bunny; } diff --git a/src/metro/caches.ts b/src/metro/caches.ts index c61a767..a0e84d9 100644 --- a/src/metro/caches.ts +++ b/src/metro/caches.ts @@ -2,16 +2,21 @@ import { ClientInfoManager, MMKVManager } from "@lib/api/native/modules"; import { throttle } from "@lib/utils/throttle"; import SparkMD5 from "spark-md5"; -// fucked types right here interface MetroCacheStore { - v: 4; + v: 5; buildNumber: number; - findCache: Record | undefined>; - polyfillCache: Record | undefined>; + findIndex: Record; + polyfillCache: Record; assetsCache: Record; } -const PYON_METRO_CACHE_KEY = "__bunny_metro_cache_key_v4__"; +const BUNNY_METRO_CACHE_KEY = "__bunny_metro_cache_key_v5__"; let metroCache = null as unknown as MetroCacheStore; @@ -26,15 +31,15 @@ export function getFuncUniqCall() { function buildInitCache() { metroCache = { - v: 4, + v: 5, buildNumber: ClientInfoManager.Build, - findCache: {}, + findIndex: {}, polyfillCache: {}, assetsCache: {} } as const; // Make sure all assets are cached. Delay by a second - // because force loading all of results in an unexpected crash. + // because force loading all will results in an unexpected crash. setTimeout(() => { for (const id in window.modules) { require("@metro/modules").requireModule(id); @@ -43,8 +48,8 @@ function buildInitCache() { } export async function initMetroCache() { - const rawCache = await MMKVManager.getItem(PYON_METRO_CACHE_KEY); - if (String(1) !== "1" || rawCache == null) return void buildInitCache(); + const rawCache = await MMKVManager.getItem(BUNNY_METRO_CACHE_KEY); + if (rawCache == null) return void buildInitCache(); try { metroCache = JSON.parse(rawCache); @@ -58,12 +63,12 @@ export async function initMetroCache() { } const saveCache = throttle(() => { - MMKVManager.setItem(PYON_METRO_CACHE_KEY, JSON.stringify(metroCache)); + MMKVManager.setItem(BUNNY_METRO_CACHE_KEY, JSON.stringify(metroCache)); }); export function registerModuleFindCacheId(uniqueId: string, moduleId: number, all: boolean) { - (metroCache.findCache[uniqueId] ??= { _: undefined })[moduleId] = 1; - if (all) metroCache.findCache[uniqueId]!._ ||= 1; + (metroCache.findIndex[uniqueId] ??= { _: undefined })[moduleId] = 1; + if (all) metroCache.findIndex[uniqueId]!._ ||= 1; saveCache(); } diff --git a/src/metro/finders.ts b/src/metro/finders.ts index 41b1cf9..31d19a4 100644 --- a/src/metro/finders.ts +++ b/src/metro/finders.ts @@ -1,4 +1,4 @@ -import { getFuncUniqCall } from "./caches"; +import { getFuncUniqCall, registerModuleFindCacheId } from "./caches"; import { FilterFn } from "./filters"; import { getModules } from "./modules"; @@ -14,12 +14,14 @@ function testExports(moduleExports: any, filter: FilterFn(filter: FilterFn) { - const uniq = getFuncUniqCall(); + const uniq = filter.serialized || getFuncUniqCall(); for (const [id, moduleExports] of getModules(uniq, false)) { const testedExports = testExports(moduleExports, filter); - if (testedExports !== undefined) + if (testedExports !== undefined) { + registerModuleFindCacheId(uniq, id, false); return testedExports; + } } } @@ -29,12 +31,14 @@ export function find(filter: FilterFn) { */ export function findAll(filter: FilterFn) { const foundExports: any[] = []; - const uniq = getFuncUniqCall(); + const uniq = filter.serialized || getFuncUniqCall(); for (const [id, moduleExports] of getModules(uniq, true)) { const testedExports = testExports(moduleExports, filter); - if (testedExports !== undefined) + if (testedExports !== undefined) { foundExports.push(testedExports); + registerModuleFindCacheId(uniq, id, true); + } } return foundExports; } diff --git a/src/metro/index.ts b/src/metro/index.ts new file mode 100644 index 0000000..d48960a --- /dev/null +++ b/src/metro/index.ts @@ -0,0 +1,3 @@ +export * from "./filters"; +export * from "./finders"; +export * from "./utils"; diff --git a/src/metro/modules.ts b/src/metro/modules.ts index f794ac1..ba7ed90 100644 --- a/src/metro/modules.ts +++ b/src/metro/modules.ts @@ -157,7 +157,7 @@ export function* getModules(uniqueId: string | null, all = false) { let cache = null; if (uniqueId) { - cache = getMetroCache().findCache[uniqueId]; + cache = getMetroCache().findIndex[uniqueId]; if (all && !cache?._) cache = undefined; } @@ -167,3 +167,12 @@ export function* getModules(uniqueId: string | null, all = false) { yield [id, exports]; } } + +export function* getCachedPolyfillModules(name: string) { + const cache = getMetroCache().polyfillCache[name]; + for (const id in cache ?? modules) { + const exports = requireModule(id); + if (isBadExports(exports)) continue; + yield [id, exports]; + } +} diff --git a/src/metro/polyfills/redesign.ts b/src/metro/polyfills/redesign.ts index 913d51c..04f9e11 100644 --- a/src/metro/polyfills/redesign.ts +++ b/src/metro/polyfills/redesign.ts @@ -1,5 +1,5 @@ -import { getMetroCache, registerPolyfillCacheId } from "@metro/caches"; -import { getModules, requireModule } from "@metro/modules"; +import { registerPolyfillCacheId } from "@metro/caches"; +import { getCachedPolyfillModules, requireModule } from "@metro/modules"; import { LiteralUnion } from "type-fest"; const redesignProps = new Set([ @@ -103,8 +103,7 @@ type Keys = LiteralUnion ? U : string, const redesignPropSource = {} as Record; const redesignModule = {} as Record; -const cache = getMetroCache().polyfillCache.redesign_module; -for (const id in cache ?? getModules(null)) { +for (const id in getCachedPolyfillModules("redesign_module")) { const moduleExports = requireModule(id); polyfillRedesignModule(moduleExports, Number(id)); } diff --git a/src/metro/utils.ts b/src/metro/utils.ts index dd74dc8..7509b16 100644 --- a/src/metro/utils.ts +++ b/src/metro/utils.ts @@ -1,8 +1,16 @@ import { byDisplayName, byName, byProps, byStoreName, byTypeName } from "./filters"; -import { find } from "./finders"; +import { find, findAll } from "./finders"; export const findByProps = (...props: string[]) => find(byProps(...props)); +export const findByPropsAll = (...props: string[]) => findAll(byProps(...props)); + export const findByName = (name: string, expDefault = true) => find(expDefault ? byName(name) : byName.byDefault(name)); +export const findByNameAll = (name: string, expDefault = true) => findAll(expDefault ? byName(name) : byName.byDefault(name)); + export const findByDisplayName = (name: string, expDefault = true) => find(expDefault ? byDisplayName(name) : byDisplayName.byDefault(name)); +export const findByDisplayNameAll = (name: string, expDefault = true) => findAll(expDefault ? byDisplayName(name) : byDisplayName.byDefault(name)); + export const findByTypeName = (name: string, expDefault = true) => find(expDefault ? byTypeName(name) : byTypeName.byDefault(name)); +export const findByTypeNameAll = (name: string, expDefault = true) => findAll(expDefault ? byTypeName(name) : byTypeName.byDefault(name)); + export const findByStoreName = (name: string) => find(byStoreName(name));