Skip to content

Commit

Permalink
metro(cache): properly cache assets
Browse files Browse the repository at this point in the history
  • Loading branch information
pylixonly committed Jun 1, 2024
1 parent 93ab105 commit 5a5639c
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 17 deletions.
37 changes: 23 additions & 14 deletions src/lib/api/assets.ts
Original file line number Diff line number Diff line change
@@ -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;
},
});
Expand Down Expand Up @@ -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;

6 changes: 3 additions & 3 deletions src/metro/caches.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
}
}

0 comments on commit 5a5639c

Please sign in to comment.