File size: 1,767 Bytes
bee6636
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 { type MessageW2R, type MessageR2W } from "../client/swruntime";

export class FakeServiceWorker {
	syncToken = 0;
	promises: Record<number, (val?: MessageR2W) => void> = {};
	messageChannel = new MessageChannel();
	connected = false;

	constructor(

		public handle: MessagePort,

		public origin: string

	) {
		this.messageChannel.port1.addEventListener("message", (event) => {
			if ("scramjet$type" in event.data) {
				if (event.data.scramjet$type === "init") {
					this.connected = true;
				} else {
					this.handleMessage(event.data);
				}
			}
		});
		this.messageChannel.port1.start();

		this.handle.postMessage(
			{
				scramjet$type: "init",
				scramjet$port: this.messageChannel.port2,
			},
			[this.messageChannel.port2]
		);
	}

	handleMessage(data: MessageR2W) {
		const cb = this.promises[data.scramjet$token];
		if (cb) {
			cb(data);
			delete this.promises[data.scramjet$token];
		}
	}

	async fetch(request: Request): Promise<Response | false> {
		const token = this.syncToken++;

		const message: MessageW2R = {
			scramjet$type: "fetch",
			scramjet$token: token,
			scramjet$request: {
				url: request.url,
				body: request.body,
				headers: Array.from(request.headers.entries()),
				method: request.method,
				mode: request.mode,
				destinitation: request.destination,
			},
		};

		const transfer = request.body ? [request.body] : [];

		this.handle.postMessage(message, transfer);

		const { scramjet$response: r } = (await new Promise((resolve) => {
			this.promises[token] = resolve;
		})) as MessageR2W;

		if (!r) return false;

		return new Response(r.body, {
			headers: r.headers,
			status: r.status,
			statusText: r.statusText,
		});
	}
}