diff --git a/lib/get/getCache.js b/lib/get/getCache.js index 450469c7..7e566a30 100644 --- a/lib/get/getCache.js +++ b/lib/get/getCache.js @@ -18,7 +18,13 @@ function _copyCache(node, out, fromKey) { Object. keys(node). filter(function(k) { - return !isInternalKey(k); + // Its not an internal key and the node has a value. In the cache + // there are 3 possibilities for values. + // 1: A branch node. + // 2: A $type-value node. + // 3: undefined + // We will strip out 3 + return !isInternalKey(k) && node[k]; }). forEach(function(key) { var cacheNext = node[key]; diff --git a/lib/get/getValueSync.js b/lib/get/getValueSync.js index 04d8a4f2..aefbffb3 100644 --- a/lib/get/getValueSync.js +++ b/lib/get/getValueSync.js @@ -31,9 +31,10 @@ module.exports = function getValueSync(model, simplePath, noClone) { type = next.$type; - // Up to the last key we follow references + // Up to the last key we follow references, ensure that they are not + // expired either. if (depth < len) { - if (type === $ref) { + if (type === $ref && !isExpired(next)) { ref = followReference(model, root, root, next, next.value); refNode = ref[0]; diff --git a/test/falcor/bind/bind-cases.spec.js b/test/falcor/bind/bind-cases.spec.js index 4f05b2f7..1301ed59 100644 --- a/test/falcor/bind/bind-cases.spec.js +++ b/test/falcor/bind/bind-cases.spec.js @@ -9,6 +9,8 @@ var Bound = Expected.Bound; var noOp = function() {}; var chai = require("chai"); var expect = chai.expect; +var ref = Model.ref; +var atom = Model.atom; describe('Deref', function() { it('should deref to a branch node.', function(done) { @@ -70,6 +72,26 @@ describe('Deref', function() { }). subscribe(noOp, done, done); }); + + it('should not be able to get an item out of the core that is expired, but previously hard-linked.', function() { + // hardlinks + var model = new Model({ + cache: { + lolomo: ref(['lolomos', 'abc'], {$expires: Date.now() + 1000}), + lolomos: { + abc: { + 0: atom('foo') + } + } + } + }); + + // expires the hardlinked item. + model._root.cache.lolomo.$expires = Date.now() - 10; + var out = model._getValueSync(model, ['lolomo', 0]); + + expect(out.value).to.equals(undefined); + }); }); function getCache() { diff --git a/test/falcor/get/index.js b/test/falcor/get/index.js index 12edc554..12f88620 100644 --- a/test/falcor/get/index.js +++ b/test/falcor/get/index.js @@ -5,7 +5,6 @@ describe('Get', function() { require('./get.dataSource-and-bind.spec'); require('./get.cacheAsDataSource.spec'); require('./get.pathSyntax.spec'); - require('./get.getCache.spec'); require('./get.clone.spec'); require('./get.gen.spec'); }); diff --git a/test/get-core/edges.spec.js b/test/get-core/edges.spec.js index bd1c32eb..703cbdff 100644 --- a/test/get-core/edges.spec.js +++ b/test/get-core/edges.spec.js @@ -7,6 +7,7 @@ var ref = jsonGraph.ref; var $ref = require('./../../lib/types/ref'); var $atom = require('./../../lib/types/atom'); var _ = require('lodash'); +var Model = require('./../../lib').Model; describe('Edges', function() { // PathMap ---------------------------------------- diff --git a/test/falcor/get/get.getCache.spec.js b/test/get-core/get.cache.spec.js similarity index 51% rename from test/falcor/get/get.getCache.spec.js rename to test/get-core/get.cache.spec.js index 55564aee..3574290f 100644 --- a/test/falcor/get/get.getCache.spec.js +++ b/test/get-core/get.cache.spec.js @@ -1,17 +1,12 @@ -var cacheGenerator = require('./../../CacheGenerator'); -var falcor = require("./../../../lib/"); -var clean = require('./../../cleanData').clean; +var cacheGenerator = require('./../CacheGenerator'); +var falcor = require("./../../lib/"); +var clean = require('./../cleanData').clean; var Model = falcor.Model; -var Rx = require('rx'); -var noOp = function() {}; -var Observable = Rx.Observable; -var _ = require('lodash'); var expect = require('chai').expect; -var $ref = falcor.Model.ref; -var $atom = falcor.Model.atom; -var $error = falcor.Model.error; +var atom = Model.atom; describe('getCache', function() { + it("should serialize the cache", function() { var model = new Model({ cache: cacheGenerator(0, 1) }); var cache = model.getCache(); @@ -25,5 +20,21 @@ describe('getCache', function() { clean(cache); expect(cache).to.deep.equals(cacheGenerator(3, 1)); }); + + it('should serialize a cache with undefined values.', function() { + var model = new Model({ + cache: { + test: 'foo' + } + }); + + // mimicking cache clean-up + model._root.cache.testing = undefined; + var cache = model.getCache(); + clean(cache); + expect(cache).to.deep.equals({ + test: atom('foo', {$modelCreated: true}) + }); + }); }); diff --git a/test/get-core/index.js b/test/get-core/index.js index 47c66ac3..6c02a011 100644 --- a/test/get-core/index.js +++ b/test/get-core/index.js @@ -5,4 +5,5 @@ describe('Get Core', function() { require('./errors.spec'); require('./deref.spec'); require('./edges.spec'); + require('./get.cache.spec'); }); diff --git a/test/getCoreRunner.js b/test/getCoreRunner.js index 6c2e1c18..d72a6b21 100644 --- a/test/getCoreRunner.js +++ b/test/getCoreRunner.js @@ -25,10 +25,16 @@ module.exports = function(testConfig) { cache = cache(); } var source = testConfig.source; - var model = new Model({ - cache: cache, - source: source - }); + var model; + if (testConfig.model) { + model = testConfig.model; + } + else { + model = new Model({ + cache: cache, + source: source + }); + } if (testConfig.treatErrorsAsValues) { model = model.treatErrorsAsValues();