@lifeart/async-dom 2.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +623 -0
  3. package/dist/base.d.cts +398 -0
  4. package/dist/base.d.cts.map +1 -0
  5. package/dist/base.d.ts +398 -0
  6. package/dist/base.d.ts.map +1 -0
  7. package/dist/cli.cjs +528 -0
  8. package/dist/cli.cjs.map +1 -0
  9. package/dist/cli.d.cts +1 -0
  10. package/dist/cli.d.ts +1 -0
  11. package/dist/cli.js +493 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/debug.d.cts +145 -0
  14. package/dist/debug.d.cts.map +1 -0
  15. package/dist/debug.d.ts +145 -0
  16. package/dist/debug.d.ts.map +1 -0
  17. package/dist/index.cjs +26 -0
  18. package/dist/index.d.cts +560 -0
  19. package/dist/index.d.cts.map +1 -0
  20. package/dist/index.d.ts +560 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +5 -0
  23. package/dist/index2.d.cts +5 -0
  24. package/dist/index2.d.ts +5 -0
  25. package/dist/index3.d.cts +882 -0
  26. package/dist/index3.d.cts.map +1 -0
  27. package/dist/index3.d.ts +882 -0
  28. package/dist/index3.d.ts.map +1 -0
  29. package/dist/main-thread.cjs +5459 -0
  30. package/dist/main-thread.cjs.map +1 -0
  31. package/dist/main-thread.js +5429 -0
  32. package/dist/main-thread.js.map +1 -0
  33. package/dist/react.cjs +116 -0
  34. package/dist/react.cjs.map +1 -0
  35. package/dist/react.d.cts +91 -0
  36. package/dist/react.d.cts.map +1 -0
  37. package/dist/react.d.ts +91 -0
  38. package/dist/react.d.ts.map +1 -0
  39. package/dist/react.js +113 -0
  40. package/dist/react.js.map +1 -0
  41. package/dist/resolve-debug.cjs +24 -0
  42. package/dist/resolve-debug.cjs.map +1 -0
  43. package/dist/resolve-debug.js +19 -0
  44. package/dist/resolve-debug.js.map +1 -0
  45. package/dist/server.cjs +250 -0
  46. package/dist/server.cjs.map +1 -0
  47. package/dist/server.d.cts +127 -0
  48. package/dist/server.d.cts.map +1 -0
  49. package/dist/server.d.ts +127 -0
  50. package/dist/server.d.ts.map +1 -0
  51. package/dist/server.js +245 -0
  52. package/dist/server.js.map +1 -0
  53. package/dist/svelte.cjs +48 -0
  54. package/dist/svelte.cjs.map +1 -0
  55. package/dist/svelte.d.cts +38 -0
  56. package/dist/svelte.d.cts.map +1 -0
  57. package/dist/svelte.d.ts +38 -0
  58. package/dist/svelte.d.ts.map +1 -0
  59. package/dist/svelte.js +47 -0
  60. package/dist/svelte.js.map +1 -0
  61. package/dist/sync-channel.cjs +532 -0
  62. package/dist/sync-channel.cjs.map +1 -0
  63. package/dist/sync-channel.js +425 -0
  64. package/dist/sync-channel.js.map +1 -0
  65. package/dist/transport.cjs +213 -0
  66. package/dist/transport.cjs.map +1 -0
  67. package/dist/transport.d.cts +79 -0
  68. package/dist/transport.d.cts.map +1 -0
  69. package/dist/transport.d.ts +79 -0
  70. package/dist/transport.d.ts.map +1 -0
  71. package/dist/transport.js +202 -0
  72. package/dist/transport.js.map +1 -0
  73. package/dist/vite-plugin.cjs +112 -0
  74. package/dist/vite-plugin.cjs.map +1 -0
  75. package/dist/vite-plugin.d.cts +39 -0
  76. package/dist/vite-plugin.d.cts.map +1 -0
  77. package/dist/vite-plugin.d.ts +39 -0
  78. package/dist/vite-plugin.d.ts.map +1 -0
  79. package/dist/vite-plugin.js +107 -0
  80. package/dist/vite-plugin.js.map +1 -0
  81. package/dist/vue.cjs +123 -0
  82. package/dist/vue.cjs.map +1 -0
  83. package/dist/vue.d.cts +126 -0
  84. package/dist/vue.d.cts.map +1 -0
  85. package/dist/vue.d.ts +126 -0
  86. package/dist/vue.d.ts.map +1 -0
  87. package/dist/vue.js +120 -0
  88. package/dist/vue.js.map +1 -0
  89. package/dist/worker-thread.cjs +2751 -0
  90. package/dist/worker-thread.cjs.map +1 -0
  91. package/dist/worker-thread.js +2692 -0
  92. package/dist/worker-thread.js.map +1 -0
  93. package/dist/worker-transport.cjs +136 -0
  94. package/dist/worker-transport.cjs.map +1 -0
  95. package/dist/worker-transport.d.cts +162 -0
  96. package/dist/worker-transport.d.cts.map +1 -0
  97. package/dist/worker-transport.d.ts +162 -0
  98. package/dist/worker-transport.d.ts.map +1 -0
  99. package/dist/worker-transport.js +125 -0
  100. package/dist/worker-transport.js.map +1 -0
  101. package/dist/worker.cjs +12 -0
  102. package/dist/worker.d.cts +2 -0
  103. package/dist/worker.d.ts +2 -0
  104. package/dist/worker.js +2 -0
  105. package/dist/ws-server-transport.cjs +147 -0
  106. package/dist/ws-server-transport.cjs.map +1 -0
  107. package/dist/ws-server-transport.d.cts +64 -0
  108. package/dist/ws-server-transport.d.cts.map +1 -0
  109. package/dist/ws-server-transport.d.ts +64 -0
  110. package/dist/ws-server-transport.d.ts.map +1 -0
  111. package/dist/ws-server-transport.js +142 -0
  112. package/dist/ws-server-transport.js.map +1 -0
  113. package/dist/ws-transport.cjs +954 -0
  114. package/dist/ws-transport.cjs.map +1 -0
  115. package/dist/ws-transport.js +913 -0
  116. package/dist/ws-transport.js.map +1 -0
  117. package/package.json +145 -0
@@ -0,0 +1,213 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_ws_transport = require("./ws-transport.cjs");
3
+ const require_worker_transport = require("./worker-transport.cjs");
4
+ const require_ws_server_transport = require("./ws-server-transport.cjs");
5
+ //#region src/transport/comlink-adapter.ts
6
+ function createComlinkEndpoint(transport) {
7
+ const listeners = /* @__PURE__ */ new Set();
8
+ transport.onMessage((message) => {
9
+ const event = new MessageEvent("message", { data: message });
10
+ for (const listener of listeners) if (typeof listener === "function") listener(event);
11
+ else listener.handleEvent(event);
12
+ });
13
+ return {
14
+ postMessage(message) {
15
+ transport.send(message);
16
+ },
17
+ addEventListener(_type, listener) {
18
+ listeners.add(listener);
19
+ },
20
+ removeEventListener(_type, listener) {
21
+ listeners.delete(listener);
22
+ }
23
+ };
24
+ }
25
+ //#endregion
26
+ //#region src/transport/shared-worker-transport.ts
27
+ /**
28
+ * Transport implementation using a SharedWorker MessagePort.
29
+ * Used on the main thread side to communicate with a SharedWorker.
30
+ */
31
+ var SharedWorkerTransport = class {
32
+ handlers = [];
33
+ _readyState = "open";
34
+ _statsEnabled = false;
35
+ _stats = {
36
+ messageCount: 0,
37
+ totalBytes: 0,
38
+ largestMessageBytes: 0,
39
+ lastMessageBytes: 0
40
+ };
41
+ _heartbeatInterval = null;
42
+ _heartbeatTimeout = null;
43
+ _awaitingPong = false;
44
+ onError;
45
+ onClose;
46
+ constructor(port) {
47
+ this.port = port;
48
+ port.onmessage = (e) => {
49
+ const data = e.data;
50
+ if (data && typeof data === "object" && data.type === "pong") {
51
+ this._awaitingPong = false;
52
+ this._clearHeartbeatTimeout();
53
+ return;
54
+ }
55
+ for (const h of this.handlers) try {
56
+ h(data);
57
+ } catch (err) {
58
+ console.error("[async-dom] Handler error:", err);
59
+ }
60
+ };
61
+ port.onmessageerror = () => {
62
+ const error = /* @__PURE__ */ new Error("SharedWorker message deserialization failed");
63
+ this.onError?.(error);
64
+ };
65
+ try {
66
+ port.addEventListener("close", () => {
67
+ this._stopHeartbeat();
68
+ if (this._readyState !== "closed") {
69
+ this._readyState = "closed";
70
+ this.onClose?.();
71
+ }
72
+ });
73
+ } catch {}
74
+ this._startHeartbeat();
75
+ }
76
+ _startHeartbeat() {
77
+ this._heartbeatInterval = setInterval(() => {
78
+ if (this._readyState !== "open") {
79
+ this._stopHeartbeat();
80
+ return;
81
+ }
82
+ if (this._awaitingPong) return;
83
+ this._awaitingPong = true;
84
+ this.port.postMessage({ type: "ping" });
85
+ this._heartbeatTimeout = setTimeout(() => {
86
+ if (this._readyState !== "closed") {
87
+ this._readyState = "closed";
88
+ this._stopHeartbeat();
89
+ this.onClose?.();
90
+ }
91
+ }, 15e3);
92
+ }, 5e3);
93
+ }
94
+ _clearHeartbeatTimeout() {
95
+ if (this._heartbeatTimeout !== null) {
96
+ clearTimeout(this._heartbeatTimeout);
97
+ this._heartbeatTimeout = null;
98
+ }
99
+ }
100
+ _stopHeartbeat() {
101
+ this._clearHeartbeatTimeout();
102
+ if (this._heartbeatInterval !== null) {
103
+ clearInterval(this._heartbeatInterval);
104
+ this._heartbeatInterval = null;
105
+ }
106
+ }
107
+ enableStats(enabled) {
108
+ this._statsEnabled = enabled;
109
+ }
110
+ send(message) {
111
+ if (this._readyState !== "open") return;
112
+ if (this._statsEnabled) {
113
+ const size = JSON.stringify(message).length;
114
+ this._stats.messageCount++;
115
+ this._stats.totalBytes += size;
116
+ this._stats.lastMessageBytes = size;
117
+ if (size > this._stats.largestMessageBytes) this._stats.largestMessageBytes = size;
118
+ }
119
+ this.port.postMessage(message);
120
+ }
121
+ onMessage(handler) {
122
+ this.handlers.push(handler);
123
+ }
124
+ close() {
125
+ this._stopHeartbeat();
126
+ this._readyState = "closed";
127
+ this.port.close();
128
+ }
129
+ get readyState() {
130
+ return this._readyState;
131
+ }
132
+ getStats() {
133
+ return { ...this._stats };
134
+ }
135
+ };
136
+ /**
137
+ * Transport implementation used inside a SharedWorker.
138
+ * Communicates with the main thread via a MessagePort received from the connect event.
139
+ */
140
+ var SharedWorkerSelfTransport = class {
141
+ handlers = [];
142
+ _readyState = "open";
143
+ _statsEnabled = false;
144
+ _stats = {
145
+ messageCount: 0,
146
+ totalBytes: 0,
147
+ largestMessageBytes: 0,
148
+ lastMessageBytes: 0
149
+ };
150
+ onError;
151
+ onClose;
152
+ constructor(port) {
153
+ this.port = port;
154
+ port.onmessage = (e) => {
155
+ const data = e.data;
156
+ if (data && typeof data === "object" && data.type === "ping") {
157
+ port.postMessage({ type: "pong" });
158
+ return;
159
+ }
160
+ for (const h of this.handlers) try {
161
+ h(data);
162
+ } catch (err) {
163
+ console.error("[async-dom] Handler error:", err);
164
+ }
165
+ };
166
+ port.onmessageerror = () => {
167
+ const error = /* @__PURE__ */ new Error("SharedWorker message deserialization failed");
168
+ this.onError?.(error);
169
+ };
170
+ port.start();
171
+ }
172
+ enableStats(enabled) {
173
+ this._statsEnabled = enabled;
174
+ }
175
+ send(message) {
176
+ if (this._readyState !== "open") return;
177
+ if (this._statsEnabled) {
178
+ const size = JSON.stringify(message).length;
179
+ this._stats.messageCount++;
180
+ this._stats.totalBytes += size;
181
+ this._stats.lastMessageBytes = size;
182
+ if (size > this._stats.largestMessageBytes) this._stats.largestMessageBytes = size;
183
+ }
184
+ this.port.postMessage(message);
185
+ }
186
+ onMessage(handler) {
187
+ this.handlers.push(handler);
188
+ }
189
+ close() {
190
+ this._readyState = "closed";
191
+ this.port.close();
192
+ }
193
+ get readyState() {
194
+ return this._readyState;
195
+ }
196
+ getStats() {
197
+ return { ...this._stats };
198
+ }
199
+ };
200
+ //#endregion
201
+ exports.BinaryWorkerSelfTransport = require_ws_transport.BinaryWorkerSelfTransport;
202
+ exports.BinaryWorkerTransport = require_ws_transport.BinaryWorkerTransport;
203
+ exports.SharedWorkerSelfTransport = SharedWorkerSelfTransport;
204
+ exports.SharedWorkerTransport = SharedWorkerTransport;
205
+ exports.WebSocketServerTransport = require_ws_server_transport.WebSocketServerTransport;
206
+ exports.WebSocketTransport = require_ws_transport.WebSocketTransport;
207
+ exports.WorkerSelfTransport = require_worker_transport.WorkerSelfTransport;
208
+ exports.WorkerTransport = require_worker_transport.WorkerTransport;
209
+ exports.createComlinkEndpoint = createComlinkEndpoint;
210
+ exports.decodeBinaryMessage = require_ws_transport.decodeBinaryMessage;
211
+ exports.encodeBinaryMessage = require_ws_transport.encodeBinaryMessage;
212
+
213
+ //# sourceMappingURL=transport.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.cjs","names":[],"sources":["../src/transport/comlink-adapter.ts","../src/transport/shared-worker-transport.ts"],"sourcesContent":["import type { Message } from \"../core/protocol.ts\";\nimport type { Transport, TransportReadyState } from \"./base.ts\";\n\n/**\n * Adapts a Transport into a Comlink-compatible Endpoint.\n *\n * This allows using Comlink's RPC-style API over any async-dom transport.\n * Requires `comlink` as a peer dependency.\n *\n * Usage:\n * ```ts\n * import * as Comlink from 'comlink';\n * import { createComlinkEndpoint } from '@lifeart/async-dom/transport';\n *\n * const endpoint = createComlinkEndpoint(transport);\n * const api = Comlink.wrap(endpoint);\n * ```\n */\nexport interface ComlinkEndpoint {\n\tpostMessage(message: unknown, transfer?: Transferable[]): void;\n\taddEventListener(\n\t\ttype: string,\n\t\tlistener: EventListenerOrEventListenerObject,\n\t\toptions?: boolean | AddEventListenerOptions,\n\t): void;\n\tremoveEventListener(\n\t\ttype: string,\n\t\tlistener: EventListenerOrEventListenerObject,\n\t\toptions?: boolean | EventListenerOptions,\n\t): void;\n}\n\nexport function createComlinkEndpoint(transport: Transport): ComlinkEndpoint {\n\tconst listeners = new Set<EventListenerOrEventListenerObject>();\n\n\ttransport.onMessage((message: Message) => {\n\t\tconst event = new MessageEvent(\"message\", { data: message });\n\t\tfor (const listener of listeners) {\n\t\t\tif (typeof listener === \"function\") {\n\t\t\t\tlistener(event);\n\t\t\t} else {\n\t\t\t\tlistener.handleEvent(event);\n\t\t\t}\n\t\t}\n\t});\n\n\treturn {\n\t\tpostMessage(message: unknown) {\n\t\t\ttransport.send(message as Message);\n\t\t},\n\t\taddEventListener(_type: string, listener: EventListenerOrEventListenerObject) {\n\t\t\tlisteners.add(listener);\n\t\t},\n\t\tremoveEventListener(_type: string, listener: EventListenerOrEventListenerObject) {\n\t\t\tlisteners.delete(listener);\n\t\t},\n\t};\n}\n\nexport type { Transport, TransportReadyState };\n","import type { Message } from \"../core/protocol.ts\";\nimport type { Transport, TransportReadyState, TransportStats } from \"./base.ts\";\n\n/**\n * Transport implementation using a SharedWorker MessagePort.\n * Used on the main thread side to communicate with a SharedWorker.\n */\nexport class SharedWorkerTransport implements Transport {\n\tprivate handlers: Array<(message: Message) => void> = [];\n\tprivate _readyState: TransportReadyState = \"open\";\n\tprivate _statsEnabled = false;\n\tprivate _stats: TransportStats = {\n\t\tmessageCount: 0,\n\t\ttotalBytes: 0,\n\t\tlargestMessageBytes: 0,\n\t\tlastMessageBytes: 0,\n\t};\n\tprivate _heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n\tprivate _heartbeatTimeout: ReturnType<typeof setTimeout> | null = null;\n\tprivate _awaitingPong = false;\n\tonError?: (error: Error) => void;\n\tonClose?: () => void;\n\n\tconstructor(private port: MessagePort) {\n\t\tport.onmessage = (e: MessageEvent) => {\n\t\t\tconst data = e.data;\n\t\t\t// Handle pong responses for heartbeat — don't forward to app handlers\n\t\t\tif (data && typeof data === \"object\" && data.type === \"pong\") {\n\t\t\t\tthis._awaitingPong = false;\n\t\t\t\tthis._clearHeartbeatTimeout();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const h of this.handlers) {\n\t\t\t\ttry {\n\t\t\t\t\th(data as Message);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(\"[async-dom] Handler error:\", err);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tport.onmessageerror = () => {\n\t\t\tconst error = new Error(\"SharedWorker message deserialization failed\");\n\t\t\tthis.onError?.(error);\n\t\t};\n\n\t\t// Chrome 122+ supports close event on MessagePort for instant detection\n\t\ttry {\n\t\t\tport.addEventListener(\"close\", () => {\n\t\t\t\tthis._stopHeartbeat();\n\t\t\t\tif (this._readyState !== \"closed\") {\n\t\t\t\t\tthis._readyState = \"closed\";\n\t\t\t\t\tthis.onClose?.();\n\t\t\t\t}\n\t\t\t});\n\t\t} catch {\n\t\t\t// Not supported in this browser — heartbeat handles it\n\t\t}\n\n\t\tthis._startHeartbeat();\n\t}\n\n\tprivate _startHeartbeat(): void {\n\t\tthis._heartbeatInterval = setInterval(() => {\n\t\t\tif (this._readyState !== \"open\") {\n\t\t\t\tthis._stopHeartbeat();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Only send a new ping if we're not still waiting for a pong\n\t\t\tif (this._awaitingPong) return;\n\t\t\tthis._awaitingPong = true;\n\t\t\tthis.port.postMessage({ type: \"ping\" });\n\t\t\tthis._heartbeatTimeout = setTimeout(() => {\n\t\t\t\tif (this._readyState !== \"closed\") {\n\t\t\t\t\tthis._readyState = \"closed\";\n\t\t\t\t\tthis._stopHeartbeat();\n\t\t\t\t\tthis.onClose?.();\n\t\t\t\t}\n\t\t\t}, 15_000);\n\t\t}, 5_000);\n\t}\n\n\tprivate _clearHeartbeatTimeout(): void {\n\t\tif (this._heartbeatTimeout !== null) {\n\t\t\tclearTimeout(this._heartbeatTimeout);\n\t\t\tthis._heartbeatTimeout = null;\n\t\t}\n\t}\n\n\tprivate _stopHeartbeat(): void {\n\t\tthis._clearHeartbeatTimeout();\n\t\tif (this._heartbeatInterval !== null) {\n\t\t\tclearInterval(this._heartbeatInterval);\n\t\t\tthis._heartbeatInterval = null;\n\t\t}\n\t}\n\n\tenableStats(enabled: boolean): void {\n\t\tthis._statsEnabled = enabled;\n\t}\n\n\tsend(message: Message): void {\n\t\tif (this._readyState !== \"open\") {\n\t\t\treturn;\n\t\t}\n\t\tif (this._statsEnabled) {\n\t\t\tconst size = JSON.stringify(message).length;\n\t\t\tthis._stats.messageCount++;\n\t\t\tthis._stats.totalBytes += size;\n\t\t\tthis._stats.lastMessageBytes = size;\n\t\t\tif (size > this._stats.largestMessageBytes) {\n\t\t\t\tthis._stats.largestMessageBytes = size;\n\t\t\t}\n\t\t}\n\t\tthis.port.postMessage(message);\n\t}\n\n\tonMessage(handler: (message: Message) => void): void {\n\t\tthis.handlers.push(handler);\n\t}\n\n\tclose(): void {\n\t\tthis._stopHeartbeat();\n\t\tthis._readyState = \"closed\";\n\t\tthis.port.close();\n\t}\n\n\tget readyState(): TransportReadyState {\n\t\treturn this._readyState;\n\t}\n\n\tgetStats(): TransportStats {\n\t\treturn { ...this._stats };\n\t}\n}\n\n/**\n * Transport implementation used inside a SharedWorker.\n * Communicates with the main thread via a MessagePort received from the connect event.\n */\nexport class SharedWorkerSelfTransport implements Transport {\n\tprivate handlers: Array<(message: Message) => void> = [];\n\tprivate _readyState: TransportReadyState = \"open\";\n\tprivate _statsEnabled = false;\n\tprivate _stats: TransportStats = {\n\t\tmessageCount: 0,\n\t\ttotalBytes: 0,\n\t\tlargestMessageBytes: 0,\n\t\tlastMessageBytes: 0,\n\t};\n\tonError?: (error: Error) => void;\n\tonClose?: () => void;\n\n\tconstructor(private port: MessagePort) {\n\t\tport.onmessage = (e: MessageEvent) => {\n\t\t\tconst data = e.data;\n\t\t\t// Respond to ping with pong automatically — don't forward to app handlers\n\t\t\tif (data && typeof data === \"object\" && data.type === \"ping\") {\n\t\t\t\tport.postMessage({ type: \"pong\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const h of this.handlers) {\n\t\t\t\ttry {\n\t\t\t\t\th(data as Message);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(\"[async-dom] Handler error:\", err);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tport.onmessageerror = () => {\n\t\t\tconst error = new Error(\"SharedWorker message deserialization failed\");\n\t\t\tthis.onError?.(error);\n\t\t};\n\n\t\t// Explicit start() required when using addEventListener pattern,\n\t\t// but also safe to call with onmessage assignment\n\t\tport.start();\n\t}\n\n\tenableStats(enabled: boolean): void {\n\t\tthis._statsEnabled = enabled;\n\t}\n\n\tsend(message: Message): void {\n\t\tif (this._readyState !== \"open\") {\n\t\t\treturn;\n\t\t}\n\t\tif (this._statsEnabled) {\n\t\t\tconst size = JSON.stringify(message).length;\n\t\t\tthis._stats.messageCount++;\n\t\t\tthis._stats.totalBytes += size;\n\t\t\tthis._stats.lastMessageBytes = size;\n\t\t\tif (size > this._stats.largestMessageBytes) {\n\t\t\t\tthis._stats.largestMessageBytes = size;\n\t\t\t}\n\t\t}\n\t\tthis.port.postMessage(message);\n\t}\n\n\tonMessage(handler: (message: Message) => void): void {\n\t\tthis.handlers.push(handler);\n\t}\n\n\tclose(): void {\n\t\tthis._readyState = \"closed\";\n\t\tthis.port.close();\n\t}\n\n\tget readyState(): TransportReadyState {\n\t\treturn this._readyState;\n\t}\n\n\tgetStats(): TransportStats {\n\t\treturn { ...this._stats };\n\t}\n}\n"],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ import { n as TransportReadyState, p as Message, r as TransportStats, t as Transport } from "./base.cjs";
2
+ import { a as decodeBinaryMessage, c as WebSocketTransportOptions, i as BinaryWorkerTransport, n as WorkerTransport, o as encodeBinaryMessage, r as BinaryWorkerSelfTransport, s as WebSocketTransport, t as WorkerSelfTransport } from "./worker-transport.cjs";
3
+ import { n as WebSocketServerTransport, t as WebSocketLike } from "./ws-server-transport.cjs";
4
+
5
+ //#region src/transport/comlink-adapter.d.ts
6
+
7
+ /**
8
+ * Adapts a Transport into a Comlink-compatible Endpoint.
9
+ *
10
+ * This allows using Comlink's RPC-style API over any async-dom transport.
11
+ * Requires `comlink` as a peer dependency.
12
+ *
13
+ * Usage:
14
+ * ```ts
15
+ * import * as Comlink from 'comlink';
16
+ * import { createComlinkEndpoint } from '@lifeart/async-dom/transport';
17
+ *
18
+ * const endpoint = createComlinkEndpoint(transport);
19
+ * const api = Comlink.wrap(endpoint);
20
+ * ```
21
+ */
22
+ interface ComlinkEndpoint {
23
+ postMessage(message: unknown, transfer?: Transferable[]): void;
24
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
25
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
26
+ }
27
+ declare function createComlinkEndpoint(transport: Transport): ComlinkEndpoint;
28
+ //#endregion
29
+ //#region src/transport/shared-worker-transport.d.ts
30
+ /**
31
+ * Transport implementation using a SharedWorker MessagePort.
32
+ * Used on the main thread side to communicate with a SharedWorker.
33
+ */
34
+ declare class SharedWorkerTransport implements Transport {
35
+ private port;
36
+ private handlers;
37
+ private _readyState;
38
+ private _statsEnabled;
39
+ private _stats;
40
+ private _heartbeatInterval;
41
+ private _heartbeatTimeout;
42
+ private _awaitingPong;
43
+ onError?: (error: Error) => void;
44
+ onClose?: () => void;
45
+ constructor(port: MessagePort);
46
+ private _startHeartbeat;
47
+ private _clearHeartbeatTimeout;
48
+ private _stopHeartbeat;
49
+ enableStats(enabled: boolean): void;
50
+ send(message: Message): void;
51
+ onMessage(handler: (message: Message) => void): void;
52
+ close(): void;
53
+ get readyState(): TransportReadyState;
54
+ getStats(): TransportStats;
55
+ }
56
+ /**
57
+ * Transport implementation used inside a SharedWorker.
58
+ * Communicates with the main thread via a MessagePort received from the connect event.
59
+ */
60
+ declare class SharedWorkerSelfTransport implements Transport {
61
+ private port;
62
+ private handlers;
63
+ private _readyState;
64
+ private _statsEnabled;
65
+ private _stats;
66
+ onError?: (error: Error) => void;
67
+ onClose?: () => void;
68
+ constructor(port: MessagePort);
69
+ enableStats(enabled: boolean): void;
70
+ send(message: Message): void;
71
+ onMessage(handler: (message: Message) => void): void;
72
+ close(): void;
73
+ get readyState(): TransportReadyState;
74
+ getStats(): TransportStats;
75
+ }
76
+ //# sourceMappingURL=shared-worker-transport.d.ts.map
77
+ //#endregion
78
+ export { BinaryWorkerSelfTransport, BinaryWorkerTransport, type ComlinkEndpoint, SharedWorkerSelfTransport, SharedWorkerTransport, type Transport, type TransportReadyState, type TransportStats, type WebSocketLike, WebSocketServerTransport, WebSocketTransport, type WebSocketTransportOptions, WorkerSelfTransport, WorkerTransport, createComlinkEndpoint, decodeBinaryMessage, encodeBinaryMessage };
79
+ //# sourceMappingURL=transport.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.cts","names":[],"sources":["../src/transport/comlink-adapter.ts","../src/transport/shared-worker-transport.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAkBA;;;;;;;;AAcA;;;AAA6D,UAd5C,eAAA,CAc4C;EAAe,WAAA,CAAA,OAAA,EAAA,OAAA,EAAA,QAAA,CAAA,EAblC,YAakC,EAAA,CAAA,EAAA,IAAA;2CAVhE,wDACU;8CAIV,wDACU;;ACrBT,iBDyBG,qBAAA,CCzBmB,SAAA,EDyBc,SCzBd,CAAA,EDyB0B,eCzB1B;;;;;;ADWnC;AAAgC,cCXnB,qBAAA,YAAiC,SDWd,CAAA;UACU,IAAA;UAG9B,QAAA;UACU,WAAA;UAIV,aAAA;UACU,MAAA;EAAoB,QAAA,kBAAA;EAI1B,QAAA,iBAAqB;EAAA,QAAA,aAAA;SAAY,CAAA,EAAA,CAAA,KAAA,ECZ9B,KDY8B,EAAA,GAAA,IAAA;SAAY,CAAA,EAAA,GAAA,GAAA,IAAA;EAAe,WAAA,CAAA,IAAA,ECTjD,WDSiD;;;;ECzB/D,WAAA,CAAA,OAAA,EAAA,OAAsB,CAAA,EAAA,IAAA;EAAA,IAAA,CAAA,OAAA,EA8FpB,OA9FoB,CAAA,EAAA,IAAA;WAahB,CAAA,OAAA,EAAA,CAAA,OAAA,EAiGW,OAjGX,EAAA,GAAA,IAAA,CAAA,EAAA,IAAA;OAGQ,CAAA,CAAA,EAAA,IAAA;MA8EZ,UAAA,CAAA,CAAA,EA0BI,mBA1BJ;UAgBe,CAAA,CAAA,EAcjB,cAdiB;;;;;AAuB9B;AAAuC,cAA1B,yBAAA,YAAqC,SAAX,CAAA;UAUpB,IAAA;UAGQ,QAAA;UA+BZ,WAAA;UAgBe,aAAA;UASX,MAAA;SAIN,CAAA,EAAA,CAAA,KAAA,EA/DM,KA+DN,EAAA,GAAA,IAAA;SAzEqC,CAAA,EAAA,GAAA,GAAA,IAAA;EAAS,WAAA,CAAA,IAAA,EAahC,WAbgC;;gBA4C5C;+BAgBe;;oBASX;cAIN"}
@@ -0,0 +1,79 @@
1
+ import { n as TransportReadyState, p as Message, r as TransportStats, t as Transport } from "./base.js";
2
+ import { a as decodeBinaryMessage, c as WebSocketTransportOptions, i as BinaryWorkerTransport, n as WorkerTransport, o as encodeBinaryMessage, r as BinaryWorkerSelfTransport, s as WebSocketTransport, t as WorkerSelfTransport } from "./worker-transport.js";
3
+ import { n as WebSocketServerTransport, t as WebSocketLike } from "./ws-server-transport.js";
4
+
5
+ //#region src/transport/comlink-adapter.d.ts
6
+
7
+ /**
8
+ * Adapts a Transport into a Comlink-compatible Endpoint.
9
+ *
10
+ * This allows using Comlink's RPC-style API over any async-dom transport.
11
+ * Requires `comlink` as a peer dependency.
12
+ *
13
+ * Usage:
14
+ * ```ts
15
+ * import * as Comlink from 'comlink';
16
+ * import { createComlinkEndpoint } from '@lifeart/async-dom/transport';
17
+ *
18
+ * const endpoint = createComlinkEndpoint(transport);
19
+ * const api = Comlink.wrap(endpoint);
20
+ * ```
21
+ */
22
+ interface ComlinkEndpoint {
23
+ postMessage(message: unknown, transfer?: Transferable[]): void;
24
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
25
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
26
+ }
27
+ declare function createComlinkEndpoint(transport: Transport): ComlinkEndpoint;
28
+ //#endregion
29
+ //#region src/transport/shared-worker-transport.d.ts
30
+ /**
31
+ * Transport implementation using a SharedWorker MessagePort.
32
+ * Used on the main thread side to communicate with a SharedWorker.
33
+ */
34
+ declare class SharedWorkerTransport implements Transport {
35
+ private port;
36
+ private handlers;
37
+ private _readyState;
38
+ private _statsEnabled;
39
+ private _stats;
40
+ private _heartbeatInterval;
41
+ private _heartbeatTimeout;
42
+ private _awaitingPong;
43
+ onError?: (error: Error) => void;
44
+ onClose?: () => void;
45
+ constructor(port: MessagePort);
46
+ private _startHeartbeat;
47
+ private _clearHeartbeatTimeout;
48
+ private _stopHeartbeat;
49
+ enableStats(enabled: boolean): void;
50
+ send(message: Message): void;
51
+ onMessage(handler: (message: Message) => void): void;
52
+ close(): void;
53
+ get readyState(): TransportReadyState;
54
+ getStats(): TransportStats;
55
+ }
56
+ /**
57
+ * Transport implementation used inside a SharedWorker.
58
+ * Communicates with the main thread via a MessagePort received from the connect event.
59
+ */
60
+ declare class SharedWorkerSelfTransport implements Transport {
61
+ private port;
62
+ private handlers;
63
+ private _readyState;
64
+ private _statsEnabled;
65
+ private _stats;
66
+ onError?: (error: Error) => void;
67
+ onClose?: () => void;
68
+ constructor(port: MessagePort);
69
+ enableStats(enabled: boolean): void;
70
+ send(message: Message): void;
71
+ onMessage(handler: (message: Message) => void): void;
72
+ close(): void;
73
+ get readyState(): TransportReadyState;
74
+ getStats(): TransportStats;
75
+ }
76
+ //# sourceMappingURL=shared-worker-transport.d.ts.map
77
+ //#endregion
78
+ export { BinaryWorkerSelfTransport, BinaryWorkerTransport, type ComlinkEndpoint, SharedWorkerSelfTransport, SharedWorkerTransport, type Transport, type TransportReadyState, type TransportStats, type WebSocketLike, WebSocketServerTransport, WebSocketTransport, type WebSocketTransportOptions, WorkerSelfTransport, WorkerTransport, createComlinkEndpoint, decodeBinaryMessage, encodeBinaryMessage };
79
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","names":[],"sources":["../src/transport/comlink-adapter.ts","../src/transport/shared-worker-transport.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAkBA;;;;;;;;AAcA;;;AAA6D,UAd5C,eAAA,CAc4C;EAAe,WAAA,CAAA,OAAA,EAAA,OAAA,EAAA,QAAA,CAAA,EAblC,YAakC,EAAA,CAAA,EAAA,IAAA;2CAVhE,wDACU;8CAIV,wDACU;;ACrBT,iBDyBG,qBAAA,CCzBmB,SAAA,EDyBc,SCzBd,CAAA,EDyB0B,eCzB1B;;;;;;ADWnC;AAAgC,cCXnB,qBAAA,YAAiC,SDWd,CAAA;UACU,IAAA;UAG9B,QAAA;UACU,WAAA;UAIV,aAAA;UACU,MAAA;EAAoB,QAAA,kBAAA;EAI1B,QAAA,iBAAqB;EAAA,QAAA,aAAA;SAAY,CAAA,EAAA,CAAA,KAAA,ECZ9B,KDY8B,EAAA,GAAA,IAAA;SAAY,CAAA,EAAA,GAAA,GAAA,IAAA;EAAe,WAAA,CAAA,IAAA,ECTjD,WDSiD;;;;ECzB/D,WAAA,CAAA,OAAA,EAAA,OAAsB,CAAA,EAAA,IAAA;EAAA,IAAA,CAAA,OAAA,EA8FpB,OA9FoB,CAAA,EAAA,IAAA;WAahB,CAAA,OAAA,EAAA,CAAA,OAAA,EAiGW,OAjGX,EAAA,GAAA,IAAA,CAAA,EAAA,IAAA;OAGQ,CAAA,CAAA,EAAA,IAAA;MA8EZ,UAAA,CAAA,CAAA,EA0BI,mBA1BJ;UAgBe,CAAA,CAAA,EAcjB,cAdiB;;;;;AAuB9B;AAAuC,cAA1B,yBAAA,YAAqC,SAAX,CAAA;UAUpB,IAAA;UAGQ,QAAA;UA+BZ,WAAA;UAgBe,aAAA;UASX,MAAA;SAIN,CAAA,EAAA,CAAA,KAAA,EA/DM,KA+DN,EAAA,GAAA,IAAA;SAzEqC,CAAA,EAAA,GAAA,GAAA,IAAA;EAAS,WAAA,CAAA,IAAA,EAahC,WAbgC;;gBA4C5C;+BAgBe;;oBASX;cAIN"}
@@ -0,0 +1,202 @@
1
+ import { a as encodeBinaryMessage, i as decodeBinaryMessage, n as BinaryWorkerSelfTransport, r as BinaryWorkerTransport, t as WebSocketTransport } from "./ws-transport.js";
2
+ import { n as WorkerTransport, t as WorkerSelfTransport } from "./worker-transport.js";
3
+ import { t as WebSocketServerTransport } from "./ws-server-transport.js";
4
+ //#region src/transport/comlink-adapter.ts
5
+ function createComlinkEndpoint(transport) {
6
+ const listeners = /* @__PURE__ */ new Set();
7
+ transport.onMessage((message) => {
8
+ const event = new MessageEvent("message", { data: message });
9
+ for (const listener of listeners) if (typeof listener === "function") listener(event);
10
+ else listener.handleEvent(event);
11
+ });
12
+ return {
13
+ postMessage(message) {
14
+ transport.send(message);
15
+ },
16
+ addEventListener(_type, listener) {
17
+ listeners.add(listener);
18
+ },
19
+ removeEventListener(_type, listener) {
20
+ listeners.delete(listener);
21
+ }
22
+ };
23
+ }
24
+ //#endregion
25
+ //#region src/transport/shared-worker-transport.ts
26
+ /**
27
+ * Transport implementation using a SharedWorker MessagePort.
28
+ * Used on the main thread side to communicate with a SharedWorker.
29
+ */
30
+ var SharedWorkerTransport = class {
31
+ handlers = [];
32
+ _readyState = "open";
33
+ _statsEnabled = false;
34
+ _stats = {
35
+ messageCount: 0,
36
+ totalBytes: 0,
37
+ largestMessageBytes: 0,
38
+ lastMessageBytes: 0
39
+ };
40
+ _heartbeatInterval = null;
41
+ _heartbeatTimeout = null;
42
+ _awaitingPong = false;
43
+ onError;
44
+ onClose;
45
+ constructor(port) {
46
+ this.port = port;
47
+ port.onmessage = (e) => {
48
+ const data = e.data;
49
+ if (data && typeof data === "object" && data.type === "pong") {
50
+ this._awaitingPong = false;
51
+ this._clearHeartbeatTimeout();
52
+ return;
53
+ }
54
+ for (const h of this.handlers) try {
55
+ h(data);
56
+ } catch (err) {
57
+ console.error("[async-dom] Handler error:", err);
58
+ }
59
+ };
60
+ port.onmessageerror = () => {
61
+ const error = /* @__PURE__ */ new Error("SharedWorker message deserialization failed");
62
+ this.onError?.(error);
63
+ };
64
+ try {
65
+ port.addEventListener("close", () => {
66
+ this._stopHeartbeat();
67
+ if (this._readyState !== "closed") {
68
+ this._readyState = "closed";
69
+ this.onClose?.();
70
+ }
71
+ });
72
+ } catch {}
73
+ this._startHeartbeat();
74
+ }
75
+ _startHeartbeat() {
76
+ this._heartbeatInterval = setInterval(() => {
77
+ if (this._readyState !== "open") {
78
+ this._stopHeartbeat();
79
+ return;
80
+ }
81
+ if (this._awaitingPong) return;
82
+ this._awaitingPong = true;
83
+ this.port.postMessage({ type: "ping" });
84
+ this._heartbeatTimeout = setTimeout(() => {
85
+ if (this._readyState !== "closed") {
86
+ this._readyState = "closed";
87
+ this._stopHeartbeat();
88
+ this.onClose?.();
89
+ }
90
+ }, 15e3);
91
+ }, 5e3);
92
+ }
93
+ _clearHeartbeatTimeout() {
94
+ if (this._heartbeatTimeout !== null) {
95
+ clearTimeout(this._heartbeatTimeout);
96
+ this._heartbeatTimeout = null;
97
+ }
98
+ }
99
+ _stopHeartbeat() {
100
+ this._clearHeartbeatTimeout();
101
+ if (this._heartbeatInterval !== null) {
102
+ clearInterval(this._heartbeatInterval);
103
+ this._heartbeatInterval = null;
104
+ }
105
+ }
106
+ enableStats(enabled) {
107
+ this._statsEnabled = enabled;
108
+ }
109
+ send(message) {
110
+ if (this._readyState !== "open") return;
111
+ if (this._statsEnabled) {
112
+ const size = JSON.stringify(message).length;
113
+ this._stats.messageCount++;
114
+ this._stats.totalBytes += size;
115
+ this._stats.lastMessageBytes = size;
116
+ if (size > this._stats.largestMessageBytes) this._stats.largestMessageBytes = size;
117
+ }
118
+ this.port.postMessage(message);
119
+ }
120
+ onMessage(handler) {
121
+ this.handlers.push(handler);
122
+ }
123
+ close() {
124
+ this._stopHeartbeat();
125
+ this._readyState = "closed";
126
+ this.port.close();
127
+ }
128
+ get readyState() {
129
+ return this._readyState;
130
+ }
131
+ getStats() {
132
+ return { ...this._stats };
133
+ }
134
+ };
135
+ /**
136
+ * Transport implementation used inside a SharedWorker.
137
+ * Communicates with the main thread via a MessagePort received from the connect event.
138
+ */
139
+ var SharedWorkerSelfTransport = class {
140
+ handlers = [];
141
+ _readyState = "open";
142
+ _statsEnabled = false;
143
+ _stats = {
144
+ messageCount: 0,
145
+ totalBytes: 0,
146
+ largestMessageBytes: 0,
147
+ lastMessageBytes: 0
148
+ };
149
+ onError;
150
+ onClose;
151
+ constructor(port) {
152
+ this.port = port;
153
+ port.onmessage = (e) => {
154
+ const data = e.data;
155
+ if (data && typeof data === "object" && data.type === "ping") {
156
+ port.postMessage({ type: "pong" });
157
+ return;
158
+ }
159
+ for (const h of this.handlers) try {
160
+ h(data);
161
+ } catch (err) {
162
+ console.error("[async-dom] Handler error:", err);
163
+ }
164
+ };
165
+ port.onmessageerror = () => {
166
+ const error = /* @__PURE__ */ new Error("SharedWorker message deserialization failed");
167
+ this.onError?.(error);
168
+ };
169
+ port.start();
170
+ }
171
+ enableStats(enabled) {
172
+ this._statsEnabled = enabled;
173
+ }
174
+ send(message) {
175
+ if (this._readyState !== "open") return;
176
+ if (this._statsEnabled) {
177
+ const size = JSON.stringify(message).length;
178
+ this._stats.messageCount++;
179
+ this._stats.totalBytes += size;
180
+ this._stats.lastMessageBytes = size;
181
+ if (size > this._stats.largestMessageBytes) this._stats.largestMessageBytes = size;
182
+ }
183
+ this.port.postMessage(message);
184
+ }
185
+ onMessage(handler) {
186
+ this.handlers.push(handler);
187
+ }
188
+ close() {
189
+ this._readyState = "closed";
190
+ this.port.close();
191
+ }
192
+ get readyState() {
193
+ return this._readyState;
194
+ }
195
+ getStats() {
196
+ return { ...this._stats };
197
+ }
198
+ };
199
+ //#endregion
200
+ export { BinaryWorkerSelfTransport, BinaryWorkerTransport, SharedWorkerSelfTransport, SharedWorkerTransport, WebSocketServerTransport, WebSocketTransport, WorkerSelfTransport, WorkerTransport, createComlinkEndpoint, decodeBinaryMessage, encodeBinaryMessage };
201
+
202
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","names":[],"sources":["../src/transport/comlink-adapter.ts","../src/transport/shared-worker-transport.ts"],"sourcesContent":["import type { Message } from \"../core/protocol.ts\";\nimport type { Transport, TransportReadyState } from \"./base.ts\";\n\n/**\n * Adapts a Transport into a Comlink-compatible Endpoint.\n *\n * This allows using Comlink's RPC-style API over any async-dom transport.\n * Requires `comlink` as a peer dependency.\n *\n * Usage:\n * ```ts\n * import * as Comlink from 'comlink';\n * import { createComlinkEndpoint } from '@lifeart/async-dom/transport';\n *\n * const endpoint = createComlinkEndpoint(transport);\n * const api = Comlink.wrap(endpoint);\n * ```\n */\nexport interface ComlinkEndpoint {\n\tpostMessage(message: unknown, transfer?: Transferable[]): void;\n\taddEventListener(\n\t\ttype: string,\n\t\tlistener: EventListenerOrEventListenerObject,\n\t\toptions?: boolean | AddEventListenerOptions,\n\t): void;\n\tremoveEventListener(\n\t\ttype: string,\n\t\tlistener: EventListenerOrEventListenerObject,\n\t\toptions?: boolean | EventListenerOptions,\n\t): void;\n}\n\nexport function createComlinkEndpoint(transport: Transport): ComlinkEndpoint {\n\tconst listeners = new Set<EventListenerOrEventListenerObject>();\n\n\ttransport.onMessage((message: Message) => {\n\t\tconst event = new MessageEvent(\"message\", { data: message });\n\t\tfor (const listener of listeners) {\n\t\t\tif (typeof listener === \"function\") {\n\t\t\t\tlistener(event);\n\t\t\t} else {\n\t\t\t\tlistener.handleEvent(event);\n\t\t\t}\n\t\t}\n\t});\n\n\treturn {\n\t\tpostMessage(message: unknown) {\n\t\t\ttransport.send(message as Message);\n\t\t},\n\t\taddEventListener(_type: string, listener: EventListenerOrEventListenerObject) {\n\t\t\tlisteners.add(listener);\n\t\t},\n\t\tremoveEventListener(_type: string, listener: EventListenerOrEventListenerObject) {\n\t\t\tlisteners.delete(listener);\n\t\t},\n\t};\n}\n\nexport type { Transport, TransportReadyState };\n","import type { Message } from \"../core/protocol.ts\";\nimport type { Transport, TransportReadyState, TransportStats } from \"./base.ts\";\n\n/**\n * Transport implementation using a SharedWorker MessagePort.\n * Used on the main thread side to communicate with a SharedWorker.\n */\nexport class SharedWorkerTransport implements Transport {\n\tprivate handlers: Array<(message: Message) => void> = [];\n\tprivate _readyState: TransportReadyState = \"open\";\n\tprivate _statsEnabled = false;\n\tprivate _stats: TransportStats = {\n\t\tmessageCount: 0,\n\t\ttotalBytes: 0,\n\t\tlargestMessageBytes: 0,\n\t\tlastMessageBytes: 0,\n\t};\n\tprivate _heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n\tprivate _heartbeatTimeout: ReturnType<typeof setTimeout> | null = null;\n\tprivate _awaitingPong = false;\n\tonError?: (error: Error) => void;\n\tonClose?: () => void;\n\n\tconstructor(private port: MessagePort) {\n\t\tport.onmessage = (e: MessageEvent) => {\n\t\t\tconst data = e.data;\n\t\t\t// Handle pong responses for heartbeat — don't forward to app handlers\n\t\t\tif (data && typeof data === \"object\" && data.type === \"pong\") {\n\t\t\t\tthis._awaitingPong = false;\n\t\t\t\tthis._clearHeartbeatTimeout();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const h of this.handlers) {\n\t\t\t\ttry {\n\t\t\t\t\th(data as Message);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(\"[async-dom] Handler error:\", err);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tport.onmessageerror = () => {\n\t\t\tconst error = new Error(\"SharedWorker message deserialization failed\");\n\t\t\tthis.onError?.(error);\n\t\t};\n\n\t\t// Chrome 122+ supports close event on MessagePort for instant detection\n\t\ttry {\n\t\t\tport.addEventListener(\"close\", () => {\n\t\t\t\tthis._stopHeartbeat();\n\t\t\t\tif (this._readyState !== \"closed\") {\n\t\t\t\t\tthis._readyState = \"closed\";\n\t\t\t\t\tthis.onClose?.();\n\t\t\t\t}\n\t\t\t});\n\t\t} catch {\n\t\t\t// Not supported in this browser — heartbeat handles it\n\t\t}\n\n\t\tthis._startHeartbeat();\n\t}\n\n\tprivate _startHeartbeat(): void {\n\t\tthis._heartbeatInterval = setInterval(() => {\n\t\t\tif (this._readyState !== \"open\") {\n\t\t\t\tthis._stopHeartbeat();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Only send a new ping if we're not still waiting for a pong\n\t\t\tif (this._awaitingPong) return;\n\t\t\tthis._awaitingPong = true;\n\t\t\tthis.port.postMessage({ type: \"ping\" });\n\t\t\tthis._heartbeatTimeout = setTimeout(() => {\n\t\t\t\tif (this._readyState !== \"closed\") {\n\t\t\t\t\tthis._readyState = \"closed\";\n\t\t\t\t\tthis._stopHeartbeat();\n\t\t\t\t\tthis.onClose?.();\n\t\t\t\t}\n\t\t\t}, 15_000);\n\t\t}, 5_000);\n\t}\n\n\tprivate _clearHeartbeatTimeout(): void {\n\t\tif (this._heartbeatTimeout !== null) {\n\t\t\tclearTimeout(this._heartbeatTimeout);\n\t\t\tthis._heartbeatTimeout = null;\n\t\t}\n\t}\n\n\tprivate _stopHeartbeat(): void {\n\t\tthis._clearHeartbeatTimeout();\n\t\tif (this._heartbeatInterval !== null) {\n\t\t\tclearInterval(this._heartbeatInterval);\n\t\t\tthis._heartbeatInterval = null;\n\t\t}\n\t}\n\n\tenableStats(enabled: boolean): void {\n\t\tthis._statsEnabled = enabled;\n\t}\n\n\tsend(message: Message): void {\n\t\tif (this._readyState !== \"open\") {\n\t\t\treturn;\n\t\t}\n\t\tif (this._statsEnabled) {\n\t\t\tconst size = JSON.stringify(message).length;\n\t\t\tthis._stats.messageCount++;\n\t\t\tthis._stats.totalBytes += size;\n\t\t\tthis._stats.lastMessageBytes = size;\n\t\t\tif (size > this._stats.largestMessageBytes) {\n\t\t\t\tthis._stats.largestMessageBytes = size;\n\t\t\t}\n\t\t}\n\t\tthis.port.postMessage(message);\n\t}\n\n\tonMessage(handler: (message: Message) => void): void {\n\t\tthis.handlers.push(handler);\n\t}\n\n\tclose(): void {\n\t\tthis._stopHeartbeat();\n\t\tthis._readyState = \"closed\";\n\t\tthis.port.close();\n\t}\n\n\tget readyState(): TransportReadyState {\n\t\treturn this._readyState;\n\t}\n\n\tgetStats(): TransportStats {\n\t\treturn { ...this._stats };\n\t}\n}\n\n/**\n * Transport implementation used inside a SharedWorker.\n * Communicates with the main thread via a MessagePort received from the connect event.\n */\nexport class SharedWorkerSelfTransport implements Transport {\n\tprivate handlers: Array<(message: Message) => void> = [];\n\tprivate _readyState: TransportReadyState = \"open\";\n\tprivate _statsEnabled = false;\n\tprivate _stats: TransportStats = {\n\t\tmessageCount: 0,\n\t\ttotalBytes: 0,\n\t\tlargestMessageBytes: 0,\n\t\tlastMessageBytes: 0,\n\t};\n\tonError?: (error: Error) => void;\n\tonClose?: () => void;\n\n\tconstructor(private port: MessagePort) {\n\t\tport.onmessage = (e: MessageEvent) => {\n\t\t\tconst data = e.data;\n\t\t\t// Respond to ping with pong automatically — don't forward to app handlers\n\t\t\tif (data && typeof data === \"object\" && data.type === \"ping\") {\n\t\t\t\tport.postMessage({ type: \"pong\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const h of this.handlers) {\n\t\t\t\ttry {\n\t\t\t\t\th(data as Message);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(\"[async-dom] Handler error:\", err);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tport.onmessageerror = () => {\n\t\t\tconst error = new Error(\"SharedWorker message deserialization failed\");\n\t\t\tthis.onError?.(error);\n\t\t};\n\n\t\t// Explicit start() required when using addEventListener pattern,\n\t\t// but also safe to call with onmessage assignment\n\t\tport.start();\n\t}\n\n\tenableStats(enabled: boolean): void {\n\t\tthis._statsEnabled = enabled;\n\t}\n\n\tsend(message: Message): void {\n\t\tif (this._readyState !== \"open\") {\n\t\t\treturn;\n\t\t}\n\t\tif (this._statsEnabled) {\n\t\t\tconst size = JSON.stringify(message).length;\n\t\t\tthis._stats.messageCount++;\n\t\t\tthis._stats.totalBytes += size;\n\t\t\tthis._stats.lastMessageBytes = size;\n\t\t\tif (size > this._stats.largestMessageBytes) {\n\t\t\t\tthis._stats.largestMessageBytes = size;\n\t\t\t}\n\t\t}\n\t\tthis.port.postMessage(message);\n\t}\n\n\tonMessage(handler: (message: Message) => void): void {\n\t\tthis.handlers.push(handler);\n\t}\n\n\tclose(): void {\n\t\tthis._readyState = \"closed\";\n\t\tthis.port.close();\n\t}\n\n\tget readyState(): TransportReadyState {\n\t\treturn this._readyState;\n\t}\n\n\tgetStats(): TransportStats {\n\t\treturn { ...this._stats };\n\t}\n}\n"],"mappings":"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"}