Skip to content

Instantly share code, notes, and snippets.

@xandris
Created December 19, 2015 04:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xandris/1309858ab93deb6ad0ab to your computer and use it in GitHub Desktop.
Save xandris/1309858ab93deb6ad0ab to your computer and use it in GitHub Desktop.
(function(){
'use strict';
let meta=new Map();
let queue=[];
let timeout;
let dispatching = false;
function observe(obj, key, watcher) {
let m=meta.get(obj);
if(!m) {
m={watches: {}};
meta.set(obj, m);
}
let w=m.watches[key];
if(!w) {
w={ val:obj[key], watchers: [] };
let fromProto = !obj.hasOwnProperty(key);
Object.defineProperty(obj, key, {
get() {
return fromProto ? Object.getPrototypeOf(obj)[key] : w.val;
},
set(val) {
fromProto = false;
let old = w.val;
w.val = val;
w.watchers = [...w.watchers, watcher];
queue.push([watchers, val, old, obj]);
scheduleDispatch();
}
});
}
return ()=>{
let idx=w.watchers.indexOf(watcher);
if(idx >= 0) {
w.watchers = [...w.watchers.slice(0, idx), ...w.watchers.slice(idx+1) ];
}
};
}
function scheduleDispatch() {
if(dispatching) {
return;
}
if(timeout) {
window.cancelTimeout(timeout);
}
timeout = window.setTimeout(dispatch, 0);
}
function dispatch() {
timeout = undefined;
dispatching = true;
try {
let q = queue;
queue = [];
for(let [watchers, cur, old, obj] of q) {
for(let w of watchers) {
w(cur, old, obj);
}
}
} finally {
dispatching = false;
}
}
return observe;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment