You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
78 lines
1.9 KiB
78 lines
1.9 KiB
export const STOP_PROPAGATION = "stop_propagation";
|
|
|
|
export class Signal {
|
|
constructor() {
|
|
this.receivers = [];
|
|
this.modifyCount = 0;
|
|
}
|
|
|
|
/**
|
|
* Adds a new signal listener
|
|
* @param {function} receiver
|
|
* @param {object} scope
|
|
*/
|
|
add(receiver, scope = null) {
|
|
assert(receiver, "receiver is null");
|
|
this.receivers.push({ receiver, scope });
|
|
++this.modifyCount;
|
|
}
|
|
|
|
/**
|
|
* Adds a new signal listener
|
|
* @param {function} receiver
|
|
* @param {object} scope
|
|
*/
|
|
addToTop(receiver, scope = null) {
|
|
assert(receiver, "receiver is null");
|
|
this.receivers.unshift({ receiver, scope });
|
|
++this.modifyCount;
|
|
}
|
|
|
|
/**
|
|
* Dispatches the signal
|
|
* @param {...any} payload
|
|
*/
|
|
dispatch() {
|
|
const modifyState = this.modifyCount;
|
|
|
|
const n = this.receivers.length;
|
|
for (let i = 0; i < n; ++i) {
|
|
const { receiver, scope } = this.receivers[i];
|
|
if (receiver.apply(scope, arguments) === STOP_PROPAGATION) {
|
|
return STOP_PROPAGATION;
|
|
}
|
|
|
|
if (modifyState !== this.modifyCount) {
|
|
// Signal got modified during iteration
|
|
return STOP_PROPAGATION;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes a receiver
|
|
* @param {function} receiver
|
|
*/
|
|
remove(receiver) {
|
|
let index = null;
|
|
const n = this.receivers.length;
|
|
for (let i = 0; i < n; ++i) {
|
|
if (this.receivers[i].receiver === receiver) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
assert(index !== null, "Receiver not found in list");
|
|
this.receivers.splice(index, 1);
|
|
++this.modifyCount;
|
|
}
|
|
|
|
/**
|
|
* Removes all receivers
|
|
*/
|
|
removeAll() {
|
|
this.receivers = [];
|
|
++this.modifyCount;
|
|
}
|
|
}
|