refactor(metro): last one I promise
This commit is contained in:
parent
da76c66702
commit
d2341a3323
8 changed files with 70 additions and 62 deletions
|
|
@ -53,4 +53,4 @@ export function patchAssets(module: AssetModule) {
|
|||
export const find = (filter: (a: any) => void): Asset | null | undefined => Object.values(all).find(filter);
|
||||
export const getAssetByName = (name: string): Asset => all[name];
|
||||
export const getAssetByID = (id: number): Asset => assetsModule.getAssetByID(id);
|
||||
export const getAssetIDByName = (name: string) => all[name]?.id ?? requireModule(getMetroCache().assetsCache[name]);
|
||||
export const getAssetIDByName = (name: string) => all[name]?.id ?? requireModule(getMetroCache().assetsIndex[name]);
|
||||
|
|
|
|||
|
|
@ -3,38 +3,37 @@ import { throttle } from "@lib/utils/throttle";
|
|||
|
||||
import { getCachedPolyfillModules } from "./modules";
|
||||
|
||||
const BUNNY_METRO_CACHE_KEY = "__bunny_metro_cache_key_v5__";
|
||||
|
||||
type ModulesMap = {
|
||||
_?: 1;
|
||||
[id: number]: 1 | void;
|
||||
};
|
||||
|
||||
interface MetroCacheStore {
|
||||
v: 5;
|
||||
buildNumber: number;
|
||||
_v: 6;
|
||||
_buildNumber: number;
|
||||
findIndex: Record<string, ModulesMap | undefined>;
|
||||
polyfillCache: Record<string, ModulesMap | undefined>;
|
||||
assetsCache: Record<string, number>;
|
||||
polyfillIndex: Record<string, ModulesMap | undefined>;
|
||||
assetsIndex: Record<string, number>;
|
||||
}
|
||||
|
||||
let metroCache = null as unknown as MetroCacheStore;
|
||||
const BUNNY_METRO_CACHE_KEY = "__bunny_metro_cache_key_v5__";
|
||||
let _metroCache = null as unknown as MetroCacheStore;
|
||||
|
||||
export function getMetroCache() {
|
||||
return metroCache;
|
||||
return _metroCache;
|
||||
}
|
||||
|
||||
function buildInitCache() {
|
||||
metroCache = {
|
||||
v: 5,
|
||||
buildNumber: ClientInfoManager.Build,
|
||||
_metroCache = {
|
||||
_v: 6,
|
||||
_buildNumber: ClientInfoManager.Build,
|
||||
findIndex: {},
|
||||
polyfillCache: {},
|
||||
assetsCache: {}
|
||||
polyfillIndex: {},
|
||||
assetsIndex: {}
|
||||
} as const;
|
||||
|
||||
// Make sure all assets are cached. Delay by a second
|
||||
// because force loading all will results in an unexpected crash.
|
||||
// because force loading it all will results in an unexpected crash.
|
||||
setTimeout(() => {
|
||||
for (const id in window.modules) {
|
||||
require("@metro/modules").requireModule(id);
|
||||
|
|
@ -47,9 +46,9 @@ export async function initMetroCache() {
|
|||
if (rawCache == null) return void buildInitCache();
|
||||
|
||||
try {
|
||||
metroCache = JSON.parse(rawCache);
|
||||
if (metroCache.buildNumber !== ClientInfoManager.Build) {
|
||||
metroCache = null!;
|
||||
_metroCache = JSON.parse(rawCache);
|
||||
if (_metroCache._buildNumber !== ClientInfoManager.Build) {
|
||||
_metroCache = null!;
|
||||
throw "cache invalidated; version mismatch";
|
||||
}
|
||||
} catch {
|
||||
|
|
@ -57,10 +56,10 @@ export async function initMetroCache() {
|
|||
}
|
||||
}
|
||||
|
||||
const saveCache = throttle(() => MMKVManager.setItem(BUNNY_METRO_CACHE_KEY, JSON.stringify(metroCache)));
|
||||
const saveCache = throttle(() => MMKVManager.setItem(BUNNY_METRO_CACHE_KEY, JSON.stringify(_metroCache)));
|
||||
|
||||
export function getCacherForUniq(uniq: string, allFind: boolean) {
|
||||
const indexObject = metroCache.findIndex[uniq] ??= {};
|
||||
const indexObject = _metroCache.findIndex[uniq] ??= {};
|
||||
|
||||
return {
|
||||
cacheId(moduleId: number) {
|
||||
|
|
@ -75,7 +74,7 @@ export function getCacherForUniq(uniq: string, allFind: boolean) {
|
|||
}
|
||||
|
||||
export function getPolyfillModuleCacher(name: string) {
|
||||
const indexObject = metroCache.polyfillCache[name] ??= {};
|
||||
const indexObject = _metroCache.polyfillIndex[name] ??= {};
|
||||
|
||||
return {
|
||||
getModules() {
|
||||
|
|
@ -90,7 +89,7 @@ export function getPolyfillModuleCacher(name: string) {
|
|||
|
||||
export function registerAssetCacheId(name: string, moduleId: number) {
|
||||
if (!isNaN(moduleId)) {
|
||||
metroCache.assetsCache[name] = moduleId;
|
||||
_metroCache.assetsIndex[name] = moduleId;
|
||||
saveCache();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { findExports } from "@metro/finders";
|
||||
import { Dispatcher } from "@metro/types";
|
||||
import { createSimpleFilter, findByProps } from "@metro/utils";
|
||||
import { findByFilePath, findByProps } from "@metro/utils";
|
||||
|
||||
// Discord
|
||||
export const constants = findByProps("Fonts", "Permissions");
|
||||
|
|
@ -12,10 +11,7 @@ export const assets = findByProps("registerAsset");
|
|||
export const invites = findByProps("acceptInviteAndTransitionToInviteChannel");
|
||||
export const commands = findByProps("getBuiltInCommands");
|
||||
export const navigation = findByProps("pushLazy");
|
||||
export const toasts = findExports(createSimpleFilter(
|
||||
m => m.open && m.close && !m.startDrag && !m.init && !m.openReplay && !m.setAlwaysOnTop && !m.setAccountFlag,
|
||||
"bunny.metro.common.toasts"
|
||||
));
|
||||
export const toasts = findByFilePath("modules/toast/native/ToastActionCreators.tsx").default;
|
||||
export const messageUtil = findByProps("sendBotMessage");
|
||||
export const navigationStack = findByProps("createStackNavigator");
|
||||
export const NavigationNative = findByProps("NavigationContainer");
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export const byStoreName = createFilterDefinition<[string]>(
|
|||
);
|
||||
|
||||
export const byFilePath = createFilterDefinition<[string]>(
|
||||
([path], _, id) => metroModules[id]?.__filePath === path,
|
||||
([path], _, id, defaultCheck) => !defaultCheck && metroModules[id]?.__filePath === path,
|
||||
path => `bunny.metro.byFilePath(${path})`
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,21 @@
|
|||
import { getCacherForUniq } from "./caches";
|
||||
import { getModules, requireModule } from "./modules";
|
||||
import { FilterFn } from "./utils";
|
||||
import { FilterFn } from "./types";
|
||||
|
||||
function testExports<A extends unknown[]>(moduleExports: any, moduleId: number, filter: FilterFn<A>) {
|
||||
if (moduleExports.default && moduleExports.__esModule && filter(moduleExports.default, moduleId))
|
||||
if (moduleExports.default && moduleExports.__esModule && filter(moduleExports.default, moduleId, true)) {
|
||||
return [moduleExports.default, true];
|
||||
if (filter(moduleExports, moduleId))
|
||||
}
|
||||
|
||||
if (!filter.defaultFilter && filter(moduleExports, moduleId, false)) {
|
||||
return [moduleExports, false];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [id, defaultExports] of the first module where filter returns truthy, and undefined otherwise.
|
||||
* Returns the [id, defaultExports] of the first module where filter returns non-undefined, and undefined otherwise.
|
||||
* @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>) {
|
||||
|
|
@ -31,7 +34,7 @@ export function findModule<A extends unknown[]>(filter: FilterFn<A>) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the first module where filter returns truthy, and undefined otherwise.
|
||||
* Returns the id of the first module where filter returns non-undefined, and undefined otherwise.
|
||||
* @param filter find calls filter once for each enumerable module's exports until it finds one where filter returns a thruthy value.
|
||||
*/
|
||||
export function findModuleId<A extends unknown[]>(filter: FilterFn<A>) {
|
||||
|
|
@ -39,7 +42,7 @@ export function findModuleId<A extends unknown[]>(filter: FilterFn<A>) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the exports of the first module where filter returns truthy, and undefined otherwise.
|
||||
* Returns the exports of the first module where filter returns non-undefined, and undefined otherwise.
|
||||
* @param filter find calls filter once for each enumerable module's exports until it finds one where filter returns a thruthy value.
|
||||
*/
|
||||
export function findExports<A extends unknown[]>(filter: FilterFn<A>) {
|
||||
|
|
@ -49,7 +52,7 @@ export function findExports<A extends unknown[]>(filter: FilterFn<A>) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the [id, defaultExports] of all modules where filter returns truthy.
|
||||
* Returns the [id, defaultExports] of all modules where filter returns non-undefined.
|
||||
* @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>) {
|
||||
|
|
@ -69,7 +72,7 @@ export function findAllModule<A extends unknown[]>(filter: FilterFn<A>) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the ids of all modules where filter returns truthy.
|
||||
* Returns the ids of all modules where filter returns non-undefined.
|
||||
* @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 findAllModuleId<A extends unknown[]>(filter: FilterFn<A>) {
|
||||
|
|
@ -77,7 +80,7 @@ export function findAllModuleId<A extends unknown[]>(filter: FilterFn<A>) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the ids of all exports where filter returns truthy.
|
||||
* Returns the ids of all exports where filter returns non-undefined.
|
||||
* @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 findAllExports<A extends unknown[]>(filter: FilterFn<A>) {
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ export function* getModules(uniq: string, all = false) {
|
|||
}
|
||||
|
||||
export function* getCachedPolyfillModules(name: string) {
|
||||
const cache = getMetroCache().polyfillCache[name];
|
||||
const cache = getMetroCache().polyfillIndex[name];
|
||||
for (const id in cache ?? metroModules) {
|
||||
const exports = requireModule(id);
|
||||
if (isBadExports(exports)) continue;
|
||||
|
|
|
|||
|
|
@ -126,6 +126,29 @@ export namespace Metro {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
export type ModuleExports = any;
|
||||
export type FilterCheckDef<A extends unknown[]> = (
|
||||
args: A,
|
||||
module: any,
|
||||
modulesId: number,
|
||||
defaultCheck: boolean
|
||||
) => boolean;
|
||||
|
||||
export interface FilterFn<A extends unknown[]> {
|
||||
(m: any, id: number, defaultCheck: boolean): boolean;
|
||||
filter: FilterCheckDef<A>;
|
||||
args: A;
|
||||
defaultFilter: boolean;
|
||||
uniq: string;
|
||||
}
|
||||
|
||||
export interface FilterDefinition<A extends unknown[]> {
|
||||
(...args: A): FilterFn<A>;
|
||||
byDefault(...args: A): FilterFn<A>;
|
||||
uniqMaker(args: A): string;
|
||||
}
|
||||
|
||||
export interface Dispatcher {
|
||||
_actionHandlers: unknown;
|
||||
_interceptors?: ((payload: any) => void | boolean)[];
|
||||
|
|
|
|||
|
|
@ -1,43 +1,30 @@
|
|||
import { byDisplayName, byFilePath, byName, byProps, byStoreName, byTypeName } from "./filters";
|
||||
import { findAllExports, findExports } from "./finders";
|
||||
|
||||
type ModuleExports = any;
|
||||
type FilterCheckDef<A extends unknown[]> = (args: A, m: any, id: number) => boolean;
|
||||
|
||||
export interface FilterFn<A extends unknown[]> {
|
||||
(m: any, id: number): boolean;
|
||||
filter: FilterCheckDef<A>;
|
||||
args: A;
|
||||
isDefault: boolean;
|
||||
uniq: string;
|
||||
}
|
||||
|
||||
export interface FilterDefinition<A extends unknown[]> {
|
||||
(...args: A): FilterFn<A>;
|
||||
byDefault(...args: A): FilterFn<A>;
|
||||
uniqMaker(args: A): string;
|
||||
}
|
||||
import { FilterCheckDef, FilterDefinition, ModuleExports } from "./types";
|
||||
|
||||
export function createFilterDefinition<A extends unknown[]>(
|
||||
fn: FilterCheckDef<A>,
|
||||
uniqMaker: (args: A) => string
|
||||
): FilterDefinition<A> {
|
||||
function createHolder<T extends Function>(func: T, args: A, isDefault: boolean) {
|
||||
function createHolder<T extends Function>(func: T, args: A, defaultFilter: boolean) {
|
||||
return Object.assign(func, {
|
||||
filter: fn,
|
||||
args,
|
||||
isDefault,
|
||||
defaultFilter,
|
||||
uniq: [
|
||||
isDefault && "default::",
|
||||
defaultFilter && "default::",
|
||||
uniqMaker(args)
|
||||
].filter(Boolean).join("")
|
||||
});
|
||||
}
|
||||
|
||||
const curried = (...args: A) => createHolder((m: ModuleExports, id: number) => fn(args, m, id), args, false);
|
||||
const curried = (...args: A) => createHolder((m: ModuleExports, id: number, defaultCheck: boolean) => {
|
||||
return fn(args, m, id, defaultCheck);
|
||||
}, args, false);
|
||||
|
||||
const curriedDefault = (...args: A) => {
|
||||
function filter(m: ModuleExports, id: number) {
|
||||
return m.__esModule && m.default ? fn(args, m.default, id) : false;
|
||||
function filter(m: ModuleExports, id: number, defaultCheck: boolean) {
|
||||
return m.__esModule && m.default ? fn(args, m.default, id, defaultCheck) : false;
|
||||
}
|
||||
return createHolder(filter, args, true);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue