From ff3e75fe5ea8d439f87842d6289d7d331aa8290e Mon Sep 17 00:00:00 2001 From: Sergii Date: Tue, 17 Aug 2021 11:41:12 +0300 Subject: [PATCH] fix(ability): makes sure that other event handlers are not lost when last handler is unregistered --- packages/casl-ability/spec/ability.spec.js | 30 +++++++++++++++++----- packages/casl-ability/src/RuleIndex.ts | 14 ++++++---- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/packages/casl-ability/spec/ability.spec.js b/packages/casl-ability/spec/ability.spec.js index 7afc97680..3dd32698b 100755 --- a/packages/casl-ability/spec/ability.spec.js +++ b/packages/casl-ability/spec/ability.spec.js @@ -221,25 +221,41 @@ describe('Ability', () => { spy(() => results.push(0)), spy(() => results.push(1)), spy(() => results.push(2)), - spy(() => results.push(3)) ] const unsubscribe = [] unsubscribe[0] = ability.on('updated', handlers[0]) unsubscribe[1] = ability.on('updated', handlers[1]) - unsubscribe[2] = ability.on('updated', handlers[2]) - unsubscribe[3] = ability.on('updated', () => { - handlers[3]() - unsubscribe[2]() + unsubscribe[2] = ability.on('updated', () => { + handlers[2]() + unsubscribe[1]() }) ability.update([]) - expect(results).to.deep.equal([3, 2, 1, 0]) + expect(results).to.deep.equal([2, 1, 0]) results = [] ability.update([{ action: 'read', subject: 'all' }]) - expect(results).to.deep.equal([3, 1, 0]) + expect(results).to.deep.equal([2, 0]) + }) + + it('can unregister last handler', () => { + let results = [] + const handlers = [ + spy(() => results.push(0)), + spy(() => results.push(1)), + spy(() => results.push(2)), + ] + const unsubscribe = [] + + unsubscribe[0] = ability.on('updated', handlers[0]) + unsubscribe[1] = ability.on('updated', handlers[1]) + unsubscribe[2] = ability.on('updated', handlers[2]) + unsubscribe[2](); + ability.update([]) + + expect(results).to.deep.equal([1, 0]) }) }) }) diff --git a/packages/casl-ability/src/RuleIndex.ts b/packages/casl-ability/src/RuleIndex.ts index 3126111b5..5b137d71d 100644 --- a/packages/casl-ability/src/RuleIndex.ts +++ b/packages/casl-ability/src/RuleIndex.ts @@ -218,16 +218,20 @@ export class RuleIndex { event: T, handler: EventsMap>[T] ): Unsubscribe { - const head = this._events.get(event) || null; - const item = linkedItem(handler, head); + const tail = this._events.get(event) || null; + const item = linkedItem(handler, tail); this._events.set(event, item); return () => { - if (!item.next && !item.prev && this._events.get(event) === item) { + const currentTail = this._events.get(event); + + if (!item.next && !item.prev && currentTail === item) { this._events.delete(event); - } else { - unlinkItem(item); + } else if (item === currentTail) { + this._events.set(event, item.prev); } + + unlinkItem(item); }; }