Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules/
npm-debug.log
.DS_Store
coverage/
.vscode

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing newline at EOF. Reasoning

1 change: 1 addition & 0 deletions benchmark/cache/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use stict'
const ora = require('ora')
const Table = require('cli-table2')
const debug = require('logdown')()
Expand Down
1 change: 1 addition & 0 deletions benchmark/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use stict'
const ora = require('ora')
const Table = require('cli-table2')
const debug = require('logdown')()
Expand Down
1 change: 1 addition & 0 deletions benchmark/recursive-solo.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use stict'
const ora = require('ora')
const logger = require('logdown')()
const Table = require('cli-table2')
Expand Down
1 change: 1 addition & 0 deletions benchmark/strategy/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use stict'
const ora = require('ora')
const Table = require('cli-table2')
const debug = require('logdown')()
Expand Down
11 changes: 7 additions & 4 deletions benchmark/strategy/partial-application.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ function strategy (fn, options) {
return cache.get(cacheKey)
}

function variadic (fn, cache, serializer, ...args) {
function variadic (fn, cache, serializer) {
for (var _len = arguments.length, args = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
args[_key - 3] = arguments[_key];
}
var cacheKey = serializer(args)

if (!cache.has(cacheKey)) {
Expand All @@ -34,9 +37,9 @@ function strategy (fn, options) {
return cache.get(cacheKey)
}

var memoized = fn.length === 1
? monadic
: variadic
var memoized = fn.length === 1 ?
monadic :
variadic

memoized = memoized.bind(this, fn, options.cache.create(), options.serializer)
memoized.label = 'strategy: Partial application, cache: ' + options.cache.label + ', serializer: ' + options.serializer.label
Expand Down
16 changes: 16 additions & 0 deletions src/delme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
var memoize = require('../src')

var circular = {
a: 'foo'
}
circular.b = circular

function circularFunction (a) {
return a.a
}

var memoizedCircularFunction = memoize(circularFunction)

// Assertions
var one = memoizedCircularFunction(circular)
var two = memoizedCircularFunction(circular)
69 changes: 57 additions & 12 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'
const util = require('util')
//
// Main
//
Expand Down Expand Up @@ -57,7 +59,11 @@ function strategyDefault (fn, options) {
return cache.get(cacheKey)
}

function variadic (fn, cache, serializer, ...args) {
function variadic (fn, cache, serializerrgs) {
for (var _len = arguments.length, args = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
args[_key - 3] = arguments[_key];
}

var cacheKey = serializer(args)

if (!cache.has(cacheKey)) {
Expand All @@ -69,9 +75,9 @@ function strategyDefault (fn, options) {
return cache.get(cacheKey)
}

var memoized = fn.length === 1
? monadic
: variadic
var memoized = fn.length === 1 ?
monadic :
variadic

memoized = memoized.bind(
this,
Expand All @@ -89,36 +95,75 @@ function strategyDefault (fn, options) {
// Serializer
//

function serializerDefault (...args) {
return JSON.stringify(args)
function customReplacer(args) {
var cache = [];
const replacer = function (key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
// Circular reference found, discard key
return
}
// Store value in our collection
cache.push(value)
}
}
cache = null // Enable garbage collection
return replacer
}

//
// Serializer
//

function serializerDefault () {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key]
}

try {
// try the fastest way first.
return JSON.stringify(args)
} catch (error) {
if (error instanceof TypeError &&
error.message === 'Converting circular structure to JSON') {
// if node
if (util && util.inspect) {
return JSON.stringify(util.inspect(args))
} else {
return JSON.stringify(args, customReplacer)
}
} else {
throw error // let others bubble up
}
}
}

//
// Cache
//

class ObjectWithoutPrototypeCache {
constructor () {
constructor() {
this.cache = Object.create(null)
}

has (key) {
has(key) {
return (key in this.cache)
}

get (key) {
get(key) {
return this.cache[key]
}

set (key, value) {
set(key, value) {
this.cache[key] = value
}

delete (key) {
delete(key) {
delete this.cache[key]
}
}

const cacheDefault = {
create: () => new ObjectWithoutPrototypeCache()
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EOF

18 changes: 18 additions & 0 deletions src/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,21 @@ test('inject custom serializer', function () {

expect(serializerMethodExecutionCount).toBe(2)
})

test('memoize circular JSON', function () {
var circular = {
a: 'foo'
}
circular.b = circular

function circularFunction(a) {
return a.a
}

var memoizedCircularFunction = memoize(circularFunction)

// Assertions

expect(memoizedCircularFunction(circular)).toBe("foo")
expect(memoizedCircularFunction(circular)).toBe("foo")
})