Skip to content

Commit

Permalink
fix(ability): makes sure that other event handlers are not lost when …
Browse files Browse the repository at this point in the history
…last handler is unregistered
  • Loading branch information
stalniy committed Aug 17, 2021
1 parent 207f2be commit ff3e75f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 12 deletions.
30 changes: 23 additions & 7 deletions packages/casl-ability/spec/ability.spec.js
Expand Up @@ -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])
})
})
})
Expand Down
14 changes: 9 additions & 5 deletions packages/casl-ability/src/RuleIndex.ts
Expand Up @@ -218,16 +218,20 @@ export class RuleIndex<A extends Abilities, Conditions> {
event: T,
handler: EventsMap<Public<this>>[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);
};
}

Expand Down

0 comments on commit ff3e75f

Please sign in to comment.