)]}'
{"version":3,"sources":["reactive-dict/reactive-dict.js","reactive-dict/migration.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yE;AACA,mE;AACA,kC;AACA,0B;AACA,uB;AACA,gC;AACA,E;AACA,mC;AACA,6D;AACA,qB;AACA,iC;AACA,E;;AAEA,mE;AACA,oC;AACA,4B;AACA,iB;AACA,uC;AACA,oD;AACA,uE;AACA,2D;AACA,iE;AACA,8C;AACA,6D;AACA,2B;AACA,Y;AACA,oE;AACA,K;AACA,U;AACA,oD;AACA,mB;AACA,G;;AAEA,yC;AACA,8C;AACA,E;;AAEA,kC;AACA,qE;AACA,8D;AACA,qC;;AAEA,sC;AACA,oB;;AAEA,qE;AACA,mC;AACA,a;AACA,K;AACA,qD;AACA,kD;AACA,0B;;AAEA,6B;;AAEA,yC;AACA,mE;AACA,qC;AACA,a;AACA,2B;;AAEA,gC;AACA,uB;AACA,M;;AAEA,+B;AACA,iC;AACA,0D;AACA,6C;AACA,K;AACA,I;;AAEA,qC;AACA,oB;AACA,iE;AACA,uF;AACA,yC;AACA,uC;AACA,2B;AACA,K;AACA,I;;AAEA,uB;AACA,oB;AACA,yB;AACA,+B;AACA,iC;AACA,I;;AAEA,iC;AACA,oB;;AAEA,+C;AACA,wB;AACA,uC;AACA,gC;AACA,K;;AAEA,wE;AACA,sE;AACA,4E;AACA,0E;AACA,+E;AACA,oD;AACA,M;AACA,2E;AACA,qB;AACA,oC;AACA,oC;AACA,qC;AACA,uC;AACA,mC;AACA,mD;AACA,uB;AACA,mE;AACA,2C;;AAEA,yB;AACA,2B;;AAEA,2D;AACA,yE;;AAEA,mE;AACA,kB;AACA,0C;AACA,2E;AACA,qD;AACA,wE;AACA,2D;AACA,W;AACA,O;AACA,K;;AAEA,6B;AACA,gE;AACA,yC;AACA,I;;AAEA,iC;AACA,oB;;AAEA,yC;AACA,2B;AACA,O;AACA,I;;AAEA,8B;AACA,oB;AACA,iC;AACA,iD;AACA,kC;AACA,K;AACA,I;;AAEA,8D;AACA,iE;AACA,kC;AACA,gD;AACA,qB;AACA,G;AACA,G;;;;;;;;;;;;;;;;;;;ACjKA,oD;AACA,0D;;AAEA,sD;AACA,sD;AACA,oD;;AAEA,c;AACA,E;;AAEA,kE;AACA,oD;AACA,gE;;AAEA,gD;AACA,E;;AAEA,wC;AACA,+D;AACA,gE;AACA,4E;AACA,2C;AACA,yD;;AAEA,sE;AACA,gB;AACA,iE;AACA,sD;AACA,2B;;AAEA,wC;AACA,6E;;AAEA,0C;AACA,K;AACA,C","file":"/packages/reactive-dict.js","sourcesContent":["// XXX come up with a serialization method which canonicalizes object key\n// order, which would allow us to use objects as values for equals.\nvar stringify = function (value) {\n  if (value === undefined)\n    return 'undefined';\n  return EJSON.stringify(value);\n};\nvar parse = function (serialized) {\n  if (serialized === undefined || serialized === 'undefined')\n    return undefined;\n  return EJSON.parse(serialized);\n};\n\n// XXX COMPAT WITH 0.9.1 : accept migrationData instead of dictName\nReactiveDict = function (dictName) {\n  // this.keys: key -> value\n  if (dictName) {\n    if (typeof dictName === 'string') {\n      // the normal case, argument is a string name.\n      // _registerDictForMigrate will throw an error on duplicate name.\n      ReactiveDict._registerDictForMigrate(dictName, this);\n      this.keys = ReactiveDict._loadMigratedDict(dictName) || {};\n    } else if (typeof dictName === 'object') {\n      // back-compat case: dictName is actually migrationData\n      this.keys = dictName;\n    } else {\n      throw new Error(\"Invalid ReactiveDict argument: \" + dictName);\n    }\n  } else {\n    // no name given; no migration will be performed\n    this.keys = {};\n  }\n\n  this.keyDeps = {}; // key -> Dependency\n  this.keyValueDeps = {}; // key -> Dependency\n};\n\n_.extend(ReactiveDict.prototype, {\n  // set() began as a key/value method, but we are now overloading it\n  // to take an object of key/value pairs, similar to backbone\n  // http://backbonejs.org/#Model-set\n\n  set: function (keyOrObject, value) {\n    var self = this;\n\n    if ((typeof keyOrObject === 'object') && (value === undefined)) {\n      self._setObject(keyOrObject);\n      return;\n    }\n    // the input isn't an object, so it must be a key\n    // and we resume with the rest of the function\n    var key = keyOrObject;\n\n    value = stringify(value);\n\n    var oldSerializedValue = 'undefined';\n    if (_.has(self.keys, key)) oldSerializedValue = self.keys[key];\n    if (value === oldSerializedValue)\n      return;\n    self.keys[key] = value;\n\n    var changed = function (v) {\n      v && v.changed();\n    };\n\n    changed(self.keyDeps[key]);\n    if (self.keyValueDeps[key]) {\n      changed(self.keyValueDeps[key][oldSerializedValue]);\n      changed(self.keyValueDeps[key][value]);\n    }\n  },\n\n  setDefault: function (key, value) {\n    var self = this;\n    // for now, explicitly check for undefined, since there is no\n    // ReactiveDict.clear().  Later we might have a ReactiveDict.clear(), in which case\n    // we should check if it has the key.\n    if (self.keys[key] === undefined) {\n      self.set(key, value);\n    }\n  },\n\n  get: function (key) {\n    var self = this;\n    self._ensureKey(key);\n    self.keyDeps[key].depend();\n    return parse(self.keys[key]);\n  },\n\n  equals: function (key, value) {\n    var self = this;\n\n    // Mongo.ObjectID is in the 'mongo' package\n    var ObjectID = null;\n    if (typeof Mongo !== 'undefined') {\n      ObjectID = Mongo.ObjectID;\n    }\n\n    // We don't allow objects (or arrays that might include objects) for\n    // .equals, because JSON.stringify doesn't canonicalize object key\n    // order. (We can make equals have the right return value by parsing the\n    // current value and using EJSON.equals, but we won't have a canonical\n    // element of keyValueDeps[key] to store the dependency.) You can still use\n    // \"EJSON.equals(reactiveDict.get(key), value)\".\n    //\n    // XXX we could allow arrays as long as we recursively check that there\n    // are no objects\n    if (typeof value !== 'string' &&\n        typeof value !== 'number' &&\n        typeof value !== 'boolean' &&\n        typeof value !== 'undefined' &&\n        !(value instanceof Date) &&\n        !(ObjectID && value instanceof ObjectID) &&\n        value !== null)\n      throw new Error(\"ReactiveDict.equals: value must be scalar\");\n    var serializedValue = stringify(value);\n\n    if (Tracker.active) {\n      self._ensureKey(key);\n\n      if (! _.has(self.keyValueDeps[key], serializedValue))\n        self.keyValueDeps[key][serializedValue] = new Tracker.Dependency;\n\n      var isNew = self.keyValueDeps[key][serializedValue].depend();\n      if (isNew) {\n        Tracker.onInvalidate(function () {\n          // clean up [key][serializedValue] if it's now empty, so we don't\n          // use O(n) memory for n = values seen ever\n          if (! self.keyValueDeps[key][serializedValue].hasDependents())\n            delete self.keyValueDeps[key][serializedValue];\n        });\n      }\n    }\n\n    var oldValue = undefined;\n    if (_.has(self.keys, key)) oldValue = parse(self.keys[key]);\n    return EJSON.equals(oldValue, value);\n  },\n\n  _setObject: function (object) {\n    var self = this;\n\n    _.each(object, function (value, key){\n      self.set(key, value);\n    });\n  },\n\n  _ensureKey: function (key) {\n    var self = this;\n    if (!(key in self.keyDeps)) {\n      self.keyDeps[key] = new Tracker.Dependency;\n      self.keyValueDeps[key] = {};\n    }\n  },\n\n  // Get a JSON value that can be passed to the constructor to\n  // create a new ReactiveDict with the same contents as this one\n  _getMigrationData: function () {\n    // XXX sanitize and make sure it's JSONible?\n    return this.keys;\n  }\n});\n","ReactiveDict._migratedDictData = {}; // name -> data\nReactiveDict._dictsToMigrate = {}; // name -> ReactiveDict\n\nReactiveDict._loadMigratedDict = function (dictName) {\n  if (_.has(ReactiveDict._migratedDictData, dictName))\n    return ReactiveDict._migratedDictData[dictName];\n\n  return null;\n};\n\nReactiveDict._registerDictForMigrate = function (dictName, dict) {\n  if (_.has(ReactiveDict._dictsToMigrate, dictName))\n    throw new Error(\"Duplicate ReactiveDict name: \" + dictName);\n\n  ReactiveDict._dictsToMigrate[dictName] = dict;\n};\n\nif (Meteor.isClient && Package.reload) {\n  // Put old migrated data into ReactiveDict._migratedDictData,\n  // where it can be accessed by ReactiveDict._loadMigratedDict.\n  var migrationData = Package.reload.Reload._migrationData('reactive-dict');\n  if (migrationData && migrationData.dicts)\n    ReactiveDict._migratedDictData = migrationData.dicts;\n\n  // On migration, assemble the data from all the dicts that have been\n  // registered.\n  Package.reload.Reload._onMigrate('reactive-dict', function () {\n    var dictsToMigrate = ReactiveDict._dictsToMigrate;\n    var dataToMigrate = {};\n\n    for (var dictName in dictsToMigrate)\n      dataToMigrate[dictName] = dictsToMigrate[dictName]._getMigrationData();\n\n    return [true, {dicts: dataToMigrate}];\n  });\n}\n"]}