// eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck /* eslint-disable no-new,no-useless-call */ // mutableProxyFactory from https://stackoverflow.com/a/54460544 // (C) Alex Hall https://stackoverflow.com/users/2482744/alex-hall // License CC BY-SA 3.0 /* eslint-disable @typescript-eslint/ban-types */ export class PProxyHandler implements ProxyHandler { getPrototypeOf?(target: T): object | null { return Reflect.getPrototypeOf(target); } // eslint-disable-next-line @typescript-eslint/no-explicit-any setPrototypeOf?(target: T, v: any): boolean { return Reflect.setPrototypeOf(target, v); } isExtensible?(target: T): boolean { return Reflect.isExtensible(target); } preventExtensions?(target: T): boolean { return Reflect.preventExtensions(target); } getOwnPropertyDescriptor?( target: T, p: PropertyKey ): PropertyDescriptor | undefined { return Reflect.getOwnPropertyDescriptor(target, p); } has?(target: T, p: PropertyKey): boolean { return Reflect.has(target, p); } // eslint-disable-next-line @typescript-eslint/no-explicit-any get?(target: T, p: PropertyKey, receiver: any): any { return Reflect.get(target, p, receiver); } // eslint-disable-next-line @typescript-eslint/no-explicit-any set?(target: T, p: PropertyKey, value: any, receiver: any): boolean { return Reflect.set(target, p, value, receiver); } deleteProperty?(target: T, p: PropertyKey): boolean { return Reflect.deleteProperty(target, p); } defineProperty?( target: T, p: PropertyKey, attributes: PropertyDescriptor ): boolean { return Reflect.defineProperty(target, p, attributes); } enumerate?(target: T): PropertyKey[] { return Reflect.ownKeys(target); } ownKeys?(target: T): PropertyKey[] { return Reflect.ownKeys(target); } // eslint-disable-next-line @typescript-eslint/no-explicit-any apply?(target: T, thisArg: any, argArray?: any): any { return Reflect.apply(target as Function, thisArg, argArray); } // eslint-disable-next-line @typescript-eslint/no-explicit-any construct?(target: T, argArray: any, newTarget?: any): object { return Reflect.construct(target as Function, argArray, newTarget); } } interface MutableProxy { setTarget(target: T): void; setHandler(handler: PProxyHandler): void; getTarget(): T; getHandler(): ProxyHandler; proxy: T; } export function mutableProxyFactory( mutableTarget: T, mutableHandler?: ProxyHandler ): MutableProxy { if (!mutableHandler) mutableHandler = new PProxyHandler(); return { setTarget(target: T): void { new Proxy(target, {}); // test target validity mutableTarget = target; }, setHandler(handler: PProxyHandler): void { new Proxy({}, handler); // test handler validity Object.keys(handler).forEach((key) => { const value = handler[key]; if (Reflect[key] && typeof value !== "function") { throw new Error(`Trap "${key}: ${value}" is not a function`); } }); mutableHandler = handler; }, getTarget(): T { return mutableTarget; }, getHandler(): PProxyHandler { return mutableHandler; }, proxy: new Proxy( mutableTarget, new Proxy( {}, { // Dynamically forward all the traps to the associated methods on the mutable handler get(target, property) { return (_target, ...args) => mutableHandler[property].apply(mutableHandler, [ mutableTarget, ...args, ]); }, } ) ), }; }