ReactiveDict: can set absent value to undefined

Setting a ReactiveDict value to `undefined` does not remove it, and
undefined values are migrated.  Therefore, it is odd that setting
'foo' to `undefined` on the empty dict does not produce the dict
`{foo: undefined}`, but setting 'foo' first to another value and *then*
`undefined` does.  So, we fix that.

This means that setting a value to `undefined` blocks `setDefault` on
that key, which makes sense given that setting the value to 123 and then
`undefined` blocks `setDefault` on that key.
This commit is contained in:
David Greenspan
2015-09-17 09:57:18 -07:00
parent 5a36f344e8
commit 60aa9f7c9d
3 changed files with 21 additions and 9 deletions

View File

@@ -16,5 +16,6 @@ Package.onTest(function (api) {
api.use('tinytest'); api.use('tinytest');
api.use('reactive-dict'); api.use('reactive-dict');
api.use('tracker'); api.use('tracker');
api.use('underscore');
api.addFiles('reactive-dict-tests.js'); api.addFiles('reactive-dict-tests.js');
}); });

View File

@@ -1,11 +1,19 @@
Tinytest.add('ReactiveDict - set to undefined', function (test) {
var dict = new ReactiveDict;
dict.set('foo', undefined);
test.equal(_.keys(dict.all()), ['foo']);
dict.setDefault('foo', 'bar');
test.equal(dict.get('foo'), undefined);
});
Tinytest.add('ReactiveDict - all() works', function (test) { Tinytest.add('ReactiveDict - all() works', function (test) {
var all = {}, dict = new ReactiveDict; var all = {}, dict = new ReactiveDict;
Tracker.autorun(function() { Tracker.autorun(function() {
all = dict.all(); all = dict.all();
}); });
test.equal(all, {}); test.equal(all, {});
dict.set('foo', 'bar'); dict.set('foo', 'bar');
Tracker.flush(); Tracker.flush();
test.equal(all, {foo: 'bar'}); test.equal(all, {foo: 'bar'});
@@ -15,7 +23,7 @@ Tinytest.add('ReactiveDict - all() works', function (test) {
Tinytest.add('ReactiveDict - clear() works', function (test) { Tinytest.add('ReactiveDict - clear() works', function (test) {
var dict = new ReactiveDict; var dict = new ReactiveDict;
dict.set('foo', 'bar'); dict.set('foo', 'bar');
var val, equals, equalsUndefined, all; var val, equals, equalsUndefined, all;
Tracker.autorun(function() { Tracker.autorun(function() {
val = dict.get('foo'); val = dict.get('foo');
@@ -29,16 +37,16 @@ Tinytest.add('ReactiveDict - clear() works', function (test) {
Tracker.autorun(function() { Tracker.autorun(function() {
all = dict.all(); all = dict.all();
}); });
test.equal(val, 'bar'); test.equal(val, 'bar');
test.equal(equals, true); test.equal(equals, true);
test.equal(equalsUndefined, false); test.equal(equalsUndefined, false);
test.equal(all, {foo: 'bar'}); test.equal(all, {foo: 'bar'});
dict.clear(); dict.clear();
Tracker.flush(); Tracker.flush();
test.isUndefined(val); test.isUndefined(val);
test.equal(equals, false); test.equal(equals, false);
test.equal(equalsUndefined, true); test.equal(equalsUndefined, true);
test.equal(all, {}); test.equal(all, {});
}); });

View File

@@ -50,6 +50,7 @@ _.extend(ReactiveDict.prototype, {
var self = this; var self = this;
if ((typeof keyOrObject === 'object') && (value === undefined)) { if ((typeof keyOrObject === 'object') && (value === undefined)) {
// Called as `dict.set({...})`
self._setObject(keyOrObject); self._setObject(keyOrObject);
return; return;
} }
@@ -60,9 +61,11 @@ _.extend(ReactiveDict.prototype, {
value = stringify(value); value = stringify(value);
var oldSerializedValue = 'undefined'; var oldSerializedValue = 'undefined';
if (_.has(self.keys, key)) oldSerializedValue = self.keys[key]; if (_.has(self.keys, key)) {
if (value === oldSerializedValue) oldSerializedValue = self.keys[key];
return; if (value === oldSerializedValue)
return;
}
self.keys[key] = value; self.keys[key] = value;
self.allDeps.changed(); self.allDeps.changed();