{"version":3,"sources":["mongo/mongo_driver.js","mongo/oplog_tailing.js","mongo/observe_multiplex.js","mongo/doc_fetcher.js","mongo/polling_observe_driver.js","mongo/oplog_observe_driver.js","mongo/local_collection_driver.js","mongo/remote_collection_driver.js","mongo/collection.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,G;AACA,+D;AACA,qE;AACA,qB;AACA,E;AACA,uE;AACA,8C;AACA,G;;AAEA,+B;AACA,qC;AACA,kC;AACA,wD;;AAEA,oB;AACA,e;;AAEA,6B;AACA,Y;AACA,yD;AACA,mB;AACA,G;AACA,E;;AAEA,6C;AACA,0E;AACA,oB;AACA,0B;AACA,mC;;AAEA,8E;AACA,sE;AACA,6C;AACA,kC;AACA,2B;AACA,8D;AACA,K;AACA,iB;AACA,yC;AACA,qD;AACA,O;AACA,e;AACA,G;AACA,e;AACA,E;;AAEA,4E;AACA,6B;AACA,2E;AACA,iD;AACA,oC;AACA,c;AACA,E;;AAEA,gE;AACA,kE;;AAEA,sD;AACA,2C;AACA,sC;AACA,kC;AACA,G;AACA,6C;AACA,sD;AACA,G;AACA,uD;AACA,kC;AACA,yE;AACA,G;AACA,8C;AACA,gF;AACA,4E;AACA,gF;AACA,+C;AACA,oB;AACA,G;AACA,mB;AACA,E;;AAEA,sD;AACA,iC;AACA,qE;AACA,+E;AACA,+B;AACA,oD;AACA,G;AACA,2C;AACA,wD;AACA,G;AACA,8C;AACA,gF;AACA,4E;AACA,gF;AACA,+C;AACA,oB;AACA,G;AACA,sC;AACA,qE;AACA,G;AACA,uE;AACA,4E;AACA,mB;AACA,E;;AAEA,yD;AACA,wD;AACA,oB;;AAEA,uD;AACA,yC;AACA,gC;;AAEA,qB;AACA,wC;AACA,yD;AACA,8B;AACA,kC;AACA,2B;AACA,gC;AACA,6B;AACA,K;AACA,K;AACA,a;AACA,E;;;AAGA,2C;AACA,kB;AACA,0B;AACA,iC;AACA,kC;;AAEA,iE;;AAEA,qE;AACA,uE;AACA,sD;AACA,gD;AACA,8C;AACA,G;;AAEA,sE;AACA,sB;AACA,iE;AACA,oE;AACA,iB;AACA,wE;AACA,2C;AACA,kE;AACA,+C;AACA,0C;AACA,G;;AAEA,6E;AACA,4B;AACA,mC;AACA,6E;AACA,2E;AACA,oD;AACA,qD;AACA,G;;AAEA,iB;AACA,8E;AACA,yE;AACA,uD;AACA,uB;AACA,2B;AACA,0B;;;AAGA,iC;AACA,kB;AACA,Q;AACA,iB;AACA,2B;AACA,0B;AACA,kB;AACA,oB;AACA,S;;AAEA,iE;AACA,0C;AACA,6D;AACA,2B;AACA,iE;AACA,qC;AACA,kD;AACA,4C;AACA,+D;AACA,6B;AACA,8B;AACA,mB;AACA,e;AACA,kD;AACA,6E;AACA,8E;AACA,2E;AACA,6E;AACA,iE;AACA,mC;AACA,a;AACA,c;;AAEA,2C;AACA,oC;AACA,Q;AACA,8C;AACA,K;AACA,I;;AAEA,iE;AACA,iC;;AAEA,uD;AACA,gF;AACA,4C;AACA,G;AACA,E;;AAEA,8C;AACA,kB;;AAEA,gB;AACA,2D;;AAEA,0B;AACA,sC;AACA,2B;AACA,kB;AACA,uB;;AAEA,+D;AACA,8D;AACA,2B;AACA,2D;AACA,E;;AAEA,kD;AACA,qE;AACA,kB;;AAEA,gB;AACA,mE;;AAEA,0B;AACA,wD;AACA,uB;AACA,E;;AAEA,8D;AACA,6C;AACA,kB;;AAEA,gB;AACA,6E;;AAEA,4B;AACA,2B;AACA,mB;AACA,wD;AACA,uB;AACA,gB;AACA,E;;AAEA,gE;AACA,oE;AACA,kE;AACA,kE;AACA,gE;AACA,0D;AACA,kB;AACA,iD;AACA,Y;AACA,8B;AACA,M;AACA,uC;AACA,E;;AAEA,6E;AACA,kC;AACA,6D;AACA,iD;AACA,E;;;AAGA,kC;;AAEA,6E;AACA,8E;AACA,+E;AACA,4E;AACA,wB;AACA,E;AACA,oE;AACA,sE;AACA,mE;AACA,yE;AACA,4D;AACA,E;AACA,8D;AACA,mE;AACA,6D;;AAEA,yD;AACA,iC;AACA,gB;AACA,uD;AACA,gB;AACA,K;AACA,sB;AACA,iB;AACA,4B;AACA,iB;AACA,gB;AACA,I;AACA,E;;AAEA,mD;AACA,yD;AACA,E;;AAEA,wE;AACA,yD;AACA,kB;;AAEA,gC;AACA,iB;AACA,yB;AACA,Y;AACA,I;;AAEA,gE;AACA,sC;AACA,sB;AACA,iB;AACA,W;AACA,G;;AAEA,mD;AACA,0C;AACA,wB;AACA,0D;AACA,W;AACA,G;;AAEA,sC;AACA,6B;AACA,qE;AACA,I;AACA,8E;AACA,O;AACA,yD;AACA,yE;AACA,8C;AACA,e;AACA,sB;AACA,Y;AACA,G;AACA,E;;AAEA,2E;AACA,S;AACA,0E;AACA,kB;AACA,gD;AACA,2E;AACA,+E;AACA,8E;AACA,W;AACA,oE;AACA,oB;AACA,uC;AACA,qD;AACA,O;AACA,U;AACA,+B;AACA,G;AACA,E;;AAEA,wE;AACA,yD;AACA,kB;;AAEA,gE;AACA,sC;AACA,sB;AACA,iB;AACA,yB;AACA,Q;AACA,c;AACA,G;;AAEA,sC;AACA,6B;AACA,6C;AACA,I;AACA,8E;;AAEA,O;AACA,yD;AACA,yE;AACA,8C;AACA,e;AACA,sB;AACA,Y;AACA,G;AACA,E;;AAEA,2E;AACA,kB;;AAEA,sC;AACA,6B;AACA,yD;AACA,2C;AACA,I;AACA,kE;;AAEA,O;AACA,wD;AACA,wB;AACA,e;AACA,sB;AACA,Y;AACA,G;AACA,E;;AAEA,6E;AACA,kE;AACA,kB;;AAEA,kD;AACA,uB;AACA,mB;AACA,G;;AAEA,gE;AACA,sC;AACA,sB;AACA,iB;AACA,yB;AACA,Q;AACA,c;AACA,G;;AAEA,kE;AACA,gE;AACA,+D;AACA,uE;AACA,gB;AACA,sC;AACA,qE;;AAEA,8C;AACA,qC;AACA,oB;AACA,uD;AACA,iC;AACA,W;AACA,G;;AAEA,6B;;AAEA,sC;AACA,6B;AACA,6C;AACA,I;AACA,qD;AACA,O;AACA,yD;AACA,iC;AACA,0D;AACA,gD;AACA,8C;AACA,2E;AACA,6E;AACA,6B;AACA,wD;;AAEA,2E;AACA,iE;;AAEA,+C;AACA,0C;;AAEA,+C;AACA,yE;AACA,qB;AACA,2B;AACA,c;AACA,gB;AACA,O;AACA,K;;AAEA,8D;AACA,4E;AACA,uE;AACA,oE;AACA,+E;AACA,yC;AACA,Q;AACA,2E;AACA,+E;AACA,sE;AACA,Q;AACA,kC;AACA,+E;AACA,mC;AACA,4C;AACA,0B;AACA,uE;AACA,6E;AACA,mC;AACA,gC;AACA,gF;AACA,+E;AACA,4E;AACA,gD;AACA,iD;AACA,c;AACA,kC;AACA,S;AACA,Q;AACA,Y;AACA,wB;AACA,2C;AACA,+D;AACA,sB;AACA,kD;AACA,kD;AACA,8D;AACA,6D;AACA,wC;AACA,8C;AACA,0C;AACA,4C;AACA,a;AACA,W;AACA,gC;AACA,Y;AACA,K;AACA,e;AACA,sB;AACA,Y;AACA,G;AACA,E;;AAEA,wC;AACA,wB;AACA,uB;AACA,sB;AACA,iC;AACA,sB;AACA,Y;AACA,uB;AACA,K;AACA,G;AACA,8B;AACA,oB;AACA,6E;AACA,G;AACA,kB;AACA,E;;AAEA,6B;;AAEA,sB;AACA,yD;AACA,+E;AACA,+C;AACA,yB;AACA,gB;AACA,+D;AACA,gB;;AAEA,+E;AACA,gF;AACA,iE;AACA,+D;AACA,gB;;AAEA,e;AACA,E;;AAEA,uE;AACA,2E;AACA,4E;AACA,0E;AACA,0E;AACA,iE;AACA,wE;AACA,qE;AACA,2E;AACA,6E;AACA,uE;AACA,yE;AACA,qE;AACA,wE;AACA,gB;;AAEA,a;AACA,iE;AACA,8C;AACA,iB;AACA,mE;AACA,gE;AACA,gE;AACA,mD;AACA,uE;AACA,gE;AACA,yB;AACA,U;AACA,iB;AACA,G;;AAEA,oD;AACA,4B;AACA,e;AACA,wB;AACA,I;AACA,4B;AACA,e;AACA,gB;AACA,I;;AAEA,mC;;AAEA,8B;AACA,Y;AACA,kB;AACA,qF;AACA,Y;AACA,0D;AACA,wE;AACA,kC;AACA,0C;AACA,0C;AACA,4C;AACA,oD;AACA,+B;AACA,8B;AACA,kD;AACA,4B;AACA,K;AACA,I;;AAEA,yC;AACA,qC;AACA,kE;AACA,c;AACA,sE;AACA,sE;AACA,kC;AACA,oD;AACA,uE;AACA,wE;AACA,4E;AACA,uC;AACA,kC;AACA,0C;AACA,2B;AACA,gC;AACA,0C;AACA,mD;AACA,kD;AACA,6B;AACA,yB;AACA,0B;AACA,I;;AAEA,a;AACA,E;;AAEA,4E;AACA,kE;AACA,oB;AACA,uE;AACA,I;AACA,G;;AAEA,+E;AACA,6E;AACA,Q;AACA,2E;AACA,iE;AACA,kB;AACA,oD;AACA,uB;AACA,iB;AACA,G;;AAEA,mD;AACA,4C;AACA,oC;AACA,0C;AACA,mC;AACA,E;;AAEA,+E;AACA,kB;;AAEA,6B;AACA,kB;;AAEA,oB;AACA,oE;AACA,E;;AAEA,wE;AACA,wD;AACA,kB;AACA,6B;AACA,kB;;AAEA,0B;AACA,oB;AACA,kE;AACA,E;;AAEA,6E;AACA,oC;AACA,yE;AACA,6D;AACA,kB;AACA,4C;;AAEA,+E;AACA,+C;AACA,sD;AACA,0B;AACA,4E;AACA,gB;AACA,E;AACA,yE;AACA,kB;;AAEA,8E;AACA,mC;AACA,sD;AACA,0B;AACA,iE;AACA,gB;AACA,E;;AAEA,U;;AAEA,qD;AACA,E;AACA,yE;AACA,6E;AACA,6E;AACA,4E;AACA,mD;AACA,E;AACA,yD;AACA,6D;AACA,E;AACA,yE;AACA,8E;AACA,8E;AACA,gC;AACA,E;AACA,+E;AACA,sC;AACA,E;AACA,gF;AACA,yB;AACA,E;AACA,mE;AACA,4E;AACA,iB;AACA,6E;AACA,wB;AACA,+E;AACA,4E;AACA,8E;;AAEA,kE;AACA,kB;AACA,uC;AACA,8D;AACA,+B;AACA,E;;AAEA,8C;AACA,kB;;AAEA,sB;AACA,8C;AACA,iC;AACA,E;;AAEA,gE;AACA,0C;AACA,oB;;AAEA,8C;AACA,iD;AACA,yE;;AAEA,mC;AACA,qE;AACA,kC;AACA,+E;AACA,+C;AACA,iC;AACA,4B;AACA,W;AACA,K;;AAEA,iD;AACA,0C;AACA,I;AACA,G;;AAEA,2E;AACA,2E;AACA,uD;AACA,wB;AACA,uC;AACA,E;;AAEA,6C;AACA,mD;AACA,E;;AAEA,gF;AACA,+E;AACA,a;;AAEA,kD;AACA,kB;AACA,0D;AACA,gE;AACA,E;;AAEA,yE;AACA,wE;AACA,+C;AACA,mD;AACA,kB;AACA,gD;AACA,C;;AAEA,iD;AACA,kB;AACA,qE;AACA,E;;AAEA,wD;AACA,kB;AACA,8E;AACA,qC;AACA,iD;AACA,E;;AAEA,8D;AACA,iC;AACA,kB;AACA,sE;;AAEA,wE;AACA,gD;AACA,sB;AACA,6B;AACA,+B;AACA,4B;AACA,I;;AAEA,2E;AACA,+B;AACA,mC;AACA,iC;AACA,8E;AACA,+D;AACA,kC;AACA,gF;AACA,+B;AACA,sC;AACA,8E;AACA,gF;AACA,8E;AACA,8E;AACA,oC;AACA,gE;AACA,wC;AACA,sC;AACA,K;AACA,G;;AAEA,iC;AACA,yE;AACA,wC;;AAEA,qE;AACA,E;;AAEA,yE;AACA,kB;AACA,sE;;AAEA,4B;AACA,8C;AACA,0E;AACA,uE;AACA,4D;AACA,oE;AACA,oD;AACA,2C;AACA,U;AACA,2B;AACA,G;;AAEA,2E;AACA,wE;AACA,kE;AACA,4C;AACA,2C;AACA,sE;AACA,gD;AACA,E;;AAEA,uC;AACA,4B;AACA,oB;;AAEA,kB;AACA,qD;;AAEA,4B;AACA,0D;;AAEA,2E;AACA,2E;AACA,gF;AACA,+E;AACA,gF;AACA,gF;AACA,uE;AACA,oD;AACA,4C;AACA,O;;AAEA,0B;AACA,mC;;AAEA,iB;AACA,K;AACA,I;;AAEA,yC;AACA,oB;;AAEA,iC;AACA,mB;;AAEA,0E;AACA,8E;AACA,2D;AACA,kB;AACA,kB;AACA,mC;AACA,uB;AACA,mE;AACA,K;AACA,I;;AAEA,kE;AACA,qC;AACA,oB;AACA,iB;AACA,wC;AACA,2E;AACA,O;AACA,e;AACA,I;;AAEA,wB;AACA,oB;;AAEA,8B;AACA,4B;;AAEA,kD;AACA,I;;AAEA,wC;AACA,sB;AACA,oB;;AAEA,2B;AACA,I;;AAEA,sB;AACA,oB;AACA,gC;AACA,I;;AAEA,sB;AACA,oB;AACA,2C;AACA,I;;AAEA,0C;AACA,qC;AACA,oB;AACA,kB;AACA,0B;AACA,Y;AACA,+C;AACA,mC;AACA,kC;AACA,S;AACA,qB;AACA,K;AACA,G;AACA,G;;AAEA,4E;AACA,kB;AACA,0C;AACA,uD;;AAEA,gE;;AAEA,sB;AACA,yB;AACA,0B;AACA,kB;AACA,kB;AACA,e;AACA,W;AACA,uC;AACA,qB;AACA,0E;AACA,2E;AACA,oE;AACA,mB;AACA,O;AACA,6E;AACA,wD;AACA,kB;AACA,e;AACA,gB;AACA,6E;AACA,8E;AACA,+E;AACA,qD;AACA,wB;AACA,yB;AACA,c;AACA,8D;AACA,qB;AACA,yC;AACA,S;AACA,qE;AACA,2C;AACA,sB;AACA,sC;AACA,6E;AACA,yE;AACA,oB;AACA,qC;AACA,c;AACA,O;AACA,K;AACA,I;;AAEA,qB;;AAEA,U;AACA,uB;AACA,qB;AACA,qB;AACA,K;AACA,I;AACA,E;;AAEA,sD;AACA,4C;AACA,kB;;AAEA,2C;AACA,+E;AACA,G;;AAEA,gF;AACA,oC;AACA,yC;AACA,oD;AACA,yD;AACA,wE;AACA,G;;AAEA,kC;AACA,qD;;AAEA,iC;AACA,0B;;AAEA,gF;AACA,6E;AACA,2E;AACA,uC;AACA,uD;AACA,0D;AACA,Y;AACA,yB;AACA,yC;AACA,4C;AACA,yB;AACA,6B;AACA,uD;AACA,+B;AACA,S;AACA,S;AACA,0D;AACA,K;AACA,K;;AAEA,gE;;AAEA,oB;AACA,wB;AACA,6B;AACA,mB;AACA,8E;AACA,4E;AACA,6B;AACA,+C;AACA,2C;AACA,sB;AACA,+E;AACA,wE;AACA,a;AACA,sE;AACA,sB;AACA,qB;AACA,wE;AACA,iE;AACA,uB;AACA,S;AACA,sB;AACA,8D;AACA,8E;AACA,sB;AACA,4E;AACA,yB;AACA,4C;AACA,sB;AACA,a;AACA,uE;AACA,8D;AACA,sB;AACA,qB;AACA,wE;AACA,iE;AACA,uB;AACA,S;AACA,iE;;AAEA,8E;AACA,qC;AACA,2C;AACA,wB;AACA,+B;AACA,uB;AACA,8C;AACA,4C;AACA,4D;AACA,O;;AAEA,+C;AACA,+C;AACA,G;;AAEA,kD;AACA,yD;;AAEA,uB;AACA,E;;AAEA,wE;AACA,8E;AACA,0E;AACA,8E;AACA,kC;;AAEA,0D;AACA,qB;AACA,wD;AACA,0D;AACA,gC;AACA,K;;AAEA,U;AACA,uB;AACA,6C;AACA,wB;AACA,S;AACA,K;AACA,I;AACA,E;;AAEA,gE;AACA,2D;AACA,0D;AACA,gC;AACA,oB;AACA,uC;AACA,+C;AACA,O;AACA,qE;AACA,U;AACA,yB;AACA,G;AACA,E;;AAEA,6D;AACA,E;AACA,wC;AACA,8E;AACA,gF;AACA,U;AACA,8E;AACA,2E;AACA,kE;AACA,2E;AACA,yE;AACA,gF;AACA,4E;AACA,iD;AACA,yE;AACA,6E;AACA,wD;AACA,yC;AACA,gF;AACA,4E;AACA,8E;AACA,+E;AACA,gF;AACA,uE;AACA,2E;AACA,0E;AACA,8E;AACA,4B;AACA,8D;AACA,4C;AACA,kB;;AAEA,4E;AACA,sC;AACA,4C;AACA,uC;AACA,6E;AACA,mD;AACA,yE;AACA,G;;AAEA,sD;AACA,qB;AACA,mB;AACA,mD;AACA,kB;AACA,kB;AACA,2C;AACA,Y;AACA,+B;AACA,K;AACA,K;AACA,E;;AAEA,sE;AACA,6D;AACA,iD;AACA,kD;;AAEA,4C;;;;;;;;;;;;;;;;;;;AC9vCA,0C;;AAEA,8B;;AAEA,qE;;AAEA,+D;AACA,+D;AACA,iD;AACA,gC;AACA,gD;AACA,E;;AAEA,4B;AACA,wE;AACA,E;;AAEA,yB;AACA,oB;AACA,oB;AACA,yB;AACA,oB;AACA,yB;AACA,qB;AACA,yB;AACA,mE;AACA,qC;AACA,M;AACA,sD;AACA,E;;AAEA,2C;AACA,kB;AACA,4B;AACA,wB;;AAEA,wC;AACA,mC;AACA,wB;AACA,0B;AACA,mC;AACA,4C;AACA,6D;AACA,K;AACA,6B;AACA,0D;AACA,U;AACA,qC;AACA,qD;AACA,+C;AACA,I;;AAEA,2E;AACA,4E;AACA,yD;AACA,sE;AACA,I;AACA,2E;AACA,oE;AACA,4D;AACA,I;AACA,2E;AACA,gF;AACA,yE;AACA,6E;AACA,6E;AACA,0E;AACA,8D;AACA,I;AACA,2E;AACA,+B;AACA,+B;;AAEA,yC;AACA,qD;AACA,K;;AAEA,oD;AACA,6B;;AAEA,uB;AACA,E;;AAEA,iC;AACA,qB;AACA,oB;AACA,sB;AACA,a;AACA,yB;AACA,yB;AACA,8B;AACA,uC;AACA,I;AACA,8C;AACA,oB;AACA,sB;AACA,gE;;AAEA,4E;AACA,6B;;AAEA,oC;AACA,+D;AACA,gE;AACA,kD;AACA,uB;AACA,0D;AACA,O;AACA,gE;AACA,Y;AACA,yB;AACA,4B;AACA,O;AACA,M;AACA,I;AACA,0E;AACA,oC;AACA,yC;AACA,oB;AACA,sB;AACA,oE;AACA,yD;AACA,I;AACA,6E;AACA,uE;AACA,uB;AACA,4E;AACA,yB;AACA,kC;AACA,oB;AACA,sB;AACA,qE;;AAEA,gF;AACA,gB;AACA,6B;;AAEA,4B;AACA,2E;AACA,+E;AACA,gE;AACA,W;AACA,+D;AACA,oD;AACA,mD;AACA,c;AACA,mB;AACA,8E;AACA,+B;AACA,sE;AACA,gC;AACA,O;AACA,K;;AAEA,sB;AACA,a;;AAEA,qB;AACA,wE;AACA,a;AACA,K;;AAEA,0B;AACA,Y;AACA,2E;;AAEA,6E;AACA,yC;AACA,a;AACA,K;;;AAGA,+E;AACA,6E;AACA,kD;AACA,qD;AACA,8B;AACA,4E;AACA,oB;AACA,K;AACA,uB;AACA,wE;AACA,a;AACA,I;AACA,8B;AACA,oB;AACA,iE;AACA,gD;AACA,gE;AACA,8E;AACA,yC;AACA,K;;AAEA,uE;AACA,6E;AACA,0E;AACA,6E;AACA,sE;AACA,8E;AACA,gF;AACA,uB;AACA,M;AACA,8E;AACA,2D;AACA,oD;AACA,qC;AACA,0D;AACA,yE;AACA,8D;AACA,yD;AACA,qC;;AAEA,2E;AACA,wC;AACA,uB;AACA,sD;AACA,qC;AACA,+B;AACA,6E;AACA,8C;AACA,8E;AACA,yC;AACA,K;;AAEA,iC;AACA,gE;AACA,qE;;AAEA,yD;AACA,yB;AACA,0D;AACA,kD;AACA,2E;AACA,yE;AACA,8B;AACA,gD;AACA,K;;AAEA,kD;AACA,yD;;AAEA,sD;AACA,yC;AACA,mC;AACA,iC;AACA,O;AACA,M;AACA,+B;AACA,I;;AAEA,kC;AACA,oB;AACA,2B;AACA,a;AACA,8B;AACA,8B;AACA,W;AACA,iE;AACA,6E;AACA,wC;AACA,yD;AACA,mD;AACA,qC;;AAEA,iE;AACA,yB;AACA,0B;AACA,e;;AAEA,6E;AACA,mD;AACA,mD;AACA,qB;AACA,W;;AAEA,6C;;AAEA,oE;AACA,6D;AACA,wC;AACA,6C;AACA,W;;AAEA,4E;AACA,+C;AACA,kC;;AAEA,gF;AACA,yB;AACA,8C;AACA,4C;AACA,0C;AACA,8B;AACA,kB;AACA,wC;AACA,sC;AACA,W;;AAEA,uC;;AAEA,qE;AACA,wB;AACA,sB;AACA,2E;AACA,2C;AACA,S;AACA,iB;AACA,mC;AACA,O;AACA,O;AACA,I;AACA,sC;AACA,oB;AACA,+B;AACA,8C;AACA,4D;AACA,sC;AACA,sD;AACA,gC;AACA,K;AACA,G;AACA,G;;;;;;;;;;;;;;;;;;;ACjUA,0C;;AAEA,yC;AACA,kB;;AAEA,6C;AACA,0C;;AAEA,2D;AACA,iD;;AAEA,kC;AACA,kD;AACA,+C;AACA,qB;AACA,iC;AACA,4D;AACA,+B;AACA,sE;AACA,4E;AACA,c;AACA,mD;;AAEA,wD;AACA,+C;AACA,8D;AACA,M;AACA,K;AACA,E;;AAEA,wC;AACA,kD;AACA,oB;;AAEA,2E;AACA,qE;AACA,qE;AACA,uB;AACA,qC;AACA,sB;AACA,gF;AACA,mD;;AAEA,6D;AACA,8C;;AAEA,qC;AACA,yC;AACA,qE;AACA,+B;AACA,6B;AACA,qD;AACA,O;AACA,wD;AACA,6B;AACA,I;;AAEA,0E;AACA,yE;AACA,I;AACA,8E;AACA,8E;AACA,8D;AACA,+B;AACA,oB;;AAEA,4E;AACA,+E;AACA,0B;AACA,uB;AACA,2E;;AAEA,6B;;AAEA,6D;AACA,+C;;AAEA,mC;AACA,6D;AACA,mB;AACA,K;AACA,I;AACA,6B;AACA,oB;AACA,4B;;AAEA,yE;AACA,iD;AACA,oD;AACA,iD;;AAEA,4E;AACA,kE;AACA,mB;AACA,6D;AACA,oD;;AAEA,8E;AACA,4D;AACA,yB;AACA,I;;AAEA,+E;AACA,8C;AACA,sB;AACA,oB;AACA,uC;AACA,wB;AACA,gE;AACA,iC;AACA,O;AACA,I;;AAEA,2E;AACA,8E;AACA,gF;AACA,yE;AACA,2E;AACA,8C;AACA,8B;AACA,oB;AACA,qC;AACA,wB;AACA,uE;AACA,yC;AACA,mC;AACA,O;AACA,I;;AAEA,8E;AACA,8E;AACA,4E;AACA,0B;AACA,oB;AACA,uC;AACA,yB;AACA,6E;AACA,W;AACA,O;AACA,I;AACA,8B;AACA,oB;AACA,sB;AACA,kE;AACA,Q;AACA,6C;AACA,I;AACA,uB;AACA,0C;AACA,I;AACA,iD;AACA,oB;AACA,uC;AACA,mD;AACA,yB;AACA,e;;AAEA,8C;AACA,8E;AACA,2E;AACA,0E;AACA,gB;AACA,2E;;AAEA,gF;AACA,c;AACA,2B;AACA,yE;AACA,wE;AACA,O;;AAEA,2E;AACA,gF;AACA,gF;AACA,6E;AACA,wE;AACA,yD;AACA,8D;AACA,oB;AACA,iB;AACA,kD;AACA,uE;AACA,4D;AACA,S;AACA,O;AACA,I;;AAEA,gF;AACA,2E;AACA,gF;AACA,qE;AACA,gC;AACA,oB;AACA,oC;AACA,sE;AACA,kE;AACA,a;AACA,a;AACA,oD;AACA,iD;AACA,4C;AACA,uE;AACA,oC;AACA,wB;AACA,wB;AACA,qE;AACA,U;AACA,wB;AACA,O;AACA,G;AACA,G;;;AAGA,4B;AACA,mD;AACA,kB;AACA,wE;AACA,2C;AACA,kC;AACA,uD;AACA,0B;AACA,yC;AACA,2D;AACA,2E;AACA,6E;AACA,0E;AACA,gB;AACA,yD;AACA,oC;AACA,Q;AACA,K;AACA,K;AACA,wB;AACA,mC;AACA,E;AACA,4C;AACA,kB;AACA,oB;AACA,W;AACA,uB;AACA,2C;AACA,E;;;;;;;;;;;;;;;;;;;ACjPA,kC;AACA,0C;;AAEA,yC;AACA,kB;AACA,0C;AACA,qC;AACA,kC;AACA,E;;AAEA,gC;AACA,2E;AACA,W;AACA,I;AACA,6E;AACA,2E;AACA,kD;AACA,I;AACA,4E;AACA,iC;AACA,4D;AACA,oB;;AAEA,kC;AACA,gC;AACA,4B;;AAEA,8E;AACA,gD;AACA,sD;AACA,0D;AACA,a;AACA,K;;AAEA,sE;;AAEA,uB;AACA,W;AACA,gD;AACA,6C;AACA,yE;AACA,uD;AACA,uC;AACA,+E;AACA,yE;AACA,+E;AACA,kC;AACA,2C;AACA,2C;AACA,S;AACA,mB;AACA,uC;AACA,6B;AACA,S;AACA,iB;AACA,0E;AACA,kC;AACA,oD;AACA,O;AACA,a;AACA,G;AACA,G;;AAEA,kC;;;;;;;;;;;;;;;;;;;AC/DA,2C;AACA,kB;;AAEA,sD;AACA,0C;AACA,kC;AACA,0C;AACA,2B;AACA,wB;;AAEA,uE;AACA,6B;;AAEA,kE;AACA,kC;AACA,uB;;AAEA,+E;AACA,gF;AACA,6E;AACA,+E;AACA,0E;AACA,+E;AACA,iD;AACA,wC;AACA,sE;;AAEA,iE;AACA,iC;AACA,2C;AACA,yD;;AAEA,4C;AACA,mD;;AAEA,kC;AACA,sD;AACA,8E;AACA,8E;AACA,mE;AACA,qD;AACA,gB;AACA,qD;AACA,0E;AACA,6E;AACA,sD;AACA,kD;AACA,sC;AACA,K;AACA,I;AACA,oE;;AAEA,yE;AACA,sE;AACA,c;AACA,I;AACA,6E;AACA,+E;AACA,U;AACA,sC;AACA,+D;AACA,U;AACA,4C;AACA,4D;AACA,0C;AACA,2C;AACA,O;AACA,G;;AAEA,qC;AACA,2C;;AAEA,2D;AACA,oD;AACA,E;;AAEA,0C;AACA,uE;AACA,kD;AACA,oB;AACA,8C;AACA,a;AACA,wC;AACA,2C;AACA,wB;AACA,O;AACA,I;;AAEA,iD;AACA,I;AACA,+E;AACA,oE;AACA,2E;AACA,a;AACA,I;AACA,yE;AACA,+B;AACA,oB;AACA,sE;AACA,4D;AACA,wC;AACA,yE;AACA,2C;;AAEA,8E;AACA,uB;AACA,gD;AACA,0D;AACA,yD;AACA,I;AACA,8B;AACA,oB;AACA,uE;AACA,gD;AACA,0D;AACA,yD;AACA,0D;AACA,4D;AACA,yC;AACA,wB;AACA,O;AACA,I;;AAEA,2B;AACA,oB;AACA,wC;;AAEA,sB;AACA,a;;AAEA,sB;AACA,mC;AACA,sB;AACA,mB;AACA,2C;AACA,mE;AACA,K;;AAEA,+D;;AAEA,oE;AACA,6C;AACA,6B;;AAEA,gD;AACA,S;AACA,4E;AACA,iB;AACA,iD;AACA,2E;AACA,8E;AACA,gF;AACA,gF;AACA,yB;AACA,qC;AACA,oB;AACA,8C;AACA,2E;AACA,e;AACA,O;;AAEA,uE;AACA,8E;AACA,4D;AACA,+E;AACA,0E;AACA,2D;AACA,sE;AACA,sD;AACA,8E;AACA,a;AACA,K;;AAEA,iB;AACA,yB;AACA,wC;AACA,kE;AACA,K;;AAEA,gF;AACA,mE;AACA,4B;AACA,c;AACA,gC;;AAEA,gF;AACA,wE;AACA,+C;AACA,+B;;AAEA,8E;AACA,mE;AACA,yE;AACA,qD;AACA,2C;AACA,2C;AACA,sB;AACA,S;AACA,O;AACA,I;;AAEA,qB;AACA,oB;AACA,yB;AACA,uD;AACA,uD;AACA,8C;AACA,oB;AACA,O;AACA,6D;AACA,uD;AACA,G;AACA,G;;;;;;;;;;;;;;;;;;;ACpNA,kC;AACA,0C;;AAEA,a;AACA,uB;AACA,uB;AACA,kB;AACA,E;;AAEA,yE;AACA,6C;AACA,qC;AACA,4C;AACA,sB;AACA,S;AACA,+B;AACA,iB;AACA,0C;AACA,gB;AACA,K;AACA,I;AACA,E;;AAEA,6E;AACA,6E;AACA,uE;AACA,+E;AACA,mC;AACA,yC;AACA,kB;AACA,gD;;AAEA,sD;AACA,0C;AACA,0C;;AAEA,wB;AACA,6E;AACA,G;;AAEA,8B;AACA,8E;AACA,6C;AACA,oD;;AAEA,gD;AACA,8D;AACA,oC;AACA,2E;AACA,qD;AACA,6E;AACA,6E;AACA,+C;AACA,8D;;AAEA,wD;AACA,wD;AACA,kC;AACA,0B;AACA,sE;AACA,+E;AACA,2D;AACA,U;AACA,oB;AACA,4B;AACA,wB;AACA,mC;AACA,iD;AACA,G;;AAEA,8E;AACA,8E;AACA,mD;AACA,mC;;AAEA,wB;AACA,yB;;AAEA,2D;AACA,kD;;AAEA,4C;;AAEA,kD;AACA,kC;AACA,gE;AACA,sE;AACA,+E;AACA,+B;AACA,2E;AACA,a;AACA,kF;AACA,gE;AACA,4B;;AAEA,iD;AACA,iC;AACA,4B;;AAEA,yC;AACA,6C;;AAEA,8E;AACA,2B;AACA,yE;AACA,yC;AACA,8B;AACA,M;AACA,K;;AAEA,8D;AACA,uE;AACA,wC;AACA,qE;AACA,mC;AACA,4C;AACA,8E;AACA,gF;AACA,4B;AACA,oC;AACA,kB;AACA,uE;AACA,+C;AACA,iD;AACA,gB;AACA,yD;AACA,W;AACA,Y;AACA,O;AACA,O;AACA,K;;AAEA,yC;AACA,mC;AACA,sD;AACA,qE;AACA,qD;AACA,iB;AACA,e;AACA,qC;AACA,gF;AACA,0D;AACA,gC;AACA,2D;AACA,4B;AACA,uD;AACA,4B;AACA,kD;AACA,yE;AACA,+E;AACA,oB;AACA,iD;AACA,8B;AACA,a;AACA,gB;AACA,4D;AACA,S;AACA,S;AACA,K;AACA,K;;AAEA,gF;AACA,sC;AACA,+E;AACA,iB;AACA,8B;AACA,S;;AAEA,sE;AACA,uD;AACA,oD;AACA,4B;AACA,M;AACA,E;;AAEA,wC;AACA,qC;AACA,oB;AACA,yC;AACA,gC;AACA,wB;AACA,6D;AACA,8D;;AAEA,0E;AACA,yE;AACA,gF;AACA,+C;AACA,gE;AACA,sE;AACA,yD;AACA,yD;AACA,kE;AACA,gE;AACA,S;;AAEA,8D;AACA,mE;;AAEA,iD;AACA,sF;AACA,S;;AAEA,iD;AACA,oD;AACA,4D;AACA,O;AACA,O;AACA,I;AACA,mC;AACA,oB;AACA,yC;AACA,iC;AACA,oC;AACA,kE;AACA,e;;AAEA,+C;AACA,mD;;AAEA,+E;AACA,6E;;AAEA,6C;AACA,yE;AACA,sB;AACA,8D;AACA,2D;AACA,uC;AACA,6C;AACA,e;AACA,O;;AAEA,6E;;AAEA,gF;AACA,6E;AACA,6E;AACA,+E;AACA,+D;AACA,yC;AACA,e;;AAEA,oE;AACA,8E;AACA,gF;AACA,8E;AACA,mC;AACA,e;;AAEA,4E;AACA,wE;AACA,4E;AACA,8E;AACA,6E;AACA,gD;;AAEA,mD;AACA,O;AACA,I;AACA,mD;AACA,oB;AACA,yC;AACA,gE;AACA,oD;AACA,oD;AACA,uD;AACA,oC;AACA,8B;AACA,+C;AACA,O;AACA,I;AACA,oC;AACA,oB;AACA,yC;AACA,qE;;AAEA,6E;AACA,yD;AACA,mE;;AAEA,sD;;AAEA,iF;AACA,qC;AACA,yC;AACA,O;AACA,O;AACA,I;AACA,+E;AACA,mC;AACA,kC;AACA,oB;AACA,yC;AACA,yC;AACA,+E;AACA,6E;AACA,kD;AACA,yE;AACA,gC;AACA,O;AACA,I;AACA,kE;AACA,+E;AACA,sC;AACA,gC;AACA,oB;AACA,yC;AACA,uB;AACA,kC;AACA,sE;AACA,yD;AACA,8E;;AAEA,8B;AACA,wC;AACA,gE;AACA,mE;AACA,qE;AACA,6E;AACA,e;AACA,6E;AACA,8E;AACA,8C;AACA,kE;AACA,0C;;AAEA,8E;AACA,wE;AACA,wE;AACA,uE;AACA,+C;;AAEA,4E;AACA,iC;AACA,4D;AACA,0C;;AAEA,8D;;AAEA,sB;AACA,oC;AACA,4B;AACA,mC;AACA,c;AACA,kD;AACA,yC;AACA,O;AACA,O;AACA,I;AACA,8D;AACA,+E;AACA,sC;AACA,kC;AACA,oB;AACA,yC;AACA,qD;AACA,+E;;AAEA,oC;AACA,kC;AACA,mD;AACA,iC;AACA,O;AACA,O;AACA,I;AACA,qC;AACA,oB;AACA,yC;AACA,8E;;AAEA,oD;AACA,0E;AACA,2D;;AAEA,wC;AACA,kC;AACA,+C;AACA,iC;AACA,8C;AACA,6C;AACA,0C;AACA,0E;AACA,8E;;AAEA,8B;AACA,yE;AACA,2E;AACA,2E;AACA,qB;AACA,Y;AACA,6E;AACA,gF;AACA,8E;AACA,sC;AACA,iD;AACA,mD;AACA,iD;;AAEA,iC;AACA,sD;AACA,kB;AACA,4E;AACA,sC;AACA,0D;AACA,0D;AACA,sD;;AAEA,sD;AACA,wE;;AAEA,2B;AACA,4C;AACA,oB;AACA,8D;AACA,+C;AACA,a;AACA,W;AACA,oC;AACA,mD;AACA,gF;AACA,6E;AACA,0E;AACA,0B;AACA,6C;;AAEA,iD;AACA,4C;AACA,6D;AACA,4C;AACA,0D;;AAEA,qE;AACA,+D;;AAEA,qD;AACA,0E;AACA,6C;AACA,uD;;AAEA,0B;AACA,2C;AACA,qC;AACA,0C;AACA,oD;AACA,kB;AACA,4D;AACA,6C;AACA,8E;AACA,iE;AACA,mD;AACA,sC;AACA,a;AACA,W;AACA,gB;AACA,uG;AACA,S;AACA,O;AACA,O;AACA,I;AACA,wC;AACA,oB;AACA,yC;AACA,gD;AACA,8E;AACA,4B;AACA,wD;AACA,8D;AACA,+C;AACA,+E;AACA,4E;AACA,6E;AACA,kB;AACA,W;;AAEA,4D;AACA,6C;AACA,+E;;AAEA,sD;AACA,uD;AACA,yD;AACA,0B;AACA,+B;AACA,8E;AACA,6D;AACA,mE;AACA,sB;AACA,gD;AACA,mE;AACA,2D;AACA,qB;AACA,4B;AACA,8E;AACA,uC;AACA,uE;AACA,+E;AACA,+E;AACA,mD;AACA,yD;AACA,8C;AACA,qB;AACA,6E;AACA,2E;AACA,+E;AACA,0E;AACA,6E;AACA,kD;AACA,6C;AACA,mB;AACA,2B;AACA,4B;AACA,4E;AACA,4E;AACA,sC;AACA,oC;AACA,iC;AACA,iB;AACA,kB;AACA,a;AACA,qB;AACA,gF;AACA,6C;AACA,mB;AACA,yC;AACA,S;AACA,uE;AACA,sD;AACA,2C;AACA,2B;AACA,U;AACA,O;AACA,I;AACA,0B;AACA,oB;AACA,yC;AACA,8C;AACA,yD;AACA,iD;AACA,6C;AACA,qC;AACA,wB;AACA,W;AACA,S;AACA,O;AACA,I;AACA,4C;AACA,oB;AACA,yC;AACA,2D;AACA,O;AACA,I;AACA,oD;AACA,oB;AACA,yC;AACA,2B;AACA,4E;AACA,uD;AACA,2C;AACA,0E;AACA,wC;AACA,oD;AACA,e;AACA,O;;AAEA,0B;AACA,sC;AACA,6D;AACA,mC;AACA,iC;AACA,oC;AACA,+E;AACA,uE;AACA,4E;;AAEA,4E;AACA,sB;AACA,uD;AACA,kC;AACA,iC;AACA,4E;AACA,gF;AACA,4E;AACA,qB;AACA,uE;AACA,+E;AACA,0D;AACA,+E;AACA,iC;AACA,kC;AACA,2D;;AAEA,sD;AACA,4E;;AAEA,wB;AACA,yD;AACA,yD;AACA,0C;AACA,6E;AACA,2B;AACA,8C;AACA,wE;AACA,uC;;AAEA,0B;AACA,e;AACA,kD;AACA,uB;AACA,4C;AACA,sB;AACA,4D;AACA,wD;AACA,+C;AACA,6C;AACA,a;AACA,mB;AACA,W;AACA,gE;AACA,2C;AACA,iE;AACA,6E;AACA,sD;AACA,2C;AACA,2C;AACA,S;AACA,c;AACA,uD;AACA,O;AACA,O;AACA,I;AACA,Y;AACA,iC;AACA,oB;AACA,sB;AACA,0D;;AAEA,+C;;AAEA,sB;AACA,0C;;AAEA,2E;AACA,4B;AACA,8B;;AAEA,oC;AACA,I;;AAEA,gF;AACA,yE;AACA,I;AACA,0E;AACA,a;AACA,I;AACA,gF;AACA,W;AACA,I;AACA,4E;AACA,2E;AACA,qE;AACA,sE;AACA,qE;AACA,2B;AACA,oB;AACA,yC;AACA,wB;AACA,e;;AAEA,+E;AACA,qD;AACA,qC;AACA,+D;AACA,gD;;AAEA,6E;AACA,qE;AACA,gC;AACA,yB;AACA,6B;AACA,S;AACA,O;AACA,I;;AAEA,Y;AACA,iC;AACA,oB;AACA,4B;AACA,8B;;AAEA,iD;AACA,kB;AACA,uE;AACA,wB;AACA,e;;AAEA,8C;AACA,6C;;AAEA,gF;AACA,4E;AACA,qE;AACA,qB;AACA,gD;AACA,8E;AACA,kC;AACA,oE;AACA,W;AACA,qD;AACA,8C;AACA,yC;AACA,c;AACA,wC;AACA,W;AACA,c;AACA,mB;AACA,6D;AACA,6E;AACA,gF;AACA,2E;AACA,8E;AACA,sC;AACA,0C;AACA,iB;AACA,S;;AAEA,8E;AACA,+B;AACA,iE;AACA,gC;AACA,O;AACA,K;;AAEA,sB;AACA,a;;AAEA,mD;AACA,I;;AAEA,gF;AACA,4C;AACA,I;AACA,0E;AACA,8E;AACA,2D;AACA,8E;AACA,qE;AACA,I;AACA,gF;AACA,0D;AACA,wC;AACA,iC;AACA,oB;AACA,yC;AACA,wB;AACA,e;;AAEA,wE;AACA,qC;AACA,2C;AACA,0B;AACA,kC;AACA,O;;AAEA,8E;AACA,+B;AACA,4C;AACA,O;AACA,I;;AAEA,Y;AACA,8B;AACA,oB;;AAEA,sB;AACA,a;AACA,kE;AACA,sB;AACA,a;AACA,uC;AACA,uD;;AAEA,yC;AACA,2C;AACA,+C;AACA,0B;AACA,6C;AACA,yB;AACA,c;AACA,uC;AACA,O;AACA,O;AACA,I;;AAEA,gD;AACA,oB;AACA,gD;AACA,4E;AACA,gF;AACA,8E;AACA,8E;AACA,oE;AACA,6D;;AAEA,4E;AACA,+B;AACA,0C;;AAEA,8C;AACA,+B;AACA,6E;AACA,8C;AACA,+C;AACA,yC;AACA,iB;AACA,wD;AACA,O;AACA,I;;;AAGA,gF;AACA,kC;AACA,oD;AACA,I;AACA,+E;AACA,8E;AACA,4E;AACA,wD;AACA,oB;AACA,yC;;AAEA,+E;AACA,uB;AACA,wB;AACA,wC;AACA,O;;AAEA,oE;AACA,iD;AACA,2B;AACA,kD;AACA,gC;AACA,+B;AACA,S;AACA,yC;AACA,kC;AACA,S;;AAEA,iC;AACA,uE;AACA,2D;AACA,6C;AACA,iC;AACA,S;;AAEA,8E;AACA,e;AACA,6C;AACA,yD;AACA,oB;AACA,oE;AACA,6E;AACA,yC;AACA,+D;AACA,O;AACA,kD;AACA,gC;AACA,6E;AACA,S;;AAEA,oC;AACA,4C;AACA,mC;AACA,S;;AAEA,gE;AACA,O;AACA,I;;AAEA,gF;AACA,0E;AACA,W;AACA,I;AACA,6E;AACA,e;AACA,qB;AACA,oB;AACA,sB;AACA,a;AACA,yB;AACA,iD;AACA,oB;AACA,O;;AAEA,sE;AACA,yE;AACA,8E;AACA,yE;AACA,0B;AACA,gE;AACA,sC;AACA,O;AACA,iD;;AAEA,6D;AACA,2B;AACA,mC;AACA,6B;AACA,mC;AACA,kC;AACA,iC;;AAEA,6D;AACA,qD;AACA,I;;AAEA,0C;AACA,oB;AACA,yC;AACA,yB;;AAEA,wB;AACA,kD;AACA,iE;AACA,iF;AACA,O;;AAEA,0B;AACA,iC;AACA,O;AACA,G;AACA,G;;AAEA,8E;AACA,qE;AACA,+B;AACA,4E;AACA,8B;AACA,0C;;AAEA,oC;AACA,4B;AACA,iB;;AAEA,4E;AACA,+C;AACA,gF;AACA,0C;AACA,qE;;AAEA,uE;AACA,kD;AACA,uB;AACA,S;AACA,gE;AACA,iB;AACA,sC;AACA,qB;AACA,U;AACA,gB;AACA,K;AACA,G;;AAEA,4C;AACA,sE;AACA,0C;AACA,6E;AACA,4E;AACA,iC;AACA,6E;AACA,oE;AACA,uD;AACA,E;;AAEA,wD;AACA,uD;AACA,kD;AACA,oC;AACA,O;AACA,K;AACA,E;;AAEA,uD;;;;;;;;;;;;;;;;;;;ACt9BA,qC;AACA,kB;AACA,8B;AACA,E;;AAEA,qD;AACA,6B;AACA,kD;AACA,2B;AACA,E;;AAEA,2C;AACA,+B;AACA,oB;AACA,c;AACA,iC;AACA,iB;AACA,4D;AACA,K;AACA,2C;AACA,4C;AACA,6E;AACA,6C;AACA,oE;AACA,G;AACA,G;;AAEA,Y;AACA,kD;;;;;;;;;;;;;;;;;;;AC5BA,kD;AACA,uB;AACA,kB;AACA,uD;AACA,E;;AAEA,2D;AACA,yB;AACA,oB;AACA,iB;AACA,W;AACA,uD;AACA,yE;AACA,0C;AACA,oB;AACA,yD;AACA,S;AACA,e;AACA,G;AACA,G;;;AAGA,oE;AACA,qE;AACA,gE;AACA,mE;AACA,6B;;AAEA,uC;;AAEA,oC;AACA,6D;AACA,G;;AAEA,iB;AACA,4D;;AAEA,gF;AACA,G;;;;;;;;;;;;;;;;;;;ACtCA,sE;AACA,iE;;AAEA,G;AACA,+C;AACA,a;AACA,G;AACA,W;;AAEA,G;AACA,wC;AACA,kB;AACA,2B;AACA,S;AACA,qH;AACA,4B;AACA,oV;AACA,wI;;AAEA,iC;AACA,qE;;AAEA,kD;AACA,uX;AACA,G;AACA,6C;AACA,kB;AACA,2C;AACA,iE;;AAEA,iC;AACA,6E;AACA,6E;AACA,oE;AACA,gB;AACA,G;;AAEA,kD;AACA,oB;AACA,yE;AACA,G;;AAEA,mC;AACA,yE;AACA,sF;AACA,e;AACA,4B;AACA,oC;AACA,G;AACA,uE;AACA,0D;AACA,yC;AACA,G;AACA,sB;AACA,0B;AACA,2B;AACA,oB;AACA,uB;AACA,8B;AACA,c;;AAEA,iC;AACA,e;AACA,mC;AACA,wE;AACA,mD;AACA,M;AACA,U;AACA,gB;AACA,U;AACA,mC;AACA,wE;AACA,sB;AACA,M;AACA,U;AACA,G;;AAEA,qE;;AAEA,4C;AACA,yD;AACA,4B;AACA,8B;AACA,0C;AACA,2B;AACA,yC;AACA,M;AACA,qC;;AAEA,yB;AACA,6E;AACA,4E;AACA,mE;AACA,wB;AACA,qD;AACA,gD;AACA,uD;AACA,uE;AACA,Y;AACA,8C;AACA,K;AACA,G;;AAEA,kE;AACA,oB;AACA,iC;;AAEA,2D;AACA,6D;AACA,qE;AACA,oC;AACA,mD;AACA,+E;AACA,mC;AACA,Q;AACA,+E;AACA,wE;AACA,0E;AACA,0E;AACA,+E;AACA,6E;AACA,yC;AACA,gD;AACA,2E;AACA,0E;AACA,gF;AACA,gF;AACA,gB;AACA,mC;AACA,4C;;AAEA,kB;AACA,sC;AACA,Q;;AAEA,yB;AACA,4E;AACA,8B;AACA,uD;AACA,oD;;AAEA,+E;AACA,2E;AACA,sC;AACA,oC;AACA,oC;AACA,yB;AACA,oB;AACA,+C;AACA,4B;AACA,6C;AACA,kB;AACA,kD;AACA,sD;AACA,W;AACA,iB;AACA,yC;AACA,oB;AACA,0F;AACA,W;AACA,wE;AACA,2C;AACA,mB;AACA,uF;AACA,2C;AACA,2C;AACA,mB;AACA,qE;AACA,uC;AACA,8B;AACA,sD;AACA,wC;AACA,qC;AACA,uC;AACA,yC;AACA,sB;AACA,mC;AACA,qC;AACA,2C;AACA,e;AACA,e;AACA,uD;AACA,W;AACA,gB;AACA,wE;AACA,S;;AAEA,Q;;AAEA,iD;AACA,8B;AACA,2C;AACA,Q;;AAEA,+E;AACA,+B;AACA,kC;AACA,yC;AACA,Q;AACA,sC;AACA,oD;AACA,O;AACA,O;;AAEA,Y;AACA,4E;AACA,G;;AAEA,gC;;AAEA,gB;AACA,6E;AACA,oC;AACA,gD;AACA,yB;AACA,wB;AACA,G;AACA,E;;AAEA,G;AACA,uB;AACA,G;;;AAGA,sC;;AAEA,qC;AACA,yB;AACA,gB;AACA,Q;AACA,qB;AACA,I;;AAEA,oC;AACA,oB;AACA,0B;AACA,4C;AACA,Y;AACA,2D;AACA,+D;AACA,oE;AACA,8D;AACA,4D;AACA,U;;AAEA,uB;AACA,kC;AACA,kB;AACA,K;AACA,I;;AAEA,K;AACA,yE;AACA,oB;AACA,iB;AACA,+B;AACA,c;AACA,+E;AACA,8B;AACA,iF;AACA,4E;AACA,sE;AACA,2F;AACA,uG;AACA,4J;AACA,4B;AACA,K;AACA,4C;AACA,8D;AACA,8D;AACA,6C;AACA,oB;AACA,wC;AACA,iE;AACA,iE;AACA,I;;AAEA,K;AACA,sG;AACA,oB;AACA,oB;AACA,+B;AACA,c;AACA,+E;AACA,8B;AACA,iF;AACA,4E;AACA,2F;AACA,mG;AACA,2J;AACA,sB;AACA,K;AACA,+C;AACA,oB;AACA,wC;AACA,oE;AACA,oE;AACA,G;;AAEA,G;;AAEA,sE;AACA,6C;AACA,kC;AACA,wC;AACA,M;AACA,oC;AACA,0C;AACA,M;AACA,4B;AACA,kC;AACA,K;AACA,K;;AAEA,6E;AACA,kE;;AAEA,wD;AACA,kD;AACA,E;;AAEA,0E;AACA,+E;AACA,wE;AACA,sB;AACA,yD;AACA,mC;AACA,8C;AACA,+B;;AAEA,0D;AACA,2B;AACA,8B;;AAEA,e;AACA,0C;AACA,sE;AACA,kC;AACA,qD;AACA,yD;AACA,4D;AACA,iE;AACA,yC;AACA,uC;AACA,2C;AACA,K;AACA,sD;AACA,gD;AACA,4C;AACA,oD;AACA,S;AACA,Y;AACA,uB;AACA,K;AACA,K;AACA,a;AACA,E;;AAEA,qE;AACA,W;AACA,sD;AACA,uC;;AAEA,yC;AACA,wB;AACA,sE;AACA,oE;AACA,wB;AACA,wB;AACA,uB;AACA,wB;AACA,mB;AACA,qC;;AAEA,kB;AACA,E;;AAEA,8D;AACA,gE;AACA,2B;AACA,mE;AACA,6B;AACA,G;AACA,E;;AAEA,gE;AACA,0E;AACA,0E;AACA,gE;AACA,8E;AACA,iC;AACA,E;AACA,qE;AACA,6D;AACA,qE;AACA,oE;AACA,gF;AACA,gF;AACA,8E;AACA,gE;AACA,E;AACA,0D;AACA,6D;AACA,uB;AACA,E;AACA,gE;AACA,qE;AACA,iB;AACA,E;AACA,mE;AACA,oE;AACA,8D;AACA,kE;AACA,O;;AAEA,G;AACA,yE;AACA,kB;AACA,kB;AACA,6B;AACA,Y;AACA,iI;AACA,iJ;AACA,G;;AAEA,G;AACA,qG;AACA,kB;AACA,iB;AACA,6B;AACA,Y;AACA,sE;AACA,wE;AACA,4B;AACA,0I;AACA,gG;AACA,0K;AACA,G;;AAEA,G;AACA,gD;AACA,kB;AACA,iB;AACA,6B;AACA,Y;AACA,sE;AACA,mG;AACA,G;;AAEA,wD;AACA,iE;AACA,oB;AACA,oC;AACA,iB;AACA,iB;AACA,Y;;AAEA,8E;AACA,gD;AACA,sB;AACA,+C;AACA,sD;AACA,4B;AACA,K;;AAEA,4B;AACA,uB;AACA,uD;AACA,qD;AACA,sC;AACA,6B;AACA,+B;AACA,uD;AACA,qD;AACA,sG;AACA,c;AACA,8B;AACA,6E;AACA,4E;AACA,qC;AACA,qE;AACA,uD;AACA,2B;AACA,+B;AACA,W;AACA,S;AACA,yB;AACA,qD;AACA,S;AACA,O;AACA,Y;AACA,2D;;AAEA,8B;AACA,2E;AACA,+E;AACA,2E;AACA,wB;AACA,uD;AACA,yE;AACA,6E;AACA,mC;AACA,wD;AACA,mE;AACA,uE;AACA,qC;AACA,mD;AACA,W;AACA,S;AACA,O;AACA,K;;AAEA,uE;AACA,8D;AACA,mE;AACA,8B;AACA,kC;AACA,4B;AACA,S;AACA,wB;AACA,c;AACA,sB;AACA,O;AACA,M;;AAEA,wB;AACA,mB;AACA,kD;AACA,kF;AACA,Q;AACA,K;;AAEA,gC;AACA,iE;AACA,mE;AACA,mB;;AAEA,mD;AACA,oE;;AAEA,yE;AACA,sE;AACA,qE;AACA,kE;AACA,uE;AACA,gB;AACA,+E;AACA,+E;AACA,gC;AACA,0C;AACA,kB;AACA,0E;AACA,U;AACA,O;;AAEA,sD;AACA,8E;AACA,6E;AACA,4E;AACA,8C;AACA,O;;AAEA,kD;AACA,mG;AACA,Q;;AAEA,Y;AACA,gE;AACA,qC;AACA,iC;AACA,W;AACA,6E;AACA,6E;AACA,gE;AACA,4E;AACA,8D;AACA,mB;AACA,uB;AACA,sB;AACA,sB;AACA,S;AACA,gB;AACA,O;AACA,K;;AAEA,oE;AACA,+E;AACA,uD;AACA,e;AACA,I;AACA,G;;AAEA,G;AACA,4Q;AACA,kB;AACA,sE;AACA,wE;AACA,4B;AACA,0I;AACA,0K;AACA,G;AACA,iE;AACA,mE;AACA,kB;AACA,oD;AACA,uB;AACA,iB;AACA,G;AACA,wC;AACA,2E;AACA,wB;AACA,E;;AAEA,6E;AACA,oC;AACA,qE;AACA,kB;AACA,qC;AACA,wE;AACA,gD;AACA,E;AACA,0D;AACA,kB;AACA,mC;AACA,sE;AACA,qC;AACA,E;AACA,0D;AACA,kB;AACA,uC;AACA,2E;AACA,oC;AACA,E;AACA,wF;AACA,kB;AACA,gD;AACA,mF;AACA,mE;AACA,E;;AAEA,wD;AACA,kB;AACA,yC;AACA,yE;AACA,G;AACA,0C;AACA,E;;AAEA,sD;AACA,kB;AACA,wD;AACA,uE;AACA,G;AACA,+B;AACA,E;;;AAGA,G;AACA,qK;AACA,kB;AACA,S;AACA,uG;AACA,G;AACA,2C;;AAEA,G;AACA,0G;AACA,S;AACA,uB;AACA,G;AACA,sC;;AAEA,G;AACA,uB;AACA,G;AACA,uC;;AAEA,G;AACA,uB;AACA,G;AACA,2C;;AAEA,G;AACA,sC;AACA,G;;AAEA,uE;AACA,gB;AACA,E;AACA,yC;AACA,mD;AACA,E;AACA,4D;AACA,wD;AACA,qE;AACA,E;AACA,0C;AACA,uD;AACA,E;AACA,wB;AACA,uE;AACA,0D;AACA,E;AACA,kE;AACA,wB;AACA,qE;AACA,oE;AACA,uB;AACA,2E;AACA,6E;AACA,sC;AACA,E;AACA,8E;AACA,6E;AACA,mC;;AAEA,c;AACA,qD;AACA,oB;AACA,0E;AACA,4C;AACA,uC;AACA,+D;AACA,O;;AAEA,oB;AACA,4B;;AAEA,4D;AACA,0B;AACA,mD;AACA,yF;AACA,S;;AAEA,6E;AACA,uE;AACA,sB;AACA,8C;AACA,wE;AACA,gB;AACA,kE;AACA,+B;AACA,S;;AAEA,gE;AACA,O;AACA,O;;AAEA,sE;AACA,0E;AACA,6B;AACA,4D;AACA,+D;AACA,8E;AACA,O;AACA,uC;AACA,K;AACA,I;;AAEA,K;AACA,mH;AACA,kB;AACA,4B;AACA,2J;AACA,uL;AACA,4I;AACA,K;AACA,wD;AACA,8C;AACA,I;;AAEA,K;AACA,qC;AACA,kB;AACA,4B;AACA,0M;AACA,uL;AACA,4I;AACA,K;AACA,uD;AACA,6C;AACA,I;AACA,K;;;AAGA,gE;AACA,kB;;AAEA,qE;AACA,iE;AACA,2B;;AAEA,8E;AACA,4E;AACA,+E;AACA,uB;AACA,6B;;AAEA,sB;AACA,kC;AACA,kC;AACA,kC;AACA,oE;AACA,c;AACA,yB;AACA,I;;AAEA,kB;AACA,mC;;AAEA,gE;AACA,gC;AACA,wC;;AAEA,qB;AACA,yB;AACA,e;;AAEA,8D;AACA,uD;AACA,6E;AACA,sC;AACA,wC;AACA,a;AACA,6E;AACA,gF;AACA,+E;AACA,uE;AACA,2E;AACA,yE;AACA,Y;AACA,4E;AACA,yE;AACA,qE;AACA,qD;AACA,iC;AACA,8D;AACA,4C;AACA,W;;AAEA,kC;AACA,2E;AACA,iC;AACA,qC;AACA,wC;AACA,kD;AACA,sC;AACA,W;;AAEA,wE;;AAEA,kF;AACA,iC;AACA,kC;AACA,oD;;AAEA,iC;AACA,6D;AACA,8D;AACA,qC;AACA,8E;AACA,6D;AACA,a;;AAEA,qC;AACA,kF;AACA,sC;AACA,0D;AACA,+D;AACA,0C;AACA,qC;AACA,wC;AACA,6E;AACA,8E;AACA,+E;AACA,4E;AACA,2E;AACA,6E;AACA,uE;AACA,+E;AACA,+E;AACA,4E;AACA,+C;AACA,0E;AACA,kB;AACA,+E;AACA,4B;AACA,yD;AACA,W;AACA,qB;AACA,uE;AACA,sD;AACA,kB;AACA,oB;AACA,W;AACA,S;AACA,Q;AACA,O;AACA,iE;AACA,sD;AACA,oE;AACA,gC;AACA,8D;AACA,kC;AACA,G;AACA,E;;;AAGA,6D;AACA,kB;;AAEA,yC;AACA,iB;AACA,uE;AACA,Y;AACA,6C;AACA,oE;AACA,oC;AACA,K;AACA,G;AACA,E;;AAEA,sD;AACA,kB;AACA,mC;AACA,8B;AACA,wB;AACA,E;;AAEA,4D;AACA,gB;AACA,4B;AACA,2B;AACA,gF;AACA,2E;AACA,+E;AACA,mD;AACA,yD;AACA,+B;AACA,4B;AACA,K;AACA,mC;AACA,G;AACA,a;AACA,E;;AAEA,oE;AACA,uE;AACA,kB;;AAEA,0B;AACA,wC;AACA,+D;AACA,yE;AACA,O;AACA,iD;AACA,G;AACA,wE;AACA,gE;AACA,0E;AACA,O;AACA,iD;AACA,G;;AAEA,0E;AACA,+B;AACA,2B;AACA,0B;;AAEA,sD;AACA,E;;AAEA,8C;AACA,0B;AACA,oC;AACA,a;AACA,E;;AAEA,uE;AACA,mE;AACA,kE;AACA,2C;AACA,uD;AACA,yC;AACA,kB;;AAEA,yB;;AAEA,mC;;AAEA,8D;AACA,iE;;AAEA,2E;AACA,W;AACA,qB;AACA,+D;AACA,kE;;AAEA,iF;AACA,mF;AACA,qB;;AAEA,4B;AACA,kB;AACA,2B;AACA,gD;AACA,G;AACA,yC;AACA,+B;AACA,kD;AACA,uD;AACA,6B;AACA,2F;AACA,Y;AACA,+C;AACA,6D;AACA,yB;AACA,sC;AACA,yD;;AAEA,mD;AACA,uC;AACA,6B;AACA,S;AACA,K;AACA,K;;AAEA,sC;AACA,yC;AACA,4B;AACA,wD;AACA,wC;AACA,O;AACA,G;;AAEA,4D;AACA,+B;AACA,a;;AAEA,0B;AACA,wC;AACA,+D;AACA,oD;AACA,4B;AACA,kC;AACA,4B;AACA,8B;AACA,O;AACA,iD;AACA,G;AACA,wE;AACA,gE;AACA,oD;AACA,6B;AACA,mC;AACA,6B;AACA,+B;AACA,O;AACA,iD;AACA,G;;AAEA,gC;;AAEA,4E;AACA,6E;AACA,+E;AACA,4B;;AAEA,sC;AACA,kD;AACA,E;;AAEA,iE;AACA,8D;AACA,oE;AACA,8D;AACA,uE;AACA,6D;AACA,iC;AACA,qE;AACA,6B;AACA,E;;AAEA,sE;AACA,8B;AACA,0E;AACA,kB;;AAEA,sC;AACA,yC;AACA,4B;AACA,wD;AACA,wC;AACA,O;AACA,G;;AAEA,4D;AACA,W;AACA,a;;AAEA,0B;AACA,wC;AACA,+D;AACA,2D;AACA,O;AACA,iD;AACA,G;AACA,wE;AACA,gE;AACA,4D;AACA,O;AACA,iD;AACA,G;;AAEA,4E;AACA,gF;AACA,8E;AACA,sC;;AAEA,kE;AACA,E;;AAEA,G;AACA,uB;AACA,G;AACA,qC","file":"/packages/mongo.js","sourcesContent":["/**\n * Provide a synchronous Collection API using fibers, backed by\n * MongoDB.  This is only for use on the server, and mostly identical\n * to the client API.\n *\n * NOTE: the public API methods must be run within a fiber. If you call\n * these outside of a fiber they will explode!\n */\n\nvar path = Npm.require('path');\nvar MongoDB = Npm.require('mongodb');\nvar Fiber = Npm.require('fibers');\nvar Future = Npm.require(path.join('fibers', 'future'));\n\nMongoInternals = {};\nMongoTest = {};\n\nMongoInternals.NpmModules = {\n  mongodb: {\n    version: Npm.require('mongodb/package.json').version,\n    module: MongoDB\n  }\n};\n\n// Older version of what is now available via\n// MongoInternals.NpmModules.mongodb.module.  It was never documented, but\n// people do use it.\n// XXX COMPAT WITH 1.0.3.2\nMongoInternals.NpmModule = MongoDB;\n\n// This is used to add or remove EJSON from the beginning of everything nested\n// inside an EJSON custom type. It should only be called on pure JSON!\nvar replaceNames = function (filter, thing) {\n  if (typeof thing === \"object\") {\n    if (_.isArray(thing)) {\n      return _.map(thing, _.bind(replaceNames, null, filter));\n    }\n    var ret = {};\n    _.each(thing, function (value, key) {\n      ret[filter(key)] = replaceNames(filter, value);\n    });\n    return ret;\n  }\n  return thing;\n};\n\n// Ensure that EJSON.clone keeps a Timestamp as a Timestamp (instead of just\n// doing a structural clone).\n// XXX how ok is this? what if there are multiple copies of MongoDB loaded?\nMongoDB.Timestamp.prototype.clone = function () {\n  // Timestamps should be immutable.\n  return this;\n};\n\nvar makeMongoLegal = function (name) { return \"EJSON\" + name; };\nvar unmakeMongoLegal = function (name) { return name.substr(5); };\n\nvar replaceMongoAtomWithMeteor = function (document) {\n  if (document instanceof MongoDB.Binary) {\n    var buffer = document.value(true);\n    return new Uint8Array(buffer);\n  }\n  if (document instanceof MongoDB.ObjectID) {\n    return new Mongo.ObjectID(document.toHexString());\n  }\n  if (document[\"EJSON$type\"] && document[\"EJSON$value\"]\n      && _.size(document) === 2) {\n    return EJSON.fromJSONValue(replaceNames(unmakeMongoLegal, document));\n  }\n  if (document instanceof MongoDB.Timestamp) {\n    // For now, the Meteor representation of a Mongo timestamp type (not a date!\n    // this is a weird internal thing used in the oplog!) is the same as the\n    // Mongo representation. We need to do this explicitly or else we would do a\n    // structural clone and lose the prototype.\n    return document;\n  }\n  return undefined;\n};\n\nvar replaceMeteorAtomWithMongo = function (document) {\n  if (EJSON.isBinary(document)) {\n    // This does more copies than we'd like, but is necessary because\n    // MongoDB.BSON only looks like it takes a Uint8Array (and doesn't actually\n    // serialize it correctly).\n    return new MongoDB.Binary(new Buffer(document));\n  }\n  if (document instanceof Mongo.ObjectID) {\n    return new MongoDB.ObjectID(document.toHexString());\n  }\n  if (document instanceof MongoDB.Timestamp) {\n    // For now, the Meteor representation of a Mongo timestamp type (not a date!\n    // this is a weird internal thing used in the oplog!) is the same as the\n    // Mongo representation. We need to do this explicitly or else we would do a\n    // structural clone and lose the prototype.\n    return document;\n  }\n  if (EJSON._isCustomType(document)) {\n    return replaceNames(makeMongoLegal, EJSON.toJSONValue(document));\n  }\n  // It is not ordinarily possible to stick dollar-sign keys into mongo\n  // so we don't bother checking for things that need escaping at this time.\n  return undefined;\n};\n\nvar replaceTypes = function (document, atomTransformer) {\n  if (typeof document !== 'object' || document === null)\n    return document;\n\n  var replacedTopLevelAtom = atomTransformer(document);\n  if (replacedTopLevelAtom !== undefined)\n    return replacedTopLevelAtom;\n\n  var ret = document;\n  _.each(document, function (val, key) {\n    var valReplaced = replaceTypes(val, atomTransformer);\n    if (val !== valReplaced) {\n      // Lazy clone. Shallow copy.\n      if (ret === document)\n        ret = _.clone(document);\n      ret[key] = valReplaced;\n    }\n  });\n  return ret;\n};\n\n\nMongoConnection = function (url, options) {\n  var self = this;\n  options = options || {};\n  self._observeMultiplexers = {};\n  self._onFailoverHook = new Hook;\n\n  var mongoOptions = {db: {safe: true}, server: {}, replSet: {}};\n\n  // Set autoReconnect to true, unless passed on the URL. Why someone\n  // would want to set autoReconnect to false, I'm not really sure, but\n  // keeping this for backwards compatibility for now.\n  if (!(/[\\?&]auto_?[rR]econnect=/.test(url))) {\n    mongoOptions.server.auto_reconnect = true;\n  }\n\n  // Disable the native parser by default, unless specifically enabled\n  // in the mongo URL.\n  // - The native driver can cause errors which normally would be\n  //   thrown, caught, and handled into segfaults that take down the\n  //   whole app.\n  // - Binary modules don't yet work when you bundle and move the bundle\n  //   to a different platform (aka deploy)\n  // We should revisit this after binary npm module support lands.\n  if (!(/[\\?&]native_?[pP]arser=/.test(url))) {\n    mongoOptions.db.native_parser = false;\n  }\n\n  // XXX maybe we should have a better way of allowing users to configure the\n  // underlying Mongo driver\n  if (_.has(options, 'poolSize')) {\n    // If we just set this for \"server\", replSet will override it. If we just\n    // set it for replSet, it will be ignored if we're not using a replSet.\n    mongoOptions.server.poolSize = options.poolSize;\n    mongoOptions.replSet.poolSize = options.poolSize;\n  }\n\n  self.db = null;\n  // We keep track of the ReplSet's primary, so that we can trigger hooks when\n  // it changes.  The Node driver's joined callback seems to fire way too\n  // often, which is why we need to track it ourselves.\n  self._primary = null;\n  self._oplogHandle = null;\n  self._docFetcher = null;\n\n\n  var connectFuture = new Future;\n  MongoDB.connect(\n    url,\n    mongoOptions,\n    Meteor.bindEnvironment(\n      function (err, db) {\n        if (err) {\n          throw err;\n        }\n\n        // First, figure out what the current primary is, if any.\n        if (db.serverConfig._state.master)\n          self._primary = db.serverConfig._state.master.name;\n        db.serverConfig.on(\n          'joined', Meteor.bindEnvironment(function (kind, doc) {\n            if (kind === 'primary') {\n              if (doc.primary !== self._primary) {\n                self._primary = doc.primary;\n                self._onFailoverHook.each(function (callback) {\n                  callback();\n                  return true;\n                });\n              }\n            } else if (doc.me === self._primary) {\n              // The thing we thought was primary is now something other than\n              // primary.  Forget that we thought it was primary.  (This means\n              // that if a server stops being primary and then starts being\n              // primary again without another server becoming primary in the\n              // middle, we'll correctly count it as a failover.)\n              self._primary = null;\n            }\n          }));\n\n        // Allow the constructor to return.\n        connectFuture['return'](db);\n      },\n      connectFuture.resolver()  // onException\n    )\n  );\n\n  // Wait for the connection to be successful; throws on failure.\n  self.db = connectFuture.wait();\n\n  if (options.oplogUrl && ! Package['disable-oplog']) {\n    self._oplogHandle = new OplogHandle(options.oplogUrl, self.db.databaseName);\n    self._docFetcher = new DocFetcher(self);\n  }\n};\n\nMongoConnection.prototype.close = function() {\n  var self = this;\n\n  if (! self.db)\n    throw Error(\"close called before Connection created?\");\n\n  // XXX probably untested\n  var oplogHandle = self._oplogHandle;\n  self._oplogHandle = null;\n  if (oplogHandle)\n    oplogHandle.stop();\n\n  // Use Future.wrap so that errors get thrown. This happens to\n  // work even outside a fiber since the 'close' method is not\n  // actually asynchronous.\n  Future.wrap(_.bind(self.db.close, self.db))(true).wait();\n};\n\n// Returns the Mongo Collection object; may yield.\nMongoConnection.prototype.rawCollection = function (collectionName) {\n  var self = this;\n\n  if (! self.db)\n    throw Error(\"rawCollection called before Connection created?\");\n\n  var future = new Future;\n  self.db.collection(collectionName, future.resolver());\n  return future.wait();\n};\n\nMongoConnection.prototype._createCappedCollection = function (\n    collectionName, byteSize, maxDocuments) {\n  var self = this;\n\n  if (! self.db)\n    throw Error(\"_createCappedCollection called before Connection created?\");\n\n  var future = new Future();\n  self.db.createCollection(\n    collectionName,\n    { capped: true, size: byteSize, max: maxDocuments },\n    future.resolver());\n  future.wait();\n};\n\n// This should be called synchronously with a write, to create a\n// transaction on the current write fence, if any. After we can read\n// the write, and after observers have been notified (or at least,\n// after the observer notifiers have added themselves to the write\n// fence), you should call 'committed()' on the object returned.\nMongoConnection.prototype._maybeBeginWrite = function () {\n  var self = this;\n  var fence = DDPServer._CurrentWriteFence.get();\n  if (fence)\n    return fence.beginWrite();\n  else\n    return {committed: function () {}};\n};\n\n// Internal interface: adds a callback which is called when the Mongo primary\n// changes. Returns a stop handle.\nMongoConnection.prototype._onFailover = function (callback) {\n  return this._onFailoverHook.register(callback);\n};\n\n\n//////////// Public API //////////\n\n// The write methods block until the database has confirmed the write (it may\n// not be replicated or stable on disk, but one server has confirmed it) if no\n// callback is provided. If a callback is provided, then they call the callback\n// when the write is confirmed. They return nothing on success, and raise an\n// exception on failure.\n//\n// After making a write (with insert, update, remove), observers are\n// notified asynchronously. If you want to receive a callback once all\n// of the observer notifications have landed for your write, do the\n// writes inside a write fence (set DDPServer._CurrentWriteFence to a new\n// _WriteFence, and then set a callback on the write fence.)\n//\n// Since our execution environment is single-threaded, this is\n// well-defined -- a write \"has been made\" if it's returned, and an\n// observer \"has been notified\" if its callback has returned.\n\nvar writeCallback = function (write, refresh, callback) {\n  return function (err, result) {\n    if (! err) {\n      // XXX We don't have to run this on error, right?\n      refresh();\n    }\n    write.committed();\n    if (callback)\n      callback(err, result);\n    else if (err)\n      throw err;\n  };\n};\n\nvar bindEnvironmentForWrite = function (callback) {\n  return Meteor.bindEnvironment(callback, \"Mongo write\");\n};\n\nMongoConnection.prototype._insert = function (collection_name, document,\n                                              callback) {\n  var self = this;\n\n  var sendError = function (e) {\n    if (callback)\n      return callback(e);\n    throw e;\n  };\n\n  if (collection_name === \"___meteor_failure_test_collection\") {\n    var e = new Error(\"Failure test\");\n    e.expected = true;\n    sendError(e);\n    return;\n  }\n\n  if (!(LocalCollection._isPlainObject(document) &&\n        !EJSON._isCustomType(document))) {\n    sendError(new Error(\n      \"Only plain objects may be inserted into MongoDB\"));\n    return;\n  }\n\n  var write = self._maybeBeginWrite();\n  var refresh = function () {\n    Meteor.refresh({collection: collection_name, id: document._id });\n  };\n  callback = bindEnvironmentForWrite(writeCallback(write, refresh, callback));\n  try {\n    var collection = self.rawCollection(collection_name);\n    collection.insert(replaceTypes(document, replaceMeteorAtomWithMongo),\n                      {safe: true}, callback);\n  } catch (e) {\n    write.committed();\n    throw e;\n  }\n};\n\n// Cause queries that may be affected by the selector to poll in this write\n// fence.\nMongoConnection.prototype._refresh = function (collectionName, selector) {\n  var self = this;\n  var refreshKey = {collection: collectionName};\n  // If we know which documents we're removing, don't poll queries that are\n  // specific to other documents. (Note that multiple notifications here should\n  // not cause multiple polls, since all our listener is doing is enqueueing a\n  // poll.)\n  var specificIds = LocalCollection._idsMatchedBySelector(selector);\n  if (specificIds) {\n    _.each(specificIds, function (id) {\n      Meteor.refresh(_.extend({id: id}, refreshKey));\n    });\n  } else {\n    Meteor.refresh(refreshKey);\n  }\n};\n\nMongoConnection.prototype._remove = function (collection_name, selector,\n                                              callback) {\n  var self = this;\n\n  if (collection_name === \"___meteor_failure_test_collection\") {\n    var e = new Error(\"Failure test\");\n    e.expected = true;\n    if (callback)\n      return callback(e);\n    else\n      throw e;\n  }\n\n  var write = self._maybeBeginWrite();\n  var refresh = function () {\n    self._refresh(collection_name, selector);\n  };\n  callback = bindEnvironmentForWrite(writeCallback(write, refresh, callback));\n\n  try {\n    var collection = self.rawCollection(collection_name);\n    collection.remove(replaceTypes(selector, replaceMeteorAtomWithMongo),\n                      {safe: true}, callback);\n  } catch (e) {\n    write.committed();\n    throw e;\n  }\n};\n\nMongoConnection.prototype._dropCollection = function (collectionName, cb) {\n  var self = this;\n\n  var write = self._maybeBeginWrite();\n  var refresh = function () {\n    Meteor.refresh({collection: collectionName, id: null,\n                    dropCollection: true});\n  };\n  cb = bindEnvironmentForWrite(writeCallback(write, refresh, cb));\n\n  try {\n    var collection = self.rawCollection(collectionName);\n    collection.drop(cb);\n  } catch (e) {\n    write.committed();\n    throw e;\n  }\n};\n\nMongoConnection.prototype._update = function (collection_name, selector, mod,\n                                              options, callback) {\n  var self = this;\n\n  if (! callback && options instanceof Function) {\n    callback = options;\n    options = null;\n  }\n\n  if (collection_name === \"___meteor_failure_test_collection\") {\n    var e = new Error(\"Failure test\");\n    e.expected = true;\n    if (callback)\n      return callback(e);\n    else\n      throw e;\n  }\n\n  // explicit safety check. null and undefined can crash the mongo\n  // driver. Although the node driver and minimongo do 'support'\n  // non-object modifier in that they don't crash, they are not\n  // meaningful operations and do not do anything. Defensively throw an\n  // error here.\n  if (!mod || typeof mod !== 'object')\n    throw new Error(\"Invalid modifier. Modifier must be an object.\");\n\n  if (!(LocalCollection._isPlainObject(mod) &&\n        !EJSON._isCustomType(mod))) {\n    throw new Error(\n      \"Only plain objects may be used as replacement\" +\n        \" documents in MongoDB\");\n    return;\n  }\n\n  if (!options) options = {};\n\n  var write = self._maybeBeginWrite();\n  var refresh = function () {\n    self._refresh(collection_name, selector);\n  };\n  callback = writeCallback(write, refresh, callback);\n  try {\n    var collection = self.rawCollection(collection_name);\n    var mongoOpts = {safe: true};\n    // explictly enumerate options that minimongo supports\n    if (options.upsert) mongoOpts.upsert = true;\n    if (options.multi) mongoOpts.multi = true;\n    // Lets you get a more more full result from MongoDB. Use with caution:\n    // might not work with C.upsert (as opposed to C.update({upsert:true}) or\n    // with simulated upsert.\n    if (options.fullResult) mongoOpts.fullResult = true;\n\n    var mongoSelector = replaceTypes(selector, replaceMeteorAtomWithMongo);\n    var mongoMod = replaceTypes(mod, replaceMeteorAtomWithMongo);\n\n    var isModify = isModificationMod(mongoMod);\n    var knownId = selector._id || mod._id;\n\n    if (options._forbidReplace && ! isModify) {\n      var e = new Error(\"Invalid modifier. Replacements are forbidden.\");\n      if (callback) {\n        return callback(e);\n      } else {\n        throw e;\n      }\n    }\n\n    if (options.upsert && (! knownId) && options.insertedId) {\n      // XXX If we know we're using Mongo 2.6 (and this isn't a replacement)\n      //     we should be able to just use $setOnInsert instead of this\n      //     simulated upsert thing. (We can't use $setOnInsert with\n      //     replacements because there's nowhere to write it, and $setOnInsert\n      //     can't set _id on Mongo 2.4.)\n      //\n      //     Also, in the future we could do a real upsert for the mongo id\n      //     generation case, if the the node mongo driver gives us back the id\n      //     of the upserted doc (which our current version does not).\n      //\n      //     For more context, see\n      //     https://github.com/meteor/meteor/issues/2278#issuecomment-64252706\n      simulateUpsertWithInsertedId(\n        collection, mongoSelector, mongoMod,\n        isModify, options,\n        // This callback does not need to be bindEnvironment'ed because\n        // simulateUpsertWithInsertedId() wraps it and then passes it through\n        // bindEnvironmentForWrite.\n        function (err, result) {\n          // If we got here via a upsert() call, then options._returnObject will\n          // be set and we should return the whole object. Otherwise, we should\n          // just return the number of affected docs to match the mongo API.\n          if (result && ! options._returnObject)\n            callback(err, result.numberAffected);\n          else\n            callback(err, result);\n        }\n      );\n    } else {\n      collection.update(\n        mongoSelector, mongoMod, mongoOpts,\n        bindEnvironmentForWrite(function (err, result, extra) {\n          if (! err) {\n            if (result && options._returnObject) {\n              result = { numberAffected: result };\n              // If this was an upsert() call, and we ended up\n              // inserting a new doc and we know its id, then\n              // return that id as well.\n              if (options.upsert && knownId &&\n                  ! extra.updatedExisting)\n                result.insertedId = knownId;\n            }\n          }\n          callback(err, result);\n        }));\n    }\n  } catch (e) {\n    write.committed();\n    throw e;\n  }\n};\n\nvar isModificationMod = function (mod) {\n  var isReplace = false;\n  var isModify = false;\n  for (var k in mod) {\n    if (k.substr(0, 1) === '$') {\n      isModify = true;\n    } else {\n      isReplace = true;\n    }\n  }\n  if (isModify && isReplace) {\n    throw new Error(\n      \"Update parameter cannot have both modifier and non-modifier fields.\");\n  }\n  return isModify;\n};\n\nvar NUM_OPTIMISTIC_TRIES = 3;\n\n// exposed for testing\nMongoConnection._isCannotChangeIdError = function (err) {\n  // First check for what this error looked like in Mongo 2.4.  Either of these\n  // checks should work, but just to be safe...\n  if (err.code === 13596)\n    return true;\n  if (err.err.indexOf(\"cannot change _id of a document\") === 0)\n    return true;\n\n  // Now look for what it looks like in Mongo 2.6.  We don't use the error code\n  // here, because the error code we observed it producing (16837) appears to be\n  // a far more generic error code based on examining the source.\n  if (err.err.indexOf(\"The _id field cannot be changed\") === 0)\n    return true;\n\n  return false;\n};\n\nvar simulateUpsertWithInsertedId = function (collection, selector, mod,\n                                             isModify, options, callback) {\n  // STRATEGY:  First try doing a plain update.  If it affected 0 documents,\n  // then without affecting the database, we know we should probably do an\n  // insert.  We then do a *conditional* insert that will fail in the case\n  // of a race condition.  This conditional insert is actually an\n  // upsert-replace with an _id, which will never successfully update an\n  // existing document.  If this upsert fails with an error saying it\n  // couldn't change an existing _id, then we know an intervening write has\n  // caused the query to match something.  We go back to step one and repeat.\n  // Like all \"optimistic write\" schemes, we rely on the fact that it's\n  // unlikely our writes will continue to be interfered with under normal\n  // circumstances (though sufficiently heavy contention with writers\n  // disagreeing on the existence of an object will cause writes to fail\n  // in theory).\n\n  var newDoc;\n  // Run this code up front so that it fails fast if someone uses\n  // a Mongo update operator we don't support.\n  if (isModify) {\n    // We've already run replaceTypes/replaceMeteorAtomWithMongo on\n    // selector and mod.  We assume it doesn't matter, as far as\n    // the behavior of modifiers is concerned, whether `_modify`\n    // is run on EJSON or on mongo-converted EJSON.\n    var selectorDoc = LocalCollection._removeDollarOperators(selector);\n    LocalCollection._modify(selectorDoc, mod, {isInsert: true});\n    newDoc = selectorDoc;\n  } else {\n    newDoc = mod;\n  }\n\n  var insertedId = options.insertedId; // must exist\n  var mongoOptsForUpdate = {\n    safe: true,\n    multi: options.multi\n  };\n  var mongoOptsForInsert = {\n    safe: true,\n    upsert: true\n  };\n\n  var tries = NUM_OPTIMISTIC_TRIES;\n\n  var doUpdate = function () {\n    tries--;\n    if (! tries) {\n      callback(new Error(\"Upsert failed after \" + NUM_OPTIMISTIC_TRIES + \" tries.\"));\n    } else {\n      collection.update(selector, mod, mongoOptsForUpdate,\n                        bindEnvironmentForWrite(function (err, result) {\n                          if (err)\n                            callback(err);\n                          else if (result)\n                            callback(null, {\n                              numberAffected: result\n                            });\n                          else\n                            doConditionalInsert();\n                        }));\n    }\n  };\n\n  var doConditionalInsert = function () {\n    var replacementWithId = _.extend(\n      replaceTypes({_id: insertedId}, replaceMeteorAtomWithMongo),\n      newDoc);\n    collection.update(selector, replacementWithId, mongoOptsForInsert,\n                      bindEnvironmentForWrite(function (err, result) {\n                        if (err) {\n                          // figure out if this is a\n                          // \"cannot change _id of document\" error, and\n                          // if so, try doUpdate() again, up to 3 times.\n                          if (MongoConnection._isCannotChangeIdError(err)) {\n                            doUpdate();\n                          } else {\n                            callback(err);\n                          }\n                        } else {\n                          callback(null, {\n                            numberAffected: result,\n                            insertedId: insertedId\n                          });\n                        }\n                      }));\n  };\n\n  doUpdate();\n};\n\n_.each([\"insert\", \"update\", \"remove\", \"dropCollection\"], function (method) {\n  MongoConnection.prototype[method] = function (/* arguments */) {\n    var self = this;\n    return Meteor.wrapAsync(self[\"_\" + method]).apply(self, arguments);\n  };\n});\n\n// XXX MongoConnection.upsert() does not return the id of the inserted document\n// unless you set it explicitly in the selector or modifier (as a replacement\n// doc).\nMongoConnection.prototype.upsert = function (collectionName, selector, mod,\n                                             options, callback) {\n  var self = this;\n  if (typeof options === \"function\" && ! callback) {\n    callback = options;\n    options = {};\n  }\n\n  return self.update(collectionName, selector, mod,\n                     _.extend({}, options, {\n                       upsert: true,\n                       _returnObject: true\n                     }), callback);\n};\n\nMongoConnection.prototype.find = function (collectionName, selector, options) {\n  var self = this;\n\n  if (arguments.length === 1)\n    selector = {};\n\n  return new Cursor(\n    self, new CursorDescription(collectionName, selector, options));\n};\n\nMongoConnection.prototype.findOne = function (collection_name, selector,\n                                              options) {\n  var self = this;\n  if (arguments.length === 1)\n    selector = {};\n\n  options = options || {};\n  options.limit = 1;\n  return self.find(collection_name, selector, options).fetch()[0];\n};\n\n// We'll actually design an index API later. For now, we just pass through to\n// Mongo's, but make it synchronous.\nMongoConnection.prototype._ensureIndex = function (collectionName, index,\n                                                   options) {\n  var self = this;\n  options = _.extend({safe: true}, options);\n\n  // We expect this function to be called at startup, not from within a method,\n  // so we don't interact with the write fence.\n  var collection = self.rawCollection(collectionName);\n  var future = new Future;\n  var indexName = collection.ensureIndex(index, options, future.resolver());\n  future.wait();\n};\nMongoConnection.prototype._dropIndex = function (collectionName, index) {\n  var self = this;\n\n  // This function is only used by test code, not within a method, so we don't\n  // interact with the write fence.\n  var collection = self.rawCollection(collectionName);\n  var future = new Future;\n  var indexName = collection.dropIndex(index, future.resolver());\n  future.wait();\n};\n\n// CURSORS\n\n// There are several classes which relate to cursors:\n//\n// CursorDescription represents the arguments used to construct a cursor:\n// collectionName, selector, and (find) options.  Because it is used as a key\n// for cursor de-dup, everything in it should either be JSON-stringifiable or\n// not affect observeChanges output (eg, options.transform functions are not\n// stringifiable but do not affect observeChanges).\n//\n// SynchronousCursor is a wrapper around a MongoDB cursor\n// which includes fully-synchronous versions of forEach, etc.\n//\n// Cursor is the cursor object returned from find(), which implements the\n// documented Mongo.Collection cursor API.  It wraps a CursorDescription and a\n// SynchronousCursor (lazily: it doesn't contact Mongo until you call a method\n// like fetch or forEach on it).\n//\n// ObserveHandle is the \"observe handle\" returned from observeChanges. It has a\n// reference to an ObserveMultiplexer.\n//\n// ObserveMultiplexer allows multiple identical ObserveHandles to be driven by a\n// single observe driver.\n//\n// There are two \"observe drivers\" which drive ObserveMultiplexers:\n//   - PollingObserveDriver caches the results of a query and reruns it when\n//     necessary.\n//   - OplogObserveDriver follows the Mongo operation log to directly observe\n//     database changes.\n// Both implementations follow the same simple interface: when you create them,\n// they start sending observeChanges callbacks (and a ready() invocation) to\n// their ObserveMultiplexer, and you stop them by calling their stop() method.\n\nCursorDescription = function (collectionName, selector, options) {\n  var self = this;\n  self.collectionName = collectionName;\n  self.selector = Mongo.Collection._rewriteSelector(selector);\n  self.options = options || {};\n};\n\nCursor = function (mongo, cursorDescription) {\n  var self = this;\n\n  self._mongo = mongo;\n  self._cursorDescription = cursorDescription;\n  self._synchronousCursor = null;\n};\n\n_.each(['forEach', 'map', 'fetch', 'count'], function (method) {\n  Cursor.prototype[method] = function () {\n    var self = this;\n\n    // You can only observe a tailable cursor.\n    if (self._cursorDescription.options.tailable)\n      throw new Error(\"Cannot call \" + method + \" on a tailable cursor\");\n\n    if (!self._synchronousCursor) {\n      self._synchronousCursor = self._mongo._createSynchronousCursor(\n        self._cursorDescription, {\n          // Make sure that the \"self\" argument to forEach/map callbacks is the\n          // Cursor, not the SynchronousCursor.\n          selfForIteration: self,\n          useTransform: true\n        });\n    }\n\n    return self._synchronousCursor[method].apply(\n      self._synchronousCursor, arguments);\n  };\n});\n\n// Since we don't actually have a \"nextObject\" interface, there's really no\n// reason to have a \"rewind\" interface.  All it did was make multiple calls\n// to fetch/map/forEach return nothing the second time.\n// XXX COMPAT WITH 0.8.1\nCursor.prototype.rewind = function () {\n};\n\nCursor.prototype.getTransform = function () {\n  return this._cursorDescription.options.transform;\n};\n\n// When you call Meteor.publish() with a function that returns a Cursor, we need\n// to transmute it into the equivalent subscription.  This is the function that\n// does that.\n\nCursor.prototype._publishCursor = function (sub) {\n  var self = this;\n  var collection = self._cursorDescription.collectionName;\n  return Mongo.Collection._publishCursor(self, sub, collection);\n};\n\n// Used to guarantee that publish functions return at most one cursor per\n// collection. Private, because we might later have cursors that include\n// documents from multiple collections somehow.\nCursor.prototype._getCollectionName = function () {\n  var self = this;\n  return self._cursorDescription.collectionName;\n}\n\nCursor.prototype.observe = function (callbacks) {\n  var self = this;\n  return LocalCollection._observeFromObserveChanges(self, callbacks);\n};\n\nCursor.prototype.observeChanges = function (callbacks) {\n  var self = this;\n  var ordered = LocalCollection._observeChangesCallbacksAreOrdered(callbacks);\n  return self._mongo._observeChanges(\n    self._cursorDescription, ordered, callbacks);\n};\n\nMongoConnection.prototype._createSynchronousCursor = function(\n    cursorDescription, options) {\n  var self = this;\n  options = _.pick(options || {}, 'selfForIteration', 'useTransform');\n\n  var collection = self.rawCollection(cursorDescription.collectionName);\n  var cursorOptions = cursorDescription.options;\n  var mongoOptions = {\n    sort: cursorOptions.sort,\n    limit: cursorOptions.limit,\n    skip: cursorOptions.skip\n  };\n\n  // Do we want a tailable cursor (which only works on capped collections)?\n  if (cursorOptions.tailable) {\n    // We want a tailable cursor...\n    mongoOptions.tailable = true;\n    // ... and for the server to wait a bit if any getMore has no data (rather\n    // than making us put the relevant sleeps in the client)...\n    mongoOptions.awaitdata = true;\n    // ... and to keep querying the server indefinitely rather than just 5 times\n    // if there's no more data.\n    mongoOptions.numberOfRetries = -1;\n    // And if this is on the oplog collection and the cursor specifies a 'ts',\n    // then set the undocumented oplog replay flag, which does a special scan to\n    // find the first document (instead of creating an index on ts). This is a\n    // very hard-coded Mongo flag which only works on the oplog collection and\n    // only works with the ts field.\n    if (cursorDescription.collectionName === OPLOG_COLLECTION &&\n        cursorDescription.selector.ts) {\n      mongoOptions.oplogReplay = true;\n    }\n  }\n\n  var dbCursor = collection.find(\n    replaceTypes(cursorDescription.selector, replaceMeteorAtomWithMongo),\n    cursorOptions.fields, mongoOptions);\n\n  return new SynchronousCursor(dbCursor, cursorDescription, options);\n};\n\nvar SynchronousCursor = function (dbCursor, cursorDescription, options) {\n  var self = this;\n  options = _.pick(options || {}, 'selfForIteration', 'useTransform');\n\n  self._dbCursor = dbCursor;\n  self._cursorDescription = cursorDescription;\n  // The \"self\" argument passed to forEach/map callbacks. If we're wrapped\n  // inside a user-visible Cursor, we want to provide the outer cursor!\n  self._selfForIteration = options.selfForIteration || self;\n  if (options.useTransform && cursorDescription.options.transform) {\n    self._transform = LocalCollection.wrapTransform(\n      cursorDescription.options.transform);\n  } else {\n    self._transform = null;\n  }\n\n  // Need to specify that the callback is the first argument to nextObject,\n  // since otherwise when we try to call it with no args the driver will\n  // interpret \"undefined\" first arg as an options hash and crash.\n  self._synchronousNextObject = Future.wrap(\n    dbCursor.nextObject.bind(dbCursor), 0);\n  self._synchronousCount = Future.wrap(dbCursor.count.bind(dbCursor));\n  self._visitedIds = new LocalCollection._IdMap;\n};\n\n_.extend(SynchronousCursor.prototype, {\n  _nextObject: function () {\n    var self = this;\n\n    while (true) {\n      var doc = self._synchronousNextObject().wait();\n\n      if (!doc) return null;\n      doc = replaceTypes(doc, replaceMongoAtomWithMeteor);\n\n      if (!self._cursorDescription.options.tailable && _.has(doc, '_id')) {\n        // Did Mongo give us duplicate documents in the same cursor? If so,\n        // ignore this one. (Do this before the transform, since transform might\n        // return some unrelated value.) We don't do this for tailable cursors,\n        // because we want to maintain O(1) memory usage. And if there isn't _id\n        // for some reason (maybe it's the oplog), then we don't do this either.\n        // (Be careful to do this for falsey but existing _id, though.)\n        if (self._visitedIds.has(doc._id)) continue;\n        self._visitedIds.set(doc._id, true);\n      }\n\n      if (self._transform)\n        doc = self._transform(doc);\n\n      return doc;\n    }\n  },\n\n  forEach: function (callback, thisArg) {\n    var self = this;\n\n    // Get back to the beginning.\n    self._rewind();\n\n    // We implement the loop ourself instead of using self._dbCursor.each,\n    // because \"each\" will call its callback outside of a fiber which makes it\n    // much more complex to make this function synchronous.\n    var index = 0;\n    while (true) {\n      var doc = self._nextObject();\n      if (!doc) return;\n      callback.call(thisArg, doc, index++, self._selfForIteration);\n    }\n  },\n\n  // XXX Allow overlapping callback executions if callback yields.\n  map: function (callback, thisArg) {\n    var self = this;\n    var res = [];\n    self.forEach(function (doc, index) {\n      res.push(callback.call(thisArg, doc, index, self._selfForIteration));\n    });\n    return res;\n  },\n\n  _rewind: function () {\n    var self = this;\n\n    // known to be synchronous\n    self._dbCursor.rewind();\n\n    self._visitedIds = new LocalCollection._IdMap;\n  },\n\n  // Mostly usable for tailable cursors.\n  close: function () {\n    var self = this;\n\n    self._dbCursor.close();\n  },\n\n  fetch: function () {\n    var self = this;\n    return self.map(_.identity);\n  },\n\n  count: function () {\n    var self = this;\n    return self._synchronousCount().wait();\n  },\n\n  // This method is NOT wrapped in Cursor.\n  getRawObjects: function (ordered) {\n    var self = this;\n    if (ordered) {\n      return self.fetch();\n    } else {\n      var results = new LocalCollection._IdMap;\n      self.forEach(function (doc) {\n        results.set(doc._id, doc);\n      });\n      return results;\n    }\n  }\n});\n\nMongoConnection.prototype.tail = function (cursorDescription, docCallback) {\n  var self = this;\n  if (!cursorDescription.options.tailable)\n    throw new Error(\"Can only tail a tailable cursor\");\n\n  var cursor = self._createSynchronousCursor(cursorDescription);\n\n  var stopped = false;\n  var lastTS = undefined;\n  var loop = function () {\n    while (true) {\n      if (stopped)\n        return;\n      try {\n        var doc = cursor._nextObject();\n      } catch (err) {\n        // There's no good way to figure out if this was actually an error\n        // from Mongo. Ah well. But either way, we need to retry the cursor\n        // (unless the failure was because the observe got stopped).\n        doc = null;\n      }\n      // Since cursor._nextObject can yield, we need to check again to see if\n      // we've been stopped before calling the callback.\n      if (stopped)\n        return;\n      if (doc) {\n        // If a tailable cursor contains a \"ts\" field, use it to recreate the\n        // cursor on error. (\"ts\" is a standard that Mongo uses internally for\n        // the oplog, and there's a special flag that lets you do binary search\n        // on it instead of needing to use an index.)\n        lastTS = doc.ts;\n        docCallback(doc);\n      } else {\n        var newSelector = _.clone(cursorDescription.selector);\n        if (lastTS) {\n          newSelector.ts = {$gt: lastTS};\n        }\n        cursor = self._createSynchronousCursor(new CursorDescription(\n          cursorDescription.collectionName,\n          newSelector,\n          cursorDescription.options));\n        // Mongo failover takes many seconds.  Retry in a bit.  (Without this\n        // setTimeout, we peg the CPU at 100% and never notice the actual\n        // failover.\n        Meteor.setTimeout(loop, 100);\n        break;\n      }\n    }\n  };\n\n  Meteor.defer(loop);\n\n  return {\n    stop: function () {\n      stopped = true;\n      cursor.close();\n    }\n  };\n};\n\nMongoConnection.prototype._observeChanges = function (\n    cursorDescription, ordered, callbacks) {\n  var self = this;\n\n  if (cursorDescription.options.tailable) {\n    return self._observeChangesTailable(cursorDescription, ordered, callbacks);\n  }\n\n  // You may not filter out _id when observing changes, because the id is a core\n  // part of the observeChanges API.\n  if (cursorDescription.options.fields &&\n      (cursorDescription.options.fields._id === 0 ||\n       cursorDescription.options.fields._id === false)) {\n    throw Error(\"You may not observe a cursor with {fields: {_id: 0}}\");\n  }\n\n  var observeKey = JSON.stringify(\n    _.extend({ordered: ordered}, cursorDescription));\n\n  var multiplexer, observeDriver;\n  var firstHandle = false;\n\n  // Find a matching ObserveMultiplexer, or create a new one. This next block is\n  // guaranteed to not yield (and it doesn't call anything that can observe a\n  // new query), so no other calls to this function can interleave with it.\n  Meteor._noYieldsAllowed(function () {\n    if (_.has(self._observeMultiplexers, observeKey)) {\n      multiplexer = self._observeMultiplexers[observeKey];\n    } else {\n      firstHandle = true;\n      // Create a new ObserveMultiplexer.\n      multiplexer = new ObserveMultiplexer({\n        ordered: ordered,\n        onStop: function () {\n          delete self._observeMultiplexers[observeKey];\n          observeDriver.stop();\n        }\n      });\n      self._observeMultiplexers[observeKey] = multiplexer;\n    }\n  });\n\n  var observeHandle = new ObserveHandle(multiplexer, callbacks);\n\n  if (firstHandle) {\n    var matcher, sorter;\n    var canUseOplog = _.all([\n      function () {\n        // At a bare minimum, using the oplog requires us to have an oplog, to\n        // want unordered callbacks, and to not want a callback on the polls\n        // that won't happen.\n        return self._oplogHandle && !ordered &&\n          !callbacks._testOnlyPollCallback;\n      }, function () {\n        // We need to be able to compile the selector. Fall back to polling for\n        // some newfangled $selector that minimongo doesn't support yet.\n        try {\n          matcher = new Minimongo.Matcher(cursorDescription.selector);\n          return true;\n        } catch (e) {\n          // XXX make all compilation errors MinimongoError or something\n          //     so that this doesn't ignore unrelated exceptions\n          return false;\n        }\n      }, function () {\n        // ... and the selector itself needs to support oplog.\n        return OplogObserveDriver.cursorSupported(cursorDescription, matcher);\n      }, function () {\n        // And we need to be able to compile the sort, if any.  eg, can't be\n        // {$natural: 1}.\n        if (!cursorDescription.options.sort)\n          return true;\n        try {\n          sorter = new Minimongo.Sorter(cursorDescription.options.sort,\n                                        { matcher: matcher });\n          return true;\n        } catch (e) {\n          // XXX make all compilation errors MinimongoError or something\n          //     so that this doesn't ignore unrelated exceptions\n          return false;\n        }\n      }], function (f) { return f(); });  // invoke each function\n\n    var driverClass = canUseOplog ? OplogObserveDriver : PollingObserveDriver;\n    observeDriver = new driverClass({\n      cursorDescription: cursorDescription,\n      mongoHandle: self,\n      multiplexer: multiplexer,\n      ordered: ordered,\n      matcher: matcher,  // ignored by polling\n      sorter: sorter,  // ignored by polling\n      _testOnlyPollCallback: callbacks._testOnlyPollCallback\n    });\n\n    // This field is only set for use in tests.\n    multiplexer._observeDriver = observeDriver;\n  }\n\n  // Blocks until the initial adds have been sent.\n  multiplexer.addHandleAndSendInitialAdds(observeHandle);\n\n  return observeHandle;\n};\n\n// Listen for the invalidation messages that will trigger us to poll the\n// database for changes. If this selector specifies specific IDs, specify them\n// here, so that updates to different specific IDs don't cause us to poll.\n// listenCallback is the same kind of (notification, complete) callback passed\n// to InvalidationCrossbar.listen.\n\nlistenAll = function (cursorDescription, listenCallback) {\n  var listeners = [];\n  forEachTrigger(cursorDescription, function (trigger) {\n    listeners.push(DDPServer._InvalidationCrossbar.listen(\n      trigger, listenCallback));\n  });\n\n  return {\n    stop: function () {\n      _.each(listeners, function (listener) {\n        listener.stop();\n      });\n    }\n  };\n};\n\nforEachTrigger = function (cursorDescription, triggerCallback) {\n  var key = {collection: cursorDescription.collectionName};\n  var specificIds = LocalCollection._idsMatchedBySelector(\n    cursorDescription.selector);\n  if (specificIds) {\n    _.each(specificIds, function (id) {\n      triggerCallback(_.extend({id: id}, key));\n    });\n    triggerCallback(_.extend({dropCollection: true, id: null}, key));\n  } else {\n    triggerCallback(key);\n  }\n};\n\n// observeChanges for tailable cursors on capped collections.\n//\n// Some differences from normal cursors:\n//   - Will never produce anything other than 'added' or 'addedBefore'. If you\n//     do update a document that has already been produced, this will not notice\n//     it.\n//   - If you disconnect and reconnect from Mongo, it will essentially restart\n//     the query, which will lead to duplicate results. This is pretty bad,\n//     but if you include a field called 'ts' which is inserted as\n//     new MongoInternals.MongoTimestamp(0, 0) (which is initialized to the\n//     current Mongo-style timestamp), we'll be able to find the place to\n//     restart properly. (This field is specifically understood by Mongo with an\n//     optimization which allows it to find the right place to start without\n//     an index on ts. It's how the oplog works.)\n//   - No callbacks are triggered synchronously with the call (there's no\n//     differentiation between \"initial data\" and \"later changes\"; everything\n//     that matches the query gets sent asynchronously).\n//   - De-duplication is not implemented.\n//   - Does not yet interact with the write fence. Probably, this should work by\n//     ignoring removes (which don't work on capped collections) and updates\n//     (which don't affect tailable cursors), and just keeping track of the ID\n//     of the inserted object, and closing the write fence once you get to that\n//     ID (or timestamp?).  This doesn't work well if the document doesn't match\n//     the query, though.  On the other hand, the write fence can close\n//     immediately if it does not match the query. So if we trust minimongo\n//     enough to accurately evaluate the query against the write fence, we\n//     should be able to do this...  Of course, minimongo doesn't even support\n//     Mongo Timestamps yet.\nMongoConnection.prototype._observeChangesTailable = function (\n    cursorDescription, ordered, callbacks) {\n  var self = this;\n\n  // Tailable cursors only ever call added/addedBefore callbacks, so it's an\n  // error if you didn't provide them.\n  if ((ordered && !callbacks.addedBefore) ||\n      (!ordered && !callbacks.added)) {\n    throw new Error(\"Can't observe an \" + (ordered ? \"ordered\" : \"unordered\")\n                    + \" tailable cursor without a \"\n                    + (ordered ? \"addedBefore\" : \"added\") + \" callback\");\n  }\n\n  return self.tail(cursorDescription, function (doc) {\n    var id = doc._id;\n    delete doc._id;\n    // The ts is an implementation detail. Hide it.\n    delete doc.ts;\n    if (ordered) {\n      callbacks.addedBefore(id, doc, null);\n    } else {\n      callbacks.added(id, doc);\n    }\n  });\n};\n\n// XXX We probably need to find a better way to expose this. Right now\n// it's only used by tests, but in fact you need it in normal\n// operation to interact with capped collections.\nMongoInternals.MongoTimestamp = MongoDB.Timestamp;\n\nMongoInternals.Connection = MongoConnection;\n","var Future = Npm.require('fibers/future');\n\nOPLOG_COLLECTION = 'oplog.rs';\n\nvar TOO_FAR_BEHIND = process.env.METEOR_OPLOG_TOO_FAR_BEHIND || 2000;\n\n// Like Perl's quotemeta: quotes all regexp metacharacters. See\n//   https://github.com/substack/quotemeta/blob/master/index.js\n// XXX this is duplicated with accounts_server.js\nvar quotemeta = function (str) {\n    return String(str).replace(/(\\W)/g, '\\\\$1');\n};\n\nvar showTS = function (ts) {\n  return \"Timestamp(\" + ts.getHighBits() + \", \" + ts.getLowBits() + \")\";\n};\n\nidForOp = function (op) {\n  if (op.op === 'd')\n    return op.o._id;\n  else if (op.op === 'i')\n    return op.o._id;\n  else if (op.op === 'u')\n    return op.o2._id;\n  else if (op.op === 'c')\n    throw Error(\"Operator 'c' doesn't supply an object with id: \" +\n                EJSON.stringify(op));\n  else\n    throw Error(\"Unknown op: \" + EJSON.stringify(op));\n};\n\nOplogHandle = function (oplogUrl, dbName) {\n  var self = this;\n  self._oplogUrl = oplogUrl;\n  self._dbName = dbName;\n\n  self._oplogLastEntryConnection = null;\n  self._oplogTailConnection = null;\n  self._stopped = false;\n  self._tailHandle = null;\n  self._readyFuture = new Future();\n  self._crossbar = new DDPServer._Crossbar({\n    factPackage: \"mongo-livedata\", factName: \"oplog-watchers\"\n  });\n  self._baseOplogSelector = {\n    ns: new RegExp('^' + quotemeta(self._dbName) + '\\\\.'),\n    $or: [\n      { op: {$in: ['i', 'u', 'd']} },\n      // If it is not db.collection.drop(), ignore it\n      { op: 'c', 'o.drop': { $exists: true } }]\n  };\n\n  // Data structures to support waitUntilCaughtUp(). Each oplog entry has a\n  // MongoTimestamp object on it (which is not the same as a Date --- it's a\n  // combination of time and an incrementing counter; see\n  // http://docs.mongodb.org/manual/reference/bson-types/#timestamps).\n  //\n  // _catchingUpFutures is an array of {ts: MongoTimestamp, future: Future}\n  // objects, sorted by ascending timestamp. _lastProcessedTS is the\n  // MongoTimestamp of the last oplog entry we've processed.\n  //\n  // Each time we call waitUntilCaughtUp, we take a peek at the final oplog\n  // entry in the db.  If we've already processed it (ie, it is not greater than\n  // _lastProcessedTS), waitUntilCaughtUp immediately returns. Otherwise,\n  // waitUntilCaughtUp makes a new Future and inserts it along with the final\n  // timestamp entry that it read, into _catchingUpFutures. waitUntilCaughtUp\n  // then waits on that future, which is resolved once _lastProcessedTS is\n  // incremented to be past its timestamp by the worker fiber.\n  //\n  // XXX use a priority queue or something else that's faster than an array\n  self._catchingUpFutures = [];\n  self._lastProcessedTS = null;\n\n  self._onSkippedEntriesHook = new Hook({\n    debugPrintExceptions: \"onSkippedEntries callback\"\n  });\n\n  self._entryQueue = new Meteor._DoubleEndedQueue();\n  self._workerActive = false;\n\n  self._startTailing();\n};\n\n_.extend(OplogHandle.prototype, {\n  stop: function () {\n    var self = this;\n    if (self._stopped)\n      return;\n    self._stopped = true;\n    if (self._tailHandle)\n      self._tailHandle.stop();\n    // XXX should close connections too\n  },\n  onOplogEntry: function (trigger, callback) {\n    var self = this;\n    if (self._stopped)\n      throw new Error(\"Called onOplogEntry on stopped handle!\");\n\n    // Calling onOplogEntry requires us to wait for the tailing to be ready.\n    self._readyFuture.wait();\n\n    var originalCallback = callback;\n    callback = Meteor.bindEnvironment(function (notification) {\n      // XXX can we avoid this clone by making oplog.js careful?\n      originalCallback(EJSON.clone(notification));\n    }, function (err) {\n      Meteor._debug(\"Error in oplog callback\", err.stack);\n    });\n    var listenHandle = self._crossbar.listen(trigger, callback);\n    return {\n      stop: function () {\n        listenHandle.stop();\n      }\n    };\n  },\n  // Register a callback to be invoked any time we skip oplog entries (eg,\n  // because we are too far behind).\n  onSkippedEntries: function (callback) {\n    var self = this;\n    if (self._stopped)\n      throw new Error(\"Called onSkippedEntries on stopped handle!\");\n    return self._onSkippedEntriesHook.register(callback);\n  },\n  // Calls `callback` once the oplog has been processed up to a point that is\n  // roughly \"now\": specifically, once we've processed all ops that are\n  // currently visible.\n  // XXX become convinced that this is actually safe even if oplogConnection\n  // is some kind of pool\n  waitUntilCaughtUp: function () {\n    var self = this;\n    if (self._stopped)\n      throw new Error(\"Called waitUntilCaughtUp on stopped handle!\");\n\n    // Calling waitUntilCaughtUp requries us to wait for the oplog connection to\n    // be ready.\n    self._readyFuture.wait();\n\n    while (!self._stopped) {\n      // We need to make the selector at least as restrictive as the actual\n      // tailing selector (ie, we need to specify the DB name) or else we might\n      // find a TS that won't show up in the actual tail stream.\n      try {\n        var lastEntry = self._oplogLastEntryConnection.findOne(\n          OPLOG_COLLECTION, self._baseOplogSelector,\n          {fields: {ts: 1}, sort: {$natural: -1}});\n        break;\n      } catch (e) {\n        // During failover (eg) if we get an exception we should log and retry\n        // instead of crashing.\n        Meteor._debug(\"Got exception while reading last entry: \" + e);\n        Meteor._sleepForMs(100);\n      }\n    }\n\n    if (self._stopped)\n      return;\n\n    if (!lastEntry) {\n      // Really, nothing in the oplog? Well, we've processed everything.\n      return;\n    }\n\n    var ts = lastEntry.ts;\n    if (!ts)\n      throw Error(\"oplog entry without ts: \" + EJSON.stringify(lastEntry));\n\n    if (self._lastProcessedTS && ts.lessThanOrEqual(self._lastProcessedTS)) {\n      // We've already caught up to here.\n      return;\n    }\n\n\n    // Insert the future into our list. Almost always, this will be at the end,\n    // but it's conceivable that if we fail over from one primary to another,\n    // the oplog entries we see will go backwards.\n    var insertAfter = self._catchingUpFutures.length;\n    while (insertAfter - 1 > 0\n           && self._catchingUpFutures[insertAfter - 1].ts.greaterThan(ts)) {\n      insertAfter--;\n    }\n    var f = new Future;\n    self._catchingUpFutures.splice(insertAfter, 0, {ts: ts, future: f});\n    f.wait();\n  },\n  _startTailing: function () {\n    var self = this;\n    // First, make sure that we're talking to the local database.\n    var mongodbUri = Npm.require('mongodb-uri');\n    if (mongodbUri.parse(self._oplogUrl).database !== 'local') {\n      throw Error(\"$MONGO_OPLOG_URL must be set to the 'local' database of \" +\n                  \"a Mongo replica set\");\n    }\n\n    // We make two separate connections to Mongo. The Node Mongo driver\n    // implements a naive round-robin connection pool: each \"connection\" is a\n    // pool of several (5 by default) TCP connections, and each request is\n    // rotated through the pools. Tailable cursor queries block on the server\n    // until there is some data to return (or until a few seconds have\n    // passed). So if the connection pool used for tailing cursors is the same\n    // pool used for other queries, the other queries will be delayed by seconds\n    // 1/5 of the time.\n    //\n    // The tail connection will only ever be running a single tail command, so\n    // it only needs to make one underlying TCP connection.\n    self._oplogTailConnection = new MongoConnection(\n      self._oplogUrl, {poolSize: 1});\n    // XXX better docs, but: it's to get monotonic results\n    // XXX is it safe to say \"if there's an in flight query, just use its\n    //     results\"? I don't think so but should consider that\n    self._oplogLastEntryConnection = new MongoConnection(\n      self._oplogUrl, {poolSize: 1});\n\n    // Now, make sure that there actually is a repl set here. If not, oplog\n    // tailing won't ever find anything!\n    var f = new Future;\n    self._oplogLastEntryConnection.db.admin().command(\n      { ismaster: 1 }, f.resolver());\n    var isMasterDoc = f.wait();\n    if (!(isMasterDoc && isMasterDoc.documents && isMasterDoc.documents[0] &&\n          isMasterDoc.documents[0].setName)) {\n      throw Error(\"$MONGO_OPLOG_URL must be set to the 'local' database of \" +\n                  \"a Mongo replica set\");\n    }\n\n    // Find the last oplog entry.\n    var lastOplogEntry = self._oplogLastEntryConnection.findOne(\n      OPLOG_COLLECTION, {}, {sort: {$natural: -1}, fields: {ts: 1}});\n\n    var oplogSelector = _.clone(self._baseOplogSelector);\n    if (lastOplogEntry) {\n      // Start after the last entry that currently exists.\n      oplogSelector.ts = {$gt: lastOplogEntry.ts};\n      // If there are any calls to callWhenProcessedLatest before any other\n      // oplog entries show up, allow callWhenProcessedLatest to call its\n      // callback immediately.\n      self._lastProcessedTS = lastOplogEntry.ts;\n    }\n\n    var cursorDescription = new CursorDescription(\n      OPLOG_COLLECTION, oplogSelector, {tailable: true});\n\n    self._tailHandle = self._oplogTailConnection.tail(\n      cursorDescription, function (doc) {\n        self._entryQueue.push(doc);\n        self._maybeStartWorker();\n      }\n    );\n    self._readyFuture.return();\n  },\n\n  _maybeStartWorker: function () {\n    var self = this;\n    if (self._workerActive)\n      return;\n    self._workerActive = true;\n    Meteor.defer(function () {\n      try {\n        while (! self._stopped && ! self._entryQueue.isEmpty()) {\n          // Are we too far behind? Just tell our observers that they need to\n          // repoll, and drop our queue.\n          if (self._entryQueue.length > TOO_FAR_BEHIND) {\n            var lastEntry = self._entryQueue.pop();\n            self._entryQueue.clear();\n\n            self._onSkippedEntriesHook.each(function (callback) {\n              callback();\n              return true;\n            });\n\n            // Free any waitUntilCaughtUp() calls that were waiting for us to\n            // pass something that we just skipped.\n            self._setLastProcessedTS(lastEntry.ts);\n            continue;\n          }\n\n          var doc = self._entryQueue.shift();\n\n          if (!(doc.ns && doc.ns.length > self._dbName.length + 1 &&\n                doc.ns.substr(0, self._dbName.length + 1) ===\n                (self._dbName + '.'))) {\n            throw new Error(\"Unexpected ns\");\n          }\n\n          var trigger = {collection: doc.ns.substr(self._dbName.length + 1),\n                         dropCollection: false,\n                         op: doc};\n\n          // Is it a special command and the collection name is hidden somewhere\n          // in operator?\n          if (trigger.collection === \"$cmd\") {\n            trigger.collection = doc.o.drop;\n            trigger.dropCollection = true;\n            trigger.id = null;\n          } else {\n            // All other ops have an id.\n            trigger.id = idForOp(doc);\n          }\n\n          self._crossbar.fire(trigger);\n\n          // Now that we've processed this operation, process pending\n          // sequencers.\n          if (!doc.ts)\n            throw Error(\"oplog entry without ts: \" + EJSON.stringify(doc));\n          self._setLastProcessedTS(doc.ts);\n        }\n      } finally {\n        self._workerActive = false;\n      }\n    });\n  },\n  _setLastProcessedTS: function (ts) {\n    var self = this;\n    self._lastProcessedTS = ts;\n    while (!_.isEmpty(self._catchingUpFutures)\n           && self._catchingUpFutures[0].ts.lessThanOrEqual(\n             self._lastProcessedTS)) {\n      var sequencer = self._catchingUpFutures.shift();\n      sequencer.future.return();\n    }\n  }\n});\n","var Future = Npm.require('fibers/future');\n\nObserveMultiplexer = function (options) {\n  var self = this;\n\n  if (!options || !_.has(options, 'ordered'))\n    throw Error(\"must specified ordered\");\n\n  Package.facts && Package.facts.Facts.incrementServerFact(\n    \"mongo-livedata\", \"observe-multiplexers\", 1);\n\n  self._ordered = options.ordered;\n  self._onStop = options.onStop || function () {};\n  self._queue = new Meteor._SynchronousQueue();\n  self._handles = {};\n  self._readyFuture = new Future;\n  self._cache = new LocalCollection._CachingChangeObserver({\n    ordered: options.ordered});\n  // Number of addHandleAndSendInitialAdds tasks scheduled but not yet\n  // running. removeHandle uses this to know if it's time to call the onStop\n  // callback.\n  self._addHandleTasksScheduledButNotPerformed = 0;\n\n  _.each(self.callbackNames(), function (callbackName) {\n    self[callbackName] = function (/* ... */) {\n      self._applyCallback(callbackName, _.toArray(arguments));\n    };\n  });\n};\n\n_.extend(ObserveMultiplexer.prototype, {\n  addHandleAndSendInitialAdds: function (handle) {\n    var self = this;\n\n    // Check this before calling runTask (even though runTask does the same\n    // check) so that we don't leak an ObserveMultiplexer on error by\n    // incrementing _addHandleTasksScheduledButNotPerformed and never\n    // decrementing it.\n    if (!self._queue.safeToRunTask())\n      throw new Error(\n        \"Can't call observeChanges from an observe callback on the same query\");\n    ++self._addHandleTasksScheduledButNotPerformed;\n\n    Package.facts && Package.facts.Facts.incrementServerFact(\n      \"mongo-livedata\", \"observe-handles\", 1);\n\n    self._queue.runTask(function () {\n      self._handles[handle._id] = handle;\n      // Send out whatever adds we have so far (whether or not we the\n      // multiplexer is ready).\n      self._sendAdds(handle);\n      --self._addHandleTasksScheduledButNotPerformed;\n    });\n    // *outside* the task, since otherwise we'd deadlock\n    self._readyFuture.wait();\n  },\n\n  // Remove an observe handle. If it was the last observe handle, call the\n  // onStop callback; you cannot add any more observe handles after this.\n  //\n  // This is not synchronized with polls and handle additions: this means that\n  // you can safely call it from within an observe callback, but it also means\n  // that we have to be careful when we iterate over _handles.\n  removeHandle: function (id) {\n    var self = this;\n\n    // This should not be possible: you can only call removeHandle by having\n    // access to the ObserveHandle, which isn't returned to user code until the\n    // multiplex is ready.\n    if (!self._ready())\n      throw new Error(\"Can't remove handles until the multiplex is ready\");\n\n    delete self._handles[id];\n\n    Package.facts && Package.facts.Facts.incrementServerFact(\n      \"mongo-livedata\", \"observe-handles\", -1);\n\n    if (_.isEmpty(self._handles) &&\n        self._addHandleTasksScheduledButNotPerformed === 0) {\n      self._stop();\n    }\n  },\n  _stop: function (options) {\n    var self = this;\n    options = options || {};\n\n    // It shouldn't be possible for us to stop when all our handles still\n    // haven't been returned from observeChanges!\n    if (! self._ready() && ! options.fromQueryError)\n      throw Error(\"surprising _stop: not ready\");\n\n    // Call stop callback (which kills the underlying process which sends us\n    // callbacks and removes us from the connection's dictionary).\n    self._onStop();\n    Package.facts && Package.facts.Facts.incrementServerFact(\n      \"mongo-livedata\", \"observe-multiplexers\", -1);\n\n    // Cause future addHandleAndSendInitialAdds calls to throw (but the onStop\n    // callback should make our connection forget about us).\n    self._handles = null;\n  },\n\n  // Allows all addHandleAndSendInitialAdds calls to return, once all preceding\n  // adds have been processed. Does not block.\n  ready: function () {\n    var self = this;\n    self._queue.queueTask(function () {\n      if (self._ready())\n        throw Error(\"can't make ObserveMultiplex ready twice!\");\n      self._readyFuture.return();\n    });\n  },\n\n  // If trying to execute the query results in an error, call this. This is\n  // intended for permanent errors, not transient network errors that could be\n  // fixed. It should only be called before ready(), because if you called ready\n  // that meant that you managed to run the query once. It will stop this\n  // ObserveMultiplex and cause addHandleAndSendInitialAdds calls (and thus\n  // observeChanges calls) to throw the error.\n  queryError: function (err) {\n    var self = this;\n    self._queue.runTask(function () {\n      if (self._ready())\n        throw Error(\"can't claim query has an error after it worked!\");\n      self._stop({fromQueryError: true});\n      self._readyFuture.throw(err);\n    });\n  },\n\n  // Calls \"cb\" once the effects of all \"ready\", \"addHandleAndSendInitialAdds\"\n  // and observe callbacks which came before this call have been propagated to\n  // all handles. \"ready\" must have already been called on this multiplexer.\n  onFlush: function (cb) {\n    var self = this;\n    self._queue.queueTask(function () {\n      if (!self._ready())\n        throw Error(\"only call onFlush on a multiplexer that will be ready\");\n      cb();\n    });\n  },\n  callbackNames: function () {\n    var self = this;\n    if (self._ordered)\n      return [\"addedBefore\", \"changed\", \"movedBefore\", \"removed\"];\n    else\n      return [\"added\", \"changed\", \"removed\"];\n  },\n  _ready: function () {\n    return this._readyFuture.isResolved();\n  },\n  _applyCallback: function (callbackName, args) {\n    var self = this;\n    self._queue.queueTask(function () {\n      // If we stopped in the meantime, do nothing.\n      if (!self._handles)\n        return;\n\n      // First, apply the change to the cache.\n      // XXX We could make applyChange callbacks promise not to hang on to any\n      // state from their arguments (assuming that their supplied callbacks\n      // don't) and skip this clone. Currently 'changed' hangs on to state\n      // though.\n      self._cache.applyChange[callbackName].apply(null, EJSON.clone(args));\n\n      // If we haven't finished the initial adds, then we should only be getting\n      // adds.\n      if (!self._ready() &&\n          (callbackName !== 'added' && callbackName !== 'addedBefore')) {\n        throw new Error(\"Got \" + callbackName + \" during initial adds\");\n      }\n\n      // Now multiplex the callbacks out to all observe handles. It's OK if\n      // these calls yield; since we're inside a task, no other use of our queue\n      // can continue until these are done. (But we do have to be careful to not\n      // use a handle that got removed, because removeHandle does not use the\n      // queue; thus, we iterate over an array of keys that we control.)\n      _.each(_.keys(self._handles), function (handleId) {\n        var handle = self._handles && self._handles[handleId];\n        if (!handle)\n          return;\n        var callback = handle['_' + callbackName];\n        // clone arguments so that callbacks can mutate their arguments\n        callback && callback.apply(null, EJSON.clone(args));\n      });\n    });\n  },\n\n  // Sends initial adds to a handle. It should only be called from within a task\n  // (the task that is processing the addHandleAndSendInitialAdds call). It\n  // synchronously invokes the handle's added or addedBefore; there's no need to\n  // flush the queue afterwards to ensure that the callbacks get out.\n  _sendAdds: function (handle) {\n    var self = this;\n    if (self._queue.safeToRunTask())\n      throw Error(\"_sendAdds may only be called from within a task!\");\n    var add = self._ordered ? handle._addedBefore : handle._added;\n    if (!add)\n      return;\n    // note: docs may be an _IdMap or an OrderedDict\n    self._cache.docs.forEach(function (doc, id) {\n      if (!_.has(self._handles, handle._id))\n        throw Error(\"handle got removed before sending initial adds!\");\n      var fields = EJSON.clone(doc);\n      delete fields._id;\n      if (self._ordered)\n        add(id, fields, null); // we're going in order, so add at end\n      else\n        add(id, fields);\n    });\n  }\n});\n\n\nvar nextObserveHandleId = 1;\nObserveHandle = function (multiplexer, callbacks) {\n  var self = this;\n  // The end user is only supposed to call stop().  The other fields are\n  // accessible to the multiplexer, though.\n  self._multiplexer = multiplexer;\n  _.each(multiplexer.callbackNames(), function (name) {\n    if (callbacks[name]) {\n      self['_' + name] = callbacks[name];\n    } else if (name === \"addedBefore\" && callbacks.added) {\n      // Special case: if you specify \"added\" and \"movedBefore\", you get an\n      // ordered observe where for some reason you don't get ordering data on\n      // the adds.  I dunno, we wrote tests for it, there must have been a\n      // reason.\n      self._addedBefore = function (id, fields, before) {\n        callbacks.added(id, fields);\n      };\n    }\n  });\n  self._stopped = false;\n  self._id = nextObserveHandleId++;\n};\nObserveHandle.prototype.stop = function () {\n  var self = this;\n  if (self._stopped)\n    return;\n  self._stopped = true;\n  self._multiplexer.removeHandle(self._id);\n};\n","var Fiber = Npm.require('fibers');\nvar Future = Npm.require('fibers/future');\n\nDocFetcher = function (mongoConnection) {\n  var self = this;\n  self._mongoConnection = mongoConnection;\n  // Map from cache key -> [callback]\n  self._callbacksForCacheKey = {};\n};\n\n_.extend(DocFetcher.prototype, {\n  // Fetches document \"id\" from collectionName, returning it or null if not\n  // found.\n  //\n  // If you make multiple calls to fetch() with the same cacheKey (a string),\n  // DocFetcher may assume that they all return the same document. (It does\n  // not check to see if collectionName/id match.)\n  //\n  // You may assume that callback is never called synchronously (and in fact\n  // OplogObserveDriver does so).\n  fetch: function (collectionName, id, cacheKey, callback) {\n    var self = this;\n\n    check(collectionName, String);\n    // id is some sort of scalar\n    check(cacheKey, String);\n\n    // If there's already an in-progress fetch for this cache key, yield until\n    // it's done and return whatever it returns.\n    if (_.has(self._callbacksForCacheKey, cacheKey)) {\n      self._callbacksForCacheKey[cacheKey].push(callback);\n      return;\n    }\n\n    var callbacks = self._callbacksForCacheKey[cacheKey] = [callback];\n\n    Fiber(function () {\n      try {\n        var doc = self._mongoConnection.findOne(\n          collectionName, {_id: id}) || null;\n        // Return doc to all relevant callbacks. Note that this array can\n        // continue to grow during callback excecution.\n        while (!_.isEmpty(callbacks)) {\n          // Clone the document so that the various calls to fetch don't return\n          // objects that are intertwingled with each other. Clone before\n          // popping the future, so that if clone throws, the error gets passed\n          // to the next callback.\n          var clonedDoc = EJSON.clone(doc);\n          callbacks.pop()(null, clonedDoc);\n        }\n      } catch (e) {\n        while (!_.isEmpty(callbacks)) {\n          callbacks.pop()(e);\n        }\n      } finally {\n        // XXX consider keeping the doc around for a period of time before\n        // removing from the cache\n        delete self._callbacksForCacheKey[cacheKey];\n      }\n    }).run();\n  }\n});\n\nMongoTest.DocFetcher = DocFetcher;\n","PollingObserveDriver = function (options) {\n  var self = this;\n\n  self._cursorDescription = options.cursorDescription;\n  self._mongoHandle = options.mongoHandle;\n  self._ordered = options.ordered;\n  self._multiplexer = options.multiplexer;\n  self._stopCallbacks = [];\n  self._stopped = false;\n\n  self._synchronousCursor = self._mongoHandle._createSynchronousCursor(\n    self._cursorDescription);\n\n  // previous results snapshot.  on each poll cycle, diffs against\n  // results drives the callbacks.\n  self._results = null;\n\n  // The number of _pollMongo calls that have been added to self._taskQueue but\n  // have not started running. Used to make sure we never schedule more than one\n  // _pollMongo (other than possibly the one that is currently running). It's\n  // also used by _suspendPolling to pretend there's a poll scheduled. Usually,\n  // it's either 0 (for \"no polls scheduled other than maybe one currently\n  // running\") or 1 (for \"a poll scheduled that isn't running yet\"), but it can\n  // also be 2 if incremented by _suspendPolling.\n  self._pollsScheduledButNotStarted = 0;\n  self._pendingWrites = []; // people to notify when polling completes\n\n  // Make sure to create a separately throttled function for each\n  // PollingObserveDriver object.\n  self._ensurePollIsScheduled = _.throttle(\n    self._unthrottledEnsurePollIsScheduled, 50 /* ms */);\n\n  // XXX figure out if we still need a queue\n  self._taskQueue = new Meteor._SynchronousQueue();\n\n  var listenersHandle = listenAll(\n    self._cursorDescription, function (notification) {\n      // When someone does a transaction that might affect us, schedule a poll\n      // of the database. If that transaction happens inside of a write fence,\n      // block the fence until we've polled and notified observers.\n      var fence = DDPServer._CurrentWriteFence.get();\n      if (fence)\n        self._pendingWrites.push(fence.beginWrite());\n      // Ensure a poll is scheduled... but if we already know that one is,\n      // don't hit the throttled _ensurePollIsScheduled function (which might\n      // lead to us calling it unnecessarily in 50ms).\n      if (self._pollsScheduledButNotStarted === 0)\n        self._ensurePollIsScheduled();\n    }\n  );\n  self._stopCallbacks.push(function () { listenersHandle.stop(); });\n\n  // every once and a while, poll even if we don't think we're dirty, for\n  // eventual consistency with database writes from outside the Meteor\n  // universe.\n  //\n  // For testing, there's an undocumented callback argument to observeChanges\n  // which disables time-based polling and gets called at the beginning of each\n  // poll.\n  if (options._testOnlyPollCallback) {\n    self._testOnlyPollCallback = options._testOnlyPollCallback;\n  } else {\n    var intervalHandle = Meteor.setInterval(\n      _.bind(self._ensurePollIsScheduled, self), 10 * 1000);\n    self._stopCallbacks.push(function () {\n      Meteor.clearInterval(intervalHandle);\n    });\n  }\n\n  // Make sure we actually poll soon!\n  self._unthrottledEnsurePollIsScheduled();\n\n  Package.facts && Package.facts.Facts.incrementServerFact(\n    \"mongo-livedata\", \"observe-drivers-polling\", 1);\n};\n\n_.extend(PollingObserveDriver.prototype, {\n  // This is always called through _.throttle (except once at startup).\n  _unthrottledEnsurePollIsScheduled: function () {\n    var self = this;\n    if (self._pollsScheduledButNotStarted > 0)\n      return;\n    ++self._pollsScheduledButNotStarted;\n    self._taskQueue.queueTask(function () {\n      self._pollMongo();\n    });\n  },\n\n  // test-only interface for controlling polling.\n  //\n  // _suspendPolling blocks until any currently running and scheduled polls are\n  // done, and prevents any further polls from being scheduled. (new\n  // ObserveHandles can be added and receive their initial added callbacks,\n  // though.)\n  //\n  // _resumePolling immediately polls, and allows further polls to occur.\n  _suspendPolling: function() {\n    var self = this;\n    // Pretend that there's another poll scheduled (which will prevent\n    // _ensurePollIsScheduled from queueing any more polls).\n    ++self._pollsScheduledButNotStarted;\n    // Now block until all currently running or scheduled polls are done.\n    self._taskQueue.runTask(function() {});\n\n    // Confirm that there is only one \"poll\" (the fake one we're pretending to\n    // have) scheduled.\n    if (self._pollsScheduledButNotStarted !== 1)\n      throw new Error(\"_pollsScheduledButNotStarted is \" +\n                      self._pollsScheduledButNotStarted);\n  },\n  _resumePolling: function() {\n    var self = this;\n    // We should be in the same state as in the end of _suspendPolling.\n    if (self._pollsScheduledButNotStarted !== 1)\n      throw new Error(\"_pollsScheduledButNotStarted is \" +\n                      self._pollsScheduledButNotStarted);\n    // Run a poll synchronously (which will counteract the\n    // ++_pollsScheduledButNotStarted from _suspendPolling).\n    self._taskQueue.runTask(function () {\n      self._pollMongo();\n    });\n  },\n\n  _pollMongo: function () {\n    var self = this;\n    --self._pollsScheduledButNotStarted;\n\n    if (self._stopped)\n      return;\n\n    var first = false;\n    var oldResults = self._results;\n    if (!oldResults) {\n      first = true;\n      // XXX maybe use OrderedDict instead?\n      oldResults = self._ordered ? [] : new LocalCollection._IdMap;\n    }\n\n    self._testOnlyPollCallback && self._testOnlyPollCallback();\n\n    // Save the list of pending writes which this round will commit.\n    var writesForCycle = self._pendingWrites;\n    self._pendingWrites = [];\n\n    // Get the new query results. (This yields.)\n    try {\n      var newResults = self._synchronousCursor.getRawObjects(self._ordered);\n    } catch (e) {\n      if (first && typeof(e.code) === 'number') {\n        // This is an error document sent to us by mongod, not a connection\n        // error generated by the client. And we've never seen this query work\n        // successfully. Probably it's a bad selector or something, so we should\n        // NOT retry. Instead, we should halt the observe (which ends up calling\n        // `stop` on us).\n        self._multiplexer.queryError(\n          new Error(\n            \"Exception while polling query \" +\n              JSON.stringify(self._cursorDescription) + \": \" + e.message));\n        return;\n      }\n\n      // getRawObjects can throw if we're having trouble talking to the\n      // database.  That's fine --- we will repoll later anyway. But we should\n      // make sure not to lose track of this cycle's writes.\n      // (It also can throw if there's just something invalid about this query;\n      // unfortunately the ObserveDriver API doesn't provide a good way to\n      // \"cancel\" the observe from the inside in this case.\n      Array.prototype.push.apply(self._pendingWrites, writesForCycle);\n      Meteor._debug(\"Exception while polling query \" +\n                    JSON.stringify(self._cursorDescription) + \": \" + e.stack);\n      return;\n    }\n\n    // Run diffs.\n    if (!self._stopped) {\n      LocalCollection._diffQueryChanges(\n        self._ordered, oldResults, newResults, self._multiplexer);\n    }\n\n    // Signals the multiplexer to allow all observeChanges calls that share this\n    // multiplexer to return. (This happens asynchronously, via the\n    // multiplexer's queue.)\n    if (first)\n      self._multiplexer.ready();\n\n    // Replace self._results atomically.  (This assignment is what makes `first`\n    // stay through on the next cycle, so we've waited until after we've\n    // committed to ready-ing the multiplexer.)\n    self._results = newResults;\n\n    // Once the ObserveMultiplexer has processed everything we've done in this\n    // round, mark all the writes which existed before this call as\n    // commmitted. (If new writes have shown up in the meantime, there'll\n    // already be another _pollMongo task scheduled.)\n    self._multiplexer.onFlush(function () {\n      _.each(writesForCycle, function (w) {\n        w.committed();\n      });\n    });\n  },\n\n  stop: function () {\n    var self = this;\n    self._stopped = true;\n    _.each(self._stopCallbacks, function (c) { c(); });\n    // Release any write fences that are waiting on us.\n    _.each(self._pendingWrites, function (w) {\n      w.committed();\n    });\n    Package.facts && Package.facts.Facts.incrementServerFact(\n      \"mongo-livedata\", \"observe-drivers-polling\", -1);\n  }\n});\n","var Fiber = Npm.require('fibers');\nvar Future = Npm.require('fibers/future');\n\nvar PHASE = {\n  QUERYING: \"QUERYING\",\n  FETCHING: \"FETCHING\",\n  STEADY: \"STEADY\"\n};\n\n// Exception thrown by _needToPollQuery which unrolls the stack up to the\n// enclosing call to finishIfNeedToPollQuery.\nvar SwitchedToQuery = function () {};\nvar finishIfNeedToPollQuery = function (f) {\n  return function () {\n    try {\n      f.apply(this, arguments);\n    } catch (e) {\n      if (!(e instanceof SwitchedToQuery))\n        throw e;\n    }\n  };\n};\n\n// OplogObserveDriver is an alternative to PollingObserveDriver which follows\n// the Mongo operation log instead of just re-polling the query. It obeys the\n// same simple interface: constructing it starts sending observeChanges\n// callbacks (and a ready() invocation) to the ObserveMultiplexer, and you stop\n// it by calling the stop() method.\nOplogObserveDriver = function (options) {\n  var self = this;\n  self._usesOplog = true;  // tests look at this\n\n  self._cursorDescription = options.cursorDescription;\n  self._mongoHandle = options.mongoHandle;\n  self._multiplexer = options.multiplexer;\n\n  if (options.ordered) {\n    throw Error(\"OplogObserveDriver only supports unordered observeChanges\");\n  }\n\n  var sorter = options.sorter;\n  // We don't support $near and other geo-queries so it's OK to initialize the\n  // comparator only once in the constructor.\n  var comparator = sorter && sorter.getComparator();\n\n  if (options.cursorDescription.options.limit) {\n    // There are several properties ordered driver implements:\n    // - _limit is a positive number\n    // - _comparator is a function-comparator by which the query is ordered\n    // - _unpublishedBuffer is non-null Min/Max Heap,\n    //                      the empty buffer in STEADY phase implies that the\n    //                      everything that matches the queries selector fits\n    //                      into published set.\n    // - _published - Min Heap (also implements IdMap methods)\n\n    var heapOptions = { IdMap: LocalCollection._IdMap };\n    self._limit = self._cursorDescription.options.limit;\n    self._comparator = comparator;\n    self._sorter = sorter;\n    self._unpublishedBuffer = new MinMaxHeap(comparator, heapOptions);\n    // We need something that can find Max value in addition to IdMap interface\n    self._published = new MaxHeap(comparator, heapOptions);\n  } else {\n    self._limit = 0;\n    self._comparator = null;\n    self._sorter = null;\n    self._unpublishedBuffer = null;\n    self._published = new LocalCollection._IdMap;\n  }\n\n  // Indicates if it is safe to insert a new document at the end of the buffer\n  // for this query. i.e. it is known that there are no documents matching the\n  // selector those are not in published or buffer.\n  self._safeAppendToBuffer = false;\n\n  self._stopped = false;\n  self._stopHandles = [];\n\n  Package.facts && Package.facts.Facts.incrementServerFact(\n    \"mongo-livedata\", \"observe-drivers-oplog\", 1);\n\n  self._registerPhaseChange(PHASE.QUERYING);\n\n  var selector = self._cursorDescription.selector;\n  self._matcher = options.matcher;\n  var projection = self._cursorDescription.options.fields || {};\n  self._projectionFn = LocalCollection._compileProjection(projection);\n  // Projection function, result of combining important fields for selector and\n  // existing fields projection\n  self._sharedProjection = self._matcher.combineIntoProjection(projection);\n  if (sorter)\n    self._sharedProjection = sorter.combineIntoProjection(self._sharedProjection);\n  self._sharedProjectionFn = LocalCollection._compileProjection(\n    self._sharedProjection);\n\n  self._needToFetch = new LocalCollection._IdMap;\n  self._currentlyFetching = null;\n  self._fetchGeneration = 0;\n\n  self._requeryWhenDoneThisQuery = false;\n  self._writesToCommitWhenWeReachSteady = [];\n\n  // If the oplog handle tells us that it skipped some entries (because it got\n  // behind, say), re-poll.\n  self._stopHandles.push(self._mongoHandle._oplogHandle.onSkippedEntries(\n    finishIfNeedToPollQuery(function () {\n      self._needToPollQuery();\n    })\n  ));\n\n  forEachTrigger(self._cursorDescription, function (trigger) {\n    self._stopHandles.push(self._mongoHandle._oplogHandle.onOplogEntry(\n      trigger, function (notification) {\n        Meteor._noYieldsAllowed(finishIfNeedToPollQuery(function () {\n          var op = notification.op;\n          if (notification.dropCollection) {\n            // Note: this call is not allowed to block on anything (especially\n            // on waiting for oplog entries to catch up) because that will block\n            // onOplogEntry!\n            self._needToPollQuery();\n          } else {\n            // All other operators should be handled depending on phase\n            if (self._phase === PHASE.QUERYING)\n              self._handleOplogEntryQuerying(op);\n            else\n              self._handleOplogEntrySteadyOrFetching(op);\n          }\n        }));\n      }\n    ));\n  });\n\n  // XXX ordering w.r.t. everything else?\n  self._stopHandles.push(listenAll(\n    self._cursorDescription, function (notification) {\n      // If we're not in a write fence, we don't have to do anything.\n      var fence = DDPServer._CurrentWriteFence.get();\n      if (!fence)\n        return;\n      var write = fence.beginWrite();\n      // This write cannot complete until we've caught up to \"this point\" in the\n      // oplog, and then made it back to the steady state.\n      Meteor.defer(function () {\n        self._mongoHandle._oplogHandle.waitUntilCaughtUp();\n        if (self._stopped) {\n          // We're stopped, so just immediately commit.\n          write.committed();\n        } else if (self._phase === PHASE.STEADY) {\n          // Make sure that all of the callbacks have made it through the\n          // multiplexer and been delivered to ObserveHandles before committing\n          // writes.\n          self._multiplexer.onFlush(function () {\n            write.committed();\n          });\n        } else {\n          self._writesToCommitWhenWeReachSteady.push(write);\n        }\n      });\n    }\n  ));\n\n  // When Mongo fails over, we need to repoll the query, in case we processed an\n  // oplog entry that got rolled back.\n  self._stopHandles.push(self._mongoHandle._onFailover(finishIfNeedToPollQuery(\n    function () {\n      self._needToPollQuery();\n    })));\n\n  // Give _observeChanges a chance to add the new ObserveHandle to our\n  // multiplexer, so that the added calls get streamed.\n  Meteor.defer(finishIfNeedToPollQuery(function () {\n    self._runInitialQuery();\n  }));\n};\n\n_.extend(OplogObserveDriver.prototype, {\n  _addPublished: function (id, doc) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      var fields = _.clone(doc);\n      delete fields._id;\n      self._published.set(id, self._sharedProjectionFn(doc));\n      self._multiplexer.added(id, self._projectionFn(fields));\n\n      // After adding this document, the published set might be overflowed\n      // (exceeding capacity specified by limit). If so, push the maximum\n      // element to the buffer, we might want to save it in memory to reduce the\n      // amount of Mongo lookups in the future.\n      if (self._limit && self._published.size() > self._limit) {\n        // XXX in theory the size of published is no more than limit+1\n        if (self._published.size() !== self._limit + 1) {\n          throw new Error(\"After adding to published, \" +\n                          (self._published.size() - self._limit) +\n                          \" documents are overflowing the set\");\n        }\n\n        var overflowingDocId = self._published.maxElementId();\n        var overflowingDoc = self._published.get(overflowingDocId);\n\n        if (EJSON.equals(overflowingDocId, id)) {\n          throw new Error(\"The document just added is overflowing the published set\");\n        }\n\n        self._published.remove(overflowingDocId);\n        self._multiplexer.removed(overflowingDocId);\n        self._addBuffered(overflowingDocId, overflowingDoc);\n      }\n    });\n  },\n  _removePublished: function (id) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._published.remove(id);\n      self._multiplexer.removed(id);\n      if (! self._limit || self._published.size() === self._limit)\n        return;\n\n      if (self._published.size() > self._limit)\n        throw Error(\"self._published got too big\");\n\n      // OK, we are publishing less than the limit. Maybe we should look in the\n      // buffer to find the next element past what we were publishing before.\n\n      if (!self._unpublishedBuffer.empty()) {\n        // There's something in the buffer; move the first thing in it to\n        // _published.\n        var newDocId = self._unpublishedBuffer.minElementId();\n        var newDoc = self._unpublishedBuffer.get(newDocId);\n        self._removeBuffered(newDocId);\n        self._addPublished(newDocId, newDoc);\n        return;\n      }\n\n      // There's nothing in the buffer.  This could mean one of a few things.\n\n      // (a) We could be in the middle of re-running the query (specifically, we\n      // could be in _publishNewResults). In that case, _unpublishedBuffer is\n      // empty because we clear it at the beginning of _publishNewResults. In\n      // this case, our caller already knows the entire answer to the query and\n      // we don't need to do anything fancy here.  Just return.\n      if (self._phase === PHASE.QUERYING)\n        return;\n\n      // (b) We're pretty confident that the union of _published and\n      // _unpublishedBuffer contain all documents that match selector. Because\n      // _unpublishedBuffer is empty, that means we're confident that _published\n      // contains all documents that match selector. So we have nothing to do.\n      if (self._safeAppendToBuffer)\n        return;\n\n      // (c) Maybe there are other documents out there that should be in our\n      // buffer. But in that case, when we emptied _unpublishedBuffer in\n      // _removeBuffered, we should have called _needToPollQuery, which will\n      // either put something in _unpublishedBuffer or set _safeAppendToBuffer\n      // (or both), and it will put us in QUERYING for that whole time. So in\n      // fact, we shouldn't be able to get here.\n\n      throw new Error(\"Buffer inexplicably empty\");\n    });\n  },\n  _changePublished: function (id, oldDoc, newDoc) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._published.set(id, self._sharedProjectionFn(newDoc));\n      var projectedNew = self._projectionFn(newDoc);\n      var projectedOld = self._projectionFn(oldDoc);\n      var changed = LocalCollection._makeChangedFields(\n        projectedNew, projectedOld);\n      if (!_.isEmpty(changed))\n        self._multiplexer.changed(id, changed);\n    });\n  },\n  _addBuffered: function (id, doc) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._unpublishedBuffer.set(id, self._sharedProjectionFn(doc));\n\n      // If something is overflowing the buffer, we just remove it from cache\n      if (self._unpublishedBuffer.size() > self._limit) {\n        var maxBufferedId = self._unpublishedBuffer.maxElementId();\n\n        self._unpublishedBuffer.remove(maxBufferedId);\n\n        // Since something matching is removed from cache (both published set and\n        // buffer), set flag to false\n        self._safeAppendToBuffer = false;\n      }\n    });\n  },\n  // Is called either to remove the doc completely from matching set or to move\n  // it to the published set later.\n  _removeBuffered: function (id) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._unpublishedBuffer.remove(id);\n      // To keep the contract \"buffer is never empty in STEADY phase unless the\n      // everything matching fits into published\" true, we poll everything as\n      // soon as we see the buffer becoming empty.\n      if (! self._unpublishedBuffer.size() && ! self._safeAppendToBuffer)\n        self._needToPollQuery();\n    });\n  },\n  // Called when a document has joined the \"Matching\" results set.\n  // Takes responsibility of keeping _unpublishedBuffer in sync with _published\n  // and the effect of limit enforced.\n  _addMatching: function (doc) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      var id = doc._id;\n      if (self._published.has(id))\n        throw Error(\"tried to add something already published \" + id);\n      if (self._limit && self._unpublishedBuffer.has(id))\n        throw Error(\"tried to add something already existed in buffer \" + id);\n\n      var limit = self._limit;\n      var comparator = self._comparator;\n      var maxPublished = (limit && self._published.size() > 0) ?\n        self._published.get(self._published.maxElementId()) : null;\n      var maxBuffered = (limit && self._unpublishedBuffer.size() > 0)\n        ? self._unpublishedBuffer.get(self._unpublishedBuffer.maxElementId())\n        : null;\n      // The query is unlimited or didn't publish enough documents yet or the\n      // new document would fit into published set pushing the maximum element\n      // out, then we need to publish the doc.\n      var toPublish = ! limit || self._published.size() < limit ||\n        comparator(doc, maxPublished) < 0;\n\n      // Otherwise we might need to buffer it (only in case of limited query).\n      // Buffering is allowed if the buffer is not filled up yet and all\n      // matching docs are either in the published set or in the buffer.\n      var canAppendToBuffer = !toPublish && self._safeAppendToBuffer &&\n        self._unpublishedBuffer.size() < limit;\n\n      // Or if it is small enough to be safely inserted to the middle or the\n      // beginning of the buffer.\n      var canInsertIntoBuffer = !toPublish && maxBuffered &&\n        comparator(doc, maxBuffered) <= 0;\n\n      var toBuffer = canAppendToBuffer || canInsertIntoBuffer;\n\n      if (toPublish) {\n        self._addPublished(id, doc);\n      } else if (toBuffer) {\n        self._addBuffered(id, doc);\n      } else {\n        // dropping it and not saving to the cache\n        self._safeAppendToBuffer = false;\n      }\n    });\n  },\n  // Called when a document leaves the \"Matching\" results set.\n  // Takes responsibility of keeping _unpublishedBuffer in sync with _published\n  // and the effect of limit enforced.\n  _removeMatching: function (id) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      if (! self._published.has(id) && ! self._limit)\n        throw Error(\"tried to remove something matching but not cached \" + id);\n\n      if (self._published.has(id)) {\n        self._removePublished(id);\n      } else if (self._unpublishedBuffer.has(id)) {\n        self._removeBuffered(id);\n      }\n    });\n  },\n  _handleDoc: function (id, newDoc) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      var matchesNow = newDoc && self._matcher.documentMatches(newDoc).result;\n\n      var publishedBefore = self._published.has(id);\n      var bufferedBefore = self._limit && self._unpublishedBuffer.has(id);\n      var cachedBefore = publishedBefore || bufferedBefore;\n\n      if (matchesNow && !cachedBefore) {\n        self._addMatching(newDoc);\n      } else if (cachedBefore && !matchesNow) {\n        self._removeMatching(id);\n      } else if (cachedBefore && matchesNow) {\n        var oldDoc = self._published.get(id);\n        var comparator = self._comparator;\n        var minBuffered = self._limit && self._unpublishedBuffer.size() &&\n          self._unpublishedBuffer.get(self._unpublishedBuffer.minElementId());\n\n        if (publishedBefore) {\n          // Unlimited case where the document stays in published once it\n          // matches or the case when we don't have enough matching docs to\n          // publish or the changed but matching doc will stay in published\n          // anyways.\n          //\n          // XXX: We rely on the emptiness of buffer. Be sure to maintain the\n          // fact that buffer can't be empty if there are matching documents not\n          // published. Notably, we don't want to schedule repoll and continue\n          // relying on this property.\n          var staysInPublished = ! self._limit ||\n            self._unpublishedBuffer.size() === 0 ||\n            comparator(newDoc, minBuffered) <= 0;\n\n          if (staysInPublished) {\n            self._changePublished(id, oldDoc, newDoc);\n          } else {\n            // after the change doc doesn't stay in the published, remove it\n            self._removePublished(id);\n            // but it can move into buffered now, check it\n            var maxBuffered = self._unpublishedBuffer.get(\n              self._unpublishedBuffer.maxElementId());\n\n            var toBuffer = self._safeAppendToBuffer ||\n                  (maxBuffered && comparator(newDoc, maxBuffered) <= 0);\n\n            if (toBuffer) {\n              self._addBuffered(id, newDoc);\n            } else {\n              // Throw away from both published set and buffer\n              self._safeAppendToBuffer = false;\n            }\n          }\n        } else if (bufferedBefore) {\n          oldDoc = self._unpublishedBuffer.get(id);\n          // remove the old version manually instead of using _removeBuffered so\n          // we don't trigger the querying immediately.  if we end this block\n          // with the buffer empty, we will need to trigger the query poll\n          // manually too.\n          self._unpublishedBuffer.remove(id);\n\n          var maxPublished = self._published.get(\n            self._published.maxElementId());\n          var maxBuffered = self._unpublishedBuffer.size() &&\n                self._unpublishedBuffer.get(\n                  self._unpublishedBuffer.maxElementId());\n\n          // the buffered doc was updated, it could move to published\n          var toPublish = comparator(newDoc, maxPublished) < 0;\n\n          // or stays in buffer even after the change\n          var staysInBuffer = (! toPublish && self._safeAppendToBuffer) ||\n                (!toPublish && maxBuffered &&\n                 comparator(newDoc, maxBuffered) <= 0);\n\n          if (toPublish) {\n            self._addPublished(id, newDoc);\n          } else if (staysInBuffer) {\n            // stays in buffer but changes\n            self._unpublishedBuffer.set(id, newDoc);\n          } else {\n            // Throw away from both published set and buffer\n            self._safeAppendToBuffer = false;\n            // Normally this check would have been done in _removeBuffered but\n            // we didn't use it, so we need to do it ourself now.\n            if (! self._unpublishedBuffer.size()) {\n              self._needToPollQuery();\n            }\n          }\n        } else {\n          throw new Error(\"cachedBefore implies either of publishedBefore or bufferedBefore is true.\");\n        }\n      }\n    });\n  },\n  _fetchModifiedDocuments: function () {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._registerPhaseChange(PHASE.FETCHING);\n      // Defer, because nothing called from the oplog entry handler may yield,\n      // but fetch() yields.\n      Meteor.defer(finishIfNeedToPollQuery(function () {\n        while (!self._stopped && !self._needToFetch.empty()) {\n          if (self._phase === PHASE.QUERYING) {\n            // While fetching, we decided to go into QUERYING mode, and then we\n            // saw another oplog entry, so _needToFetch is not empty. But we\n            // shouldn't fetch these documents until AFTER the query is done.\n            break;\n          }\n\n          // Being in steady phase here would be surprising.\n          if (self._phase !== PHASE.FETCHING)\n            throw new Error(\"phase in fetchModifiedDocuments: \" + self._phase);\n\n          self._currentlyFetching = self._needToFetch;\n          var thisGeneration = ++self._fetchGeneration;\n          self._needToFetch = new LocalCollection._IdMap;\n          var waiting = 0;\n          var fut = new Future;\n          // This loop is safe, because _currentlyFetching will not be updated\n          // during this loop (in fact, it is never mutated).\n          self._currentlyFetching.forEach(function (cacheKey, id) {\n            waiting++;\n            self._mongoHandle._docFetcher.fetch(\n              self._cursorDescription.collectionName, id, cacheKey,\n              finishIfNeedToPollQuery(function (err, doc) {\n                try {\n                  if (err) {\n                    Meteor._debug(\"Got exception while fetching documents: \" +\n                                  err);\n                    // If we get an error from the fetcher (eg, trouble\n                    // connecting to Mongo), let's just abandon the fetch phase\n                    // altogether and fall back to polling. It's not like we're\n                    // getting live updates anyway.\n                    if (self._phase !== PHASE.QUERYING) {\n                      self._needToPollQuery();\n                    }\n                  } else if (!self._stopped && self._phase === PHASE.FETCHING\n                             && self._fetchGeneration === thisGeneration) {\n                    // We re-check the generation in case we've had an explicit\n                    // _pollQuery call (eg, in another fiber) which should\n                    // effectively cancel this round of fetches.  (_pollQuery\n                    // increments the generation.)\n                    self._handleDoc(id, doc);\n                  }\n                } finally {\n                  waiting--;\n                  // Because fetch() never calls its callback synchronously,\n                  // this is safe (ie, we won't call fut.return() before the\n                  // forEach is done).\n                  if (waiting === 0)\n                    fut.return();\n                }\n              }));\n          });\n          fut.wait();\n          // Exit now if we've had a _pollQuery call (here or in another fiber).\n          if (self._phase === PHASE.QUERYING)\n            return;\n          self._currentlyFetching = null;\n        }\n        // We're done fetching, so we can be steady, unless we've had a\n        // _pollQuery call (here or in another fiber).\n        if (self._phase !== PHASE.QUERYING)\n          self._beSteady();\n      }));\n    });\n  },\n  _beSteady: function () {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._registerPhaseChange(PHASE.STEADY);\n      var writes = self._writesToCommitWhenWeReachSteady;\n      self._writesToCommitWhenWeReachSteady = [];\n      self._multiplexer.onFlush(function () {\n        _.each(writes, function (w) {\n          w.committed();\n        });\n      });\n    });\n  },\n  _handleOplogEntryQuerying: function (op) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      self._needToFetch.set(idForOp(op), op.ts.toString());\n    });\n  },\n  _handleOplogEntrySteadyOrFetching: function (op) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      var id = idForOp(op);\n      // If we're already fetching this one, or about to, we can't optimize;\n      // make sure that we fetch it again if necessary.\n      if (self._phase === PHASE.FETCHING &&\n          ((self._currentlyFetching && self._currentlyFetching.has(id)) ||\n           self._needToFetch.has(id))) {\n        self._needToFetch.set(id, op.ts.toString());\n        return;\n      }\n\n      if (op.op === 'd') {\n        if (self._published.has(id) ||\n            (self._limit && self._unpublishedBuffer.has(id)))\n          self._removeMatching(id);\n      } else if (op.op === 'i') {\n        if (self._published.has(id))\n          throw new Error(\"insert found for already-existing ID in published\");\n        if (self._unpublishedBuffer && self._unpublishedBuffer.has(id))\n          throw new Error(\"insert found for already-existing ID in buffer\");\n\n        // XXX what if selector yields?  for now it can't but later it could\n        // have $where\n        if (self._matcher.documentMatches(op.o).result)\n          self._addMatching(op.o);\n      } else if (op.op === 'u') {\n        // Is this a modifier ($set/$unset, which may require us to poll the\n        // database to figure out if the whole document matches the selector) or\n        // a replacement (in which case we can just directly re-evaluate the\n        // selector)?\n        var isReplace = !_.has(op.o, '$set') && !_.has(op.o, '$unset');\n        // If this modifier modifies something inside an EJSON custom type (ie,\n        // anything with EJSON$), then we can't try to use\n        // LocalCollection._modify, since that just mutates the EJSON encoding,\n        // not the actual object.\n        var canDirectlyModifyDoc =\n          !isReplace && modifierCanBeDirectlyApplied(op.o);\n\n        var publishedBefore = self._published.has(id);\n        var bufferedBefore = self._limit && self._unpublishedBuffer.has(id);\n\n        if (isReplace) {\n          self._handleDoc(id, _.extend({_id: id}, op.o));\n        } else if ((publishedBefore || bufferedBefore) &&\n                   canDirectlyModifyDoc) {\n          // Oh great, we actually know what the document is, so we can apply\n          // this directly.\n          var newDoc = self._published.has(id)\n            ? self._published.get(id) : self._unpublishedBuffer.get(id);\n          newDoc = EJSON.clone(newDoc);\n\n          newDoc._id = id;\n          try {\n            LocalCollection._modify(newDoc, op.o);\n          } catch (e) {\n            if (e.name !== \"MinimongoError\")\n              throw e;\n            // We didn't understand the modifier.  Re-fetch.\n            self._needToFetch.set(id, op.ts.toString());\n            if (self._phase === PHASE.STEADY) {\n              self._fetchModifiedDocuments();\n            }\n            return;\n          }\n          self._handleDoc(id, self._sharedProjectionFn(newDoc));\n        } else if (!canDirectlyModifyDoc ||\n                   self._matcher.canBecomeTrueByModifier(op.o) ||\n                   (self._sorter && self._sorter.affectedByModifier(op.o))) {\n          self._needToFetch.set(id, op.ts.toString());\n          if (self._phase === PHASE.STEADY)\n            self._fetchModifiedDocuments();\n        }\n      } else {\n        throw Error(\"XXX SURPRISING OPERATION: \" + op);\n      }\n    });\n  },\n  // Yields!\n  _runInitialQuery: function () {\n    var self = this;\n    if (self._stopped)\n      throw new Error(\"oplog stopped surprisingly early\");\n\n    self._runQuery({initial: true});  // yields\n\n    if (self._stopped)\n      return;  // can happen on queryError\n\n    // Allow observeChanges calls to return. (After this, it's possible for\n    // stop() to be called.)\n    self._multiplexer.ready();\n\n    self._doneQuerying();  // yields\n  },\n\n  // In various circumstances, we may just want to stop processing the oplog and\n  // re-run the initial query, just as if we were a PollingObserveDriver.\n  //\n  // This function may not block, because it is called from an oplog entry\n  // handler.\n  //\n  // XXX We should call this when we detect that we've been in FETCHING for \"too\n  // long\".\n  //\n  // XXX We should call this when we detect Mongo failover (since that might\n  // mean that some of the oplog entries we have processed have been rolled\n  // back). The Node Mongo driver is in the middle of a bunch of huge\n  // refactorings, including the way that it notifies you when primary\n  // changes. Will put off implementing this until driver 1.4 is out.\n  _pollQuery: function () {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      if (self._stopped)\n        return;\n\n      // Yay, we get to forget about all the things we thought we had to fetch.\n      self._needToFetch = new LocalCollection._IdMap;\n      self._currentlyFetching = null;\n      ++self._fetchGeneration;  // ignore any in-flight fetches\n      self._registerPhaseChange(PHASE.QUERYING);\n\n      // Defer so that we don't yield.  We don't need finishIfNeedToPollQuery\n      // here because SwitchedToQuery is not thrown in QUERYING mode.\n      Meteor.defer(function () {\n        self._runQuery();\n        self._doneQuerying();\n      });\n    });\n  },\n\n  // Yields!\n  _runQuery: function (options) {\n    var self = this;\n    options = options || {};\n    var newResults, newBuffer;\n\n    // This while loop is just to retry failures.\n    while (true) {\n      // If we've been stopped, we don't have to run anything any more.\n      if (self._stopped)\n        return;\n\n      newResults = new LocalCollection._IdMap;\n      newBuffer = new LocalCollection._IdMap;\n\n      // Query 2x documents as the half excluded from the original query will go\n      // into unpublished buffer to reduce additional Mongo lookups in cases\n      // when documents are removed from the published set and need a\n      // replacement.\n      // XXX needs more thought on non-zero skip\n      // XXX 2 is a \"magic number\" meaning there is an extra chunk of docs for\n      // buffer if such is needed.\n      var cursor = self._cursorForQuery({ limit: self._limit * 2 });\n      try {\n        cursor.forEach(function (doc, i) {  // yields\n          if (!self._limit || i < self._limit)\n            newResults.set(doc._id, doc);\n          else\n            newBuffer.set(doc._id, doc);\n        });\n        break;\n      } catch (e) {\n        if (options.initial && typeof(e.code) === 'number') {\n          // This is an error document sent to us by mongod, not a connection\n          // error generated by the client. And we've never seen this query work\n          // successfully. Probably it's a bad selector or something, so we\n          // should NOT retry. Instead, we should halt the observe (which ends\n          // up calling `stop` on us).\n          self._multiplexer.queryError(e);\n          return;\n        }\n\n        // During failover (eg) if we get an exception we should log and retry\n        // instead of crashing.\n        Meteor._debug(\"Got exception while polling query: \" + e);\n        Meteor._sleepForMs(100);\n      }\n    }\n\n    if (self._stopped)\n      return;\n\n    self._publishNewResults(newResults, newBuffer);\n  },\n\n  // Transitions to QUERYING and runs another query, or (if already in QUERYING)\n  // ensures that we will query again later.\n  //\n  // This function may not block, because it is called from an oplog entry\n  // handler. However, if we were not already in the QUERYING phase, it throws\n  // an exception that is caught by the closest surrounding\n  // finishIfNeedToPollQuery call; this ensures that we don't continue running\n  // close that was designed for another phase inside PHASE.QUERYING.\n  //\n  // (It's also necessary whenever logic in this file yields to check that other\n  // phases haven't put us into QUERYING mode, though; eg,\n  // _fetchModifiedDocuments does this.)\n  _needToPollQuery: function () {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      if (self._stopped)\n        return;\n\n      // If we're not already in the middle of a query, we can query now\n      // (possibly pausing FETCHING).\n      if (self._phase !== PHASE.QUERYING) {\n        self._pollQuery();\n        throw new SwitchedToQuery;\n      }\n\n      // We're currently in QUERYING. Set a flag to ensure that we run another\n      // query when we're done.\n      self._requeryWhenDoneThisQuery = true;\n    });\n  },\n\n  // Yields!\n  _doneQuerying: function () {\n    var self = this;\n\n    if (self._stopped)\n      return;\n    self._mongoHandle._oplogHandle.waitUntilCaughtUp();  // yields\n    if (self._stopped)\n      return;\n    if (self._phase !== PHASE.QUERYING)\n      throw Error(\"Phase unexpectedly \" + self._phase);\n\n    Meteor._noYieldsAllowed(function () {\n      if (self._requeryWhenDoneThisQuery) {\n        self._requeryWhenDoneThisQuery = false;\n        self._pollQuery();\n      } else if (self._needToFetch.empty()) {\n        self._beSteady();\n      } else {\n        self._fetchModifiedDocuments();\n      }\n    });\n  },\n\n  _cursorForQuery: function (optionsOverwrite) {\n    var self = this;\n    return Meteor._noYieldsAllowed(function () {\n      // The query we run is almost the same as the cursor we are observing,\n      // with a few changes. We need to read all the fields that are relevant to\n      // the selector, not just the fields we are going to publish (that's the\n      // \"shared\" projection). And we don't want to apply any transform in the\n      // cursor, because observeChanges shouldn't use the transform.\n      var options = _.clone(self._cursorDescription.options);\n\n      // Allow the caller to modify the options. Useful to specify different\n      // skip and limit values.\n      _.extend(options, optionsOverwrite);\n\n      options.fields = self._sharedProjection;\n      delete options.transform;\n      // We are NOT deep cloning fields or selector here, which should be OK.\n      var description = new CursorDescription(\n        self._cursorDescription.collectionName,\n        self._cursorDescription.selector,\n        options);\n      return new Cursor(self._mongoHandle, description);\n    });\n  },\n\n\n  // Replace self._published with newResults (both are IdMaps), invoking observe\n  // callbacks on the multiplexer.\n  // Replace self._unpublishedBuffer with newBuffer.\n  //\n  // XXX This is very similar to LocalCollection._diffQueryUnorderedChanges. We\n  // should really: (a) Unify IdMap and OrderedDict into Unordered/OrderedDict\n  // (b) Rewrite diff.js to use these classes instead of arrays and objects.\n  _publishNewResults: function (newResults, newBuffer) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n\n      // If the query is limited and there is a buffer, shut down so it doesn't\n      // stay in a way.\n      if (self._limit) {\n        self._unpublishedBuffer.clear();\n      }\n\n      // First remove anything that's gone. Be careful not to modify\n      // self._published while iterating over it.\n      var idsToRemove = [];\n      self._published.forEach(function (doc, id) {\n        if (!newResults.has(id))\n          idsToRemove.push(id);\n      });\n      _.each(idsToRemove, function (id) {\n        self._removePublished(id);\n      });\n\n      // Now do adds and changes.\n      // If self has a buffer and limit, the new fetched result will be\n      // limited correctly as the query has sort specifier.\n      newResults.forEach(function (doc, id) {\n        self._handleDoc(id, doc);\n      });\n\n      // Sanity-check that everything we tried to put into _published ended up\n      // there.\n      // XXX if this is slow, remove it later\n      if (self._published.size() !== newResults.size()) {\n        throw Error(\n          \"The Mongo server and the Meteor query disagree on how \" +\n            \"many documents match your query. Maybe it is hitting a Mongo \" +\n            \"edge case? The query is: \" +\n            EJSON.stringify(self._cursorDescription.selector));\n      }\n      self._published.forEach(function (doc, id) {\n        if (!newResults.has(id))\n          throw Error(\"_published has a doc that newResults doesn't; \" + id);\n      });\n\n      // Finally, replace the buffer\n      newBuffer.forEach(function (doc, id) {\n        self._addBuffered(id, doc);\n      });\n\n      self._safeAppendToBuffer = newBuffer.size() < self._limit;\n    });\n  },\n\n  // This stop function is invoked from the onStop of the ObserveMultiplexer, so\n  // it shouldn't actually be possible to call it until the multiplexer is\n  // ready.\n  //\n  // It's important to check self._stopped after every call in this file that\n  // can yield!\n  stop: function () {\n    var self = this;\n    if (self._stopped)\n      return;\n    self._stopped = true;\n    _.each(self._stopHandles, function (handle) {\n      handle.stop();\n    });\n\n    // Note: we *don't* use multiplexer.onFlush here because this stop\n    // callback is actually invoked by the multiplexer itself when it has\n    // determined that there are no handles left. So nothing is actually going\n    // to get flushed (and it's probably not valid to call methods on the\n    // dying multiplexer).\n    _.each(self._writesToCommitWhenWeReachSteady, function (w) {\n      w.committed();  // maybe yields?\n    });\n    self._writesToCommitWhenWeReachSteady = null;\n\n    // Proactively drop references to potentially big things.\n    self._published = null;\n    self._unpublishedBuffer = null;\n    self._needToFetch = null;\n    self._currentlyFetching = null;\n    self._oplogEntryHandle = null;\n    self._listenersHandle = null;\n\n    Package.facts && Package.facts.Facts.incrementServerFact(\n      \"mongo-livedata\", \"observe-drivers-oplog\", -1);\n  },\n\n  _registerPhaseChange: function (phase) {\n    var self = this;\n    Meteor._noYieldsAllowed(function () {\n      var now = new Date;\n\n      if (self._phase) {\n        var timeDiff = now - self._phaseStartTime;\n        Package.facts && Package.facts.Facts.incrementServerFact(\n          \"mongo-livedata\", \"time-spent-in-\" + self._phase + \"-phase\", timeDiff);\n      }\n\n      self._phase = phase;\n      self._phaseStartTime = now;\n    });\n  }\n});\n\n// Does our oplog tailing code support this cursor? For now, we are being very\n// conservative and allowing only simple queries with simple options.\n// (This is a \"static method\".)\nOplogObserveDriver.cursorSupported = function (cursorDescription, matcher) {\n  // First, check the options.\n  var options = cursorDescription.options;\n\n  // Did the user say no explicitly?\n  if (options._disableOplog)\n    return false;\n\n  // skip is not supported: to support it we would need to keep track of all\n  // \"skipped\" documents or at least their ids.\n  // limit w/o a sort specifier is not supported: current implementation needs a\n  // deterministic way to order documents.\n  if (options.skip || (options.limit && !options.sort)) return false;\n\n  // If a fields projection option is given check if it is supported by\n  // minimongo (some operators are not supported).\n  if (options.fields) {\n    try {\n      LocalCollection._checkSupportedProjection(options.fields);\n    } catch (e) {\n      if (e.name === \"MinimongoError\")\n        return false;\n      else\n        throw e;\n    }\n  }\n\n  // We don't allow the following selectors:\n  //   - $where (not confident that we provide the same JS environment\n  //             as Mongo, and can yield!)\n  //   - $near (has \"interesting\" properties in MongoDB, like the possibility\n  //            of returning an ID multiple times, though even polling maybe\n  //            have a bug there)\n  //           XXX: once we support it, we would need to think more on how we\n  //           initialize the comparators when we create the driver.\n  return !matcher.hasWhere() && !matcher.hasGeoQuery();\n};\n\nvar modifierCanBeDirectlyApplied = function (modifier) {\n  return _.all(modifier, function (fields, operation) {\n    return _.all(fields, function (value, field) {\n      return !/EJSON\\$/.test(field);\n    });\n  });\n};\n\nMongoInternals.OplogObserveDriver = OplogObserveDriver;\n","LocalCollectionDriver = function () {\n  var self = this;\n  self.noConnCollections = {};\n};\n\nvar ensureCollection = function (name, collections) {\n  if (!(name in collections))\n    collections[name] = new LocalCollection(name);\n  return collections[name];\n};\n\n_.extend(LocalCollectionDriver.prototype, {\n  open: function (name, conn) {\n    var self = this;\n    if (!name)\n      return new LocalCollection;\n    if (! conn) {\n      return ensureCollection(name, self.noConnCollections);\n    }\n    if (! conn._mongo_livedata_collections)\n      conn._mongo_livedata_collections = {};\n    // XXX is there a way to keep track of a connection's collections without\n    // dangling it off the connection object?\n    return ensureCollection(name, conn._mongo_livedata_collections);\n  }\n});\n\n// singleton\nLocalCollectionDriver = new LocalCollectionDriver;\n","MongoInternals.RemoteCollectionDriver = function (\n  mongo_url, options) {\n  var self = this;\n  self.mongo = new MongoConnection(mongo_url, options);\n};\n\n_.extend(MongoInternals.RemoteCollectionDriver.prototype, {\n  open: function (name) {\n    var self = this;\n    var ret = {};\n    _.each(\n      ['find', 'findOne', 'insert', 'update', 'upsert',\n       'remove', '_ensureIndex', '_dropIndex', '_createCappedCollection',\n       'dropCollection', 'rawCollection'],\n      function (m) {\n        ret[m] = _.bind(self.mongo[m], self.mongo, name);\n      });\n    return ret;\n  }\n});\n\n\n// Create the singleton RemoteCollectionDriver only on demand, so we\n// only require Mongo configuration if it's actually used (eg, not if\n// you're only trying to receive data from a remote DDP server.)\nMongoInternals.defaultRemoteCollectionDriver = _.once(function () {\n  var connectionOptions = {};\n\n  var mongoUrl = process.env.MONGO_URL;\n\n  if (process.env.MONGO_OPLOG_URL) {\n    connectionOptions.oplogUrl = process.env.MONGO_OPLOG_URL;\n  }\n\n  if (! mongoUrl)\n    throw new Error(\"MONGO_URL must be set in environment\");\n\n  return new MongoInternals.RemoteCollectionDriver(mongoUrl, connectionOptions);\n});\n","// options.connection, if given, is a LivedataClient or LivedataServer\n// XXX presently there is no way to destroy/clean up a Collection\n\n/**\n * @summary Namespace for MongoDB-related items\n * @namespace\n */\nMongo = {};\n\n/**\n * @summary Constructor for a Collection\n * @locus Anywhere\n * @instancename collection\n * @class\n * @param {String} name The name of the collection.  If null, creates an unmanaged (unsynchronized) local collection.\n * @param {Object} [options]\n * @param {Object} options.connection The server connection that will manage this collection. Uses the default connection if not specified.  Pass the return value of calling [`DDP.connect`](#ddp_connect) to specify a different server. Pass `null` to specify no connection. Unmanaged (`name` is null) collections cannot specify a connection.\n * @param {String} options.idGeneration The method of generating the `_id` fields of new documents in this collection.  Possible values:\n\n - **`'STRING'`**: random strings\n - **`'MONGO'`**:  random [`Mongo.ObjectID`](#mongo_object_id) values\n\nThe default id generation technique is `'STRING'`.\n * @param {Function} options.transform An optional transformation function. Documents will be passed through this function before being returned from `fetch` or `findOne`, and before being passed to callbacks of `observe`, `map`, `forEach`, `allow`, and `deny`. Transforms are *not* applied for the callbacks of `observeChanges` or to cursors returned from publish functions.\n */\nMongo.Collection = function (name, options) {\n  var self = this;\n  if (! (self instanceof Mongo.Collection))\n    throw new Error('use \"new\" to construct a Mongo.Collection');\n\n  if (!name && (name !== null)) {\n    Meteor._debug(\"Warning: creating anonymous collection. It will not be \" +\n                  \"saved or synchronized over the network. (Pass null for \" +\n                  \"the collection name to turn off this warning.)\");\n    name = null;\n  }\n\n  if (name !== null && typeof name !== \"string\") {\n    throw new Error(\n      \"First argument to new Mongo.Collection must be a string or null\");\n  }\n\n  if (options && options.methods) {\n    // Backwards compatibility hack with original signature (which passed\n    // \"connection\" directly instead of in options. (Connections must have a \"methods\"\n    // method.)\n    // XXX remove before 1.0\n    options = {connection: options};\n  }\n  // Backwards compatibility: \"connection\" used to be called \"manager\".\n  if (options && options.manager && !options.connection) {\n    options.connection = options.manager;\n  }\n  options = _.extend({\n    connection: undefined,\n    idGeneration: 'STRING',\n    transform: null,\n    _driver: undefined,\n    _preventAutopublish: false\n  }, options);\n\n  switch (options.idGeneration) {\n  case 'MONGO':\n    self._makeNewID = function () {\n      var src = name ? DDP.randomStream('/collection/' + name) : Random;\n      return new Mongo.ObjectID(src.hexString(24));\n    };\n    break;\n  case 'STRING':\n  default:\n    self._makeNewID = function () {\n      var src = name ? DDP.randomStream('/collection/' + name) : Random;\n      return src.id();\n    };\n    break;\n  }\n\n  self._transform = LocalCollection.wrapTransform(options.transform);\n\n  if (! name || options.connection === null)\n    // note: nameless collections never have a connection\n    self._connection = null;\n  else if (options.connection)\n    self._connection = options.connection;\n  else if (Meteor.isClient)\n    self._connection = Meteor.connection;\n  else\n    self._connection = Meteor.server;\n\n  if (!options._driver) {\n    // XXX This check assumes that webapp is loaded so that Meteor.server !==\n    // null. We should fully support the case of \"want to use a Mongo-backed\n    // collection from Node code without webapp\", but we don't yet.\n    // #MeteorServerNull\n    if (name && self._connection === Meteor.server &&\n        typeof MongoInternals !== \"undefined\" &&\n        MongoInternals.defaultRemoteCollectionDriver) {\n      options._driver = MongoInternals.defaultRemoteCollectionDriver();\n    } else {\n      options._driver = LocalCollectionDriver;\n    }\n  }\n\n  self._collection = options._driver.open(name, self._connection);\n  self._name = name;\n  self._driver = options._driver;\n\n  if (self._connection && self._connection.registerStore) {\n    // OK, we're going to be a slave, replicating some remote\n    // database, except possibly with some temporary divergence while\n    // we have unacknowledged RPC's.\n    var ok = self._connection.registerStore(name, {\n      // Called at the beginning of a batch of updates. batchSize is the number\n      // of update calls to expect.\n      //\n      // XXX This interface is pretty janky. reset probably ought to go back to\n      // being its own function, and callers shouldn't have to calculate\n      // batchSize. The optimization of not calling pause/remove should be\n      // delayed until later: the first call to update() should buffer its\n      // message, and then we can either directly apply it at endUpdate time if\n      // it was the only update, or do pauseObservers/apply/apply at the next\n      // update() if there's another one.\n      beginUpdate: function (batchSize, reset) {\n        // pause observers so users don't see flicker when updating several\n        // objects at once (including the post-reconnect reset-and-reapply\n        // stage), and so that a re-sorting of a query can take advantage of the\n        // full _diffQuery moved calculation instead of applying change one at a\n        // time.\n        if (batchSize > 1 || reset)\n          self._collection.pauseObservers();\n\n        if (reset)\n          self._collection.remove({});\n      },\n\n      // Apply an update.\n      // XXX better specify this interface (not in terms of a wire message)?\n      update: function (msg) {\n        var mongoId = LocalCollection._idParse(msg.id);\n        var doc = self._collection.findOne(mongoId);\n\n        // Is this a \"replace the whole doc\" message coming from the quiescence\n        // of method writes to an object? (Note that 'undefined' is a valid\n        // value meaning \"remove it\".)\n        if (msg.msg === 'replace') {\n          var replace = msg.replace;\n          if (!replace) {\n            if (doc)\n              self._collection.remove(mongoId);\n          } else if (!doc) {\n            self._collection.insert(replace);\n          } else {\n            // XXX check that replace has no $ ops\n            self._collection.update(mongoId, replace);\n          }\n          return;\n        } else if (msg.msg === 'added') {\n          if (doc) {\n            throw new Error(\"Expected not to find a document already present for an add\");\n          }\n          self._collection.insert(_.extend({_id: mongoId}, msg.fields));\n        } else if (msg.msg === 'removed') {\n          if (!doc)\n            throw new Error(\"Expected to find a document already present for removed\");\n          self._collection.remove(mongoId);\n        } else if (msg.msg === 'changed') {\n          if (!doc)\n            throw new Error(\"Expected to find a document to change\");\n          if (!_.isEmpty(msg.fields)) {\n            var modifier = {};\n            _.each(msg.fields, function (value, key) {\n              if (value === undefined) {\n                if (!modifier.$unset)\n                  modifier.$unset = {};\n                modifier.$unset[key] = 1;\n              } else {\n                if (!modifier.$set)\n                  modifier.$set = {};\n                modifier.$set[key] = value;\n              }\n            });\n            self._collection.update(mongoId, modifier);\n          }\n        } else {\n          throw new Error(\"I don't know how to deal with this message\");\n        }\n\n      },\n\n      // Called at the end of a batch of updates.\n      endUpdate: function () {\n        self._collection.resumeObservers();\n      },\n\n      // Called around method stub invocations to capture the original versions\n      // of modified documents.\n      saveOriginals: function () {\n        self._collection.saveOriginals();\n      },\n      retrieveOriginals: function () {\n        return self._collection.retrieveOriginals();\n      }\n    });\n\n    if (!ok)\n      throw new Error(\"There is already a collection named '\" + name + \"'\");\n  }\n\n  self._defineMutationMethods();\n\n  // autopublish\n  if (Package.autopublish && !options._preventAutopublish && self._connection\n      && self._connection.publish) {\n    self._connection.publish(null, function () {\n      return self.find();\n    }, {is_auto: true});\n  }\n};\n\n///\n/// Main collection API\n///\n\n\n_.extend(Mongo.Collection.prototype, {\n\n  _getFindSelector: function (args) {\n    if (args.length == 0)\n      return {};\n    else\n      return args[0];\n  },\n\n  _getFindOptions: function (args) {\n    var self = this;\n    if (args.length < 2) {\n      return { transform: self._transform };\n    } else {\n      check(args[1], Match.Optional(Match.ObjectIncluding({\n        fields: Match.Optional(Match.OneOf(Object, undefined)),\n        sort: Match.Optional(Match.OneOf(Object, Array, undefined)),\n        limit: Match.Optional(Match.OneOf(Number, undefined)),\n        skip: Match.Optional(Match.OneOf(Number, undefined))\n     })));\n\n      return _.extend({\n        transform: self._transform\n      }, args[1]);\n    }\n  },\n\n  /**\n   * @summary Find the documents in a collection that match the selector.\n   * @locus Anywhere\n   * @method find\n   * @memberOf Mongo.Collection\n   * @instance\n   * @param {MongoSelector} [selector] A query describing the documents to find\n   * @param {Object} [options]\n   * @param {MongoSortSpecifier} options.sort Sort order (default: natural order)\n   * @param {Number} options.skip Number of results to skip at the beginning\n   * @param {Number} options.limit Maximum number of results to return\n   * @param {MongoFieldSpecifier} options.fields Dictionary of fields to return or exclude.\n   * @param {Boolean} options.reactive (Client only) Default `true`; pass `false` to disable reactivity\n   * @param {Function} options.transform Overrides `transform` on the  [`Collection`](#collections) for this cursor.  Pass `null` to disable transformation.\n   * @returns {Mongo.Cursor}\n   */\n  find: function (/* selector, options */) {\n    // Collection.find() (return all docs) behaves differently\n    // from Collection.find(undefined) (return 0 docs).  so be\n    // careful about the length of arguments.\n    var self = this;\n    var argArray = _.toArray(arguments);\n    return self._collection.find(self._getFindSelector(argArray),\n                                 self._getFindOptions(argArray));\n  },\n\n  /**\n   * @summary Finds the first document that matches the selector, as ordered by sort and skip options.\n   * @locus Anywhere\n   * @method findOne\n   * @memberOf Mongo.Collection\n   * @instance\n   * @param {MongoSelector} [selector] A query describing the documents to find\n   * @param {Object} [options]\n   * @param {MongoSortSpecifier} options.sort Sort order (default: natural order)\n   * @param {Number} options.skip Number of results to skip at the beginning\n   * @param {MongoFieldSpecifier} options.fields Dictionary of fields to return or exclude.\n   * @param {Boolean} options.reactive (Client only) Default true; pass false to disable reactivity\n   * @param {Function} options.transform Overrides `transform` on the [`Collection`](#collections) for this cursor.  Pass `null` to disable transformation.\n   * @returns {Object}\n   */\n  findOne: function (/* selector, options */) {\n    var self = this;\n    var argArray = _.toArray(arguments);\n    return self._collection.findOne(self._getFindSelector(argArray),\n                                    self._getFindOptions(argArray));\n  }\n\n});\n\nMongo.Collection._publishCursor = function (cursor, sub, collection) {\n  var observeHandle = cursor.observeChanges({\n    added: function (id, fields) {\n      sub.added(collection, id, fields);\n    },\n    changed: function (id, fields) {\n      sub.changed(collection, id, fields);\n    },\n    removed: function (id) {\n      sub.removed(collection, id);\n    }\n  });\n\n  // We don't call sub.ready() here: it gets called in livedata_server, after\n  // possibly calling _publishCursor on multiple returned cursors.\n\n  // register stop callback (expects lambda w/ no args).\n  sub.onStop(function () {observeHandle.stop();});\n};\n\n// protect against dangerous selectors.  falsey and {_id: falsey} are both\n// likely programmer error, and not what you want, particularly for destructive\n// operations.  JS regexps don't serialize over DDP but can be trivially\n// replaced by $regex.\nMongo.Collection._rewriteSelector = function (selector) {\n  // shorthand -- scalars match _id\n  if (LocalCollection._selectorIsId(selector))\n    selector = {_id: selector};\n\n  if (!selector || (('_id' in selector) && !selector._id))\n    // can't match anything\n    return {_id: Random.id()};\n\n  var ret = {};\n  _.each(selector, function (value, key) {\n    // Mongo supports both {field: /foo/} and {field: {$regex: /foo/}}\n    if (value instanceof RegExp) {\n      ret[key] = convertRegexpToMongoSelector(value);\n    } else if (value && value.$regex instanceof RegExp) {\n      ret[key] = convertRegexpToMongoSelector(value.$regex);\n      // if value is {$regex: /foo/, $options: ...} then $options\n      // override the ones set on $regex.\n      if (value.$options !== undefined)\n        ret[key].$options = value.$options;\n    }\n    else if (_.contains(['$or','$and','$nor'], key)) {\n      // Translate lower levels of $and/$or/$nor\n      ret[key] = _.map(value, function (v) {\n        return Mongo.Collection._rewriteSelector(v);\n      });\n    } else {\n      ret[key] = value;\n    }\n  });\n  return ret;\n};\n\n// convert a JS RegExp object to a Mongo {$regex: ..., $options: ...}\n// selector\nvar convertRegexpToMongoSelector = function (regexp) {\n  check(regexp, RegExp); // safety belt\n\n  var selector = {$regex: regexp.source};\n  var regexOptions = '';\n  // JS RegExp objects support 'i', 'm', and 'g'. Mongo regex $options\n  // support 'i', 'm', 'x', and 's'. So we support 'i' and 'm' here.\n  if (regexp.ignoreCase)\n    regexOptions += 'i';\n  if (regexp.multiline)\n    regexOptions += 'm';\n  if (regexOptions)\n    selector.$options = regexOptions;\n\n  return selector;\n};\n\nvar throwIfSelectorIsNotId = function (selector, methodName) {\n  if (!LocalCollection._selectorIsIdPerhapsAsObject(selector)) {\n    throw new Meteor.Error(\n      403, \"Not permitted. Untrusted code may only \" + methodName +\n        \" documents by ID.\");\n  }\n};\n\n// 'insert' immediately returns the inserted document's new _id.\n// The others return values immediately if you are in a stub, an in-memory\n// unmanaged collection, or a mongo-backed collection and you don't pass a\n// callback. 'update' and 'remove' return the number of affected\n// documents. 'upsert' returns an object with keys 'numberAffected' and, if an\n// insert happened, 'insertedId'.\n//\n// Otherwise, the semantics are exactly like other methods: they take\n// a callback as an optional last argument; if no callback is\n// provided, they block until the operation is complete, and throw an\n// exception if it fails; if a callback is provided, then they don't\n// necessarily block, and they call the callback when they finish with error and\n// result arguments.  (The insert method provides the document ID as its result;\n// update and remove provide the number of affected docs as the result; upsert\n// provides an object with numberAffected and maybe insertedId.)\n//\n// On the client, blocking is impossible, so if a callback\n// isn't provided, they just return immediately and any error\n// information is lost.\n//\n// There's one more tweak. On the client, if you don't provide a\n// callback, then if there is an error, a message will be logged with\n// Meteor._debug.\n//\n// The intent (though this is actually determined by the underlying\n// drivers) is that the operations should be done synchronously, not\n// generating their result until the database has acknowledged\n// them. In the future maybe we should provide a flag to turn this\n// off.\n\n/**\n * @summary Insert a document in the collection.  Returns its unique _id.\n * @locus Anywhere\n * @method  insert\n * @memberOf Mongo.Collection\n * @instance\n * @param {Object} doc The document to insert. May not yet have an _id attribute, in which case Meteor will generate one for you.\n * @param {Function} [callback] Optional.  If present, called with an error object as the first argument and, if no error, the _id as the second.\n */\n\n/**\n * @summary Modify one or more documents in the collection. Returns the number of affected documents.\n * @locus Anywhere\n * @method update\n * @memberOf Mongo.Collection\n * @instance\n * @param {MongoSelector} selector Specifies which documents to modify\n * @param {MongoModifier} modifier Specifies how to modify the documents\n * @param {Object} [options]\n * @param {Boolean} options.multi True to modify all matching documents; false to only modify one of the matching documents (the default).\n * @param {Boolean} options.upsert True to insert a document if no matching documents are found.\n * @param {Function} [callback] Optional.  If present, called with an error object as the first argument and, if no error, the number of affected documents as the second.\n */\n\n/**\n * @summary Remove documents from the collection\n * @locus Anywhere\n * @method remove\n * @memberOf Mongo.Collection\n * @instance\n * @param {MongoSelector} selector Specifies which documents to remove\n * @param {Function} [callback] Optional.  If present, called with an error object as its argument.\n */\n\n_.each([\"insert\", \"update\", \"remove\"], function (name) {\n  Mongo.Collection.prototype[name] = function (/* arguments */) {\n    var self = this;\n    var args = _.toArray(arguments);\n    var callback;\n    var insertId;\n    var ret;\n\n    // Pull off any callback (or perhaps a 'callback' variable that was passed\n    // in undefined, like how 'upsert' does it).\n    if (args.length &&\n        (args[args.length - 1] === undefined ||\n         args[args.length - 1] instanceof Function)) {\n      callback = args.pop();\n    }\n\n    if (name === \"insert\") {\n      if (!args.length)\n        throw new Error(\"insert requires an argument\");\n      // shallow-copy the document and generate an ID\n      args[0] = _.extend({}, args[0]);\n      if ('_id' in args[0]) {\n        insertId = args[0]._id;\n        if (!insertId || !(typeof insertId === 'string'\n              || insertId instanceof Mongo.ObjectID))\n          throw new Error(\"Meteor requires document _id fields to be non-empty strings or ObjectIDs\");\n      } else {\n        var generateId = true;\n        // Don't generate the id if we're the client and the 'outermost' call\n        // This optimization saves us passing both the randomSeed and the id\n        // Passing both is redundant.\n        if (self._connection && self._connection !== Meteor.server) {\n          var enclosing = DDP._CurrentInvocation.get();\n          if (!enclosing) {\n            generateId = false;\n          }\n        }\n        if (generateId) {\n          insertId = args[0]._id = self._makeNewID();\n        }\n      }\n    } else {\n      args[0] = Mongo.Collection._rewriteSelector(args[0]);\n\n      if (name === \"update\") {\n        // Mutate args but copy the original options object. We need to add\n        // insertedId to options, but don't want to mutate the caller's options\n        // object. We need to mutate `args` because we pass `args` into the\n        // driver below.\n        var options = args[2] = _.clone(args[2]) || {};\n        if (options && typeof options !== \"function\" && options.upsert) {\n          // set `insertedId` if absent.  `insertedId` is a Meteor extension.\n          if (options.insertedId) {\n            if (!(typeof options.insertedId === 'string'\n                  || options.insertedId instanceof Mongo.ObjectID))\n              throw new Error(\"insertedId must be string or ObjectID\");\n          } else if (! args[0]._id) {\n            options.insertedId = self._makeNewID();\n          }\n        }\n      }\n    }\n\n    // On inserts, always return the id that we generated; on all other\n    // operations, just return the result from the collection.\n    var chooseReturnValueFromCollectionResult = function (result) {\n      if (name === \"insert\") {\n        if (!insertId && result) {\n          insertId = result;\n        }\n        return insertId;\n      } else {\n        return result;\n      }\n    };\n\n    var wrappedCallback;\n    if (callback) {\n      wrappedCallback = function (error, result) {\n        callback(error, ! error && chooseReturnValueFromCollectionResult(result));\n      };\n    }\n\n    // XXX see #MeteorServerNull\n    if (self._connection && self._connection !== Meteor.server) {\n      // just remote to another endpoint, propagate return value or\n      // exception.\n\n      var enclosing = DDP._CurrentInvocation.get();\n      var alreadyInSimulation = enclosing && enclosing.isSimulation;\n\n      if (Meteor.isClient && !wrappedCallback && ! alreadyInSimulation) {\n        // Client can't block, so it can't report errors by exception,\n        // only by callback. If they forget the callback, give them a\n        // default one that logs the error, so they aren't totally\n        // baffled if their writes don't work because their database is\n        // down.\n        // Don't give a default callback in simulation, because inside stubs we\n        // want to return the results from the local collection immediately and\n        // not force a callback.\n        wrappedCallback = function (err) {\n          if (err)\n            Meteor._debug(name + \" failed: \" + (err.reason || err.stack));\n        };\n      }\n\n      if (!alreadyInSimulation && name !== \"insert\") {\n        // If we're about to actually send an RPC, we should throw an error if\n        // this is a non-ID selector, because the mutation methods only allow\n        // single-ID selectors. (If we don't throw here, we'll see flicker.)\n        throwIfSelectorIsNotId(args[0], name);\n      }\n\n      ret = chooseReturnValueFromCollectionResult(\n        self._connection.apply(self._prefix + name, args, {returnStubValue: true}, wrappedCallback)\n      );\n\n    } else {\n      // it's my collection.  descend into the collection object\n      // and propagate any exception.\n      args.push(wrappedCallback);\n      try {\n        // If the user provided a callback and the collection implements this\n        // operation asynchronously, then queryRet will be undefined, and the\n        // result will be returned through the callback instead.\n        var queryRet = self._collection[name].apply(self._collection, args);\n        ret = chooseReturnValueFromCollectionResult(queryRet);\n      } catch (e) {\n        if (callback) {\n          callback(e);\n          return null;\n        }\n        throw e;\n      }\n    }\n\n    // both sync and async, unless we threw an exception, return ret\n    // (new document ID for insert, num affected for update/remove, object with\n    // numberAffected and maybe insertedId for upsert).\n    return ret;\n  };\n});\n\n/**\n * @summary Modify one or more documents in the collection, or insert one if no matching documents were found. Returns an object with keys `numberAffected` (the number of documents modified)  and `insertedId` (the unique _id of the document that was inserted, if any).\n * @locus Anywhere\n * @param {MongoSelector} selector Specifies which documents to modify\n * @param {MongoModifier} modifier Specifies how to modify the documents\n * @param {Object} [options]\n * @param {Boolean} options.multi True to modify all matching documents; false to only modify one of the matching documents (the default).\n * @param {Function} [callback] Optional.  If present, called with an error object as the first argument and, if no error, the number of affected documents as the second.\n */\nMongo.Collection.prototype.upsert = function (selector, modifier,\n                                               options, callback) {\n  var self = this;\n  if (! callback && typeof options === \"function\") {\n    callback = options;\n    options = {};\n  }\n  return self.update(selector, modifier,\n              _.extend({}, options, { _returnObject: true, upsert: true }),\n              callback);\n};\n\n// We'll actually design an index API later. For now, we just pass through to\n// Mongo's, but make it synchronous.\nMongo.Collection.prototype._ensureIndex = function (index, options) {\n  var self = this;\n  if (!self._collection._ensureIndex)\n    throw new Error(\"Can only call _ensureIndex on server collections\");\n  self._collection._ensureIndex(index, options);\n};\nMongo.Collection.prototype._dropIndex = function (index) {\n  var self = this;\n  if (!self._collection._dropIndex)\n    throw new Error(\"Can only call _dropIndex on server collections\");\n  self._collection._dropIndex(index);\n};\nMongo.Collection.prototype._dropCollection = function () {\n  var self = this;\n  if (!self._collection.dropCollection)\n    throw new Error(\"Can only call _dropCollection on server collections\");\n  self._collection.dropCollection();\n};\nMongo.Collection.prototype._createCappedCollection = function (byteSize, maxDocuments) {\n  var self = this;\n  if (!self._collection._createCappedCollection)\n    throw new Error(\"Can only call _createCappedCollection on server collections\");\n  self._collection._createCappedCollection(byteSize, maxDocuments);\n};\n\nMongo.Collection.prototype.rawCollection = function () {\n  var self = this;\n  if (! self._collection.rawCollection) {\n    throw new Error(\"Can only call rawCollection on server collections\");\n  }\n  return self._collection.rawCollection();\n};\n\nMongo.Collection.prototype.rawDatabase = function () {\n  var self = this;\n  if (! (self._driver.mongo && self._driver.mongo.db)) {\n    throw new Error(\"Can only call rawDatabase on server collections\");\n  }\n  return self._driver.mongo.db;\n};\n\n\n/**\n * @summary Create a Mongo-style `ObjectID`.  If you don't specify a `hexString`, the `ObjectID` will generated randomly (not using MongoDB's ID construction rules).\n * @locus Anywhere\n * @class\n * @param {String} hexString Optional.  The 24-character hexadecimal contents of the ObjectID to create\n */\nMongo.ObjectID = LocalCollection._ObjectID;\n\n/**\n * @summary To create a cursor, use find. To access the documents in a cursor, use forEach, map, or fetch.\n * @class\n * @instanceName cursor\n */\nMongo.Cursor = LocalCollection.Cursor;\n\n/**\n * @deprecated in 0.9.1\n */\nMongo.Collection.Cursor = Mongo.Cursor;\n\n/**\n * @deprecated in 0.9.1\n */\nMongo.Collection.ObjectID = Mongo.ObjectID;\n\n///\n/// Remote methods and access control.\n///\n\n// Restrict default mutators on collection. allow() and deny() take the\n// same options:\n//\n// options.insert {Function(userId, doc)}\n//   return true to allow/deny adding this document\n//\n// options.update {Function(userId, docs, fields, modifier)}\n//   return true to allow/deny updating these documents.\n//   `fields` is passed as an array of fields that are to be modified\n//\n// options.remove {Function(userId, docs)}\n//   return true to allow/deny removing these documents\n//\n// options.fetch {Array}\n//   Fields to fetch for these validators. If any call to allow or deny\n//   does not have this option then all fields are loaded.\n//\n// allow and deny can be called multiple times. The validators are\n// evaluated as follows:\n// - If neither deny() nor allow() has been called on the collection,\n//   then the request is allowed if and only if the \"insecure\" smart\n//   package is in use.\n// - Otherwise, if any deny() function returns true, the request is denied.\n// - Otherwise, if any allow() function returns true, the request is allowed.\n// - Otherwise, the request is denied.\n//\n// Meteor may call your deny() and allow() functions in any order, and may not\n// call all of them if it is able to make a decision without calling them all\n// (so don't include side effects).\n\n(function () {\n  var addValidator = function(allowOrDeny, options) {\n    // validate keys\n    var VALID_KEYS = ['insert', 'update', 'remove', 'fetch', 'transform'];\n    _.each(_.keys(options), function (key) {\n      if (!_.contains(VALID_KEYS, key))\n        throw new Error(allowOrDeny + \": Invalid key: \" + key);\n    });\n\n    var self = this;\n    self._restricted = true;\n\n    _.each(['insert', 'update', 'remove'], function (name) {\n      if (options[name]) {\n        if (!(options[name] instanceof Function)) {\n          throw new Error(allowOrDeny + \": Value for `\" + name + \"` must be a function\");\n        }\n\n        // If the transform is specified at all (including as 'null') in this\n        // call, then take that; otherwise, take the transform from the\n        // collection.\n        if (options.transform === undefined) {\n          options[name].transform = self._transform;  // already wrapped\n        } else {\n          options[name].transform = LocalCollection.wrapTransform(\n            options.transform);\n        }\n\n        self._validators[name][allowOrDeny].push(options[name]);\n      }\n    });\n\n    // Only update the fetch fields if we're passed things that affect\n    // fetching. This way allow({}) and allow({insert: f}) don't result in\n    // setting fetchAllFields\n    if (options.update || options.remove || options.fetch) {\n      if (options.fetch && !(options.fetch instanceof Array)) {\n        throw new Error(allowOrDeny + \": Value for `fetch` must be an array\");\n      }\n      self._updateFetch(options.fetch);\n    }\n  };\n\n  /**\n   * @summary Allow users to write directly to this collection from client code, subject to limitations you define.\n   * @locus Server\n   * @param {Object} options\n   * @param {Function} options.insert,update,remove Functions that look at a proposed modification to the database and return true if it should be allowed.\n   * @param {String[]} options.fetch Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your `update` and `remove` functions.\n   * @param {Function} options.transform Overrides `transform` on the  [`Collection`](#collections).  Pass `null` to disable transformation.\n   */\n  Mongo.Collection.prototype.allow = function(options) {\n    addValidator.call(this, 'allow', options);\n  };\n\n  /**\n   * @summary Override `allow` rules.\n   * @locus Server\n   * @param {Object} options\n   * @param {Function} options.insert,update,remove Functions that look at a proposed modification to the database and return true if it should be denied, even if an [allow](#allow) rule says otherwise.\n   * @param {String[]} options.fetch Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your `update` and `remove` functions.\n   * @param {Function} options.transform Overrides `transform` on the  [`Collection`](#collections).  Pass `null` to disable transformation.\n   */\n  Mongo.Collection.prototype.deny = function(options) {\n    addValidator.call(this, 'deny', options);\n  };\n})();\n\n\nMongo.Collection.prototype._defineMutationMethods = function() {\n  var self = this;\n\n  // set to true once we call any allow or deny methods. If true, use\n  // allow/deny semantics. If false, use insecure mode semantics.\n  self._restricted = false;\n\n  // Insecure mode (default to allowing writes). Defaults to 'undefined' which\n  // means insecure iff the insecure package is loaded. This property can be\n  // overriden by tests or packages wishing to change insecure mode behavior of\n  // their collections.\n  self._insecure = undefined;\n\n  self._validators = {\n    insert: {allow: [], deny: []},\n    update: {allow: [], deny: []},\n    remove: {allow: [], deny: []},\n    upsert: {allow: [], deny: []}, // dummy arrays; can't set these!\n    fetch: [],\n    fetchAllFields: false\n  };\n\n  if (!self._name)\n    return; // anonymous collection\n\n  // XXX Think about method namespacing. Maybe methods should be\n  // \"Meteor:Mongo:insert/NAME\"?\n  self._prefix = '/' + self._name + '/';\n\n  // mutation methods\n  if (self._connection) {\n    var m = {};\n\n    _.each(['insert', 'update', 'remove'], function (method) {\n      m[self._prefix + method] = function (/* ... */) {\n        // All the methods do their own validation, instead of using check().\n        check(arguments, [Match.Any]);\n        var args = _.toArray(arguments);\n        try {\n          // For an insert, if the client didn't specify an _id, generate one\n          // now; because this uses DDP.randomStream, it will be consistent with\n          // what the client generated. We generate it now rather than later so\n          // that if (eg) an allow/deny rule does an insert to the same\n          // collection (not that it really should), the generated _id will\n          // still be the first use of the stream and will be consistent.\n          //\n          // However, we don't actually stick the _id onto the document yet,\n          // because we want allow/deny rules to be able to differentiate\n          // between arbitrary client-specified _id fields and merely\n          // client-controlled-via-randomSeed fields.\n          var generatedId = null;\n          if (method === \"insert\" && !_.has(args[0], '_id')) {\n            generatedId = self._makeNewID();\n          }\n\n          if (this.isSimulation) {\n            // In a client simulation, you can do any mutation (even with a\n            // complex selector).\n            if (generatedId !== null)\n              args[0]._id = generatedId;\n            return self._collection[method].apply(\n              self._collection, args);\n          }\n\n          // This is the server receiving a method call from the client.\n\n          // We don't allow arbitrary selectors in mutations from the client: only\n          // single-ID selectors.\n          if (method !== 'insert')\n            throwIfSelectorIsNotId(args[0], method);\n\n          if (self._restricted) {\n            // short circuit if there is no way it will pass.\n            if (self._validators[method].allow.length === 0) {\n              throw new Meteor.Error(\n                403, \"Access denied. No allow validators set on restricted \" +\n                  \"collection for method '\" + method + \"'.\");\n            }\n\n            var validatedMethodName =\n                  '_validated' + method.charAt(0).toUpperCase() + method.slice(1);\n            args.unshift(this.userId);\n            method === 'insert' && args.push(generatedId);\n            return self[validatedMethodName].apply(self, args);\n          } else if (self._isInsecure()) {\n            if (generatedId !== null)\n              args[0]._id = generatedId;\n            // In insecure mode, allow any mutation (with a simple selector).\n            // XXX This is kind of bogus.  Instead of blindly passing whatever\n            //     we get from the network to this function, we should actually\n            //     know the correct arguments for the function and pass just\n            //     them.  For example, if you have an extraneous extra null\n            //     argument and this is Mongo on the server, the .wrapAsync'd\n            //     functions like update will get confused and pass the\n            //     \"fut.resolver()\" in the wrong slot, where _update will never\n            //     invoke it. Bam, broken DDP connection.  Probably should just\n            //     take this whole method and write it three times, invoking\n            //     helpers for the common code.\n            return self._collection[method].apply(self._collection, args);\n          } else {\n            // In secure mode, if we haven't called allow or deny, then nothing\n            // is permitted.\n            throw new Meteor.Error(403, \"Access denied\");\n          }\n        } catch (e) {\n          if (e.name === 'MongoError' || e.name === 'MinimongoError') {\n            throw new Meteor.Error(409, e.toString());\n          } else {\n            throw e;\n          }\n        }\n      };\n    });\n    // Minimongo on the server gets no stubs; instead, by default\n    // it wait()s until its result is ready, yielding.\n    // This matches the behavior of macromongo on the server better.\n    // XXX see #MeteorServerNull\n    if (Meteor.isClient || self._connection === Meteor.server)\n      self._connection.methods(m);\n  }\n};\n\n\nMongo.Collection.prototype._updateFetch = function (fields) {\n  var self = this;\n\n  if (!self._validators.fetchAllFields) {\n    if (fields) {\n      self._validators.fetch = _.union(self._validators.fetch, fields);\n    } else {\n      self._validators.fetchAllFields = true;\n      // clear fetch just to make sure we don't accidentally read it\n      self._validators.fetch = null;\n    }\n  }\n};\n\nMongo.Collection.prototype._isInsecure = function () {\n  var self = this;\n  if (self._insecure === undefined)\n    return !!Package.insecure;\n  return self._insecure;\n};\n\nvar docToValidate = function (validator, doc, generatedId) {\n  var ret = doc;\n  if (validator.transform) {\n    ret = EJSON.clone(doc);\n    // If you set a server-side transform on your collection, then you don't get\n    // to tell the difference between \"client specified the ID\" and \"server\n    // generated the ID\", because transforms expect to get _id.  If you want to\n    // do that check, you can do it with a specific\n    // `C.allow({insert: f, transform: null})` validator.\n    if (generatedId !== null) {\n      ret._id = generatedId;\n    }\n    ret = validator.transform(ret);\n  }\n  return ret;\n};\n\nMongo.Collection.prototype._validatedInsert = function (userId, doc,\n                                                         generatedId) {\n  var self = this;\n\n  // call user validators.\n  // Any deny returns true means denied.\n  if (_.any(self._validators.insert.deny, function(validator) {\n    return validator(userId, docToValidate(validator, doc, generatedId));\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n  // Any allow returns true means proceed. Throw error if they all fail.\n  if (_.all(self._validators.insert.allow, function(validator) {\n    return !validator(userId, docToValidate(validator, doc, generatedId));\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n\n  // If we generated an ID above, insert it now: after the validation, but\n  // before actually inserting.\n  if (generatedId !== null)\n    doc._id = generatedId;\n\n  self._collection.insert.call(self._collection, doc);\n};\n\nvar transformDoc = function (validator, doc) {\n  if (validator.transform)\n    return validator.transform(doc);\n  return doc;\n};\n\n// Simulate a mongo `update` operation while validating that the access\n// control rules set by calls to `allow/deny` are satisfied. If all\n// pass, rewrite the mongo operation to use $in to set the list of\n// document ids to change ##ValidatedChange\nMongo.Collection.prototype._validatedUpdate = function(\n    userId, selector, mutator, options) {\n  var self = this;\n\n  check(mutator, Object);\n\n  options = _.clone(options) || {};\n\n  if (!LocalCollection._selectorIsIdPerhapsAsObject(selector))\n    throw new Error(\"validated update should be of a single ID\");\n\n  // We don't support upserts because they don't fit nicely into allow/deny\n  // rules.\n  if (options.upsert)\n    throw new Meteor.Error(403, \"Access denied. Upserts not \" +\n                           \"allowed in a restricted collection.\");\n\n  var noReplaceError = \"Access denied. In a restricted collection you can only\" +\n        \" update documents, not replace them. Use a Mongo update operator, such \" +\n        \"as '$set'.\";\n\n  // compute modified fields\n  var fields = [];\n  if (_.isEmpty(mutator)) {\n    throw new Meteor.Error(403, noReplaceError);\n  }\n  _.each(mutator, function (params, op) {\n    if (op.charAt(0) !== '$') {\n      throw new Meteor.Error(403, noReplaceError);\n    } else if (!_.has(ALLOWED_UPDATE_OPERATIONS, op)) {\n      throw new Meteor.Error(\n        403, \"Access denied. Operator \" + op + \" not allowed in a restricted collection.\");\n    } else {\n      _.each(_.keys(params), function (field) {\n        // treat dotted fields as if they are replacing their\n        // top-level part\n        if (field.indexOf('.') !== -1)\n          field = field.substring(0, field.indexOf('.'));\n\n        // record the field we are trying to change\n        if (!_.contains(fields, field))\n          fields.push(field);\n      });\n    }\n  });\n\n  var findOptions = {transform: null};\n  if (!self._validators.fetchAllFields) {\n    findOptions.fields = {};\n    _.each(self._validators.fetch, function(fieldName) {\n      findOptions.fields[fieldName] = 1;\n    });\n  }\n\n  var doc = self._collection.findOne(selector, findOptions);\n  if (!doc)  // none satisfied!\n    return 0;\n\n  // call user validators.\n  // Any deny returns true means denied.\n  if (_.any(self._validators.update.deny, function(validator) {\n    var factoriedDoc = transformDoc(validator, doc);\n    return validator(userId,\n                     factoriedDoc,\n                     fields,\n                     mutator);\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n  // Any allow returns true means proceed. Throw error if they all fail.\n  if (_.all(self._validators.update.allow, function(validator) {\n    var factoriedDoc = transformDoc(validator, doc);\n    return !validator(userId,\n                      factoriedDoc,\n                      fields,\n                      mutator);\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n\n  options._forbidReplace = true;\n\n  // Back when we supported arbitrary client-provided selectors, we actually\n  // rewrote the selector to include an _id clause before passing to Mongo to\n  // avoid races, but since selector is guaranteed to already just be an ID, we\n  // don't have to any more.\n\n  return self._collection.update.call(\n    self._collection, selector, mutator, options);\n};\n\n// Only allow these operations in validated updates. Specifically\n// whitelist operations, rather than blacklist, so new complex\n// operations that are added aren't automatically allowed. A complex\n// operation is one that does more than just modify its target\n// field. For now this contains all update operations except '$rename'.\n// http://docs.mongodb.org/manual/reference/operators/#update\nvar ALLOWED_UPDATE_OPERATIONS = {\n  $inc:1, $set:1, $unset:1, $addToSet:1, $pop:1, $pullAll:1, $pull:1,\n  $pushAll:1, $push:1, $bit:1\n};\n\n// Simulate a mongo `remove` operation while validating access control\n// rules. See #ValidatedChange\nMongo.Collection.prototype._validatedRemove = function(userId, selector) {\n  var self = this;\n\n  var findOptions = {transform: null};\n  if (!self._validators.fetchAllFields) {\n    findOptions.fields = {};\n    _.each(self._validators.fetch, function(fieldName) {\n      findOptions.fields[fieldName] = 1;\n    });\n  }\n\n  var doc = self._collection.findOne(selector, findOptions);\n  if (!doc)\n    return 0;\n\n  // call user validators.\n  // Any deny returns true means denied.\n  if (_.any(self._validators.remove.deny, function(validator) {\n    return validator(userId, transformDoc(validator, doc));\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n  // Any allow returns true means proceed. Throw error if they all fail.\n  if (_.all(self._validators.remove.allow, function(validator) {\n    return !validator(userId, transformDoc(validator, doc));\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n\n  // Back when we supported arbitrary client-provided selectors, we actually\n  // rewrote the selector to {_id: {$in: [ids that we found]}} before passing to\n  // Mongo to avoid races, but since selector is guaranteed to already just be\n  // an ID, we don't have to any more.\n\n  return self._collection.remove.call(self._collection, selector);\n};\n\n/**\n * @deprecated in 0.9.1\n */\nMeteor.Collection = Mongo.Collection;\n"]}