UNPKG

recoder-code

Version:

🚀 AI-powered development platform - Chat with 32+ models, build projects, automate workflows. Free models included!

356 lines (264 loc) • 7.5 kB
const errors = require('./lib/errors') class EventListener { constructor() { this.list = [] this.count = 0 } 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) { this.count++ ctx.emit('newListener', name, fn) // Emit BEFORE adding this.list.unshift([fn, once]) } remove(ctx, name, fn) { for (let i = 0, n = this.list.length; i < n; i++) { const l = this.list[i] if (l[0] === fn) { this.list.splice(i, 1) if (this.count === 1) delete ctx._events[name] ctx.emit('removeListener', name, fn) // Emit AFTER removing this.count-- return } } } removeAll(ctx, name) { const list = [...this.list] this.list = [] if (this.count === list.length) delete ctx._events[name] for (let i = list.length - 1; i >= 0; i--) { ctx.emit('removeListener', name, list[i][0]) // Emit AFTER removing } this.count -= list.length } emit(ctx, name, ...args) { const list = [...this.list] for (let i = 0, n = list.length; i < n; i++) { const l = list[i] if (l[1] === true) this.remove(ctx, name, l[0]) Reflect.apply(l[0], ctx, args) } return list.length > 0 } } function appendListener(ctx, name, fn, once) { const e = ctx._events[name] || (ctx._events[name] = new EventListener()) e.append(ctx, name, fn, once) return ctx } function prependListener(ctx, name, fn, once) { const e = ctx._events[name] || (ctx._events[name] = new EventListener()) e.prepend(ctx, name, fn, once) return ctx } function removeListener(ctx, name, fn) { const e = ctx._events[name] if (e !== undefined) e.remove(ctx, name, fn) return ctx } function throwUnhandledError(...args) { let err if (args.length > 0) err = args[0] if (err instanceof Error === false) err = errors.UNHANDLED_ERROR(err) if (Error.captureStackTrace) { Error.captureStackTrace(err, exports.prototype.emit) } queueMicrotask(() => { throw err }) } module.exports = exports = class EventEmitter { constructor() { this._events = Object.create(null) } addListener(name, fn) { return appendListener(this, name, fn, false) } addOnceListener(name, fn) { return appendListener(this, name, fn, true) } prependListener(name, fn) { return prependListener(this, name, fn, false) } prependOnceListener(name, fn) { return prependListener(this, name, fn, true) } removeListener(name, fn) { return removeListener(this, name, fn) } on(name, fn) { return appendListener(this, name, fn, false) } once(name, fn) { return appendListener(this, name, fn, true) } off(name, fn) { return removeListener(this, name, fn) } emit(name, ...args) { if (name === 'error' && this._events.error === undefined) { throwUnhandledError(...args) } const e = this._events[name] return e === undefined ? false : e.emit(this, name, ...args) } listeners(name) { const e = this._events[name] return e === undefined ? [] : [...e.list] } listenerCount(name) { const e = this._events[name] return e === undefined ? 0 : e.list.length } getMaxListeners() { return EventEmitter.defaultMaxListeners } setMaxListeners(n) {} removeAllListeners(name) { if (arguments.length === 0) { for (const key of Reflect.ownKeys(this._events)) { if (key === 'removeListener') continue this.removeAllListeners(key) } this.removeAllListeners('removeListener') } else { const e = this._events[name] if (e !== undefined) e.removeAll(this, name) } return this } } exports.EventEmitter = exports exports.errors = errors exports.defaultMaxListeners = 10 exports.on = function on(emitter, name, opts = {}) { const { signal } = opts if (signal && signal.aborted) { throw errors.OPERATION_ABORTED(signal.reason) } let error = null let done = false const events = [] const promises = [] emitter.on(name, onevent) if (name !== 'error') emitter.on('error', onerror) if (signal) signal.addEventListener('abort', onabort) return { next() { if (events.length) { return Promise.resolve({ value: events.shift(), done: false }) } if (error) { const err = error error = null return Promise.reject(err) } if (done) return onclose() return new Promise((resolve, reject) => promises.push({ resolve, reject }) ) }, return() { return onclose() }, throw(err) { return onerror(err) }, [Symbol.asyncIterator]() { return this } } function onevent(...args) { if (promises.length) { promises.shift().resolve({ value: args, done: false }) } else { events.push(args) } } function onerror(err) { if (promises.length) { promises.shift().reject(err) } else { error = err } return Promise.resolve({ done: true }) } function onabort() { onerror(errors.OPERATION_ABORTED(signal.reason)) } function onclose() { emitter.off(name, onevent) if (name !== 'error') emitter.off('error', onerror) if (signal) signal.removeEventListener('abort', onabort) done = true if (promises.length) promises.shift().resolve({ done: true }) return Promise.resolve({ done: true }) } } exports.once = function once(emitter, name, opts = {}) { const { signal } = opts if (signal && signal.aborted) { throw errors.OPERATION_ABORTED(signal.reason) } return new Promise((resolve, reject) => { if (name !== 'error') emitter.on('error', onerror) if (signal) signal.addEventListener('abort', onabort) emitter.once(name, (...args) => { if (name !== 'error') emitter.off('error', onerror) if (signal) signal.removeEventListener('abort', onabort) resolve(args) }) function onerror(err) { emitter.off('error', onerror) reject(err) } function onabort() { signal.removeEventListener('abort', onabort) onerror(errors.OPERATION_ABORTED(signal.reason)) } }) } exports.forward = function forward(from, to, names, opts = {}) { if (typeof names === 'string') names = [names] const { emit = to.emit.bind(to) } = opts 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]) } }) } 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) } } } }