metro(cache): properly cache assets

This commit is contained in:
amsyarasyiq 2024-06-02 02:32:01 +08:00
parent 93ab105735
commit 5a5639c7a8
2 changed files with 26 additions and 17 deletions

View file

@ -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<string, Asset> = new Proxy<any>({}, {
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;

View file

@ -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<string, number>,
findIndex: {} as Record<string, ModulesMap | undefined>,
polyfillIndex: {} as Record<string, ModulesMap | undefined>,
assetsIndex: {} as Record<string, number>
assetsIndex: {} as Record<string, ModulesMap | undefined>
} 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();
}
}