prevent cyclical store computations, and computation duplication

pull/964/head
Rich Harris 7 years ago
parent a717c82bb4
commit d479224067

@ -48,19 +48,30 @@ assign(Store.prototype, {
_sortComputedProperties: function() {
var computed = this._computed;
var sorted = this._sortedComputedProperties = [];
var cycles;
var visited = blankObject();
function visit(key) {
if (cycles[key]) {
throw new Error(`Cyclical dependency detected — a computed property cannot indirectly depend on itself`);
}
if (visited[key]) return;
visited[key] = true;
var c = computed[key];
if (c) {
cycles[key] = true;
c.deps.forEach(visit);
sorted.push(c);
}
}
for (var key in this._computed) visit(key);
for (var key in this._computed) {
cycles = blankObject();
visit(key);
}
},
compute: function(key, deps, fn) {

@ -1,5 +1,5 @@
import assert from 'assert';
import { Store, combineStores } from '../../store.js';
import { Store } from '../../store.js';
describe('store', () => {
describe('get', () => {
@ -142,5 +142,29 @@ describe('store', () => {
store.set({ bar: 'whatever' });
}, /'bar' is a read-only property/);
});
it('allows multiple dependents to depend on the same computed property', () => {
const store = new Store({
a: 1
});
store.compute('b', ['a'], a => a * 2);
store.compute('c', ['b'], b => b * 3);
store.compute('d', ['b'], b => b * 4);
assert.deepEqual(store.get(), { a: 1, b: 2, c: 6, d: 8 });
// bit cheeky, testing a private property, but whatever
assert.equal(store._sortedComputedProperties.length, 3);
});
it('prevents cyclical dependencies', () => {
const store = new Store();
assert.throws(() => {
store.compute('a', ['b'], b => b + 1);
store.compute('b', ['a'], a => a + 1);
}, /Cyclical dependency detected — a computed property cannot indirectly depend on itself/);
});
});
});

Loading…
Cancel
Save