diff --git a/src/js/builtins/ConsoleObject.ts b/src/js/builtins/ConsoleObject.ts index a04528c29d..f146d8c1e9 100644 --- a/src/js/builtins/ConsoleObject.ts +++ b/src/js/builtins/ConsoleObject.ts @@ -266,13 +266,11 @@ export function createConsoleConstructor(console: typeof globalThis.console) { const kUseStderr = Symbol("kUseStderr"); const optionsMap = new WeakMap(); - 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 = { diff --git a/src/js/internal/assert/utils.ts b/src/js/internal/assert/utils.ts index 203881c904..31f08742f6 100644 --- a/src/js/internal/assert/utils.ts +++ b/src/js/internal/assert/utils.ts @@ -8,7 +8,6 @@ function loadAssertionError() { } } -// const { Buffer } = require('node:buffer'); // const { // isErrorStackTraceLimitWritable, // overrideStackTrace, diff --git a/src/js/internal/fs/cp-sync.ts b/src/js/internal/fs/cp-sync.ts index 84ebb6cd08..bc716a53dd 100644 --- a/src/js/internal/fs/cp-sync.ts +++ b/src/js/internal/fs/cp-sync.ts @@ -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."); } diff --git a/src/js/internal/streams/duplex.ts b/src/js/internal/streams/duplex.ts index 41a8731bda..69754017b6 100644 --- a/src/js/internal/streams/duplex.ts +++ b/src/js/internal/streams/duplex.ts @@ -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, diff --git a/src/js/internal/streams/from.ts b/src/js/internal/streams/from.ts index 46308d5d3d..3c03283e38 100644 --- a/src/js/internal/streams/from.ts +++ b/src/js/internal/streams/from.ts @@ -1,7 +1,3 @@ -"use strict"; - -const { Buffer } = require("node:buffer"); - const SymbolIterator = Symbol.iterator; const SymbolAsyncIterator = Symbol.asyncIterator; const PromisePrototypeThen = Promise.prototype.then; diff --git a/src/js/internal/streams/native-readable.ts b/src/js/internal/streams/native-readable.ts index ba4aa326c8..d1d341b4ad 100644 --- a/src/js/internal/streams/native-readable.ts +++ b/src/js/internal/streams/native-readable.ts @@ -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"); diff --git a/src/js/internal/streams/passthrough.ts b/src/js/internal/streams/passthrough.ts index 7fb5fd901d..e749cf07ec 100644 --- a/src/js/internal/streams/passthrough.ts +++ b/src/js/internal/streams/passthrough.ts @@ -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); } diff --git a/src/js/internal/streams/readable.ts b/src/js/internal/streams/readable.ts index 63bfb17f63..70044abd4f 100644 --- a/src/js/internal/streams/readable.ts +++ b/src/js/internal/streams/readable.ts @@ -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, diff --git a/src/js/internal/streams/transform.ts b/src/js/internal/streams/transform.ts index ce6d43ec6f..7207a70136 100644 --- a/src/js/internal/streams/transform.ts +++ b/src/js/internal/streams/transform.ts @@ -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; diff --git a/src/js/internal/streams/writable.ts b/src/js/internal/streams/writable.ts index c1c9d4ba63..05bc6c594a 100644 --- a/src/js/internal/streams/writable.ts +++ b/src/js/internal/streams/writable.ts @@ -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, diff --git a/src/js/internal/webstreams_adapters.ts b/src/js/internal/webstreams_adapters.ts index 916bf812d8..bdcfd6e027 100644 --- a/src/js/internal/webstreams_adapters.ts +++ b/src/js/internal/webstreams_adapters.ts @@ -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"); diff --git a/src/js/node/_http_incoming.ts b/src/js/node/_http_incoming.ts index f98be938ce..cb3b92ccd4 100644 --- a/src/js/node/_http_incoming.ts +++ b/src/js/node/_http_incoming.ts @@ -1,4 +1,4 @@ -const { Readable } = require("node:stream"); +const { Readable } = require("internal/streams/readable"); const { abortedSymbol, diff --git a/src/js/node/assert.ts b/src/js/node/assert.ts index 3d35366fa4..4c7a2d6b31 100644 --- a/src/js/node/assert.ts +++ b/src/js/node/assert.ts @@ -22,7 +22,6 @@ "use strict"; const { SafeMap, SafeSet, SafeWeakSet } = require("internal/primordials"); -const { Buffer } = require("node:buffer"); const { isKeyObject, isPromise, diff --git a/src/js/node/child_process.ts b/src/js/node/child_process.ts index 73cf698810..aa892ffe8c 100644 --- a/src/js/node/child_process.ts +++ b/src/js/node/child_process.ts @@ -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(); diff --git a/src/js/node/dgram.ts b/src/js/node/dgram.ts index 0dd094da1e..dc83eea4b2 100644 --- a/src/js/node/dgram.ts +++ b/src/js/node/dgram.ts @@ -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); diff --git a/src/js/node/http2.ts b/src/js/node/http2.ts index efc89dc513..b418db36fc 100644 --- a/src/js/node/http2.ts +++ b/src/js/node/http2.ts @@ -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"); diff --git a/src/js/node/perf_hooks.ts b/src/js/node/perf_hooks.ts index 8c19388bf2..64305a693b 100644 --- a/src/js/node/perf_hooks.ts +++ b/src/js/node/perf_hooks.ts @@ -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: { diff --git a/src/js/node/querystring.ts b/src/js/node/querystring.ts index 80a69f8371..cc8a5900c5 100644 --- a/src/js/node/querystring.ts +++ b/src/js/node/querystring.ts @@ -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; diff --git a/src/js/node/readline.ts b/src/js/node/readline.ts index 9cf88d4702..e212e363ce 100644 --- a/src/js/node/readline.ts +++ b/src/js/node/readline.ts @@ -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`. diff --git a/src/js/node/stream.consumers.ts b/src/js/node/stream.consumers.ts index 84f3b0d03c..13548c09d5 100644 --- a/src/js/node/stream.consumers.ts +++ b/src/js/node/stream.consumers.ts @@ -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 { diff --git a/src/js/node/stream.ts b/src/js/node/stream.ts index 306191f914..f0323f26bf 100644 --- a/src/js/node/stream.ts +++ b/src/js/node/stream.ts @@ -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; diff --git a/src/js/node/tls.ts b/src/js/node/tls.ts index 44b5c09c6c..df0f37fcdc 100644 --- a/src/js/node/tls.ts +++ b/src/js/node/tls.ts @@ -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"); diff --git a/src/js/node/zlib.ts b/src/js/node/zlib.ts index 57902037a0..8caa689aaf 100644 --- a/src/js/node/zlib.ts +++ b/src/js/node/zlib.ts @@ -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) {