diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bun.js/events.exports.js | 464 | ||||
-rw-r--r-- | src/bun.js/module_loader.zig | 10 |
2 files changed, 1 insertions, 473 deletions
diff --git a/src/bun.js/events.exports.js b/src/bun.js/events.exports.js deleted file mode 100644 index 3e4536ff2..000000000 --- a/src/bun.js/events.exports.js +++ /dev/null @@ -1,464 +0,0 @@ -// Reimplementation of https://nodejs.org/api/events.html -// Reference: https://github.com/nodejs/node/blob/main/lib/events.js -var { isPromise, Array, Object } = import.meta.primordials; -const SymbolFor = Symbol.for; -const ObjectDefineProperty = Object.defineProperty; -const kCapture = Symbol("kCapture"); -const kErrorMonitor = SymbolFor("events.errorMonitor"); -const kMaxEventTargetListeners = Symbol("events.maxEventTargetListeners"); -const kMaxEventTargetListenersWarned = Symbol("events.maxEventTargetListenersWarned"); -const kWatermarkData = SymbolFor("nodejs.watermarkData"); -const kRejection = SymbolFor("nodejs.rejection"); -const captureRejectionSymbol = SymbolFor("nodejs.rejection"); -const ArrayPrototypeSlice = Array.prototype.slice; - -var defaultMaxListeners = 10; - -// EventEmitter must be a standard function because some old code will do weird tricks like `EventEmitter.apply(this)`. -function EventEmitter(opts) { - if (this._events === undefined || this._events === this.__proto__._events) { - this._events = { __proto__: null }; - this._eventsCount = 0; - } - - this._maxListeners ??= undefined; - if ( - (this[kCapture] = opts?.captureRejections ? Boolean(opts?.captureRejections) : EventEmitter.prototype[kCapture]) - ) { - this.emit = emitWithRejectionCapture; - } -} - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._eventsCount = 0; -EventEmitter.prototype._maxListeners = undefined; -EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { - validateNumber(n, "setMaxListeners", 0); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.getMaxListeners = function getMaxListeners() { - return this._maxListeners ?? defaultMaxListeners; -}; - -function emitError(emitter, args) { - var { _events: events } = emitter; - args[0] ??= new Error("Unhandled error."); - if (!events) throw args[0]; - var errorMonitor = events[kErrorMonitor]; - if (errorMonitor) { - for (var handler of ArrayPrototypeSlice.call(errorMonitor)) { - handler.apply(emitter, args); - } - } - var handlers = events.error; - if (!handlers) throw args[0]; - for (var handler of ArrayPrototypeSlice.call(handlers)) { - handler.apply(emitter, args); - } - return true; -} - -function addCatch(emitter, promise, type, args) { - promise.then(undefined, function (err) { - // The callback is called with nextTick to avoid a follow-up rejection from this promise. - process.nextTick(emitUnhandledRejectionOrErr, emitter, err, type, args); - }); -} - -function emitUnhandledRejectionOrErr(emitter, err, type, args) { - if (typeof emitter[kRejection] === "function") { - emitter[kRejection](err, type, ...args); - } else { - // If the error handler throws, it is not catchable and it will end up in 'uncaughtException'. - // We restore the previous value of kCapture in case the uncaughtException is present - // and the exception is handled. - try { - emitter[kCapture] = false; - emitter.emit("error", err); - } finally { - emitter[kCapture] = true; - } - } -} - -const emitWithoutRejectionCapture = function emit(type, ...args) { - if (type === "error") { - return emitError(this, args); - } - var { _events: events } = this; - if (events === undefined) return false; - var handlers = events[type]; - if (handlers === undefined) return false; - - for (var handler of [...handlers]) { - handler.apply(this, args); - } - return true; -}; - -const emitWithRejectionCapture = function emit(type, ...args) { - if (type === "error") { - return emitError(this, args); - } - var { _events: events } = this; - if (events === undefined) return false; - var handlers = events[type]; - if (handlers === undefined) return false; - for (var handler of [...handlers]) { - var result = handler.apply(this, args); - if (result !== undefined && isPromise(result)) { - addCatch(this, result, type, args); - } - } - return true; -}; - -EventEmitter.prototype.emit = emitWithoutRejectionCapture; - -EventEmitter.prototype.addListener = function addListener(type, fn) { - checkListener(fn); - var events = this._events; - if (!events) { - events = this._events = { __proto__: null }; - this._eventsCount = 0; - } else if (events.newListener) { - this.emit("newListener", type, fn.listener ?? fn); - } - var handlers = events[type]; - if (!handlers) { - events[type] = [fn]; - this._eventsCount++; - } else { - handlers.push(fn); - var m = this._maxListeners ?? defaultMaxListeners; - if (m > 0 && handlers.length > m && !handlers.warned) { - overflowWarning(this, type, handlers); - } - } - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.prependListener = function prependListener(type, fn) { - checkListener(fn); - var events = this._events; - if (!events) { - events = this._events = { __proto__: null }; - this._eventsCount = 0; - } else if (events.newListener) { - this.emit("newListener", type, fn.listener ?? fn); - } - var handlers = events[type]; - if (!handlers) { - events[type] = [fn]; - this._eventsCount++; - } else { - handlers.unshift(fn); - var m = this._maxListeners ?? defaultMaxListeners; - if (m > 0 && handlers.length > m && !handlers.warned) { - overflowWarning(this, type, handlers); - } - } - return this; -}; - -function overflowWarning(emitter, type, handlers) { - handlers.warned = true; - const warn = new Error( - `Possible EventEmitter memory leak detected. ${handlers.length} ${String(type)} listeners ` + - `added to [${emitter.constructor.name}]. Use emitter.setMaxListeners() to increase limit`, - ); - warn.name = "MaxListenersExceededWarning"; - warn.emitter = emitter; - warn.type = type; - warn.count = handlers.length; - process.emitWarning(warn); -} - -function onceWrapper(type, listener, ...args) { - this.removeListener(type, listener); - listener.apply(this, args); -} - -EventEmitter.prototype.once = function once(type, fn) { - checkListener(fn); - const bound = onceWrapper.bind(this, type, fn); - bound.listener = fn; - this.addListener(type, bound); - return this; -}; - -EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, fn) { - checkListener(fn); - const bound = onceWrapper.bind(this, type, fn); - bound.listener = fn; - this.prependListener(type, bound); - return this; -}; - -EventEmitter.prototype.removeListener = function removeListener(type, fn) { - checkListener(fn); - var { _events: events } = this; - if (!events) return this; - var handlers = events[type]; - if (!handlers) return this; - var length = handlers.length; - let position = -1; - for (let i = length - 1; i >= 0; i--) { - if (handlers[i] === fn || handlers[i].listener === fn) { - position = i; - break; - } - } - if (position < 0) return this; - if (position === 0) { - handlers.shift(); - } else { - handlers.splice(position, 1); - } - if (handlers.length === 0) { - delete events[type]; - this._eventsCount--; - } - return this; -}; - -EventEmitter.prototype.off = EventEmitter.prototype.removeListener; - -EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) { - var { _events: events } = this; - if (type && events) { - if (events[type]) { - delete events[type]; - this._eventsCount--; - } - } else { - this._events = { __proto__: null }; - } - return this; -}; - -EventEmitter.prototype.listeners = function listeners(type) { - var { _events: events } = this; - if (!events) return []; - var handlers = events[type]; - if (!handlers) return []; - return handlers.map(x => x.listener ?? x); -}; - -EventEmitter.prototype.rawListeners = function rawListeners(type) { - var { _events } = this; - if (!_events) return []; - var handlers = _events[type]; - if (!handlers) return []; - return handlers.slice(); -}; - -EventEmitter.prototype.listenerCount = function listenerCount(type) { - var { _events: events } = this; - if (!events) return 0; - return events[type]?.length ?? 0; -}; - -EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; -}; - -EventEmitter.prototype[kCapture] = false; - -function once(emitter, type, { signal } = {}) { - validateAbortSignal(signal, "options.signal"); - if (signal?.aborted) { - throw new AbortError(undefined, { cause: signal?.reason }); - } - return new Promise((resolve, reject) => { - const errorListener = err => { - emitter.removeListener(type, resolver); - if (signal != null) { - eventTargetAgnosticRemoveListener(signal, "abort", abortListener); - } - reject(err); - }; - const resolver = (...args) => { - if (typeof emitter.removeListener === "function") { - emitter.removeListener("error", errorListener); - } - if (signal != null) { - eventTargetAgnosticRemoveListener(signal, "abort", abortListener); - } - resolve(args); - }; - eventTargetAgnosticAddListener(emitter, type, resolver, { once: true }); - if (type !== "error" && typeof emitter.once === "function") { - // EventTarget does not have `error` event semantics like Node - // EventEmitters, we listen to `error` events only on EventEmitters. - emitter.once("error", errorListener); - } - function abortListener() { - eventTargetAgnosticRemoveListener(emitter, type, resolver); - eventTargetAgnosticRemoveListener(emitter, "error", errorListener); - reject(new AbortError(undefined, { cause: signal?.reason })); - } - if (signal != null) { - eventTargetAgnosticAddListener(signal, "abort", abortListener, { once: true }); - } - }); -} -EventEmitter.once = once; - -function on(emitter, type, { signal, close, highWatermark = Number.MAX_SAFE_INTEGER, lowWatermark = 1 } = {}) { - throw new Error("events.on is not implemented. See https://github.com/oven-sh/bun/issues/2679"); -} -EventEmitter.on = on; - -function getEventListeners(emitter, type) { - if (emitter instanceof EventTarget) { - throw new Error( - "getEventListeners with an EventTarget is not implemented. See https://github.com/oven-sh/bun/issues/2678", - ); - } - return emitter.listeners(type); -} -EventEmitter.getEventListeners = getEventListeners; - -function setMaxListeners(n, ...eventTargets) { - validateNumber(n, "setMaxListeners", 0); - var length; - if (eventTargets && (length = eventTargets.length)) { - for (let i = 0; i < length; i++) { - eventTargets[i].setMaxListeners(n); - } - } else { - defaultMaxListeners = n; - } -} -EventEmitter.setMaxListeners = setMaxListeners; - -function listenerCount(emitter, type) { - return emitter.listenerCount(type); -} -EventEmitter.listenerCount = listenerCount; - -EventEmitter.EventEmitter = EventEmitter; -EventEmitter.usingDomains = false; -EventEmitter.captureRejectionSymbol = captureRejectionSymbol; -ObjectDefineProperty(EventEmitter, "captureRejections", { - __proto__: null, - get() { - return EventEmitter.prototype[kCapture]; - }, - set(value) { - validateBoolean(value, "EventEmitter.captureRejections"); - - EventEmitter.prototype[kCapture] = value; - }, - enumerable: true, -}); -EventEmitter.errorMonitor = kErrorMonitor; -Object.defineProperties(EventEmitter, { - defaultMaxListeners: { - enumerable: true, - get: () => { - return defaultMaxListeners; - }, - set: arg => { - validateNumber(arg, "defaultMaxListeners", 0); - defaultMaxListeners = arg; - }, - }, - kMaxEventTargetListeners: { - __proto__: null, - value: kMaxEventTargetListeners, - enumerable: false, - configurable: false, - writable: false, - }, - kMaxEventTargetListenersWarned: { - __proto__: null, - value: kMaxEventTargetListenersWarned, - enumerable: false, - configurable: false, - writable: false, - }, -}); -EventEmitter.init = EventEmitter; -EventEmitter[Symbol.for("CommonJS")] = 0; - -export default EventEmitter; - -function eventTargetAgnosticRemoveListener(emitter, name, listener, flags) { - if (typeof emitter.removeListener === "function") { - emitter.removeListener(name, listener); - } else { - emitter.removeEventListener(name, listener, flags); - } -} - -function eventTargetAgnosticAddListener(emitter, name, listener, flags) { - if (typeof emitter.on === "function") { - emitter.on(name, listener); - } else { - emitter.addEventListener(name, listener); - } -} - -class AbortError extends Error { - constructor(message = "The operation was aborted", options = undefined) { - if (options !== undefined && typeof options !== "object") { - throw new codes.ERR_INVALID_ARG_TYPE("options", "Object", options); - } - super(message, options); - this.code = "ABORT_ERR"; - this.name = "AbortError"; - } -} - -function ERR_INVALID_ARG_TYPE(name, type, value) { - const err = new TypeError(`The "${name}" argument must be of type ${type}. Received ${value}`); - err.code = "ERR_INVALID_ARG_TYPE"; - return err; -} - -function ERR_OUT_OF_RANGE(name, range, value) { - const err = new RangeError(`The "${name}" argument is out of range. It must be ${range}. Received ${value}`); - err.code = "ERR_OUT_OF_RANGE"; - return err; -} - -function validateAbortSignal(signal, name) { - if (signal !== undefined && (signal === null || typeof signal !== "object" || !("aborted" in signal))) { - throw new ERR_INVALID_ARG_TYPE(name, "AbortSignal", signal); - } -} - -function validateNumber(value, name, min = undefined, max) { - if (typeof value !== "number") throw new ERR_INVALID_ARG_TYPE(name, "number", value); - if ( - (min != null && value < min) || - (max != null && value > max) || - ((min != null || max != null) && Number.isNaN(value)) - ) { - throw new ERR_OUT_OF_RANGE( - name, - `${min != null ? `>= ${min}` : ""}${min != null && max != null ? " && " : ""}${max != null ? `<= ${max}` : ""}`, - value, - ); - } -} - -function checkListener(listener) { - if (typeof listener !== "function") { - throw new TypeError("The listener must be a function"); - } -} - -export class EventEmitterAsyncResource extends EventEmitter { - constructor(options = undefined) { - throw new Error("EventEmitterAsyncResource is not implemented. See https://github.com/oven-sh/bun/issues/2681"); - } -} - -EventEmitter.EventEmitterAsyncResource = EventEmitterAsyncResource; diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index 127bc85e3..ede5622dc 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -1712,15 +1712,7 @@ pub const ModuleLoader = struct { .@"node:buffer" => return jsSyntheticModule(.@"node:buffer"), .@"node:string_decoder" => return jsSyntheticModule(.@"node:string_decoder"), .@"node:module" => return jsSyntheticModule(.@"node:module"), - .@"node:events" => { - return ResolvedSource{ - .allocator = null, - .source_code = ZigString.init(jsModuleFromFile(jsc_vm.load_builtins_from_path, "events.exports.js")), - .specifier = ZigString.init("node:events"), - .source_url = ZigString.init("node:events"), - .hash = 0, - }; - }, + .@"node:events" => return jsSyntheticModule(.@"node:events"), .@"node:process" => return jsSyntheticModule(.@"node:process"), .@"node:tty" => return jsSyntheticModule(.@"node:tty"), .@"node:util/types" => return jsSyntheticModule(.@"node:util/types"), |