@ccheever/exact-ibex-runtime 0.1.0
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.
- package/package.json +63 -0
- package/src/abort/AbortController.ts +23 -0
- package/src/abort/AbortSignal.ts +152 -0
- package/src/abort/index.ts +2 -0
- package/src/accessibility.ts +12 -0
- package/src/arraybuffer-detach.ts +109 -0
- package/src/base64/base64.ts +168 -0
- package/src/base64/index.ts +1 -0
- package/src/blob/Blob.ts +259 -0
- package/src/blob/File.ts +59 -0
- package/src/blob/FormData.ts +323 -0
- package/src/blob/index.ts +3 -0
- package/src/bootstrap.ts +1946 -0
- package/src/broadcast/BroadcastChannel.ts +280 -0
- package/src/broadcast/index.ts +5 -0
- package/src/cache/Cache.ts +349 -0
- package/src/cache/CacheStorage.ts +89 -0
- package/src/cache/index.ts +27 -0
- package/src/camera/index.ts +6202 -0
- package/src/camera/processor.worker.ts +194 -0
- package/src/camera/scene.ts +195 -0
- package/src/clipboard/Clipboard.ts +129 -0
- package/src/clipboard/ClipboardItem.ts +97 -0
- package/src/clipboard/index.ts +6 -0
- package/src/clone/index.ts +1 -0
- package/src/clone/structuredClone.ts +389 -0
- package/src/clone/transferableSymbols.ts +2 -0
- package/src/compression/CompressionStream.ts +146 -0
- package/src/compression/DecompressionStream.ts +342 -0
- package/src/compression/index.ts +4 -0
- package/src/console/Console.ts +341 -0
- package/src/console/index.ts +2 -0
- package/src/core/accessibility-state.ts +263 -0
- package/src/core/accessibility.ts +184 -0
- package/src/core/agent-state.ts +37 -0
- package/src/core/diagnostics-logs.ts +144 -0
- package/src/core/host-call-bridge.ts +16 -0
- package/src/core/i18n-helpers.ts +189 -0
- package/src/core/locale-state.ts +253 -0
- package/src/core/locale.ts +95 -0
- package/src/crypto/Crypto.ts +2743 -0
- package/src/crypto/index.ts +1 -0
- package/src/diagnostics/logs.ts +7 -0
- package/src/encoding/TextDecoder.ts +1181 -0
- package/src/encoding/TextDecoderStream.ts +58 -0
- package/src/encoding/TextEncoder.ts +180 -0
- package/src/encoding/TextEncoderStream.ts +39 -0
- package/src/encoding/index.ts +8 -0
- package/src/events/CloseEvent.ts +91 -0
- package/src/events/DOMException.ts +409 -0
- package/src/events/ErrorEvent.ts +39 -0
- package/src/events/Event.ts +151 -0
- package/src/events/EventTarget.ts +280 -0
- package/src/events/FocusEvent.ts +27 -0
- package/src/events/KeyboardEvent.ts +46 -0
- package/src/events/MessageEvent.ts +61 -0
- package/src/events/ProgressEvent.ts +33 -0
- package/src/events/PromiseRejectionEvent.ts +31 -0
- package/src/events/index.ts +52 -0
- package/src/eventsource/EventSource.ts +371 -0
- package/src/eventsource/index.ts +2 -0
- package/src/fetch/Headers.ts +642 -0
- package/src/fetch/Request.ts +760 -0
- package/src/fetch/Response.ts +543 -0
- package/src/fetch/body.ts +1256 -0
- package/src/fetch/cookie-jar.ts +566 -0
- package/src/fetch/demo.ts +207 -0
- package/src/fetch/errors.ts +101 -0
- package/src/fetch/fetch.ts +2610 -0
- package/src/fetch/index.ts +101 -0
- package/src/fetch/native-bridge.ts +65 -0
- package/src/fetch/types.ts +258 -0
- package/src/filereader/FileReader.ts +236 -0
- package/src/filereader/index.ts +1 -0
- package/src/fs/Dirent.ts +39 -0
- package/src/fs/ExactFile.ts +450 -0
- package/src/fs/Stats.ts +80 -0
- package/src/fs/index.ts +944 -0
- package/src/fs/promises.ts +386 -0
- package/src/fs/shared.ts +328 -0
- package/src/http-server/index.js +697 -0
- package/src/http-server/index.ts +27 -0
- package/src/identity.generated.ts +14 -0
- package/src/index.ts +283 -0
- package/src/indexeddb/IDBCursor.ts +188 -0
- package/src/indexeddb/IDBDatabase.ts +343 -0
- package/src/indexeddb/IDBFactory.ts +269 -0
- package/src/indexeddb/IDBIndex.ts +194 -0
- package/src/indexeddb/IDBKeyRange.ts +109 -0
- package/src/indexeddb/IDBObjectStore.ts +468 -0
- package/src/indexeddb/IDBRequest.ts +163 -0
- package/src/indexeddb/IDBTransaction.ts +207 -0
- package/src/indexeddb/index.ts +34 -0
- package/src/indexeddb/utils.ts +52 -0
- package/src/inspect/index.ts +1 -0
- package/src/inspect/inspect.ts +465 -0
- package/src/internal/detect.ts +104 -0
- package/src/locale.ts +10 -0
- package/src/location/index.ts +1059 -0
- package/src/locks/LockManager.ts +460 -0
- package/src/locks/index.ts +12 -0
- package/src/media/VideoFrame.ts +58 -0
- package/src/messaging/MessageChannel.ts +31 -0
- package/src/messaging/MessagePort.ts +180 -0
- package/src/messaging/index.ts +2 -0
- package/src/messaging.ts +247 -0
- package/src/native/NativeModules.ts +354 -0
- package/src/native/index.ts +1 -0
- package/src/navigator/Navigator.ts +351 -0
- package/src/navigator/index.ts +1 -0
- package/src/node/Buffer.ts +1786 -0
- package/src/node/index.ts +4 -0
- package/src/node/path.ts +495 -0
- package/src/node/process.ts +2528 -0
- package/src/performance/Performance.ts +532 -0
- package/src/performance/index.ts +21 -0
- package/src/polyfills/array.ts +236 -0
- package/src/polyfills/arraybuffer.ts +172 -0
- package/src/polyfills/groupby.ts +85 -0
- package/src/polyfills/index.ts +85 -0
- package/src/polyfills/intl.ts +1956 -0
- package/src/polyfills/iterator.ts +479 -0
- package/src/polyfills/promise.ts +37 -0
- package/src/polyfills/set.ts +245 -0
- package/src/polyfills/string.ts +85 -0
- package/src/polyfills/typedarray.ts +110 -0
- package/src/promise-rejection-tracking.ts +464 -0
- package/src/react-native/index.ts +388 -0
- package/src/runtime-entry.ts +55 -0
- package/src/scheduling/AnimationFrame.ts +105 -0
- package/src/scheduling/IdleCallback.ts +167 -0
- package/src/scheduling/index.ts +13 -0
- package/src/security/Capabilities.ts +1146 -0
- package/src/security/Permissions.ts +392 -0
- package/src/security/capability-bits.generated.ts +63 -0
- package/src/security/index.ts +16 -0
- package/src/sqlite/Database.ts +456 -0
- package/src/sqlite/Statement.ts +206 -0
- package/src/sqlite/constants.ts +79 -0
- package/src/sqlite/errors.ts +25 -0
- package/src/sqlite/index.ts +34 -0
- package/src/sqlite/module.js +438 -0
- package/src/storage/Storage.ts +291 -0
- package/src/storage/StorageManager.ts +91 -0
- package/src/storage/index.ts +3 -0
- package/src/stream-compat.ts +47 -0
- package/src/streams/ReadableStream.ts +4131 -0
- package/src/streams/TransformStream.ts +375 -0
- package/src/streams/WritableStream.ts +866 -0
- package/src/streams/index.ts +41 -0
- package/src/timers/Timers.ts +296 -0
- package/src/timers/index.ts +11 -0
- package/src/url/URL.ts +656 -0
- package/src/url/URLPattern.ts +850 -0
- package/src/url/URLSearchParams.ts +244 -0
- package/src/url/index.ts +9 -0
- package/src/websocket/WebSocket.ts +770 -0
- package/src/websocket/WebSocketError.ts +52 -0
- package/src/websocket/WebSocketStream.ts +628 -0
- package/src/websocket/index.ts +7 -0
- package/src/window/index.ts +872 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* MessagePort implementation for Ibex runtime
|
|
4
|
+
*
|
|
5
|
+
* Implements the HTML MessagePort API for two-way communication.
|
|
6
|
+
* @see https://html.spec.whatwg.org/multipage/web-messaging.html#message-ports
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { EventTarget } from '../events/EventTarget';
|
|
10
|
+
import { MessageEvent } from '../events/MessageEvent';
|
|
11
|
+
import { structuredClone } from '../clone/structuredClone';
|
|
12
|
+
import { structuredCloneTransferSymbol } from '../clone/transferableSymbols';
|
|
13
|
+
|
|
14
|
+
// Store for port pairs - weak references to avoid memory leaks
|
|
15
|
+
const portPairs = new WeakMap<MessagePort, MessagePort>();
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* MessagePort represents one end of a two-way communication channel.
|
|
19
|
+
* Messages sent through one port are received by the other port.
|
|
20
|
+
*/
|
|
21
|
+
export class MessagePort extends EventTarget {
|
|
22
|
+
#started = false;
|
|
23
|
+
#closed = false;
|
|
24
|
+
#queue: Array<{ data: any; transfer: Transferable[] }> = [];
|
|
25
|
+
#onmessage: ((this: MessagePort, ev: MessageEvent) => any) | null = null;
|
|
26
|
+
#onmessageerror: ((this: MessagePort, ev: MessageEvent) => any) | null = null;
|
|
27
|
+
|
|
28
|
+
constructor() {
|
|
29
|
+
super();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get onmessage(): ((this: MessagePort, ev: MessageEvent) => any) | null {
|
|
33
|
+
return this.#onmessage;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
set onmessage(value: ((this: MessagePort, ev: MessageEvent) => any) | null) {
|
|
37
|
+
this.#onmessage = value;
|
|
38
|
+
if (value !== null) {
|
|
39
|
+
this.start();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get onmessageerror(): ((this: MessagePort, ev: MessageEvent) => any) | null {
|
|
44
|
+
return this.#onmessageerror;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
set onmessageerror(value: ((this: MessagePort, ev: MessageEvent) => any) | null) {
|
|
48
|
+
this.#onmessageerror = value;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Posts a message through the channel.
|
|
53
|
+
* The message is cloned using the structured clone algorithm.
|
|
54
|
+
*/
|
|
55
|
+
postMessage(message: any, transfer?: Transferable[]): void;
|
|
56
|
+
postMessage(message: any, options?: StructuredSerializeOptions): void;
|
|
57
|
+
postMessage(message: any, transferOrOptions?: Transferable[] | StructuredSerializeOptions): void {
|
|
58
|
+
if (this.#closed) {
|
|
59
|
+
return; // Silently ignore messages on closed ports
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const transfer: Transferable[] = Array.isArray(transferOrOptions)
|
|
63
|
+
? transferOrOptions
|
|
64
|
+
: (transferOrOptions?.transfer ?? []);
|
|
65
|
+
|
|
66
|
+
const otherPort = portPairs.get(this);
|
|
67
|
+
if (!otherPort) {
|
|
68
|
+
return; // No paired port, message is lost
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Clone the message
|
|
72
|
+
const clonedMessage = structuredClone(message, { transfer });
|
|
73
|
+
|
|
74
|
+
// Queue or deliver the message
|
|
75
|
+
if (otherPort.#started) {
|
|
76
|
+
otherPort._deliverMessage(clonedMessage, []);
|
|
77
|
+
} else {
|
|
78
|
+
otherPort.#queue.push({ data: clonedMessage, transfer: [] });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Begins dispatching messages received on the port.
|
|
84
|
+
* Messages are held in a queue until start() is called.
|
|
85
|
+
*/
|
|
86
|
+
start(): void {
|
|
87
|
+
if (this.#started || this.#closed) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
this.#started = true;
|
|
92
|
+
|
|
93
|
+
// Deliver queued messages
|
|
94
|
+
const queue = this.#queue;
|
|
95
|
+
this.#queue = [];
|
|
96
|
+
|
|
97
|
+
for (const { data, transfer } of queue) {
|
|
98
|
+
this._deliverMessage(data, transfer);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Disconnects the port, preventing any further messages.
|
|
104
|
+
*/
|
|
105
|
+
close(): void {
|
|
106
|
+
this.#closed = true;
|
|
107
|
+
this.#started = false;
|
|
108
|
+
this.#queue = [];
|
|
109
|
+
|
|
110
|
+
// Disconnect from paired port
|
|
111
|
+
const otherPort = portPairs.get(this);
|
|
112
|
+
if (otherPort) {
|
|
113
|
+
portPairs.delete(this);
|
|
114
|
+
portPairs.delete(otherPort);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Internal method to deliver a message to this port.
|
|
120
|
+
*/
|
|
121
|
+
_deliverMessage(data: any, ports: MessagePort[]): void {
|
|
122
|
+
// Dispatch asynchronously per spec
|
|
123
|
+
queueMicrotask(() => {
|
|
124
|
+
if (this.#closed) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const event = new MessageEvent('message', {
|
|
129
|
+
data,
|
|
130
|
+
origin: '',
|
|
131
|
+
lastEventId: '',
|
|
132
|
+
source: null,
|
|
133
|
+
ports,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Call onmessage handler
|
|
137
|
+
if (this.#onmessage) {
|
|
138
|
+
this.#onmessage.call(this, event);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Dispatch event
|
|
142
|
+
this.dispatchEvent(event);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Internal method to set up port pairing.
|
|
148
|
+
*/
|
|
149
|
+
static _pair(port1: MessagePort, port2: MessagePort): void {
|
|
150
|
+
portPairs.set(port1, port2);
|
|
151
|
+
portPairs.set(port2, port1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
[structuredCloneTransferSymbol](): MessagePort {
|
|
155
|
+
const transferredPort = new MessagePort();
|
|
156
|
+
const otherPort = portPairs.get(this);
|
|
157
|
+
transferredPort.#queue = this.#queue;
|
|
158
|
+
if (otherPort) {
|
|
159
|
+
portPairs.set(transferredPort, otherPort);
|
|
160
|
+
portPairs.set(otherPort, transferredPort);
|
|
161
|
+
portPairs.delete(this);
|
|
162
|
+
}
|
|
163
|
+
this.#queue = [];
|
|
164
|
+
this.#closed = true;
|
|
165
|
+
this.#started = false;
|
|
166
|
+
this.#onmessage = null;
|
|
167
|
+
this.#onmessageerror = null;
|
|
168
|
+
return transferredPort;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
get [Symbol.toStringTag](): string {
|
|
172
|
+
return 'MessagePort';
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
interface StructuredSerializeOptions {
|
|
177
|
+
transfer?: Transferable[];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export default MessagePort;
|
package/src/messaging.ts
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MessagePort and MessageChannel - Web Standard Messaging API
|
|
3
|
+
*
|
|
4
|
+
* Provides in-process message passing between ports via the structured clone
|
|
5
|
+
* algorithm. Messages are always delivered asynchronously (via queueMicrotask)
|
|
6
|
+
* to match the HTML specification behaviour.
|
|
7
|
+
*
|
|
8
|
+
* @see https://html.spec.whatwg.org/multipage/web-messaging.html#message-channels
|
|
9
|
+
* @see https://html.spec.whatwg.org/multipage/web-messaging.html#message-ports
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { EventTarget } from './events/EventTarget';
|
|
13
|
+
import { MessageEvent } from './events/MessageEvent';
|
|
14
|
+
import { structuredClone } from './clone/structuredClone';
|
|
15
|
+
import { structuredCloneTransferSymbol } from './clone/transferableSymbols';
|
|
16
|
+
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// MessagePort
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A MessagePort represents one end of a two-port message channel.
|
|
23
|
+
*
|
|
24
|
+
* The port must be *started* before it will dispatch queued messages.
|
|
25
|
+
* Setting the `onmessage` property implicitly calls `start()` (per spec).
|
|
26
|
+
* Using `addEventListener('message', ...)` does NOT auto-start; the caller
|
|
27
|
+
* must invoke `start()` explicitly.
|
|
28
|
+
*/
|
|
29
|
+
export class MessagePort extends EventTarget {
|
|
30
|
+
/** The entangled remote port, or null if not yet wired / closed. */
|
|
31
|
+
#remotePort: MessagePort | null = null;
|
|
32
|
+
|
|
33
|
+
/** Whether `start()` has been called. */
|
|
34
|
+
#started = false;
|
|
35
|
+
|
|
36
|
+
/** Whether `close()` has been called. */
|
|
37
|
+
#closed = false;
|
|
38
|
+
|
|
39
|
+
/** Messages received before `start()` was called. */
|
|
40
|
+
#queue: unknown[] = [];
|
|
41
|
+
|
|
42
|
+
/** Backing field for the `onmessage` property. */
|
|
43
|
+
#onmessage: ((this: MessagePort, ev: MessageEvent) => any) | null = null;
|
|
44
|
+
|
|
45
|
+
/** Backing field for the `onmessageerror` property. */
|
|
46
|
+
#onmessageerror: ((this: MessagePort, ev: MessageEvent) => any) | null = null;
|
|
47
|
+
|
|
48
|
+
// -- Event handler properties (IDL attributes) ---------------------------
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Setting `onmessage` implicitly calls `start()` per the HTML spec.
|
|
52
|
+
*/
|
|
53
|
+
get onmessage(): ((this: MessagePort, ev: MessageEvent) => any) | null {
|
|
54
|
+
return this.#onmessage;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
set onmessage(handler: ((this: MessagePort, ev: MessageEvent) => any) | null) {
|
|
58
|
+
this.#onmessage = handler;
|
|
59
|
+
// Per spec: setting onmessage implicitly starts the port
|
|
60
|
+
this.start();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
get onmessageerror(): ((this: MessagePort, ev: MessageEvent) => any) | null {
|
|
64
|
+
return this.#onmessageerror;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
set onmessageerror(handler: ((this: MessagePort, ev: MessageEvent) => any) | null) {
|
|
68
|
+
this.#onmessageerror = handler;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// -- Public API -----------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Post a message through this port to the entangled remote port.
|
|
75
|
+
*
|
|
76
|
+
* The `value` is cloned via `structuredClone` before delivery so that the
|
|
77
|
+
* sender and receiver hold independent copies.
|
|
78
|
+
*
|
|
79
|
+
* @param value The message payload (must be structured-cloneable).
|
|
80
|
+
* @param transferList Optional transfer list for ArrayBuffer ownership move.
|
|
81
|
+
*/
|
|
82
|
+
postMessage(value: unknown, transferList?: Transferable[]): void {
|
|
83
|
+
if (this.#closed) {
|
|
84
|
+
return; // Silently ignore per spec (sender side closed)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const remote = this.#remotePort;
|
|
88
|
+
if (!remote || remote.#closed) {
|
|
89
|
+
return; // No entangled port or remote is closed
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Clone the message data
|
|
93
|
+
let clonedData: unknown;
|
|
94
|
+
try {
|
|
95
|
+
clonedData = structuredClone(value, { transfer: transferList as ArrayBuffer[] | undefined });
|
|
96
|
+
} catch (err) {
|
|
97
|
+
// Cloning failed — dispatch messageerror on the remote port
|
|
98
|
+
queueMicrotask(() => {
|
|
99
|
+
if (!remote.#closed) {
|
|
100
|
+
remote.#dispatchMessageError(err);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Deliver asynchronously
|
|
107
|
+
if (remote.#started) {
|
|
108
|
+
queueMicrotask(() => {
|
|
109
|
+
if (!remote.#closed) {
|
|
110
|
+
remote.#dispatchMessage(clonedData);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
} else {
|
|
114
|
+
// Queue the message until the remote port is started
|
|
115
|
+
remote.#queue.push(clonedData);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Begin dispatching messages. Messages posted before `start()` is called
|
|
121
|
+
* are buffered and flushed when start is invoked.
|
|
122
|
+
*/
|
|
123
|
+
start(): void {
|
|
124
|
+
if (this.#started) {
|
|
125
|
+
return; // Idempotent
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
this.#started = true;
|
|
129
|
+
|
|
130
|
+
// Flush any queued messages
|
|
131
|
+
if (this.#queue.length > 0) {
|
|
132
|
+
const pending = this.#queue.splice(0);
|
|
133
|
+
for (const data of pending) {
|
|
134
|
+
queueMicrotask(() => {
|
|
135
|
+
if (!this.#closed) {
|
|
136
|
+
this.#dispatchMessage(data);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Disentangle this port. After calling `close()`, no more messages will
|
|
145
|
+
* be sent or received through this port.
|
|
146
|
+
*/
|
|
147
|
+
close(): void {
|
|
148
|
+
this.#closed = true;
|
|
149
|
+
this.#queue.length = 0;
|
|
150
|
+
this.#remotePort = null;
|
|
151
|
+
this.#onmessage = null;
|
|
152
|
+
this.#onmessageerror = null;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// -- Internal wiring (used by MessageChannel) ----------------------------
|
|
156
|
+
|
|
157
|
+
/** @internal Wire this port to its remote partner. */
|
|
158
|
+
_setRemotePort(remote: MessagePort): void {
|
|
159
|
+
this.#remotePort = remote;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
[structuredCloneTransferSymbol](): MessagePort {
|
|
163
|
+
const transferredPort = new MessagePort();
|
|
164
|
+
const remote = this.#remotePort;
|
|
165
|
+
|
|
166
|
+
transferredPort.#queue = this.#queue;
|
|
167
|
+
transferredPort.#started = this.#started;
|
|
168
|
+
|
|
169
|
+
if (remote && !remote.#closed) {
|
|
170
|
+
transferredPort._setRemotePort(remote);
|
|
171
|
+
remote._setRemotePort(transferredPort);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
this.#queue = [];
|
|
175
|
+
this.#started = false;
|
|
176
|
+
this.#closed = true;
|
|
177
|
+
this.#remotePort = null;
|
|
178
|
+
this.#onmessage = null;
|
|
179
|
+
this.#onmessageerror = null;
|
|
180
|
+
|
|
181
|
+
return transferredPort;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// -- Private helpers ------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
#dispatchMessage(data: unknown): void {
|
|
187
|
+
const event = new MessageEvent('message', { data });
|
|
188
|
+
|
|
189
|
+
// Call the IDL onmessage handler first
|
|
190
|
+
if (this.#onmessage) {
|
|
191
|
+
try {
|
|
192
|
+
this.#onmessage.call(this, event);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
console.error('[MessagePort] onmessage handler threw:', error);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Then dispatch to addEventListener listeners
|
|
199
|
+
this.dispatchEvent(event);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
#dispatchMessageError(error: unknown): void {
|
|
203
|
+
const event = new MessageEvent('messageerror', { data: error });
|
|
204
|
+
|
|
205
|
+
if (this.#onmessageerror) {
|
|
206
|
+
try {
|
|
207
|
+
this.#onmessageerror.call(this, event);
|
|
208
|
+
} catch (e) {
|
|
209
|
+
console.error('[MessagePort] onmessageerror handler threw:', e);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
this.dispatchEvent(event);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// -- Symbol.toStringTag ---------------------------------------------------
|
|
217
|
+
|
|
218
|
+
get [Symbol.toStringTag](): string {
|
|
219
|
+
return 'MessagePort';
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
// MessageChannel
|
|
225
|
+
// ---------------------------------------------------------------------------
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* A MessageChannel creates a pair of entangled MessagePort objects. Messages
|
|
229
|
+
* posted on one port are delivered to the other and vice versa.
|
|
230
|
+
*/
|
|
231
|
+
export class MessageChannel {
|
|
232
|
+
readonly port1: MessagePort;
|
|
233
|
+
readonly port2: MessagePort;
|
|
234
|
+
|
|
235
|
+
constructor() {
|
|
236
|
+
this.port1 = new MessagePort();
|
|
237
|
+
this.port2 = new MessagePort();
|
|
238
|
+
|
|
239
|
+
// Wire the two ports together
|
|
240
|
+
this.port1._setRemotePort(this.port2);
|
|
241
|
+
this.port2._setRemotePort(this.port1);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
get [Symbol.toStringTag](): string {
|
|
245
|
+
return 'MessageChannel';
|
|
246
|
+
}
|
|
247
|
+
}
|