refactor(metro): rework cache

This commit is contained in:
amsyarasyiq 2024-05-20 20:20:55 +08:00
parent 309072ae44
commit da76c66702
6 changed files with 62 additions and 43 deletions

View file

@ -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<string, ModulesIndexer | undefined>;
polyfillCache: Record<string, ModulesIndexer | undefined>;
findIndex: Record<string, ModulesMap | undefined>;
polyfillCache: Record<string, ModulesMap | undefined>;
assetsCache: Record<string, number>;
}
@ -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();
}
}

View file

@ -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<A extends unknown[]>(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<A extends unknown[]>(filter: FilterFn<A>) {
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<A extends unknown[]>(filter: FilterFn<A>) {
* @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<A extends unknown[]>(filter: FilterFn<A>) {
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;
}

View file

@ -1,3 +1,4 @@
export * as common from "./common";
export * from "./filters";
export * from "./finders";
export * from "./utils";

View file

@ -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) {

View file

@ -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<typeof redesignProps extends Set<infer U> ? U : string,
const redesignPropSource = {} as Record<Keys, any>;
const redesignModule = {} as Record<Keys, any>;
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");
}
}

View file

@ -9,27 +9,27 @@ export interface FilterFn<A extends unknown[]> {
filter: FilterCheckDef<A>;
args: A;
isDefault: boolean;
serialized: string;
uniq: string;
}
export interface FilterDef<A extends unknown[]> {
export interface FilterDefinition<A extends unknown[]> {
(...args: A): FilterFn<A>;
byDefault(...args: A): FilterFn<A>;
serializer(args: A): string;
uniqMaker(args: A): string;
}
export function createFilterDefinition<A extends unknown[]>(
fn: FilterCheckDef<A>,
serializer: (args: A) => string
): FilterDef<A> {
uniqMaker: (args: A) => string
): FilterDefinition<A> {
function createHolder<T extends Function>(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<A extends unknown[]>(
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}`
)();
}