dt_automate/vendor/github.com/playwright-community/playwright-go/event_emitter.go
2025-02-19 18:30:19 +08:00

164 lines
3.3 KiB
Go

package playwright
import (
"math"
"reflect"
"slices"
"sync"
)
type EventEmitter interface {
Emit(name string, payload ...interface{}) bool
ListenerCount(name string) int
On(name string, handler interface{})
Once(name string, handler interface{})
RemoveListener(name string, handler interface{})
RemoveListeners(name string)
}
type (
eventEmitter struct {
eventsMutex sync.Mutex
events map[string]*eventRegister
hasInit bool
}
eventRegister struct {
sync.Mutex
listeners []listener
}
listener struct {
handler interface{}
once bool
}
)
func NewEventEmitter() EventEmitter {
return &eventEmitter{}
}
func (e *eventEmitter) Emit(name string, payload ...interface{}) (hasListener bool) {
e.eventsMutex.Lock()
e.init()
evt, ok := e.events[name]
if !ok {
e.eventsMutex.Unlock()
return
}
e.eventsMutex.Unlock()
return evt.callHandlers(payload...) > 0
}
func (e *eventEmitter) Once(name string, handler interface{}) {
e.addEvent(name, handler, true)
}
func (e *eventEmitter) On(name string, handler interface{}) {
e.addEvent(name, handler, false)
}
func (e *eventEmitter) RemoveListener(name string, handler interface{}) {
e.eventsMutex.Lock()
defer e.eventsMutex.Unlock()
e.init()
if evt, ok := e.events[name]; ok {
evt.Lock()
defer evt.Unlock()
evt.removeHandler(handler)
}
}
func (e *eventEmitter) RemoveListeners(name string) {
e.eventsMutex.Lock()
defer e.eventsMutex.Unlock()
e.init()
delete(e.events, name)
}
// ListenerCount count the listeners by name, count all if name is empty
func (e *eventEmitter) ListenerCount(name string) int {
e.eventsMutex.Lock()
defer e.eventsMutex.Unlock()
e.init()
if name != "" {
evt, ok := e.events[name]
if !ok {
return 0
}
return evt.count()
}
count := 0
for key := range e.events {
count += e.events[key].count()
}
return count
}
func (e *eventEmitter) addEvent(name string, handler interface{}, once bool) {
e.eventsMutex.Lock()
defer e.eventsMutex.Unlock()
e.init()
if _, ok := e.events[name]; !ok {
e.events[name] = &eventRegister{
listeners: make([]listener, 0),
}
}
e.events[name].addHandler(handler, once)
}
func (e *eventEmitter) init() {
if !e.hasInit {
e.events = make(map[string]*eventRegister, 0)
e.hasInit = true
}
}
func (er *eventRegister) addHandler(handler interface{}, once bool) {
er.Lock()
defer er.Unlock()
er.listeners = append(er.listeners, listener{handler: handler, once: once})
}
func (er *eventRegister) count() int {
er.Lock()
defer er.Unlock()
return len(er.listeners)
}
func (er *eventRegister) removeHandler(handler interface{}) {
handlerPtr := reflect.ValueOf(handler).Pointer()
er.listeners = slices.DeleteFunc(er.listeners, func(l listener) bool {
return reflect.ValueOf(l.handler).Pointer() == handlerPtr
})
}
func (er *eventRegister) callHandlers(payloads ...interface{}) int {
payloadV := make([]reflect.Value, 0)
for _, p := range payloads {
payloadV = append(payloadV, reflect.ValueOf(p))
}
handle := func(l listener) {
handlerV := reflect.ValueOf(l.handler)
handlerV.Call(payloadV[:int(math.Min(float64(handlerV.Type().NumIn()), float64(len(payloadV))))])
}
er.Lock()
defer er.Unlock()
count := len(er.listeners)
for _, l := range er.listeners {
if l.once {
defer er.removeHandler(l.handler)
}
handle(l)
}
return count
}