diff options
| author | 2022-08-22 07:49:58 -0700 | |
|---|---|---|
| committer | 2022-08-22 07:49:58 -0700 | |
| commit | 5273415ce578d27b9e65161ca1bee4016de7f641 (patch) | |
| tree | 9deaa66136acca83f176654c764dcb865356e7bf | |
| parent | 47a91e745781bd97b1747e2b11234244cd46b29d (diff) | |
| download | bun-5273415ce578d27b9e65161ca1bee4016de7f641.tar.gz bun-5273415ce578d27b9e65161ca1bee4016de7f641.tar.zst bun-5273415ce578d27b9e65161ca1bee4016de7f641.zip | |
Add some optimizations to FetchHeaders
Diffstat (limited to '')
| -rw-r--r-- | src/bun.js/bindings/webcore/FetchHeaders.cpp | 14 | ||||
| -rw-r--r-- | src/bun.js/bindings/webcore/HTTPHeaderNames.h | 102 | ||||
| -rw-r--r-- | src/bun.js/bindings/webcore/JSFetchHeaders.cpp | 88 |
3 files changed, 188 insertions, 16 deletions
diff --git a/src/bun.js/bindings/webcore/FetchHeaders.cpp b/src/bun.js/bindings/webcore/FetchHeaders.cpp index d4ecba216..e852a74d1 100644 --- a/src/bun.js/bindings/webcore/FetchHeaders.cpp +++ b/src/bun.js/bindings/webcore/FetchHeaders.cpp @@ -76,20 +76,6 @@ static ExceptionOr<void> appendToHeaderMap(const String& name, const String& val return {}; } -static void appendToHeaderMapFast(const String& name, const String& value, HTTPHeaderMap& headers, FetchHeaders::Guard guard) -{ - String combinedValue; - if (headers.contains(name)) { - combinedValue = makeString(headers.get(name), ", ", value); - } else { - combinedValue = value.isolatedCopy(); - } - - headers.append(name.isolatedCopy(), WTFMove(combinedValue)); - // if (guard == FetchHeaders::Guard::RequestNoCors) - // removePrivilegedNoCORSRequestHeaders(headers); -} - static ExceptionOr<void> appendToHeaderMap(const HTTPHeaderMap::HTTPHeaderMapConstIterator::KeyValue& header, HTTPHeaderMap& headers, FetchHeaders::Guard guard) { String normalizedValue = stripLeadingAndTrailingHTTPSpaces(header.value); diff --git a/src/bun.js/bindings/webcore/HTTPHeaderNames.h b/src/bun.js/bindings/webcore/HTTPHeaderNames.h index 92dff5c19..246afeefa 100644 --- a/src/bun.js/bindings/webcore/HTTPHeaderNames.h +++ b/src/bun.js/bindings/webcore/HTTPHeaderNames.h @@ -238,6 +238,108 @@ template<> struct EnumTraits<WebCore::HTTPHeaderName> { WebCore::HTTPHeaderName::XXSSProtection>; }; +static StaticStringImpl* staticHeaderNames[] = { + MAKE_STATIC_STRING_IMPL("accept"), + MAKE_STATIC_STRING_IMPL("accept-charset"), + MAKE_STATIC_STRING_IMPL("accept-encoding"), + MAKE_STATIC_STRING_IMPL("accept-language"), + MAKE_STATIC_STRING_IMPL("accept-ranges"), + MAKE_STATIC_STRING_IMPL("access-control-allow-credentials"), + MAKE_STATIC_STRING_IMPL("access-control-allow-headers"), + MAKE_STATIC_STRING_IMPL("access-control-allow-methods"), + MAKE_STATIC_STRING_IMPL("access-control-allow-origin"), + MAKE_STATIC_STRING_IMPL("access-control-expose-headers"), + MAKE_STATIC_STRING_IMPL("access-control-max-age"), + MAKE_STATIC_STRING_IMPL("access-control-request-headers"), + MAKE_STATIC_STRING_IMPL("access-control-request-method"), + MAKE_STATIC_STRING_IMPL("age"), + MAKE_STATIC_STRING_IMPL("authorization"), + MAKE_STATIC_STRING_IMPL("cache-control"), + MAKE_STATIC_STRING_IMPL("connection"), + MAKE_STATIC_STRING_IMPL("content-disposition"), + MAKE_STATIC_STRING_IMPL("content-encoding"), + MAKE_STATIC_STRING_IMPL("content-language"), + MAKE_STATIC_STRING_IMPL("content-length"), + MAKE_STATIC_STRING_IMPL("content-location"), + MAKE_STATIC_STRING_IMPL("content-range"), + MAKE_STATIC_STRING_IMPL("content-security-policy"), + MAKE_STATIC_STRING_IMPL("content-security-policy-report-only"), + MAKE_STATIC_STRING_IMPL("content-type"), + MAKE_STATIC_STRING_IMPL("cookie"), + MAKE_STATIC_STRING_IMPL("cookie2"), + MAKE_STATIC_STRING_IMPL("cross-origin-embedder-policy"), + MAKE_STATIC_STRING_IMPL("cross-origin-embedder-policy-report-only"), + MAKE_STATIC_STRING_IMPL("cross-origin-opener-policy"), + MAKE_STATIC_STRING_IMPL("cross-origin-opener-policy-report-only"), + MAKE_STATIC_STRING_IMPL("cross-origin-resource-policy"), + MAKE_STATIC_STRING_IMPL("dnt"), + MAKE_STATIC_STRING_IMPL("date"), + MAKE_STATIC_STRING_IMPL("default-style"), + MAKE_STATIC_STRING_IMPL("etag"), + MAKE_STATIC_STRING_IMPL("expect"), + MAKE_STATIC_STRING_IMPL("expires"), + MAKE_STATIC_STRING_IMPL("host"), + MAKE_STATIC_STRING_IMPL("icy-metaint"), + MAKE_STATIC_STRING_IMPL("icy-metadata"), + MAKE_STATIC_STRING_IMPL("if-match"), + MAKE_STATIC_STRING_IMPL("if-modified-since"), + MAKE_STATIC_STRING_IMPL("if-none-match"), + MAKE_STATIC_STRING_IMPL("if-range"), + MAKE_STATIC_STRING_IMPL("if-unmodified-since"), + MAKE_STATIC_STRING_IMPL("keep-alive"), + MAKE_STATIC_STRING_IMPL("last-event-id"), + MAKE_STATIC_STRING_IMPL("last-modified"), + MAKE_STATIC_STRING_IMPL("link"), + MAKE_STATIC_STRING_IMPL("location"), + MAKE_STATIC_STRING_IMPL("origin"), + MAKE_STATIC_STRING_IMPL("ping-from"), + MAKE_STATIC_STRING_IMPL("ping-to"), + MAKE_STATIC_STRING_IMPL("pragma"), + MAKE_STATIC_STRING_IMPL("proxy-authorization"), + MAKE_STATIC_STRING_IMPL("purpose"), + MAKE_STATIC_STRING_IMPL("range"), + MAKE_STATIC_STRING_IMPL("referer"), + MAKE_STATIC_STRING_IMPL("referrer-policy"), + MAKE_STATIC_STRING_IMPL("refresh"), + MAKE_STATIC_STRING_IMPL("report-to"), + MAKE_STATIC_STRING_IMPL("sec-fetch-dest"), + MAKE_STATIC_STRING_IMPL("sec-fetch-mode"), + MAKE_STATIC_STRING_IMPL("sec-websocket-accept"), + MAKE_STATIC_STRING_IMPL("sec-websocket-extensions"), + MAKE_STATIC_STRING_IMPL("sec-websocket-key"), + MAKE_STATIC_STRING_IMPL("sec-websocket-protocol"), + MAKE_STATIC_STRING_IMPL("sec-websocket-version"), + MAKE_STATIC_STRING_IMPL("server-timing"), + MAKE_STATIC_STRING_IMPL("service-worker"), + MAKE_STATIC_STRING_IMPL("service-worker-allowed"), + MAKE_STATIC_STRING_IMPL("service-worker-navigation-preload"), + MAKE_STATIC_STRING_IMPL("set-cookie"), + MAKE_STATIC_STRING_IMPL("set-cookie2"), + MAKE_STATIC_STRING_IMPL("sourcemap"), + MAKE_STATIC_STRING_IMPL("strict-transport-security"), + MAKE_STATIC_STRING_IMPL("te"), + MAKE_STATIC_STRING_IMPL("timing-allow-origin"), + MAKE_STATIC_STRING_IMPL("trailer"), + MAKE_STATIC_STRING_IMPL("transfer-encoding"), + MAKE_STATIC_STRING_IMPL("upgrade"), + MAKE_STATIC_STRING_IMPL("upgrade-insecure-requests"), + MAKE_STATIC_STRING_IMPL("user-agent"), + MAKE_STATIC_STRING_IMPL("vary"), + MAKE_STATIC_STRING_IMPL("via"), + MAKE_STATIC_STRING_IMPL("x-content-type-options"), + MAKE_STATIC_STRING_IMPL("x-dns-prefetch-control"), + MAKE_STATIC_STRING_IMPL("x-frame-options"), + MAKE_STATIC_STRING_IMPL("x-sourcemap"), + MAKE_STATIC_STRING_IMPL("x-temp-tablet"), + MAKE_STATIC_STRING_IMPL("x-xss-protection"), +}; + +static WTF::StaticStringImpl* httpHeaderNameStringImpl(WebCore::HTTPHeaderName headerName) { + return staticHeaderNames[static_cast<size_t>(headerName)]; +} + + } // namespace WTF + #endif // HTTPHeaderNames_h diff --git a/src/bun.js/bindings/webcore/JSFetchHeaders.cpp b/src/bun.js/bindings/webcore/JSFetchHeaders.cpp index 8ea72b567..ef9474a1b 100644 --- a/src/bun.js/bindings/webcore/JSFetchHeaders.cpp +++ b/src/bun.js/bindings/webcore/JSFetchHeaders.cpp @@ -71,6 +71,10 @@ static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_keys); static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_values); static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_forEach); +// Non-standard functions +static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_toJSON); +static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_size); + // Attributes static JSC_DECLARE_CUSTOM_GETTER(jsFetchHeadersConstructor); @@ -116,7 +120,21 @@ template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSFetchHeadersDOMConstructor: auto* castedThis = jsCast<JSFetchHeadersDOMConstructor*>(callFrame->jsCallee()); ASSERT(castedThis); EnsureStillAliveScope argument0 = callFrame->argument(0); - auto init = argument0.value().isUndefined() ? std::optional<Converter<IDLUnion<IDLSequence<IDLSequence<IDLByteString>>, IDLRecord<IDLByteString, IDLByteString>>>::ReturnType>() : std::optional<Converter<IDLUnion<IDLSequence<IDLSequence<IDLByteString>>, IDLRecord<IDLByteString, IDLByteString>>>::ReturnType>(convert<IDLUnion<IDLSequence<IDLSequence<IDLByteString>>, IDLRecord<IDLByteString, IDLByteString>>>(*lexicalGlobalObject, argument0.value())); + + auto init = std::optional<Converter<IDLUnion<IDLSequence<IDLSequence<IDLByteString>>, IDLRecord<IDLByteString, IDLByteString>>>::ReturnType>(); + + if (argument0.value() && !argument0.value().isUndefined()) { + if (auto* existingJsFetchHeaders = jsDynamicCast<JSFetchHeaders*>(argument0.value())) { + auto newHeaders = FetchHeaders::create(existingJsFetchHeaders->wrapped()); + auto jsValue = toJSNewlyCreated<IDLInterface<FetchHeaders>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(newHeaders)); + if constexpr (IsExceptionOr<decltype(jsValue)>) + RETURN_IF_EXCEPTION(throwScope, {}); + setSubclassStructureIfNeeded<FetchHeaders>(lexicalGlobalObject, callFrame, asObject(jsValue)); + RETURN_IF_EXCEPTION(throwScope, {}); + } + init = std::optional<Converter<IDLUnion<IDLSequence<IDLSequence<IDLByteString>>, IDLRecord<IDLByteString, IDLByteString>>>::ReturnType>(convert<IDLUnion<IDLSequence<IDLSequence<IDLByteString>>, IDLRecord<IDLByteString, IDLByteString>>>(*lexicalGlobalObject, argument0.value())); + } + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); auto object = FetchHeaders::create(WTFMove(init)); if constexpr (IsExceptionOr<decltype(object)>) @@ -161,6 +179,8 @@ static const HashTableValue JSFetchHeadersPrototypeTableValues[] = { { "keys"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsFetchHeadersPrototypeFunction_keys), (intptr_t)(0) } }, { "values"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsFetchHeadersPrototypeFunction_values), (intptr_t)(0) } }, { "forEach"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsFetchHeadersPrototypeFunction_forEach), (intptr_t)(1) } }, + { "toJSON"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsFetchHeadersPrototypeFunction_toJSON), (intptr_t)(0) } }, + { "size"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsFetchHeadersPrototypeFunction_size), (intptr_t)(0) } }, }; const ClassInfo JSFetchHeadersPrototype::s_info = { "Headers"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSFetchHeadersPrototype) }; @@ -237,6 +257,71 @@ static inline JSC::EncodedJSValue jsFetchHeadersPrototypeFunction_appendBody(JSC RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.append(WTFMove(name), WTFMove(value)); }))); } +/** + * Non standard function. + **/ +static inline JSC::EncodedJSValue jsFetchHeadersPrototypeFunction_toJSONBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSFetchHeaders>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto& impl = castedThis->wrapped(); + size_t size = impl.size(); + JSObject* obj; + if (size == 0) { + obj = constructEmptyObject(lexicalGlobalObject); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(obj)); + } else if (size < 64) { + obj = constructEmptyObject(lexicalGlobalObject, lexicalGlobalObject->objectPrototype(), size); + } else { + obj = constructEmptyObject(lexicalGlobalObject); + } + + auto& internal = impl.internalHeaders(); + { + auto& vec = internal.commonHeaders(); + for (auto it = vec.begin(); it != vec.end(); ++it) { + auto& name = it->key; + auto& value = it->value; + obj->putDirect(vm, Identifier::fromString(vm, String(WTF::httpHeaderNameStringImpl(name))), jsString(vm, value), 0); + } + } + + { + auto& vec = internal.uncommonHeaders(); + for (auto it = vec.begin(); it != vec.end(); ++it) { + auto& name = it->key; + auto& value = it->value; + obj->putDirect(vm, Identifier::fromString(vm, name), jsString(vm, value), 0); + } + } + + RELEASE_AND_RETURN(throwScope, JSValue::encode(obj)); +} + +JSC_DEFINE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_toJSON, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSFetchHeaders>::call<jsFetchHeadersPrototypeFunction_toJSONBody>(*lexicalGlobalObject, *callFrame, "toJSON"); +} + +/** + * Non standard function. + **/ +static inline JSC::EncodedJSValue jsFetchHeadersPrototypeFunction_sizeBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSFetchHeaders>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + + auto& impl = castedThis->wrapped(); + auto size = impl.size(); + return JSValue::encode(jsNumber(size)); +} + +JSC_DEFINE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_size, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSFetchHeaders>::call<jsFetchHeadersPrototypeFunction_sizeBody>(*lexicalGlobalObject, *callFrame, "size"); +} + JSC_DEFINE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_append, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation<JSFetchHeaders>::call<jsFetchHeadersPrototypeFunction_appendBody>(*lexicalGlobalObject, *callFrame, "append"); @@ -498,5 +583,4 @@ FetchHeaders* JSFetchHeaders::toWrapped(JSC::VM& vm, JSC::JSValue value) return &wrapper->wrapped(); return nullptr; } - } |
