From bacf9cf38388c32244768845b347dfb907dcd419 Mon Sep 17 00:00:00 2001 From: memdmp Date: Thu, 14 Aug 2025 14:29:38 +0200 Subject: feat: an implementation of OnceCell --- src/lib/vendor/once-cell/index.ts | 94 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/lib/vendor/once-cell/index.ts (limited to 'src/lib') diff --git a/src/lib/vendor/once-cell/index.ts b/src/lib/vendor/once-cell/index.ts new file mode 100644 index 0000000..5ae37f0 --- /dev/null +++ b/src/lib/vendor/once-cell/index.ts @@ -0,0 +1,94 @@ +export type Proxy = T; +export type OnceCell = Proxy; +export type OnceCellConstructor = Proxy<((create: () => T) => Proxy) & (new (create: () => T) => OnceCell) & { + dereference: (cell: OnceCell) => T +}>; +/** + * @license MIT + * @copyright memdmp + */ +export const OnceCell = new Proxy( + // We use the function keyword here to indicate that this *may* be a constructor + function (create: () => T): OnceCell { + if (typeof create !== 'function') throw new Error('Must pass function to OnceCell') + let createOnce = (): T extends object ? T : never => { + const t = create(); + return (createOnce = () => t as T extends object ? T : never)() + } + const onceCellProxyImplementation: ProxyHandler<{ + get value(): T + }> = { + get(_, idx, receiver) { + const target = createOnce(); + if (idx === '*internal.oncecelldereference') return target; + // .valueOf() and similar prototype methods should be proxied properly + if (!Object.hasOwnProperty.call(target, idx) && typeof target[idx as keyof T] === 'function') { + return (...args: unknown[]) => { + // @ts-expect-error we don't know .call's argument types, so we just hope and pray they're good and leave it to the caller to deal with it if it isn't + return target[idx as keyof T].call(target, args); + } + } + // return Reflect.get(obj, idx, receiver) + return target[idx as keyof T]; + }, + set(_, ...args) { + return Reflect.set(createOnce(), ...args) + }, + has(_, idx, ...args) { + if (idx === '*internal.oncecelldereference') return true // to comply with the OnceCell type declaration's meaning + return Reflect.has(createOnce(), idx, ...args) + }, + deleteProperty(_, ...args) { + return Reflect.deleteProperty(createOnce(), ...args) + }, + isExtensible(_, ...args) { + return Reflect.isExtensible(createOnce(), ...args) + }, + ownKeys(_, ...args) { + return Reflect.ownKeys(createOnce(), ...args) + }, + defineProperty(_, ...args) { + return Reflect.defineProperty(createOnce(), ...args) + }, + getOwnPropertyDescriptor(_, ...args) { + return Reflect.getOwnPropertyDescriptor(createOnce(), ...args) + }, + preventExtensions(_, ...args) { + return Reflect.preventExtensions(createOnce(), ...args) + }, + getPrototypeOf(_, ...args) { + return Reflect.getPrototypeOf(createOnce(), ...args) + }, + setPrototypeOf(_, ...args) { + return Reflect.setPrototypeOf(createOnce(), ...args) + }, + apply(_, ...args) { + type F = (this: any, ...args: any[]) => any + return Reflect.apply(createOnce() as unknown as T extends F ? F : never, ...args) + }, + construct(_, ...args) { + type F = (this: any, ...args: any[]) => any + return Reflect.construct(createOnce() as unknown as T extends F ? F : never, ...args) + }, + } + return new Proxy({ + /** For debuggers */ + get value() { + return createOnce() + } + }, onceCellProxyImplementation) as unknown as OnceCell + }, { + construct(onceCellCreationFunction, argArray, newTarget) { + return onceCellCreationFunction(argArray[0]) + }, +}) as OnceCellConstructor +OnceCell.dereference = (t) => Reflect.get(t as object, '*internal.oncecelldereference', t) +Object.freeze(OnceCell) +export default OnceCell -- cgit v1.2.3