File size: 2,193 Bytes
04ad412
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
65
66
67
68
69
70
71
72
73
74
import { toError } from "./toError.js";
/** Owns the parent half of the iframe fetch transport. */
export class ParentFetchBridge {
    port;
    #parentPort;
    #fetch;
    #requests = new Map();
    #closed = false;
    constructor(fetchFn) {
        this.#fetch = fetchFn;
        const channel = new MessageChannel();
        this.port = channel.port2;
        channel.port1.onmessage = this.#handleMessage;
        channel.port1.start();
        this.#parentPort = channel.port1;
    }
    close() {
        if (this.#closed) {
            return;
        }
        this.#closed = true;
        for (const [port, controller] of this.#requests) {
            controller.abort();
            port.close();
        }
        this.#requests.clear();
        this.#parentPort.close();
    }
    #handleMessage = (event) => {
        if (this.#closed) {
            return;
        }
        void this.#fetchStream(event.data.url, event.data.options, event.data.port);
    };
    async #fetchStream(url, options, port) {
        const controller = new AbortController();
        this.#requests.set(port, controller);
        port.onmessage = (event) => {
            if (event.data.type === "abort") {
                controller.abort();
            }
            this.#finishRequest(port);
        };
        port.start();
        try {
            const response = await this.#fetch(url, {
                ...options,
                signal: controller.signal,
            });
            const message = {
                type: "response",
                status: response.status,
                statusText: response.statusText,
                headers: [...response.headers.entries()],
                body: response.body,
            };
            port.postMessage(message, response.body ? [response.body] : []);
        }
        catch (err) {
            const error = toError(err);
            port.postMessage({
                type: "error",
                name: error.name,
                message: error.message,
            });
            this.#finishRequest(port);
        }
    }
    #finishRequest(port) {
        this.#requests.delete(port);
        port.close();
    }
}