GoonCord/src/lib/utils/lazy.ts

46 lines
1.7 KiB
TypeScript
Raw Normal View History

2024-05-21 16:04:56 +08:00
const factorySymbol = Symbol("lazyFactory");
const cacheSymbol = Symbol("lazyCache");
2024-05-20 20:57:48 +08:00
const unconfigurable = ["arguments", "caller", "prototype"];
const isUnconfigurable = (key: PropertyKey) => typeof key === "string" && unconfigurable.includes(key);
const lazyHandler: ProxyHandler<any> = {
ownKeys: target => {
2024-05-21 16:04:56 +08:00
const cacheKeys = Reflect.ownKeys(target[factorySymbol]());
2024-05-20 20:57:48 +08:00
unconfigurable.forEach(key => isUnconfigurable(key) && cacheKeys.push(key));
return cacheKeys;
},
getOwnPropertyDescriptor: (target, p) => {
if (isUnconfigurable(p)) return Reflect.getOwnPropertyDescriptor(target, p);
2024-05-21 16:04:56 +08:00
const descriptor = Reflect.getOwnPropertyDescriptor(target[factorySymbol](), p);
2024-05-20 20:57:48 +08:00
if (descriptor) Object.defineProperty(target, p, descriptor);
return descriptor;
2024-05-21 16:04:56 +08:00
}
2024-05-20 20:57:48 +08:00
};
2024-05-21 16:04:56 +08:00
// Mirror all Reflect methods
Object.getOwnPropertyNames(Reflect).forEach(fnName => {
// @ts-ignore
lazyHandler[fnName] ??= (target: any, ...args: any[]) => {
// @ts-ignore
return Reflect[fnName](target[factorySymbol](), ...args);
};
});
2024-05-20 20:57:48 +08:00
/**
* Lazy proxy that will only call the factory function when needed (when a property is accessed)
* @param factory Factory function to create the object
2024-05-21 16:04:56 +08:00
* @param fallback A fallback value to return if the factory returns undefined
2024-05-20 20:57:48 +08:00
* @returns A proxy that will call the factory function only when needed
2024-05-21 16:04:56 +08:00
* @example const ChannelStore = proxyLazy(() => findByProps("getChannelId"));
2024-05-20 20:57:48 +08:00
*/
2024-05-21 16:04:56 +08:00
export function proxyLazy<T>(factory: () => T, fallback?: any): T {
const dummy = function () { } as any;
dummy[factorySymbol] = () => {
return (dummy[cacheSymbol] ??= factory()) ?? fallback;
};
2024-05-20 20:57:48 +08:00
return new Proxy(dummy, lazyHandler) as any;
}