refactor: lazification
This commit is contained in:
parent
7e3c8b81d2
commit
035ee80045
5 changed files with 85 additions and 35 deletions
|
|
@ -1,10 +1,10 @@
|
|||
import { getFactoryOfProxy } from "@lib/utils/lazy";
|
||||
import { getProxyFactory } from "@lib/utils/lazy";
|
||||
import { findByPropsProxy } from "@metro/utils";
|
||||
|
||||
const jsxRuntime = findByPropsProxy("jsx", "jsxs", "Fragment");
|
||||
|
||||
function unproxyFirstArg<T>(args: T[]) {
|
||||
const factory = getFactoryOfProxy(args[0]);
|
||||
const factory = getProxyFactory(args[0]);
|
||||
if (factory) args[0] = factory();
|
||||
return args;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import * as plugins from "@lib/managers/plugins";
|
|||
import * as themes from "@lib/managers/themes";
|
||||
import { loaderConfig, settings } from "@lib/settings";
|
||||
import * as utils from "@lib/utils";
|
||||
import { logModule } from "@lib/utils/logger";
|
||||
import { DiscordLogger } from "@lib/utils/logger";
|
||||
import * as metro from "@metro";
|
||||
import * as common from "@metro/common";
|
||||
import { Forms } from "@metro/common/components";
|
||||
|
|
@ -32,7 +32,7 @@ export async function createVdPluginObject(plugin: plugins.BunnyPlugin) {
|
|||
// Wrapping this with wrapSync is NOT an option.
|
||||
storage: await createStorage<Record<string, any>>(storage.createMMKVBackend(plugin.id)),
|
||||
},
|
||||
logger: new logModule(`Bunny » ${plugin.manifest.name}`),
|
||||
logger: new DiscordLogger(`Bunny » ${plugin.manifest.name}`),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,34 +1,76 @@
|
|||
/* eslint-disable func-call-spacing */
|
||||
const unconfigurable = ["arguments", "caller", "prototype"];
|
||||
const isUnconfigurable = (key: PropertyKey) => typeof key === "string" && unconfigurable.includes(key);
|
||||
|
||||
const proxyToFactoryMap = new WeakMap<any, () => any>();
|
||||
const dummyToFactoryMap = new WeakMap<any, () => any>();
|
||||
interface IsolatedEntries {
|
||||
[keys: symbol | string]: any;
|
||||
}
|
||||
|
||||
interface LazyOptions {
|
||||
hint?: "function" | "object";
|
||||
isolatedEntries?: IsolatedEntries
|
||||
}
|
||||
|
||||
interface ContextHolder {
|
||||
options: LazyOptions;
|
||||
factory: any
|
||||
}
|
||||
|
||||
const unconfigurable = new Set(["arguments", "caller", "prototype"]);
|
||||
const isUnconfigurable = (key: PropertyKey) => typeof key === "string" && unconfigurable.has(key);
|
||||
|
||||
const factories = new WeakMap<any, () => any>();
|
||||
const proxyContextHolder = new WeakMap<any, ContextHolder>();
|
||||
|
||||
const lazyHandler: ProxyHandler<any> = {
|
||||
...Object.fromEntries(Object.getOwnPropertyNames(Reflect).map(fnName => {
|
||||
return [fnName, (target: any, ...args: any[]) => {
|
||||
const resolved = dummyToFactoryMap.get(target)!();
|
||||
if (!resolved) throw new Error(`Trying to ${fnName} of ${typeof resolved}`);
|
||||
const contextHolder = proxyContextHolder.get(target);
|
||||
const resolved = contextHolder?.factory();
|
||||
if (!resolved) throw new Error(`Trying to Reflect.${fnName} of ${typeof resolved}`);
|
||||
// @ts-expect-error
|
||||
return Reflect[fnName](resolved, ...args);
|
||||
}];
|
||||
})),
|
||||
ownKeys: target => {
|
||||
const resolved = dummyToFactoryMap.get(target)!();
|
||||
if (!resolved) throw new Error(`Trying to ownKeys of ${typeof resolved}`);
|
||||
has(target, p) {
|
||||
const contextHolder = proxyContextHolder.get(target);
|
||||
|
||||
const cacheKeys = Reflect.ownKeys(dummyToFactoryMap.get(target)!());
|
||||
if (contextHolder?.options) {
|
||||
const { isolatedEntries } = contextHolder.options;
|
||||
if (isolatedEntries && p in isolatedEntries) return true;
|
||||
}
|
||||
|
||||
const resolved = contextHolder?.factory();
|
||||
if (!resolved) throw new Error(`Trying to Reflect.has of ${typeof resolved}`);
|
||||
return Reflect.has(resolved, p);
|
||||
},
|
||||
get(target, p, receiver) {
|
||||
const contextHolder = proxyContextHolder.get(target);
|
||||
|
||||
if (contextHolder?.options) {
|
||||
const { isolatedEntries } = contextHolder.options;
|
||||
if (isolatedEntries?.[p]) return isolatedEntries[p];
|
||||
}
|
||||
|
||||
const resolved = contextHolder?.factory();
|
||||
if (!resolved) throw new Error(`Trying to Reflect.get of ${typeof resolved}`);
|
||||
return Reflect.get(resolved, p, receiver);
|
||||
},
|
||||
ownKeys: target => {
|
||||
const contextHolder = proxyContextHolder.get(target);
|
||||
const resolved = contextHolder?.factory();
|
||||
if (!resolved) throw new Error(`Trying to Reflect.ownKeys of ${typeof resolved}`);
|
||||
|
||||
const cacheKeys = Reflect.ownKeys(resolved);
|
||||
unconfigurable.forEach(key => !cacheKeys.includes(key) && cacheKeys.push(key));
|
||||
return cacheKeys;
|
||||
},
|
||||
getOwnPropertyDescriptor: (target, p) => {
|
||||
const resolved = dummyToFactoryMap.get(target)!();
|
||||
const contextHolder = proxyContextHolder.get(target);
|
||||
const resolved = contextHolder?.factory();
|
||||
if (!resolved) throw new Error(`Trying to getOwnPropertyDescriptor of ${typeof resolved}`);
|
||||
|
||||
if (isUnconfigurable(p)) return Reflect.getOwnPropertyDescriptor(target, p);
|
||||
|
||||
const descriptor = Reflect.getOwnPropertyDescriptor(dummyToFactoryMap.get(target)!(), p);
|
||||
const descriptor = Reflect.getOwnPropertyDescriptor(resolved, p);
|
||||
if (descriptor) Object.defineProperty(target, p, descriptor);
|
||||
return descriptor;
|
||||
},
|
||||
|
|
@ -41,15 +83,18 @@ const lazyHandler: ProxyHandler<any> = {
|
|||
* @returns A proxy that will call the factory function only when needed
|
||||
* @example const ChannelStore = proxyLazy(() => findByProps("getChannelId"));
|
||||
*/
|
||||
export function proxyLazy<T>(factory: () => T, asFunction = true): T {
|
||||
export function proxyLazy<T>(factory: () => T, opts: LazyOptions = {}): T {
|
||||
let cache: T;
|
||||
|
||||
const dummy = asFunction ? function () { } as any : {};
|
||||
const dummy = opts.hint !== "object" ? function () { } as any : {};
|
||||
const proxyFactory = () => cache ??= factory();
|
||||
|
||||
const proxy = new Proxy(dummy, lazyHandler) as T;
|
||||
proxyToFactoryMap.set(proxy, proxyFactory);
|
||||
dummyToFactoryMap.set(dummy, proxyFactory);
|
||||
factories.set(proxy, proxyFactory);
|
||||
proxyContextHolder.set(dummy, {
|
||||
factory,
|
||||
options: opts,
|
||||
});
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
|
@ -63,8 +108,8 @@ export function proxyLazy<T>(factory: () => T, asFunction = true): T {
|
|||
* const { uuid4 } = lazyDestructure(() => findByProps("uuid4"))
|
||||
* uuid4; // <- is a lazy proxy!
|
||||
*/
|
||||
export function lazyDestructure<T extends Record<PropertyKey, unknown>>(factory: () => T, asFunction = false): T {
|
||||
const proxiedObject = proxyLazy(factory, asFunction);
|
||||
export function lazyDestructure<T extends Record<PropertyKey, unknown>>(factory: () => T, opts: LazyOptions = {}): T {
|
||||
const proxiedObject = proxyLazy(factory);
|
||||
|
||||
return new Proxy({}, {
|
||||
get(_, property) {
|
||||
|
|
@ -72,16 +117,16 @@ export function lazyDestructure<T extends Record<PropertyKey, unknown>>(factory:
|
|||
return function* () {
|
||||
yield proxiedObject;
|
||||
yield new Proxy({}, {
|
||||
get: (_, p) => proxyLazy(() => proxiedObject[p])
|
||||
get: (_, p) => proxyLazy(() => proxiedObject[p], opts)
|
||||
});
|
||||
throw new Error("This is not a real iterator, this is likely used incorrectly");
|
||||
};
|
||||
}
|
||||
return proxyLazy(() => proxiedObject[property]);
|
||||
return proxyLazy(() => proxiedObject[property], opts);
|
||||
}
|
||||
}) as T;
|
||||
}
|
||||
|
||||
export function getFactoryOfProxy<T>(obj: T): (() => T) | void {
|
||||
return proxyToFactoryMap.get(obj) as (() => T) | void;
|
||||
export function getProxyFactory<T>(obj: T): (() => T) | void {
|
||||
return factories.get(obj) as (() => T) | void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@ export interface Logger {
|
|||
verbose: LoggerFunction;
|
||||
}
|
||||
|
||||
export const logModule = findByNameProxy("Logger");
|
||||
export const logger: Logger = new logModule("Bunny");
|
||||
export const DiscordLogger = findByNameProxy("Logger");
|
||||
export const logger: Logger = new DiscordLogger("Bunny");
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ import { findExports } from "./finders";
|
|||
import { metroModules, subscribeModule } from "./modules";
|
||||
import type { FilterFn } from "./types";
|
||||
|
||||
const proxyContextMap = new WeakMap<any, FindProxyContext<any[]>>();
|
||||
const moduleContextSymbol = Symbol.for("bunny.metro.modules");
|
||||
const proxyContexts = new WeakMap<any, ModuleProxyContext<any[]>>();
|
||||
|
||||
interface FindProxyContext<A extends unknown[]> {
|
||||
interface ModuleProxyContext<A extends unknown[]> {
|
||||
filter: FilterFn<A>;
|
||||
indexed: boolean;
|
||||
moduleId: number | undefined;
|
||||
|
|
@ -34,15 +35,15 @@ function subscribeModuleOfFind(proxy: any, callback: (exports: any) => void) {
|
|||
});
|
||||
}
|
||||
|
||||
export function getFindContext<A extends unknown[]>(proxy: any): FindProxyContext<A> | void {
|
||||
return proxyContextMap.get(proxy) as unknown as FindProxyContext<A>;
|
||||
export function getFindContext<A extends unknown[]>(proxy: any): ModuleProxyContext<A> | void {
|
||||
return proxyContexts.get(proxy) as unknown as ModuleProxyContext<A>;
|
||||
}
|
||||
|
||||
export function createFindProxy<A extends unknown[]>(filter: FilterFn<A>) {
|
||||
let cache: any = undefined;
|
||||
|
||||
const moduleId = getIndexedSingleFind(filter);
|
||||
const context: FindProxyContext<A> = {
|
||||
const context: ModuleProxyContext<A> = {
|
||||
filter,
|
||||
indexed: !!moduleId,
|
||||
moduleId,
|
||||
|
|
@ -65,8 +66,12 @@ export function createFindProxy<A extends unknown[]>(filter: FilterFn<A>) {
|
|||
}
|
||||
};
|
||||
|
||||
const proxy = proxyLazy(() => context.unproxy());
|
||||
proxyContextMap.set(proxy, context as FindProxyContext<any>);
|
||||
const proxy = proxyLazy(() => context.unproxy(), {
|
||||
isolatedEntries: {
|
||||
[moduleContextSymbol]: context
|
||||
}
|
||||
});
|
||||
proxyContexts.set(proxy, context as ModuleProxyContext<any>);
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue