Skip to content

Commit

Permalink
spread operator detection. impliments #5
Browse files Browse the repository at this point in the history
  • Loading branch information
theKashey committed Mar 13, 2018
1 parent 5f3fdd8 commit a42d80c
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 15 deletions.
3 changes: 2 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"presets": ["env"]
"presets": ["env"],
"plugins": ["transform-object-rest-spread"]
}
31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ lodash.memoize x 3.941.183
fast-memoize x 34.699.858
memoize-state x 4.615.104
```
> this 4 millions operations per second? A bit more that enough
## The common memoization
Memoize-state is not a best fit for a common case. It is designed to handle
Expand Down Expand Up @@ -271,11 +272,37 @@ and numbers differs.
```
memoize-state is comparable with lodash and underscore, even in this example.

## Spread no-op
>memoize-state: object spread detected in XXX. Consider refactoring.
Memoize state could not properly work if you "spread" state
```js
const mapStateToProps = ({prop,i,need,...rest}) =>....
//or
const mapStateToProps = (state, props) => ({ ...state, ...props })
//or
const mapState = ({ page, direction, ...state }) => ({
page,
direction,
isLoading: isLoading(state)
})
```
It will assume, that you need ALL the keys, meanwhile - you could not.

Workaround - refactor the code
```js
const mapState = state => ({
page: state.page,
direction: state.direction,
isLoading: isLoading(state)
})
```

See [issue](https://github.com/theKashey/memoize-state/issues/3#issuecomment-372226092) for more details

## Compatibility

__NOT__ compatible with __IE11__. One have to provide a proxy polyfill to make this work.
See https://github.com/GoogleChrome/proxy-polyfill
IE11/Android compatible. Contains [proxy-polyfill](https://github.com/GoogleChrome/proxy-polyfill) inside.

# Licence
MIT
12 changes: 12 additions & 0 deletions _tests/smoke.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {expect} from 'chai';
import {isProxyfied} from 'proxyequal';
import sinon from 'sinon';
import memoize, {shouldBePure, isThisPure} from '../src/index';

describe('memoize-proxy', () => {
Expand Down Expand Up @@ -394,6 +395,17 @@ describe('memoize-proxy', () => {
expect(isThisPure(() => fun3(array))).to.be.true;
});

it('should report about spread operator', () => {
const mapState = ({a, ...rest}) => a;
const fn = memoize(mapState);
const spy = sinon.stub(console, "warn");
fn({a: 1, b: 1});

sinon.assert.calledWith(spy, 'memoize-state: object spread detected in ', mapState, '. Consider refactoring.');

spy.restore();
});

describe('shouldBePure', () => {
const A = [1, 2, 3];

Expand Down
7 changes: 3 additions & 4 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,6 @@ function memoize(func) {
return func.call.apply(func, [this].concat(args));
}

//let result = (options.shallowCheck && shallowHit(cache, args)) || (options.equalCheck && equalHit(cache, args));
var result = shallowEqualHit(cache, args);

lastCallWasMemoized = Boolean(result);
Expand Down Expand Up @@ -365,7 +364,7 @@ function memoize(func) {
Object.defineProperty(functor, 'cacheStatistics', {
get: function get() {
return {
ratio: cacheHit / cacheHit,
ratio: cacheHit / cacheMiss,
memoizationDisabled: memoizationDisabled,

cacheHit: cacheHit,
Expand Down Expand Up @@ -435,7 +434,7 @@ var shallowTest = function shallowTest(a, b) {
}

if (errors.length && errorMessage) {
console.error.call(console, errorMessage.map(function (err) {
console.error.apply(console, errorMessage.map(function (err) {
return typeof err === 'string' ? err.replace('$KEYS$', errors.join(',')) : err;
}));
}
Expand Down Expand Up @@ -466,7 +465,7 @@ var shallBePure = exports.shallBePure = function shallBePure(fnCall) {
if (functor.isPure && lastResult) {
if (lastResult !== fresult) {
if (lastMemoizedResult === mresult) {
functor.isPure = shallowTest(lastResult, fresult, message + ' `' + fnCall.name + '`\'s result is not equal at [$KEYS$], while should be equal');
functor.isPure = shallowTest(lastResult, fresult, message, fnCall, '`s result is not equal at [$KEYS$], while should be equal');
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-eslint": "^8.2.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-env": "^1.6.1",
"benchmark": "^2.1.4",
"chai": "^4.1.2",
Expand All @@ -45,6 +46,6 @@
},
"homepage": "https://github.com/theKashey/memoize-state#readme",
"dependencies": {
"proxyequal": "^1.4.0"
"proxyequal": "^1.4.1"
}
}
16 changes: 12 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,11 @@ function callIn(that, cache, args, func, memoizationDepth, proxyMap = []) {
});
const newArgs = args.map((arg, index) => proxies[index] ? proxies[index].state : arg);
const preResult = func.call(that, ...newArgs);
let spreadDetected = false;
const affected = proxies
.map(proxy => {
if (proxy) {
spreadDetected |= proxy.spreadDetected;
const affected = proxy.affected || emptyArray;
return {
useAffected: [...affected],
Expand All @@ -135,6 +137,13 @@ function callIn(that, cache, args, func, memoizationDepth, proxyMap = []) {
} else {
updateCacheLine(cache, 0, cacheLine);
}

if (spreadDetected) {
if (process.env.NODE_ENV !== 'production') {
console.warn('memoize-state: object spread detected in ', func, '. Consider refactoring.');
}
}

return result;
}

Expand Down Expand Up @@ -223,7 +232,6 @@ function memoize(func, _options = {}) {
return func.call(this, ...args);
}

//let result = (options.shallowCheck && shallowHit(cache, args)) || (options.equalCheck && equalHit(cache, args));
let result = (shallowEqualHit(cache, args));

lastCallWasMemoized = Boolean(result);
Expand Down Expand Up @@ -285,7 +293,7 @@ function memoize(func, _options = {}) {

Object.defineProperty(functor, 'cacheStatistics', {
get: () => ({
ratio: cacheHit / cacheHit,
ratio: cacheHit / cacheMiss,
memoizationDisabled,

cacheHit,
Expand Down Expand Up @@ -351,7 +359,7 @@ const shallowTest = (a, b, ...errorMessage) => {
}

if (errors.length && errorMessage) {
console.error.call(console, errorMessage.map(err => typeof err === 'string' ? err.replace('$KEYS$', errors.join(',')) : err))
console.error.apply(console, errorMessage.map(err => typeof err === 'string' ? err.replace('$KEYS$', errors.join(',')) : err))
}
return !errors.length;
};
Expand All @@ -376,7 +384,7 @@ export const shallBePure = (fnCall, message = 'shouldBePure') => {
if (functor.isPure && lastResult) {
if (lastResult !== fresult) {
if (lastMemoizedResult === mresult) {
functor.isPure = shallowTest(lastResult, fresult, message + ' `' + fnCall.name + '`\'s result is not equal at [$KEYS$], while should be equal');
functor.isPure = shallowTest(lastResult, fresult, message, fnCall, '`s result is not equal at [$KEYS$], while should be equal');
}
}
}
Expand Down
17 changes: 14 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,10 @@ babel-plugin-syntax-exponentiation-operator@^6.8.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"

babel-plugin-syntax-object-rest-spread@^6.8.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"

babel-plugin-syntax-trailing-function-commas@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
Expand Down Expand Up @@ -590,6 +594,13 @@ babel-plugin-transform-exponentiation-operator@^6.22.0:
babel-plugin-syntax-exponentiation-operator "^6.8.0"
babel-runtime "^6.22.0"

babel-plugin-transform-object-rest-spread@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06"
dependencies:
babel-plugin-syntax-object-rest-spread "^6.8.0"
babel-runtime "^6.26.0"

babel-plugin-transform-regenerator@^6.22.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
Expand Down Expand Up @@ -1944,9 +1955,9 @@ proxy-polyfill@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/proxy-polyfill/-/proxy-polyfill-0.2.0.tgz#3c9d2a0fe7682c3903674e304f5d27797b711446"

proxyequal@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/proxyequal/-/proxyequal-1.4.0.tgz#b613fd5c4adb8692627db38201a11e54fb211551"
proxyequal@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/proxyequal/-/proxyequal-1.4.1.tgz#8b1492aba54a3f54ebb3406c5df7b825ddf1545a"
dependencies:
proxy-polyfill "^0.2.0"
search-trie "^1.0.0"
Expand Down

0 comments on commit a42d80c

Please sign in to comment.