Skip to content

Commit

Permalink
Warn loudly when non-string/number keys are used
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacs committed Nov 25, 2015
1 parent 2e2d3d4 commit ba1abfa
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 0 deletions.
18 changes: 18 additions & 0 deletions README.md
Expand Up @@ -24,6 +24,24 @@ If you put more stuff in it, then items will fall out.
If you try to put an oversized thing in it, then it'll fall out right
away.

## Keys should always be Strings or Numbers

Note: this module will print warnings to `console.error` if you use a
key that is not a String or Number. Because items are stored in an
object, which coerces keys to a string, it won't go well for you if
you try to use a key that is not a unique string, it'll cause surprise
collisions. For example:

```JavaScript
// Bad Example! Dont' do this!
var cache = LRU()
var a = {}
var b = {}
cache.set(a, 'this is a')
cache.set(b, 'this is b')
console.log(cache.get(a)) // prints: 'this is b'
```

## Options

* `max` The maximum size of the cache, checked by applying the length
Expand Down
16 changes: 16 additions & 0 deletions lib/lru-cache.js
Expand Up @@ -13,6 +13,14 @@ function hOP (obj, key) {

function naiveLength () { return 1 }

var didTypeWarning = false
function typeCheckKey(key) {
if (!didTypeWarning && typeof key !== 'string' && typeof key !== 'number') {
didTypeWarning = true
console.error(new TypeError("LRU: key must be a string or number. Almost certainly a bug! " + typeof key).stack)
}
}

function LRUCache (options) {
if (!(this instanceof LRUCache))
return new LRUCache(options)
Expand Down Expand Up @@ -163,6 +171,8 @@ LRUCache.prototype.dumpLru = function () {

LRUCache.prototype.set = function (key, value, maxAge) {
maxAge = maxAge || this._maxAge
typeCheckKey(key)

var now = maxAge ? Date.now() : 0
var len = this._lengthCalculator(value)

Expand Down Expand Up @@ -207,6 +217,7 @@ LRUCache.prototype.set = function (key, value, maxAge) {
}

LRUCache.prototype.has = function (key) {
typeCheckKey(key)
if (!hOP(this._cache, key)) return false
var hit = this._cache[key]
if (isStale(this, hit)) {
Expand All @@ -216,10 +227,12 @@ LRUCache.prototype.has = function (key) {
}

LRUCache.prototype.get = function (key) {
typeCheckKey(key)
return get(this, key, true)
}

LRUCache.prototype.peek = function (key) {
typeCheckKey(key)
return get(this, key, false)
}

Expand All @@ -230,6 +243,7 @@ LRUCache.prototype.pop = function () {
}

LRUCache.prototype.del = function (key) {
typeCheckKey(key)
del(this, this._cache[key])
}

Expand All @@ -241,6 +255,7 @@ LRUCache.prototype.load = function (arr) {
//A previous serialized cache has the most recent items first
for (var l = arr.length - 1; l >= 0; l-- ) {
var hit = arr[l]
typeCheckKey(hit.k)
var expiresAt = hit.e || 0
if (expiresAt === 0) {
//the item was created without expiration in a non aged cache
Expand All @@ -254,6 +269,7 @@ LRUCache.prototype.load = function (arr) {
}

function get (self, key, doUse) {
typeCheckKey(key)
var hit = self._cache[key]
if (hit) {
if (isStale(self, hit)) {
Expand Down

0 comments on commit ba1abfa

Please sign in to comment.