From aa68ee577b4fe37fb3838c9463cd92cffb3d88b2 Mon Sep 17 00:00:00 2001 From: ipaterson Date: Fri, 16 Sep 2016 15:22:13 -0400 Subject: [PATCH 1/2] Added failing test showing that an autobound method does not memoize properly --- test/unit/decorate.spec.js | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/unit/decorate.spec.js b/test/unit/decorate.spec.js index dfa9f54..ca47044 100644 --- a/test/unit/decorate.spec.js +++ b/test/unit/decorate.spec.js @@ -1,3 +1,4 @@ +import autobind from '../../lib/autobind'; import decorate from '../../lib/decorate'; import { memoize } from 'lodash'; @@ -38,6 +39,13 @@ describe('@decorate', function () { callCount++; return this; } + + @decorate(memoize) + @autobind + getFooAutobound() { + callCount++; + return this; + } } }); @@ -66,9 +74,39 @@ describe('@decorate', function () { foo1Result.should.not.equal(foo2Result); foo1Result.should.equal(foo1); foo2Result.should.equal(foo2); + }); + + it('is applied in a way that allows memoization', function () { + const foo1 = new Foo(); + const foo2 = new Foo(); + + const foo1Result = foo1.getFoo(); + const foo2Result = foo2.getFoo(); foo1.getFoo(); callCount.should.equal(2); + + foo1.getFoo(1); + foo1.getFoo(2); + + callCount.should.equal(4); + }); + + it('is applied in a way that allows memoization when autobound', function () { + const foo1 = new Foo(); + const foo2 = new Foo(); + + const foo1Result = foo1.getFooAutobound(); + const foo2Result = foo2.getFooAutobound(); + + foo1.getFooAutobound(); + + callCount.should.equal(2); + + foo1.getFooAutobound(1); + foo1.getFooAutobound(2); + + callCount.should.equal(4); }); }); From 6490aa3c14689883aa84d2c375c99814a53b1831 Mon Sep 17 00:00:00 2001 From: ipaterson Date: Fri, 16 Sep 2016 15:24:31 -0400 Subject: [PATCH 2/2] Avoid redecorating on every invocation when applied following a decorator that produces a getter --- src/decorate.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/decorate.js b/src/decorate.js index 4111fb0..e84265e 100644 --- a/src/decorate.js +++ b/src/decorate.js @@ -13,22 +13,20 @@ function handleDescriptor(target, key, descriptor, [decorator, ...args]) { get() { const fn = isGetter ? originalGet.call(this) : originalValue; const value = decorator.call(this, fn, ...args); + const desc = { + configurable, + enumerable, + value, + writable + }; if (isGetter) { - return value; - } else { - const desc = { - configurable, - enumerable - }; - - desc.value = value; - desc.writable = writable; + desc.writable = true; + } - Object.defineProperty(this, key, desc); + Object.defineProperty(this, key, desc); - return value; - } + return value; }, set: isGetter ? originalSet : createDefaultSetter() };