From 5a5639c7a87b8d5a119c2824abf2291bea2e5ba9 Mon Sep 17 00:00:00 2001 From: amsyarasyiq <82711525+amsyarasyiq@users.noreply.github.com> Date: Sun, 2 Jun 2024 02:32:01 +0800 Subject: [PATCH] metro(cache): properly cache assets --- src/lib/api/assets.ts | 37 +++++++++++++++++++++++-------------- src/metro/caches.ts | 6 +++--- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/lib/api/assets.ts b/src/lib/api/assets.ts index 5df2a86..c63da54 100644 --- a/src/lib/api/assets.ts +++ b/src/lib/api/assets.ts @@ -1,28 +1,38 @@ -// TODO: Rewrite the whole thing to fit new metro :3 - import { after } from "@lib/api/patcher"; import { getMetroCache, registerAssetCacheId } from "@metro/caches"; import { getImportingModuleId, requireModule } from "@metro/modules"; +// TODO: Deprecate this map, make another that maps to an array of assets (Asset[]) instead +/** + * Pitfall: Multiple assets may have the same name, this is fine if we require the asset only for display,\ + * but not when used to get the registered id/index. In some condition, this would break some plugins like HideGiftButton that gets id by name.\ + */ export const assetsMap: Record = new Proxy({}, { - get(target, p) { + get(cache, p) { if (typeof p !== "string") return undefined; - if (target[p]) return target[p]; + if (cache[p]) return cache[p]; - const moduleId = getMetroCache().assetsIndex[p]; - if (moduleId == null) return undefined; + const moduleIds = getMetroCache().assetsIndex[p]; + if (moduleIds == null || Object.keys(moduleIds).length === 0) return undefined; - const assetIndex = requireModule(moduleId); - const assetDefinition = assetsModule.getAssetByID(assetIndex); + for (const id in moduleIds) { + const assetIndex = requireModule(Number(id)); + const assetDefinition = assetsModule.getAssetByID(assetIndex); - assetDefinition.index ??= assetDefinition.id ??= assetIndex; - assetDefinition.moduleId ??= moduleId; + assetDefinition.index ??= assetDefinition.id ??= assetIndex; + assetDefinition.moduleId ??= id; - return target[p] = assetDefinition; + // ??= is intended, we only assign to the first asset registered + // Though, VD seems to assign the last registered, but doing that breaks HideGiftButton so idk + // https://github.com/vendetta-mod/Vendetta/blob/rewrite/src/ui/assets.ts + cache[p] ??= assetDefinition; + } + + return cache[p]; }, - ownKeys(target) { + ownKeys(cache) { const keys = Reflect.ownKeys(getMetroCache().assetsIndex); - for (const key of keys) target[key] = this.get!(target, key, {}); + for (const key of keys) cache[key] = this.get!(cache, key, {}); return keys; }, }); @@ -61,4 +71,3 @@ export const findAsset = (filter: (a: any) => void): Asset | null | undefined => export const requireAssetByName = (name: string): Asset => assetsMap[name]; export const requireAssetByIndex = (id: number): Asset => assetsModule.getAssetByID(id); export const requireAssetIndex = (name: string) => assetsMap[name]?.index; - diff --git a/src/metro/caches.ts b/src/metro/caches.ts index 9f933b9..ec6ce66 100644 --- a/src/metro/caches.ts +++ b/src/metro/caches.ts @@ -1,7 +1,7 @@ import { ClientInfoManager, MMKVManager } from "@lib/api/native/modules"; import { throttle } from "@lib/utils/throttle"; -const CACHE_VERSION = 31; +const CACHE_VERSION = 32; const BUNNY_METRO_CACHE_KEY = `__bunny_metro_cache_key_v${CACHE_VERSION}__`; export enum ExportsFlags { @@ -30,7 +30,7 @@ function buildInitCache() { exportsIndex: {} as Record, findIndex: {} as Record, polyfillIndex: {} as Record, - assetsIndex: {} as Record + assetsIndex: {} as Record } as const; // Make sure all assets are cached. Delay by a second @@ -125,7 +125,7 @@ export function getPolyfillModuleCacher(name: string) { export function registerAssetCacheId(name: string, moduleId: number) { if (!isNaN(moduleId)) { - _metroCache.assetsIndex[name] = moduleId; + (_metroCache.assetsIndex[name] ??= {})[moduleId] = 1; saveCache(); } }