feat(metro): cache module flags

This commit is contained in:
amsyarasyiq 2024-05-21 20:21:54 +08:00
parent 5c7d819264
commit 3667a4361e
3 changed files with 54 additions and 9 deletions

View file

@ -1,28 +1,40 @@
import { ClientInfoManager, MMKVManager } from "@lib/api/native/modules";
import { throttle } from "@lib/utils/throttle";
const CACHE_VERSION = 12;
const BUNNY_METRO_CACHE_KEY = `__bunny_metro_cache_key_v${CACHE_VERSION}__`;
export enum ExportsFlags {
EXISTS = 1 << 0,
ES_MODULE = 1 << 1,
BLACKLISTED = 1 << 2,
FUNCTION = 1 << 3,
PRIMITIVE = 1 << 4,
}
type ModulesMap = {
_?: 1;
[id: number]: 1 | void;
[id: number]: number;
};
interface MetroCacheStore {
_v: 10;
_v: typeof CACHE_VERSION;
_buildNumber: number;
exportsIndex: Record<string, [number, number]>;
findIndex: Record<string, ModulesMap | undefined>;
polyfillIndex: Record<string, ModulesMap | undefined>;
assetsIndex: Record<string, number>;
}
const BUNNY_METRO_CACHE_KEY = "__bunny_metro_cache_key_v10__";
let _metroCache = null as unknown as MetroCacheStore;
export const getMetroCache = window.__getMetroCache = () => _metroCache;
function buildInitCache() {
_metroCache = {
_v: 10,
_v: CACHE_VERSION,
_buildNumber: ClientInfoManager.Build,
exportsIndex: {},
findIndex: {},
polyfillIndex: {},
assetsIndex: {}
@ -54,13 +66,37 @@ export async function initMetroCache() {
const saveCache = throttle(() => MMKVManager.setItem(BUNNY_METRO_CACHE_KEY, JSON.stringify(_metroCache)));
function extractExportsFlags(moduleExports: any) {
if (!moduleExports) return 0;
let bit = ExportsFlags.EXISTS;
bit |= moduleExports.__esModule ? ExportsFlags.ES_MODULE : 0;
bit |= typeof moduleExports === "function" ? ExportsFlags.FUNCTION : 0;
if (typeof moduleExports === "string" || typeof moduleExports === "number") {
bit |= ExportsFlags.PRIMITIVE;
}
return bit;
}
export function indexExportsFlags(moduleId: number, moduleExports: any) {
_metroCache.exportsIndex[moduleId] ??= moduleExports.default && moduleExports.__esModule
? [extractExportsFlags(moduleExports), extractExportsFlags(moduleExports.default)]
: [extractExportsFlags(moduleExports), 0];
}
export function indexBlacklistFlag(id: number) {
_metroCache.exportsIndex[id] ??= [ExportsFlags.BLACKLISTED, ExportsFlags.BLACKLISTED];
}
export function getCacherForUniq(uniq: string, allFind: boolean) {
let indexObject = _metroCache.findIndex[uniq];
return {
cacheId(moduleId: number) {
cacheId(moduleId: number, exports: any) {
indexObject ??= _metroCache.findIndex[uniq] ??= {};
indexObject[moduleId] = 1;
indexObject[moduleId] ??= extractExportsFlags(exports);
saveCache();
},
finish() {

View file

@ -24,7 +24,7 @@ export function findModule<A extends unknown[]>(filter: FilterFn<A>) {
for (const [id, moduleExports] of getModules(filter.uniq, false)) {
const [testedExports, defaultExp] = testExports(moduleExports, id, filter);
if (testedExports !== undefined) {
cacheId(id);
cacheId(id, testedExports);
return [id, defaultExp];
}
}
@ -63,7 +63,7 @@ export function findAllModule<A extends unknown[]>(filter: FilterFn<A>) {
const [testedExports, defaultExp] = testExports(moduleExports, id, filter);
if (testedExports !== undefined) {
foundExports.push([id, defaultExp]);
cacheId(id);
cacheId(id, testedExports);
}
}

View file

@ -1,4 +1,4 @@
import { getMetroCache } from "@metro/caches";
import { ExportsFlags, getMetroCache, indexBlacklistFlag, indexExportsFlags } from "@metro/caches";
import { Metro } from "@metro/types";
import { before, instead } from "spitroast";
@ -16,6 +16,12 @@ let _importingModuleId: string | null = null;
for (const id in metroModules) {
const metroModule = metroModules[id];
const cache = getMetroCache().exportsIndex[id];
if (cache?.[0] & ExportsFlags.BLACKLISTED) {
blacklistModule(id);
continue;
}
if (metroModule!.factory) {
instead("factory", metroModule, ((args: Parameters<Metro.FactoryFn>, origFunc: Metro.FactoryFn) => {
_importingModuleId = id;
@ -51,6 +57,7 @@ for (const id in metroModules) {
function blacklistModule(id: string) {
Object.defineProperty(metroModules, id, { enumerable: false });
blacklistedIds.add(id);
indexBlacklistFlag(Number(id));
}
function isBadExports(exports: any) {
@ -58,6 +65,8 @@ function isBadExports(exports: any) {
}
function onModuleRequire(moduleExports: any, id: Metro.ModuleID) {
indexExportsFlags(Number(id), moduleExports);
// Temporary
moduleExports.initSentry &&= () => undefined;
if (moduleExports.default?.track && moduleExports.default.trackMaker)