From accccbfdaf4e4c69ae5fde404675a3debbb9b6d7 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Fri, 28 Mar 2025 01:15:00 -0700 Subject: [PATCH] 2x faster headers.get, headers.delete, headers.has (#18571) --- src/bun.js/bindings/NodeHTTP.cpp | 2 + src/bun.js/bindings/webcore/FetchHeaders.cpp | 41 +++++++++++-------- src/bun.js/bindings/webcore/HTTPHeaderMap.cpp | 10 +++++ src/bun.js/bindings/webcore/HTTPHeaderMap.h | 1 + 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/bun.js/bindings/NodeHTTP.cpp b/src/bun.js/bindings/NodeHTTP.cpp index 614c6e3a3c..358334bfbf 100644 --- a/src/bun.js/bindings/NodeHTTP.cpp +++ b/src/bun.js/bindings/NodeHTTP.cpp @@ -1379,6 +1379,8 @@ JSC_DEFINE_HOST_FUNCTION(jsHTTPSetHeader, (JSGlobalObject * globalObject, CallFr if (nameValue.isString()) { String name = nameValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + FetchHeaders* impl = &headers->wrapped(); if (valueValue.isUndefined()) diff --git a/src/bun.js/bindings/webcore/FetchHeaders.cpp b/src/bun.js/bindings/webcore/FetchHeaders.cpp index a6b64d5cd1..970c0a18ea 100644 --- a/src/bun.js/bindings/webcore/FetchHeaders.cpp +++ b/src/bun.js/bindings/webcore/FetchHeaders.cpp @@ -207,22 +207,20 @@ ExceptionOr FetchHeaders::append(const String& name, const String& value) // https://fetch.spec.whatwg.org/#dom-headers-delete ExceptionOr FetchHeaders::remove(const StringView name) { + ASSERT_WITH_MESSAGE(m_guard == FetchHeaders::Guard::None, "We don't use guards in Bun"); + + HTTPHeaderName headerName; + if (findHTTPHeaderName(name, headerName)) { + ++m_updateCounter; + m_headers.remove(headerName); + return {}; + } + if (!isValidHTTPToken(name)) return Exception { TypeError, makeString("Invalid header name: '"_s, name, "'"_s) }; - if (m_guard == FetchHeaders::Guard::Immutable) - return Exception { TypeError, "Headers object's guard is 'immutable'"_s }; - if (m_guard == FetchHeaders::Guard::Request && isForbiddenHeaderName(name)) - return {}; - if (m_guard == FetchHeaders::Guard::RequestNoCors && !isNoCORSSafelistedRequestHeaderName(name) && !isPriviledgedNoCORSRequestHeaderName(name)) - return {}; - if (m_guard == FetchHeaders::Guard::Response && isForbiddenResponseHeaderName(name)) - return {}; ++m_updateCounter; - m_headers.remove(name); - - if (m_guard == FetchHeaders::Guard::RequestNoCors) - removePrivilegedNoCORSRequestHeaders(m_headers); + m_headers.removeUncommonHeader(name); return {}; } @@ -234,16 +232,23 @@ size_t FetchHeaders::memoryCost() const ExceptionOr FetchHeaders::get(const StringView name) const { - if (!isValidHTTPToken(name)) - return Exception { TypeError, makeString("Invalid header name: '"_s, name, "'"_s) }; - return m_headers.get(name); + auto result = m_headers.get(name); + if (result.isEmpty()) { + if (!isValidHTTPToken(name)) + return Exception { TypeError, makeString("Invalid header name: '"_s, name, "'"_s) }; + } + + return result; } ExceptionOr FetchHeaders::has(const StringView name) const { - if (!isValidHTTPToken(name)) - return Exception { TypeError, makeString("Invalid header name: '"_s, name, '"') }; - return m_headers.contains(name); + bool has = m_headers.contains(name); + if (!has) { + if (!isValidHTTPToken(name)) + return Exception { TypeError, makeString("Invalid header name: '"_s, name, '"') }; + } + return has; } ExceptionOr FetchHeaders::set(const HTTPHeaderName name, const String& value) diff --git a/src/bun.js/bindings/webcore/HTTPHeaderMap.cpp b/src/bun.js/bindings/webcore/HTTPHeaderMap.cpp index 65330b5af5..9b95c823de 100644 --- a/src/bun.js/bindings/webcore/HTTPHeaderMap.cpp +++ b/src/bun.js/bindings/webcore/HTTPHeaderMap.cpp @@ -219,6 +219,16 @@ bool HTTPHeaderMap::remove(const StringView name) if (findHTTPHeaderName(name, headerName)) return remove(headerName); + return removeUncommonHeader(name); +} + +bool HTTPHeaderMap::removeUncommonHeader(const StringView name) +{ +#if ASSERT_ENABLED + HTTPHeaderName headerName; + ASSERT(!findHTTPHeaderName(name, headerName)); +#endif + return m_uncommonHeaders.removeFirstMatching([&](auto& header) { return equalIgnoringASCIICase(header.key, name); }); diff --git a/src/bun.js/bindings/webcore/HTTPHeaderMap.h b/src/bun.js/bindings/webcore/HTTPHeaderMap.h index bbc28eedf0..126170bf2e 100644 --- a/src/bun.js/bindings/webcore/HTTPHeaderMap.h +++ b/src/bun.js/bindings/webcore/HTTPHeaderMap.h @@ -189,6 +189,7 @@ public: WEBCORE_EXPORT bool contains(const StringView) const; WEBCORE_EXPORT int64_t indexOf(StringView name) const; WEBCORE_EXPORT bool remove(const StringView); + WEBCORE_EXPORT bool removeUncommonHeader(const StringView); WEBCORE_EXPORT String getIndex(HeaderIndex index) const; WEBCORE_EXPORT bool setIndex(HeaderIndex index, const String &value);