const MszWatcher = function() { const handlers = []; const watch = (handler, ...args) => { if(typeof handler !== 'function') throw 'handler must be a function'; if(handlers.includes(handler)) throw 'handler already registered'; handlers.push(handler); args.push(true); handler(...args); }; const unwatch = handler => { $ari(handlers, handler); }; return { watch: watch, unwatch: unwatch, call: (...args) => { args.push(false); for(const handler of handlers) handler(...args); }, }; }; const MszWatcherCollection = function() { const watchers = new Map; const getWatcher = name => { const watcher = watchers.get(name); if(watcher === undefined) throw 'undefined watcher name'; return watcher; }; const watch = (name, handler, ...args) => { getWatcher(name).watch(handler, ...args); }; const unwatch = (name, handler) => { getWatcher(name).unwatch(handler); }; return { watch: watch, unwatch: unwatch, define: names => { if(typeof names === 'string') watchers.set(names, new MszWatcher); else if(Array.isArray(names)) for(const name of names) watchers.set(name, new MszWatcher); else throw 'names must be an array of names or a single name'; }, call: (name, ...args) => { getWatcher(name).call(...args); }, }; };