Support add/removing listeners whilst firing event

If you removed an event listener whilst it was being fired, this would alter the
list of handlers, which would cause the fireEvent function to read past the end
of the array (and to skip the next listener). Now, we clone the array of
listeners before firing, so adding/removing listeners has no effect on an
already firing event.