diff --git a/Makefile b/Makefile
index eb1c55d9fe..487d7e4bb1 100644
--- a/Makefile
+++ b/Makefile
@@ -200,9 +200,11 @@ MAC_INCLUDE_DIRS := -I$(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders \
LINUX_INCLUDE_DIRS := -I$(JSC_INCLUDE_DIR) \
-Isrc/javascript/jsc/bindings/
-INCLUDE_DIRS := -I$(BUN_DEPS_DIR)/uws
+UWS_INCLUDE_DIR := -I$(BUN_DEPS_DIR)/uws/uSockets/src -I$(BUN_DEPS_DIR)/uws/src -I$(BUN_DEPS_DIR)
+INCLUDE_DIRS := $(UWS_INCLUDE_DIR)
+
ifeq ($(OS_NAME),linux)
INCLUDE_DIRS += $(LINUX_INCLUDE_DIRS)
@@ -456,7 +458,7 @@ build-obj-wasm-small:
build-obj-safe:
$(ZIG) build obj -Drelease-safe
-UWS_CC_FLAGS = -pthread -DUWS_HTTPRESPONSE_NO_WRITEMARK=1 -DLIBUS_USE_OPENSSL=1 -DLIBUS_USE_BORINGSSL=1 -DWITH_BORINGSSL=1 -Wpedantic -Wall -Wextra -Wsign-conversion -Wconversion -Isrc -IuSockets/src -DUWS_WITH_PROXY
+UWS_CC_FLAGS = -pthread -DLIBUS_USE_OPENSSL=1 -DUWS_HTTPRESPONSE_NO_WRITEMARK=1 -DLIBUS_USE_BORINGSSL=1 -DWITH_BORINGSSL=1 -Wpedantic -Wall -Wextra -Wsign-conversion -Wconversion $(UWS_INCLUDE) -DUWS_WITH_PROXY
UWS_CXX_FLAGS = $(UWS_CC_FLAGS) -std=gnu++17
UWS_LDFLAGS = -I$(BUN_DEPS_DIR)/boringssl/include
@@ -1032,7 +1034,7 @@ wasm-return1:
# We do this outside of build.zig for performance reasons
# The C compilation stuff with build.zig is really slow and we don't need to run this as often as the rest
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
- $(CXX) $(CLANG_FLAGS) \
+ $(CXX) $(CLANG_FLAGS) $(UWS_INCLUDE) \
$(MACOS_MIN_FLAG) \
$(OPTIMIZATION_LEVEL) \
-fno-exceptions \
diff --git a/integration/bunjs-only-snippets/globals.test.js b/integration/bunjs-only-snippets/globals.test.js
index 831bbd93fb..b498e0e8ec 100644
--- a/integration/bunjs-only-snippets/globals.test.js
+++ b/integration/bunjs-only-snippets/globals.test.js
@@ -16,7 +16,8 @@ it("extendable", () => {
var Foo = class extends Class {};
var bar = new Foo();
expect(bar instanceof Class).toBe(true);
- expect(Class.prototype instanceof Class).toBe(true);
+ expect(!!Class.prototype).toBe(true);
+ expect(typeof Class.prototype).toBe("object");
}
expect(true).toBe(true);
});
diff --git a/integration/bunjs-only-snippets/html-rewriter.test.js b/integration/bunjs-only-snippets/html-rewriter.test.js
index a4ca965aad..68e2849d90 100644
--- a/integration/bunjs-only-snippets/html-rewriter.test.js
+++ b/integration/bunjs-only-snippets/html-rewriter.test.js
@@ -26,10 +26,6 @@ describe("HTMLRewriter", () => {
expect(await res.text()).toBe("
replace
");
});
- it("exists globally", async () => {
- expect(typeof HTMLRewriter).toBe("function");
- expect(typeof HTMLRewriter.constructor).toBe("function");
- });
it("supports element handlers", async () => {
var rewriter = new HTMLRewriter();
rewriter.on("div", {
diff --git a/integration/bunjs-only-snippets/mmap.test.js b/integration/bunjs-only-snippets/mmap.test.js
index 03ce75e871..3dd3aadb93 100644
--- a/integration/bunjs-only-snippets/mmap.test.js
+++ b/integration/bunjs-only-snippets/mmap.test.js
@@ -10,13 +10,13 @@ it("mmap finalizer", async () => {
map = null;
Bun.gc(true);
- await new Promise(resolve => setTimeout(resolve, 1));
+ await new Promise((resolve) => setTimeout(resolve, 1));
});
-it('mmap passed to other syscalls', async () => {
+it("mmap passed to other syscalls", async () => {
const map = Bun.mmap(path);
- await Bun.write(path + '1', map);
- const text = await (await Bun.file(path + '1')).text();
+ await Bun.write(path + "1", map);
+ const text = await (await Bun.file(path + "1")).text();
expect(text).toBe(new TextDecoder().decode(map));
});
@@ -46,4 +46,4 @@ it("mmap private", () => {
map2[0] = 0;
expect(map2[0]).toBe(0);
expect(map[0]).toBe(old);
-});
\ No newline at end of file
+});
diff --git a/integration/bunjs-only-snippets/response.file.test.js b/integration/bunjs-only-snippets/response.file.test.js
index d094c0a624..6a879c7589 100644
--- a/integration/bunjs-only-snippets/response.file.test.js
+++ b/integration/bunjs-only-snippets/response.file.test.js
@@ -2,12 +2,28 @@ import fs from "fs";
import { it, expect } from "bun:test";
import path from "path";
+function gc() {
+ Bun.gc(true);
+}
+
+// we must ensure that finalizers are run
+// so that the reference-counting logic is exercised
+function gcTick() {
+ gc();
+ return new Promise((resolve) => {
+ setTimeout(resolve, 0);
+ });
+}
+
it("Bun.file not found returns ENOENT", async () => {
try {
+ await gcTick();
await Bun.file("/does/not/exist.txt").text();
+ await gcTick();
} catch (exception) {
expect(exception.code).toBe("ENOENT");
}
+ await gcTick();
});
it("Bun.write('out.txt', 'string')", async () => {
@@ -17,11 +33,15 @@ it("Bun.write('out.txt', 'string')", async () => {
fs.unlinkSync(path.join("/tmp", "out.txt"));
} catch (e) {}
}
-
+ await gcTick();
await Bun.write("/tmp/out.txt", "string");
+ await gcTick();
const out = Bun.file("/tmp/out.txt");
+ await gcTick();
expect(await out.text()).toBe("string");
+ await gcTick();
expect(await out.text()).toBe(fs.readFileSync("/tmp/out.txt", "utf8"));
+ await gcTick();
}
});
@@ -30,38 +50,47 @@ it("Bun.write blob", async () => {
Bun.file("/tmp/response-file.test.txt"),
Bun.file(path.join(import.meta.dir, "fetch.js.txt"))
);
+ await gcTick();
await Bun.write(Bun.file("/tmp/response-file.test.txt"), "blah blah blha");
+ await gcTick();
await Bun.write(
Bun.file("/tmp/response-file.test.txt"),
new Uint32Array(1024)
);
+ await gcTick();
await Bun.write("/tmp/response-file.test.txt", new Uint32Array(1024));
+ await gcTick();
expect(
await Bun.write(
new TextEncoder().encode("/tmp/response-file.test.txt"),
new Uint32Array(1024)
)
).toBe(new Uint32Array(1024).byteLength);
+ await gcTick();
});
it("Bun.file -> Bun.file", async () => {
try {
fs.unlinkSync(path.join("/tmp", "fetch.js.in"));
} catch (e) {}
-
+ await gcTick();
try {
fs.unlinkSync(path.join("/tmp", "fetch.js.out"));
} catch (e) {}
-
+ await gcTick();
const file = path.join(import.meta.dir, "fetch.js.txt");
+ await gcTick();
const text = fs.readFileSync(file, "utf8");
fs.writeFileSync("/tmp/fetch.js.in", text, { mode: 0644 });
+ await gcTick();
{
const result = await Bun.write(
Bun.file("/tmp/fetch.js.out"),
Bun.file("/tmp/fetch.js.in")
);
+ await gcTick();
expect(await Bun.file("/tmp/fetch.js.out").text()).toBe(text);
+ await gcTick();
}
{
@@ -75,14 +104,18 @@ it("Bun.file -> Bun.file", async () => {
}
{
+ await gcTick();
await Bun.write("/tmp/fetch.js.in", Bun.file("/tmp/fetch.js.out"));
+ await gcTick();
expect(await Bun.file("/tmp/fetch.js.in").text()).toBe(text);
}
});
it("Bun.file", async () => {
const file = path.join(import.meta.dir, "fetch.js.txt");
+ await gcTick();
expect(await Bun.file(file).text()).toBe(fs.readFileSync(file, "utf8"));
+ await gcTick();
});
it("Bun.file as a Blob", async () => {
@@ -92,27 +125,34 @@ it("Bun.file as a Blob", async () => {
// internally, instead of a byte array, it stores the file path!
// this enables several performance optimizations
var blob = Bun.file(filePath);
+ await gcTick();
// no size because we haven't read it from disk yet
expect(blob.size).toBe(0);
+ await gcTick();
// now it reads "./fetch.js.txt" from the filesystem
// it's lazy, only loads once we ask for it
// if it fails, the promise will reject at this point
expect(await blob.text()).toBe(fixture);
+ await gcTick();
// now that it's loaded, the size updates
expect(blob.size).toBe(fixture.length);
+ await gcTick();
// and it only loads once for _all_ blobs pointing to that file path
// until all references are released
expect((await blob.arrayBuffer()).byteLength).toBe(fixture.length);
+ await gcTick();
const array = new Uint8Array(await blob.arrayBuffer());
+ await gcTick();
const text = fixture;
for (let i = 0; i < text.length; i++) {
expect(array[i]).toBe(text.charCodeAt(i));
}
+ await gcTick();
expect(blob.size).toBe(fixture.length);
blob = null;
- Bun.gc(true);
+ await gcTick();
await new Promise((resolve) => setTimeout(resolve, 1));
// now we're back
var blob = Bun.file(filePath);
@@ -121,9 +161,13 @@ it("Bun.file as a Blob", async () => {
it("Response -> Bun.file", async () => {
const file = path.join(import.meta.dir, "fetch.js.txt");
+ await gcTick();
const text = fs.readFileSync(file, "utf8");
+ await gcTick();
const response = new Response(Bun.file(file));
+ await gcTick();
expect(await response.text()).toBe(text);
+ await gcTick();
});
it("Bun.file -> Response", async () => {
@@ -131,18 +175,29 @@ it("Bun.file -> Response", async () => {
try {
fs.unlinkSync("/tmp/fetch.js.out");
} catch {}
-
+ await gcTick();
const file = path.join(import.meta.dir, "fetch.js.txt");
+ await gcTick();
const text = fs.readFileSync(file, "utf8");
+ await gcTick();
const resp = await fetch("https://example.com");
+ await gcTick();
expect(await Bun.write("/tmp/fetch.js.out", resp)).toBe(text.length);
+ await gcTick();
expect(await Bun.file("/tmp/fetch.js.out").text()).toBe(text);
+ await gcTick();
});
it("Response -> Bun.file -> Response -> text", async () => {
+ await gcTick();
const file = path.join(import.meta.dir, "fetch.js.txt");
+ await gcTick();
const text = fs.readFileSync(file, "utf8");
+ await gcTick();
const response = new Response(Bun.file(file));
+ await gcTick();
const response2 = response.clone();
+ await gcTick();
expect(await response2.text()).toBe(text);
+ await gcTick();
});
diff --git a/src/deps/_libusockets.h b/src/deps/_libusockets.h
index f0825e2948..d63fc38ca9 100644
--- a/src/deps/_libusockets.h
+++ b/src/deps/_libusockets.h
@@ -1,3 +1,4 @@
+#pragma once
#ifndef LIBUWS_CAPI_HEADER
#define LIBUWS_CAPI_HEADER
@@ -7,6 +8,15 @@
#include
#include
#include
+
+#ifndef STRING_POINTER
+#define STRING_POINTER
+typedef struct StringPointer {
+ uint32_t off;
+ uint32_t len;
+} StringPointer;
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -282,11 +292,6 @@ void uws_loop_addPreHandler(us_loop_t *loop, void *key,
void uws_loop_removePreHandler(us_loop_t *loop, void *ctx_);
void uws_loop_defer(us_loop_t *loop, void *ctx, void (*cb)(void *ctx));
-typedef struct StringPointer {
- uint32_t off;
- uint32_t len;
-} StringPointer;
-
void uws_res_write_headers(int ssl, uws_res_t *res, const StringPointer *names,
const StringPointer *values, size_t count,
const char *buf);
diff --git a/src/javascript/jsc/api/html_rewriter.zig b/src/javascript/jsc/api/html_rewriter.zig
index e3a3c6d759..ac6190f7ef 100644
--- a/src/javascript/jsc/api/html_rewriter.zig
+++ b/src/javascript/jsc/api/html_rewriter.zig
@@ -217,7 +217,7 @@ pub const HTMLRewriter = struct {
pub fn returnEmptyResponse(this: *HTMLRewriter, global: *JSGlobalObject, response: *Response) JSValue {
var result = bun.default_allocator.create(Response) catch unreachable;
- response.cloneInto(result, getAllocator(global.ref()));
+ response.cloneInto(result, getAllocator(global.ref()), global);
this.finalizeWithoutDestroy();
return JSValue.fromRef(Response.makeMaybePooled(global.ref(), result));
}
@@ -280,7 +280,6 @@ pub const HTMLRewriter = struct {
.body = .{
.init = .{
.status_code = 200,
- .headers = null,
},
.value = .{
.Locked = .{
diff --git a/src/javascript/jsc/api/server.zig b/src/javascript/jsc/api/server.zig
index 38fad7c0c6..aeb13b6bc3 100644
--- a/src/javascript/jsc/api/server.zig
+++ b/src/javascript/jsc/api/server.zig
@@ -377,7 +377,7 @@ pub fn NewServer(comptime ssl_enabled: bool, comptime debug_mode: bool) type {
response_ptr: ?*JSC.WebCore.Response = null,
blob: JSC.WebCore.Blob = JSC.WebCore.Blob{},
promise: ?*JSC.JSValue = null,
- response_headers: ?*JSC.WebCore.Headers.RefCountedHeaders = null,
+ response_headers: ?*JSC.FetchHeaders = null,
has_abort_handler: bool = false,
has_sendfile_ctx: bool = false,
has_called_error_handler: bool = false,
@@ -559,25 +559,18 @@ pub fn NewServer(comptime ssl_enabled: bool, comptime debug_mode: bool) type {
fn writeHeaders(
this: *RequestContext,
- headers_: *Headers.RefCountedHeaders,
+ headers: *JSC.FetchHeaders,
) void {
- var headers: *JSC.WebCore.Headers = headers_.get();
- if (headers.getHeaderIndex("content-length")) |index| {
- headers.entries.orderedRemove(index);
+ headers.remove(&ZigString.init("content-length"));
+ if (!headers.has(&ZigString.init("content-type"))) {
+ if (this.blob.content_type.len > 0) {
+ this.resp.writeHeader("content-type", this.blob.content_type);
+ } else if (MimeType.sniff(this.blob.sharedView())) |content| {
+ this.resp.writeHeader("content-type", content.value);
+ }
}
- if (this.blob.content_type.len > 0 and headers.getHeaderIndex("content-type") == null) {
- this.resp.writeHeader("content-type", this.blob.content_type);
- } else if (MimeType.sniff(this.blob.sharedView())) |content| {
- this.resp.writeHeader("content-type", content.value);
- }
-
- defer headers_.deref();
- var entries = headers.entries.slice();
- const names = entries.items(.name);
- const values = entries.items(.value);
-
- this.resp.writeHeaders(names, values, headers.buf.items);
+ headers.toUWSResponse(ssl_enabled, this.resp);
}
pub fn writeStatus(this: *RequestContext, status: u16) void {
@@ -834,8 +827,9 @@ pub fn NewServer(comptime ssl_enabled: bool, comptime debug_mode: bool) type {
this.writeStatus(status);
- if (response.body.init.headers) |headers_| {
+ if (response.body.init.headers.as(JSC.FetchHeaders)) |headers_| {
this.writeHeaders(headers_);
+ headers_.deref();
} else if (this.blob.content_type.len > 0) {
this.resp.writeHeader("content-type", this.blob.content_type);
} else if (MimeType.sniff(this.blob.sharedView())) |content| {
diff --git a/src/javascript/jsc/base.zig b/src/javascript/jsc/base.zig
index 20752e8e65..aa9e9abd26 100644
--- a/src/javascript/jsc/base.zig
+++ b/src/javascript/jsc/base.zig
@@ -21,7 +21,6 @@ const Response = WebCore.Response;
const Request = WebCore.Request;
const Router = @import("./api/router.zig");
const FetchEvent = WebCore.FetchEvent;
-const Headers = WebCore.Headers.RefCountedHeaders;
const IdentityContext = @import("../../identity_context.zig").IdentityContext;
const Body = WebCore.Body;
@@ -2536,7 +2535,6 @@ pub const JSPrivateDataPtr = TaggedPointerUnion(.{
ExpectPrototype,
FetchEvent,
FetchTaskletContext,
- Headers,
HTMLRewriter,
JSNode,
LazyPropertiesObject,
diff --git a/src/javascript/jsc/bindings/ZigGlobalObject.cpp b/src/javascript/jsc/bindings/ZigGlobalObject.cpp
index a99087abfd..178fe3d1d1 100644
--- a/src/javascript/jsc/bindings/ZigGlobalObject.cpp
+++ b/src/javascript/jsc/bindings/ZigGlobalObject.cpp
@@ -86,10 +86,11 @@
#include "JSCustomEvent.h"
#include "JSAbortController.h"
#include "JSEvent.h"
+#include "JSFetchHeaders.h"
#include "Process.h"
-#include "JavaScriptCore/RemoteInspectorServer.h"
+#include
using JSGlobalObject = JSC::JSGlobalObject;
using Exception = JSC::Exception;
@@ -372,6 +373,17 @@ JSC_DEFINE_CUSTOM_GETTER(JSCustomEvent_getter,
WebCore::JSCustomEvent::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject));
}
+JSC_DECLARE_CUSTOM_GETTER(JSFetchHeaders_getter);
+
+JSC_DEFINE_CUSTOM_GETTER(JSFetchHeaders_getter,
+ (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue,
+ JSC::PropertyName))
+{
+ Zig::GlobalObject* thisObject = JSC::jsCast(lexicalGlobalObject);
+ return JSC::JSValue::encode(
+ WebCore::JSFetchHeaders::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject));
+}
+
JSC_DECLARE_CUSTOM_GETTER(JSEventTarget_getter);
JSC_DEFINE_CUSTOM_GETTER(JSEventTarget_getter,
@@ -849,11 +861,14 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm
putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "CustomEvent"), JSC::CustomGetterSetter::create(vm, JSCustomEvent_getter, nullptr),
JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
+ putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "Headers"), JSC::CustomGetterSetter::create(vm, JSFetchHeaders_getter, nullptr),
+ JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
+
extraStaticGlobals.releaseBuffer();
- // this->setRemoteDebuggingEnabled(true);
+ this->setRemoteDebuggingEnabled(true);
// auto& server = Inspector::RemoteInspectorServer::singleton();
- // if (server.start("127.0.0.1", 9222)) {
+ // if (server.start("localhost", 9222)) {
// }
}
diff --git a/src/javascript/jsc/bindings/bindings.cpp b/src/javascript/jsc/bindings/bindings.cpp
index 3f5486c5fb..9bb5b33f3a 100644
--- a/src/javascript/jsc/bindings/bindings.cpp
+++ b/src/javascript/jsc/bindings/bindings.cpp
@@ -48,20 +48,234 @@
#include "wtf/text/StringView.h"
#include "wtf/text/WTFString.h"
+#include "JSFetchHeaders.h"
+#include "FetchHeaders.h"
#include "DOMURL.h"
#include "JSDOMURL.h"
-extern "C" {
+#include "_libusockets.h"
+#include
+#include
+#include
+#include "IDLTypes.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConstructor.h"
+#include "JSDOMConvertBase.h"
+#include "JSDOMConvertBoolean.h"
+#include "JSDOMConvertInterface.h"
+#include "JSDOMConvertNullable.h"
+#include "JSDOMConvertRecord.h"
+#include "JSDOMConvertSequences.h"
+#include "JSDOMConvertStrings.h"
+#include "JSDOMConvertUnion.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSDOMGlobalObjectInlines.h"
+#include "JSDOMIterator.h"
+#include "JSDOMOperation.h"
+#include "JSDOMWrapperCache.h"
-WebCore__DOMURL* WebCore__DOMURL__cast(JSC__JSValue JSValue0)
+template
+OutType* WebCoreCast(JSC__JSValue JSValue0, JSC::VM* vm)
{
- auto* jsdomURL = JSC::jsCast(JSC::JSValue::decode(JSValue0));
+ // we must use jsDynamicCast here so that we check that the type is correct
+ WebCoreType* jsdomURL = JSC::jsDynamicCast(*vm, JSC::JSValue::decode(JSValue0));
if (jsdomURL == nullptr) {
return nullptr;
}
- return &jsdomURL->wrapped();
+ return reinterpret_cast(&jsdomURL->wrapped());
}
+
+template
+static void copyToUWS(WebCore::FetchHeaders* headers, UWSResponse* res)
+{
+ auto iter = headers->createIterator();
+ uint32_t i = 0;
+ unsigned count = 0;
+ for (auto pair = iter.next(); pair; pair = iter.next()) {
+ auto name = pair->key;
+ auto value = pair->value;
+ res->writeHeader(std::string_view(reinterpret_cast(name.characters8()), name.length()), std::string_view(reinterpret_cast(value.characters8()), value.length()));
+ }
+}
+
+extern "C" {
+
+void WebCore__FetchHeaders__toUWSResponse(WebCore__FetchHeaders* arg0, bool is_ssl, void* arg2)
+{
+ if (is_ssl) {
+ copyToUWS>(arg0, reinterpret_cast*>(arg2));
+ } else {
+ copyToUWS>(arg0, reinterpret_cast*>(arg2));
+ }
+}
+
+void WebCore__FetchHeaders__append(WebCore__FetchHeaders* headers, const ZigString* arg1, const ZigString* arg2)
+{
+ headers->append(Zig::toString(*arg1), Zig::toString(*arg2));
+}
+WebCore__FetchHeaders* WebCore__FetchHeaders__cast_(JSC__JSValue JSValue0, JSC__VM* vm)
+{
+ return WebCoreCast(JSValue0, vm);
+}
+
+using namespace WebCore;
+
+WebCore__FetchHeaders* WebCore__FetchHeaders__createFromJS(JSC__JSGlobalObject* lexicalGlobalObject, JSC__JSValue argument0_)
+{
+ Zig::GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject);
+ EnsureStillAliveScope argument0 = JSC::JSValue::decode(argument0_);
+ auto throwScope = DECLARE_THROW_SCOPE(lexicalGlobalObject->vm());
+ auto init = argument0.value().isUndefined() ? std::optional>, IDLRecord>>::ReturnType>() : std::optional>, IDLRecord>>::ReturnType>(convert>, IDLRecord>>(*lexicalGlobalObject, argument0.value()));
+ RETURN_IF_EXCEPTION(throwScope, nullptr);
+ return WebCoreCast(
+ JSC::JSValue::encode(WebCore::toJSNewlyCreated(lexicalGlobalObject, globalObject, WebCore::FetchHeaders::create(WTFMove(init)).releaseReturnValue())),
+ &lexicalGlobalObject->vm());
+}
+
+JSC__JSValue WebCore__FetchHeaders__toJS(WebCore__FetchHeaders* headers, JSC__JSGlobalObject* lexicalGlobalObject)
+{
+ Zig::GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject);
+
+ return JSC::JSValue::encode(WebCore::toJS(lexicalGlobalObject, globalObject, headers));
+}
+JSC__JSValue WebCore__FetchHeaders__clone(WebCore__FetchHeaders* headers, JSC__JSGlobalObject* arg1)
+{
+ Zig::GlobalObject* globalObject = reinterpret_cast(arg1);
+ auto clone = WebCore::FetchHeaders::create();
+ if (headers->size() > 0) {
+ auto iter = headers->createIterator();
+ uint32_t i = 0;
+ unsigned count = 0;
+ for (auto pair = iter.next(); pair; pair = iter.next()) {
+ auto name = pair->key;
+ auto value = pair->value;
+ clone->append(name.isolatedCopy(), value.isolatedCopy());
+ }
+ }
+ return JSC::JSValue::encode(WebCore::toJSNewlyCreated(arg1, globalObject, WTFMove(clone)));
+}
+
+// WebCore__FetchHeaders* WebCore__FetchHeaders__cloneThis(WebCore__FetchHeaders* headers)
+// {
+
+// return JSC::JSValue::encode(WebCore::toJSNewlyCreated(globalObject, globalObject, WebCore::FetchHeaders::create(*headers)));
+// }
+
+void WebCore__FetchHeaders__copyTo(WebCore__FetchHeaders* headers, StringPointer* names, StringPointer* values, unsigned char* buf)
+{
+ auto iter = headers->createIterator();
+ uint32_t i = 0;
+ unsigned count = 0;
+ for (auto pair = iter.next(); pair; pair = iter.next()) {
+ auto name = pair->key;
+ auto value = pair->value;
+ names[count] = { i, name.length() };
+ memcpy(&buf[i], name.characters8(), name.length());
+ i += name.length();
+ values[count++] = { i, value.length() };
+ memcpy(&buf[i], value.characters8(), value.length());
+ i += value.length();
+ }
+}
+void WebCore__FetchHeaders__count(WebCore__FetchHeaders* headers, uint32_t* count, uint32_t* buf_len)
+{
+ auto iter = headers->createIterator();
+ uint32_t i = 0;
+ for (auto pair = iter.next(); pair; pair = iter.next()) {
+ i += pair->key.length();
+ i += pair->value.length();
+ }
+
+ *count = headers->size();
+ *buf_len = i;
+}
+typedef struct PicoHTTPHeader {
+ unsigned const char* name;
+ size_t name_len;
+ unsigned const char* value;
+ size_t value_len;
+} PicoHTTPHeader;
+
+typedef struct PicoHTTPHeaders {
+ const PicoHTTPHeader* ptr;
+ size_t len;
+} PicoHTTPHeaders;
+JSC__JSValue WebCore__FetchHeaders__createFromPicoHeaders_(JSC__JSGlobalObject* arg0, const void* arg1)
+{
+ PicoHTTPHeaders pico_headers = *reinterpret_cast(arg1);
+ Vector> pairs;
+ pairs.reserveCapacity(pico_headers.len);
+ for (size_t i = 0; i < pico_headers.len; i++) {
+ WTF::String name = WTF::String(pico_headers.ptr[i].name, pico_headers.ptr[i].name_len);
+ WTF::String value = WTF::String(pico_headers.ptr[i].value, pico_headers.ptr[i].value_len);
+ pairs.uncheckedAppend(KeyValuePair(name, value));
+ }
+
+ Ref headers = WebCore::FetchHeaders::create();
+ headers->fill(WebCore::FetchHeaders::Init(pairs));
+ pairs.releaseBuffer();
+ return JSC::JSValue::encode(WebCore::toJSNewlyCreated(arg0, reinterpret_cast(arg0), WTFMove(headers)));
+}
+JSC__JSValue WebCore__FetchHeaders__createFromUWS(JSC__JSGlobalObject* arg0, void* arg1)
+{
+ uWS::HttpRequest req = *reinterpret_cast(arg1);
+ Vector> pairs;
+ pairs.reserveCapacity(55);
+ for (const auto& header : req) {
+ auto name = WTF::String(reinterpret_cast(header.first.data()), header.first.length());
+ auto value = WTF::String(reinterpret_cast(header.second.data()), header.second.length());
+ pairs.uncheckedAppend(KeyValuePair(name, value));
+ }
+
+ Ref headers = WebCore::FetchHeaders::create();
+ headers->fill(WebCore::FetchHeaders::Init(pairs));
+ pairs.releaseBuffer();
+ return JSC::JSValue::encode(WebCore::toJS(arg0, reinterpret_cast(arg0), headers));
+}
+void WebCore__FetchHeaders__deref(WebCore__FetchHeaders* arg0)
+{
+ arg0->deref();
+}
+
+JSC__JSValue WebCore__FetchHeaders__createValue(JSC__JSGlobalObject* arg0, StringPointer* arg1, StringPointer* arg2, const ZigString* arg3, uint32_t count)
+{
+ Vector> pairs;
+ pairs.reserveCapacity(count);
+ ZigString buf = *arg3;
+ for (uint32_t i = 0; i < count; i++) {
+ WTF::String name = Zig::toStringCopy(buf, arg1[i]);
+ WTF::String value = Zig::toStringCopy(buf, arg2[i]);
+ pairs.uncheckedAppend(KeyValuePair(name, value));
+ }
+
+ Ref headers = WebCore::FetchHeaders::create();
+ headers->fill(WebCore::FetchHeaders::Init(pairs));
+ pairs.releaseBuffer();
+ return JSC::JSValue::encode(WebCore::toJS(arg0, reinterpret_cast(arg0), headers));
+}
+void WebCore__FetchHeaders__get_(WebCore__FetchHeaders* headers, const ZigString* arg1, ZigString* arg2)
+{
+ *arg2 = Zig::toZigString(headers->get(Zig::toString(*arg1)).releaseReturnValue());
+}
+bool WebCore__FetchHeaders__has(WebCore__FetchHeaders* headers, const ZigString* arg1)
+{
+ return headers->has(Zig::toString(*arg1)).releaseReturnValue();
+}
+void WebCore__FetchHeaders__put_(WebCore__FetchHeaders* headers, const ZigString* arg1, const ZigString* arg2)
+{
+ headers->set(Zig::toString(*arg1), Zig::toString(*arg2));
+}
+void WebCore__FetchHeaders__remove(WebCore__FetchHeaders* headers, const ZigString* arg1)
+{
+ headers->remove(Zig::toString(*arg1));
+}
+
+WebCore__DOMURL* WebCore__DOMURL__cast_(JSC__JSValue JSValue0, JSC::VM* vm)
+{
+ return WebCoreCast(JSValue0, vm);
+}
+
void WebCore__DOMURL__href_(WebCore__DOMURL* domURL, ZigString* arg1)
{
const WTF::URL& href = domURL->href();
diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig
index 15f71a4707..0f8d5de00a 100644
--- a/src/javascript/jsc/bindings/bindings.zig
+++ b/src/javascript/jsc/bindings/bindings.zig
@@ -110,6 +110,24 @@ pub const ZigString = extern struct {
pub const empty = Slice{ .allocator = bun.default_allocator, .ptr = undefined, .len = 0, .allocated = false };
+ pub fn clone(this: Slice, allocator: std.mem.Allocator) !Slice {
+ if (!this.allocated) {
+ return Slice{ .allocator = allocator, .ptr = this.ptr, .len = this.len, .allocated = false };
+ }
+
+ var duped = try allocator.dupe(u8, this.ptr[0..this.len]);
+ return Slice{ .allocator = allocator, .ptr = duped.ptr, .len = this.len, .allocated = true };
+ }
+
+ pub fn cloneZ(this: Slice, allocator: std.mem.Allocator) !Slice {
+ if (this.allocated or this.len == 0) {
+ return this;
+ }
+
+ var duped = try allocator.dupeZ(u8, this.ptr[0..this.len]);
+ return Slice{ .allocator = allocator, .ptr = duped.ptr, .len = this.len, .allocated = true };
+ }
+
pub fn slice(this: Slice) []const u8 {
return this.ptr[0..this.len];
}
@@ -272,6 +290,28 @@ pub const ZigString = extern struct {
};
}
+ pub fn toSliceZ(this: ZigString, allocator: std.mem.Allocator) Slice {
+ if (this.len == 0)
+ return Slice{ .ptr = "", .len = 0, .allocator = allocator, .allocated = false };
+
+ if (is16Bit(&this)) {
+ var buffer = std.fmt.allocPrintZ(allocator, "{}", .{this}) catch unreachable;
+ return Slice{
+ .ptr = buffer.ptr,
+ .len = @truncate(u32, buffer.len),
+ .allocated = true,
+ .allocator = allocator,
+ };
+ }
+
+ return Slice{
+ .ptr = untagged(this.ptr),
+ .len = @truncate(u32, this.len),
+ .allocated = false,
+ .allocator = allocator,
+ };
+ }
+
pub fn sliceZBuf(this: ZigString, buf: *[bun.MAX_PATH_BYTES]u8) ![:0]const u8 {
return try std.fmt.bufPrintZ(buf, "{}", .{this});
}
@@ -355,8 +395,12 @@ pub const DOMURL = opaque {
const cppFn = shim.cppFn;
pub const name = "WebCore::DOMURL";
+ pub fn cast_(value: JSValue, vm: *VM) ?*DOMURL {
+ return shim.cppFn("cast_", .{ value, vm });
+ }
+
pub fn cast(value: JSValue) ?*DOMURL {
- return shim.cppFn("cast", .{value});
+ return cast_(value, JSC.VirtualMachine.vm.global.vm());
}
pub fn href_(this: *DOMURL, out: *ZigString) void {
@@ -380,12 +424,291 @@ pub const DOMURL = opaque {
}
pub const Extern = [_][]const u8{
- "cast",
+ "cast_",
"href_",
"pathname_",
};
};
+const Api = @import("../../../api/schema.zig").Api;
+
+pub const FetchHeaders = opaque {
+ pub const shim = Shimmer("WebCore", "FetchHeaders", @This());
+
+ const cppFn = shim.cppFn;
+ pub const name = "WebCore::FetchHeaders";
+
+ pub fn createValue(
+ global: *JSGlobalObject,
+ names: [*c]Api.StringPointer,
+ values: [*c]Api.StringPointer,
+ buf: *const ZigString,
+ count_: u32,
+ ) JSValue {
+ return shim.cppFn("createValue", .{
+ global,
+ names,
+ values,
+ buf,
+ count_,
+ });
+ }
+
+ pub fn createFromJS(
+ global: *JSGlobalObject,
+ value: JSValue,
+ ) ?*FetchHeaders {
+ return shim.cppFn("createFromJS", .{
+ global,
+ value,
+ });
+ }
+
+ pub fn putDefault(this: *FetchHeaders, name_: []const u8, value: []const u8) void {
+ if (this.has(&ZigString.init(name_))) {
+ return;
+ }
+
+ this.put_(&ZigString.init(name_), &ZigString.init(value));
+ }
+
+ pub fn from(
+ global: *JSGlobalObject,
+ names: [*c]Api.StringPointer,
+ values: [*c]Api.StringPointer,
+ buf: *const ZigString,
+ count_: u32,
+ ) JSValue {
+ return shim.cppFn("createValue", .{
+ global,
+ names,
+ values,
+ buf,
+ count_,
+ });
+ }
+
+ pub fn createFromUWS(
+ global: *JSGlobalObject,
+ uws_request: *anyopaque,
+ ) JSValue {
+ return shim.cppFn("createFromUWS", .{
+ global,
+ uws_request,
+ });
+ }
+
+ pub fn toUWSResponse(
+ headers: *FetchHeaders,
+ is_ssl: bool,
+ uws_response: *anyopaque,
+ ) void {
+ return shim.cppFn("toUWSResponse", .{
+ headers,
+ is_ssl,
+ uws_response,
+ });
+ }
+
+ const PicoHeaders = extern struct {
+ ptr: *const anyopaque,
+ len: usize,
+ };
+
+ pub fn createEmpty(
+ global: *JSGlobalObject,
+ ) JSValue {
+ const pico_ = PicoHeaders{ .ptr = undefined, .len = 0 };
+ return shim.cppFn("createFromPicoHeaders_", .{
+ global,
+ &pico_,
+ });
+ }
+
+ pub fn createFromPicoHeaders(
+ global: *JSGlobalObject,
+ pico_headers: anytype,
+ ) JSValue {
+ const out = PicoHeaders{ .ptr = pico_headers.ptr, .len = pico_headers.len };
+ const result = shim.cppFn("createFromPicoHeaders_", .{
+ global,
+ &out,
+ });
+ return result;
+ }
+
+ pub fn createFromPicoHeaders_(
+ global: *JSGlobalObject,
+ pico_headers: *const anyopaque,
+ ) JSValue {
+ return shim.cppFn("createFromPicoHeaders_", .{
+ global,
+ pico_headers,
+ });
+ }
+
+ pub fn append(
+ this: *FetchHeaders,
+ name_: *const ZigString,
+ value: *const ZigString,
+ ) void {
+ return shim.cppFn("append", .{
+ this,
+ name_,
+ value,
+ });
+ }
+
+ pub fn put_(
+ this: *FetchHeaders,
+ name_: *const ZigString,
+ value: *const ZigString,
+ ) void {
+ return shim.cppFn("put_", .{
+ this,
+ name_,
+ value,
+ });
+ }
+
+ pub fn put(
+ this: *FetchHeaders,
+ name_: []const u8,
+ value: []const u8,
+ ) void {
+ this.put_(&ZigString.init(name_), &ZigString.init(value));
+ }
+
+ pub fn get_(
+ this: *FetchHeaders,
+ name_: *const ZigString,
+ out: *ZigString,
+ ) void {
+ shim.cppFn("get_", .{
+ this,
+ name_,
+ out,
+ });
+ }
+
+ pub fn get(
+ this: *FetchHeaders,
+ name_: []const u8,
+ ) ?[]const u8 {
+ var out = ZigString.Empty;
+ get_(this, &ZigString.init(name_), &out);
+ if (out.len > 0) {
+ return out.slice();
+ }
+
+ return null;
+ }
+
+ pub fn has(
+ this: *FetchHeaders,
+ name_: *const ZigString,
+ ) bool {
+ return shim.cppFn("has", .{
+ this,
+ name_,
+ });
+ }
+
+ pub fn remove(
+ this: *FetchHeaders,
+ name_: *const ZigString,
+ ) void {
+ return shim.cppFn("remove", .{
+ this,
+ name_,
+ });
+ }
+
+ pub fn cast_(value: JSValue, vm: *VM) ?*FetchHeaders {
+ return shim.cppFn("cast_", .{ value, vm });
+ }
+
+ pub fn cast(value: JSValue) ?*FetchHeaders {
+ return cast_(value, JSC.VirtualMachine.vm.global.vm());
+ }
+
+ pub fn toJS(this: *FetchHeaders, globalThis: *JSGlobalObject) JSValue {
+ return shim.cppFn("toJS", .{ this, globalThis });
+ }
+
+ pub fn count(
+ this: *FetchHeaders,
+ names: *u32,
+ buf_len: *u32,
+ ) void {
+ return shim.cppFn("count", .{
+ this,
+ names,
+ buf_len,
+ });
+ }
+
+ pub fn clone(
+ this: *FetchHeaders,
+ global: *JSGlobalObject,
+ ) JSValue {
+ return shim.cppFn("clone", .{
+ this,
+ global,
+ });
+ }
+
+ pub fn cloneThis(
+ this: *FetchHeaders,
+ ) ?*FetchHeaders {
+ return shim.cppFn("cloneThis", .{
+ this,
+ });
+ }
+
+ pub fn deref(
+ this: *FetchHeaders,
+ ) void {
+ return shim.cppFn("deref", .{
+ this,
+ });
+ }
+
+ pub fn copyTo(
+ this: *FetchHeaders,
+ names: [*c]Api.StringPointer,
+ values: [*c]Api.StringPointer,
+ buf: [*]u8,
+ ) void {
+ return shim.cppFn("copyTo", .{
+ this,
+ names,
+ values,
+ buf,
+ });
+ }
+
+ pub const Extern = [_][]const u8{
+ "append",
+ "cast_",
+ "clone",
+ "cloneThis",
+ "copyTo",
+ "count",
+ "createFromJS",
+ "createFromPicoHeaders_",
+ "createFromUWS",
+ "createValue",
+ "deref",
+ "get_",
+ "has",
+ "put_",
+ "remove",
+ "toJS",
+ "toUWSResponse",
+ };
+};
+
pub const SystemError = extern struct {
errno: c_int = 0,
/// label for errno
@@ -1667,6 +1990,10 @@ pub const String = extern struct {
};
};
+pub const BuiltinName = enum(u8) {
+ headers,
+};
+
pub const JSValue = enum(u64) {
_,
@@ -1935,13 +2262,17 @@ pub const JSValue = enum(u64) {
}
pub fn as(value: JSValue, comptime ZigType: type) ?*ZigType {
- if (value.isUndefinedOrNull())
+ if (value.isEmptyOrUndefinedOrNull())
return null;
if (comptime ZigType == DOMURL) {
return DOMURL.cast(value);
}
+ if (comptime ZigType == FetchHeaders) {
+ return FetchHeaders.cast(value);
+ }
+
return JSC.GetJSPrivateData(ZigType, value.asObjectRef());
}
@@ -2083,6 +2414,12 @@ pub const JSValue = enum(u64) {
pub fn isNull(this: JSValue) bool {
return @enumToInt(this) == 0x2;
}
+ pub fn isEmptyOrUndefinedOrNull(this: JSValue) bool {
+ return switch (@enumToInt(this)) {
+ 0, 0xa, 0x2 => true,
+ else => false,
+ };
+ }
pub fn isUndefinedOrNull(this: JSValue) bool {
return switch (@enumToInt(this)) {
0xa, 0x2 => true,
@@ -2249,6 +2586,10 @@ pub const JSValue = enum(u64) {
return cppFn("getIfPropertyExistsImpl", .{ this, global, ptr, len });
}
+ pub fn getHiddenIfPropertyExistsImpl(this: JSValue, global: *JSGlobalObject, ptr: [*]const u8, len: u32) JSValue {
+ return cppFn("getHiddenIfPropertyExistsImpl", .{ this, global, ptr, len });
+ }
+
pub fn getSymbolDescription(this: JSValue, global: *JSGlobalObject, str: *ZigString) void {
cppFn("getSymbolDescription", .{ this, global, str });
}
@@ -2314,6 +2655,11 @@ pub const JSValue = enum(u64) {
return if (@enumToInt(value) != 0) value else return null;
}
+ pub fn getHidden(this: JSValue, global: *JSGlobalObject, property: []const u8) ?JSValue {
+ const value = getIfPropertyExistsImpl(this, global, property.ptr, @intCast(u32, property.len));
+ return if (@enumToInt(value) != 0) value else return null;
+ }
+
pub fn getTruthy(this: JSValue, global: *JSGlobalObject, property: []const u8) ?JSValue {
if (get(this, global, property)) |prop| {
if (@enumToInt(prop) == 0 or prop.isUndefinedOrNull()) return null;
diff --git a/src/javascript/jsc/bindings/exports.zig b/src/javascript/jsc/bindings/exports.zig
index 8c6cb17c99..d58e451576 100644
--- a/src/javascript/jsc/bindings/exports.zig
+++ b/src/javascript/jsc/bindings/exports.zig
@@ -1695,11 +1695,6 @@ pub const ZigConsoleClient = struct {
response.writeFormat(this, writer_, enable_ansi_colors) catch {};
return;
},
- @field(JSPrivateDataPtr.Tag, @typeName(JSC.WebCore.Headers.RefCountedHeaders)) => {
- var obj = priv_data.as(JSC.WebCore.Headers.RefCountedHeaders);
- obj.leak().writeFormat(this, writer_, enable_ansi_colors) catch {};
- return;
- },
.Request => {
this.printAs(.JSON, Writer, writer_, value, .Object, enable_ansi_colors);
return;
diff --git a/src/javascript/jsc/bindings/header-gen.zig b/src/javascript/jsc/bindings/header-gen.zig
index 612f862158..30467f6985 100644
--- a/src/javascript/jsc/bindings/header-gen.zig
+++ b/src/javascript/jsc/bindings/header-gen.zig
@@ -41,6 +41,7 @@ pub fn cTypeLabel(comptime Type: type) ?[]const u8 {
f64 => "double",
f32 => "float",
*anyopaque => "void*",
+ *const anyopaque => "const void*",
[*]bool => "bool*",
[*]usize => "size_t*",
[*]isize => "int*",
diff --git a/src/javascript/jsc/bindings/headers-cpp.h b/src/javascript/jsc/bindings/headers-cpp.h
index ab5dead544..9d0ce21131 100644
--- a/src/javascript/jsc/bindings/headers-cpp.h
+++ b/src/javascript/jsc/bindings/headers-cpp.h
@@ -1,4 +1,4 @@
-//-- AUTOGENERATED FILE -- 1648722142
+//-- AUTOGENERATED FILE -- 1648790662
// clang-format off
#pragma once
@@ -256,8 +256,8 @@ extern "C" const size_t Zig__ConsoleClient_object_align_ = alignof(Zig::ConsoleC
extern "C" const size_t Bun__Timer_object_size_ = sizeof(Bun__Timer);
extern "C" const size_t Bun__Timer_object_align_ = alignof(Bun__Timer);
-const size_t sizes[31] = {sizeof(JSC::JSObject), sizeof(WebCore::DOMURL), sizeof(SystemError), sizeof(JSC::JSCell), sizeof(JSC::JSString), sizeof(Inspector::ScriptArguments), sizeof(JSC::JSModuleLoader), sizeof(JSC::JSModuleRecord), sizeof(JSC::JSPromise), sizeof(JSC::JSInternalPromise), sizeof(JSC::SourceOrigin), sizeof(JSC::SourceCode), sizeof(JSC::JSFunction), sizeof(JSC::JSGlobalObject), sizeof(WTF::URL), sizeof(WTF::String), sizeof(JSC::JSValue), sizeof(JSC::PropertyName), sizeof(JSC::Exception), sizeof(JSC::VM), sizeof(JSC::ThrowScope), sizeof(JSC::CatchScope), sizeof(JSC::CallFrame), sizeof(JSC::Identifier), sizeof(WTF::StringImpl), sizeof(WTF::ExternalStringImpl), sizeof(WTF::StringView), sizeof(Zig::GlobalObject), sizeof(Bun__Readable), sizeof(Bun__Writable), sizeof(Bun__Path)};
+const size_t sizes[32] = {sizeof(JSC::JSObject), sizeof(WebCore::DOMURL), sizeof(WebCore::FetchHeaders), sizeof(SystemError), sizeof(JSC::JSCell), sizeof(JSC::JSString), sizeof(Inspector::ScriptArguments), sizeof(JSC::JSModuleLoader), sizeof(JSC::JSModuleRecord), sizeof(JSC::JSPromise), sizeof(JSC::JSInternalPromise), sizeof(JSC::SourceOrigin), sizeof(JSC::SourceCode), sizeof(JSC::JSFunction), sizeof(JSC::JSGlobalObject), sizeof(WTF::URL), sizeof(WTF::String), sizeof(JSC::JSValue), sizeof(JSC::PropertyName), sizeof(JSC::Exception), sizeof(JSC::VM), sizeof(JSC::ThrowScope), sizeof(JSC::CatchScope), sizeof(JSC::CallFrame), sizeof(JSC::Identifier), sizeof(WTF::StringImpl), sizeof(WTF::ExternalStringImpl), sizeof(WTF::StringView), sizeof(Zig::GlobalObject), sizeof(Bun__Readable), sizeof(Bun__Writable), sizeof(Bun__Path)};
-const char* names[31] = {"JSC__JSObject", "WebCore__DOMURL", "SystemError", "JSC__JSCell", "JSC__JSString", "Inspector__ScriptArguments", "JSC__JSModuleLoader", "JSC__JSModuleRecord", "JSC__JSPromise", "JSC__JSInternalPromise", "JSC__SourceOrigin", "JSC__SourceCode", "JSC__JSFunction", "JSC__JSGlobalObject", "WTF__URL", "WTF__String", "JSC__JSValue", "JSC__PropertyName", "JSC__Exception", "JSC__VM", "JSC__ThrowScope", "JSC__CatchScope", "JSC__CallFrame", "JSC__Identifier", "WTF__StringImpl", "WTF__ExternalStringImpl", "WTF__StringView", "Zig__GlobalObject", "Bun__Readable", "Bun__Writable", "Bun__Path"};
+const char* names[32] = {"JSC__JSObject", "WebCore__DOMURL", "WebCore__FetchHeaders", "SystemError", "JSC__JSCell", "JSC__JSString", "Inspector__ScriptArguments", "JSC__JSModuleLoader", "JSC__JSModuleRecord", "JSC__JSPromise", "JSC__JSInternalPromise", "JSC__SourceOrigin", "JSC__SourceCode", "JSC__JSFunction", "JSC__JSGlobalObject", "WTF__URL", "WTF__String", "JSC__JSValue", "JSC__PropertyName", "JSC__Exception", "JSC__VM", "JSC__ThrowScope", "JSC__CatchScope", "JSC__CallFrame", "JSC__Identifier", "WTF__StringImpl", "WTF__ExternalStringImpl", "WTF__StringView", "Zig__GlobalObject", "Bun__Readable", "Bun__Writable", "Bun__Path"};
-const size_t aligns[31] = {alignof(JSC::JSObject), alignof(WebCore::DOMURL), alignof(SystemError), alignof(JSC::JSCell), alignof(JSC::JSString), alignof(Inspector::ScriptArguments), alignof(JSC::JSModuleLoader), alignof(JSC::JSModuleRecord), alignof(JSC::JSPromise), alignof(JSC::JSInternalPromise), alignof(JSC::SourceOrigin), alignof(JSC::SourceCode), alignof(JSC::JSFunction), alignof(JSC::JSGlobalObject), alignof(WTF::URL), alignof(WTF::String), alignof(JSC::JSValue), alignof(JSC::PropertyName), alignof(JSC::Exception), alignof(JSC::VM), alignof(JSC::ThrowScope), alignof(JSC::CatchScope), alignof(JSC::CallFrame), alignof(JSC::Identifier), alignof(WTF::StringImpl), alignof(WTF::ExternalStringImpl), alignof(WTF::StringView), alignof(Zig::GlobalObject), alignof(Bun__Readable), alignof(Bun__Writable), alignof(Bun__Path)};
+const size_t aligns[32] = {alignof(JSC::JSObject), alignof(WebCore::DOMURL), alignof(WebCore::FetchHeaders), alignof(SystemError), alignof(JSC::JSCell), alignof(JSC::JSString), alignof(Inspector::ScriptArguments), alignof(JSC::JSModuleLoader), alignof(JSC::JSModuleRecord), alignof(JSC::JSPromise), alignof(JSC::JSInternalPromise), alignof(JSC::SourceOrigin), alignof(JSC::SourceCode), alignof(JSC::JSFunction), alignof(JSC::JSGlobalObject), alignof(WTF::URL), alignof(WTF::String), alignof(JSC::JSValue), alignof(JSC::PropertyName), alignof(JSC::Exception), alignof(JSC::VM), alignof(JSC::ThrowScope), alignof(JSC::CatchScope), alignof(JSC::CallFrame), alignof(JSC::Identifier), alignof(WTF::StringImpl), alignof(WTF::ExternalStringImpl), alignof(WTF::StringView), alignof(Zig::GlobalObject), alignof(Bun__Readable), alignof(Bun__Writable), alignof(Bun__Path)};
diff --git a/src/javascript/jsc/bindings/headers-handwritten.h b/src/javascript/jsc/bindings/headers-handwritten.h
index 0c4cc2754e..8bfc1a09d8 100644
--- a/src/javascript/jsc/bindings/headers-handwritten.h
+++ b/src/javascript/jsc/bindings/headers-handwritten.h
@@ -175,12 +175,15 @@ typedef struct {
uint8_t cell_type;
} Bun__ArrayBuffer;
-#ifdef __cplusplus
-
+#ifndef STRING_POINTER
+#define STRING_POINTER
typedef struct StringPointer {
uint32_t off;
uint32_t len;
} StringPointer;
+#endif
+
+#ifdef __cplusplus
extern "C" ZigErrorCode Zig_ErrorCodeParserError;
diff --git a/src/javascript/jsc/bindings/headers-replacements.zig b/src/javascript/jsc/bindings/headers-replacements.zig
index fd1e7b4e97..c503d32887 100644
--- a/src/javascript/jsc/bindings/headers-replacements.zig
+++ b/src/javascript/jsc/bindings/headers-replacements.zig
@@ -60,3 +60,5 @@ pub const Bun__Readable = bindings.NodeReadableStream;
pub const Bun__Writable = bindings.NodeWritableStream;
pub const Bun__ArrayBuffer = bindings.ArrayBuffer;
pub const struct_WebCore__DOMURL = bindings.DOMURL;
+pub const struct_WebCore__FetchHeaders = bindings.FetchHeaders;
+pub const StringPointer = @import("../../../api/schema.zig").Api.StringPointer;
diff --git a/src/javascript/jsc/bindings/headers.h b/src/javascript/jsc/bindings/headers.h
index d99f24e58f..9175274cbd 100644
--- a/src/javascript/jsc/bindings/headers.h
+++ b/src/javascript/jsc/bindings/headers.h
@@ -1,5 +1,5 @@
// clang-format: off
-//-- AUTOGENERATED FILE -- 1648722142
+//-- AUTOGENERATED FILE -- 1648790662
#pragma once
#include
@@ -152,9 +152,10 @@ typedef struct JSC__IteratorPrototype JSC__IteratorPrototype; // JSC::IteratorPr
typedef Bun__Readable Bun__Readable;
typedef bJSC__JSInternalPromise JSC__JSInternalPromise; // JSC::JSInternalPromise
typedef Bun__Writable Bun__Writable;
+typedef struct JSC__MapIteratorPrototype JSC__MapIteratorPrototype; // JSC::MapIteratorPrototype
typedef struct JSC__RegExpPrototype JSC__RegExpPrototype; // JSC::RegExpPrototype
typedef bJSC__CallFrame JSC__CallFrame; // JSC::CallFrame
-typedef struct JSC__MapIteratorPrototype JSC__MapIteratorPrototype; // JSC::MapIteratorPrototype
+typedef struct WebCore__FetchHeaders WebCore__FetchHeaders; // WebCore::FetchHeaders
typedef bWTF__StringView WTF__StringView; // WTF::StringView
typedef bJSC__ThrowScope JSC__ThrowScope; // JSC::ThrowScope
typedef bWTF__StringImpl WTF__StringImpl; // WTF::StringImpl
@@ -230,6 +231,7 @@ class JSMicrotaskCallback;
}
namespace WebCore {
class DOMURL;
+class FetchHeaders;
}
namespace Inspector {
class ScriptArguments;
@@ -287,6 +289,7 @@ using WTF__StringView = WTF::StringView;
using WTF__ExternalStringImpl = WTF::ExternalStringImpl;
using Zig__JSMicrotaskCallback = Zig::JSMicrotaskCallback;
using WebCore__DOMURL = WebCore::DOMURL;
+using WebCore__FetchHeaders = WebCore::FetchHeaders;
using Inspector__ScriptArguments = Inspector::ScriptArguments;
#endif
@@ -306,9 +309,27 @@ CPP_DECL JSC__JSValue ZigString__toExternalValue(const ZigString* arg0, JSC__JSG
CPP_DECL JSC__JSValue ZigString__toExternalValueWithCallback(const ZigString* arg0, JSC__JSGlobalObject* arg1, void (*ArgFn2)(void* arg0, void* arg1, size_t arg2));
CPP_DECL JSC__JSValue ZigString__toValue(const ZigString* arg0, JSC__JSGlobalObject* arg1);
CPP_DECL JSC__JSValue ZigString__toValueGC(const ZigString* arg0, JSC__JSGlobalObject* arg1);
-CPP_DECL WebCore__DOMURL* WebCore__DOMURL__cast(JSC__JSValue JSValue0);
+CPP_DECL WebCore__DOMURL* WebCore__DOMURL__cast_(JSC__JSValue JSValue0, JSC__VM* arg1);
CPP_DECL void WebCore__DOMURL__href_(WebCore__DOMURL* arg0, ZigString* arg1);
CPP_DECL void WebCore__DOMURL__pathname_(WebCore__DOMURL* arg0, ZigString* arg1);
+CPP_DECL void WebCore__FetchHeaders__append(WebCore__FetchHeaders* arg0, const ZigString* arg1, const ZigString* arg2);
+CPP_DECL WebCore__FetchHeaders* WebCore__FetchHeaders__cast_(JSC__JSValue JSValue0, JSC__VM* arg1);
+CPP_DECL JSC__JSValue WebCore__FetchHeaders__clone(WebCore__FetchHeaders* arg0, JSC__JSGlobalObject* arg1);
+CPP_DECL WebCore__FetchHeaders* WebCore__FetchHeaders__cloneThis(WebCore__FetchHeaders* arg0);
+CPP_DECL void WebCore__FetchHeaders__copyTo(WebCore__FetchHeaders* arg0, StringPointer* arg1, StringPointer* arg2, unsigned char* arg3);
+CPP_DECL void WebCore__FetchHeaders__count(WebCore__FetchHeaders* arg0, uint32_t* arg1, uint32_t* arg2);
+CPP_DECL WebCore__FetchHeaders* WebCore__FetchHeaders__createFromJS(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1);
+CPP_DECL JSC__JSValue WebCore__FetchHeaders__createFromPicoHeaders_(JSC__JSGlobalObject* arg0, const void* arg1);
+CPP_DECL JSC__JSValue WebCore__FetchHeaders__createFromUWS(JSC__JSGlobalObject* arg0, void* arg1);
+CPP_DECL JSC__JSValue WebCore__FetchHeaders__createValue(JSC__JSGlobalObject* arg0, StringPointer* arg1, StringPointer* arg2, const ZigString* arg3, uint32_t arg4);
+CPP_DECL void WebCore__FetchHeaders__deref(WebCore__FetchHeaders* arg0);
+CPP_DECL void WebCore__FetchHeaders__get_(WebCore__FetchHeaders* arg0, const ZigString* arg1, ZigString* arg2);
+CPP_DECL bool WebCore__FetchHeaders__has(WebCore__FetchHeaders* arg0, const ZigString* arg1);
+CPP_DECL uint32_t WebCore__FetchHeaders__keyCount(WebCore__FetchHeaders* arg0);
+CPP_DECL void WebCore__FetchHeaders__put_(WebCore__FetchHeaders* arg0, const ZigString* arg1, const ZigString* arg2);
+CPP_DECL void WebCore__FetchHeaders__remove(WebCore__FetchHeaders* arg0, const ZigString* arg1);
+CPP_DECL JSC__JSValue WebCore__FetchHeaders__toJS(WebCore__FetchHeaders* arg0, JSC__JSGlobalObject* arg1);
+CPP_DECL void WebCore__FetchHeaders__toUWSResponse(WebCore__FetchHeaders* arg0, bool arg1, void* arg2);
CPP_DECL JSC__JSValue SystemError__toErrorInstance(const SystemError* arg0, JSC__JSGlobalObject* arg1);
#pragma mark - JSC::JSCell
diff --git a/src/javascript/jsc/bindings/headers.zig b/src/javascript/jsc/bindings/headers.zig
index e82ca8e709..2eb6ad46f4 100644
--- a/src/javascript/jsc/bindings/headers.zig
+++ b/src/javascript/jsc/bindings/headers.zig
@@ -60,6 +60,8 @@ pub const Bun__Readable = bindings.NodeReadableStream;
pub const Bun__Writable = bindings.NodeWritableStream;
pub const Bun__ArrayBuffer = bindings.ArrayBuffer;
pub const struct_WebCore__DOMURL = bindings.DOMURL;
+pub const struct_WebCore__FetchHeaders = bindings.FetchHeaders;
+pub const StringPointer = @import("../../../api/schema.zig").Api.StringPointer;
// GENERATED CODE - DO NOT MODIFY BY HAND
pub const ptrdiff_t = c_long;
@@ -106,10 +108,12 @@ pub const WTF__URL = bWTF__URL;
pub const JSC__IteratorPrototype = struct_JSC__IteratorPrototype;
pub const JSC__JSInternalPromise = bJSC__JSInternalPromise;
+pub const JSC__MapIteratorPrototype = struct_JSC__MapIteratorPrototype;
+
pub const JSC__RegExpPrototype = struct_JSC__RegExpPrototype;
pub const JSC__CallFrame = bJSC__CallFrame;
-pub const JSC__MapIteratorPrototype = struct_JSC__MapIteratorPrototype;
+pub const WebCore__FetchHeaders = struct_WebCore__FetchHeaders;
pub const WTF__StringView = bWTF__StringView;
pub const JSC__ThrowScope = bJSC__ThrowScope;
pub const WTF__StringImpl = bWTF__StringImpl;
@@ -147,9 +151,27 @@ pub extern fn ZigString__toExternalValue(arg0: [*c]const ZigString, arg1: [*c]JS
pub extern fn ZigString__toExternalValueWithCallback(arg0: [*c]const ZigString, arg1: [*c]JSC__JSGlobalObject, ArgFn2: ?fn (?*anyopaque, ?*anyopaque, usize) callconv(.C) void) JSC__JSValue;
pub extern fn ZigString__toValue(arg0: [*c]const ZigString, arg1: [*c]JSC__JSGlobalObject) JSC__JSValue;
pub extern fn ZigString__toValueGC(arg0: [*c]const ZigString, arg1: [*c]JSC__JSGlobalObject) JSC__JSValue;
-pub extern fn WebCore__DOMURL__cast(JSValue0: JSC__JSValue) ?*WebCore__DOMURL;
+pub extern fn WebCore__DOMURL__cast_(JSValue0: JSC__JSValue, arg1: [*c]JSC__VM) ?*WebCore__DOMURL;
pub extern fn WebCore__DOMURL__href_(arg0: ?*WebCore__DOMURL, arg1: [*c]ZigString) void;
pub extern fn WebCore__DOMURL__pathname_(arg0: ?*WebCore__DOMURL, arg1: [*c]ZigString) void;
+pub extern fn WebCore__FetchHeaders__append(arg0: ?*WebCore__FetchHeaders, arg1: [*c]const ZigString, arg2: [*c]const ZigString) void;
+pub extern fn WebCore__FetchHeaders__cast_(JSValue0: JSC__JSValue, arg1: [*c]JSC__VM) ?*WebCore__FetchHeaders;
+pub extern fn WebCore__FetchHeaders__clone(arg0: ?*WebCore__FetchHeaders, arg1: [*c]JSC__JSGlobalObject) JSC__JSValue;
+pub extern fn WebCore__FetchHeaders__cloneThis(arg0: ?*WebCore__FetchHeaders) ?*WebCore__FetchHeaders;
+pub extern fn WebCore__FetchHeaders__copyTo(arg0: ?*WebCore__FetchHeaders, arg1: [*c]StringPointer, arg2: [*c]StringPointer, arg3: [*c]u8) void;
+pub extern fn WebCore__FetchHeaders__count(arg0: ?*WebCore__FetchHeaders, arg1: [*c]u32, arg2: [*c]u32) void;
+pub extern fn WebCore__FetchHeaders__createFromJS(arg0: [*c]JSC__JSGlobalObject, JSValue1: JSC__JSValue) ?*WebCore__FetchHeaders;
+pub extern fn WebCore__FetchHeaders__createFromPicoHeaders_(arg0: [*c]JSC__JSGlobalObject, arg1: ?*const anyopaque) JSC__JSValue;
+pub extern fn WebCore__FetchHeaders__createFromUWS(arg0: [*c]JSC__JSGlobalObject, arg1: ?*anyopaque) JSC__JSValue;
+pub extern fn WebCore__FetchHeaders__createValue(arg0: [*c]JSC__JSGlobalObject, arg1: [*c]StringPointer, arg2: [*c]StringPointer, arg3: [*c]const ZigString, arg4: u32) JSC__JSValue;
+pub extern fn WebCore__FetchHeaders__deref(arg0: ?*WebCore__FetchHeaders) void;
+pub extern fn WebCore__FetchHeaders__get_(arg0: ?*WebCore__FetchHeaders, arg1: [*c]const ZigString, arg2: [*c]ZigString) void;
+pub extern fn WebCore__FetchHeaders__has(arg0: ?*WebCore__FetchHeaders, arg1: [*c]const ZigString) bool;
+pub extern fn WebCore__FetchHeaders__keyCount(arg0: ?*WebCore__FetchHeaders) u32;
+pub extern fn WebCore__FetchHeaders__put_(arg0: ?*WebCore__FetchHeaders, arg1: [*c]const ZigString, arg2: [*c]const ZigString) void;
+pub extern fn WebCore__FetchHeaders__remove(arg0: ?*WebCore__FetchHeaders, arg1: [*c]const ZigString) void;
+pub extern fn WebCore__FetchHeaders__toJS(arg0: ?*WebCore__FetchHeaders, arg1: [*c]JSC__JSGlobalObject) JSC__JSValue;
+pub extern fn WebCore__FetchHeaders__toUWSResponse(arg0: ?*WebCore__FetchHeaders, arg1: bool, arg2: ?*anyopaque) void;
pub extern fn SystemError__toErrorInstance(arg0: [*c]const SystemError, arg1: [*c]JSC__JSGlobalObject) JSC__JSValue;
pub extern fn JSC__JSCell__getObject(arg0: [*c]JSC__JSCell) [*c]JSC__JSObject;
pub extern fn JSC__JSCell__getString(arg0: [*c]JSC__JSCell, arg1: [*c]JSC__JSGlobalObject) bWTF__String;
diff --git a/src/javascript/jsc/bindings/helpers.h b/src/javascript/jsc/bindings/helpers.h
index 79c9a7ace8..e4ceb5696a 100644
--- a/src/javascript/jsc/bindings/helpers.h
+++ b/src/javascript/jsc/bindings/helpers.h
@@ -125,6 +125,36 @@ static const WTF::String toString(ZigString str)
reinterpret_cast(untag(str.ptr)), str.len));
}
+static const WTF::String toString(ZigString str, StringPointer ptr)
+{
+ if (str.len == 0 || str.ptr == nullptr || ptr.len == 0) {
+ return WTF::String();
+ }
+ if (UNLIKELY(isTaggedUTF8Ptr(str.ptr))) {
+ return WTF::String::fromUTF8(&untag(str.ptr)[ptr.off], ptr.len);
+ }
+
+ return !isTaggedUTF16Ptr(str.ptr)
+ ? WTF::String(WTF::StringImpl::createWithoutCopying(&untag(str.ptr)[ptr.off], ptr.len))
+ : WTF::String(WTF::StringImpl::createWithoutCopying(
+ &reinterpret_cast(untag(str.ptr))[ptr.off], ptr.len));
+}
+
+static const WTF::String toStringCopy(ZigString str, StringPointer ptr)
+{
+ if (str.len == 0 || str.ptr == nullptr || ptr.len == 0) {
+ return WTF::String();
+ }
+ if (UNLIKELY(isTaggedUTF8Ptr(str.ptr))) {
+ return WTF::String::fromUTF8(&untag(str.ptr)[ptr.off], ptr.len);
+ }
+
+ return !isTaggedUTF16Ptr(str.ptr)
+ ? WTF::String(WTF::StringImpl::create(&untag(str.ptr)[ptr.off], ptr.len))
+ : WTF::String(WTF::StringImpl::create(
+ &reinterpret_cast(untag(str.ptr))[ptr.off], ptr.len));
+}
+
static const WTF::String toStringCopy(ZigString str)
{
if (str.len == 0 || str.ptr == nullptr) {
diff --git a/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h b/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h
index 3b496536bc..ad1b6a32bb 100644
--- a/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h
+++ b/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h
@@ -101,8 +101,8 @@ public:
// std::unique_ptr m_clientSubspaceForFileSystemDirectoryReader;
// std::unique_ptr m_clientSubspaceForFileSystemEntry;
// std::unique_ptr m_clientSubspaceForFileSystemFileEntry;
- // std::unique_ptr m_clientSubspaceForFetchHeaders;
- // std::unique_ptr m_clientSubspaceForFetchHeadersIterator;
+ std::unique_ptr m_clientSubspaceForFetchHeaders;
+ std::unique_ptr m_clientSubspaceForFetchHeadersIterator;
// std::unique_ptr m_clientSubspaceForFetchRequest;
// std::unique_ptr m_clientSubspaceForFetchResponse;
// std::unique_ptr m_clientSubspaceForFileSystemDirectoryHandle;
diff --git a/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h b/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h
index bb4cc33273..75d91c0a20 100644
--- a/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h
+++ b/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h
@@ -89,8 +89,8 @@ public:
// std::unique_ptr m_subspaceForFileSystemDirectoryReader;
// std::unique_ptr m_subspaceForFileSystemEntry;
// std::unique_ptr m_subspaceForFileSystemFileEntry;
- // std::unique_ptr m_subspaceForFetchHeaders;
- // std::unique_ptr m_subspaceForFetchHeadersIterator;
+ std::unique_ptr m_subspaceForFetchHeaders;
+ std::unique_ptr m_subspaceForFetchHeadersIterator;
// std::unique_ptr m_subspaceForFetchRequest;
// std::unique_ptr m_subspaceForFetchResponse;
// std::unique_ptr m_subspaceForFileSystemDirectoryHandle;
diff --git a/src/javascript/jsc/bindings/webcore/FetchHeaders.cpp b/src/javascript/jsc/bindings/webcore/FetchHeaders.cpp
new file mode 100644
index 0000000000..26af08f1ad
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/FetchHeaders.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2016 Canon Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted, provided that the following conditions
+ * are required to be met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Canon Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FetchHeaders.h"
+
+#include "HTTPParsers.h"
+
+namespace WebCore {
+
+// https://fetch.spec.whatwg.org/#concept-headers-remove-privileged-no-cors-request-headers
+static void removePrivilegedNoCORSRequestHeaders(HTTPHeaderMap& headers)
+{
+ headers.remove(HTTPHeaderName::Range);
+}
+
+static ExceptionOr canWriteHeader(const String& name, const String& value, const String& combinedValue, FetchHeaders::Guard guard)
+{
+ if (!isValidHTTPToken(name))
+ return Exception { TypeError, makeString("Invalid header name: '", name, "'") };
+ ASSERT(value.isEmpty() || (!isHTTPSpace(value[0]) && !isHTTPSpace(value[value.length() - 1])));
+ if (!isValidHTTPHeaderValue((value)))
+ return Exception { TypeError, makeString("Header '", name, "' has invalid value: '", value, "'") };
+ if (guard == FetchHeaders::Guard::Immutable)
+ return Exception { TypeError, "Headers object's guard is 'immutable'"_s };
+ if (guard == FetchHeaders::Guard::Request && isForbiddenHeaderName(name))
+ return false;
+ if (guard == FetchHeaders::Guard::RequestNoCors && !combinedValue.isEmpty() && !isSimpleHeader(name, combinedValue))
+ return false;
+ if (guard == FetchHeaders::Guard::Response && isForbiddenResponseHeaderName(name))
+ return false;
+ return true;
+}
+
+static ExceptionOr appendToHeaderMap(const String& name, const String& value, HTTPHeaderMap& headers, FetchHeaders::Guard guard)
+{
+ String normalizedValue = stripLeadingAndTrailingHTTPSpaces(value);
+ String combinedValue = normalizedValue;
+ if (headers.contains(name))
+ combinedValue = makeString(headers.get(name), ", ", normalizedValue);
+ auto canWriteResult = canWriteHeader(name, normalizedValue, combinedValue, guard);
+ if (canWriteResult.hasException())
+ return canWriteResult.releaseException();
+ if (!canWriteResult.releaseReturnValue())
+ return { };
+ headers.set(name, combinedValue);
+
+ if (guard == FetchHeaders::Guard::RequestNoCors)
+ removePrivilegedNoCORSRequestHeaders(headers);
+
+ return { };
+}
+
+static ExceptionOr appendToHeaderMap(const HTTPHeaderMap::HTTPHeaderMapConstIterator::KeyValue& header, HTTPHeaderMap& headers, FetchHeaders::Guard guard)
+{
+ String normalizedValue = stripLeadingAndTrailingHTTPSpaces(header.value);
+ auto canWriteResult = canWriteHeader(header.key, normalizedValue, header.value, guard);
+ if (canWriteResult.hasException())
+ return canWriteResult.releaseException();
+ if (!canWriteResult.releaseReturnValue())
+ return { };
+ if (header.keyAsHTTPHeaderName)
+ headers.add(header.keyAsHTTPHeaderName.value(), header.value);
+ else
+ headers.add(header.key, header.value);
+
+ if (guard == FetchHeaders::Guard::RequestNoCors)
+ removePrivilegedNoCORSRequestHeaders(headers);
+
+ return { };
+}
+
+// https://fetch.spec.whatwg.org/#concept-headers-fill
+static ExceptionOr fillHeaderMap(HTTPHeaderMap& headers, const FetchHeaders::Init& headersInit, FetchHeaders::Guard guard)
+{
+ if (std::holds_alternative>>(headersInit)) {
+ auto& sequence = std::get>>(headersInit);
+ for (auto& header : sequence) {
+ if (header.size() != 2)
+ return Exception { TypeError, "Header sub-sequence must contain exactly two items"_s };
+ auto result = appendToHeaderMap(header[0], header[1], headers, guard);
+ if (result.hasException())
+ return result.releaseException();
+ }
+ } else {
+ auto& record = std::get>>(headersInit);
+ for (auto& header : record) {
+ auto result = appendToHeaderMap(header.key, header.value, headers, guard);
+ if (result.hasException())
+ return result.releaseException();
+ }
+ }
+
+ return { };
+}
+
+ExceptionOr[> FetchHeaders::create(std::optional&& headersInit)
+{
+ HTTPHeaderMap headers;
+
+ if (headersInit) {
+ auto result = fillHeaderMap(headers, *headersInit, Guard::None);
+ if (result.hasException())
+ return result.releaseException();
+ }
+
+ return adoptRef(*new FetchHeaders { Guard::None, WTFMove(headers) });
+}
+
+ExceptionOr FetchHeaders::fill(const Init& headerInit)
+{
+ return fillHeaderMap(m_headers, headerInit, m_guard);
+}
+
+ExceptionOr FetchHeaders::fill(const FetchHeaders& otherHeaders)
+{
+ for (auto& header : otherHeaders.m_headers) {
+ auto result = appendToHeaderMap(header, m_headers, m_guard);
+ if (result.hasException())
+ return result.releaseException();
+ }
+
+ return { };
+}
+
+ExceptionOr FetchHeaders::append(const String& name, const String& value)
+{
+ return appendToHeaderMap(name, value, m_headers, m_guard);
+}
+
+// https://fetch.spec.whatwg.org/#dom-headers-delete
+ExceptionOr FetchHeaders::remove(const String& name)
+{
+ if (!isValidHTTPToken(name))
+ return Exception { TypeError, makeString("Invalid header name: '", name, "'") };
+ 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_headers.remove(name);
+
+ if (m_guard == FetchHeaders::Guard::RequestNoCors)
+ removePrivilegedNoCORSRequestHeaders(m_headers);
+
+ return { };
+}
+
+ExceptionOr FetchHeaders::get(const String& name) const
+{
+ if (!isValidHTTPToken(name))
+ return Exception { TypeError, makeString("Invalid header name: '", name, "'") };
+ return m_headers.get(name);
+}
+
+ExceptionOr FetchHeaders::has(const String& name) const
+{
+ if (!isValidHTTPToken(name))
+ return Exception { TypeError, makeString("Invalid header name: '", name, "'") };
+ return m_headers.contains(name);
+}
+
+ExceptionOr FetchHeaders::set(const String& name, const String& value)
+{
+ String normalizedValue = stripLeadingAndTrailingHTTPSpaces(value);
+ auto canWriteResult = canWriteHeader(name, normalizedValue, normalizedValue, m_guard);
+ if (canWriteResult.hasException())
+ return canWriteResult.releaseException();
+ if (!canWriteResult.releaseReturnValue())
+ return { };
+
+ m_headers.set(name, normalizedValue);
+
+ if (m_guard == FetchHeaders::Guard::RequestNoCors)
+ removePrivilegedNoCORSRequestHeaders(m_headers);
+
+ return { };
+}
+
+void FetchHeaders::filterAndFill(const HTTPHeaderMap& headers, Guard guard)
+{
+ for (auto& header : headers) {
+ String normalizedValue = stripLeadingAndTrailingHTTPSpaces(header.value);
+ auto canWriteResult = canWriteHeader(header.key, normalizedValue, header.value, guard);
+ if (canWriteResult.hasException())
+ continue;
+ if (!canWriteResult.releaseReturnValue())
+ continue;
+ if (header.keyAsHTTPHeaderName)
+ m_headers.add(header.keyAsHTTPHeaderName.value(), header.value);
+ else
+ m_headers.add(header.key, header.value);
+ }
+}
+
+std::optional> FetchHeaders::Iterator::next()
+{
+ while (m_currentIndex < m_keys.size()) {
+ auto key = m_keys[m_currentIndex++];
+ auto value = m_headers->m_headers.get(key);
+ if (!value.isNull())
+ return KeyValuePair { WTFMove(key), WTFMove(value) };
+ }
+ return std::nullopt;
+}
+
+FetchHeaders::Iterator::Iterator(FetchHeaders& headers)
+ : m_headers(headers)
+{
+ m_keys.reserveInitialCapacity(headers.m_headers.size());
+ for (auto& header : headers.m_headers)
+ m_keys.uncheckedAppend(header.key.convertToASCIILowercase());
+ std::sort(m_keys.begin(), m_keys.end(), WTF::codePointCompareLessThan);
+}
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/webcore/FetchHeaders.h b/src/javascript/jsc/bindings/webcore/FetchHeaders.h
new file mode 100644
index 0000000000..c6a74880f8
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/FetchHeaders.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2016 Canon Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted, provided that the following conditions
+ * are required to be met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Canon Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ExceptionOr.h"
+#include "HTTPHeaderMap.h"
+#include
+#include
+#include
+
+namespace WebCore {
+
+class FetchHeaders : public RefCounted {
+public:
+ enum class Guard {
+ None,
+ Immutable,
+ Request,
+ RequestNoCors,
+ Response
+ };
+
+ using Init = std::variant>, Vector>>;
+ static ExceptionOr][> create(std::optional&&);
+
+ static Ref create(Guard guard = Guard::None, HTTPHeaderMap&& headers = {}) { return adoptRef(*new FetchHeaders { guard, WTFMove(headers) }); }
+ static Ref create(const FetchHeaders& headers) { return adoptRef(*new FetchHeaders { headers }); }
+
+ ExceptionOr append(const String& name, const String& value);
+ ExceptionOr remove(const String&);
+ ExceptionOr get(const String&) const;
+ ExceptionOr has(const String&) const;
+ ExceptionOr set(const String& name, const String& value);
+
+ ExceptionOr fill(const Init&);
+ ExceptionOr fill(const FetchHeaders&);
+ void filterAndFill(const HTTPHeaderMap&, Guard);
+
+ inline uint32_t size()
+ {
+ return m_headers.size();
+ }
+
+ String fastGet(HTTPHeaderName name) const { return m_headers.get(name); }
+ bool fastHas(HTTPHeaderName name) const { return m_headers.contains(name); }
+ void fastSet(HTTPHeaderName name, const String& value) { m_headers.set(name, value); }
+
+ class Iterator {
+ public:
+ explicit Iterator(FetchHeaders&);
+ std::optional> next();
+
+ private:
+ Ref m_headers;
+ size_t m_currentIndex { 0 };
+ Vector m_keys;
+ };
+ Iterator createIterator() { return Iterator { *this }; }
+
+ void setInternalHeaders(HTTPHeaderMap&& headers) { m_headers = WTFMove(headers); }
+ const HTTPHeaderMap& internalHeaders() const { return m_headers; }
+
+ void setGuard(Guard);
+ Guard guard() const { return m_guard; }
+
+private:
+ FetchHeaders(Guard, HTTPHeaderMap&&);
+ explicit FetchHeaders(const FetchHeaders&);
+
+ Guard m_guard;
+ HTTPHeaderMap m_headers;
+};
+
+inline FetchHeaders::FetchHeaders(Guard guard, HTTPHeaderMap&& headers)
+ : m_guard(guard)
+ , m_headers(WTFMove(headers))
+{
+}
+
+inline FetchHeaders::FetchHeaders(const FetchHeaders& other)
+ : RefCounted()
+ , m_guard(other.m_guard)
+ , m_headers(other.m_headers)
+{
+}
+
+inline void FetchHeaders::setGuard(Guard guard)
+{
+ ASSERT(!m_headers.size());
+ m_guard = guard;
+}
+
+} // namespace WebCore
+
+namespace WTF {
+
+template<> struct EnumTraits {
+ using values = EnumValues<
+ WebCore::FetchHeaders::Guard,
+ WebCore::FetchHeaders::Guard::None,
+ WebCore::FetchHeaders::Guard::Immutable,
+ WebCore::FetchHeaders::Guard::Request,
+ WebCore::FetchHeaders::Guard::RequestNoCors,
+ WebCore::FetchHeaders::Guard::Response>;
+};
+
+}
diff --git a/src/javascript/jsc/bindings/webcore/FetchHeaders.idl b/src/javascript/jsc/bindings/webcore/FetchHeaders.idl
new file mode 100644
index 0000000000..daa0ebb8e9
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/FetchHeaders.idl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Canon Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted, provided that the following conditions
+ * are required to be met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Canon Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+typedef (sequence> or record) HeadersInit;
+
+[
+ Exposed=(Window,Worker),
+ InterfaceName=Headers,
+] interface FetchHeaders {
+ constructor(optional HeadersInit init);
+
+ undefined append(ByteString name, ByteString value);
+ [ImplementedAs=remove] undefined delete(ByteString name);
+ ByteString? get(ByteString name);
+ boolean has(ByteString name);
+ undefined set(ByteString name, ByteString value);
+
+ iterable;
+};
diff --git a/src/javascript/jsc/bindings/webcore/HTTPHeaderField.cpp b/src/javascript/jsc/bindings/webcore/HTTPHeaderField.cpp
new file mode 100644
index 0000000000..a4d101bdd1
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/HTTPHeaderField.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "HTTPHeaderField.h"
+
+namespace WebCore {
+
+namespace RFC7230 {
+
+bool isTokenCharacter(UChar c)
+{
+ return isASCIIAlpha(c) || isASCIIDigit(c)
+ || c == '!' || c == '#' || c == '$'
+ || c == '%' || c == '&' || c == '\''
+ || c == '*' || c == '+' || c == '-'
+ || c == '.' || c == '^' || c == '_'
+ || c == '`' || c == '|' || c == '~';
+}
+
+bool isDelimiter(UChar c)
+{
+ return c == '(' || c == ')' || c == ','
+ || c == '/' || c == ':' || c == ';'
+ || c == '<' || c == '=' || c == '>'
+ || c == '?' || c == '@' || c == '['
+ || c == '\\' || c == ']' || c == '{'
+ || c == '}' || c == '"';
+}
+
+static bool isVisibleCharacter(UChar c)
+{
+ return isTokenCharacter(c) || isDelimiter(c);
+}
+
+bool isWhitespace(UChar c)
+{
+ return c == ' ' || c == '\t';
+}
+
+template
+static bool isInRange(UChar c)
+{
+ return c >= min && c <= max;
+}
+
+static bool isOBSText(UChar c)
+{
+ return isInRange<0x80, 0xFF>(c);
+}
+
+static bool isQuotedTextCharacter(UChar c)
+{
+ return isWhitespace(c)
+ || c == 0x21
+ || isInRange<0x23, 0x5B>(c)
+ || isInRange<0x5D, 0x7E>(c)
+ || isOBSText(c);
+}
+
+bool isQuotedPairSecondOctet(UChar c)
+{
+ return isWhitespace(c)
+ || isVisibleCharacter(c)
+ || isOBSText(c);
+}
+
+bool isCommentText(UChar c)
+{
+ return isWhitespace(c)
+ || isInRange<0x21, 0x27>(c)
+ || isInRange<0x2A, 0x5B>(c)
+ || isInRange<0x5D, 0x7E>(c)
+ || isOBSText(c);
+}
+
+static bool isValidName(StringView name)
+{
+ if (!name.length())
+ return false;
+ for (size_t i = 0; i < name.length(); ++i) {
+ if (!isTokenCharacter(name[i]))
+ return false;
+ }
+ return true;
+}
+
+static bool isValidValue(StringView value)
+{
+ enum class State {
+ OptionalWhitespace,
+ Token,
+ QuotedString,
+ Comment,
+ };
+ State state = State::OptionalWhitespace;
+ size_t commentDepth = 0;
+ bool hadNonWhitespace = false;
+
+ for (size_t i = 0; i < value.length(); ++i) {
+ UChar c = value[i];
+ switch (state) {
+ case State::OptionalWhitespace:
+ if (isWhitespace(c))
+ continue;
+ hadNonWhitespace = true;
+ if (isTokenCharacter(c)) {
+ state = State::Token;
+ continue;
+ }
+ if (c == '"') {
+ state = State::QuotedString;
+ continue;
+ }
+ if (c == '(') {
+ ASSERT(!commentDepth);
+ ++commentDepth;
+ state = State::Comment;
+ continue;
+ }
+ return false;
+
+ case State::Token:
+ if (isTokenCharacter(c))
+ continue;
+ state = State::OptionalWhitespace;
+ continue;
+ case State::QuotedString:
+ if (c == '"') {
+ state = State::OptionalWhitespace;
+ continue;
+ }
+ if (c == '\\') {
+ ++i;
+ if (i == value.length())
+ return false;
+ if (!isQuotedPairSecondOctet(value[i]))
+ return false;
+ continue;
+ }
+ if (!isQuotedTextCharacter(c))
+ return false;
+ continue;
+ case State::Comment:
+ if (c == '(') {
+ ++commentDepth;
+ continue;
+ }
+ if (c == ')') {
+ --commentDepth;
+ if (!commentDepth)
+ state = State::OptionalWhitespace;
+ continue;
+ }
+ if (c == '\\') {
+ ++i;
+ if (i == value.length())
+ return false;
+ if (!isQuotedPairSecondOctet(value[i]))
+ return false;
+ continue;
+ }
+ if (!isCommentText(c))
+ return false;
+ continue;
+ }
+ }
+
+ switch (state) {
+ case State::OptionalWhitespace:
+ case State::Token:
+ return hadNonWhitespace;
+ case State::QuotedString:
+ case State::Comment:
+ // Unclosed comments or quotes are invalid values.
+ break;
+ }
+ return false;
+}
+
+} // namespace RFC7230
+
+std::optional HTTPHeaderField::create(String&& unparsedName, String&& unparsedValue)
+{
+ StringView strippedName = StringView(unparsedName).stripLeadingAndTrailingMatchedCharacters(RFC7230::isWhitespace);
+ StringView strippedValue = StringView(unparsedValue).stripLeadingAndTrailingMatchedCharacters(RFC7230::isWhitespace);
+ if (!RFC7230::isValidName(strippedName) || !RFC7230::isValidValue(strippedValue))
+ return std::nullopt;
+
+ String name = strippedName.length() == unparsedName.length() ? WTFMove(unparsedName) : strippedName.toString();
+ String value = strippedValue.length() == unparsedValue.length() ? WTFMove(unparsedValue) : strippedValue.toString();
+ return {{ WTFMove(name), WTFMove(value) }};
+}
+
+}
diff --git a/src/javascript/jsc/bindings/webcore/HTTPHeaderField.h b/src/javascript/jsc/bindings/webcore/HTTPHeaderField.h
new file mode 100644
index 0000000000..c5fbc1b436
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/HTTPHeaderField.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include
+
+namespace WebCore {
+
+class WEBCORE_EXPORT HTTPHeaderField {
+public:
+ static std::optional create(String&& name, String&& value);
+
+ const String& name() const { return m_name; }
+ const String& value() const { return m_value; }
+
+ template void encode(Encoder&) const;
+ template static std::optional decode(Decoder&);
+
+private:
+ HTTPHeaderField(String&& name, String&& value)
+ : m_name(WTFMove(name))
+ , m_value(WTFMove(value))
+ { }
+ String m_name;
+ String m_value;
+};
+
+template
+void HTTPHeaderField::encode(Encoder& encoder) const
+{
+ encoder << m_name;
+ encoder << m_value;
+}
+
+template
+std::optional HTTPHeaderField::decode(Decoder& decoder)
+{
+ std::optional name;
+ decoder >> name;
+ if (!name)
+ return std::nullopt;
+
+ std::optional value;
+ decoder >> value;
+ if (!value)
+ return std::nullopt;
+
+ return {{ WTFMove(*name), WTFMove(*value) }};
+}
+
+namespace RFC7230 {
+bool isTokenCharacter(UChar);
+bool isWhitespace(UChar);
+bool isCommentText(UChar);
+bool isQuotedPairSecondOctet(UChar);
+bool isDelimiter(UChar);
+} // namespace RFC7230
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/webcore/HTTPHeaderMap.cpp b/src/javascript/jsc/bindings/webcore/HTTPHeaderMap.cpp
new file mode 100644
index 0000000000..bd516cf6c6
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/HTTPHeaderMap.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2022 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "HTTPHeaderMap.h"
+
+#include
+#include
+#include
+
+namespace WebCore {
+
+HTTPHeaderMap::HTTPHeaderMap()
+{
+}
+
+HTTPHeaderMap HTTPHeaderMap::isolatedCopy() const &
+{
+ HTTPHeaderMap map;
+ map.m_commonHeaders = crossThreadCopy(m_commonHeaders);
+ map.m_uncommonHeaders = crossThreadCopy(m_uncommonHeaders);
+ return map;
+}
+
+HTTPHeaderMap HTTPHeaderMap::isolatedCopy() &&
+{
+ HTTPHeaderMap map;
+ map.m_commonHeaders = crossThreadCopy(WTFMove(m_commonHeaders));
+ map.m_uncommonHeaders = crossThreadCopy(WTFMove(m_uncommonHeaders));
+ return map;
+}
+
+String HTTPHeaderMap::get(const String& name) const
+{
+ HTTPHeaderName headerName;
+ if (findHTTPHeaderName(name, headerName))
+ return get(headerName);
+
+ return getUncommonHeader(name);
+}
+
+String HTTPHeaderMap::getUncommonHeader(const String& name) const
+{
+ auto index = m_uncommonHeaders.findIf([&](auto& header) {
+ return equalIgnoringASCIICase(header.key, name);
+ });
+ return index != notFound ? m_uncommonHeaders[index].value : String();
+}
+
+#if USE(CF)
+
+void HTTPHeaderMap::set(CFStringRef name, const String& value)
+{
+ // Fast path: avoid constructing a temporary String in the common header case.
+ if (auto* nameCharacters = CFStringGetCStringPtr(name, kCFStringEncodingASCII)) {
+ unsigned length = CFStringGetLength(name);
+ HTTPHeaderName headerName;
+ if (findHTTPHeaderName(StringView(nameCharacters, length), headerName))
+ set(headerName, value);
+ else
+ setUncommonHeader(String(nameCharacters, length), value);
+
+ return;
+ }
+
+ set(String(name), value);
+}
+
+#endif // USE(CF)
+
+void HTTPHeaderMap::set(const String& name, const String& value)
+{
+ HTTPHeaderName headerName;
+ if (findHTTPHeaderName(name, headerName)) {
+ set(headerName, value);
+ return;
+ }
+
+ setUncommonHeader(name, value);
+}
+
+void HTTPHeaderMap::setUncommonHeader(const String& name, const String& value)
+{
+ auto index = m_uncommonHeaders.findIf([&](auto& header) {
+ return equalIgnoringASCIICase(header.key, name);
+ });
+ if (index == notFound)
+ m_uncommonHeaders.append(UncommonHeader { name, value });
+ else
+ m_uncommonHeaders[index].value = value;
+}
+
+void HTTPHeaderMap::add(const String& name, const String& value)
+{
+ HTTPHeaderName headerName;
+ if (findHTTPHeaderName(name, headerName)) {
+ add(headerName, value);
+ return;
+ }
+ auto index = m_uncommonHeaders.findIf([&](auto& header) {
+ return equalIgnoringASCIICase(header.key, name);
+ });
+ if (index == notFound)
+ m_uncommonHeaders.append(UncommonHeader { name, value });
+ else
+ m_uncommonHeaders[index].value = makeString(m_uncommonHeaders[index].value, ", ", value);
+}
+
+void HTTPHeaderMap::append(const String& name, const String& value)
+{
+ ASSERT(!contains(name));
+
+ HTTPHeaderName headerName;
+ if (findHTTPHeaderName(name, headerName))
+ m_commonHeaders.append(CommonHeader { headerName, value });
+ else
+ m_uncommonHeaders.append(UncommonHeader { name, value });
+}
+
+bool HTTPHeaderMap::addIfNotPresent(HTTPHeaderName headerName, const String& value)
+{
+ if (contains(headerName))
+ return false;
+
+ m_commonHeaders.append(CommonHeader { headerName, value });
+ return true;
+}
+
+bool HTTPHeaderMap::contains(const String& name) const
+{
+ HTTPHeaderName headerName;
+ if (findHTTPHeaderName(name, headerName))
+ return contains(headerName);
+
+ return m_uncommonHeaders.findIf([&](auto& header) {
+ return equalIgnoringASCIICase(header.key, name);
+ }) != notFound;
+}
+
+bool HTTPHeaderMap::remove(const String& name)
+{
+ HTTPHeaderName headerName;
+ if (findHTTPHeaderName(name, headerName))
+ return remove(headerName);
+
+ return m_uncommonHeaders.removeFirstMatching([&](auto& header) {
+ return equalIgnoringASCIICase(header.key, name);
+ });
+}
+
+String HTTPHeaderMap::get(HTTPHeaderName name) const
+{
+ auto index = m_commonHeaders.findIf([&](auto& header) {
+ return header.key == name;
+ });
+ return index != notFound ? m_commonHeaders[index].value : String();
+}
+
+void HTTPHeaderMap::set(HTTPHeaderName name, const String& value)
+{
+ auto index = m_commonHeaders.findIf([&](auto& header) {
+ return header.key == name;
+ });
+ if (index == notFound)
+ m_commonHeaders.append(CommonHeader { name, value });
+ else
+ m_commonHeaders[index].value = value;
+}
+
+bool HTTPHeaderMap::contains(HTTPHeaderName name) const
+{
+ return m_commonHeaders.findIf([&](auto& header) {
+ return header.key == name;
+ }) != notFound;
+}
+
+bool HTTPHeaderMap::remove(HTTPHeaderName name)
+{
+ return m_commonHeaders.removeFirstMatching([&](auto& header) {
+ return header.key == name;
+ });
+}
+
+void HTTPHeaderMap::add(HTTPHeaderName name, const String& value)
+{
+ auto index = m_commonHeaders.findIf([&](auto& header) {
+ return header.key == name;
+ });
+ if (index != notFound)
+ m_commonHeaders[index].value = makeString(m_commonHeaders[index].value, ", ", value);
+ else
+ m_commonHeaders.append(CommonHeader { name, value });
+}
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/webcore/HTTPHeaderMap.h b/src/javascript/jsc/bindings/webcore/HTTPHeaderMap.h
new file mode 100644
index 0000000000..1fe19d3118
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/HTTPHeaderMap.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "HTTPHeaderNames.h"
+#include
+#include
+
+namespace WebCore {
+
+// FIXME: Not every header fits into a map. Notably, multiple Set-Cookie header fields are needed to set multiple cookies.
+
+class HTTPHeaderMap {
+public:
+ struct CommonHeader {
+ HTTPHeaderName key;
+ String value;
+
+ CommonHeader isolatedCopy() const & { return { key , value.isolatedCopy() }; }
+ CommonHeader isolatedCopy() && { return { key , WTFMove(value).isolatedCopy() }; }
+ template void encode(Encoder&) const;
+ template static std::optional decode(Decoder&);
+
+ bool operator==(const CommonHeader& other) const { return key == other.key && value == other.value; }
+ };
+
+ struct UncommonHeader {
+ String key;
+ String value;
+
+ UncommonHeader isolatedCopy() const & { return { key.isolatedCopy() , value.isolatedCopy() }; }
+ UncommonHeader isolatedCopy() && { return { WTFMove(key).isolatedCopy() , WTFMove(value).isolatedCopy() }; }
+ template void encode(Encoder&) const;
+ template static std::optional decode(Decoder&);
+
+ bool operator==(const UncommonHeader& other) const { return key == other.key && value == other.value; }
+ };
+
+ typedef Vector CommonHeadersVector;
+ typedef Vector UncommonHeadersVector;
+
+ class HTTPHeaderMapConstIterator {
+ public:
+ HTTPHeaderMapConstIterator(const HTTPHeaderMap& table, CommonHeadersVector::const_iterator commonHeadersIt, UncommonHeadersVector::const_iterator uncommonHeadersIt)
+ : m_table(table)
+ , m_commonHeadersIt(commonHeadersIt)
+ , m_uncommonHeadersIt(uncommonHeadersIt)
+ {
+ if (!updateKeyValue(m_commonHeadersIt))
+ updateKeyValue(m_uncommonHeadersIt);
+ }
+
+ struct KeyValue {
+ String key;
+ std::optional keyAsHTTPHeaderName;
+ String value;
+ };
+
+ const KeyValue* get() const
+ {
+ ASSERT(*this != m_table.end());
+ return &m_keyValue;
+ }
+ const KeyValue& operator*() const { return *get(); }
+ const KeyValue* operator->() const { return get(); }
+
+ HTTPHeaderMapConstIterator& operator++()
+ {
+ if (m_commonHeadersIt != m_table.m_commonHeaders.end()) {
+ if (updateKeyValue(++m_commonHeadersIt))
+ return *this;
+ } else
+ ++m_uncommonHeadersIt;
+
+ updateKeyValue(m_uncommonHeadersIt);
+ return *this;
+ }
+
+ bool operator!=(const HTTPHeaderMapConstIterator& other) const { return !(*this == other); }
+ bool operator==(const HTTPHeaderMapConstIterator& other) const
+ {
+ return m_commonHeadersIt == other.m_commonHeadersIt && m_uncommonHeadersIt == other.m_uncommonHeadersIt;
+ }
+
+ private:
+ bool updateKeyValue(CommonHeadersVector::const_iterator it)
+ {
+ if (it == m_table.commonHeaders().end())
+ return false;
+ m_keyValue.key = httpHeaderNameString(it->key).toStringWithoutCopying();
+ m_keyValue.keyAsHTTPHeaderName = it->key;
+ m_keyValue.value = it->value;
+ return true;
+ }
+ bool updateKeyValue(UncommonHeadersVector::const_iterator it)
+ {
+ if (it == m_table.uncommonHeaders().end())
+ return false;
+ m_keyValue.key = it->key;
+ m_keyValue.keyAsHTTPHeaderName = std::nullopt;
+ m_keyValue.value = it->value;
+ return true;
+ }
+
+ const HTTPHeaderMap& m_table;
+ CommonHeadersVector::const_iterator m_commonHeadersIt;
+ UncommonHeadersVector::const_iterator m_uncommonHeadersIt;
+ KeyValue m_keyValue;
+ };
+ typedef HTTPHeaderMapConstIterator const_iterator;
+
+ WEBCORE_EXPORT HTTPHeaderMap();
+
+ // Gets a copy of the data suitable for passing to another thread.
+ WEBCORE_EXPORT HTTPHeaderMap isolatedCopy() const &;
+ WEBCORE_EXPORT HTTPHeaderMap isolatedCopy() &&;
+
+ bool isEmpty() const { return m_commonHeaders.isEmpty() && m_uncommonHeaders.isEmpty(); }
+ int size() const { return m_commonHeaders.size() + m_uncommonHeaders.size(); }
+
+ void clear()
+ {
+ m_commonHeaders.clear();
+ m_uncommonHeaders.clear();
+ }
+
+ void shrinkToFit()
+ {
+ m_commonHeaders.shrinkToFit();
+ m_uncommonHeaders.shrinkToFit();
+ }
+
+ WEBCORE_EXPORT String get(const String& name) const;
+ WEBCORE_EXPORT void set(const String& name, const String& value);
+ WEBCORE_EXPORT void add(const String& name, const String& value);
+ WEBCORE_EXPORT void append(const String& name, const String& value);
+ WEBCORE_EXPORT bool contains(const String&) const;
+ WEBCORE_EXPORT bool remove(const String&);
+
+#if USE(CF)
+ void set(CFStringRef name, const String& value);
+#ifdef __OBJC__
+ void set(NSString *name, const String& value) { set((__bridge CFStringRef)name, value); }
+#endif
+#endif
+
+ WEBCORE_EXPORT String get(HTTPHeaderName) const;
+ void set(HTTPHeaderName, const String& value);
+ void add(HTTPHeaderName, const String& value);
+ bool addIfNotPresent(HTTPHeaderName, const String&);
+ WEBCORE_EXPORT bool contains(HTTPHeaderName) const;
+ WEBCORE_EXPORT bool remove(HTTPHeaderName);
+
+ // Instead of passing a string literal to any of these functions, just use a HTTPHeaderName instead.
+ template String get(const char (&)[length]) const = delete;
+ template void set(const char (&)[length], const String&) = delete;
+ template bool contains(const char (&)[length]) = delete;
+ template bool remove(const char (&)[length]) = delete;
+
+ const CommonHeadersVector& commonHeaders() const { return m_commonHeaders; }
+ const UncommonHeadersVector& uncommonHeaders() const { return m_uncommonHeaders; }
+ CommonHeadersVector& commonHeaders() { return m_commonHeaders; }
+ UncommonHeadersVector& uncommonHeaders() { return m_uncommonHeaders; }
+
+ const_iterator begin() const { return const_iterator(*this, m_commonHeaders.begin(), m_uncommonHeaders.begin()); }
+ const_iterator end() const { return const_iterator(*this, m_commonHeaders.end(), m_uncommonHeaders.end()); }
+
+ friend bool operator==(const HTTPHeaderMap& a, const HTTPHeaderMap& b)
+ {
+ if (a.m_commonHeaders.size() != b.m_commonHeaders.size() || a.m_uncommonHeaders.size() != b.m_uncommonHeaders.size())
+ return false;
+ for (auto& commonHeader : a.m_commonHeaders) {
+ if (b.get(commonHeader.key) != commonHeader.value)
+ return false;
+ }
+ for (auto& uncommonHeader : a.m_uncommonHeaders) {
+ if (b.getUncommonHeader(uncommonHeader.key) != uncommonHeader.value)
+ return false;
+ }
+ return true;
+ }
+
+ friend bool operator!=(const HTTPHeaderMap& a, const HTTPHeaderMap& b)
+ {
+ return !(a == b);
+ }
+
+ template void encode(Encoder&) const;
+ template static WARN_UNUSED_RETURN bool decode(Decoder&, HTTPHeaderMap&);
+
+private:
+ void setUncommonHeader(const String& name, const String& value);
+ WEBCORE_EXPORT String getUncommonHeader(const String& name) const;
+
+ CommonHeadersVector m_commonHeaders;
+ UncommonHeadersVector m_uncommonHeaders;
+};
+
+template
+void HTTPHeaderMap::CommonHeader::encode(Encoder& encoder) const
+{
+ encoder << key;
+ encoder << value;
+}
+
+template
+auto HTTPHeaderMap::CommonHeader::decode(Decoder& decoder) -> std::optional
+{
+ HTTPHeaderName name;
+ if (!decoder.decode(name))
+ return std::nullopt;
+ String value;
+ if (!decoder.decode(value))
+ return std::nullopt;
+
+ return CommonHeader { name, WTFMove(value) };
+}
+
+template
+void HTTPHeaderMap::UncommonHeader::encode(Encoder& encoder) const
+{
+ encoder << key;
+ encoder << value;
+}
+
+template
+auto HTTPHeaderMap::UncommonHeader::decode(Decoder& decoder) -> std::optional
+{
+ String name;
+ if (!decoder.decode(name))
+ return std::nullopt;
+ String value;
+ if (!decoder.decode(value))
+ return std::nullopt;
+
+ return UncommonHeader { WTFMove(name), WTFMove(value) };
+}
+
+template
+void HTTPHeaderMap::encode(Encoder& encoder) const
+{
+ encoder << m_commonHeaders;
+ encoder << m_uncommonHeaders;
+}
+
+template
+bool HTTPHeaderMap::decode(Decoder& decoder, HTTPHeaderMap& headerMap)
+{
+ if (!decoder.decode(headerMap.m_commonHeaders))
+ return false;
+
+ if (!decoder.decode(headerMap.m_uncommonHeaders))
+ return false;
+
+ return true;
+}
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/webcore/HTTPHeaderNames.cpp b/src/javascript/jsc/bindings/webcore/HTTPHeaderNames.cpp
new file mode 100644
index 0000000000..2846f15e54
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/HTTPHeaderNames.cpp
@@ -0,0 +1,718 @@
+/* C++ code produced by gperf version 3.0.3 */
+/* Command-line: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/gperf --key-positions='*' -D -n -s 2 --output-file=HTTPHeaderNames.cpp HTTPHeaderNames.gperf */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to ."
+#endif
+
+#line 2 "HTTPHeaderNames.gperf"
+
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/// This file is generated by create-http-header-name-table, do not edit.
+
+#include "config.h"
+#include "HTTPHeaderNames.h"
+
+#include
+
+IGNORE_WARNINGS_BEGIN("implicit-fallthrough")
+
+// Older versions of gperf like to use the `register` keyword.
+#define register
+
+namespace WebCore {
+
+static const struct HeaderNameString {
+ const char* const name;
+ unsigned length;
+} headerNameStrings[] = {
+ { "Accept", 6 },
+ { "Accept-Charset", 14 },
+ { "Accept-Encoding", 15 },
+ { "Accept-Language", 15 },
+ { "Accept-Ranges", 13 },
+ { "Access-Control-Allow-Credentials", 32 },
+ { "Access-Control-Allow-Headers", 28 },
+ { "Access-Control-Allow-Methods", 28 },
+ { "Access-Control-Allow-Origin", 27 },
+ { "Access-Control-Expose-Headers", 29 },
+ { "Access-Control-Max-Age", 22 },
+ { "Access-Control-Request-Headers", 30 },
+ { "Access-Control-Request-Method", 29 },
+ { "Age", 3 },
+ { "Authorization", 13 },
+ { "Cache-Control", 13 },
+ { "Connection", 10 },
+ { "Content-Disposition", 19 },
+ { "Content-Encoding", 16 },
+ { "Content-Language", 16 },
+ { "Content-Length", 14 },
+ { "Content-Location", 16 },
+ { "Content-Range", 13 },
+ { "Content-Security-Policy", 23 },
+ { "Content-Security-Policy-Report-Only", 35 },
+ { "Content-Type", 12 },
+ { "Cookie", 6 },
+ { "Cookie2", 7 },
+ { "Cross-Origin-Embedder-Policy", 28 },
+ { "Cross-Origin-Embedder-Policy-Report-Only", 40 },
+ { "Cross-Origin-Opener-Policy", 26 },
+ { "Cross-Origin-Opener-Policy-Report-Only", 38 },
+ { "Cross-Origin-Resource-Policy", 28 },
+ { "DNT", 3 },
+ { "Date", 4 },
+ { "Default-Style", 13 },
+ { "ETag", 4 },
+ { "Expect", 6 },
+ { "Expires", 7 },
+ { "Host", 4 },
+ { "Icy-MetaInt", 11 },
+ { "Icy-Metadata", 12 },
+ { "If-Match", 8 },
+ { "If-Modified-Since", 17 },
+ { "If-None-Match", 13 },
+ { "If-Range", 8 },
+ { "If-Unmodified-Since", 19 },
+ { "Keep-Alive", 10 },
+ { "Last-Event-ID", 13 },
+ { "Last-Modified", 13 },
+ { "Link", 4 },
+ { "Location", 8 },
+ { "Origin", 6 },
+ { "Ping-From", 9 },
+ { "Ping-To", 7 },
+ { "Pragma", 6 },
+ { "Proxy-Authorization", 19 },
+ { "Purpose", 7 },
+ { "Range", 5 },
+ { "Referer", 7 },
+ { "Referrer-Policy", 15 },
+ { "Refresh", 7 },
+ { "Report-To", 9 },
+ { "Sec-Fetch-Dest", 14 },
+ { "Sec-Fetch-Mode", 14 },
+ { "Sec-WebSocket-Accept", 20 },
+ { "Sec-WebSocket-Extensions", 24 },
+ { "Sec-WebSocket-Key", 17 },
+ { "Sec-WebSocket-Protocol", 22 },
+ { "Sec-WebSocket-Version", 21 },
+ { "Server-Timing", 13 },
+ { "Service-Worker", 14 },
+ { "Service-Worker-Allowed", 22 },
+ { "Service-Worker-Navigation-Preload", 33 },
+ { "Set-Cookie", 10 },
+ { "Set-Cookie2", 11 },
+ { "SourceMap", 9 },
+ { "TE", 2 },
+ { "Timing-Allow-Origin", 19 },
+ { "Trailer", 7 },
+ { "Transfer-Encoding", 17 },
+ { "Upgrade", 7 },
+ { "Upgrade-Insecure-Requests", 25 },
+ { "User-Agent", 10 },
+ { "Vary", 4 },
+ { "Via", 3 },
+ { "X-Content-Type-Options", 22 },
+ { "X-DNS-Prefetch-Control", 22 },
+ { "X-Frame-Options", 15 },
+ { "X-SourceMap", 11 },
+ { "X-Temp-Tablet", 13 },
+ { "X-XSS-Protection", 16 },
+};
+
+
+#line 149 "HTTPHeaderNames.gperf"
+struct HeaderNameHashEntry {
+ const char* name;
+ HTTPHeaderName headerName;
+};
+enum
+ {
+ TOTAL_KEYWORDS = 92,
+ MIN_WORD_LENGTH = 2,
+ MAX_WORD_LENGTH = 40,
+ MIN_HASH_VALUE = 5,
+ MAX_HASH_VALUE = 815
+ };
+
+/* maximum key range = 811, duplicates = 0 */
+
+#ifndef GPERF_DOWNCASE
+#define GPERF_DOWNCASE 1
+static unsigned char gperf_downcase[256] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
+ 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
+ 255
+ };
+#endif
+
+#ifndef GPERF_CASE_STRNCMP
+#define GPERF_CASE_STRNCMP 1
+static int
+gperf_case_strncmp (register const char *s1, register const char *s2, register unsigned int n)
+{
+ for (; n > 0;)
+ {
+ unsigned char c1 = gperf_downcase[(unsigned char)*s1++];
+ unsigned char c2 = gperf_downcase[(unsigned char)*s2++];
+ if (c1 != 0 && c1 == c2)
+ {
+ n--;
+ continue;
+ }
+ return (int)c1 - (int)c2;
+ }
+ return 0;
+}
+#endif
+
+class HTTPHeaderNamesHash
+{
+private:
+ static inline unsigned int header_name_hash_function (const char *str, unsigned int len);
+public:
+ static const struct HeaderNameHashEntry *findHeaderNameImpl (const char *str, unsigned int len);
+};
+
+inline unsigned int
+HTTPHeaderNamesHash::header_name_hash_function (register const char *str, register unsigned int len)
+{
+ static const unsigned short asso_values[] =
+ {
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 0, 816, 816, 816, 816,
+ 5, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 0, 40, 0, 115, 0,
+ 120, 10, 155, 5, 816, 4, 45, 155, 5, 0,
+ 30, 0, 5, 60, 5, 5, 135, 55, 50, 15,
+ 60, 816, 816, 816, 816, 816, 816, 0, 40, 0,
+ 115, 0, 120, 10, 155, 5, 816, 4, 45, 155,
+ 5, 0, 30, 0, 5, 60, 5, 5, 135, 55,
+ 50, 15, 60, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816, 816, 816, 816, 816,
+ 816, 816, 816, 816, 816, 816
+ };
+ register unsigned int hval = 0;
+
+ switch (len)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[39]];
+ /*FALLTHROUGH*/
+ case 39:
+ hval += asso_values[(unsigned char)str[38]];
+ /*FALLTHROUGH*/
+ case 38:
+ hval += asso_values[(unsigned char)str[37]];
+ /*FALLTHROUGH*/
+ case 37:
+ hval += asso_values[(unsigned char)str[36]];
+ /*FALLTHROUGH*/
+ case 36:
+ hval += asso_values[(unsigned char)str[35]];
+ /*FALLTHROUGH*/
+ case 35:
+ hval += asso_values[(unsigned char)str[34]];
+ /*FALLTHROUGH*/
+ case 34:
+ hval += asso_values[(unsigned char)str[33]];
+ /*FALLTHROUGH*/
+ case 33:
+ hval += asso_values[(unsigned char)str[32]];
+ /*FALLTHROUGH*/
+ case 32:
+ hval += asso_values[(unsigned char)str[31]];
+ /*FALLTHROUGH*/
+ case 31:
+ hval += asso_values[(unsigned char)str[30]];
+ /*FALLTHROUGH*/
+ case 30:
+ hval += asso_values[(unsigned char)str[29]];
+ /*FALLTHROUGH*/
+ case 29:
+ hval += asso_values[(unsigned char)str[28]];
+ /*FALLTHROUGH*/
+ case 28:
+ hval += asso_values[(unsigned char)str[27]];
+ /*FALLTHROUGH*/
+ case 27:
+ hval += asso_values[(unsigned char)str[26]];
+ /*FALLTHROUGH*/
+ case 26:
+ hval += asso_values[(unsigned char)str[25]];
+ /*FALLTHROUGH*/
+ case 25:
+ hval += asso_values[(unsigned char)str[24]];
+ /*FALLTHROUGH*/
+ case 24:
+ hval += asso_values[(unsigned char)str[23]];
+ /*FALLTHROUGH*/
+ case 23:
+ hval += asso_values[(unsigned char)str[22]];
+ /*FALLTHROUGH*/
+ case 22:
+ hval += asso_values[(unsigned char)str[21]];
+ /*FALLTHROUGH*/
+ case 21:
+ hval += asso_values[(unsigned char)str[20]];
+ /*FALLTHROUGH*/
+ case 20:
+ hval += asso_values[(unsigned char)str[19]];
+ /*FALLTHROUGH*/
+ case 19:
+ hval += asso_values[(unsigned char)str[18]];
+ /*FALLTHROUGH*/
+ case 18:
+ hval += asso_values[(unsigned char)str[17]];
+ /*FALLTHROUGH*/
+ case 17:
+ hval += asso_values[(unsigned char)str[16]];
+ /*FALLTHROUGH*/
+ case 16:
+ hval += asso_values[(unsigned char)str[15]];
+ /*FALLTHROUGH*/
+ case 15:
+ hval += asso_values[(unsigned char)str[14]];
+ /*FALLTHROUGH*/
+ case 14:
+ hval += asso_values[(unsigned char)str[13]];
+ /*FALLTHROUGH*/
+ case 13:
+ hval += asso_values[(unsigned char)str[12]];
+ /*FALLTHROUGH*/
+ case 12:
+ hval += asso_values[(unsigned char)str[11]];
+ /*FALLTHROUGH*/
+ case 11:
+ hval += asso_values[(unsigned char)str[10]];
+ /*FALLTHROUGH*/
+ case 10:
+ hval += asso_values[(unsigned char)str[9]];
+ /*FALLTHROUGH*/
+ case 9:
+ hval += asso_values[(unsigned char)str[8]];
+ /*FALLTHROUGH*/
+ case 8:
+ hval += asso_values[(unsigned char)str[7]];
+ /*FALLTHROUGH*/
+ case 7:
+ hval += asso_values[(unsigned char)str[6]];
+ /*FALLTHROUGH*/
+ case 6:
+ hval += asso_values[(unsigned char)str[5]];
+ /*FALLTHROUGH*/
+ case 5:
+ hval += asso_values[(unsigned char)str[4]];
+ /*FALLTHROUGH*/
+ case 4:
+ hval += asso_values[(unsigned char)str[3]];
+ /*FALLTHROUGH*/
+ case 3:
+ hval += asso_values[(unsigned char)str[2]];
+ /*FALLTHROUGH*/
+ case 2:
+ hval += asso_values[(unsigned char)str[1]];
+ /*FALLTHROUGH*/
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return hval;
+}
+
+static const struct HeaderNameHashEntry header_name_wordlist[] =
+ {
+#line 236 "HTTPHeaderNames.gperf"
+ {"TE", HTTPHeaderName::TE},
+#line 185 "HTTPHeaderNames.gperf"
+ {"Cookie", HTTPHeaderName::Cookie},
+#line 172 "HTTPHeaderNames.gperf"
+ {"Age", HTTPHeaderName::Age},
+#line 186 "HTTPHeaderNames.gperf"
+ {"Cookie2", HTTPHeaderName::Cookie2},
+#line 195 "HTTPHeaderNames.gperf"
+ {"ETag", HTTPHeaderName::ETag},
+#line 217 "HTTPHeaderNames.gperf"
+ {"Range", HTTPHeaderName::Range},
+#line 175 "HTTPHeaderNames.gperf"
+ {"Connection", HTTPHeaderName::Connection},
+#line 211 "HTTPHeaderNames.gperf"
+ {"Origin", HTTPHeaderName::Origin},
+#line 159 "HTTPHeaderNames.gperf"
+ {"Accept", HTTPHeaderName::Accept},
+#line 181 "HTTPHeaderNames.gperf"
+ {"Content-Range", HTTPHeaderName::ContentRange},
+#line 221 "HTTPHeaderNames.gperf"
+ {"Report-To", HTTPHeaderName::ReportTo},
+#line 213 "HTTPHeaderNames.gperf"
+ {"Ping-To", HTTPHeaderName::PingTo},
+#line 209 "HTTPHeaderNames.gperf"
+ {"Link", HTTPHeaderName::Link},
+#line 210 "HTTPHeaderNames.gperf"
+ {"Location", HTTPHeaderName::Location},
+#line 238 "HTTPHeaderNames.gperf"
+ {"Trailer", HTTPHeaderName::Trailer},
+#line 184 "HTTPHeaderNames.gperf"
+ {"Content-Type", HTTPHeaderName::ContentType},
+#line 233 "HTTPHeaderNames.gperf"
+ {"Set-Cookie", HTTPHeaderName::SetCookie},
+#line 234 "HTTPHeaderNames.gperf"
+ {"Set-Cookie2", HTTPHeaderName::SetCookie2},
+#line 180 "HTTPHeaderNames.gperf"
+ {"Content-Location", HTTPHeaderName::ContentLocation},
+#line 196 "HTTPHeaderNames.gperf"
+ {"Expect", HTTPHeaderName::Expect},
+#line 242 "HTTPHeaderNames.gperf"
+ {"User-Agent", HTTPHeaderName::UserAgent},
+#line 178 "HTTPHeaderNames.gperf"
+ {"Content-Language", HTTPHeaderName::ContentLanguage},
+#line 162 "HTTPHeaderNames.gperf"
+ {"Accept-Language", HTTPHeaderName::AcceptLanguage},
+#line 163 "HTTPHeaderNames.gperf"
+ {"Accept-Ranges", HTTPHeaderName::AcceptRanges},
+#line 193 "HTTPHeaderNames.gperf"
+ {"Date", HTTPHeaderName::Date},
+#line 192 "HTTPHeaderNames.gperf"
+ {"DNT", HTTPHeaderName::DNT},
+#line 216 "HTTPHeaderNames.gperf"
+ {"Purpose", HTTPHeaderName::Purpose},
+#line 218 "HTTPHeaderNames.gperf"
+ {"Referer", HTTPHeaderName::Referer},
+#line 244 "HTTPHeaderNames.gperf"
+ {"Via", HTTPHeaderName::Via},
+#line 204 "HTTPHeaderNames.gperf"
+ {"If-Range", HTTPHeaderName::IfRange},
+#line 197 "HTTPHeaderNames.gperf"
+ {"Expires", HTTPHeaderName::Expires},
+#line 243 "HTTPHeaderNames.gperf"
+ {"Vary", HTTPHeaderName::Vary},
+#line 177 "HTTPHeaderNames.gperf"
+ {"Content-Encoding", HTTPHeaderName::ContentEncoding},
+#line 240 "HTTPHeaderNames.gperf"
+ {"Upgrade", HTTPHeaderName::Upgrade},
+#line 161 "HTTPHeaderNames.gperf"
+ {"Accept-Encoding", HTTPHeaderName::AcceptEncoding},
+#line 199 "HTTPHeaderNames.gperf"
+ {"Icy-MetaInt", HTTPHeaderName::IcyMetaInt},
+#line 214 "HTTPHeaderNames.gperf"
+ {"Pragma", HTTPHeaderName::Pragma},
+#line 182 "HTTPHeaderNames.gperf"
+ {"Content-Security-Policy", HTTPHeaderName::ContentSecurityPolicy},
+#line 174 "HTTPHeaderNames.gperf"
+ {"Cache-Control", HTTPHeaderName::CacheControl},
+#line 206 "HTTPHeaderNames.gperf"
+ {"Keep-Alive", HTTPHeaderName::KeepAlive},
+#line 198 "HTTPHeaderNames.gperf"
+ {"Host", HTTPHeaderName::Host},
+#line 245 "HTTPHeaderNames.gperf"
+ {"X-Content-Type-Options", HTTPHeaderName::XContentTypeOptions},
+#line 219 "HTTPHeaderNames.gperf"
+ {"Referrer-Policy", HTTPHeaderName::ReferrerPolicy},
+#line 179 "HTTPHeaderNames.gperf"
+ {"Content-Length", HTTPHeaderName::ContentLength},
+#line 226 "HTTPHeaderNames.gperf"
+ {"Sec-WebSocket-Key", HTTPHeaderName::SecWebSocketKey},
+#line 173 "HTTPHeaderNames.gperf"
+ {"Authorization", HTTPHeaderName::Authorization},
+#line 235 "HTTPHeaderNames.gperf"
+ {"SourceMap", HTTPHeaderName::SourceMap},
+#line 224 "HTTPHeaderNames.gperf"
+ {"Sec-WebSocket-Accept", HTTPHeaderName::SecWebSocketAccept},
+#line 160 "HTTPHeaderNames.gperf"
+ {"Accept-Charset", HTTPHeaderName::AcceptCharset},
+#line 230 "HTTPHeaderNames.gperf"
+ {"Service-Worker", HTTPHeaderName::ServiceWorker},
+#line 250 "HTTPHeaderNames.gperf"
+ {"X-XSS-Protection", HTTPHeaderName::XXSSProtection},
+#line 189 "HTTPHeaderNames.gperf"
+ {"Cross-Origin-Opener-Policy", HTTPHeaderName::CrossOriginOpenerPolicy},
+#line 200 "HTTPHeaderNames.gperf"
+ {"Icy-Metadata", HTTPHeaderName::IcyMetadata},
+#line 248 "HTTPHeaderNames.gperf"
+ {"X-SourceMap", HTTPHeaderName::XSourceMap},
+#line 227 "HTTPHeaderNames.gperf"
+ {"Sec-WebSocket-Protocol", HTTPHeaderName::SecWebSocketProtocol},
+#line 176 "HTTPHeaderNames.gperf"
+ {"Content-Disposition", HTTPHeaderName::ContentDisposition},
+#line 183 "HTTPHeaderNames.gperf"
+ {"Content-Security-Policy-Report-Only", HTTPHeaderName::ContentSecurityPolicyReportOnly},
+#line 191 "HTTPHeaderNames.gperf"
+ {"Cross-Origin-Resource-Policy", HTTPHeaderName::CrossOriginResourcePolicy},
+#line 212 "HTTPHeaderNames.gperf"
+ {"Ping-From", HTTPHeaderName::PingFrom},
+#line 249 "HTTPHeaderNames.gperf"
+ {"X-Temp-Tablet", HTTPHeaderName::XTempTablet},
+#line 239 "HTTPHeaderNames.gperf"
+ {"Transfer-Encoding", HTTPHeaderName::TransferEncoding},
+#line 220 "HTTPHeaderNames.gperf"
+ {"Refresh", HTTPHeaderName::Refresh},
+#line 215 "HTTPHeaderNames.gperf"
+ {"Proxy-Authorization", HTTPHeaderName::ProxyAuthorization},
+#line 167 "HTTPHeaderNames.gperf"
+ {"Access-Control-Allow-Origin", HTTPHeaderName::AccessControlAllowOrigin},
+#line 237 "HTTPHeaderNames.gperf"
+ {"Timing-Allow-Origin", HTTPHeaderName::TimingAllowOrigin},
+#line 207 "HTTPHeaderNames.gperf"
+ {"Last-Event-ID", HTTPHeaderName::LastEventID},
+#line 241 "HTTPHeaderNames.gperf"
+ {"Upgrade-Insecure-Requests", HTTPHeaderName::UpgradeInsecureRequests},
+#line 229 "HTTPHeaderNames.gperf"
+ {"Server-Timing", HTTPHeaderName::ServerTiming},
+#line 169 "HTTPHeaderNames.gperf"
+ {"Access-Control-Max-Age", HTTPHeaderName::AccessControlMaxAge},
+#line 190 "HTTPHeaderNames.gperf"
+ {"Cross-Origin-Opener-Policy-Report-Only", HTTPHeaderName::CrossOriginOpenerPolicyReportOnly},
+#line 225 "HTTPHeaderNames.gperf"
+ {"Sec-WebSocket-Extensions", HTTPHeaderName::SecWebSocketExtensions},
+#line 194 "HTTPHeaderNames.gperf"
+ {"Default-Style", HTTPHeaderName::DefaultStyle},
+#line 228 "HTTPHeaderNames.gperf"
+ {"Sec-WebSocket-Version", HTTPHeaderName::SecWebSocketVersion},
+#line 247 "HTTPHeaderNames.gperf"
+ {"X-Frame-Options", HTTPHeaderName::XFrameOptions},
+#line 201 "HTTPHeaderNames.gperf"
+ {"If-Match", HTTPHeaderName::IfMatch},
+#line 203 "HTTPHeaderNames.gperf"
+ {"If-None-Match", HTTPHeaderName::IfNoneMatch},
+#line 222 "HTTPHeaderNames.gperf"
+ {"Sec-Fetch-Dest", HTTPHeaderName::SecFetchDest},
+#line 231 "HTTPHeaderNames.gperf"
+ {"Service-Worker-Allowed", HTTPHeaderName::ServiceWorkerAllowed},
+#line 164 "HTTPHeaderNames.gperf"
+ {"Access-Control-Allow-Credentials", HTTPHeaderName::AccessControlAllowCredentials},
+#line 170 "HTTPHeaderNames.gperf"
+ {"Access-Control-Request-Headers", HTTPHeaderName::AccessControlRequestHeaders},
+#line 246 "HTTPHeaderNames.gperf"
+ {"X-DNS-Prefetch-Control", HTTPHeaderName::XDNSPrefetchControl},
+#line 223 "HTTPHeaderNames.gperf"
+ {"Sec-Fetch-Mode", HTTPHeaderName::SecFetchMode},
+#line 208 "HTTPHeaderNames.gperf"
+ {"Last-Modified", HTTPHeaderName::LastModified},
+#line 232 "HTTPHeaderNames.gperf"
+ {"Service-Worker-Navigation-Preload", HTTPHeaderName::ServiceWorkerNavigationPreload},
+#line 168 "HTTPHeaderNames.gperf"
+ {"Access-Control-Expose-Headers", HTTPHeaderName::AccessControlExposeHeaders},
+#line 165 "HTTPHeaderNames.gperf"
+ {"Access-Control-Allow-Headers", HTTPHeaderName::AccessControlAllowHeaders},
+#line 187 "HTTPHeaderNames.gperf"
+ {"Cross-Origin-Embedder-Policy", HTTPHeaderName::CrossOriginEmbedderPolicy},
+#line 171 "HTTPHeaderNames.gperf"
+ {"Access-Control-Request-Method", HTTPHeaderName::AccessControlRequestMethod},
+#line 202 "HTTPHeaderNames.gperf"
+ {"If-Modified-Since", HTTPHeaderName::IfModifiedSince},
+#line 205 "HTTPHeaderNames.gperf"
+ {"If-Unmodified-Since", HTTPHeaderName::IfUnmodifiedSince},
+#line 188 "HTTPHeaderNames.gperf"
+ {"Cross-Origin-Embedder-Policy-Report-Only", HTTPHeaderName::CrossOriginEmbedderPolicyReportOnly},
+#line 166 "HTTPHeaderNames.gperf"
+ {"Access-Control-Allow-Methods", HTTPHeaderName::AccessControlAllowMethods}
+ };
+
+static const signed char lookup[] =
+ {
+ -1, -1, -1, -1, -1, 0, -1, -1, -1, 1, 2, -1, -1, -1,
+ 3, 4, -1, -1, -1, -1, 5, -1, -1, -1, -1, 6, -1, -1,
+ -1, -1, 7, -1, -1, -1, -1, 8, -1, -1, -1, -1, 9, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, 11,
+ -1, -1, -1, 12, 13, -1, -1, -1, -1, 14, -1, -1, -1, -1,
+ 15, -1, -1, -1, 16, -1, -1, -1, -1, 17, 18, -1, -1, -1,
+ -1, 19, -1, -1, -1, -1, 20, -1, -1, -1, -1, 21, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
+ -1, -1, -1, 23, -1, -1, -1, -1, 24, -1, -1, -1, -1, 25,
+ -1, -1, -1, -1, 26, -1, -1, -1, -1, 27, -1, -1, -1, -1,
+ 28, -1, -1, -1, -1, 29, -1, -1, -1, -1, 30, -1, -1, -1,
+ -1, 31, -1, -1, -1, -1, 32, -1, -1, -1, -1, 33, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35,
+ -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 37, -1, -1, -1, -1, 38, -1, -1, -1, 39, 40, -1, -1, -1,
+ -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1,
+ -1, -1, 43, -1, -1, 44, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, 46, -1, -1, -1, 47, 48, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 49, 50, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 51, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 52, -1, -1, -1, -1, 53, -1, -1,
+ -1, 54, 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1,
+ -1, -1, -1, 57, -1, -1, -1, -1, 58, -1, -1, -1, -1, 59,
+ -1, -1, -1, -1, 60, -1, -1, -1, -1, 61, -1, -1, -1, -1,
+ 62, -1, -1, -1, -1, 63, -1, -1, -1, -1, 64, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, -1, -1,
+ -1, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, 67, -1,
+ -1, -1, -1, 68, -1, -1, -1, -1, 69, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 70, 71, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 72, 73, -1, -1, -1, -1, 74, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 75, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 77, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 78, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 79, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 80, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 82, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 83, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 84, -1, -1,
+ -1, -1, 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 86, -1, -1, -1, -1, 87,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 88, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 89, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 90, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 91
+ };
+
+const struct HeaderNameHashEntry *
+HTTPHeaderNamesHash::findHeaderNameImpl (register const char *str, register unsigned int len)
+{
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ unsigned int key = header_name_hash_function (str, len);
+
+ if (key <= MAX_HASH_VALUE)
+ {
+ register int index = lookup[key];
+
+ if (index >= 0)
+ {
+ register const char *s = header_name_wordlist[index].name;
+
+ if ((((unsigned char)*str ^ (unsigned char)*s) & ~32) == 0 && !gperf_case_strncmp (str, s, len) && s[len] == '\0')
+ return &header_name_wordlist[index];
+ }
+ }
+ }
+ return 0;
+}
+#line 251 "HTTPHeaderNames.gperf"
+
+bool findHTTPHeaderName(StringView stringView, HTTPHeaderName& headerName)
+{
+ unsigned length = stringView.length();
+ if (length > maxHTTPHeaderNameLength || length < minHTTPHeaderNameLength)
+ return false;
+
+ if (stringView.is8Bit()) {
+ if (auto nameAndString = HTTPHeaderNamesHash::findHeaderNameImpl(reinterpret_cast(stringView.characters8()), length)) {
+ headerName = nameAndString->headerName;
+ return true;
+ }
+ } else {
+ LChar characters[maxHTTPHeaderNameLength];
+ for (unsigned i = 0; i < length; ++i) {
+ UChar character = stringView.characters16()[i];
+ if (!isASCII(character))
+ return false;
+
+ characters[i] = static_cast(character);
+ }
+
+ if (auto nameAndString = HTTPHeaderNamesHash::findHeaderNameImpl(reinterpret_cast(characters), length)) {
+ headerName = nameAndString->headerName;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+StringView httpHeaderNameString(HTTPHeaderName headerName)
+{
+ ASSERT(static_cast(headerName) < numHTTPHeaderNames);
+
+ const auto& name = headerNameStrings[static_cast(headerName)];
+
+ return StringView { reinterpret_cast(name.name), static_cast(name.length) };
+}
+
+} // namespace WebCore
+
+#if defined(__clang__)
+IGNORE_WARNINGS_END
+#endif
diff --git a/src/javascript/jsc/bindings/webcore/HTTPHeaderNames.gperf b/src/javascript/jsc/bindings/webcore/HTTPHeaderNames.gperf
new file mode 100644
index 0000000000..66a4b24e86
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/HTTPHeaderNames.gperf
@@ -0,0 +1,295 @@
+
+%{
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/// This file is generated by create-http-header-name-table, do not edit.
+
+#include "config.h"
+#include "HTTPHeaderNames.h"
+
+#include
+
+IGNORE_WARNINGS_BEGIN("implicit-fallthrough")
+
+// Older versions of gperf like to use the `register` keyword.
+#define register
+
+namespace WebCore {
+
+static const struct HeaderNameString {
+ const char* const name;
+ unsigned length;
+} headerNameStrings[] = {
+ { "Accept", 6 },
+ { "Accept-Charset", 14 },
+ { "Accept-Encoding", 15 },
+ { "Accept-Language", 15 },
+ { "Accept-Ranges", 13 },
+ { "Access-Control-Allow-Credentials", 32 },
+ { "Access-Control-Allow-Headers", 28 },
+ { "Access-Control-Allow-Methods", 28 },
+ { "Access-Control-Allow-Origin", 27 },
+ { "Access-Control-Expose-Headers", 29 },
+ { "Access-Control-Max-Age", 22 },
+ { "Access-Control-Request-Headers", 30 },
+ { "Access-Control-Request-Method", 29 },
+ { "Age", 3 },
+ { "Authorization", 13 },
+ { "Cache-Control", 13 },
+ { "Connection", 10 },
+ { "Content-Disposition", 19 },
+ { "Content-Encoding", 16 },
+ { "Content-Language", 16 },
+ { "Content-Length", 14 },
+ { "Content-Location", 16 },
+ { "Content-Range", 13 },
+ { "Content-Security-Policy", 23 },
+ { "Content-Security-Policy-Report-Only", 35 },
+ { "Content-Type", 12 },
+ { "Cookie", 6 },
+ { "Cookie2", 7 },
+ { "Cross-Origin-Embedder-Policy", 28 },
+ { "Cross-Origin-Embedder-Policy-Report-Only", 40 },
+ { "Cross-Origin-Opener-Policy", 26 },
+ { "Cross-Origin-Opener-Policy-Report-Only", 38 },
+ { "Cross-Origin-Resource-Policy", 28 },
+ { "DNT", 3 },
+ { "Date", 4 },
+ { "Default-Style", 13 },
+ { "ETag", 4 },
+ { "Expect", 6 },
+ { "Expires", 7 },
+ { "Host", 4 },
+ { "Icy-MetaInt", 11 },
+ { "Icy-Metadata", 12 },
+ { "If-Match", 8 },
+ { "If-Modified-Since", 17 },
+ { "If-None-Match", 13 },
+ { "If-Range", 8 },
+ { "If-Unmodified-Since", 19 },
+ { "Keep-Alive", 10 },
+ { "Last-Event-ID", 13 },
+ { "Last-Modified", 13 },
+ { "Link", 4 },
+ { "Location", 8 },
+ { "Origin", 6 },
+ { "Ping-From", 9 },
+ { "Ping-To", 7 },
+ { "Pragma", 6 },
+ { "Proxy-Authorization", 19 },
+ { "Purpose", 7 },
+ { "Range", 5 },
+ { "Referer", 7 },
+ { "Referrer-Policy", 15 },
+ { "Refresh", 7 },
+ { "Report-To", 9 },
+ { "Sec-Fetch-Dest", 14 },
+ { "Sec-Fetch-Mode", 14 },
+ { "Sec-WebSocket-Accept", 20 },
+ { "Sec-WebSocket-Extensions", 24 },
+ { "Sec-WebSocket-Key", 17 },
+ { "Sec-WebSocket-Protocol", 22 },
+ { "Sec-WebSocket-Version", 21 },
+ { "Server-Timing", 13 },
+ { "Service-Worker", 14 },
+ { "Service-Worker-Allowed", 22 },
+ { "Service-Worker-Navigation-Preload", 33 },
+ { "Set-Cookie", 10 },
+ { "Set-Cookie2", 11 },
+ { "SourceMap", 9 },
+ { "TE", 2 },
+ { "Timing-Allow-Origin", 19 },
+ { "Trailer", 7 },
+ { "Transfer-Encoding", 17 },
+ { "Upgrade", 7 },
+ { "Upgrade-Insecure-Requests", 25 },
+ { "User-Agent", 10 },
+ { "Vary", 4 },
+ { "Via", 3 },
+ { "X-Content-Type-Options", 22 },
+ { "X-DNS-Prefetch-Control", 22 },
+ { "X-Frame-Options", 15 },
+ { "X-SourceMap", 11 },
+ { "X-Temp-Tablet", 13 },
+ { "X-XSS-Protection", 16 },
+};
+
+
+%}
+
+%language=C++
+%readonly-tables
+%global-table
+%compare-strncmp
+%ignore-case
+%struct-type
+struct HeaderNameHashEntry {
+ const char* name;
+ HTTPHeaderName headerName;
+};
+%define class-name HTTPHeaderNamesHash
+%define lookup-function-name findHeaderNameImpl
+%define hash-function-name header_name_hash_function
+%define word-array-name header_name_wordlist
+%enum
+%%
+Accept, HTTPHeaderName::Accept
+Accept-Charset, HTTPHeaderName::AcceptCharset
+Accept-Encoding, HTTPHeaderName::AcceptEncoding
+Accept-Language, HTTPHeaderName::AcceptLanguage
+Accept-Ranges, HTTPHeaderName::AcceptRanges
+Access-Control-Allow-Credentials, HTTPHeaderName::AccessControlAllowCredentials
+Access-Control-Allow-Headers, HTTPHeaderName::AccessControlAllowHeaders
+Access-Control-Allow-Methods, HTTPHeaderName::AccessControlAllowMethods
+Access-Control-Allow-Origin, HTTPHeaderName::AccessControlAllowOrigin
+Access-Control-Expose-Headers, HTTPHeaderName::AccessControlExposeHeaders
+Access-Control-Max-Age, HTTPHeaderName::AccessControlMaxAge
+Access-Control-Request-Headers, HTTPHeaderName::AccessControlRequestHeaders
+Access-Control-Request-Method, HTTPHeaderName::AccessControlRequestMethod
+Age, HTTPHeaderName::Age
+Authorization, HTTPHeaderName::Authorization
+Cache-Control, HTTPHeaderName::CacheControl
+Connection, HTTPHeaderName::Connection
+Content-Disposition, HTTPHeaderName::ContentDisposition
+Content-Encoding, HTTPHeaderName::ContentEncoding
+Content-Language, HTTPHeaderName::ContentLanguage
+Content-Length, HTTPHeaderName::ContentLength
+Content-Location, HTTPHeaderName::ContentLocation
+Content-Range, HTTPHeaderName::ContentRange
+Content-Security-Policy, HTTPHeaderName::ContentSecurityPolicy
+Content-Security-Policy-Report-Only, HTTPHeaderName::ContentSecurityPolicyReportOnly
+Content-Type, HTTPHeaderName::ContentType
+Cookie, HTTPHeaderName::Cookie
+Cookie2, HTTPHeaderName::Cookie2
+Cross-Origin-Embedder-Policy, HTTPHeaderName::CrossOriginEmbedderPolicy
+Cross-Origin-Embedder-Policy-Report-Only, HTTPHeaderName::CrossOriginEmbedderPolicyReportOnly
+Cross-Origin-Opener-Policy, HTTPHeaderName::CrossOriginOpenerPolicy
+Cross-Origin-Opener-Policy-Report-Only, HTTPHeaderName::CrossOriginOpenerPolicyReportOnly
+Cross-Origin-Resource-Policy, HTTPHeaderName::CrossOriginResourcePolicy
+DNT, HTTPHeaderName::DNT
+Date, HTTPHeaderName::Date
+Default-Style, HTTPHeaderName::DefaultStyle
+ETag, HTTPHeaderName::ETag
+Expect, HTTPHeaderName::Expect
+Expires, HTTPHeaderName::Expires
+Host, HTTPHeaderName::Host
+Icy-MetaInt, HTTPHeaderName::IcyMetaInt
+Icy-Metadata, HTTPHeaderName::IcyMetadata
+If-Match, HTTPHeaderName::IfMatch
+If-Modified-Since, HTTPHeaderName::IfModifiedSince
+If-None-Match, HTTPHeaderName::IfNoneMatch
+If-Range, HTTPHeaderName::IfRange
+If-Unmodified-Since, HTTPHeaderName::IfUnmodifiedSince
+Keep-Alive, HTTPHeaderName::KeepAlive
+Last-Event-ID, HTTPHeaderName::LastEventID
+Last-Modified, HTTPHeaderName::LastModified
+Link, HTTPHeaderName::Link
+Location, HTTPHeaderName::Location
+Origin, HTTPHeaderName::Origin
+Ping-From, HTTPHeaderName::PingFrom
+Ping-To, HTTPHeaderName::PingTo
+Pragma, HTTPHeaderName::Pragma
+Proxy-Authorization, HTTPHeaderName::ProxyAuthorization
+Purpose, HTTPHeaderName::Purpose
+Range, HTTPHeaderName::Range
+Referer, HTTPHeaderName::Referer
+Referrer-Policy, HTTPHeaderName::ReferrerPolicy
+Refresh, HTTPHeaderName::Refresh
+Report-To, HTTPHeaderName::ReportTo
+Sec-Fetch-Dest, HTTPHeaderName::SecFetchDest
+Sec-Fetch-Mode, HTTPHeaderName::SecFetchMode
+Sec-WebSocket-Accept, HTTPHeaderName::SecWebSocketAccept
+Sec-WebSocket-Extensions, HTTPHeaderName::SecWebSocketExtensions
+Sec-WebSocket-Key, HTTPHeaderName::SecWebSocketKey
+Sec-WebSocket-Protocol, HTTPHeaderName::SecWebSocketProtocol
+Sec-WebSocket-Version, HTTPHeaderName::SecWebSocketVersion
+Server-Timing, HTTPHeaderName::ServerTiming
+Service-Worker, HTTPHeaderName::ServiceWorker
+Service-Worker-Allowed, HTTPHeaderName::ServiceWorkerAllowed
+Service-Worker-Navigation-Preload, HTTPHeaderName::ServiceWorkerNavigationPreload
+Set-Cookie, HTTPHeaderName::SetCookie
+Set-Cookie2, HTTPHeaderName::SetCookie2
+SourceMap, HTTPHeaderName::SourceMap
+TE, HTTPHeaderName::TE
+Timing-Allow-Origin, HTTPHeaderName::TimingAllowOrigin
+Trailer, HTTPHeaderName::Trailer
+Transfer-Encoding, HTTPHeaderName::TransferEncoding
+Upgrade, HTTPHeaderName::Upgrade
+Upgrade-Insecure-Requests, HTTPHeaderName::UpgradeInsecureRequests
+User-Agent, HTTPHeaderName::UserAgent
+Vary, HTTPHeaderName::Vary
+Via, HTTPHeaderName::Via
+X-Content-Type-Options, HTTPHeaderName::XContentTypeOptions
+X-DNS-Prefetch-Control, HTTPHeaderName::XDNSPrefetchControl
+X-Frame-Options, HTTPHeaderName::XFrameOptions
+X-SourceMap, HTTPHeaderName::XSourceMap
+X-Temp-Tablet, HTTPHeaderName::XTempTablet
+X-XSS-Protection, HTTPHeaderName::XXSSProtection
+%%
+bool findHTTPHeaderName(StringView stringView, HTTPHeaderName& headerName)
+{
+ unsigned length = stringView.length();
+ if (length > maxHTTPHeaderNameLength || length < minHTTPHeaderNameLength)
+ return false;
+
+ if (stringView.is8Bit()) {
+ if (auto nameAndString = HTTPHeaderNamesHash::findHeaderNameImpl(reinterpret_cast(stringView.characters8()), length)) {
+ headerName = nameAndString->headerName;
+ return true;
+ }
+ } else {
+ LChar characters[maxHTTPHeaderNameLength];
+ for (unsigned i = 0; i < length; ++i) {
+ UChar character = stringView.characters16()[i];
+ if (!isASCII(character))
+ return false;
+
+ characters[i] = static_cast(character);
+ }
+
+ if (auto nameAndString = HTTPHeaderNamesHash::findHeaderNameImpl(reinterpret_cast(characters), length)) {
+ headerName = nameAndString->headerName;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+StringView httpHeaderNameString(HTTPHeaderName headerName)
+{
+ ASSERT(static_cast(headerName) < numHTTPHeaderNames);
+
+ const auto& name = headerNameStrings[static_cast(headerName)];
+
+ return StringView { reinterpret_cast(name.name), static_cast(name.length) };
+}
+
+} // namespace WebCore
+
+#if defined(__clang__)
+IGNORE_WARNINGS_END
+#endif
diff --git a/src/javascript/jsc/bindings/webcore/HTTPHeaderNames.h b/src/javascript/jsc/bindings/webcore/HTTPHeaderNames.h
new file mode 100644
index 0000000000..066d40e90d
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/HTTPHeaderNames.h
@@ -0,0 +1,242 @@
+
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/// This file is generated by create-http-header-name-table, do not edit.
+
+#ifndef HTTPHeaderNames_h
+#define HTTPHeaderNames_h
+
+#include
+
+namespace WebCore {
+
+enum class HTTPHeaderName {
+ Accept,
+ AcceptCharset,
+ AcceptEncoding,
+ AcceptLanguage,
+ AcceptRanges,
+ AccessControlAllowCredentials,
+ AccessControlAllowHeaders,
+ AccessControlAllowMethods,
+ AccessControlAllowOrigin,
+ AccessControlExposeHeaders,
+ AccessControlMaxAge,
+ AccessControlRequestHeaders,
+ AccessControlRequestMethod,
+ Age,
+ Authorization,
+ CacheControl,
+ Connection,
+ ContentDisposition,
+ ContentEncoding,
+ ContentLanguage,
+ ContentLength,
+ ContentLocation,
+ ContentRange,
+ ContentSecurityPolicy,
+ ContentSecurityPolicyReportOnly,
+ ContentType,
+ Cookie,
+ Cookie2,
+ CrossOriginEmbedderPolicy,
+ CrossOriginEmbedderPolicyReportOnly,
+ CrossOriginOpenerPolicy,
+ CrossOriginOpenerPolicyReportOnly,
+ CrossOriginResourcePolicy,
+ DNT,
+ Date,
+ DefaultStyle,
+ ETag,
+ Expect,
+ Expires,
+ Host,
+ IcyMetaInt,
+ IcyMetadata,
+ IfMatch,
+ IfModifiedSince,
+ IfNoneMatch,
+ IfRange,
+ IfUnmodifiedSince,
+ KeepAlive,
+ LastEventID,
+ LastModified,
+ Link,
+ Location,
+ Origin,
+ PingFrom,
+ PingTo,
+ Pragma,
+ ProxyAuthorization,
+ Purpose,
+ Range,
+ Referer,
+ ReferrerPolicy,
+ Refresh,
+ ReportTo,
+ SecFetchDest,
+ SecFetchMode,
+ SecWebSocketAccept,
+ SecWebSocketExtensions,
+ SecWebSocketKey,
+ SecWebSocketProtocol,
+ SecWebSocketVersion,
+ ServerTiming,
+ ServiceWorker,
+ ServiceWorkerAllowed,
+ ServiceWorkerNavigationPreload,
+ SetCookie,
+ SetCookie2,
+ SourceMap,
+ TE,
+ TimingAllowOrigin,
+ Trailer,
+ TransferEncoding,
+ Upgrade,
+ UpgradeInsecureRequests,
+ UserAgent,
+ Vary,
+ Via,
+ XContentTypeOptions,
+ XDNSPrefetchControl,
+ XFrameOptions,
+ XSourceMap,
+ XTempTablet,
+ XXSSProtection,
+};
+
+const unsigned numHTTPHeaderNames = 92;
+const size_t minHTTPHeaderNameLength = 2;
+const size_t maxHTTPHeaderNameLength = 40;
+
+bool findHTTPHeaderName(StringView, HTTPHeaderName&);
+WEBCORE_EXPORT StringView httpHeaderNameString(HTTPHeaderName);
+
+} // namespace WebCore
+
+namespace WTF {
+
+template<> struct EnumTraits {
+ using values = EnumValues<
+ WebCore::HTTPHeaderName,
+ WebCore::HTTPHeaderName::Accept,
+ WebCore::HTTPHeaderName::AcceptCharset,
+ WebCore::HTTPHeaderName::AcceptEncoding,
+ WebCore::HTTPHeaderName::AcceptLanguage,
+ WebCore::HTTPHeaderName::AcceptRanges,
+ WebCore::HTTPHeaderName::AccessControlAllowCredentials,
+ WebCore::HTTPHeaderName::AccessControlAllowHeaders,
+ WebCore::HTTPHeaderName::AccessControlAllowMethods,
+ WebCore::HTTPHeaderName::AccessControlAllowOrigin,
+ WebCore::HTTPHeaderName::AccessControlExposeHeaders,
+ WebCore::HTTPHeaderName::AccessControlMaxAge,
+ WebCore::HTTPHeaderName::AccessControlRequestHeaders,
+ WebCore::HTTPHeaderName::AccessControlRequestMethod,
+ WebCore::HTTPHeaderName::Age,
+ WebCore::HTTPHeaderName::Authorization,
+ WebCore::HTTPHeaderName::CacheControl,
+ WebCore::HTTPHeaderName::Connection,
+ WebCore::HTTPHeaderName::ContentDisposition,
+ WebCore::HTTPHeaderName::ContentEncoding,
+ WebCore::HTTPHeaderName::ContentLanguage,
+ WebCore::HTTPHeaderName::ContentLength,
+ WebCore::HTTPHeaderName::ContentLocation,
+ WebCore::HTTPHeaderName::ContentRange,
+ WebCore::HTTPHeaderName::ContentSecurityPolicy,
+ WebCore::HTTPHeaderName::ContentSecurityPolicyReportOnly,
+ WebCore::HTTPHeaderName::ContentType,
+ WebCore::HTTPHeaderName::Cookie,
+ WebCore::HTTPHeaderName::Cookie2,
+ WebCore::HTTPHeaderName::CrossOriginEmbedderPolicy,
+ WebCore::HTTPHeaderName::CrossOriginEmbedderPolicyReportOnly,
+ WebCore::HTTPHeaderName::CrossOriginOpenerPolicy,
+ WebCore::HTTPHeaderName::CrossOriginOpenerPolicyReportOnly,
+ WebCore::HTTPHeaderName::CrossOriginResourcePolicy,
+ WebCore::HTTPHeaderName::DNT,
+ WebCore::HTTPHeaderName::Date,
+ WebCore::HTTPHeaderName::DefaultStyle,
+ WebCore::HTTPHeaderName::ETag,
+ WebCore::HTTPHeaderName::Expect,
+ WebCore::HTTPHeaderName::Expires,
+ WebCore::HTTPHeaderName::Host,
+ WebCore::HTTPHeaderName::IcyMetaInt,
+ WebCore::HTTPHeaderName::IcyMetadata,
+ WebCore::HTTPHeaderName::IfMatch,
+ WebCore::HTTPHeaderName::IfModifiedSince,
+ WebCore::HTTPHeaderName::IfNoneMatch,
+ WebCore::HTTPHeaderName::IfRange,
+ WebCore::HTTPHeaderName::IfUnmodifiedSince,
+ WebCore::HTTPHeaderName::KeepAlive,
+ WebCore::HTTPHeaderName::LastEventID,
+ WebCore::HTTPHeaderName::LastModified,
+ WebCore::HTTPHeaderName::Link,
+ WebCore::HTTPHeaderName::Location,
+ WebCore::HTTPHeaderName::Origin,
+ WebCore::HTTPHeaderName::PingFrom,
+ WebCore::HTTPHeaderName::PingTo,
+ WebCore::HTTPHeaderName::Pragma,
+ WebCore::HTTPHeaderName::ProxyAuthorization,
+ WebCore::HTTPHeaderName::Purpose,
+ WebCore::HTTPHeaderName::Range,
+ WebCore::HTTPHeaderName::Referer,
+ WebCore::HTTPHeaderName::ReferrerPolicy,
+ WebCore::HTTPHeaderName::Refresh,
+ WebCore::HTTPHeaderName::ReportTo,
+ WebCore::HTTPHeaderName::SecFetchDest,
+ WebCore::HTTPHeaderName::SecFetchMode,
+ WebCore::HTTPHeaderName::SecWebSocketAccept,
+ WebCore::HTTPHeaderName::SecWebSocketExtensions,
+ WebCore::HTTPHeaderName::SecWebSocketKey,
+ WebCore::HTTPHeaderName::SecWebSocketProtocol,
+ WebCore::HTTPHeaderName::SecWebSocketVersion,
+ WebCore::HTTPHeaderName::ServerTiming,
+ WebCore::HTTPHeaderName::ServiceWorker,
+ WebCore::HTTPHeaderName::ServiceWorkerAllowed,
+ WebCore::HTTPHeaderName::ServiceWorkerNavigationPreload,
+ WebCore::HTTPHeaderName::SetCookie,
+ WebCore::HTTPHeaderName::SetCookie2,
+ WebCore::HTTPHeaderName::SourceMap,
+ WebCore::HTTPHeaderName::TE,
+ WebCore::HTTPHeaderName::TimingAllowOrigin,
+ WebCore::HTTPHeaderName::Trailer,
+ WebCore::HTTPHeaderName::TransferEncoding,
+ WebCore::HTTPHeaderName::Upgrade,
+ WebCore::HTTPHeaderName::UpgradeInsecureRequests,
+ WebCore::HTTPHeaderName::UserAgent,
+ WebCore::HTTPHeaderName::Vary,
+ WebCore::HTTPHeaderName::Via,
+ WebCore::HTTPHeaderName::XContentTypeOptions,
+ WebCore::HTTPHeaderName::XDNSPrefetchControl,
+ WebCore::HTTPHeaderName::XFrameOptions,
+ WebCore::HTTPHeaderName::XSourceMap,
+ WebCore::HTTPHeaderName::XTempTablet,
+ WebCore::HTTPHeaderName::XXSSProtection
+ >;
+};
+
+} // namespace WTF
+
+#endif // HTTPHeaderNames_h
diff --git a/src/javascript/jsc/bindings/webcore/HTTPHeaderNames.in b/src/javascript/jsc/bindings/webcore/HTTPHeaderNames.in
new file mode 100644
index 0000000000..9edb2b2d78
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/HTTPHeaderNames.in
@@ -0,0 +1,119 @@
+//
+// Copyright (C) 2014 Apple Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+Accept
+Accept-Charset
+Accept-Language
+Accept-Encoding
+Accept-Ranges
+Access-Control-Allow-Credentials
+Access-Control-Allow-Headers
+Access-Control-Allow-Methods
+Access-Control-Allow-Origin
+Access-Control-Expose-Headers
+Access-Control-Max-Age
+Access-Control-Request-Headers
+Access-Control-Request-Method
+Age
+Authorization
+Cache-Control
+Connection
+Content-Disposition
+Content-Encoding
+Content-Language
+Content-Length
+Content-Location
+Content-Security-Policy
+Content-Security-Policy-Report-Only
+Content-Type
+Content-Range
+Cookie
+Cookie2
+Cross-Origin-Embedder-Policy
+Cross-Origin-Embedder-Policy-Report-Only
+Cross-Origin-Opener-Policy
+Cross-Origin-Opener-Policy-Report-Only
+Cross-Origin-Resource-Policy
+Date
+DNT
+Default-Style
+ETag
+Expect
+Expires
+Host
+If-Match
+If-Modified-Since
+If-None-Match
+If-Range
+If-Unmodified-Since
+Keep-Alive
+Last-Event-ID
+Last-Modified
+Link
+Location
+Origin
+Ping-From
+Ping-To
+Purpose
+Pragma
+Proxy-Authorization
+Range
+Referer
+Referrer-Policy
+Refresh
+Report-To
+Sec-Fetch-Dest
+Sec-Fetch-Mode
+Sec-WebSocket-Accept
+Sec-WebSocket-Extensions
+Sec-WebSocket-Key
+Sec-WebSocket-Protocol
+Sec-WebSocket-Version
+Server-Timing
+Service-Worker
+Service-Worker-Allowed
+Service-Worker-Navigation-Preload
+Set-Cookie
+Set-Cookie2
+SourceMap
+TE
+Timing-Allow-Origin
+Trailer
+Transfer-Encoding
+Upgrade
+Upgrade-Insecure-Requests
+User-Agent
+Vary
+Via
+X-Content-Type-Options
+X-DNS-Prefetch-Control
+X-Frame-Options
+X-SourceMap
+X-XSS-Protection
+X-Temp-Tablet
+
+// These headers are specific to GStreamer.
+Icy-MetaInt
+Icy-Metadata
diff --git a/src/javascript/jsc/bindings/webcore/HTTPHeaderValues.cpp b/src/javascript/jsc/bindings/webcore/HTTPHeaderValues.cpp
new file mode 100644
index 0000000000..b4869e846e
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/HTTPHeaderValues.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "HTTPHeaderValues.h"
+
+#include
+#include
+
+namespace WebCore {
+
+namespace HTTPHeaderValues {
+
+const String& textPlainContentType()
+{
+ static NeverDestroyed contentType(MAKE_STATIC_STRING_IMPL("text/plain;charset=UTF-8"));
+ return contentType;
+}
+
+const String& formURLEncodedContentType()
+{
+ static NeverDestroyed contentType(MAKE_STATIC_STRING_IMPL("application/x-www-form-urlencoded;charset=UTF-8"));
+ return contentType;
+}
+
+const String& applicationJSONContentType()
+{
+ // The default encoding is UTF-8: https://www.ietf.org/rfc/rfc4627.txt.
+ static NeverDestroyed contentType(MAKE_STATIC_STRING_IMPL("application/json"));
+ return contentType;
+}
+
+const String& noCache()
+{
+ static NeverDestroyed value(MAKE_STATIC_STRING_IMPL("no-cache"));
+ return value;
+}
+
+const String& maxAge0()
+{
+ static NeverDestroyed value(MAKE_STATIC_STRING_IMPL("max-age=0"));
+ return value;
+}
+
+}
+
+}
diff --git a/src/javascript/jsc/bindings/webcore/HTTPHeaderValues.h b/src/javascript/jsc/bindings/webcore/HTTPHeaderValues.h
new file mode 100644
index 0000000000..6345a9a8fc
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/HTTPHeaderValues.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include
+
+namespace WebCore {
+
+namespace HTTPHeaderValues {
+
+const String& textPlainContentType();
+const String& formURLEncodedContentType();
+WEBCORE_EXPORT const String& applicationJSONContentType();
+const String& noCache();
+WEBCORE_EXPORT const String& maxAge0();
+}
+
+}
diff --git a/src/javascript/jsc/bindings/webcore/HTTPParsers.cpp b/src/javascript/jsc/bindings/webcore/HTTPParsers.cpp
new file mode 100644
index 0000000000..d435cebf4d
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/HTTPParsers.cpp
@@ -0,0 +1,1034 @@
+/*
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2011 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "HTTPParsers.h"
+
+#include "HTTPHeaderField.h"
+#include "HTTPHeaderNames.h"
+#include "ParsedContentType.h"
+#include
+#include
+#include
+#include
+#include
+
+namespace WebCore {
+
+// True if characters which satisfy the predicate are present, incrementing
+// "pos" to the next character which does not satisfy the predicate.
+// Note: might return pos == str.length().
+static inline bool skipWhile(const String& str, unsigned& pos, const Function& predicate)
+{
+ const unsigned start = pos;
+ const unsigned len = str.length();
+ while (pos < len && predicate(str[pos]))
+ ++pos;
+ return pos != start;
+}
+
+// true if there is more to parse, after incrementing pos past whitespace.
+// Note: Might return pos == str.length()
+static inline bool skipWhiteSpace(const String& str, unsigned& pos)
+{
+ skipWhile(str, pos, RFC7230::isWhitespace);
+ return pos < str.length();
+}
+
+// Returns true if the function can match the whole token (case insensitive)
+// incrementing pos on match, otherwise leaving pos unchanged.
+// Note: Might return pos == str.length()
+static inline bool skipToken(const String& str, unsigned& pos, const char* token)
+{
+ unsigned len = str.length();
+ unsigned current = pos;
+
+ while (current < len && *token) {
+ if (toASCIILower(str[current]) != *token++)
+ return false;
+ ++current;
+ }
+
+ if (*token)
+ return false;
+
+ pos = current;
+ return true;
+}
+
+// True if the expected equals sign is seen and there is more to follow.
+static inline bool skipEquals(const String& str, unsigned &pos)
+{
+ return skipWhiteSpace(str, pos) && str[pos++] == '=' && skipWhiteSpace(str, pos);
+}
+
+// True if a value present, incrementing pos to next space or semicolon, if any.
+// Note: might return pos == str.length().
+static inline bool skipValue(const String& str, unsigned& pos)
+{
+ unsigned start = pos;
+ unsigned len = str.length();
+ while (pos < len) {
+ if (str[pos] == ' ' || str[pos] == '\t' || str[pos] == ';')
+ break;
+ ++pos;
+ }
+ return pos != start;
+}
+
+// See RFC 7230, Section 3.1.2.
+bool isValidReasonPhrase(const String& value)
+{
+ for (unsigned i = 0; i < value.length(); ++i) {
+ UChar c = value[i];
+ if (c == 0x7F || !isLatin1(c) || (c < 0x20 && c != '\t'))
+ return false;
+ }
+ return true;
+}
+
+// See https://fetch.spec.whatwg.org/#concept-header
+bool isValidHTTPHeaderValue(const String& value)
+{
+ UChar c = value[0];
+ if (c == ' ' || c == '\t')
+ return false;
+ c = value[value.length() - 1];
+ if (c == ' ' || c == '\t')
+ return false;
+ for (unsigned i = 0; i < value.length(); ++i) {
+ c = value[i];
+ if (c == 0x00 || c == 0x0A || c == 0x0D)
+ return false;
+ }
+ return true;
+}
+
+// See RFC 7231, Section 5.3.2.
+bool isValidAcceptHeaderValue(const String& value)
+{
+ for (unsigned i = 0; i < value.length(); ++i) {
+ UChar c = value[i];
+
+ // First check for alphanumeric for performance reasons then allowlist four delimiter characters.
+ if (isASCIIAlphanumeric(c) || c == ',' || c == '/' || c == ';' || c == '=')
+ continue;
+
+ ASSERT(isLatin1(c));
+ if (c == 0x7F || (c < 0x20 && c != '\t'))
+ return false;
+
+ if (RFC7230::isDelimiter(c))
+ return false;
+ }
+
+ return true;
+}
+
+static bool containsCORSUnsafeRequestHeaderBytes(const String& value)
+{
+ for (unsigned i = 0; i < value.length(); ++i) {
+ UChar c = value[i];
+ // https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte
+ if ((c < 0x20 && c != '\t') || (c == '"' || c == '(' || c == ')' || c == ':' || c == '<' || c == '>' || c == '?'
+ || c == '@' || c == '[' || c == '\\' || c == ']' || c == 0x7B || c == '{' || c == '}' || c == 0x7F))
+ return true;
+ }
+
+ return false;
+}
+
+// See RFC 7231, Section 5.3.5 and 3.1.3.2.
+bool isValidLanguageHeaderValue(const String& value)
+{
+ for (unsigned i = 0; i < value.length(); ++i) {
+ UChar c = value[i];
+ if (isASCIIAlphanumeric(c) || c == ' ' || c == '*' || c == ',' || c == '-' || c == '.' || c == ';' || c == '=')
+ continue;
+ return false;
+ }
+
+ // FIXME: Validate further by splitting into language tags and optional quality
+ // values (q=) and then check each language tag.
+ // Language tags https://tools.ietf.org/html/rfc7231#section-3.1.3.1
+ // Language tag syntax https://tools.ietf.org/html/bcp47#section-2.1
+ return true;
+}
+
+// See RFC 7230, Section 3.2.6.
+bool isValidHTTPToken(StringView value)
+{
+ if (value.isEmpty())
+ return false;
+ for (UChar c : value.codeUnits()) {
+ if (!RFC7230::isTokenCharacter(c))
+ return false;
+ }
+ return true;
+}
+
+bool isValidHTTPToken(const String& value)
+{
+ return isValidHTTPToken(StringView(value));
+}
+
+#if USE(GLIB)
+// True if the character at the given position satisifies a predicate, incrementing "pos" by one.
+// Note: Might return pos == str.length()
+static inline bool skipCharacter(const String& value, unsigned& pos, Function&& predicate)
+{
+ if (pos < value.length() && predicate(value[pos])) {
+ ++pos;
+ return true;
+ }
+ return false;
+}
+
+// True if the "expected" character is at the given position, incrementing "pos" by one.
+// Note: Might return pos == str.length()
+static inline bool skipCharacter(const String& value, unsigned& pos, const UChar expected)
+{
+ return skipCharacter(value, pos, [expected](const UChar c) {
+ return c == expected;
+ });
+}
+
+// True if a quoted pair is present, incrementing "pos" to the position after the quoted pair.
+// Note: Might return pos == str.length()
+// See RFC 7230, Section 3.2.6.
+static constexpr auto QuotedPairStartCharacter = '\\';
+static bool skipQuotedPair(const String& value, unsigned& pos)
+{
+ // quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
+ return skipCharacter(value, pos, QuotedPairStartCharacter)
+ && skipCharacter(value, pos, RFC7230::isQuotedPairSecondOctet);
+}
+
+// True if a comment is present, incrementing "pos" to the position after the comment.
+// Note: Might return pos == str.length()
+// See RFC 7230, Section 3.2.6.
+static constexpr auto CommentStartCharacter = '(';
+static constexpr auto CommentEndCharacter = ')';
+static bool skipComment(const String& value, unsigned& pos)
+{
+ // comment = "(" *( ctext / quoted-pair / comment ) ")"
+ // ctext = HTAB / SP / %x21-27 / %x2A-5B / %x5D-7E / obs-text
+ if (!skipCharacter(value, pos, CommentStartCharacter))
+ return false;
+
+ const unsigned end = value.length();
+ while (pos < end && value[pos] != CommentEndCharacter) {
+ switch (value[pos]) {
+ case CommentStartCharacter:
+ if (!skipComment(value, pos))
+ return false;
+ break;
+ case QuotedPairStartCharacter:
+ if (!skipQuotedPair(value, pos))
+ return false;
+ break;
+ default:
+ if (!skipWhile(value, pos, RFC7230::isCommentText))
+ return false;
+ }
+ }
+ return skipCharacter(value, pos, CommentEndCharacter);
+}
+
+// True if an HTTP header token is present, incrementing "pos" to the position after it.
+// Note: Might return pos == str.length()
+// See RFC 7230, Section 3.2.6.
+static bool skipHTTPToken(const String& value, unsigned& pos)
+{
+ return skipWhile(value, pos, RFC7230::isTokenCharacter);
+}
+
+// True if a product specifier (as in an User-Agent header) is present, incrementing "pos" to the position after it.
+// Note: Might return pos == str.length()
+// See RFC 7231, Section 5.5.3.
+static bool skipUserAgentProduct(const String& value, unsigned& pos)
+{
+ // product = token ["/" product-version]
+ // product-version = token
+ if (!skipHTTPToken(value, pos))
+ return false;
+ if (skipCharacter(value, pos, '/'))
+ return skipHTTPToken(value, pos);
+ return true;
+}
+
+// See RFC 7231, Section 5.5.3
+bool isValidUserAgentHeaderValue(const String& value)
+{
+ // User-Agent = product *( RWS ( product / comment ) )
+ unsigned pos = 0;
+ if (!skipUserAgentProduct(value, pos))
+ return false;
+
+ while (pos < value.length()) {
+ if (!skipWhiteSpace(value, pos))
+ return false;
+ if (value[pos] == CommentStartCharacter) {
+ if (!skipComment(value, pos))
+ return false;
+ } else {
+ if (!skipUserAgentProduct(value, pos))
+ return false;
+ }
+ }
+
+ return pos == value.length();
+}
+#endif
+
+static const size_t maxInputSampleSize = 128;
+template
+static String trimInputSample(CharType* p, size_t length)
+{
+ String s = String(p, std::min(length, maxInputSampleSize));
+ if (length > maxInputSampleSize)
+ s.append(horizontalEllipsis);
+ return s;
+}
+
+std::optional parseHTTPDate(const String& value)
+{
+ double dateInMillisecondsSinceEpoch = parseDateFromNullTerminatedCharacters(value.utf8().data());
+ if (!std::isfinite(dateInMillisecondsSinceEpoch))
+ return std::nullopt;
+ // This assumes system_clock epoch equals Unix epoch which is true for all implementations but unspecified.
+ // FIXME: The parsing function should be switched to WallTime too.
+ return WallTime::fromRawSeconds(dateInMillisecondsSinceEpoch / 1000.0);
+}
+
+// FIXME: This function doesn't comply with RFC 6266.
+// For example, this function doesn't handle the interaction between " and ;
+// that arises from quoted-string, nor does this function properly unquote
+// attribute values. Further this function appears to process parameter names
+// in a case-sensitive manner. (There are likely other bugs as well.)
+String filenameFromHTTPContentDisposition(StringView value)
+{
+ for (auto keyValuePair : value.split(';')) {
+ size_t valueStartPos = keyValuePair.find('=');
+ if (valueStartPos == notFound)
+ continue;
+
+ auto key = keyValuePair.left(valueStartPos).stripWhiteSpace();
+
+ if (key.isEmpty() || key != "filename")
+ continue;
+
+ auto value = keyValuePair.substring(valueStartPos + 1).stripWhiteSpace();
+
+ // Remove quotes if there are any
+ if (value.length() > 1 && value[0] == '\"')
+ value = value.substring(1, value.length() - 2);
+
+ return value.toString();
+ }
+
+ return String();
+}
+
+String extractMIMETypeFromMediaType(const String& mediaType)
+{
+ unsigned position = 0;
+ unsigned length = mediaType.length();
+
+ for (; position < length; ++position) {
+ UChar c = mediaType[position];
+ if (c != '\t' && c != ' ')
+ break;
+ }
+
+ if (position == length)
+ return mediaType;
+
+ unsigned typeStart = position;
+
+ unsigned typeEnd = position;
+ for (; position < length; ++position) {
+ UChar c = mediaType[position];
+
+ // While RFC 2616 does not allow it, other browsers allow multiple values in the HTTP media
+ // type header field, Content-Type. In such cases, the media type string passed here may contain
+ // the multiple values separated by commas. For now, this code ignores text after the first comma,
+ // which prevents it from simply failing to parse such types altogether. Later for better
+ // compatibility we could consider using the first or last valid MIME type instead.
+ // See https://bugs.webkit.org/show_bug.cgi?id=25352 for more discussion.
+ if (c == ',')
+ break;
+
+ if (c == '\t' || c == ' ' || c == ';')
+ break;
+
+ typeEnd = position + 1;
+ }
+
+ return mediaType.substring(typeStart, typeEnd - typeStart);
+}
+
+String extractCharsetFromMediaType(const String& mediaType)
+{
+ unsigned charsetPos = 0, charsetLen = 0;
+ size_t pos = 0;
+ unsigned length = mediaType.length();
+
+ while (pos < length) {
+ pos = mediaType.findIgnoringASCIICase("charset", pos);
+ if (pos == notFound || pos == 0) {
+ charsetLen = 0;
+ break;
+ }
+
+ // is what we found a beginning of a word?
+ if (mediaType[pos-1] > ' ' && mediaType[pos-1] != ';') {
+ pos += 7;
+ continue;
+ }
+
+ pos += 7;
+
+ // skip whitespace
+ while (pos != length && mediaType[pos] <= ' ')
+ ++pos;
+
+ if (mediaType[pos++] != '=') // this "charset" substring wasn't a parameter name, but there may be others
+ continue;
+
+ while (pos != length && (mediaType[pos] <= ' ' || mediaType[pos] == '"' || mediaType[pos] == '\''))
+ ++pos;
+
+ // we don't handle spaces within quoted parameter values, because charset names cannot have any
+ unsigned endpos = pos;
+ while (pos != length && mediaType[endpos] > ' ' && mediaType[endpos] != '"' && mediaType[endpos] != '\'' && mediaType[endpos] != ';')
+ ++endpos;
+
+ charsetPos = pos;
+ charsetLen = endpos - pos;
+ break;
+ }
+ return mediaType.substring(charsetPos, charsetLen);
+}
+
+XSSProtectionDisposition parseXSSProtectionHeader(const String& header, String& failureReason, unsigned& failurePosition, String& reportURL)
+{
+ static NeverDestroyed failureReasonInvalidToggle(MAKE_STATIC_STRING_IMPL("expected 0 or 1"));
+ static NeverDestroyed failureReasonInvalidSeparator(MAKE_STATIC_STRING_IMPL("expected semicolon"));
+ static NeverDestroyed failureReasonInvalidEquals(MAKE_STATIC_STRING_IMPL("expected equals sign"));
+ static NeverDestroyed failureReasonInvalidMode(MAKE_STATIC_STRING_IMPL("invalid mode directive"));
+ static NeverDestroyed failureReasonInvalidReport(MAKE_STATIC_STRING_IMPL("invalid report directive"));
+ static NeverDestroyed failureReasonDuplicateMode(MAKE_STATIC_STRING_IMPL("duplicate mode directive"));
+ static NeverDestroyed failureReasonDuplicateReport(MAKE_STATIC_STRING_IMPL("duplicate report directive"));
+ static NeverDestroyed failureReasonInvalidDirective(MAKE_STATIC_STRING_IMPL("unrecognized directive"));
+
+ unsigned pos = 0;
+
+ if (!skipWhiteSpace(header, pos))
+ return XSSProtectionDisposition::Enabled;
+
+ if (header[pos] == '0')
+ return XSSProtectionDisposition::Disabled;
+
+ if (header[pos++] != '1') {
+ failureReason = failureReasonInvalidToggle;
+ return XSSProtectionDisposition::Invalid;
+ }
+
+ XSSProtectionDisposition result = XSSProtectionDisposition::Enabled;
+ bool modeDirectiveSeen = false;
+ bool reportDirectiveSeen = false;
+
+ while (1) {
+ // At end of previous directive: consume whitespace, semicolon, and whitespace.
+ if (!skipWhiteSpace(header, pos))
+ return result;
+
+ if (header[pos++] != ';') {
+ failureReason = failureReasonInvalidSeparator;
+ failurePosition = pos;
+ return XSSProtectionDisposition::Invalid;
+ }
+
+ if (!skipWhiteSpace(header, pos))
+ return result;
+
+ // At start of next directive.
+ if (skipToken(header, pos, "mode")) {
+ if (modeDirectiveSeen) {
+ failureReason = failureReasonDuplicateMode;
+ failurePosition = pos;
+ return XSSProtectionDisposition::Invalid;
+ }
+ modeDirectiveSeen = true;
+ if (!skipEquals(header, pos)) {
+ failureReason = failureReasonInvalidEquals;
+ failurePosition = pos;
+ return XSSProtectionDisposition::Invalid;
+ }
+ if (!skipToken(header, pos, "block")) {
+ failureReason = failureReasonInvalidMode;
+ failurePosition = pos;
+ return XSSProtectionDisposition::Invalid;
+ }
+ result = XSSProtectionDisposition::BlockEnabled;
+ } else if (skipToken(header, pos, "report")) {
+ if (reportDirectiveSeen) {
+ failureReason = failureReasonDuplicateReport;
+ failurePosition = pos;
+ return XSSProtectionDisposition::Invalid;
+ }
+ reportDirectiveSeen = true;
+ if (!skipEquals(header, pos)) {
+ failureReason = failureReasonInvalidEquals;
+ failurePosition = pos;
+ return XSSProtectionDisposition::Invalid;
+ }
+ size_t startPos = pos;
+ if (!skipValue(header, pos)) {
+ failureReason = failureReasonInvalidReport;
+ failurePosition = pos;
+ return XSSProtectionDisposition::Invalid;
+ }
+ reportURL = header.substring(startPos, pos - startPos);
+ failurePosition = startPos; // If later semantic check deems unacceptable.
+ } else {
+ failureReason = failureReasonInvalidDirective;
+ failurePosition = pos;
+ return XSSProtectionDisposition::Invalid;
+ }
+ }
+}
+
+ContentTypeOptionsDisposition parseContentTypeOptionsHeader(StringView header)
+{
+ StringView leftToken = header.left(header.find(','));
+ if (equalLettersIgnoringASCIICase(stripLeadingAndTrailingHTTPSpaces(leftToken), "nosniff"))
+ return ContentTypeOptionsDisposition::Nosniff;
+ return ContentTypeOptionsDisposition::None;
+}
+
+// For example: "HTTP/1.1 200 OK" => "OK".
+// Note that HTTP/2 does not include a reason phrase, so we return the empty atom.
+AtomString extractReasonPhraseFromHTTPStatusLine(const String& statusLine)
+{
+ StringView view = statusLine;
+ size_t spacePos = view.find(' ');
+
+ // Remove status code from the status line.
+ spacePos = view.find(' ', spacePos + 1);
+ if (spacePos == notFound)
+ return emptyAtom();
+
+ return view.substring(spacePos + 1).toAtomString();
+}
+
+XFrameOptionsDisposition parseXFrameOptionsHeader(StringView header)
+{
+ XFrameOptionsDisposition result = XFrameOptionsDisposition::None;
+
+ if (header.isEmpty())
+ return result;
+
+ for (auto currentHeader : header.split(',')) {
+ currentHeader = currentHeader.stripWhiteSpace();
+ XFrameOptionsDisposition currentValue = XFrameOptionsDisposition::None;
+ if (equalLettersIgnoringASCIICase(currentHeader, "deny"))
+ currentValue = XFrameOptionsDisposition::Deny;
+ else if (equalLettersIgnoringASCIICase(currentHeader, "sameorigin"))
+ currentValue = XFrameOptionsDisposition::SameOrigin;
+ else if (equalLettersIgnoringASCIICase(currentHeader, "allowall"))
+ currentValue = XFrameOptionsDisposition::AllowAll;
+ else
+ currentValue = XFrameOptionsDisposition::Invalid;
+
+ if (result == XFrameOptionsDisposition::None)
+ result = currentValue;
+ else if (result != currentValue)
+ return XFrameOptionsDisposition::Conflict;
+ }
+ return result;
+}
+
+// https://fetch.spec.whatwg.org/#concept-header-list-get-structured-header
+// FIXME: For now, this assumes the type is "item".
+std::optional>> parseStructuredFieldValue(StringView header)
+{
+ header = stripLeadingAndTrailingHTTPSpaces(header);
+ if (header.isEmpty())
+ return std::nullopt;
+
+ // Parse a token (https://datatracker.ietf.org/doc/html/rfc8941#section-4.2.6).
+ if (!isASCIIAlpha(header[0]) && header[0] != '*')
+ return std::nullopt;
+ size_t index = 1;
+ while (index < header.length()) {
+ UChar c = header[index];
+ if (!RFC7230::isTokenCharacter(c) && c != ':' && c != '/')
+ break;
+ ++index;
+ }
+ StringView bareItem = header.substring(0, index);
+
+ // Parse parameters (https://datatracker.ietf.org/doc/html/rfc8941#section-4.2.3.2).
+ HashMap parameters;
+ while (index < header.length()) {
+ if (header[index] != ';')
+ break;
+ ++index; // Consume ';'.
+ while (index < header.length() && header[index] == ' ')
+ ++index;
+ if (index == header.length())
+ return std::nullopt;
+ // Parse a key (https://datatracker.ietf.org/doc/html/rfc8941#section-4.2.3.3)
+ if (!isASCIILower(header[index]))
+ return std::nullopt;
+ size_t keyStart = index++;
+ while (index < header.length()) {
+ UChar c = header[index];
+ if (!isASCIILower(c) && !isASCIIDigit(c) && c != '_' && c != '-' && c != '.' && c != '*')
+ break;
+ ++index;
+ }
+ String key = header.substring(keyStart, index - keyStart).toString();
+ String value = "true";
+ if (index < header.length() && header[index] == '=') {
+ ++index; // Consume '='.
+ if (isASCIIAlpha(header[index]) || header[index] == '*') {
+ // https://datatracker.ietf.org/doc/html/rfc8941#section-4.2.6
+ size_t valueStart = index++;
+ while (index < header.length()) {
+ UChar c = header[index];
+ if (!RFC7230::isTokenCharacter(c) && c != ':' && c != '/')
+ break;
+ ++index;
+ }
+ value = header.substring(valueStart, index - valueStart).toString();
+ } else if (header[index] == '"') {
+ // https://datatracker.ietf.org/doc/html/rfc8941#section-4.2.5
+ StringBuilder valueBuilder;
+ ++index; // Skip DQUOTE.
+ while (index < header.length()) {
+ if (header[index] == '\\') {
+ ++index;
+ if (index == header.length())
+ return std::nullopt;
+ if (header[index] != '\\' && header[index] != '"')
+ return std::nullopt;
+ valueBuilder.append(header[index]);
+ } else if (header[index] == '\"') {
+ value = valueBuilder.toString();
+ break;
+ } else if (header[index] <= 0x1F || (header[index] >= 0x7F && header[index] <= 0xFF)) // Not in VCHAR or SP.
+ return std::nullopt;
+ else
+ valueBuilder.append(header[index]);
+ ++index;
+ }
+ if (index == header.length())
+ return std::nullopt;
+ ++index; // Skip DQUOTE.
+ } else
+ return std::nullopt;
+ }
+ parameters.set(WTFMove(key), WTFMove(value));
+ }
+ if (index != header.length())
+ return std::nullopt;
+ return std::make_pair(bareItem, parameters);
+}
+
+bool parseRange(const String& range, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength)
+{
+ // The format of "Range" header is defined in RFC 2616 Section 14.35.1.
+ // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1
+ // We don't support multiple range requests.
+
+ rangeOffset = rangeEnd = rangeSuffixLength = -1;
+
+ // The "bytes" unit identifier should be present.
+ static const unsigned bytesLength = 6;
+ if (!startsWithLettersIgnoringASCIICase(range, "bytes="))
+ return false;
+ // FIXME: The rest of this should use StringView.
+ String byteRange = range.substring(bytesLength);
+
+ // The '-' character needs to be present.
+ int index = byteRange.find('-');
+ if (index == -1)
+ return false;
+
+ // If the '-' character is at the beginning, the suffix length, which specifies the last N bytes, is provided.
+ // Example:
+ // -500
+ if (!index) {
+ if (auto value = parseInteger(StringView { byteRange }.substring(index + 1)))
+ rangeSuffixLength = *value;
+ return true;
+ }
+
+ // Otherwise, the first-byte-position and the last-byte-position are provied.
+ // Examples:
+ // 0-499
+ // 500-
+ auto firstBytePos = parseInteger(StringView { byteRange }.left(index));
+ if (!firstBytePos)
+ return false;
+
+ auto lastBytePosStr = stripLeadingAndTrailingHTTPSpaces(StringView { byteRange }.substring(index + 1));
+ long long lastBytePos = -1;
+ if (!lastBytePosStr.isEmpty()) {
+ auto value = parseInteger(lastBytePosStr);
+ if (!value)
+ return false;
+ lastBytePos = *value;
+ }
+
+ if (*firstBytePos < 0 || !(lastBytePos == -1 || lastBytePos >= *firstBytePos))
+ return false;
+
+ rangeOffset = *firstBytePos;
+ rangeEnd = lastBytePos;
+ return true;
+}
+
+template
+static inline bool isValidHeaderNameCharacter(CharacterType character)
+{
+ // https://tools.ietf.org/html/rfc7230#section-3.2
+ // A header name should only contain one or more of
+ // alphanumeric or ! # $ % & ' * + - . ^ _ ` | ~
+ if (isASCIIAlphanumeric(character))
+ return true;
+ switch (character) {
+ case '!':
+ case '#':
+ case '$':
+ case '%':
+ case '&':
+ case '\'':
+ case '*':
+ case '+':
+ case '-':
+ case '.':
+ case '^':
+ case '_':
+ case '`':
+ case '|':
+ case '~':
+ return true;
+ default:
+ return false;
+ }
+}
+
+size_t parseHTTPHeader(const uint8_t* start, size_t length, String& failureReason, StringView& nameStr, String& valueStr, bool strict)
+{
+ auto p = start;
+ auto end = start + length;
+
+ Vector name;
+ Vector value;
+
+ bool foundFirstNameChar = false;
+ const uint8_t* namePtr = nullptr;
+ size_t nameSize = 0;
+
+ nameStr = StringView();
+ valueStr = String();
+
+ for (; p < end; p++) {
+ switch (*p) {
+ case '\r':
+ if (name.isEmpty()) {
+ if (p + 1 < end && *(p + 1) == '\n')
+ return (p + 2) - start;
+ failureReason = makeString("CR doesn't follow LF in header name at ", trimInputSample(p, end - p));
+ return 0;
+ }
+ failureReason = makeString("Unexpected CR in header name at ", trimInputSample(name.data(), name.size()));
+ return 0;
+ case '\n':
+ failureReason = makeString("Unexpected LF in header name at ", trimInputSample(name.data(), name.size()));
+ return 0;
+ case ':':
+ break;
+ default:
+ if (!isValidHeaderNameCharacter(*p)) {
+ if (name.size() < 1)
+ failureReason = "Unexpected start character in header name";
+ else
+ failureReason = makeString("Unexpected character in header name at ", trimInputSample(name.data(), name.size()));
+ return 0;
+ }
+ name.append(*p);
+ if (!foundFirstNameChar) {
+ namePtr = p;
+ foundFirstNameChar = true;
+ }
+ continue;
+ }
+ if (*p == ':') {
+ ++p;
+ break;
+ }
+ }
+
+ nameSize = name.size();
+ nameStr = StringView(namePtr, nameSize);
+
+ for (; p < end && *p == 0x20; p++) { }
+
+ for (; p < end; p++) {
+ switch (*p) {
+ case '\r':
+ break;
+ case '\n':
+ if (strict) {
+ failureReason = makeString("Unexpected LF in header value at ", trimInputSample(value.data(), value.size()));
+ return 0;
+ }
+ break;
+ default:
+ value.append(*p);
+ }
+ if (*p == '\r' || (!strict && *p == '\n')) {
+ ++p;
+ break;
+ }
+ }
+ if (p >= end || (strict && *p != '\n')) {
+ failureReason = makeString("CR doesn't follow LF after header value at ", trimInputSample(p, end - p));
+ return 0;
+ }
+ valueStr = String::fromUTF8(value.data(), value.size());
+ if (valueStr.isNull()) {
+ failureReason = "Invalid UTF-8 sequence in header value"_s;
+ return 0;
+ }
+ return p - start;
+}
+
+size_t parseHTTPRequestBody(const uint8_t* data, size_t length, Vector& body)
+{
+ body.clear();
+ body.append(data, length);
+
+ return length;
+}
+
+// Implements .
+bool isForbiddenHeaderName(const String& name)
+{
+ HTTPHeaderName headerName;
+ if (findHTTPHeaderName(name, headerName)) {
+ switch (headerName) {
+ case HTTPHeaderName::AcceptCharset:
+ case HTTPHeaderName::AcceptEncoding:
+ case HTTPHeaderName::AccessControlRequestHeaders:
+ case HTTPHeaderName::AccessControlRequestMethod:
+ case HTTPHeaderName::Connection:
+ case HTTPHeaderName::ContentLength:
+ case HTTPHeaderName::Cookie:
+ case HTTPHeaderName::Cookie2:
+ case HTTPHeaderName::Date:
+ case HTTPHeaderName::DNT:
+ case HTTPHeaderName::Expect:
+ case HTTPHeaderName::Host:
+ case HTTPHeaderName::KeepAlive:
+ case HTTPHeaderName::Origin:
+ case HTTPHeaderName::Referer:
+ case HTTPHeaderName::TE:
+ case HTTPHeaderName::Trailer:
+ case HTTPHeaderName::TransferEncoding:
+ case HTTPHeaderName::Upgrade:
+ case HTTPHeaderName::Via:
+ return true;
+ default:
+ break;
+ }
+ }
+ return startsWithLettersIgnoringASCIICase(name, "sec-") || startsWithLettersIgnoringASCIICase(name, "proxy-");
+}
+
+// Implements .
+bool isNoCORSSafelistedRequestHeaderName(const String& name)
+{
+ HTTPHeaderName headerName;
+ if (findHTTPHeaderName(name, headerName)) {
+ switch (headerName) {
+ case HTTPHeaderName::Accept:
+ case HTTPHeaderName::AcceptLanguage:
+ case HTTPHeaderName::ContentLanguage:
+ case HTTPHeaderName::ContentType:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+// Implements .
+bool isPriviledgedNoCORSRequestHeaderName(const String& name)
+{
+ return equalLettersIgnoringASCIICase(name, "range");
+}
+
+// Implements .
+bool isForbiddenResponseHeaderName(const String& name)
+{
+ return equalLettersIgnoringASCIICase(name, "set-cookie") || equalLettersIgnoringASCIICase(name, "set-cookie2");
+}
+
+// Implements .
+bool isForbiddenMethod(const String& name)
+{
+ return equalLettersIgnoringASCIICase(name, "connect") || equalLettersIgnoringASCIICase(name, "trace") || equalLettersIgnoringASCIICase(name, "track");
+}
+
+bool isSimpleHeader(const String& name, const String& value)
+{
+ HTTPHeaderName headerName;
+ if (!findHTTPHeaderName(name, headerName))
+ return false;
+ return isCrossOriginSafeRequestHeader(headerName, value);
+}
+
+bool isCrossOriginSafeHeader(HTTPHeaderName name, const HTTPHeaderSet& accessControlExposeHeaderSet)
+{
+ switch (name) {
+ case HTTPHeaderName::CacheControl:
+ case HTTPHeaderName::ContentLanguage:
+ case HTTPHeaderName::ContentLength:
+ case HTTPHeaderName::ContentType:
+ case HTTPHeaderName::Expires:
+ case HTTPHeaderName::LastModified:
+ case HTTPHeaderName::Pragma:
+ case HTTPHeaderName::Accept:
+ return true;
+ case HTTPHeaderName::SetCookie:
+ case HTTPHeaderName::SetCookie2:
+ return false;
+ default:
+ break;
+ }
+ return accessControlExposeHeaderSet.contains(httpHeaderNameString(name).toStringWithoutCopying());
+}
+
+bool isCrossOriginSafeHeader(const String& name, const HTTPHeaderSet& accessControlExposeHeaderSet)
+{
+#if ASSERT_ENABLED
+ HTTPHeaderName headerName;
+ ASSERT(!findHTTPHeaderName(name, headerName));
+#endif
+ return accessControlExposeHeaderSet.contains(name);
+}
+
+// Implements https://fetch.spec.whatwg.org/#cors-safelisted-request-header
+bool isCrossOriginSafeRequestHeader(HTTPHeaderName name, const String& value)
+{
+ switch (name) {
+ case HTTPHeaderName::Accept:
+ if (!isValidAcceptHeaderValue(value))
+ return false;
+ break;
+ case HTTPHeaderName::AcceptLanguage:
+ case HTTPHeaderName::ContentLanguage:
+ if (!isValidLanguageHeaderValue(value))
+ return false;
+ break;
+ case HTTPHeaderName::ContentType: {
+ // Preflight is required for MIME types that can not be sent via form submission.
+ if (containsCORSUnsafeRequestHeaderBytes(value))
+ return false;
+ auto parsedContentType = ParsedContentType::create(value);
+ if (!parsedContentType)
+ return false;
+ String mimeType = parsedContentType->mimeType();
+ if (!(equalLettersIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded") || equalLettersIgnoringASCIICase(mimeType, "multipart/form-data") || equalLettersIgnoringASCIICase(mimeType, "text/plain")))
+ return false;
+ break;
+ }
+ default:
+ // FIXME: Should we also make safe other headers (DPR, Downlink, Save-Data...)? That would require validating their values.
+ return false;
+ }
+ return value.length() <= 128;
+}
+
+// Implements .
+String normalizeHTTPMethod(const String& method)
+{
+ const ASCIILiteral methods[] = { "DELETE"_s, "GET"_s, "HEAD"_s, "OPTIONS"_s, "POST"_s, "PUT"_s };
+ for (auto value : methods) {
+ if (equalIgnoringASCIICase(method, value.characters())) {
+ // Don't bother allocating a new string if it's already all uppercase.
+ if (method == value)
+ break;
+ return value;
+ }
+ }
+ return method;
+}
+
+// Defined by https://tools.ietf.org/html/rfc7231#section-4.2.1
+bool isSafeMethod(const String& method)
+{
+ const ASCIILiteral safeMethods[] = { "GET"_s, "HEAD"_s, "OPTIONS"_s, "TRACE"_s };
+ for (auto value : safeMethods) {
+ if (equalIgnoringASCIICase(method, value.characters()))
+ return true;
+ }
+ return false;
+}
+
+CrossOriginResourcePolicy parseCrossOriginResourcePolicyHeader(StringView header)
+{
+ auto strippedHeader = stripLeadingAndTrailingHTTPSpaces(header);
+
+ if (strippedHeader.isEmpty())
+ return CrossOriginResourcePolicy::None;
+
+ if (strippedHeader == "same-origin")
+ return CrossOriginResourcePolicy::SameOrigin;
+
+ if (strippedHeader == "same-site")
+ return CrossOriginResourcePolicy::SameSite;
+
+ if (strippedHeader == "cross-origin")
+ return CrossOriginResourcePolicy::CrossOrigin;
+
+ return CrossOriginResourcePolicy::Invalid;
+}
+
+}
diff --git a/src/javascript/jsc/bindings/webcore/HTTPParsers.h b/src/javascript/jsc/bindings/webcore/HTTPParsers.h
new file mode 100644
index 0000000000..920a5a5b61
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/HTTPParsers.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2011 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+namespace WebCore {
+
+typedef HashSet HTTPHeaderSet;
+
+enum class HTTPHeaderName;
+
+enum class XSSProtectionDisposition {
+ Invalid,
+ Disabled,
+ Enabled,
+ BlockEnabled,
+};
+
+enum class ContentTypeOptionsDisposition : bool {
+ None,
+ Nosniff
+};
+
+enum class XFrameOptionsDisposition : uint8_t {
+ None,
+ Deny,
+ SameOrigin,
+ AllowAll,
+ Invalid,
+ Conflict
+};
+
+enum class CrossOriginResourcePolicy : uint8_t {
+ None,
+ CrossOrigin,
+ SameOrigin,
+ SameSite,
+ Invalid
+};
+
+bool isValidReasonPhrase(const String&);
+bool isValidHTTPHeaderValue(const String&);
+bool isValidAcceptHeaderValue(const String&);
+bool isValidLanguageHeaderValue(const String&);
+#if USE(GLIB)
+WEBCORE_EXPORT bool isValidUserAgentHeaderValue(const String&);
+#endif
+bool isValidHTTPToken(const String&);
+bool isValidHTTPToken(StringView);
+std::optional parseHTTPDate(const String&);
+String filenameFromHTTPContentDisposition(StringView);
+WEBCORE_EXPORT String extractMIMETypeFromMediaType(const String&);
+String extractCharsetFromMediaType(const String&);
+XSSProtectionDisposition parseXSSProtectionHeader(const String& header, String& failureReason, unsigned& failurePosition, String& reportURL);
+AtomString extractReasonPhraseFromHTTPStatusLine(const String&);
+WEBCORE_EXPORT XFrameOptionsDisposition parseXFrameOptionsHeader(StringView);
+std::optional>> parseStructuredFieldValue(StringView header);
+
+// -1 could be set to one of the return parameters to indicate the value is not specified.
+WEBCORE_EXPORT bool parseRange(const String&, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength);
+
+ContentTypeOptionsDisposition parseContentTypeOptionsHeader(StringView header);
+
+// Parsing Complete HTTP Messages.
+size_t parseHTTPHeader(const uint8_t* data, size_t length, String& failureReason, StringView& nameStr, String& valueStr, bool strict = true);
+size_t parseHTTPRequestBody(const uint8_t* data, size_t length, Vector& body);
+
+// HTTP Header routine as per https://fetch.spec.whatwg.org/#terminology-headers
+bool isForbiddenHeaderName(const String&);
+bool isNoCORSSafelistedRequestHeaderName(const String&);
+bool isPriviledgedNoCORSRequestHeaderName(const String&);
+bool isForbiddenResponseHeaderName(const String&);
+bool isForbiddenMethod(const String&);
+bool isSimpleHeader(const String& name, const String& value);
+bool isCrossOriginSafeHeader(HTTPHeaderName, const HTTPHeaderSet&);
+bool isCrossOriginSafeHeader(const String&, const HTTPHeaderSet&);
+bool isCrossOriginSafeRequestHeader(HTTPHeaderName, const String&);
+
+String normalizeHTTPMethod(const String&);
+bool isSafeMethod(const String&);
+
+WEBCORE_EXPORT CrossOriginResourcePolicy parseCrossOriginResourcePolicyHeader(StringView);
+
+inline bool isHTTPSpace(UChar character)
+{
+ return character <= ' ' && (character == ' ' || character == '\n' || character == '\t' || character == '\r');
+}
+
+// Strip leading and trailing whitespace as defined in https://fetch.spec.whatwg.org/#concept-header-value-normalize.
+inline String stripLeadingAndTrailingHTTPSpaces(const String& string)
+{
+ return string.stripLeadingAndTrailingCharacters(isHTTPSpace);
+}
+
+inline StringView stripLeadingAndTrailingHTTPSpaces(StringView string)
+{
+ return string.stripLeadingAndTrailingMatchedCharacters(isHTTPSpace);
+}
+
+template
+bool addToAccessControlAllowList(const String& string, unsigned start, unsigned end, HashSet& set)
+{
+ StringImpl* stringImpl = string.impl();
+ if (!stringImpl)
+ return true;
+
+ // Skip white space from start.
+ while (start <= end && isHTTPSpace((*stringImpl)[start]))
+ ++start;
+
+ // only white space
+ if (start > end)
+ return true;
+
+ // Skip white space from end.
+ while (end && isHTTPSpace((*stringImpl)[end]))
+ --end;
+
+ auto token = string.substring(start, end - start + 1);
+ if (!isValidHTTPToken(token))
+ return false;
+
+ set.add(WTFMove(token));
+ return true;
+}
+
+template>
+std::optional> parseAccessControlAllowList(const String& string)
+{
+ HashSet set;
+ unsigned start = 0;
+ size_t end;
+ while ((end = string.find(',', start)) != notFound) {
+ if (start != end) {
+ if (!addToAccessControlAllowList(string, start, end - 1, set))
+ return { };
+ }
+ start = end + 1;
+ }
+ if (start != string.length()) {
+ if (!addToAccessControlAllowList(string, start, string.length() - 1, set))
+ return { };
+ }
+ return set;
+}
+
+}
diff --git a/src/javascript/jsc/bindings/webcore/JSFetchHeaders.cpp b/src/javascript/jsc/bindings/webcore/JSFetchHeaders.cpp
new file mode 100644
index 0000000000..91d79388b5
--- /dev/null
+++ b/src/javascript/jsc/bindings/webcore/JSFetchHeaders.cpp
@@ -0,0 +1,502 @@
+/*
+ This file is part of the WebKit open source project.
+ This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "JSFetchHeaders.h"
+
+#include "ActiveDOMObject.h"
+#include "ExtendedDOMClientIsoSubspaces.h"
+#include "ExtendedDOMIsoSubspaces.h"
+#include "IDLTypes.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConstructor.h"
+#include "JSDOMConvertBase.h"
+#include "JSDOMConvertBoolean.h"
+#include "JSDOMConvertInterface.h"
+#include "JSDOMConvertNullable.h"
+#include "JSDOMConvertRecord.h"
+#include "JSDOMConvertSequences.h"
+#include "JSDOMConvertStrings.h"
+#include "JSDOMConvertUnion.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSDOMGlobalObjectInlines.h"
+#include "JSDOMIterator.h"
+#include "JSDOMOperation.h"
+#include "JSDOMWrapperCache.h"
+#include "ScriptExecutionContext.h"
+#include "WebCoreJSClientData.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace WebCore {
+using namespace JSC;
+
+// Functions
+
+static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_append);
+static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_delete);
+static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_get);
+static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_has);
+static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_set);
+static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_entries);
+static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_keys);
+static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_values);
+static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_forEach);
+
+// Attributes
+
+static JSC_DECLARE_CUSTOM_GETTER(jsFetchHeadersConstructor);
+
+class JSFetchHeadersPrototype final : public JSC::JSNonFinalObject {
+public:
+ using Base = JSC::JSNonFinalObject;
+ static JSFetchHeadersPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure)
+ {
+ JSFetchHeadersPrototype* ptr = new (NotNull, JSC::allocateCell(vm)) JSFetchHeadersPrototype(vm, globalObject, structure);
+ ptr->finishCreation(vm);
+ return ptr;
+ }
+
+ DECLARE_INFO;
+ template
+ static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSFetchHeadersPrototype, Base);
+ return &vm.plainObjectSpace();
+ }
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+private:
+ JSFetchHeadersPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure)
+ : JSC::JSNonFinalObject(vm, structure)
+ {
+ }
+
+ void finishCreation(JSC::VM&);
+};
+STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSFetchHeadersPrototype, JSFetchHeadersPrototype::Base);
+
+using JSFetchHeadersDOMConstructor = JSDOMConstructor;
+
+template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSFetchHeadersDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)
+{
+ VM& vm = lexicalGlobalObject->vm();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto* castedThis = jsCast(callFrame->jsCallee());
+ ASSERT(castedThis);
+ EnsureStillAliveScope argument0 = callFrame->argument(0);
+ auto init = argument0.value().isUndefined() ? std::optional>, IDLRecord>>::ReturnType>() : std::optional>, IDLRecord>>::ReturnType>(convert>, IDLRecord>>(*lexicalGlobalObject, argument0.value()));
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ auto object = FetchHeaders::create(WTFMove(init));
+ if constexpr (IsExceptionOr)
+ RETURN_IF_EXCEPTION(throwScope, {});
+ static_assert(TypeOrExceptionOrUnderlyingType::isRef);
+ auto jsValue = toJSNewlyCreated>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(object));
+ if constexpr (IsExceptionOr)
+ RETURN_IF_EXCEPTION(throwScope, {});
+ setSubclassStructureIfNeeded]