UNPKG

@pictogrammers/element

Version:

Web Component Element for TypeScript

113 lines 4.56 kB
export const addObserver = Symbol('addObserver'); export const removeObserver = Symbol('removeObserver'); export const hasObserver = Symbol('getObservers'); export const isProxy = Symbol('isProxy'); export const getTarget = Symbol('getTarget'); const arrayMutate = ['fill', 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift']; const arrayRead = ['forEach', 'slice', 'some', 'map', 'indexOf', 'lastIndexOf', 'width']; // key = obj, value = Map<ele, callback[]> const observers = new Map(); //@ts-ignore window.observers = observers; export function createProxy(obj) { return new Proxy(obj, { get(target, prop) { if (typeof prop === 'symbol') { switch (prop) { case isProxy: return true; case getTarget: return target; case hasObserver: return observers.has(obj); case addObserver: return (host, callback) => { if (observers.has(obj)) { if (observers.get(obj).has(host)) { observers.get(obj).get(host).push(callback); } else { observers.get(obj).set(host, [callback]); } } else { observers.set(obj, new Map([[host, [callback]]])); } }; case removeObserver: return (host) => { if (observers.has(obj)) { observers.get(obj).delete(host); if (observers.get(obj).size === 0) { observers.delete(obj); } } }; case Symbol.toPrimitive: case Symbol.toStringTag: return Reflect.get(target, prop); } throw new Error('Unsupported symbol'); } if (prop in target) { if (!Number.isNaN(Number(prop))) { if (typeof target[prop] === 'object') { return createProxy(target[prop]); } return target[prop]; } if (prop === 'copyWithin') { throw new Error('Unsupported array method copyWithin'); } if (arrayMutate.includes(prop)) { if (observers.has(target)) { return function () { const result = Array.prototype[prop].apply(target, arguments); const map = observers.get(target); map.forEach((callbacks, host) => { callbacks.forEach((callback) => { callback(target, prop, arguments); }); }); return result; }; } return Reflect.get(target, prop); } if (target[prop] instanceof Array) { return createProxy(target[prop]); } // nested objects do not get proxied for perf } return Reflect.get(target, prop); }, set(target, prop, value) { if (typeof prop === 'symbol') { throw new Error('Setting symbols not allowed.'); } if (Array.isArray(target)) { return Reflect.set(target, prop, value); } if (observers.has(target)) { const map = observers.get(target); map.forEach((callbacks, host) => { callbacks.forEach((callback) => { callback(prop, value); }); }); } return Reflect.set(target, prop, value); } }); } export const Mutation = { fill: 'fill', pop: 'pop', push: 'push', reverse: 'reverse', shift: 'shift', sort: 'sort', splice: 'splice', unshift: 'unshift' }; //# sourceMappingURL=proxy.js.map