feat(metro): cache module flags
This commit is contained in:
parent
5c7d819264
commit
3667a4361e
3 changed files with 54 additions and 9 deletions
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue