feat(unstable): WebSocket headers field (#30321)

This changes the second argument in the WebSocket constructor to be able
to take an object, which can contain a headers field with which the
headers for the connection can be set.

---------

Co-authored-by: Luca Casonato <hello@lcas.dev>
This commit is contained in:
Leo Kettmeir 2025-08-28 11:44:59 +02:00 committed by GitHub
parent b88c621f22
commit c217928649
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 148 additions and 23 deletions

View file

@ -23,6 +23,7 @@ import {
} from "ext:core/ops";
const {
ArrayBufferIsView,
ArrayIsArray,
ArrayPrototypeJoin,
ArrayPrototypeMap,
ArrayPrototypePush,
@ -64,18 +65,41 @@ import {
} from "ext:deno_web/02_event.js";
import { Blob, BlobPrototype } from "ext:deno_web/09_file.js";
import { getLocationHref } from "ext:deno_web/12_location.js";
import {
fillHeaders,
headerListFromHeaders,
headersFromHeaderList,
} from "ext:deno_fetch/20_headers.js";
webidl.converters["sequence<DOMString> or DOMString"] = (
webidl.converters["WebSocketInit"] = webidl.createDictionaryConverter(
"WebSocketInit",
[
{
key: "headers",
converter: webidl.converters["HeadersInit"],
},
{
key: "protocols",
converter: webidl.converters["sequence<DOMString>"],
},
],
);
webidl.converters["WebSocketInit or sequence<DOMString> or DOMString"] = (
V,
prefix,
context,
opts,
) => {
// Union for (sequence<DOMString> or DOMString)
// Union for (WebSocketInit or sequence<DOMString> or DOMString)
if (V === null || V === undefined) {
return webidl.converters["WebSocketInit"](V, prefix, context, opts);
}
if (webidl.type(V) === "Object" && V !== null) {
if (V[SymbolIterator] !== undefined) {
return webidl.converters["sequence<DOMString>"](V, prefix, context, opts);
}
return webidl.converters["WebSocketInit"](V, prefix, context, opts);
}
return webidl.converters.DOMString(V, prefix, context, opts);
};
@ -124,7 +148,7 @@ const _idleTimeoutTimeout = Symbol("[[idleTimeoutTimeout]]");
const _serverHandleIdleTimeout = Symbol("[[serverHandleIdleTimeout]]");
class WebSocket extends EventTarget {
constructor(url, protocols = []) {
constructor(url, initOrProtocols) {
super();
this[webidl.brand] = webidl.brand;
this[_rid] = undefined;
@ -142,11 +166,12 @@ class WebSocket extends EventTarget {
const prefix = "Failed to construct 'WebSocket'";
webidl.requiredArguments(arguments.length, 1, prefix);
url = webidl.converters.USVString(url, prefix, "Argument 1");
protocols = webidl.converters["sequence<DOMString> or DOMString"](
protocols,
prefix,
"Argument 2",
);
initOrProtocols = webidl.converters
["WebSocketInit or sequence<DOMString> or DOMString"](
initOrProtocols,
prefix,
"Argument 2",
);
let wsURL;
@ -179,8 +204,20 @@ class WebSocket extends EventTarget {
this[_url] = wsURL.href;
this[_role] = CLIENT;
if (typeof protocols === "string") {
protocols = [protocols];
let protocols;
let headers = null;
if (typeof initOrProtocols === "string") {
protocols = [initOrProtocols];
} else if (ArrayIsArray(initOrProtocols)) {
protocols = initOrProtocols;
} else {
protocols = initOrProtocols.protocols || [];
if (initOrProtocols.headers !== undefined) {
headers = headersFromHeaderList([], "request");
fillHeaders(headers, initOrProtocols.headers);
}
}
if (
@ -224,6 +261,7 @@ class WebSocket extends EventTarget {
wsURL.href,
ArrayPrototypeJoin(protocols, ", "),
cancelRid,
headers ? headerListFromHeaders(headers) : null,
),
(create) => {
this[_rid] = create.rid;