node: some builtins cleanup (#22200)

Co-authored-by: Meghan Denny <meghan@bun.com>
This commit is contained in:
Meghan Denny
2025-08-27 19:34:37 -08:00
committed by Claude Bot
parent 10ccb880a4
commit 40a795daf8
23 changed files with 36 additions and 113 deletions

View File

@@ -266,13 +266,11 @@ export function createConsoleConstructor(console: typeof globalThis.console) {
const kUseStderr = Symbol("kUseStderr");
const optionsMap = new WeakMap<any, any>();
function Console(this: any, options /* or: stdout, stderr, ignoreErrors = true */) {
function Console(this: any, options /* or: stdout, stderr, ignoreErrors = true */): void {
// We have to test new.target here to see if this function is called
// with new, because we need to define a custom instanceof to accommodate
// the global console.
if (new.target === undefined) {
return Reflect.construct(Console, arguments);
}
if (new.target === undefined) return new Console(...arguments);
if (!options || typeof options.write === "function") {
options = {

View File

@@ -8,7 +8,6 @@ function loadAssertionError() {
}
}
// const { Buffer } = require('node:buffer');
// const {
// isErrorStackTraceLimitWritable,
// overrideStackTrace,

View File

@@ -47,7 +47,6 @@ const {
utimesSync,
} = require("node:fs");
const { dirname, isAbsolute, join, parse, resolve, sep } = require("node:path");
const { isPromise } = require("node:util/types");
function cpSyncFn(src, dest, opts) {
// Warn about using preserveTimestamps on 32-bit node
@@ -64,7 +63,7 @@ function cpSyncFn(src, dest, opts) {
function checkPathsSync(src, dest, opts) {
if (opts.filter) {
const shouldCopy = opts.filter(src, dest);
if (isPromise(shouldCopy)) {
if ($isPromise(shouldCopy)) {
// throw new ERR_INVALID_RETURN_VALUE("boolean", "filter", shouldCopy);
throw new Error("Expected a boolean from the filter function, but got a promise. Use `fs.promises.cp` instead.");
}

View File

@@ -16,8 +16,8 @@ const ObjectKeys = Object.keys;
const ObjectDefineProperties = Object.defineProperties;
const ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
function Duplex(options) {
if (!(this instanceof Duplex)) return Reflect.construct(Duplex, [options]);
function Duplex(options): void {
if (!(this instanceof Duplex)) return new Duplex(options);
this._events ??= {
close: undefined,

View File

@@ -1,7 +1,3 @@
"use strict";
const { Buffer } = require("node:buffer");
const SymbolIterator = Symbol.iterator;
const SymbolAsyncIterator = Symbol.asyncIterator;
const PromisePrototypeThen = Promise.prototype.then;

View File

@@ -5,7 +5,7 @@
// Normally, Readable.fromWeb will wrap the ReadableStream in JavaScript. In
// Bun, `fromWeb` is able to check if the stream is backed by a native handle,
// to which it will take this path.
const Readable = require("node:stream").Readable;
const Readable = require("internal/streams/readable");
const transferToNativeReadable = $newCppFunction("ReadableStream.cpp", "jsFunctionTransferToNativeReadableStream", 1);
const { errorOrDestroy } = require("internal/streams/destroy");

View File

@@ -6,8 +6,8 @@
const Transform = require("internal/streams/transform");
function PassThrough(options) {
if (!(this instanceof PassThrough)) return Reflect.construct(PassThrough, [options]);
function PassThrough(options): void {
if (!(this instanceof PassThrough)) return new PassThrough(options);
Transform.$call(this, options);
}

View File

@@ -2,7 +2,6 @@
const EE = require("node:events");
const { Stream, prependListener } = require("internal/streams/legacy");
const { Buffer } = require("node:buffer");
const { addAbortSignal } = require("internal/streams/add-abort-signal");
const eos = require("internal/streams/end-of-stream");
const destroyImpl = require("internal/streams/destroy");
@@ -260,8 +259,8 @@ ReadableState.prototype[kOnConstructed] = function onConstructed(stream) {
}
};
function Readable(options) {
if (!(this instanceof Readable)) return Reflect.construct(Readable, [options]);
function Readable(options): void {
if (!(this instanceof Readable)) return new Readable(options);
this._events ??= {
close: undefined,

View File

@@ -47,8 +47,8 @@ const { getHighWaterMark } = require("internal/streams/state");
const kCallback = Symbol("kCallback");
function Transform(options) {
if (!(this instanceof Transform)) return Reflect.construct(Transform, [options]);
function Transform(options): void {
if (!(this instanceof Transform)) return new Transform(options);
// TODO (ronag): This should preferably always be
// applied but would be semver-major. Or even better;

View File

@@ -6,7 +6,6 @@
const EE = require("node:events");
const { Stream } = require("internal/streams/legacy");
const { Buffer } = require("node:buffer");
const destroyImpl = require("internal/streams/destroy");
const eos = require("internal/streams/end-of-stream");
const { addAbortSignal } = require("internal/streams/add-abort-signal");
@@ -356,8 +355,8 @@ WritableState.prototype[kOnConstructed] = function onConstructed(stream) {
}
};
function Writable(options) {
if (!(this instanceof Writable)) return Reflect.construct(Writable, [options]);
function Writable(options): void {
if (!(this instanceof Writable)) return new Writable(options);
this._events ??= {
close: undefined,

View File

@@ -13,7 +13,6 @@ const Readable = require("internal/streams/readable");
const Duplex = require("internal/streams/duplex");
const { destroyer } = require("internal/streams/destroy");
const { isDestroyed, isReadable, isWritable, isWritableEnded } = require("internal/streams/utils");
const { Buffer } = require("node:buffer");
const { kEmptyObject } = require("internal/shared");
const { validateBoolean, validateObject } = require("internal/validators");
const finished = require("internal/streams/end-of-stream");

View File

@@ -1,4 +1,4 @@
const { Readable } = require("node:stream");
const { Readable } = require("internal/streams/readable");
const {
abortedSymbol,

View File

@@ -22,7 +22,6 @@
"use strict";
const { SafeMap, SafeSet, SafeWeakSet } = require("internal/primordials");
const { Buffer } = require("node:buffer");
const {
isKeyObject,
isPromise,

View File

@@ -1132,7 +1132,7 @@ class ChildProcess extends EventEmitter {
if (!stdin) {
// This can happen if the process was already killed.
const { Writable } = require("node:stream");
const Writable = require("internal/streams/writable");
const stream = new Writable({
write(chunk, encoding, callback) {
// Gracefully handle writes - stream acts as if it's ended
@@ -1151,7 +1151,7 @@ class ChildProcess extends EventEmitter {
case "inherit":
return null;
case "destroyed": {
const { Writable } = require("node:stream");
const Writable = require("internal/streams/writable");
const stream = new Writable({
write(chunk, encoding, callback) {
// Gracefully handle writes - stream acts as if it's ended
@@ -1176,7 +1176,7 @@ class ChildProcess extends EventEmitter {
const value = handle?.[fdToStdioName(i as 1 | 2)!];
// This can happen if the process was already killed.
if (!value) {
const { Readable } = require("node:stream");
const Readable = require("internal/streams/readable");
const stream = new Readable({ read() {} });
// Mark as destroyed to indicate it's not usable
stream.destroy();
@@ -1190,7 +1190,7 @@ class ChildProcess extends EventEmitter {
return pipe;
}
case "destroyed": {
const { Readable } = require("node:stream");
const Readable = require("internal/streams/readable");
const stream = new Readable({ read() {} });
// Mark as destroyed to indicate it's not usable
stream.destroy();

View File

@@ -61,7 +61,6 @@ const { deprecate } = require("node:util");
const SymbolDispose = Symbol.dispose;
const SymbolAsyncDispose = Symbol.asyncDispose;
const ObjectSetPrototypeOf = Object.setPrototypeOf;
const ObjectDefineProperty = Object.defineProperty;
const FunctionPrototypeBind = Function.prototype.bind;
@@ -199,9 +198,7 @@ function Socket(type, listener) {
});
}
}
Socket.prototype = {};
ObjectSetPrototypeOf(Socket.prototype, EventEmitter.prototype);
ObjectSetPrototypeOf(Socket, EventEmitter);
$toClass(Socket, "Socket", EventEmitter);
function createSocket(type, listener) {
return new Socket(type, listener);

View File

@@ -51,7 +51,7 @@ type Http2ConnectOptions = {
const TLSSocket = tls.TLSSocket;
const Socket = net.Socket;
const EventEmitter = require("node:events");
const { Duplex } = require("node:stream");
const { Duplex } = Stream;
const { SafeArrayIterator, SafeSet } = require("internal/primordials");

View File

@@ -92,8 +92,7 @@ class PerformanceNodeTiming {
};
}
}
Object.setPrototypeOf(PerformanceNodeTiming.prototype, PerformanceEntry.prototype);
Object.setPrototypeOf(PerformanceNodeTiming, PerformanceEntry);
$toClass(PerformanceNodeTiming, "PerformanceNodeTiming", PerformanceEntry);
function createPerformanceNodeTiming() {
const object = Object.create(PerformanceNodeTiming.prototype);
@@ -118,8 +117,7 @@ class PerformanceResourceTiming {
throwNotImplemented("PerformanceResourceTiming");
}
}
Object.setPrototypeOf(PerformanceResourceTiming.prototype, PerformanceEntry.prototype);
Object.setPrototypeOf(PerformanceResourceTiming, PerformanceEntry);
$toClass(PerformanceResourceTiming, "PerformanceResourceTiming", PerformanceEntry);
export default {
performance: {

View File

@@ -1,26 +1,4 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
const { Buffer } = require("node:buffer");
// Hardcoded module "node:querystring"
const ArrayIsArray = Array.isArray;
const MathAbs = Math.abs;
const NumberIsFinite = Number.isFinite;

View File

@@ -28,6 +28,7 @@
const EventEmitter = require("node:events");
const { StringDecoder } = require("node:string_decoder");
const { promisify } = require("internal/promisify");
const { SafeStringIterator } = require("internal/primordials");
const {
validateFunction,
@@ -54,7 +55,6 @@ var debug = process.env.BUN_JS_DEBUG ? console.log : () => {};
// ----------------------------------------------------------------------------
const SymbolAsyncIterator = Symbol.asyncIterator;
const SymbolIterator = Symbol.iterator;
const SymbolFor = Symbol.for;
const ArrayFrom = Array.from;
const ArrayPrototypeFilter = Array.prototype.filter;
@@ -86,35 +86,10 @@ const MathCeil = Math.ceil;
const MathFloor = Math.floor;
const MathMax = Math.max;
const DateNow = Date.now;
const StringPrototype = String.prototype;
const StringPrototypeSymbolIterator = StringPrototype[SymbolIterator];
const StringIteratorPrototypeNext = StringPrototypeSymbolIterator.$call("").next;
const ObjectSetPrototypeOf = Object.setPrototypeOf;
const ObjectDefineProperties = Object.defineProperties;
const ObjectFreeze = Object.freeze;
const ObjectCreate = Object.create;
var createSafeIterator = (factory, next) => {
class SafeIterator {
#iterator;
constructor(iterable) {
this.#iterator = factory.$call(iterable);
}
next() {
return next.$call(this.#iterator);
}
[SymbolIterator]() {
return this;
}
}
ObjectSetPrototypeOf(SafeIterator.prototype, null);
ObjectFreeze(SafeIterator.prototype);
ObjectFreeze(SafeIterator);
return SafeIterator;
};
var SafeStringIterator = createSafeIterator(StringPrototypeSymbolIterator, StringIteratorPrototypeNext);
// ----------------------------------------------------------------------------
// Section: "Internal" modules
// ----------------------------------------------------------------------------
@@ -1226,10 +1201,7 @@ function InterfaceConstructor(input, output, completer, terminal) {
input.resume();
}
InterfaceConstructor.prototype = {};
ObjectSetPrototypeOf(InterfaceConstructor.prototype, EventEmitter.prototype);
// ObjectSetPrototypeOf(InterfaceConstructor, EventEmitter);
$toClass(InterfaceConstructor, "InterfaceConstructor", EventEmitter);
var _Interface = class Interface extends InterfaceConstructor {
// eslint-disable-next-line no-useless-constructor
@@ -2213,10 +2185,7 @@ function Interface(input, output, completer, terminal) {
this._ttyWrite = _ttyWriteDumb.bind(this);
}
}
Interface.prototype = {};
ObjectSetPrototypeOf(Interface.prototype, _Interface.prototype);
ObjectSetPrototypeOf(Interface, _Interface);
$toClass(Interface, "Interface", _Interface);
/**
* Displays `query` by writing it to the `output`.

View File

@@ -1,8 +1,4 @@
// Hardcoded module "node:stream/consumers" / "readable-stream/consumer"
"use strict";
const { Buffer } = require("node:buffer");
const JSONParse = JSON.parse;
async function blob(stream): Promise<Blob> {

View File

@@ -1,10 +1,8 @@
// Hardcoded module "node:stream" / "readable-stream"
const EE = require("node:events").EventEmitter;
const exports = require("internal/stream");
$debug("node:stream loaded");
exports.eos = require("internal/streams/end-of-stream");
exports.EventEmitter = EE;
export default exports;

View File

@@ -1,7 +1,7 @@
// Hardcoded module "node:tls"
const { isArrayBufferView, isTypedArray } = require("node:util/types");
const net = require("node:net");
const { Duplex } = require("node:stream");
const Duplex = require("internal/streams/duplex");
const addServerName = $newZigFunction("Listener.zig", "jsAddServerName", 3);
const { throwNotImplemented } = require("internal/shared");
const { throwOnInvalidTLSArray } = require("internal/tls");

View File

@@ -1,6 +1,5 @@
// Hardcoded module "node:zlib"
const assert = require("node:assert");
const BufferModule = require("node:buffer");
const crc32 = $newZigFunction("node_zlib_binding.zig", "crc32", 1);
@@ -147,8 +146,8 @@ function ZlibBase(opts, mode, handle, { flush, finishFlush, fullFlush }) {
let chunkSize = Z_DEFAULT_CHUNK;
let maxOutputLength = kMaxLength;
// The ZlibBase class is not exported to user land, the mode should only be passed in by us.
assert(typeof mode === "number");
assert(mode >= DEFLATE && mode <= ZSTD_DECOMPRESS);
$assert(typeof mode === "number");
$assert(mode >= DEFLATE && mode <= ZSTD_DECOMPRESS);
let flushBoundIdx;
if (mode === BROTLI_ENCODE || mode === BROTLI_DECODE) {
@@ -224,7 +223,7 @@ ObjectDefineProperty(ZlibBase.prototype, "bytesRead", {
});
ZlibBase.prototype.reset = function () {
assert(this._handle, "zlib binding closed");
$assert(this._handle, "zlib binding closed");
return this._handle.reset();
};
@@ -366,7 +365,7 @@ function processChunkSync(self, chunk, flushFlag) {
throw $ERR_BUFFER_TOO_LARGE(self._maxOutputLength);
}
} else {
assert(have === 0, "have should not go down");
$assert(have === 0, "have should not go down");
}
// Exhausted the output buffer, or used all the input create a new one.
@@ -445,7 +444,7 @@ function processCallback() {
self._outOffset += have;
streamBufferIsFull = !self.push(out);
} else {
assert(have === 0, "have should not go down");
$assert(have === 0, "have should not go down");
}
if (self.destroyed) {
@@ -580,7 +579,7 @@ $toClass(Zlib, "Zlib", ZlibBase);
// This callback is used by `.params()` to wait until a full flush happened before adjusting the parameters.
// In particular, the call to the native `params()` function should not happen while a write is currently in progress on the threadpool.
function paramsAfterFlushCallback(level, strategy, callback) {
assert(this._handle, "zlib binding closed");
$assert(this._handle, "zlib binding closed");
this._handle.params(level, strategy);
if (!this.destroyed) {
this._level = level;
@@ -673,7 +672,7 @@ const brotliDefaultOpts = {
fullFlush: BROTLI_OPERATION_FLUSH,
};
function Brotli(opts, mode) {
assert(mode === BROTLI_DECODE || mode === BROTLI_ENCODE);
$assert(mode === BROTLI_DECODE || mode === BROTLI_ENCODE);
TypedArrayPrototypeFill.$call(brotliInitParamsArray, -1);
if (opts?.params) {
@@ -722,7 +721,7 @@ const zstdDefaultOpts = {
class Zstd extends ZlibBase {
constructor(opts, mode, initParamsArray, maxParam) {
assert(mode === ZSTD_COMPRESS || mode === ZSTD_DECOMPRESS);
$assert(mode === ZSTD_COMPRESS || mode === ZSTD_DECOMPRESS);
initParamsArray.fill(-1);
if (opts?.params) {