What I have been doing is exploiting the fact that communication between a ServiceWorker and a WindowClient or Client on Chromium-based browsers is a full-duplex stream. So I don't necessarily need to create an HTTP/2 or HTTP/3 server to full duplex stream between any arbotrary Web page and local or remote servers or peers. That allows me to use WHAT Fetch for full duplex streaming to and from the browser, even though WHATWG Fetch still hasn't spelled that out (#1254).
```
var { readable: r, writable: w } = new TransformStream();
var writer = w.getWriter();
var encoder = new TextEncoder();
var { readable, transferableWindow } = await nativeMessageStream(
"/home/user/half_duplex_stream",
r,
);
//.then(console.log).catch(console.error);
readable.pipeThrough(new TextDecoderStream()).pipeTo(
new WritableStream({
write(v) {
console.log(v);
},
close() {
console.log("Stream close");
transferableWindow.remove();
},
abort(reason) {
console.log(reason);
transferableWindow.remove();
},
}),
).then(() => console.log("Done streaming")).catch(console.error);
```
and this in the ServiceWorker, which gets the uploaded readable side of the TransformStream using Transferable Streams
```
addEventListener("fetch", async (e) => {
console.log(e.request.url, e.request.destination, e.clientId);
if (e.request.url.includes("stream")) {
e.respondWith(
new Response(
e.request.body
.pipeThrough(new TextDecoderStream())
.pipeThrough(
new TransformStream({
async start() {
// getClientState(e.clientId);
if (globalThis.port === null) {
readable = new ReadableStream({
start: (_) => {
return controller = _;
},
cancel(reason) {
console.log(reason);
},
});
reader = readable.getReader();
port = chrome.runtime.connectNative(
chrome.runtime.getManifest().short_name,
);
port.onMessage.addListener((message) => {
controller.enqueue(encoder.encode(message));
});
port.onDisconnect.addListener((e) => {
console.log(e);
if (chrome.runtime.lastError) {
console.log(chrome.runtime.lastError);
}
controller.close();
port = readable = controller = null;
});
}
},
async transform(value, c) {
console.log(value);
port.postMessage(value);
const { value: message, done } = await reader.read();
console.log(message, done);
c.enqueue(message);
},
flush() {
console.log("flush");
},
}),
),
),
);
}
});
await writer.write(new TextEncoder().encode("b"));
// B
await writer.write(new TextEncoder().encode("c"));
// C
```
So, technically any number of streams can be piped to that single connection in the ServiceWorker
What I'm interestested in doing now is implementing either h2c and/or HTTP/3 for WebTransport server implementation in an Isolated Web App using Direct Sockets API TCPServerSocket and/or UDPSocket.