First adaptation pass
This commit is contained in:
+95
-72
@@ -1,24 +1,24 @@
|
||||
const errors = require('./lib/errors')
|
||||
|
||||
class EventListener {
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.list = []
|
||||
this.count = 0
|
||||
}
|
||||
|
||||
append (ctx, name, fn, once) {
|
||||
append(ctx, name, fn, once) {
|
||||
this.count++
|
||||
ctx.emit('newListener', name, fn) // Emit BEFORE adding
|
||||
this.list.push([fn, once])
|
||||
}
|
||||
|
||||
prepend (ctx, name, fn, once) {
|
||||
prepend(ctx, name, fn, once) {
|
||||
this.count++
|
||||
ctx.emit('newListener', name, fn) // Emit BEFORE adding
|
||||
this.list.unshift([fn, once])
|
||||
}
|
||||
|
||||
remove (ctx, name, fn) {
|
||||
remove(ctx, name, fn) {
|
||||
for (let i = 0, n = this.list.length; i < n; i++) {
|
||||
const l = this.list[i]
|
||||
|
||||
@@ -35,7 +35,7 @@ class EventListener {
|
||||
}
|
||||
}
|
||||
|
||||
removeAll (ctx, name) {
|
||||
removeAll(ctx, name) {
|
||||
const list = [...this.list]
|
||||
this.list = []
|
||||
|
||||
@@ -48,7 +48,7 @@ class EventListener {
|
||||
this.count -= list.length
|
||||
}
|
||||
|
||||
emit (ctx, name, ...args) {
|
||||
emit(ctx, name, ...args) {
|
||||
const list = [...this.list]
|
||||
|
||||
for (let i = 0, n = list.length; i < n; i++) {
|
||||
@@ -56,32 +56,35 @@ class EventListener {
|
||||
|
||||
if (l[1] === true) this.remove(ctx, name, l[0])
|
||||
|
||||
l[0].call(ctx, ...args)
|
||||
Reflect.apply(l[0], ctx, args)
|
||||
}
|
||||
|
||||
return list.length > 0
|
||||
}
|
||||
}
|
||||
|
||||
function appendListener (ctx, name, fn, once) {
|
||||
function appendListener(ctx, name, fn, once) {
|
||||
if (ctx._events === undefined) ctx._events = Object.create(null)
|
||||
const e = ctx._events[name] || (ctx._events[name] = new EventListener())
|
||||
e.append(ctx, name, fn, once)
|
||||
return ctx
|
||||
}
|
||||
|
||||
function prependListener (ctx, name, fn, once) {
|
||||
function prependListener(ctx, name, fn, once) {
|
||||
if (ctx._events === undefined) ctx._events = Object.create(null)
|
||||
const e = ctx._events[name] || (ctx._events[name] = new EventListener())
|
||||
e.prepend(ctx, name, fn, once)
|
||||
return ctx
|
||||
}
|
||||
|
||||
function removeListener (ctx, name, fn) {
|
||||
function removeListener(ctx, name, fn) {
|
||||
if (ctx._events === undefined) return ctx
|
||||
const e = ctx._events[name]
|
||||
if (e !== undefined) e.remove(ctx, name, fn)
|
||||
return ctx
|
||||
}
|
||||
|
||||
function throwUnhandledError (...args) {
|
||||
function throwUnhandledError(...args) {
|
||||
let err
|
||||
|
||||
if (args.length > 0) err = args[0]
|
||||
@@ -92,69 +95,77 @@ function throwUnhandledError (...args) {
|
||||
Error.captureStackTrace(err, exports.prototype.emit)
|
||||
}
|
||||
|
||||
queueMicrotask(() => { throw err })
|
||||
queueMicrotask(() => {
|
||||
throw err
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = exports = class EventEmitter {
|
||||
constructor () {
|
||||
constructor() {
|
||||
this._events = Object.create(null)
|
||||
}
|
||||
|
||||
addListener (name, fn) {
|
||||
addListener(name, fn) {
|
||||
return appendListener(this, name, fn, false)
|
||||
}
|
||||
|
||||
addOnceListener (name, fn) {
|
||||
addOnceListener(name, fn) {
|
||||
return appendListener(this, name, fn, true)
|
||||
}
|
||||
|
||||
prependListener (name, fn) {
|
||||
prependListener(name, fn) {
|
||||
return prependListener(this, name, fn, false)
|
||||
}
|
||||
|
||||
prependOnceListener (name, fn) {
|
||||
prependOnceListener(name, fn) {
|
||||
return prependListener(this, name, fn, true)
|
||||
}
|
||||
|
||||
removeListener (name, fn) {
|
||||
removeListener(name, fn) {
|
||||
return removeListener(this, name, fn)
|
||||
}
|
||||
|
||||
on (name, fn) {
|
||||
on(name, fn) {
|
||||
return appendListener(this, name, fn, false)
|
||||
}
|
||||
|
||||
once (name, fn) {
|
||||
once(name, fn) {
|
||||
return appendListener(this, name, fn, true)
|
||||
}
|
||||
|
||||
off (name, fn) {
|
||||
off(name, fn) {
|
||||
return removeListener(this, name, fn)
|
||||
}
|
||||
|
||||
emit (name, ...args) {
|
||||
if (name === 'error' && this._events.error === undefined) throwUnhandledError(...args)
|
||||
emit(name, ...args) {
|
||||
if (name === 'error' && this._events !== undefined && this._events.error === undefined) {
|
||||
throwUnhandledError(...args)
|
||||
}
|
||||
|
||||
if (this._events === undefined) return false
|
||||
const e = this._events[name]
|
||||
return e === undefined ? false : e.emit(this, name, ...args)
|
||||
}
|
||||
|
||||
listeners (name) {
|
||||
listeners(name) {
|
||||
if (this._events === undefined) return []
|
||||
const e = this._events[name]
|
||||
return e === undefined ? [] : [...e.list]
|
||||
}
|
||||
|
||||
listenerCount (name) {
|
||||
listenerCount(name) {
|
||||
if (this._events === undefined) return 0
|
||||
const e = this._events[name]
|
||||
return e === undefined ? 0 : e.list.length
|
||||
}
|
||||
|
||||
getMaxListeners () {
|
||||
getMaxListeners() {
|
||||
return EventEmitter.defaultMaxListeners
|
||||
}
|
||||
|
||||
setMaxListeners (n) {}
|
||||
setMaxListeners(n) {}
|
||||
|
||||
removeAllListeners (name) {
|
||||
removeAllListeners(name) {
|
||||
if (arguments.length === 0) {
|
||||
for (const key of Reflect.ownKeys(this._events)) {
|
||||
if (key === 'removeListener') continue
|
||||
@@ -175,10 +186,8 @@ exports.errors = errors
|
||||
|
||||
exports.defaultMaxListeners = 10
|
||||
|
||||
exports.on = function on (emitter, name, opts = {}) {
|
||||
const {
|
||||
signal
|
||||
} = opts
|
||||
exports.on = function on(emitter, name, opts = {}) {
|
||||
const { signal } = opts
|
||||
|
||||
if (signal && signal.aborted) {
|
||||
throw errors.OPERATION_ABORTED(signal.reason)
|
||||
@@ -197,7 +206,7 @@ exports.on = function on (emitter, name, opts = {}) {
|
||||
if (signal) signal.addEventListener('abort', onabort)
|
||||
|
||||
return {
|
||||
next () {
|
||||
next() {
|
||||
if (events.length) {
|
||||
return Promise.resolve({ value: events.shift(), done: false })
|
||||
}
|
||||
@@ -212,25 +221,23 @@ exports.on = function on (emitter, name, opts = {}) {
|
||||
|
||||
if (done) return onclose()
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
promises.push({ resolve, reject })
|
||||
)
|
||||
return new Promise((resolve, reject) => promises.push({ resolve, reject }))
|
||||
},
|
||||
|
||||
return () {
|
||||
return() {
|
||||
return onclose()
|
||||
},
|
||||
|
||||
throw (err) {
|
||||
throw(err) {
|
||||
return onerror(err)
|
||||
},
|
||||
|
||||
[Symbol.asyncIterator] () {
|
||||
[Symbol.asyncIterator]() {
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
function onevent (...args) {
|
||||
function onevent(...args) {
|
||||
if (promises.length) {
|
||||
promises.shift().resolve({ value: args, done: false })
|
||||
} else {
|
||||
@@ -238,7 +245,7 @@ exports.on = function on (emitter, name, opts = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
function onerror (err) {
|
||||
function onerror(err) {
|
||||
if (promises.length) {
|
||||
promises.shift().reject(err)
|
||||
} else {
|
||||
@@ -248,11 +255,11 @@ exports.on = function on (emitter, name, opts = {}) {
|
||||
return Promise.resolve({ done: true })
|
||||
}
|
||||
|
||||
function onabort () {
|
||||
function onabort() {
|
||||
onerror(errors.OPERATION_ABORTED(signal.reason))
|
||||
}
|
||||
|
||||
function onclose () {
|
||||
function onclose() {
|
||||
emitter.off(name, onevent)
|
||||
|
||||
if (name !== 'error') emitter.off('error', onerror)
|
||||
@@ -267,10 +274,8 @@ exports.on = function on (emitter, name, opts = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
exports.once = function once (emitter, name, opts = {}) {
|
||||
const {
|
||||
signal
|
||||
} = opts
|
||||
exports.once = function once(emitter, name, opts = {}) {
|
||||
const { signal } = opts
|
||||
|
||||
if (signal && signal.aborted) {
|
||||
throw errors.OPERATION_ABORTED(signal.reason)
|
||||
@@ -289,13 +294,13 @@ exports.once = function once (emitter, name, opts = {}) {
|
||||
resolve(args)
|
||||
})
|
||||
|
||||
function onerror (err) {
|
||||
function onerror(err) {
|
||||
emitter.off('error', onerror)
|
||||
|
||||
reject(err)
|
||||
}
|
||||
|
||||
function onabort () {
|
||||
function onabort() {
|
||||
signal.removeEventListener('abort', onabort)
|
||||
|
||||
onerror(errors.OPERATION_ABORTED(signal.reason))
|
||||
@@ -303,34 +308,52 @@ exports.once = function once (emitter, name, opts = {}) {
|
||||
})
|
||||
}
|
||||
|
||||
exports.forward = function forward (from, to, names, opts = {}) {
|
||||
exports.forward = function forward(from, to, names, opts = {}) {
|
||||
if (typeof names === 'string') names = [names]
|
||||
|
||||
const {
|
||||
emit = to.emit.bind(to)
|
||||
} = opts
|
||||
const { emit = to.emit.bind(to) } = opts
|
||||
|
||||
const listeners = names.map((name) => function onevent (...args) {
|
||||
emit(name, ...args)
|
||||
const listeners = names.map(
|
||||
(name) =>
|
||||
function onevent(...args) {
|
||||
emit(name, ...args)
|
||||
}
|
||||
)
|
||||
|
||||
to.on('newListener', (name) => {
|
||||
const i = names.indexOf(name)
|
||||
|
||||
if (i !== -1 && to.listenerCount(name) === 0) {
|
||||
from.on(name, listeners[i])
|
||||
}
|
||||
}).on('removeListener', (name) => {
|
||||
const i = names.indexOf(name)
|
||||
|
||||
if (i !== -1 && to.listenerCount(name) === 0) {
|
||||
from.off(name, listeners[i])
|
||||
}
|
||||
})
|
||||
|
||||
to
|
||||
.on('newListener', (name) => {
|
||||
const i = names.indexOf(name)
|
||||
|
||||
if (i !== -1 && to.listenerCount(name) === 0) {
|
||||
from.on(name, listeners[i])
|
||||
}
|
||||
})
|
||||
.on('removeListener', (name) => {
|
||||
const i = names.indexOf(name)
|
||||
|
||||
if (i !== -1 && to.listenerCount(name) === 0) {
|
||||
from.off(name, listeners[i])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
exports.listenerCount = function listenerCount (emitter, name) {
|
||||
exports.listenerCount = function listenerCount(emitter, name) {
|
||||
return emitter.listenerCount(name)
|
||||
}
|
||||
|
||||
exports.getMaxListeners = function getMaxListeners(emitter) {
|
||||
if (typeof emitter.getMaxListeners === 'function') {
|
||||
return emitter.getMaxListeners()
|
||||
}
|
||||
|
||||
return exports.defaultMaxListeners
|
||||
}
|
||||
|
||||
exports.setMaxListeners = function setMaxListeners(n, ...emitters) {
|
||||
if (emitters.length === 0) exports.defaultMaxListeners = n
|
||||
else {
|
||||
for (const emitter of emitters) {
|
||||
if (typeof emitter.setMaxListeners === 'function') {
|
||||
emitter.setMaxListeners(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user