UNPKG

@nomiclabs/hardhat-ethers

Version:
107 lines (85 loc) 2.64 kB
/** * Returns a read-only proxy that just forwards everything to a target, * and a function that can be used to change that underlying target */ export function createUpdatableTargetProxy<T extends object>( initialTarget: T ): { proxy: T; setTarget: (target: T) => void; } { const targetObject = { target: initialTarget, }; let isExtensible = Object.isExtensible(initialTarget); const handler: Required<ProxyHandler<T>> = { // these two functions are implemented because of the Required<ProxyHandler> type apply(_, _thisArg, _argArray) { throw new Error( "cannot be implemented because the target is not a function" ); }, construct(_, _argArray, _newTarget) { throw new Error( "cannot be implemented because the target is not a function" ); }, defineProperty(_, property, _descriptor) { throw new Error( `cannot define property ${String(property)} in read-only proxy` ); }, deleteProperty(_, property) { throw new Error( `cannot delete property ${String(property)} in read-only proxy` ); }, get(_, property, receiver) { const result = Reflect.get(targetObject.target, property, receiver); if (result instanceof Function) { return result.bind(targetObject.target); } return result; }, getOwnPropertyDescriptor(_, property) { const descriptor = Reflect.getOwnPropertyDescriptor( targetObject.target, property ); if (descriptor !== undefined) { Object.defineProperty(targetObject.target, property, descriptor); } return descriptor; }, getPrototypeOf(_) { return Reflect.getPrototypeOf(targetObject.target); }, has(_, property) { return Reflect.has(targetObject.target, property); }, isExtensible(_) { // we need to return the extensibility value of the original target return isExtensible; }, ownKeys(_) { return Reflect.ownKeys(targetObject.target); }, preventExtensions(_) { isExtensible = false; return Reflect.preventExtensions(targetObject.target); }, set(_, property, _value, _receiver) { throw new Error( `cannot set property ${String(property)} in read-only proxy` ); }, setPrototypeOf(_, _prototype) { throw new Error("cannot change the prototype in read-only proxy"); }, }; const proxy: T = new Proxy(initialTarget, handler); const setTarget = (newTarget: T) => { targetObject.target = newTarget; }; return { proxy, setTarget }; }