diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index 0818f88eae..3daeb5b682 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -76,6 +76,17 @@ declare global { revision: string; reallyExit(code?: number): never; dlopen(module: { exports: any }, filename: string, flags?: number): void; + _exiting: boolean; + noDeprecation: boolean; + + binding(m: string): object; + binding(m: "constants"): { + os: typeof import("node:os").constants; + fs: typeof import("node:fs").constants; + crypto: typeof import("node:crypto").constants; + zlib: typeof import("node:zlib").constants; + trace: typeof import("node:trace").constants; + }; } } diff --git a/src/bun.js/bindings/ErrorCode.cpp b/src/bun.js/bindings/ErrorCode.cpp index 167c22e20f..232ddb9729 100644 --- a/src/bun.js/bindings/ErrorCode.cpp +++ b/src/bun.js/bindings/ErrorCode.cpp @@ -1364,6 +1364,20 @@ JSC_DEFINE_HOST_FUNCTION(Bun::jsFunctionMakeErrorWithCode, (JSC::JSGlobalObject return JSValue::encode(createError(globalObject, ErrorCode::ERR_INVALID_IP_ADDRESS, builder.toString())); } + case Bun::ErrorCode::ERR_INVALID_ADDRESS_FAMILY: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto arg1 = callFrame->argument(2); + auto str1 = arg1.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto arg2 = callFrame->argument(3); + auto str2 = arg2.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Invalid address family: "_s, str0, " "_s, str1, ":"_s, str2); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_INVALID_ADDRESS_FAMILY, message)); + } + case Bun::ErrorCode::ERR_INVALID_ARG_VALUE: { JSValue arg0 = callFrame->argument(1); JSValue arg1 = callFrame->argument(2); @@ -1690,6 +1704,229 @@ JSC_DEFINE_HOST_FUNCTION(Bun::jsFunctionMakeErrorWithCode, (JSC::JSGlobalObject return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_TLS_PROTOCOL_VERSION_CONFLICT, message)); } + case Bun::ErrorCode::ERR_TLS_CERT_ALTNAME_INVALID: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto arg1 = callFrame->argument(2); + auto arg2 = callFrame->argument(3); + auto message = makeString("Hostname/IP does not match certificate's altnames: "_s, str0); + auto err = createError(globalObject, ErrorCode::ERR_TLS_CERT_ALTNAME_INVALID, message); + err->putDirect(vm, Identifier::fromString(vm, "reason"_s), arg0); + err->putDirect(vm, Identifier::fromString(vm, "host"_s), arg1); + err->putDirect(vm, Identifier::fromString(vm, "cert"_s), arg2); + return JSC::JSValue::encode(err); + } + + case Bun::ErrorCode::ERR_USE_AFTER_CLOSE: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString(str0, " was closed"_s); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_USE_AFTER_CLOSE, message)); + } + + case Bun::ErrorCode::ERR_INVALID_HTTP_TOKEN: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto arg1 = callFrame->argument(2); + auto str1 = arg1.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString(str0, " must be a valid HTTP token [\""_s, str1, "\"]"_s); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_INVALID_HTTP_TOKEN, message)); + } + + case Bun::ErrorCode::ERR_HTTP2_INVALID_HEADER_VALUE: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto arg1 = callFrame->argument(2); + auto str1 = arg1.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Invalid value \""_s, str0, "\" for header \""_s, str1, "\""_s); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_INVALID_HEADER_VALUE, message)); + } + + case Bun::ErrorCode::ERR_HTTP2_STATUS_INVALID: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Invalid status code: "_s, str0); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_STATUS_INVALID, message)); + } + + case Bun::ErrorCode::ERR_HTTP2_INVALID_PSEUDOHEADER: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("\""_s, str0, "\" is an invalid pseudoheader or is used incorrectly"_s); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_INVALID_PSEUDOHEADER, message)); + } + + case Bun::ErrorCode::ERR_HTTP2_STREAM_ERROR: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Stream closed with error code "_s, str0); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_STREAM_ERROR, message)); + } + + case Bun::ErrorCode::ERR_HTTP2_SESSION_ERROR: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Session closed with error code "_s, str0); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_SESSION_ERROR, message)); + } + + case Bun::ErrorCode::ERR_HTTP2_PAYLOAD_FORBIDDEN: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Responses with "_s, str0, " status must not have a payload"_s); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_PAYLOAD_FORBIDDEN, message)); + } + + case Bun::ErrorCode::ERR_HTTP2_INVALID_INFO_STATUS: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Invalid informational status code: "_s, str0); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_INVALID_INFO_STATUS, message)); + } + + case Bun::ErrorCode::ERR_INVALID_URL: { + auto arg0 = callFrame->argument(1); + auto arg1 = callFrame->argument(2); + // Don't include URL in message. (See https://github.com/nodejs/node/pull/38614) + auto err = createError(globalObject, ErrorCode::ERR_INVALID_URL, "Invalid URL"_s); + err->putDirect(vm, vm.propertyNames->input, arg0); + if (!arg1.isUndefinedOrNull()) err->putDirect(vm, Identifier::fromString(vm, "base"_s), arg1); + return JSC::JSValue::encode(err); + } + + case Bun::ErrorCode::ERR_INVALID_CHAR: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto arg1 = callFrame->argument(2); + WTF::StringBuilder builder; + builder.append("Invalid character in "_s); + builder.append(str0); + if (!arg1.isUndefined()) { + auto str1 = arg1.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + builder.append(" [\""_s); + builder.append(str1); + builder.append("\"]"_s); + } + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_INVALID_CHAR, builder.toString())); + } + + case Bun::ErrorCode::ERR_HTTP_INVALID_HEADER_VALUE: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto arg1 = callFrame->argument(2); + auto str1 = arg1.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Invalid value \""_s, str0, "\" for header \""_s, str1, "\""_s); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP_INVALID_HEADER_VALUE, message)); + } + + case Bun::ErrorCode::ERR_HTTP_HEADERS_SENT: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Cannot "_s, str0, " headers after they are sent to the client"_s); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP_HEADERS_SENT, message)); + } + + case Bun::ErrorCode::ERR_UNESCAPED_CHARACTERS: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString(str0, " contains unescaped characters"_s); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_UNESCAPED_CHARACTERS, message)); + } + + case Bun::ErrorCode::ERR_HTTP_INVALID_STATUS_CODE: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Invalid status code: "_s, str0); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP_INVALID_STATUS_CODE, message)); + } + + case Bun::ErrorCode::ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto arg1 = callFrame->argument(2); + auto str1 = arg1.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Invalid key object type "_s, str0, ", expected "_s, str1, "."_s); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE, message)); + } + + case Bun::ErrorCode::ERR_CRYPTO_INCOMPATIBLE_KEY: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto arg1 = callFrame->argument(2); + auto str1 = arg1.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Incompatible "_s, str0, ": "_s, str1); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_CRYPTO_INCOMPATIBLE_KEY, message)); + } + + case Bun::ErrorCode::ERR_CHILD_PROCESS_IPC_REQUIRED: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Forked processes must have an IPC channel, missing value 'ipc' in "_s, str0); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_CHILD_PROCESS_IPC_REQUIRED, message)); + } + + case Bun::ErrorCode::ERR_INVALID_ASYNC_ID: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto arg1 = callFrame->argument(2); + auto str1 = arg1.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Invalid "_s, str0, " value: "_s, str1); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_INVALID_ASYNC_ID, message)); + } + + case Bun::ErrorCode::ERR_ASYNC_TYPE: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("Invalid name for async \"type\": "_s, str0); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_ASYNC_TYPE, message)); + } + + case Bun::ErrorCode::ERR_ASYNC_CALLBACK: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString(str0, " must be a function"_s); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_ASYNC_CALLBACK, message)); + } + + case Bun::ErrorCode::ERR_AMBIGUOUS_ARGUMENT: { + auto arg0 = callFrame->argument(1); + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto arg1 = callFrame->argument(2); + auto str1 = arg1.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("The \""_s, str0, "\" argument is ambiguous. "_s, str1); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_AMBIGUOUS_ARGUMENT, message)); + } + case ErrorCode::ERR_IPC_DISCONNECTED: return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_IPC_DISCONNECTED, "IPC channel is already disconnected"_s)); case ErrorCode::ERR_SERVER_NOT_RUNNING: @@ -1742,12 +1979,66 @@ JSC_DEFINE_HOST_FUNCTION(Bun::jsFunctionMakeErrorWithCode, (JSC::JSGlobalObject return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_SOCKET_CLOSED_BEFORE_CONNECTION, "Socket closed before the connection was established"_s)); case ErrorCode::ERR_TLS_RENEGOTIATION_DISABLED: return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_TLS_RENEGOTIATION_DISABLED, "TLS session renegotiation disabled for this socket"_s)); + case ErrorCode::ERR_UNAVAILABLE_DURING_EXIT: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_UNAVAILABLE_DURING_EXIT, "Cannot call function in process exit handler"_s)); + case ErrorCode::ERR_TLS_CERT_ALTNAME_FORMAT: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_TLS_CERT_ALTNAME_FORMAT, "Invalid subject alternative name string"_s)); + case ErrorCode::ERR_TLS_SNI_FROM_SERVER: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_TLS_SNI_FROM_SERVER, "Cannot issue SNI from a TLS server-side socket"_s)); + case ErrorCode::ERR_INVALID_URI: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_INVALID_URI, "URI malformed"_s)); + case ErrorCode::ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED, "Cannot set HTTP/2 pseudo-headers"_s)); + case ErrorCode::ERR_HTTP2_INFO_STATUS_NOT_ALLOWED: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_INFO_STATUS_NOT_ALLOWED, "Informational status codes cannot be used"_s)); + case ErrorCode::ERR_HTTP2_HEADERS_SENT: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_HEADERS_SENT, "Response has already been initiated."_s)); + case ErrorCode::ERR_HTTP2_INVALID_STREAM: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_INVALID_STREAM, "The stream has been destroyed"_s)); + case ErrorCode::ERR_HTTP2_NO_SOCKET_MANIPULATION: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_NO_SOCKET_MANIPULATION, "HTTP/2 sockets should not be directly manipulated (e.g. read and written)"_s)); + case ErrorCode::ERR_HTTP2_SOCKET_UNBOUND: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_SOCKET_UNBOUND, "The socket has been disconnected from the Http2Session"_s)); + case ErrorCode::ERR_HTTP2_MAX_PENDING_SETTINGS_ACK: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_MAX_PENDING_SETTINGS_ACK, "Maximum number of pending settings acknowledgements"_s)); + case ErrorCode::ERR_HTTP2_INVALID_SESSION: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_INVALID_SESSION, "The session has been destroyed"_s)); + case ErrorCode::ERR_HTTP2_TRAILERS_ALREADY_SENT: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_TRAILERS_ALREADY_SENT, "Trailing headers have already been sent"_s)); + case ErrorCode::ERR_HTTP2_TRAILERS_NOT_READY: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_TRAILERS_NOT_READY, "Trailing headers cannot be sent until after the wantTrailers event is emitted"_s)); + case ErrorCode::ERR_HTTP2_SEND_FILE: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_SEND_FILE, "Directories cannot be sent"_s)); + case ErrorCode::ERR_HTTP2_SEND_FILE_NOSEEK: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_SEND_FILE_NOSEEK, "Offset or length can only be specified for regular files"_s)); + case ErrorCode::ERR_HTTP2_PUSH_DISABLED: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_PUSH_DISABLED, "HTTP/2 client has disabled push streams"_s)); + case ErrorCode::ERR_HTTP2_HEADERS_AFTER_RESPOND: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_HEADERS_AFTER_RESPOND, "Cannot specify additional headers after response initiated"_s)); + case ErrorCode::ERR_HTTP2_STATUS_101: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_STATUS_101, "HTTP status code 101 (Switching Protocols) is forbidden in HTTP/2"_s)); + case ErrorCode::ERR_HTTP2_ALTSVC_INVALID_ORIGIN: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_ALTSVC_INVALID_ORIGIN, "HTTP/2 ALTSVC frames require a valid origin"_s)); + case ErrorCode::ERR_HTTP2_INVALID_ORIGIN: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_INVALID_ORIGIN, "HTTP/2 ORIGIN frames require a valid origin"_s)); + case ErrorCode::ERR_HTTP2_ALTSVC_LENGTH: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_ALTSVC_LENGTH, "HTTP/2 ALTSVC frames are limited to 16382 bytes"_s)); + case ErrorCode::ERR_HTTP2_PING_LENGTH: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_PING_LENGTH, "HTTP2 ping payload must be 8 bytes"_s)); + case ErrorCode::ERR_HTTP2_OUT_OF_STREAMS: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP2_OUT_OF_STREAMS, "No stream ID is available because maximum stream ID has been reached"_s)); + case ErrorCode::ERR_HTTP_BODY_NOT_ALLOWED: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_HTTP_BODY_NOT_ALLOWED, "Adding content for this request method or response status is not allowed."_s)); default: { break; } } +#if BUN_DEBUG + ASSERT(false, "Improper use of @makeError! Add error function to ErrorCode.cpp and builtins.d.ts"); +#endif + auto&& message = callFrame->argument(1).toWTFString(globalObject); RETURN_IF_EXCEPTION(scope, {}); diff --git a/src/bun.js/bindings/ErrorCode.ts b/src/bun.js/bindings/ErrorCode.ts index a86650f377..c4320ce178 100644 --- a/src/bun.js/bindings/ErrorCode.ts +++ b/src/bun.js/bindings/ErrorCode.ts @@ -85,10 +85,9 @@ const errors: ErrorCodeMapping = [ ["ERR_HTTP2_ERROR", Error], ["ERR_HTTP2_HEADER_SINGLE_VALUE", TypeError], ["ERR_HTTP2_HEADERS_AFTER_RESPOND", Error], - ["ERR_HTTP2_HEADERS_SENT", Error, "ERR_HTTP2_HEADERS_SENT"], + ["ERR_HTTP2_HEADERS_SENT", Error], ["ERR_HTTP2_INFO_STATUS_NOT_ALLOWED", RangeError], ["ERR_HTTP2_INVALID_HEADER_VALUE", TypeError], - ["ERR_HTTP2_INVALID_HEADERS", Error], ["ERR_HTTP2_INVALID_INFO_STATUS", RangeError], ["ERR_HTTP2_INVALID_ORIGIN", TypeError], ["ERR_HTTP2_INVALID_PSEUDOHEADER", TypeError], @@ -115,6 +114,7 @@ const errors: ErrorCodeMapping = [ ["ERR_ILLEGAL_CONSTRUCTOR", TypeError], ["ERR_INCOMPATIBLE_OPTION_PAIR", TypeError], ["ERR_INVALID_ADDRESS", Error], + ["ERR_INVALID_ADDRESS_FAMILY", RangeError], ["ERR_INVALID_ARG_TYPE", TypeError], ["ERR_INVALID_ARG_VALUE", TypeError], ["ERR_INVALID_ASYNC_ID", RangeError], @@ -236,6 +236,7 @@ const errors: ErrorCodeMapping = [ ["ERR_UNKNOWN_CREDENTIAL", Error], ["ERR_UNKNOWN_ENCODING", TypeError], ["ERR_UNKNOWN_SIGNAL", TypeError], + ["ERR_USE_AFTER_CLOSE", Error], ["ERR_VM_MODULE_CACHED_DATA_REJECTED", Error], ["ERR_VM_MODULE_LINK_FAILURE", Error], ["ERR_WASI_NOT_STARTED", Error], diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 4784f28d08..646ac55c18 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -6423,32 +6423,6 @@ extern "C" EncodedJSValue Bun__JSObject__getCodePropertyVMInquiry(JSC::JSGlobalO return JSValue::encode(slot.getPureResult()); } -using StackCodeType = JSC::StackVisitor::Frame::CodeType; -CPP_DECL bool Bun__util__isInsideNodeModules(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -{ - auto& vm = JSC::getVM(globalObject); - bool inNodeModules = false; - JSC::StackVisitor::visit(callFrame, vm, [&](JSC::StackVisitor& visitor) -> WTF::IterationStatus { - if (Zig::isImplementationVisibilityPrivate(visitor) || visitor->isNativeCalleeFrame()) { - return WTF::IterationStatus::Continue; - } - - if (visitor->hasLineAndColumnInfo()) { - String sourceURL = Zig::sourceURL(visitor); - if (sourceURL.startsWith("node:"_s) || sourceURL.startsWith("bun:"_s)) - return WTF::IterationStatus::Continue; - if (sourceURL.contains("node_modules"_s)) - inNodeModules = true; - - return WTF::IterationStatus::Done; - } - - return WTF::IterationStatus::Continue; - }); - - return inNodeModules; -} - #if BUN_DEBUG CPP_DECL const char* Bun__CallFrame__describeFrame(JSC::CallFrame* callFrame) { diff --git a/src/bun.js/node/node_util_binding.zig b/src/bun.js/node/node_util_binding.zig index d9f76e3f5b..1cd5e9464a 100644 --- a/src/bun.js/node/node_util_binding.zig +++ b/src/bun.js/node/node_util_binding.zig @@ -138,14 +138,6 @@ pub fn extractedSplitNewLinesFastPathStringsOnly(globalThis: *JSC.JSGlobalObject }; } -extern fn Bun__util__isInsideNodeModules(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) bool; -/// Walks the call stack from bottom to top, returning `true` when it finds a -/// frame within a `node_modules` directory. -pub fn isInsideNodeModules(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { - const res = Bun__util__isInsideNodeModules(globalObject, callframe); - return JSC.JSValue.jsBoolean(res); -} - fn split( comptime encoding: bun.strings.EncodingNonAscii, globalThis: *JSC.JSGlobalObject, diff --git a/src/codegen/bundle-modules.ts b/src/codegen/bundle-modules.ts index d46a3699e1..73979226eb 100644 --- a/src/codegen/bundle-modules.ts +++ b/src/codegen/bundle-modules.ts @@ -496,32 +496,6 @@ declare module "module" { } `; - for (let i = 0; i < ErrorCode.length; i++) { - const [code, constructor, name, ...other_constructors] = ErrorCode[i]; - dts += ` -/** - * Generate a ${name ?? constructor.name} error with the \`code\` property set to ${code}. - * - * @param msg The error message - * @param args Additional arguments - */ -declare function $${code}(msg: string, ...args: any[]): ${name}; -`; - - for (const con of other_constructors) { - if (con == null) continue; - dts += ` -/** - * Generate a ${con.name} error with the \`code\` property set to ${code}. - * - * @param msg The error message - * @param args Additional arguments - */ -declare function $${code}_${con.name}(msg: string, ...args: any[]): ${name}; -`; - } - } - for (const [name] of jsclasses) { dts += `\ndeclare function $inherits${name}(value: any): boolean;`; } diff --git a/src/js/builtins.d.ts b/src/js/builtins.d.ts index a0bbbcc8af..31a157cd61 100644 --- a/src/js/builtins.d.ts +++ b/src/js/builtins.d.ts @@ -597,14 +597,14 @@ declare function $makeAbortError(message?: string, options?: { cause: Error }): /** * -- Error Codes with manual messages */ -declare function $ERR_INVALID_ARG_TYPE(argName: string, expectedType: string, actualValue: string): TypeError; -declare function $ERR_INVALID_ARG_TYPE(argName: string, expectedTypes: any[], actualValue: string): TypeError; +declare function $ERR_INVALID_ARG_TYPE(argName: string, expectedType: string, actualValue: any): TypeError; +declare function $ERR_INVALID_ARG_TYPE(argName: string, expectedTypes: string[], actualValue: any): TypeError; declare function $ERR_INVALID_ARG_VALUE(name: string, value: any, reason?: string): TypeError; declare function $ERR_UNKNOWN_ENCODING(enc: string): TypeError; declare function $ERR_STREAM_DESTROYED(method: string): Error; declare function $ERR_METHOD_NOT_IMPLEMENTED(method: string): Error; declare function $ERR_STREAM_ALREADY_FINISHED(method: string): Error; -declare function $ERR_MISSING_ARGS(a1: string, a2?: string): TypeError; +declare function $ERR_MISSING_ARGS(...args: [string, ...string[]]): TypeError; /** * `The "foo" or "bar" or "baz" argument must be specified` * @@ -614,13 +614,43 @@ declare function $ERR_MISSING_ARGS(oneOf: string[]): TypeError; declare function $ERR_INVALID_RETURN_VALUE(expected_type: string, name: string, actual_value: any): TypeError; declare function $ERR_TLS_INVALID_PROTOCOL_VERSION(a: string, b: string): TypeError; declare function $ERR_TLS_PROTOCOL_VERSION_CONFLICT(a: string, b: string): TypeError; +declare function $ERR_INVALID_IP_ADDRESS(ip: any): TypeError; +declare function $ERR_INVALID_ADDRESS_FAMILY(addressType, host, port): RangeError; +declare function $ERR_OUT_OF_RANGE(name: string, reason: string, value): RangeError; +declare function $ERR_BUFFER_TOO_LARGE(len: number): RangeError; +declare function $ERR_BROTLI_INVALID_PARAM(p: number): RangeError; +declare function $ERR_TLS_CERT_ALTNAME_INVALID(reason: string, host: string, cert): Error; +declare function $ERR_USE_AFTER_CLOSE(name: string): Error; +declare function $ERR_HTTP2_INVALID_HEADER_VALUE(value: string, name: string): TypeError; +declare function $ERR_INVALID_HTTP_TOKEN(name: string, value: string): TypeError; +declare function $ERR_HTTP2_STATUS_INVALID(code: number): RangeError; +declare function $ERR_HTTP2_INVALID_PSEUDOHEADER(name: string): TypeError; +declare function $ERR_HTTP2_STREAM_ERROR(code): Error; +declare function $ERR_HTTP2_SESSION_ERROR(code): Error; +declare function $ERR_HTTP2_PAYLOAD_FORBIDDEN(status): Error; +declare function $ERR_HTTP2_INVALID_INFO_STATUS(code): RangeError; +declare function $ERR_INVALID_URL(input, base?): TypeError; +declare function $ERR_INVALID_CHAR(name, field?): TypeError; +declare function $ERR_HTTP_INVALID_HEADER_VALUE(value: string, name: string): TypeError; +declare function $ERR_HTTP_HEADERS_SENT(action: string): Error; +declare function $ERR_INVALID_PROTOCOL(proto, expected): TypeError; +declare function $ERR_UNESCAPED_CHARACTERS(arg): TypeError; +declare function $ERR_HTTP_INVALID_STATUS_CODE(code): RangeError; +declare function $ERR_UNHANDLED_ERROR(err?): Error; +declare function $ERR_BUFFER_OUT_OF_BOUNDS(name?: string): RangeError; +declare function $ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(value, expected): TypeError; +declare function $ERR_CRYPTO_INCOMPATIBLE_KEY(name, value): Error; +declare function $ERR_CHILD_PROCESS_IPC_REQUIRED(where): Error; +declare function $ERR_INVALID_ASYNC_ID(name, value): RangeError; +declare function $ERR_ASYNC_TYPE(name): TypeError; +declare function $ERR_ASYNC_CALLBACK(name): TypeError; +declare function $ERR_AMBIGUOUS_ARGUMENT(arg, message): TypeError; declare function $ERR_IPC_DISCONNECTED(): Error; declare function $ERR_SERVER_NOT_RUNNING(): Error; declare function $ERR_IPC_CHANNEL_CLOSED(): Error; declare function $ERR_SOCKET_BAD_TYPE(): Error; declare function $ERR_ZLIB_INITIALIZATION_FAILED(): Error; -declare function $ERR_BUFFER_OUT_OF_BOUNDS(): Error; declare function $ERR_IPC_ONE_PIPE(): Error; declare function $ERR_SOCKET_ALREADY_BOUND(): Error; declare function $ERR_SOCKET_BAD_BUFFER_SIZE(): Error; @@ -641,6 +671,32 @@ declare function $ERR_SERVER_ALREADY_LISTEN(): Error; declare function $ERR_SOCKET_CLOSED(): Error; declare function $ERR_SOCKET_CLOSED_BEFORE_CONNECTION(): Error; declare function $ERR_TLS_RENEGOTIATION_DISABLED(): Error; +declare function $ERR_UNAVAILABLE_DURING_EXIT(): Error; +declare function $ERR_TLS_CERT_ALTNAME_FORMAT(): SyntaxError; +declare function $ERR_TLS_SNI_FROM_SERVER(): Error; +declare function $ERR_INVALID_URI(): URIError; +declare function $ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED(): TypeError; +declare function $ERR_HTTP2_INFO_STATUS_NOT_ALLOWED(): RangeError; +declare function $ERR_HTTP2_HEADERS_SENT(): Error; +declare function $ERR_HTTP2_INVALID_STREAM(): Error; +declare function $ERR_HTTP2_NO_SOCKET_MANIPULATION(): Error; +declare function $ERR_HTTP2_SOCKET_UNBOUND(): Error; +declare function $ERR_HTTP2_MAX_PENDING_SETTINGS_ACK(): Error; +declare function $ERR_HTTP2_INVALID_SESSION(): Error; +declare function $ERR_HTTP2_TRAILERS_ALREADY_SENT(): Error; +declare function $ERR_HTTP2_TRAILERS_NOT_READY(): Error; +declare function $ERR_HTTP2_SEND_FILE(): Error; +declare function $ERR_HTTP2_SEND_FILE_NOSEEK(): Error; +declare function $ERR_HTTP2_PUSH_DISABLED(): Error; +declare function $ERR_HTTP2_HEADERS_AFTER_RESPOND(): Error; +declare function $ERR_HTTP2_STATUS_101(): Error; +declare function $ERR_HTTP2_ALTSVC_INVALID_ORIGIN(): TypeError; +declare function $ERR_HTTP2_INVALID_ORIGIN(): TypeError; +declare function $ERR_HTTP2_ALTSVC_LENGTH(): TypeError; +declare function $ERR_HTTP2_PING_LENGTH(): RangeError; +declare function $ERR_HTTP2_OUT_OF_STREAMS(): Error; +declare function $ERR_HTTP_BODY_NOT_ALLOWED(): Error; +declare function $ERR_DIR_CLOSED(): Error; /** * Convert a function to a class-like object. diff --git a/src/js/internal/abort_listener.ts b/src/js/internal/abort_listener.ts index 8a5ee71867..89b6d0f008 100644 --- a/src/js/internal/abort_listener.ts +++ b/src/js/internal/abort_listener.ts @@ -1,8 +1,6 @@ const { validateAbortSignal, validateFunction } = require("internal/validators"); const { kResistStopPropagation } = require("internal/shared"); -const SymbolDispose = Symbol.dispose; - function addAbortListener(signal: AbortSignal, listener: EventListener): Disposable { if (signal === undefined) { throw $ERR_INVALID_ARG_TYPE("signal", "AbortSignal", signal); @@ -15,14 +13,13 @@ function addAbortListener(signal: AbortSignal, listener: EventListener): Disposa queueMicrotask(() => listener()); } else { // TODO(atlowChemi) add { subscription: true } and return directly - signal.addEventListener("abort", listener, { __proto__: null, once: true, [kResistStopPropagation]: true }); + signal.addEventListener("abort", listener, { once: true, [kResistStopPropagation]: true }); removeEventListener = () => { signal.removeEventListener("abort", listener); }; } return { - __proto__: null, - [SymbolDispose]() { + [Symbol.dispose]() { removeEventListener?.(); }, }; diff --git a/src/js/internal/assert/assertion_error.ts b/src/js/internal/assert/assertion_error.ts index b772220961..c12a3f9cd9 100644 --- a/src/js/internal/assert/assertion_error.ts +++ b/src/js/internal/assert/assertion_error.ts @@ -3,6 +3,7 @@ const { inspect } = require("internal/util/inspect"); const colors = require("internal/util/colors"); const { validateObject } = require("internal/validators"); +const { myersDiff, printMyersDiff, printSimpleMyersDiff } = require("internal/assert/myers_diff") as typeof Internal; const ErrorCaptureStackTrace = Error.captureStackTrace; const ObjectAssign = Object.assign; @@ -34,8 +35,6 @@ declare namespace Internal { function printSimpleMyersDiff(...args: any[]): any; } -const { myersDiff, printMyersDiff, printSimpleMyersDiff } = require("internal/assert/myers_diff") as typeof Internal; - const kReadableOperator = { deepStrictEqual: "Expected values to be strictly deep-equal:", strictEqual: "Expected values to be strictly equal:", @@ -242,6 +241,11 @@ function addEllipsis(string) { } class AssertionError extends Error { + generatedMessage; + actual; + expected; + operator; + constructor(options) { validateObject(options, "options"); const { @@ -361,9 +365,6 @@ class AssertionError extends Error { }); this.code = "ERR_ASSERTION"; if (details) { - this.actual = undefined; - this.expected = undefined; - this.operator = undefined; for (let i = 0; i < details.length; i++) { this["message " + i] = details[i].message; this["actual " + i] = details[i].actual; diff --git a/src/js/internal/assert/calltracker.ts b/src/js/internal/assert/calltracker.ts index 57221f78cd..dc69c78dc8 100644 --- a/src/js/internal/assert/calltracker.ts +++ b/src/js/internal/assert/calltracker.ts @@ -81,7 +81,7 @@ class CallTracker { } calls(fn, expected = 1) { - if (process._exiting) throw $ERR_UNAVAILABLE_DURING_EXIT("Cannot call function in process exit handler"); + if (process._exiting) throw $ERR_UNAVAILABLE_DURING_EXIT(); if (typeof fn === "number") { expected = fn; fn = noop; @@ -110,7 +110,7 @@ class CallTracker { } report() { - const errors = []; + const errors: Error[] = []; for (const context of this.#callChecks) { const message = context.report(); if (message !== undefined) { diff --git a/src/js/internal/cluster/Worker.ts b/src/js/internal/cluster/Worker.ts index 4249d1364c..3ed3120124 100644 --- a/src/js/internal/cluster/Worker.ts +++ b/src/js/internal/cluster/Worker.ts @@ -1,7 +1,6 @@ const EventEmitter = require("node:events"); const ObjectFreeze = Object.freeze; -const ObjectSetPrototypeOf = Object.setPrototypeOf; const kEmptyObject = ObjectFreeze({ __proto__: null }); diff --git a/src/js/internal/cluster/child.ts b/src/js/internal/cluster/child.ts index 6e9a94686d..7a73fed8c2 100644 --- a/src/js/internal/cluster/child.ts +++ b/src/js/internal/cluster/child.ts @@ -147,7 +147,7 @@ function rr(message, { indexesKey, index }, cb) { let key = message.key; - let fakeHandle: number | null = null; + let fakeHandle: Timer | null = null; function ref() { if (!fakeHandle) { diff --git a/src/js/internal/streams/duplexpair.ts b/src/js/internal/streams/duplexpair.ts index 63211b8032..a05efe5170 100644 --- a/src/js/internal/streams/duplexpair.ts +++ b/src/js/internal/streams/duplexpair.ts @@ -7,10 +7,10 @@ const kInitOtherSide = Symbol("InitOtherSide"); class DuplexSide extends Duplex { #otherSide = null; + [kCallback]: (() => void) | null = null; constructor(options) { super(options); - this[kCallback] = null; this.#otherSide = null; } diff --git a/src/js/internal/streams/legacy.ts b/src/js/internal/streams/legacy.ts index b2f61314f6..5adff57197 100644 --- a/src/js/internal/streams/legacy.ts +++ b/src/js/internal/streams/legacy.ts @@ -90,7 +90,7 @@ Stream.prototype.pipe = function (dest, options) { }; Stream.prototype.eventNames = function eventNames() { - const names = []; + const names: PropertyKey[] = []; for (const key of ReflectOwnKeys(this._events)) { if (typeof this._events[key] === "function" || (ArrayIsArray(this._events[key]) && this._events[key].length > 0)) { names.push(key); diff --git a/src/js/internal/streams/operators.ts b/src/js/internal/streams/operators.ts index c2ae0b0744..103c4e5084 100644 --- a/src/js/internal/streams/operators.ts +++ b/src/js/internal/streams/operators.ts @@ -335,7 +335,7 @@ function toIntegerOrInfinity(number) { return number; } -function drop(number, options = undefined) { +function drop(number, options?) { if (options != null) { validateObject(options, "options"); } diff --git a/src/js/internal/util.ts b/src/js/internal/util.ts deleted file mode 100644 index 32db0807c3..0000000000 --- a/src/js/internal/util.ts +++ /dev/null @@ -1,5 +0,0 @@ -const isInsideNodeModules: () => boolean = $newZigFunction("node_util_binding.zig", "isInsideNodeModules", 0); - -export default { - isInsideNodeModules, -}; diff --git a/src/js/internal/webstreams_adapters.ts b/src/js/internal/webstreams_adapters.ts index f69d1bb1b4..26c972e6f1 100644 --- a/src/js/internal/webstreams_adapters.ts +++ b/src/js/internal/webstreams_adapters.ts @@ -164,7 +164,7 @@ class ReadableFromWeb extends Readable { const encoder = new TextEncoder(); // Collect all negative (error) ZLIB codes and Z_NEED_DICT -const ZLIB_FAILURES = new SafeSet([ +const ZLIB_FAILURES: Set = new SafeSet([ ...ArrayPrototypeFilter.$call( ArrayPrototypeMap.$call(ObjectEntries(constants_zlib), ({ 0: code, 1: value }) => (value < 0 ? code : null)), Boolean, diff --git a/src/js/node/assert.ts b/src/js/node/assert.ts index b32ee2ba24..89d2452c18 100644 --- a/src/js/node/assert.ts +++ b/src/js/node/assert.ts @@ -377,7 +377,7 @@ const SafeSetPrototypeIterator = SafeSet.prototype[SymbolIterator]; * @example * compareBranch({a: 1, b: 2, c: 3}, {a: 1, b: 2}); // true */ -function compareBranch(actual, expected, comparedObjects) { +function compareBranch(actual, expected, comparedObjects?) { // Check for Map object equality if (isMap(actual) && isMap(expected)) { return Bun.deepEquals(actual, expected, true); @@ -711,17 +711,13 @@ function expectsError(stackStartFn: Function, actual: unknown, error: unknown, m } if (typeof actual === "object" && actual !== null) { if ((actual as { message?: unknown }).message === error) { - throw $ERR_AMBIGUOUS_ARGUMENT( - `The "error/message" argument is ambiguous. The error message "${(actual as { message?: unknown }).message}" is identical to the message.`, - ); + throw $ERR_AMBIGUOUS_ARGUMENT("error/message", `The error message "${(actual as { message?: unknown }).message}" is identical to the message.`); // prettier-ignore } if (Object.keys(error).length === 0) { throw $ERR_INVALID_ARG_VALUE("error", error, "may not be an empty object"); } } else if (actual === error) { - throw $ERR_AMBIGUOUS_ARGUMENT( - `The "error/message" argument is ambiguous. The error "${actual}" is identical to the message.`, - ); + throw $ERR_AMBIGUOUS_ARGUMENT("error/message", `The error "${actual}" is identical to the message.`); } message = error; error = undefined; diff --git a/src/js/node/async_hooks.ts b/src/js/node/async_hooks.ts index 840afac3b9..8a06e26c8b 100644 --- a/src/js/node/async_hooks.ts +++ b/src/js/node/async_hooks.ts @@ -269,11 +269,11 @@ class AsyncResource { triggerAsyncId = opts.triggerAsyncId === undefined ? 1 : opts.triggerAsyncId; } if (!Number.isSafeInteger(triggerAsyncId) || triggerAsyncId < -1) { - throw $ERR_INVALID_ASYNC_ID(`Invalid triggerAsyncId value: ${triggerAsyncId}`); + throw $ERR_INVALID_ASYNC_ID("triggerAsyncId", triggerAsyncId); } } if (hasEnabledCreateHook && type.length === 0) { - throw $ERR_ASYNC_TYPE(`Invalid name for async "type": ${type}`); + throw $ERR_ASYNC_TYPE(type); } setAsyncHooksEnabled(true); @@ -373,13 +373,12 @@ let hasEnabledCreateHook = false; function createHook(hook) { validateObject(hook, "hook"); const { init, before, after, destroy, promiseResolve } = hook; - if (init !== undefined && typeof init !== "function") throw $ERR_ASYNC_CALLBACK("hook.init must be a function"); - if (before !== undefined && typeof before !== "function") throw $ERR_ASYNC_CALLBACK("hook.before must be a function"); - if (after !== undefined && typeof after !== "function") throw $ERR_ASYNC_CALLBACK("hook.after must be a function"); - if (destroy !== undefined && typeof destroy !== "function") - throw $ERR_ASYNC_CALLBACK("hook.destroy must be a function"); + if (init !== undefined && typeof init !== "function") throw $ERR_ASYNC_CALLBACK("hook.init"); + if (before !== undefined && typeof before !== "function") throw $ERR_ASYNC_CALLBACK("hook.before"); + if (after !== undefined && typeof after !== "function") throw $ERR_ASYNC_CALLBACK("hook.after"); + if (destroy !== undefined && typeof destroy !== "function") throw $ERR_ASYNC_CALLBACK("hook.destroy"); if (promiseResolve !== undefined && typeof promiseResolve !== "function") - throw $ERR_ASYNC_CALLBACK("hook.promiseResolve must be a function"); + throw $ERR_ASYNC_CALLBACK("hook.promiseResolve"); return { enable() { diff --git a/src/js/node/crypto.ts b/src/js/node/crypto.ts index 521cc8ef1b..d3ddb1ca56 100644 --- a/src/js/node/crypto.ts +++ b/src/js/node/crypto.ts @@ -2571,7 +2571,7 @@ crypto_exports.diffieHellman = function diffieHellman(options) { const privateType = privateKey.asymmetricKeyType; const publicType = publicKey.asymmetricKeyType; if (privateType !== publicType || !["dh", "ec", "x448", "x25519"].includes(privateType)) { - throw $ERR_CRYPTO_INCOMPATIBLE_KEY(`Incompatible key types for Diffie-Hellman: ${privateType} and ${publicType}`); + throw $ERR_CRYPTO_INCOMPATIBLE_KEY("key types for Diffie-Hellman", `${privateType} and ${publicType}`); } return statelessDH(privateKey.$bunNativePtr, publicKey.$bunNativePtr); diff --git a/src/js/node/diagnostics_channel.ts b/src/js/node/diagnostics_channel.ts index dfdca8b13d..b87e913f6a 100644 --- a/src/js/node/diagnostics_channel.ts +++ b/src/js/node/diagnostics_channel.ts @@ -92,6 +92,10 @@ function wrapStoreRun(store, data, next, transform = defaultTransform) { } class ActiveChannel { + _subscribers; + name; + _stores; + subscribe(subscription) { validateFunction(subscription, "subscription"); @@ -162,6 +166,10 @@ class ActiveChannel { } class Channel { + _subscribers; + _stores; + name; + constructor(name) { this._subscribers = undefined; this._stores = undefined; @@ -241,6 +249,12 @@ function assertChannel(value, name) { } class TracingChannel { + start; + end; + asyncStart; + asyncEnd; + error; + constructor(nameOrChannels) { if (typeof nameOrChannels === "string") { this.start = channel(`tracing:${nameOrChannels}:start`); diff --git a/src/js/node/dns.ts b/src/js/node/dns.ts index de7af10956..bc821360ce 100644 --- a/src/js/node/dns.ts +++ b/src/js/node/dns.ts @@ -357,7 +357,7 @@ function validateResolverOptions(options) { if ("timeout" in options) { const timeout = options.timeout; if ((timeout < 0 && timeout != -1) || Math.floor(timeout) != timeout || timeout >= 2 ** 31) { - throw $ERR_OUT_OF_RANGE("Invalid timeout", timeout); + throw $ERR_OUT_OF_RANGE("timeout", "Invalid timeout", timeout); } } } diff --git a/src/js/node/events.ts b/src/js/node/events.ts index 42686bea80..ec6e1410ea 100644 --- a/src/js/node/events.ts +++ b/src/js/node/events.ts @@ -705,7 +705,7 @@ function listenerCountSlow(emitter, type) { return 0; } -function eventTargetAgnosticRemoveListener(emitter, name, listener, flags) { +function eventTargetAgnosticRemoveListener(emitter, name, listener, flags?) { if (typeof emitter.removeListener === "function") { emitter.removeListener(name, listener); } else if (typeof emitter.removeEventListener === "function") { diff --git a/src/js/node/fs.promises.ts b/src/js/node/fs.promises.ts index 88730b4e64..f987507fa7 100644 --- a/src/js/node/fs.promises.ts +++ b/src/js/node/fs.promises.ts @@ -626,7 +626,7 @@ async function writeFileAsyncIteratorInner(fd, iterable, encoding, signal: Abort $debug("Re-encoding chunk to", encoding); chunk = Buffer.from(chunk, encoding); } else if ($isUndefinedOrNull(chunk)) { - throw $ERR_INVALID_ARG_TYPE("write() expects a string, ArrayBufferView, or ArrayBuffer"); + throw $ERR_INVALID_ARG_TYPE("chunk", ["string", "ArrayBufferView", "ArrayBuffer"], chunk); } const prom = writer.write(chunk); diff --git a/src/js/node/http.ts b/src/js/node/http.ts index e236beacf0..38a77bc137 100644 --- a/src/js/node/http.ts +++ b/src/js/node/http.ts @@ -130,20 +130,18 @@ function checkInvalidHeaderChar(val: string) { return RegExpPrototypeExec.$call(headerCharRegex, val) !== null; } -const validateHeaderName = (name, label) => { +const validateHeaderName = (name, label?) => { if (typeof name !== "string" || !name || !checkIsHttpToken(name)) { - throw $ERR_INVALID_HTTP_TOKEN(`The arguments Header name is invalid. Received ${name}`); + throw $ERR_INVALID_HTTP_TOKEN(label || "Header name", name); } }; const validateHeaderValue = (name, value) => { if (value === undefined) { - // throw new ERR_HTTP_INVALID_HEADER_VALUE(value, name); - throw $ERR_HTTP_INVALID_HEADER_VALUE(`Invalid header value: ${value} for ${name}`); + throw $ERR_HTTP_INVALID_HEADER_VALUE(value, name); } if (checkInvalidHeaderChar(value)) { - // throw new ERR_INVALID_CHAR("header content", name); - throw $ERR_INVALID_CHAR(`Invalid header value: ${value} for ${name}`); + throw $ERR_INVALID_CHAR("header content", name); } }; @@ -181,7 +179,7 @@ function isValidTLSArray(obj) { if (Array.isArray(obj)) { for (var i = 0; i < obj.length; i++) { const item = obj[i]; - if (typeof item !== "string" && !isTypedArray(item) && !isArrayBuffer(item) && !$inheritsBlob(item)) return false; + if (typeof item !== "string" && !isTypedArray(item) && !isArrayBuffer(item) && !$inheritsBlob(item)) return false; // prettier-ignore } return true; } @@ -1181,7 +1179,7 @@ function hasServerResponseFinished(self, chunk, callback) { if (finished || destroyed) { let err; if (finished) { - err = $ERR_STREAM_WRITE_AFTER_END("Stream is already finished"); + err = $ERR_STREAM_WRITE_AFTER_END(); } else if (destroyed) { err = $ERR_STREAM_DESTROYED("Stream is destroyed"); } @@ -1609,7 +1607,7 @@ const OutgoingMessagePrototype = { }, _implicitHeader() { - throw $ERR_METHOD_NOT_IMPLEMENTED("The method _implicitHeader() is not implemented"); + throw $ERR_METHOD_NOT_IMPLEMENTED("_implicitHeader()"); }, flushHeaders() {}, getHeader(name) { @@ -1659,7 +1657,7 @@ const OutgoingMessagePrototype = { removeHeader(name) { if (this[headerStateSymbol] === NodeHTTPHeaderState.sent) { - throw $ERR_HTTP_HEADERS_SENT("Cannot remove header after headers have been sent."); + throw $ERR_HTTP_HEADERS_SENT("remove"); } const headers = this[headersSymbol]; if (!headers) return; @@ -1989,7 +1987,7 @@ const ServerResponsePrototype = { if (this.req?.method === "HEAD") { chunk = undefined; } else { - throw $ERR_HTTP_BODY_NOT_ALLOWED("Adding content for this request method or response status is not allowed."); + throw $ERR_HTTP_BODY_NOT_ALLOWED(); } } @@ -2076,7 +2074,7 @@ const ServerResponsePrototype = { return false; } if (chunk && !this._hasBody) { - throw $ERR_HTTP_BODY_NOT_ALLOWED("Adding content for this request method or response status is not allowed."); + throw $ERR_HTTP_BODY_NOT_ALLOWED(); } let result = 0; @@ -2268,7 +2266,7 @@ const ServerResponse_writeDeprecated = function _write(chunk, encoding, callback } if (this.destroyed || this.finished) { if (chunk) { - emitErrorNextTickIfErrorListenerNT(this, $ERR_STREAM_WRITE_AFTER_END("Cannot write after end"), callback); + emitErrorNextTickIfErrorListenerNT(this, $ERR_STREAM_WRITE_AFTER_END(), callback); } return false; } @@ -2351,7 +2349,7 @@ function ServerResponse_finalDeprecated(chunk, encoding, callback) { if (this.destroyed || this.finished) { if (chunk) { - emitErrorNextTickIfErrorListenerNT(this, $ERR_STREAM_WRITE_AFTER_END("Cannot write after end"), callback); + emitErrorNextTickIfErrorListenerNT(this, $ERR_STREAM_WRITE_AFTER_END(), callback); } return false; } @@ -2541,7 +2539,7 @@ function ClientRequest(input, options, cb) { if (chunk) { if (this.finished) { - emitErrorNextTickIfErrorListenerNT(this, $ERR_STREAM_WRITE_AFTER_END("Cannot write after end"), callback); + emitErrorNextTickIfErrorListenerNT(this, $ERR_STREAM_WRITE_AFTER_END(), callback); return this; } @@ -2918,7 +2916,7 @@ function ClientRequest(input, options, cb) { if (options.path) { const path = String(options.path); if (RegExpPrototypeExec.$call(INVALID_PATH_REGEX, path) !== null) { - throw $ERR_UNESCAPED_CHARACTERS("Request path contains unescaped characters"); + throw $ERR_UNESCAPED_CHARACTERS("Request path"); } } @@ -2954,7 +2952,7 @@ function ClientRequest(input, options, cb) { if (methodIsString && method) { if (!checkIsHttpToken(method)) { - throw $ERR_INVALID_HTTP_TOKEN("Method"); + throw $ERR_INVALID_HTTP_TOKEN("Method", method); } method = this[kMethod] = StringPrototypeToUpperCase.$call(method); } else { @@ -3400,7 +3398,7 @@ function _normalizeArgs(args) { function _writeHead(statusCode, reason, obj, response) { statusCode |= 0; if (statusCode < 100 || statusCode > 999) { - throw $ERR_HTTP_INVALID_STATUS_CODE(`Invalid status code: ${statusCode}`); + throw $ERR_HTTP_INVALID_STATUS_CODE(statusCode); } if (typeof reason === "string") { diff --git a/src/js/node/http2.ts b/src/js/node/http2.ts index db998402d4..4ef1bc2c66 100644 --- a/src/js/node/http2.ts +++ b/src/js/node/http2.ts @@ -254,13 +254,13 @@ function connectionHeaderMessageWarn() { function assertValidHeader(name, value) { if (name === "" || typeof name !== "string" || StringPrototypeIncludes.$call(name, " ")) { - throw $ERR_INVALID_HTTP_TOKEN(`The arguments Header name is invalid. Received ${name}`); + throw $ERR_INVALID_HTTP_TOKEN("Header name", name); } if (isPseudoHeader(name)) { - throw $ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED("Cannot set HTTP/2 pseudo-headers"); + throw $ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED(); } if (value === undefined || value === null) { - throw $ERR_HTTP2_INVALID_HEADER_VALUE(`Invalid value "${value}" for header "${name}"`); + throw $ERR_HTTP2_INVALID_HEADER_VALUE(value, name); } if (!isConnectionHeaderAllowed(name, value)) { connectionHeaderMessageWarn(); @@ -270,6 +270,14 @@ function assertValidHeader(name, value) { hideFromStack(assertValidHeader); class Http2ServerRequest extends Readable { + [kState]; + [kHeaders]; + [kRawHeaders]; + [kTrailers]; + [kRawTrailers]; + [kStream]; + [kAborted]; + constructor(stream, headers, options, rawHeaders) { super({ autoDestroy: false, ...options }); this[kState] = { @@ -388,7 +396,12 @@ class Http2ServerRequest extends Readable { } } class Http2ServerResponse extends Stream { - constructor(stream, options) { + [kState]; + [kHeaders]; + [kTrailers]; + [kStream]; + + constructor(stream, options?) { super(options); this[kState] = { closed: false, @@ -478,9 +491,8 @@ class Http2ServerResponse extends Stream { set statusCode(code) { code |= 0; - if (code >= 100 && code < 200) - throw $ERR_HTTP2_INFO_STATUS_NOT_ALLOWED("Informational status codes cannot be used"); - if (code < 100 || code > 599) throw $ERR_HTTP2_STATUS_INVALID(`Invalid status code: ${code}`); + if (code >= 100 && code < 200) throw $ERR_HTTP2_INFO_STATUS_NOT_ALLOWED(); + if (code < 100 || code > 599) throw $ERR_HTTP2_STATUS_INVALID(code); this[kState].statusCode = code; } @@ -523,7 +535,7 @@ class Http2ServerResponse extends Stream { removeHeader(name) { validateString(name, "name"); - if (this[kStream].headersSent) throw $ERR_HTTP2_HEADERS_SENT("Response has already been initiated."); + if (this[kStream].headersSent) throw $ERR_HTTP2_HEADERS_SENT(); name = StringPrototypeToLowerCase.$call(StringPrototypeTrim.$call(name)); @@ -538,7 +550,7 @@ class Http2ServerResponse extends Stream { setHeader(name, value) { validateString(name, "name"); - if (this[kStream].headersSent) throw $ERR_HTTP2_HEADERS_SENT("Response has already been initiated."); + if (this[kStream].headersSent) throw $ERR_HTTP2_HEADERS_SENT(); this[kSetHeader](name, value); } @@ -552,15 +564,14 @@ class Http2ServerResponse extends Stream { } if (name[0] === ":") assertValidPseudoHeader(name); - else if (!checkIsHttpToken(name)) - this.destroy($ERR_INVALID_HTTP_TOKEN(`The arguments Header name is invalid. Received ${name}`)); + else if (!checkIsHttpToken(name)) this.destroy($ERR_INVALID_HTTP_TOKEN("Header name", name)); this[kHeaders][name] = value; } appendHeader(name, value) { validateString(name, "name"); - if (this[kStream].headersSent) throw $ERR_HTTP2_HEADERS_SENT("Response has already been initiated."); + if (this[kStream].headersSent) throw $ERR_HTTP2_HEADERS_SENT(); this[kAppendHeader](name, value); } @@ -574,8 +585,7 @@ class Http2ServerResponse extends Stream { } if (name[0] === ":") assertValidPseudoHeader(name); - else if (!checkIsHttpToken(name)) - this.destroy($ERR_INVALID_HTTP_TOKEN(`The arguments Header name is invalid. Received ${name}`)); + else if (!checkIsHttpToken(name)) this.destroy($ERR_INVALID_HTTP_TOKEN("Header name", name)); // Handle various possible cases the same as OutgoingMessage.appendHeader: const headers = this[kHeaders]; @@ -612,11 +622,11 @@ class Http2ServerResponse extends Stream { if (!state.closed && !this[kStream].headersSent) this.writeHead(state.statusCode); } - writeHead(statusCode, statusMessage, headers) { + writeHead(statusCode, statusMessage?, headers?) { const state = this[kState]; if (state.closed || this.stream.destroyed) return this; - if (this[kStream].headersSent) throw $ERR_HTTP2_HEADERS_SENT("Response has already been initiated."); + if (this[kStream].headersSent) throw $ERR_HTTP2_HEADERS_SENT(); if (typeof statusMessage === "string") statusMessageWarn(); @@ -684,7 +694,7 @@ class Http2ServerResponse extends Stream { this[kStream].uncork(); } - write(chunk, encoding, cb) { + write(chunk, encoding, cb?) { const state = this[kState]; if (typeof encoding === "function") { @@ -694,9 +704,9 @@ class Http2ServerResponse extends Stream { let err; if (state.ending) { - err = $ERR_STREAM_WRITE_AFTER_END(`The stream has ended`); + err = $ERR_STREAM_WRITE_AFTER_END(); } else if (state.closed) { - err = $ERR_HTTP2_INVALID_STREAM(`The stream has been destroyed`); + err = $ERR_HTTP2_INVALID_STREAM(); } else if (state.destroyed) { return false; } @@ -764,7 +774,7 @@ class Http2ServerResponse extends Stream { createPushResponse(headers, callback) { validateFunction(callback, "callback"); if (this[kState].closed) { - const error = $ERR_HTTP2_INVALID_STREAM(`The stream has been destroyed`); + const error = $ERR_HTTP2_INVALID_STREAM(); process.nextTick(callback, error); return; } @@ -875,13 +885,11 @@ const proxySocketHandler = { case "setEncoding": case "setKeepAlive": case "setNoDelay": - throw $ERR_HTTP2_NO_SOCKET_MANIPULATION( - "HTTP/2 sockets should not be directly manipulated (e.g. read and written)", - ); + throw $ERR_HTTP2_NO_SOCKET_MANIPULATION(); default: { const socket = session[bunHTTP2Socket]; if (!socket) { - throw $ERR_HTTP2_SOCKET_UNBOUND("The socket has been disconnected from the Http2Session"); + throw $ERR_HTTP2_SOCKET_UNBOUND(); } const value = socket[prop]; return typeof value === "function" ? FunctionPrototypeBind.$call(value, socket) : value; @@ -891,7 +899,7 @@ const proxySocketHandler = { getPrototypeOf(session) { const socket = session[bunHTTP2Socket]; if (!socket) { - throw $ERR_HTTP2_SOCKET_UNBOUND("The socket has been disconnected from the Http2Session"); + throw $ERR_HTTP2_SOCKET_UNBOUND(); } return ReflectGetPrototypeOf(socket); }, @@ -912,13 +920,11 @@ const proxySocketHandler = { case "setEncoding": case "setKeepAlive": case "setNoDelay": - throw $ERR_HTTP2_NO_SOCKET_MANIPULATION( - "HTTP/2 sockets should not be directly manipulated (e.g. read and written)", - ); + throw $ERR_HTTP2_NO_SOCKET_MANIPULATION(); default: { const socket = session[bunHTTP2Socket]; if (!socket) { - throw $ERR_HTTP2_SOCKET_UNBOUND("The socket has been disconnected from the Http2Session"); + throw $ERR_HTTP2_SOCKET_UNBOUND(); } socket[prop] = value; return true; @@ -1485,7 +1491,7 @@ const kSingleValueHeaders = new SafeSet([ function assertValidPseudoHeader(key) { if (!kValidPseudoHeaders.has(key)) { - throw $ERR_HTTP2_INVALID_PSEUDOHEADER(`"${key}" is an invalid pseudoheader or is used incorrectly`); + throw $ERR_HTTP2_INVALID_PSEUDOHEADER(key); } } hideFromStack(assertValidPseudoHeader); @@ -1509,22 +1515,22 @@ class Http2Session extends EventEmitter { function streamErrorFromCode(code: number) { if (code === 0xe) { - return $ERR_HTTP2_MAX_PENDING_SETTINGS_ACK("Maximum number of pending settings acknowledgements"); + return $ERR_HTTP2_MAX_PENDING_SETTINGS_ACK(); } - return $ERR_HTTP2_STREAM_ERROR(`Stream closed with error code ${nameForErrorCode[code] || code}`); + return $ERR_HTTP2_STREAM_ERROR(nameForErrorCode[code] || code); } hideFromStack(streamErrorFromCode); function sessionErrorFromCode(code: number) { if (code === 0xe) { - return $ERR_HTTP2_MAX_PENDING_SETTINGS_ACK("Maximum number of pending settings acknowledgements"); + return $ERR_HTTP2_MAX_PENDING_SETTINGS_ACK(); } - return $ERR_HTTP2_SESSION_ERROR(`Session closed with error code ${nameForErrorCode[code] || code}`); + return $ERR_HTTP2_SESSION_ERROR(nameForErrorCode[code] || code); } hideFromStack(sessionErrorFromCode); function assertSession(session) { if (!session) { - throw $ERR_HTTP2_INVALID_SESSION(`The session has been destroyed`); + throw $ERR_HTTP2_INVALID_SESSION(); } } hideFromStack(assertSession); @@ -1623,24 +1629,22 @@ class Http2Stream extends Duplex { const session = this[bunHTTP2Session]; if (this.destroyed || this.closed) { - throw $ERR_HTTP2_INVALID_STREAM(`The stream has been destroyed`); + throw $ERR_HTTP2_INVALID_STREAM(); } if (this.#sentTrailers) { - throw $ERR_HTTP2_TRAILERS_ALREADY_SENT(`Trailing headers have already been sent`); + throw $ERR_HTTP2_TRAILERS_ALREADY_SENT(); } assertSession(session); if ((this[bunHTTP2StreamStatus] & StreamState.WantTrailer) === 0) { - throw $ERR_HTTP2_TRAILERS_NOT_READY( - "Trailing headers cannot be sent until after the wantTrailers event is emitted", - ); + throw $ERR_HTTP2_TRAILERS_NOT_READY(); } if (headers == undefined) { headers = {}; } else if (!$isObject(headers)) { - throw $ERR_HTTP2_INVALID_HEADERS("headers must be an object"); + throw $ERR_INVALID_ARG_TYPE("headers", "object", headers); } else { headers = { ...headers }; } @@ -1897,9 +1901,7 @@ function doSendFileFD(options, fd, headers, err, stat) { options.length >= 0 || isDirectory ) { - const err = isDirectory - ? $ERR_HTTP2_SEND_FILE("Directories cannot be sent") - : $ERR_HTTP2_SEND_FILE_NOSEEK("Offset or length can only be specified for regular files"); + const err = isDirectory ? $ERR_HTTP2_SEND_FILE() : $ERR_HTTP2_SEND_FILE_NOSEEK(); tryClose(fd); if (onError) onError(err); else { @@ -1915,7 +1917,7 @@ function doSendFileFD(options, fd, headers, err, stat) { if (this.destroyed || this.closed) { tryClose(fd); - const error = $ERR_HTTP2_INVALID_STREAM(`The stream has been destroyed`); + const error = $ERR_HTTP2_INVALID_STREAM(); this.respond(headers, options); this.destroy(error); return; @@ -1995,19 +1997,19 @@ class ServerHttp2Stream extends Http2Stream { super(streamId, session, headers); } pushStream() { - throw $ERR_HTTP2_PUSH_DISABLED("HTTP/2 client has disabled push streams"); + throw $ERR_HTTP2_PUSH_DISABLED(); } respondWithFile(path, headers, options) { if (this.destroyed || this.closed) { - throw $ERR_HTTP2_INVALID_STREAM(`The stream has been destroyed`); + throw $ERR_HTTP2_INVALID_STREAM(); } - if (this.headersSent) throw $ERR_HTTP2_HEADERS_SENT("Response has already been initiated."); + if (this.headersSent) throw $ERR_HTTP2_HEADERS_SENT(); if (headers == undefined) { headers = {}; } else if (!$isObject(headers)) { - throw $ERR_HTTP2_INVALID_HEADERS("headers must be an object"); + throw $ERR_INVALID_ARG_TYPE("headers", "object", headers); } else { headers = { ...headers }; } @@ -2025,7 +2027,7 @@ class ServerHttp2Stream extends Http2Stream { statusCode === HTTP_STATUS_NOT_MODIFIED || this.headRequest ) { - throw $ERR_HTTP2_PAYLOAD_FORBIDDEN(`Responses with ${statusCode} status must not have a payload`); + throw $ERR_HTTP2_PAYLOAD_FORBIDDEN(statusCode); } if (options.offset !== undefined && typeof options.offset !== "number") { @@ -2041,14 +2043,14 @@ class ServerHttp2Stream extends Http2Stream { } respondWithFD(fd, headers, options) { if (this.destroyed || this.closed) { - throw $ERR_HTTP2_INVALID_STREAM(`The stream has been destroyed`); + throw $ERR_HTTP2_INVALID_STREAM(); } - if (this.headersSent) throw $ERR_HTTP2_HEADERS_SENT("Response has already been initiated."); + if (this.headersSent) throw $ERR_HTTP2_HEADERS_SENT(); if (headers == undefined) { headers = {}; } else if (!$isObject(headers)) { - throw $ERR_HTTP2_INVALID_HEADERS("headers must be an object"); + throw $ERR_INVALID_ARG_TYPE("headers", "object", headers); } else { headers = { ...headers }; } @@ -2065,7 +2067,7 @@ class ServerHttp2Stream extends Http2Stream { statusCode === HTTP_STATUS_NOT_MODIFIED || this.headRequest ) { - throw $ERR_HTTP2_PAYLOAD_FORBIDDEN(`Responses with ${statusCode} status must not have a payload`); + throw $ERR_HTTP2_PAYLOAD_FORBIDDEN(statusCode); } options = { ...options }; if (options.offset !== undefined && typeof options.offset !== "number") { @@ -2085,26 +2087,27 @@ class ServerHttp2Stream extends Http2Stream { } additionalHeaders(headers) { if (this.destroyed || this.closed) { - throw $ERR_HTTP2_INVALID_STREAM(`The stream has been destroyed`); + throw $ERR_HTTP2_INVALID_STREAM(); } if (this.sentTrailers) { - throw $ERR_HTTP2_TRAILERS_ALREADY_SENT(`Trailing headers have already been sent`); + throw $ERR_HTTP2_TRAILERS_ALREADY_SENT(); + } + if (this.headersSent) { + throw $ERR_HTTP2_HEADERS_AFTER_RESPOND(); } - if (this.headersSent) - throw $ERR_HTTP2_HEADERS_AFTER_RESPOND("Cannot specify additional headers after response initiated"); if (headers == undefined) { headers = {}; } else if (!$isObject(headers)) { - throw $ERR_HTTP2_INVALID_HEADERS("headers must be an object"); + throw $ERR_INVALID_ARG_TYPE("headers", "object", headers); } else { headers = { ...headers }; } for (const name in headers) { if (name.startsWith(":") && name !== HTTP2_HEADER_STATUS) { - throw $ERR_HTTP2_INVALID_PSEUDOHEADER(`"${name}" is an invalid pseudoheader or is used incorrectly`); + throw $ERR_HTTP2_INVALID_PSEUDOHEADER(name); } } @@ -2126,10 +2129,9 @@ class ServerHttp2Stream extends Http2Stream { } const statusCode = headers[HTTP2_HEADER_STATUS]; if (hasStatus) { - if (statusCode === HTTP_STATUS_SWITCHING_PROTOCOLS) - throw $ERR_HTTP2_STATUS_101("HTTP status code 101 (Switching Protocols) is forbidden in HTTP/2"); + if (statusCode === HTTP_STATUS_SWITCHING_PROTOCOLS) throw $ERR_HTTP2_STATUS_101(); if (statusCode < 100 || statusCode >= 200) { - throw $ERR_HTTP2_INVALID_INFO_STATUS(`Invalid informational status code: ${statusCode}`); + throw $ERR_HTTP2_INVALID_INFO_STATUS(statusCode); } // Payload/DATA frames are not permitted in these cases @@ -2139,7 +2141,7 @@ class ServerHttp2Stream extends Http2Stream { statusCode === HTTP_STATUS_NOT_MODIFIED || this.headRequest ) { - throw $ERR_HTTP2_PAYLOAD_FORBIDDEN(`Responses with ${statusCode} status must not have a payload`); + throw $ERR_HTTP2_PAYLOAD_FORBIDDEN(statusCode); } } const session = this[bunHTTP2Session]; @@ -2154,20 +2156,20 @@ class ServerHttp2Stream extends Http2Stream { } respond(headers: any, options?: any) { if (this.destroyed || this.closed) { - throw $ERR_HTTP2_INVALID_STREAM(`The stream has been destroyed`); + throw $ERR_HTTP2_INVALID_STREAM(); } const session = this[bunHTTP2Session]; assertSession(session); - if (this.headersSent) throw $ERR_HTTP2_HEADERS_SENT("Response has already been initiated."); + if (this.headersSent) throw $ERR_HTTP2_HEADERS_SENT(); if (this.sentTrailers) { - throw $ERR_HTTP2_TRAILERS_ALREADY_SENT(`Trailing headers have already been sent`); + throw $ERR_HTTP2_TRAILERS_ALREADY_SENT(); } if (headers == undefined) { headers = {}; } else if (!$isObject(headers)) { - throw $ERR_HTTP2_INVALID_HEADERS("headers must be an object"); + throw $ERR_INVALID_ARG_TYPE("headers", "object", headers); } else { headers = { ...headers }; } @@ -2306,9 +2308,9 @@ function getOrigin(origin: any, isAltSvc: boolean): string { origin = new URL(origin).origin; } catch (e) { if (isAltSvc) { - throw $ERR_HTTP2_ALTSVC_INVALID_ORIGIN("HTTP/2 ALTSVC frames require a valid origin"); + throw $ERR_HTTP2_ALTSVC_INVALID_ORIGIN(); } else { - throw $ERR_INVALID_URL("HTTP/2 ORIGIN frames require a valid origin"); + throw $ERR_INVALID_URL(origin); } } } else if (origin != null && typeof origin === "object") { @@ -2317,9 +2319,9 @@ function getOrigin(origin: any, isAltSvc: boolean): string { validateString(origin, "origin"); if (!origin || origin === "null") { if (isAltSvc) { - throw $ERR_HTTP2_ALTSVC_INVALID_ORIGIN("HTTP/2 ALTSVC frames require a valid origin"); + throw $ERR_HTTP2_ALTSVC_INVALID_ORIGIN(); } else { - throw $ERR_HTTP2_INVALID_ORIGIN("HTTP/2 ORIGIN frames require a valid origin"); + throw $ERR_HTTP2_INVALID_ORIGIN(); } } @@ -2563,7 +2565,7 @@ class ServerHttp2Session extends Http2Session { altsvc(alt: string, originOrStream) { const MAX_LENGTH = 16382; const parser = this.#parser; - if (this.destroyed || !parser) throw $ERR_HTTP2_INVALID_SESSION(`The session has been destroyed`); + if (this.destroyed || !parser) throw $ERR_HTTP2_INVALID_SESSION(); let stream = 0; let origin; @@ -2585,7 +2587,7 @@ class ServerHttp2Session extends Http2Session { if (typeof origin !== "string") { throw $ERR_INVALID_ARG_TYPE("originOrStream", ["string", "number", "URL", "object"], originOrStream); } else if (!origin) { - throw $ERR_HTTP2_ALTSVC_INVALID_ORIGIN("HTTP/2 ALTSVC frames require a valid origin"); + throw $ERR_HTTP2_ALTSVC_INVALID_ORIGIN(); } else { origin = getOrigin(origin, true); } @@ -2594,17 +2596,17 @@ class ServerHttp2Session extends Http2Session { validateString(alt, "alt"); if (!kQuotedString.test(alt)) { - throw $ERR_INVALID_CHAR("Invalid character in alt"); + throw $ERR_INVALID_CHAR("alt"); } origin = origin || ""; if (Buffer.byteLength(origin) + Buffer.byteLength(alt) > MAX_LENGTH) { - throw $ERR_HTTP2_ALTSVC_LENGTH("HTTP/2 ALTSVC frames are limited to 16382 bytes"); + throw $ERR_HTTP2_ALTSVC_LENGTH(); } parser.altsvc(origin, alt, stream); } origin(...origins) { const parser = this.#parser; - if (this.destroyed || !parser) throw $ERR_HTTP2_INVALID_SESSION(`The session has been destroyed`); + if (this.destroyed || !parser) throw $ERR_HTTP2_INVALID_SESSION(); let length = origins.length; if (length === 0) { return; @@ -2728,7 +2730,7 @@ class ServerHttp2Session extends Http2Session { payload = payload || Buffer.alloc(8); } if (!(payload instanceof Buffer) && !isTypedArray(payload)) { - throw $ERR_INVALID_ARG_TYPE("payload must be a Buffer or TypedArray"); + throw $ERR_INVALID_ARG_TYPE("payload", ["Buffer", "TypedArray"], payload); } const parser = this.#parser; if (!parser) return false; @@ -2736,7 +2738,7 @@ class ServerHttp2Session extends Http2Session { if (typeof callback === "function") { if (payload.byteLength !== 8) { - const error = $ERR_HTTP2_PING_LENGTH("HTTP2 ping payload must be 8 bytes"); + const error = $ERR_HTTP2_PING_LENGTH(); callback(error, 0, payload); return; } @@ -2746,7 +2748,7 @@ class ServerHttp2Session extends Http2Session { this.#pingCallbacks = [[callback, Date.now()]]; } } else if (payload.byteLength !== 8) { - throw $ERR_HTTP2_PING_LENGTH("HTTP2 ping payload must be 8 bytes"); + throw $ERR_HTTP2_PING_LENGTH(); } parser.ping(payload); @@ -3133,7 +3135,7 @@ class ClientHttp2Session extends Http2Session { payload = payload || Buffer.alloc(8); } if (!(payload instanceof Buffer) && !isTypedArray(payload)) { - throw $ERR_INVALID_ARG_TYPE("payload must be a Buffer or TypedArray"); + throw $ERR_INVALID_ARG_TYPE("payload", ["Buffer", "TypedArray"], payload); } const parser = this.#parser; if (!parser) return false; @@ -3141,7 +3143,7 @@ class ClientHttp2Session extends Http2Session { if (typeof callback === "function") { if (payload.byteLength !== 8) { - const error = $ERR_HTTP2_PING_LENGTH("HTTP2 ping payload must be 8 bytes"); + const error = $ERR_HTTP2_PING_LENGTH(); callback(error, 0, payload); return; } @@ -3151,7 +3153,7 @@ class ClientHttp2Session extends Http2Session { this.#pingCallbacks = [[callback, Date.now()]]; } } else if (payload.byteLength !== 8) { - throw $ERR_HTTP2_PING_LENGTH("HTTP2 ping payload must be 8 bytes"); + throw $ERR_HTTP2_PING_LENGTH(); } parser.ping(payload); @@ -3193,7 +3195,7 @@ class ClientHttp2Session extends Http2Session { url = new URL(url); } if (!(url instanceof URL)) { - throw $ERR_INVALID_ARG_TYPE("Invalid URL"); + throw $ERR_INVALID_ARG_TYPE("url", "URL", url); } if (typeof options === "function") { listener = options; @@ -3296,17 +3298,17 @@ class ClientHttp2Session extends Http2Session { request(headers: any, options?: any) { try { if (this.destroyed || this.closed) { - throw $ERR_HTTP2_INVALID_STREAM(`The stream has been destroyed`); + throw $ERR_HTTP2_INVALID_STREAM(); } if (this.sentTrailers) { - throw $ERR_HTTP2_TRAILERS_ALREADY_SENT(`Trailing headers have already been sent`); + throw $ERR_HTTP2_TRAILERS_ALREADY_SENT(); } if (headers == undefined) { headers = {}; } else if (!$isObject(headers)) { - throw $ERR_HTTP2_INVALID_HEADERS("headers must be an object"); + throw $ERR_INVALID_ARG_TYPE("headers", "object", headers); } else { headers = { ...headers }; } @@ -3367,7 +3369,7 @@ class ClientHttp2Session extends Http2Session { const req = new ClientHttp2Stream(stream_id, this, headers); req.authority = authority; if (stream_id < 0) { - const error = $ERR_HTTP2_OUT_OF_STREAMS("No stream ID is available because maximum stream ID has been reached"); + const error = $ERR_HTTP2_OUT_OF_STREAMS(); this.emit("error", error); return null; } @@ -3479,7 +3481,7 @@ class Http2Server extends net.Server { } else if (options == null || typeof options == "object") { options = { ...options }; } else { - throw $ERR_INVALID_ARG_TYPE("options must be an object"); + throw $ERR_INVALID_ARG_TYPE("options", "object", options); } super(options, connectionListener); this.setMaxListeners(0); @@ -3518,7 +3520,7 @@ class Http2SecureServer extends tls.Server { } else if (options == null || typeof options == "object") { options = { ...options, ALPNProtocols: ["h2"] }; } else { - throw $ERR_INVALID_ARG_TYPE("options must be an object"); + throw $ERR_INVALID_ARG_TYPE("options", "object", options); } super(options, connectionListener); this.setMaxListeners(0); diff --git a/src/js/node/path.ts b/src/js/node/path.ts index 018628d021..839075af42 100644 --- a/src/js/node/path.ts +++ b/src/js/node/path.ts @@ -46,7 +46,7 @@ posix.posix = posix; type Glob = import("bun").Glob; let LazyGlob: Glob | undefined; -function loadGlob(): LazyGlob { +function loadGlob() { LazyGlob = require("bun").Glob; } @@ -68,14 +68,14 @@ function matchesGlob(isWindows, path, pattern) { if (LazyGlob === undefined) loadGlob(); validateString(pattern, "pattern"); if (isWindows) pattern = pattern.replaceAll("\\", "/"); - glob = prevGlob = new LazyGlob(pattern); + glob = prevGlob = new LazyGlob!(pattern); prevPattern = pattern; } } else { loadGlob(); // no prevGlob implies LazyGlob isn't loaded validateString(pattern, "pattern"); if (isWindows) pattern = pattern.replaceAll("\\", "/"); - glob = prevGlob = new LazyGlob(pattern); + glob = prevGlob = new LazyGlob!(pattern); prevPattern = pattern; } diff --git a/src/js/node/querystring.ts b/src/js/node/querystring.ts index d91e69f0a4..7a70d45bd3 100644 --- a/src/js/node/querystring.ts +++ b/src/js/node/querystring.ts @@ -84,7 +84,7 @@ var require_src = __commonJS((exports, module) => { // This branch should never happen because all URLSearchParams entries // should already be converted to USVString. But, included for // completion's sake anyway. - if (i >= len) throw $ERR_INVALID_URI("URI malformed"); + if (i >= len) throw $ERR_INVALID_URI(); const c2 = StringPrototypeCharCodeAt.$call(str, i) & 0x3ff; diff --git a/src/js/node/readline.ts b/src/js/node/readline.ts index 9c60e949f7..2b4d6b4199 100644 --- a/src/js/node/readline.ts +++ b/src/js/node/readline.ts @@ -162,54 +162,6 @@ function stripVTControlCharacters(str) { const kUTF16SurrogateThreshold = 0x10000; // 2 ** 16 const kEscape = "\x1b"; const kSubstringSearch = Symbol("kSubstringSearch"); -const kIsNodeError = Symbol("kIsNodeError"); - -// Errors -var errorBases = {}; -var VALID_NODE_ERROR_BASES = { - TypeError, - RangeError, - Error, -}; - -function getNodeErrorByName(typeName) { - var base = errorBases[typeName]; - if (base) { - return base; - } - if (!ObjectKeys(VALID_NODE_ERROR_BASES).includes(typeName)) { - throw new Error("Invalid NodeError type"); - } - - var Base = VALID_NODE_ERROR_BASES[typeName]; - - class NodeError extends Base { - [kIsNodeError] = true; - code; - constructor(msg, opts) { - super(msg, opts); - this.code = opts?.code || "ERR_GENERIC"; - } - - toString() { - return `${this.name} [${this.code}]: ${this.message}`; - } - } - errorBases[typeName] = NodeError; - return NodeError; -} - -var NodeError = getNodeErrorByName("Error"); -var NodeTypeError = getNodeErrorByName("TypeError"); -var NodeRangeError = getNodeErrorByName("RangeError"); - -class ERR_USE_AFTER_CLOSE extends NodeError { - constructor() { - super("This socket has been ended by the other party", { - code: "ERR_USE_AFTER_CLOSE", - }); - } -} // ---------------------------------------------------------------------------- // Section: Utils @@ -723,7 +675,7 @@ function* emitKeys(stream) { key.meta = escaped; } else if (!escaped && ch <= "\x1a") { // ctrl+letter - key.name = StringFromCharCode(StringPrototypeCharCodeAt.$call(ch) + StringPrototypeCharCodeAt.$call("a") - 1); + key.name = StringFromCharCode(StringPrototypeCharCodeAt.$call(ch, 0) + StringPrototypeCharCodeAt.$call("a", 0) - 1); // prettier-ignore key.ctrl = true; } else if (RegExpPrototypeExec.$call(/^[0-9A-Za-z]$/, ch) !== null) { // Letter, number, shift+letter @@ -1299,8 +1251,6 @@ ObjectSetPrototypeOf(InterfaceConstructor.prototype, EventEmitter.prototype); // ObjectSetPrototypeOf(InterfaceConstructor, EventEmitter); var _Interface = class Interface extends InterfaceConstructor { - // TODO: Enumerate all the properties of the class - // eslint-disable-next-line no-useless-constructor constructor(input, output, completer, terminal) { super(input, output, completer, terminal); @@ -1344,7 +1294,7 @@ var _Interface = class Interface extends InterfaceConstructor { * @param {boolean} [preserveCursor] * @returns {void} */ - prompt(preserveCursor) { + prompt(preserveCursor?) { if (this.paused) this.resume(); if (this.terminal && process.env.TERM !== "dumb") { if (!preserveCursor) this.cursor = 0; @@ -1356,7 +1306,7 @@ var _Interface = class Interface extends InterfaceConstructor { [kQuestion](query, cb) { if (this.closed) { - throw new ERR_USE_AFTER_CLOSE("readline"); + throw $ERR_USE_AFTER_CLOSE("readline"); } if (this[kQuestionCallback]) { this.prompt(); @@ -2382,133 +2332,111 @@ ObjectDefineProperties(Interface.prototype, { // Redirect internal prototype methods to the underscore notation for backward // compatibility. [kSetRawMode]: { - __proto__: null, get() { return this._setRawMode; }, }, [kOnLine]: { - __proto__: null, get() { return this._onLine; }, }, [kWriteToOutput]: { - __proto__: null, get() { return this._writeToOutput; }, }, [kAddHistory]: { - __proto__: null, get() { return this._addHistory; }, }, [kRefreshLine]: { - __proto__: null, get() { return this._refreshLine; }, }, [kNormalWrite]: { - __proto__: null, get() { return this._normalWrite; }, }, [kInsertString]: { - __proto__: null, get() { return this._insertString; }, }, [kTabComplete]: { - __proto__: null, get() { return this._tabComplete; }, }, [kWordLeft]: { - __proto__: null, get() { return this._wordLeft; }, }, [kWordRight]: { - __proto__: null, get() { return this._wordRight; }, }, [kDeleteLeft]: { - __proto__: null, get() { return this._deleteLeft; }, }, [kDeleteRight]: { - __proto__: null, get() { return this._deleteRight; }, }, [kDeleteWordLeft]: { - __proto__: null, get() { return this._deleteWordLeft; }, }, [kDeleteWordRight]: { - __proto__: null, get() { return this._deleteWordRight; }, }, [kDeleteLineLeft]: { - __proto__: null, get() { return this._deleteLineLeft; }, }, [kDeleteLineRight]: { - __proto__: null, get() { return this._deleteLineRight; }, }, [kLine]: { - __proto__: null, get() { return this._line; }, }, [kHistoryNext]: { - __proto__: null, get() { return this._historyNext; }, }, [kHistoryPrev]: { - __proto__: null, get() { return this._historyPrev; }, }, [kGetDisplayPos]: { - __proto__: null, get() { return this._getDisplayPos; }, }, [kMoveCursor]: { - __proto__: null, get() { return this._moveCursor; }, }, [kTtyWrite]: { - __proto__: null, get() { return this._ttyWrite; }, @@ -2517,7 +2445,6 @@ ObjectDefineProperties(Interface.prototype, { // Defining proxies for the internal instance properties for backward // compatibility. _decoder: { - __proto__: null, get() { return this[kDecoder]; }, @@ -2526,7 +2453,6 @@ ObjectDefineProperties(Interface.prototype, { }, }, _line_buffer: { - __proto__: null, get() { return this[kLine_buffer]; }, @@ -2535,7 +2461,6 @@ ObjectDefineProperties(Interface.prototype, { }, }, _oldPrompt: { - __proto__: null, get() { return this[kOldPrompt]; }, @@ -2544,7 +2469,6 @@ ObjectDefineProperties(Interface.prototype, { }, }, _previousKey: { - __proto__: null, get() { return this[kPreviousKey]; }, @@ -2553,7 +2477,6 @@ ObjectDefineProperties(Interface.prototype, { }, }, _prompt: { - __proto__: null, get() { return this[kPrompt]; }, @@ -2562,7 +2485,6 @@ ObjectDefineProperties(Interface.prototype, { }, }, _questionCallback: { - __proto__: null, get() { return this[kQuestionCallback]; }, @@ -2571,7 +2493,6 @@ ObjectDefineProperties(Interface.prototype, { }, }, _sawKeyPress: { - __proto__: null, get() { return this[kSawKeyPress]; }, @@ -2580,7 +2501,6 @@ ObjectDefineProperties(Interface.prototype, { }, }, _sawReturnAt: { - __proto__: null, get() { return this[kSawReturnAt]; }, diff --git a/src/js/node/tls.ts b/src/js/node/tls.ts index 226eb4dc36..cae5a32b81 100644 --- a/src/js/node/tls.ts +++ b/src/js/node/tls.ts @@ -133,7 +133,7 @@ function splitEscapedAltNames(altNames) { currentToken += StringPrototypeSubstring.$call(altNames, offset, nextQuote); const match = RegExpPrototypeExec.$call(jsonStringPattern, StringPrototypeSubstring.$call(altNames, nextQuote)); if (!match) { - throw $ERR_TLS_CERT_ALTNAME_FORMAT("Invalid subject alternative name string"); + throw $ERR_TLS_CERT_ALTNAME_FORMAT(); } currentToken += JSON.parse(match[0]); offset = nextQuote + match[0].length; @@ -200,16 +200,18 @@ function checkServerIdentity(hostname, cert) { reason = "Cert does not contain a DNS name"; } if (!valid) { - let error = $ERR_TLS_CERT_ALTNAME_INVALID(`Hostname/IP does not match certificate's altnames: ${reason}`); - error.reason = reason; - error.host = hostname; - error.cert = cert; - return error; + return $ERR_TLS_CERT_ALTNAME_INVALID(reason, hostname, cert); } } var InternalSecureContext = class SecureContext { context; + key; + cert; + ca; + passphrase; + servername; + secureOptions; constructor(options) { const context = {}; @@ -430,7 +432,7 @@ TLSSocket.prototype.enableTrace = function enableTrace() { TLSSocket.prototype.setServername = function setServername(name) { if (this.isServer) { - throw $ERR_TLS_SNI_FROM_SERVER("Cannot issue SNI from a TLS server-side socket"); + throw $ERR_TLS_SNI_FROM_SERVER(); } // if the socket is detached we can't set the servername but we set this property so when open will auto set to it this.servername = name; diff --git a/src/js/node/url.ts b/src/js/node/url.ts index 5bf493904e..acdf595833 100644 --- a/src/js/node/url.ts +++ b/src/js/node/url.ts @@ -30,11 +30,6 @@ const [domainToASCII, domainToUnicode] = $cpp("NodeURL.cpp", "Bun::createNodeURL const { urlToHttpOptions } = require("internal/url"); const { validateString } = require("internal/validators"); -var _lazyUtil; -function lazyUtil(): (typeof import("internal/util"))["default"] { - return (_lazyUtil ||= require("internal/util")); -} - function Url() { this.protocol = null; this.slashes = null; @@ -106,7 +101,7 @@ var protocolPattern = /^([a-z0-9.+-]+:)/i, }; function urlParse( - url: string | URL | Url, // really has unknown type but intellisense is nice + url: string | URL | typeof Url, // really has unknown type but intellisense is nice parseQueryString?: boolean, slashesDenoteHost?: boolean, ) { @@ -233,8 +228,9 @@ Url.prototype.parse = function parse(url: string, parseQueryString?: boolean, sl * resolution will treat //foo/bar as host=foo,path=bar because that's * how the browser resolves relative URLs. */ + let slashes; if (slashesDenoteHost || proto || rest.match(/^\/\/[^@/]+@[^@/]+/)) { - var slashes = rest.substring(0, 2) === "//"; + slashes = rest.substring(0, 2) === "//"; if (slashes && !(proto && hostlessProtocol[proto])) { rest = rest.substring(2); this.slashes = true;