From da76c6670277c2bcb8d952727e00ade61d568fb0 Mon Sep 17 00:00:00 2001 From: amsyarasyiq <82711525+amsyarasyiq@users.noreply.github.com> Date: Mon, 20 May 2024 20:20:55 +0800 Subject: [PATCH] refactor(metro): rework cache --- src/metro/caches.ts | 51 +++++++++++++++++++++------------ src/metro/finders.ts | 17 ++++++----- src/metro/index.ts | 1 + src/metro/modules.ts | 4 +-- src/metro/polyfills/redesign.ts | 12 ++++---- src/metro/utils.ts | 20 ++++++------- 6 files changed, 62 insertions(+), 43 deletions(-) diff --git a/src/metro/caches.ts b/src/metro/caches.ts index 3b93b9f..0e08279 100644 --- a/src/metro/caches.ts +++ b/src/metro/caches.ts @@ -1,9 +1,11 @@ import { ClientInfoManager, MMKVManager } from "@lib/api/native/modules"; import { throttle } from "@lib/utils/throttle"; +import { getCachedPolyfillModules } from "./modules"; + const BUNNY_METRO_CACHE_KEY = "__bunny_metro_cache_key_v5__"; -type ModulesIndexer = { +type ModulesMap = { _?: 1; [id: number]: 1 | void; }; @@ -11,8 +13,8 @@ type ModulesIndexer = { interface MetroCacheStore { v: 5; buildNumber: number; - findIndex: Record; - polyfillCache: Record; + findIndex: Record; + polyfillCache: Record; assetsCache: Record; } @@ -57,25 +59,38 @@ export async function initMetroCache() { const saveCache = throttle(() => MMKVManager.setItem(BUNNY_METRO_CACHE_KEY, JSON.stringify(metroCache))); -export function registerModuleFindCacheId(uniqueId: string, moduleId: number, all: boolean) { - (metroCache.findIndex[uniqueId] ??= { _: undefined })[moduleId] = 1; - if (all) metroCache.findIndex[uniqueId]!._ = 1; - saveCache(); +export function getCacherForUniq(uniq: string, allFind: boolean) { + const indexObject = metroCache.findIndex[uniq] ??= {}; + + return { + cacheId(moduleId: number) { + indexObject[moduleId] = 1; + saveCache(); + }, + finish() { + if (allFind) indexObject._ = 1; + saveCache(); + } + }; } -export function registerModuleFindFinished(uniqueId: string) { - metroCache.findIndex[uniqueId] ??= { _: undefined }; - saveCache(); -} +export function getPolyfillModuleCacher(name: string) { + const indexObject = metroCache.polyfillCache[name] ??= {}; -export function registerPolyfillCacheId(name: string, moduleId: number, remove = false) { - if (remove) delete metroCache.polyfillCache[name]?.[moduleId]; - else (metroCache.polyfillCache[name] ??= {})[moduleId] = 1; - saveCache(); + return { + getModules() { + return getCachedPolyfillModules(name); + }, + cacheId(moduleId: number) { + indexObject[moduleId] = 1; + saveCache(); + } + }; } export function registerAssetCacheId(name: string, moduleId: number) { - if (isNaN(moduleId)) return; - metroCache.assetsCache[name] = moduleId; - saveCache(); + if (!isNaN(moduleId)) { + metroCache.assetsCache[name] = moduleId; + saveCache(); + } } diff --git a/src/metro/finders.ts b/src/metro/finders.ts index 3358946..97c847c 100644 --- a/src/metro/finders.ts +++ b/src/metro/finders.ts @@ -1,4 +1,4 @@ -import { registerModuleFindCacheId, registerModuleFindFinished } from "./caches"; +import { getCacherForUniq } from "./caches"; import { getModules, requireModule } from "./modules"; import { FilterFn } from "./utils"; @@ -16,15 +16,17 @@ function testExports(moduleExports: any, moduleId: number, * @param filter find calls filter once for each enumerable module's exports until it finds one where filter returns a thruthy value. */ export function findModule(filter: FilterFn) { - for (const [id, moduleExports] of getModules(filter.serialized, false)) { + const { cacheId, finish } = getCacherForUniq(filter.uniq, false); + + for (const [id, moduleExports] of getModules(filter.uniq, false)) { const [testedExports, defaultExp] = testExports(moduleExports, id, filter); if (testedExports !== undefined) { - registerModuleFindCacheId(filter.serialized, id, false); + cacheId(id); return [id, defaultExp]; } } - registerModuleFindFinished(filter.serialized); + finish(); return []; } @@ -51,17 +53,18 @@ export function findExports(filter: FilterFn) { * @param filter findAll calls filter once for each enumerable module's exports, adding the exports to the returned array when filter returns a thruthy value. */ export function findAllModule(filter: FilterFn) { + const { cacheId, finish } = getCacherForUniq(filter.uniq, true); const foundExports: [id: number, defaultExp: boolean][] = []; - for (const [id, moduleExports] of getModules(filter.serialized, true)) { + for (const [id, moduleExports] of getModules(filter.uniq, true)) { const [testedExports, defaultExp] = testExports(moduleExports, id, filter); if (testedExports !== undefined) { foundExports.push([id, defaultExp]); - registerModuleFindCacheId(filter.serialized, id, true); + cacheId(id); } } - registerModuleFindFinished(filter.serialized); + finish(); return foundExports; } diff --git a/src/metro/index.ts b/src/metro/index.ts index d48960a..9d01ba2 100644 --- a/src/metro/index.ts +++ b/src/metro/index.ts @@ -1,3 +1,4 @@ +export * as common from "./common"; export * from "./filters"; export * from "./finders"; export * from "./utils"; diff --git a/src/metro/modules.ts b/src/metro/modules.ts index b1bb887..50c37ca 100644 --- a/src/metro/modules.ts +++ b/src/metro/modules.ts @@ -158,10 +158,10 @@ export function requireModule(id: Metro.ModuleID) { return moduleExports; } -export function* getModules(uniqueId: string, all = false) { +export function* getModules(uniq: string, all = false) { yield [-1, require("@metro/polyfills/redesign")]; - let cache = getMetroCache().findIndex[uniqueId]; + let cache = getMetroCache().findIndex[uniq]; if (all && !cache?._) cache = undefined; for (const id in cache ?? metroModules) { diff --git a/src/metro/polyfills/redesign.ts b/src/metro/polyfills/redesign.ts index 04f9e11..aea8f1f 100644 --- a/src/metro/polyfills/redesign.ts +++ b/src/metro/polyfills/redesign.ts @@ -1,5 +1,4 @@ -import { registerPolyfillCacheId } from "@metro/caches"; -import { getCachedPolyfillModules, requireModule } from "@metro/modules"; +import { getPolyfillModuleCacher } from "@metro/caches"; import { LiteralUnion } from "type-fest"; const redesignProps = new Set([ @@ -103,8 +102,9 @@ type Keys = LiteralUnion ? U : string, const redesignPropSource = {} as Record; const redesignModule = {} as Record; -for (const id in getCachedPolyfillModules("redesign_module")) { - const moduleExports = requireModule(id); +const cacher = getPolyfillModuleCacher("redesign_module"); + +for (const [id, moduleExports] of cacher.getModules()) { polyfillRedesignModule(moduleExports, Number(id)); } @@ -113,10 +113,10 @@ function polyfillRedesignModule(moduleExports: any, id: number) { for (const prop of redesignProps) { if (moduleExports?.[prop]) { - registerPolyfillCacheId("redesign_module", id); + cacher.cacheId(id); propMap.set(prop, null); } else if (moduleExports?.default?.[prop]) { - registerPolyfillCacheId("redesign_module", id); + cacher.cacheId(id); propMap.set(prop, "default"); } } diff --git a/src/metro/utils.ts b/src/metro/utils.ts index 5793b6a..d09c3c6 100644 --- a/src/metro/utils.ts +++ b/src/metro/utils.ts @@ -9,27 +9,27 @@ export interface FilterFn { filter: FilterCheckDef; args: A; isDefault: boolean; - serialized: string; + uniq: string; } -export interface FilterDef { +export interface FilterDefinition { (...args: A): FilterFn; byDefault(...args: A): FilterFn; - serializer(args: A): string; + uniqMaker(args: A): string; } export function createFilterDefinition( fn: FilterCheckDef, - serializer: (args: A) => string -): FilterDef { + uniqMaker: (args: A) => string +): FilterDefinition { function createHolder(func: T, args: A, isDefault: boolean) { return Object.assign(func, { filter: fn, args, isDefault, - serialized: [ + uniq: [ isDefault && "default::", - serializer(args) + uniqMaker(args) ].filter(Boolean).join("") }); } @@ -44,17 +44,17 @@ export function createFilterDefinition( return Object.assign(curried, { byDefault: curriedDefault, - serializer + uniqMaker }); } export function createSimpleFilter( filter: (m: ModuleExports) => boolean, - id: string + uniq: string ) { return createFilterDefinition( (_, m) => filter(m), - () => `dynamic::${id}` + () => `dynamic::${uniq}` )(); }