@sigx/lynx-websocket 0.4.0 → 0.4.2
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/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -221
- package/dist/index.js.map +1 -1
- package/dist/websocket.js +429 -0
- package/dist/websocket.js.map +1 -0
- package/package.json +8 -7
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { WebSocket, isWebSocketAvailable } from './websocket';
|
|
1
|
+
export { WebSocket, isWebSocketAvailable } from './websocket.js';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,224 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
for (let e = 0; e < 64; e++) t["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charCodeAt(e)] = e;
|
|
16
|
-
let n = e.replace(/=+$/, ""), r = new Uint8Array(n.length * 3 >> 2), i = 0, a = 0, o = 0;
|
|
17
|
-
for (let e = 0; e < n.length; e++) {
|
|
18
|
-
let s = t[n.charCodeAt(e)];
|
|
19
|
-
s < 0 || (a = a << 6 | s, o += 6, o >= 8 && (o -= 8, r[i++] = a >> o & 255));
|
|
20
|
-
}
|
|
21
|
-
return r.buffer;
|
|
22
|
-
}
|
|
23
|
-
function d(e) {
|
|
24
|
-
let t = new Uint8Array(e);
|
|
25
|
-
if (typeof btoa == "function") {
|
|
26
|
-
let e = "", n = 32768;
|
|
27
|
-
for (let r = 0; r < t.length; r += n) e += String.fromCharCode.apply(null, Array.from(t.subarray(r, r + n)));
|
|
28
|
-
return btoa(e);
|
|
29
|
-
}
|
|
30
|
-
let n = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", r = "", i = 0;
|
|
31
|
-
for (; i + 2 < t.length; i += 3) {
|
|
32
|
-
let e = t[i] << 16 | t[i + 1] << 8 | t[i + 2];
|
|
33
|
-
r += n[e >> 18 & 63] + n[e >> 12 & 63] + n[e >> 6 & 63] + n[e & 63];
|
|
34
|
-
}
|
|
35
|
-
if (i < t.length) {
|
|
36
|
-
let e = t.length - i, a = e === 1 ? t[i] << 16 : t[i] << 16 | t[i + 1] << 8;
|
|
37
|
-
r += n[a >> 18 & 63] + n[a >> 12 & 63], r += e === 2 ? n[a >> 6 & 63] + "=" : "==";
|
|
38
|
-
}
|
|
39
|
-
return r;
|
|
40
|
-
}
|
|
41
|
-
var f = /* @__PURE__ */ new Map(), p = 1, m = !1;
|
|
42
|
-
function h() {
|
|
43
|
-
if (m) return;
|
|
44
|
-
let e = a()?.getJSModule?.("GlobalEventEmitter");
|
|
45
|
-
e && (e.addListener(i, (e) => {
|
|
46
|
-
let t = typeof e == "string" ? g(e) : e;
|
|
47
|
-
if (!t || typeof t.id != "number") return;
|
|
48
|
-
let n = f.get(t.id);
|
|
49
|
-
n && n._dispatch(t);
|
|
50
|
-
}), m = !0);
|
|
51
|
-
}
|
|
52
|
-
function g(e) {
|
|
53
|
-
try {
|
|
54
|
-
return JSON.parse(e);
|
|
55
|
-
} catch {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
var _ = class {
|
|
60
|
-
static {
|
|
61
|
-
this.CONNECTING = o;
|
|
62
|
-
}
|
|
63
|
-
static {
|
|
64
|
-
this.OPEN = s;
|
|
65
|
-
}
|
|
66
|
-
static {
|
|
67
|
-
this.CLOSING = c;
|
|
68
|
-
}
|
|
69
|
-
static {
|
|
70
|
-
this.CLOSED = l;
|
|
71
|
-
}
|
|
72
|
-
get readyState() {
|
|
73
|
-
return this._readyState;
|
|
74
|
-
}
|
|
75
|
-
constructor(n, i) {
|
|
76
|
-
if (this.CONNECTING = o, this.OPEN = s, this.CLOSING = c, this.CLOSED = l, this.protocol = "", this.extensions = "", this.bufferedAmount = 0, this.binaryType = "arraybuffer", this.onopen = null, this.onmessage = null, this.onerror = null, this.onclose = null, this._readyState = o, this._listeners = Object.create(null), typeof n != "string" || n.length === 0) throw TypeError("WebSocket: invalid URL");
|
|
77
|
-
let a = n.indexOf(":");
|
|
78
|
-
if (a <= 0) throw SyntaxError(`WebSocket: invalid URL "${n}"`);
|
|
79
|
-
let u = n.slice(0, a).toLowerCase();
|
|
80
|
-
if (u !== "ws" && u !== "wss" && u !== "http" && u !== "https") throw SyntaxError(`WebSocket: unsupported URL scheme "${u}"`);
|
|
81
|
-
t(r), this.url = n, this._id = p++, f.set(this._id, this), h();
|
|
82
|
-
let d = Array.isArray(i) ? i : typeof i == "string" && i.length > 0 ? [i] : [];
|
|
83
|
-
e(r, "create", this._id, n, d).catch((e) => {
|
|
84
|
-
this._dispatch({
|
|
85
|
-
id: this._id,
|
|
86
|
-
type: "error",
|
|
87
|
-
data: e instanceof Error ? e.message : String(e)
|
|
88
|
-
}), this._dispatch({
|
|
89
|
-
id: this._id,
|
|
90
|
-
type: "close",
|
|
91
|
-
code: 1006,
|
|
92
|
-
reason: "",
|
|
93
|
-
wasClean: !1
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
send(t) {
|
|
98
|
-
if (this._readyState === o) throw Error("InvalidStateError: WebSocket is still in CONNECTING state.");
|
|
99
|
-
if (this._readyState !== s) return;
|
|
100
|
-
let n = !1, i;
|
|
101
|
-
if (typeof t == "string") i = t;
|
|
102
|
-
else if (t instanceof ArrayBuffer) n = !0, i = d(t);
|
|
103
|
-
else if (ArrayBuffer.isView(t)) {
|
|
104
|
-
n = !0;
|
|
105
|
-
let e = t;
|
|
106
|
-
i = d(e.buffer.slice(e.byteOffset, e.byteOffset + e.byteLength));
|
|
107
|
-
} else throw TypeError("WebSocket.send: unsupported data type");
|
|
108
|
-
this.bufferedAmount += n ? b(i) : y(i), e(r, "send", this._id, i, n).catch((e) => {
|
|
109
|
-
this._dispatch({
|
|
110
|
-
id: this._id,
|
|
111
|
-
type: "error",
|
|
112
|
-
data: e instanceof Error ? e.message : String(e)
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
close(t, n) {
|
|
117
|
-
if (!(this._readyState === c || this._readyState === l)) {
|
|
118
|
-
if (t !== void 0 && t !== 1e3 && (t < 3e3 || t > 4999)) throw Error(`InvalidAccessError: close code ${t} must be 1000 or in the 3000-4999 range.`);
|
|
119
|
-
if (n !== void 0 && y(n) > 123) throw SyntaxError("SyntaxError: close reason must be ≤123 UTF-8 bytes.");
|
|
120
|
-
this._readyState = c, e(r, "close", this._id, t ?? 1e3, n ?? "").catch((e) => {
|
|
121
|
-
this._dispatch({
|
|
122
|
-
id: this._id,
|
|
123
|
-
type: "error",
|
|
124
|
-
data: e instanceof Error ? e.message : String(e)
|
|
125
|
-
}), this._dispatch({
|
|
126
|
-
id: this._id,
|
|
127
|
-
type: "close",
|
|
128
|
-
code: 1006,
|
|
129
|
-
reason: "",
|
|
130
|
-
wasClean: !1
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
addEventListener(e, t) {
|
|
136
|
-
t && (this._listeners[e] ??= /* @__PURE__ */ new Set()).add(t);
|
|
137
|
-
}
|
|
138
|
-
removeEventListener(e, t) {
|
|
139
|
-
this._listeners[e]?.delete(t);
|
|
140
|
-
}
|
|
141
|
-
dispatchEvent(e) {
|
|
142
|
-
return this._invoke(e.type, e), !0;
|
|
143
|
-
}
|
|
144
|
-
_dispatch(e) {
|
|
145
|
-
switch (e.type) {
|
|
146
|
-
case "open":
|
|
147
|
-
this._readyState = s, typeof e.protocol == "string" && (this.protocol = e.protocol), typeof e.extensions == "string" && (this.extensions = e.extensions), this._invoke("open", {
|
|
148
|
-
type: "open",
|
|
149
|
-
target: this,
|
|
150
|
-
currentTarget: this
|
|
151
|
-
});
|
|
152
|
-
break;
|
|
153
|
-
case "message": {
|
|
154
|
-
if (this._readyState !== s) return;
|
|
155
|
-
let t;
|
|
156
|
-
t = e.isBinary && typeof e.binary == "string" ? u(e.binary) : e.data ?? "", this._invoke("message", {
|
|
157
|
-
type: "message",
|
|
158
|
-
target: this,
|
|
159
|
-
currentTarget: this,
|
|
160
|
-
data: t
|
|
161
|
-
});
|
|
162
|
-
break;
|
|
163
|
-
}
|
|
164
|
-
case "error":
|
|
165
|
-
this._invoke("error", {
|
|
166
|
-
type: "error",
|
|
167
|
-
target: this,
|
|
168
|
-
currentTarget: this,
|
|
169
|
-
message: e.data
|
|
170
|
-
});
|
|
171
|
-
break;
|
|
172
|
-
case "close":
|
|
173
|
-
if (this._readyState === l) return;
|
|
174
|
-
this._readyState = l, f.delete(this._id), this._invoke("close", {
|
|
175
|
-
type: "close",
|
|
176
|
-
target: this,
|
|
177
|
-
currentTarget: this,
|
|
178
|
-
code: e.code ?? 1006,
|
|
179
|
-
reason: e.reason ?? "",
|
|
180
|
-
wasClean: e.wasClean ?? !1
|
|
181
|
-
});
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
_invoke(e, t) {
|
|
186
|
-
let n = this[`on${e}`];
|
|
187
|
-
if (typeof n == "function") try {
|
|
188
|
-
n.call(this, t);
|
|
189
|
-
} catch (t) {
|
|
190
|
-
console.warn(`[WebSocket] on${e} handler threw:`, t);
|
|
191
|
-
}
|
|
192
|
-
let r = this._listeners[e];
|
|
193
|
-
if (r) for (let n of r) try {
|
|
194
|
-
typeof n == "function" ? n.call(this, t) : n.handleEvent(t);
|
|
195
|
-
} catch (t) {
|
|
196
|
-
console.warn(`[WebSocket] '${e}' listener threw:`, t);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
function v() {
|
|
201
|
-
return n(r);
|
|
202
|
-
}
|
|
203
|
-
function y(e) {
|
|
204
|
-
let t = 0;
|
|
205
|
-
for (let n = 0; n < e.length; n++) {
|
|
206
|
-
let r = e.charCodeAt(n);
|
|
207
|
-
r < 128 ? t += 1 : r < 2048 ? t += 2 : r >= 55296 && r <= 56319 ? (t += 4, n++) : t += 3;
|
|
208
|
-
}
|
|
209
|
-
return t;
|
|
210
|
-
}
|
|
211
|
-
function b(e) {
|
|
212
|
-
let t = e.endsWith("==") ? 2 : +!!e.endsWith("=");
|
|
213
|
-
return (e.length * 3 >> 2) - t;
|
|
214
|
-
}
|
|
215
|
-
//#endregion
|
|
216
|
-
//#region src/index.ts
|
|
1
|
+
/**
|
|
2
|
+
* `@sigx/lynx-websocket` — browser-standard `WebSocket` for sigx-lynx.
|
|
3
|
+
*
|
|
4
|
+
* Importing this module (or having `@sigx/lynx-websocket` installed so the
|
|
5
|
+
* CLI auto-discovers it during `sigx prebuild`) installs a global `WebSocket`
|
|
6
|
+
* class on `globalThis`, so portable web code that does `new WebSocket(url)`
|
|
7
|
+
* works unchanged.
|
|
8
|
+
*/
|
|
9
|
+
import { WebSocket as SigxWebSocket } from './websocket.js';
|
|
10
|
+
export { WebSocket, isWebSocketAvailable } from './websocket.js';
|
|
11
|
+
// Side-effect: register on the global so consumers don't need an import
|
|
12
|
+
// site to call `new WebSocket(...)`. Mirrors the CLI plugin's auto-import
|
|
13
|
+
// behavior for native modules — the auto-linker picks up the package's
|
|
14
|
+
// signalx-module.json and this file runs at bundle init time.
|
|
217
15
|
{
|
|
218
|
-
|
|
219
|
-
|
|
16
|
+
const g = globalThis;
|
|
17
|
+
if (typeof g.WebSocket === 'undefined') {
|
|
18
|
+
g.WebSocket = SigxWebSocket;
|
|
19
|
+
}
|
|
220
20
|
}
|
|
221
|
-
//#endregion
|
|
222
|
-
export { _ as WebSocket, v as isWebSocketAvailable };
|
|
223
|
-
|
|
224
21
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/websocket.ts","../src/index.ts"],"sourcesContent":["/**\n * Browser-standard `WebSocket` client backed by the `@sigx/lynx-websocket`\n * native module (URLSessionWebSocketTask on iOS, OkHttp WebSocket on\n * Android).\n *\n * Public surface mirrors the WHATWG WebSocket interface:\n *\n * new WebSocket(url, protocols?)\n * .readyState / .url / .protocol / .extensions / .bufferedAmount\n * .binaryType ('arraybuffer' only — 'blob' is not supported)\n * .onopen / .onmessage / .onerror / .onclose\n * .addEventListener / .removeEventListener / .dispatchEvent\n * .send(string | ArrayBuffer | ArrayBufferView)\n * .close(code?, reason?)\n *\n * Multi-socket dispatch: each instance is assigned a monotonic numeric id.\n * The native side emits a single `__sigxWebSocketEvent` global event\n * carrying `{ id, type, ... }`; the JS shim demultiplexes by id and fires\n * the matching instance's listeners.\n */\nimport { callAsync, guardModule, isModuleAvailable } from '@sigx/lynx-core';\n\nconst MODULE = 'WebSocket';\nconst EVENT_NAME = '__sigxWebSocketEvent';\n\n/** Bridge to lynx's `GlobalEventEmitter` for native → JS events. */\ninterface GlobalEventEmitterLike {\n addListener: (name: string, fn: (...a: unknown[]) => void) => void;\n removeListener: (name: string, fn: (...a: unknown[]) => void) => void;\n}\n\ninterface LynxLike {\n getJSModule?: (name: string) => GlobalEventEmitterLike | undefined;\n}\n\ndeclare const lynx: unknown | undefined;\n\nfunction lynxObj(): LynxLike | undefined {\n return typeof lynx !== 'undefined' ? (lynx as unknown as LynxLike) : undefined;\n}\n\n/** Wire payload pushed by the native side. */\ninterface NativeEvent {\n id: number;\n type: 'open' | 'message' | 'error' | 'close';\n /** Text body for message events, error message for error events. */\n data?: string;\n /** Base64-encoded binary payload (set when isBinary === true). */\n binary?: string;\n isBinary?: boolean;\n /** Negotiated subprotocol — populated on the open event. */\n protocol?: string;\n /** Negotiated extensions — populated on the open event. */\n extensions?: string;\n /** Close frame fields. */\n code?: number;\n reason?: string;\n wasClean?: boolean;\n}\n\nconst CONNECTING = 0 as const;\nconst OPEN = 1 as const;\nconst CLOSING = 2 as const;\nconst CLOSED = 3 as const;\n\ntype ReadyState = 0 | 1 | 2 | 3;\ntype BinaryType = 'arraybuffer';\n\ntype EventListenerLike = ((ev: WebSocketEventLike) => void) | { handleEvent(ev: WebSocketEventLike): void };\n\n/** Minimal WHATWG `Event` shape — enough for portable WS code. */\ninterface WebSocketEventLike {\n type: string;\n target: WebSocket;\n currentTarget: WebSocket;\n data?: unknown;\n code?: number;\n reason?: string;\n wasClean?: boolean;\n message?: string;\n}\n\n/**\n * Decode a base64 string into an `ArrayBuffer`. Lynx's BTS runtime has\n * `atob` per the platform docs, but fall back to a manual decoder to keep\n * this shim portable across hosts where it might be absent.\n */\nfunction base64ToArrayBuffer(b64: string): ArrayBuffer {\n if (typeof atob === 'function') {\n const bin = atob(b64);\n const buf = new ArrayBuffer(bin.length);\n const view = new Uint8Array(buf);\n for (let i = 0; i < bin.length; i++) view[i] = bin.charCodeAt(i);\n return buf;\n }\n // Pure-JS fallback. Not the fastest, but executed at most for binary\n // frames on hosts that ship no atob (vanishingly rare).\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n const lookup = new Int8Array(256).fill(-1);\n for (let i = 0; i < chars.length; i++) lookup[chars.charCodeAt(i)] = i;\n const clean = b64.replace(/=+$/, '');\n const out = new Uint8Array((clean.length * 3) >> 2);\n let p = 0;\n let buf = 0;\n let bits = 0;\n for (let i = 0; i < clean.length; i++) {\n const v = lookup[clean.charCodeAt(i)];\n if (v < 0) continue;\n buf = (buf << 6) | v;\n bits += 6;\n if (bits >= 8) {\n bits -= 8;\n out[p++] = (buf >> bits) & 0xff;\n }\n }\n return out.buffer;\n}\n\n/**\n * Encode an `ArrayBuffer` / view to base64 for transport to native.\n * Native side base64-decodes back to raw bytes before sending on the wire.\n */\nfunction arrayBufferToBase64(buf: ArrayBuffer): string {\n const bytes = new Uint8Array(buf);\n if (typeof btoa === 'function') {\n // Build the binary string in chunks to dodge call-stack limits on\n // large frames (String.fromCharCode.apply blows up around ~64k args).\n let bin = '';\n const CHUNK = 0x8000;\n for (let i = 0; i < bytes.length; i += CHUNK) {\n bin += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + CHUNK)));\n }\n return btoa(bin);\n }\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n let out = '';\n let i = 0;\n for (; i + 2 < bytes.length; i += 3) {\n const n = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];\n out += chars[(n >> 18) & 63] + chars[(n >> 12) & 63] + chars[(n >> 6) & 63] + chars[n & 63];\n }\n if (i < bytes.length) {\n const rem = bytes.length - i;\n const n = rem === 1 ? bytes[i] << 16 : (bytes[i] << 16) | (bytes[i + 1] << 8);\n out += chars[(n >> 18) & 63] + chars[(n >> 12) & 63];\n out += rem === 2 ? chars[(n >> 6) & 63] + '=' : '==';\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Shared event dispatch — one global lynx listener that demuxes by socket id.\n\nconst sockets = new Map<number, WebSocket>();\nlet nextId = 1;\nlet subscribed = false;\nlet cachedEmitter: GlobalEventEmitterLike | null = null;\n\nfunction ensureSubscribed(): void {\n if (subscribed) return;\n const emitter = lynxObj()?.getJSModule?.('GlobalEventEmitter');\n if (!emitter) return; // web/SSR/test — events simply won't arrive\n cachedEmitter = emitter;\n emitter.addListener(EVENT_NAME, (raw: unknown) => {\n // Lynx ships event params as a single JSON-shaped object or as the\n // first arg of the listener. Tolerate both shapes.\n const evt: NativeEvent | undefined =\n typeof raw === 'string' ? safeParse(raw) : (raw as NativeEvent | undefined);\n if (!evt || typeof evt.id !== 'number') return;\n const ws = sockets.get(evt.id);\n if (!ws) return;\n // Internal dispatch lives on the instance so it can mutate state.\n (ws as unknown as { _dispatch(e: NativeEvent): void })._dispatch(evt);\n });\n subscribed = true;\n}\n\nfunction safeParse(s: string): NativeEvent | undefined {\n try {\n return JSON.parse(s);\n } catch {\n return undefined;\n }\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * WHATWG-compatible WebSocket. Drop-in for browser code.\n *\n * @example\n * ```ts\n * const ws = new WebSocket('wss://ws.postman-echo.com/raw');\n * ws.onopen = () => ws.send('hello');\n * ws.onmessage = e => console.log(e.data);\n * ```\n */\nexport class WebSocket {\n static readonly CONNECTING = CONNECTING;\n static readonly OPEN = OPEN;\n static readonly CLOSING = CLOSING;\n static readonly CLOSED = CLOSED;\n\n readonly CONNECTING = CONNECTING;\n readonly OPEN = OPEN;\n readonly CLOSING = CLOSING;\n readonly CLOSED = CLOSED;\n\n readonly url: string;\n protocol = '';\n extensions = '';\n bufferedAmount = 0;\n binaryType: BinaryType = 'arraybuffer';\n\n onopen: ((ev: WebSocketEventLike) => void) | null = null;\n onmessage: ((ev: WebSocketEventLike) => void) | null = null;\n onerror: ((ev: WebSocketEventLike) => void) | null = null;\n onclose: ((ev: WebSocketEventLike) => void) | null = null;\n\n private _readyState: ReadyState = CONNECTING;\n private readonly _id: number;\n private readonly _listeners: Record<string, Set<EventListenerLike>> = Object.create(null);\n\n get readyState(): ReadyState {\n return this._readyState;\n }\n\n constructor(url: string, protocols?: string | string[]) {\n if (typeof url !== 'string' || url.length === 0) {\n throw new TypeError(`WebSocket: invalid URL`);\n }\n // Match browsers: only ws:/wss: are valid. We accept http:/https: too\n // and let the native side reject — some debug proxies normalise.\n const colon = url.indexOf(':');\n if (colon <= 0) {\n throw new SyntaxError(`WebSocket: invalid URL \"${url}\"`);\n }\n const scheme = url.slice(0, colon).toLowerCase();\n if (scheme !== 'ws' && scheme !== 'wss' && scheme !== 'http' && scheme !== 'https') {\n throw new SyntaxError(`WebSocket: unsupported URL scheme \"${scheme}\"`);\n }\n\n guardModule(MODULE);\n\n this.url = url;\n this._id = nextId++;\n sockets.set(this._id, this);\n ensureSubscribed();\n\n const protoList = Array.isArray(protocols)\n ? protocols\n : typeof protocols === 'string' && protocols.length > 0\n ? [protocols]\n : [];\n\n // Fire-and-forget — open/error are delivered through the event\n // channel, not the callback. We still surface synchronous bridge\n // failures (e.g. module not registered) as an async error event.\n callAsync<void>(MODULE, 'create', this._id, url, protoList).catch(err => {\n this._dispatch({\n id: this._id,\n type: 'error',\n data: err instanceof Error ? err.message : String(err),\n });\n this._dispatch({\n id: this._id,\n type: 'close',\n code: 1006,\n reason: '',\n wasClean: false,\n });\n });\n }\n\n send(data: string | ArrayBuffer | ArrayBufferView): void {\n if (this._readyState === CONNECTING) {\n // Browsers throw InvalidStateError here.\n throw new Error(\"InvalidStateError: WebSocket is still in CONNECTING state.\");\n }\n if (this._readyState !== OPEN) {\n // Browsers silently drop on CLOSING/CLOSED but warn in devtools.\n return;\n }\n\n let isBinary = false;\n let payload: string;\n if (typeof data === 'string') {\n payload = data;\n } else if (data instanceof ArrayBuffer) {\n isBinary = true;\n payload = arrayBufferToBase64(data);\n } else if (ArrayBuffer.isView(data)) {\n isBinary = true;\n const view = data as ArrayBufferView;\n // Copy the active range out of the underlying buffer so we don't\n // accidentally send bytes outside the view.\n const slice = view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength) as ArrayBuffer;\n payload = arrayBufferToBase64(slice);\n } else {\n throw new TypeError('WebSocket.send: unsupported data type');\n }\n\n // bufferedAmount is approximated as the byte length the JS side has\n // handed off — the native side acks via 'flushed' frames in a future\n // version; for now this is a write-through counter.\n this.bufferedAmount += isBinary ? base64ByteLength(payload) : utf8ByteLength(payload);\n\n callAsync<void>(MODULE, 'send', this._id, payload, isBinary).catch(err => {\n this._dispatch({\n id: this._id,\n type: 'error',\n data: err instanceof Error ? err.message : String(err),\n });\n });\n }\n\n close(code?: number, reason?: string): void {\n if (this._readyState === CLOSING || this._readyState === CLOSED) return;\n\n // WHATWG: code must be 1000 or 3000–4999. Validate to mirror browsers.\n if (code !== undefined) {\n if (code !== 1000 && (code < 3000 || code > 4999)) {\n throw new Error(\n `InvalidAccessError: close code ${code} must be 1000 or in the 3000-4999 range.`,\n );\n }\n }\n if (reason !== undefined && utf8ByteLength(reason) > 123) {\n throw new SyntaxError('SyntaxError: close reason must be ≤123 UTF-8 bytes.');\n }\n\n this._readyState = CLOSING;\n callAsync<void>(MODULE, 'close', this._id, code ?? 1000, reason ?? '').catch(err => {\n // Bridge call itself failed (e.g. module missing). Synthesize an\n // abnormal close so the instance doesn't get stuck in CLOSING and\n // we still clean up sockets state.\n this._dispatch({\n id: this._id,\n type: 'error',\n data: err instanceof Error ? err.message : String(err),\n });\n this._dispatch({\n id: this._id,\n type: 'close',\n code: 1006,\n reason: '',\n wasClean: false,\n });\n });\n }\n\n // -- EventTarget ---------------------------------------------------------\n\n addEventListener(type: string, listener: EventListenerLike): void {\n if (!listener) return;\n (this._listeners[type] ??= new Set()).add(listener);\n }\n\n removeEventListener(type: string, listener: EventListenerLike): void {\n this._listeners[type]?.delete(listener);\n }\n\n dispatchEvent(event: WebSocketEventLike): boolean {\n this._invoke(event.type, event);\n return true;\n }\n\n // -- Internal ------------------------------------------------------------\n\n /** @internal — called by the shared global-event subscriber. */\n private _dispatch(evt: NativeEvent): void {\n switch (evt.type) {\n case 'open': {\n this._readyState = OPEN;\n if (typeof evt.protocol === 'string') this.protocol = evt.protocol;\n if (typeof evt.extensions === 'string') this.extensions = evt.extensions;\n this._invoke('open', {\n type: 'open',\n target: this,\n currentTarget: this,\n });\n break;\n }\n case 'message': {\n if (this._readyState !== OPEN) return;\n let data: string | ArrayBuffer;\n if (evt.isBinary && typeof evt.binary === 'string') {\n data = base64ToArrayBuffer(evt.binary);\n } else {\n data = evt.data ?? '';\n }\n this._invoke('message', {\n type: 'message',\n target: this,\n currentTarget: this,\n data,\n });\n break;\n }\n case 'error': {\n this._invoke('error', {\n type: 'error',\n target: this,\n currentTarget: this,\n message: evt.data,\n });\n break;\n }\n case 'close': {\n if (this._readyState === CLOSED) return;\n this._readyState = CLOSED;\n sockets.delete(this._id);\n this._invoke('close', {\n type: 'close',\n target: this,\n currentTarget: this,\n code: evt.code ?? 1006,\n reason: evt.reason ?? '',\n wasClean: evt.wasClean ?? false,\n });\n break;\n }\n }\n }\n\n private _invoke(type: string, event: WebSocketEventLike): void {\n const handler = (this as unknown as Record<string, unknown>)[`on${type}`];\n if (typeof handler === 'function') {\n try {\n (handler as (e: WebSocketEventLike) => void).call(this, event);\n } catch (e) {\n console.warn(`[WebSocket] on${type} handler threw:`, e);\n }\n }\n const set = this._listeners[type];\n if (set) {\n for (const listener of set) {\n try {\n if (typeof listener === 'function') listener.call(this, event);\n else listener.handleEvent(event);\n } catch (e) {\n console.warn(`[WebSocket] '${type}' listener threw:`, e);\n }\n }\n }\n }\n}\n\n/** Whether the native WebSocket module is registered in this build. */\nexport function isWebSocketAvailable(): boolean {\n return isModuleAvailable(MODULE);\n}\n\n// ---------------------------------------------------------------------------\n// Byte-length helpers (kept local to avoid pulling a dep).\n\nfunction utf8ByteLength(s: string): number {\n let n = 0;\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i);\n if (c < 0x80) n += 1;\n else if (c < 0x800) n += 2;\n else if (c >= 0xd800 && c <= 0xdbff) {\n n += 4;\n i++; // surrogate pair\n } else n += 3;\n }\n return n;\n}\n\nfunction base64ByteLength(b64: string): number {\n const padding = b64.endsWith('==') ? 2 : b64.endsWith('=') ? 1 : 0;\n return ((b64.length * 3) >> 2) - padding;\n}\n\n// Test-only escape hatch: exported under a stable name with a leading\n// underscore so it's tree-shakeable but reachable from unit tests.\n/** @internal */\nexport const __internal = {\n deliver(evt: NativeEvent) {\n const ws = sockets.get(evt.id);\n if (ws) (ws as unknown as { _dispatch(e: NativeEvent): void })._dispatch(evt);\n },\n reset() {\n sockets.clear();\n nextId = 1;\n subscribed = false;\n cachedEmitter = null;\n },\n get cachedEmitter(): GlobalEventEmitterLike | null {\n return cachedEmitter;\n },\n};\n","/**\n * `@sigx/lynx-websocket` — browser-standard `WebSocket` for sigx-lynx.\n *\n * Importing this module (or having `@sigx/lynx-websocket` installed so the\n * CLI auto-discovers it during `sigx prebuild`) installs a global `WebSocket`\n * class on `globalThis`, so portable web code that does `new WebSocket(url)`\n * works unchanged.\n */\nimport { WebSocket as SigxWebSocket } from './websocket';\n\nexport { WebSocket, isWebSocketAvailable } from './websocket';\n\n// Side-effect: register on the global so consumers don't need an import\n// site to call `new WebSocket(...)`. Mirrors the CLI plugin's auto-import\n// behavior for native modules — the auto-linker picks up the package's\n// signalx-module.json and this file runs at bundle init time.\n{\n const g = globalThis as unknown as { WebSocket?: unknown };\n if (typeof g.WebSocket === 'undefined') {\n g.WebSocket = SigxWebSocket;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEjE,wEAAwE;AACxE,0EAA0E;AAC1E,uEAAuE;AACvE,8DAA8D;AAC9D,CAAC;IACG,MAAM,CAAC,GAAG,UAAgD,CAAC;IAC3D,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;QACrC,CAAC,CAAC,SAAS,GAAG,aAAa,CAAC;IAChC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-standard `WebSocket` client backed by the `@sigx/lynx-websocket`
|
|
3
|
+
* native module (URLSessionWebSocketTask on iOS, OkHttp WebSocket on
|
|
4
|
+
* Android).
|
|
5
|
+
*
|
|
6
|
+
* Public surface mirrors the WHATWG WebSocket interface:
|
|
7
|
+
*
|
|
8
|
+
* new WebSocket(url, protocols?)
|
|
9
|
+
* .readyState / .url / .protocol / .extensions / .bufferedAmount
|
|
10
|
+
* .binaryType ('arraybuffer' only — 'blob' is not supported)
|
|
11
|
+
* .onopen / .onmessage / .onerror / .onclose
|
|
12
|
+
* .addEventListener / .removeEventListener / .dispatchEvent
|
|
13
|
+
* .send(string | ArrayBuffer | ArrayBufferView)
|
|
14
|
+
* .close(code?, reason?)
|
|
15
|
+
*
|
|
16
|
+
* Multi-socket dispatch: each instance is assigned a monotonic numeric id.
|
|
17
|
+
* The native side emits a single `__sigxWebSocketEvent` global event
|
|
18
|
+
* carrying `{ id, type, ... }`; the JS shim demultiplexes by id and fires
|
|
19
|
+
* the matching instance's listeners.
|
|
20
|
+
*/
|
|
21
|
+
import { callAsync, guardModule, isModuleAvailable } from '@sigx/lynx-core';
|
|
22
|
+
const MODULE = 'WebSocket';
|
|
23
|
+
const EVENT_NAME = '__sigxWebSocketEvent';
|
|
24
|
+
function lynxObj() {
|
|
25
|
+
return typeof lynx !== 'undefined' ? lynx : undefined;
|
|
26
|
+
}
|
|
27
|
+
const CONNECTING = 0;
|
|
28
|
+
const OPEN = 1;
|
|
29
|
+
const CLOSING = 2;
|
|
30
|
+
const CLOSED = 3;
|
|
31
|
+
/**
|
|
32
|
+
* Decode a base64 string into an `ArrayBuffer`. Lynx's BTS runtime has
|
|
33
|
+
* `atob` per the platform docs, but fall back to a manual decoder to keep
|
|
34
|
+
* this shim portable across hosts where it might be absent.
|
|
35
|
+
*/
|
|
36
|
+
function base64ToArrayBuffer(b64) {
|
|
37
|
+
if (typeof atob === 'function') {
|
|
38
|
+
const bin = atob(b64);
|
|
39
|
+
const buf = new ArrayBuffer(bin.length);
|
|
40
|
+
const view = new Uint8Array(buf);
|
|
41
|
+
for (let i = 0; i < bin.length; i++)
|
|
42
|
+
view[i] = bin.charCodeAt(i);
|
|
43
|
+
return buf;
|
|
44
|
+
}
|
|
45
|
+
// Pure-JS fallback. Not the fastest, but executed at most for binary
|
|
46
|
+
// frames on hosts that ship no atob (vanishingly rare).
|
|
47
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
48
|
+
const lookup = new Int8Array(256).fill(-1);
|
|
49
|
+
for (let i = 0; i < chars.length; i++)
|
|
50
|
+
lookup[chars.charCodeAt(i)] = i;
|
|
51
|
+
const clean = b64.replace(/=+$/, '');
|
|
52
|
+
const out = new Uint8Array((clean.length * 3) >> 2);
|
|
53
|
+
let p = 0;
|
|
54
|
+
let buf = 0;
|
|
55
|
+
let bits = 0;
|
|
56
|
+
for (let i = 0; i < clean.length; i++) {
|
|
57
|
+
const v = lookup[clean.charCodeAt(i)];
|
|
58
|
+
if (v < 0)
|
|
59
|
+
continue;
|
|
60
|
+
buf = (buf << 6) | v;
|
|
61
|
+
bits += 6;
|
|
62
|
+
if (bits >= 8) {
|
|
63
|
+
bits -= 8;
|
|
64
|
+
out[p++] = (buf >> bits) & 0xff;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return out.buffer;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Encode an `ArrayBuffer` / view to base64 for transport to native.
|
|
71
|
+
* Native side base64-decodes back to raw bytes before sending on the wire.
|
|
72
|
+
*/
|
|
73
|
+
function arrayBufferToBase64(buf) {
|
|
74
|
+
const bytes = new Uint8Array(buf);
|
|
75
|
+
if (typeof btoa === 'function') {
|
|
76
|
+
// Build the binary string in chunks to dodge call-stack limits on
|
|
77
|
+
// large frames (String.fromCharCode.apply blows up around ~64k args).
|
|
78
|
+
let bin = '';
|
|
79
|
+
const CHUNK = 0x8000;
|
|
80
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
81
|
+
bin += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + CHUNK)));
|
|
82
|
+
}
|
|
83
|
+
return btoa(bin);
|
|
84
|
+
}
|
|
85
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
86
|
+
let out = '';
|
|
87
|
+
let i = 0;
|
|
88
|
+
for (; i + 2 < bytes.length; i += 3) {
|
|
89
|
+
const n = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
|
|
90
|
+
out += chars[(n >> 18) & 63] + chars[(n >> 12) & 63] + chars[(n >> 6) & 63] + chars[n & 63];
|
|
91
|
+
}
|
|
92
|
+
if (i < bytes.length) {
|
|
93
|
+
const rem = bytes.length - i;
|
|
94
|
+
const n = rem === 1 ? bytes[i] << 16 : (bytes[i] << 16) | (bytes[i + 1] << 8);
|
|
95
|
+
out += chars[(n >> 18) & 63] + chars[(n >> 12) & 63];
|
|
96
|
+
out += rem === 2 ? chars[(n >> 6) & 63] + '=' : '==';
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// Shared event dispatch — one global lynx listener that demuxes by socket id.
|
|
102
|
+
const sockets = new Map();
|
|
103
|
+
let nextId = 1;
|
|
104
|
+
let subscribed = false;
|
|
105
|
+
let cachedEmitter = null;
|
|
106
|
+
function ensureSubscribed() {
|
|
107
|
+
if (subscribed)
|
|
108
|
+
return;
|
|
109
|
+
const emitter = lynxObj()?.getJSModule?.('GlobalEventEmitter');
|
|
110
|
+
if (!emitter)
|
|
111
|
+
return; // web/SSR/test — events simply won't arrive
|
|
112
|
+
cachedEmitter = emitter;
|
|
113
|
+
emitter.addListener(EVENT_NAME, (raw) => {
|
|
114
|
+
// Lynx ships event params as a single JSON-shaped object or as the
|
|
115
|
+
// first arg of the listener. Tolerate both shapes.
|
|
116
|
+
const evt = typeof raw === 'string' ? safeParse(raw) : raw;
|
|
117
|
+
if (!evt || typeof evt.id !== 'number')
|
|
118
|
+
return;
|
|
119
|
+
const ws = sockets.get(evt.id);
|
|
120
|
+
if (!ws)
|
|
121
|
+
return;
|
|
122
|
+
// Internal dispatch lives on the instance so it can mutate state.
|
|
123
|
+
ws._dispatch(evt);
|
|
124
|
+
});
|
|
125
|
+
subscribed = true;
|
|
126
|
+
}
|
|
127
|
+
function safeParse(s) {
|
|
128
|
+
try {
|
|
129
|
+
return JSON.parse(s);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
/**
|
|
137
|
+
* WHATWG-compatible WebSocket. Drop-in for browser code.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```ts
|
|
141
|
+
* const ws = new WebSocket('wss://ws.postman-echo.com/raw');
|
|
142
|
+
* ws.onopen = () => ws.send('hello');
|
|
143
|
+
* ws.onmessage = e => console.log(e.data);
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export class WebSocket {
|
|
147
|
+
get readyState() {
|
|
148
|
+
return this._readyState;
|
|
149
|
+
}
|
|
150
|
+
constructor(url, protocols) {
|
|
151
|
+
this.CONNECTING = CONNECTING;
|
|
152
|
+
this.OPEN = OPEN;
|
|
153
|
+
this.CLOSING = CLOSING;
|
|
154
|
+
this.CLOSED = CLOSED;
|
|
155
|
+
this.protocol = '';
|
|
156
|
+
this.extensions = '';
|
|
157
|
+
this.bufferedAmount = 0;
|
|
158
|
+
this.binaryType = 'arraybuffer';
|
|
159
|
+
this.onopen = null;
|
|
160
|
+
this.onmessage = null;
|
|
161
|
+
this.onerror = null;
|
|
162
|
+
this.onclose = null;
|
|
163
|
+
this._readyState = CONNECTING;
|
|
164
|
+
this._listeners = Object.create(null);
|
|
165
|
+
if (typeof url !== 'string' || url.length === 0) {
|
|
166
|
+
throw new TypeError(`WebSocket: invalid URL`);
|
|
167
|
+
}
|
|
168
|
+
// Match browsers: only ws:/wss: are valid. We accept http:/https: too
|
|
169
|
+
// and let the native side reject — some debug proxies normalise.
|
|
170
|
+
const colon = url.indexOf(':');
|
|
171
|
+
if (colon <= 0) {
|
|
172
|
+
throw new SyntaxError(`WebSocket: invalid URL "${url}"`);
|
|
173
|
+
}
|
|
174
|
+
const scheme = url.slice(0, colon).toLowerCase();
|
|
175
|
+
if (scheme !== 'ws' && scheme !== 'wss' && scheme !== 'http' && scheme !== 'https') {
|
|
176
|
+
throw new SyntaxError(`WebSocket: unsupported URL scheme "${scheme}"`);
|
|
177
|
+
}
|
|
178
|
+
guardModule(MODULE);
|
|
179
|
+
this.url = url;
|
|
180
|
+
this._id = nextId++;
|
|
181
|
+
sockets.set(this._id, this);
|
|
182
|
+
ensureSubscribed();
|
|
183
|
+
const protoList = Array.isArray(protocols)
|
|
184
|
+
? protocols
|
|
185
|
+
: typeof protocols === 'string' && protocols.length > 0
|
|
186
|
+
? [protocols]
|
|
187
|
+
: [];
|
|
188
|
+
// Fire-and-forget — open/error are delivered through the event
|
|
189
|
+
// channel, not the callback. We still surface synchronous bridge
|
|
190
|
+
// failures (e.g. module not registered) as an async error event.
|
|
191
|
+
callAsync(MODULE, 'create', this._id, url, protoList).catch(err => {
|
|
192
|
+
this._dispatch({
|
|
193
|
+
id: this._id,
|
|
194
|
+
type: 'error',
|
|
195
|
+
data: err instanceof Error ? err.message : String(err),
|
|
196
|
+
});
|
|
197
|
+
this._dispatch({
|
|
198
|
+
id: this._id,
|
|
199
|
+
type: 'close',
|
|
200
|
+
code: 1006,
|
|
201
|
+
reason: '',
|
|
202
|
+
wasClean: false,
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
send(data) {
|
|
207
|
+
if (this._readyState === CONNECTING) {
|
|
208
|
+
// Browsers throw InvalidStateError here.
|
|
209
|
+
throw new Error("InvalidStateError: WebSocket is still in CONNECTING state.");
|
|
210
|
+
}
|
|
211
|
+
if (this._readyState !== OPEN) {
|
|
212
|
+
// Browsers silently drop on CLOSING/CLOSED but warn in devtools.
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
let isBinary = false;
|
|
216
|
+
let payload;
|
|
217
|
+
if (typeof data === 'string') {
|
|
218
|
+
payload = data;
|
|
219
|
+
}
|
|
220
|
+
else if (data instanceof ArrayBuffer) {
|
|
221
|
+
isBinary = true;
|
|
222
|
+
payload = arrayBufferToBase64(data);
|
|
223
|
+
}
|
|
224
|
+
else if (ArrayBuffer.isView(data)) {
|
|
225
|
+
isBinary = true;
|
|
226
|
+
const view = data;
|
|
227
|
+
// Copy the active range out of the underlying buffer so we don't
|
|
228
|
+
// accidentally send bytes outside the view.
|
|
229
|
+
const slice = view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);
|
|
230
|
+
payload = arrayBufferToBase64(slice);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
throw new TypeError('WebSocket.send: unsupported data type');
|
|
234
|
+
}
|
|
235
|
+
// bufferedAmount is approximated as the byte length the JS side has
|
|
236
|
+
// handed off — the native side acks via 'flushed' frames in a future
|
|
237
|
+
// version; for now this is a write-through counter.
|
|
238
|
+
this.bufferedAmount += isBinary ? base64ByteLength(payload) : utf8ByteLength(payload);
|
|
239
|
+
callAsync(MODULE, 'send', this._id, payload, isBinary).catch(err => {
|
|
240
|
+
this._dispatch({
|
|
241
|
+
id: this._id,
|
|
242
|
+
type: 'error',
|
|
243
|
+
data: err instanceof Error ? err.message : String(err),
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
close(code, reason) {
|
|
248
|
+
if (this._readyState === CLOSING || this._readyState === CLOSED)
|
|
249
|
+
return;
|
|
250
|
+
// WHATWG: code must be 1000 or 3000–4999. Validate to mirror browsers.
|
|
251
|
+
if (code !== undefined) {
|
|
252
|
+
if (code !== 1000 && (code < 3000 || code > 4999)) {
|
|
253
|
+
throw new Error(`InvalidAccessError: close code ${code} must be 1000 or in the 3000-4999 range.`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (reason !== undefined && utf8ByteLength(reason) > 123) {
|
|
257
|
+
throw new SyntaxError('SyntaxError: close reason must be ≤123 UTF-8 bytes.');
|
|
258
|
+
}
|
|
259
|
+
this._readyState = CLOSING;
|
|
260
|
+
callAsync(MODULE, 'close', this._id, code ?? 1000, reason ?? '').catch(err => {
|
|
261
|
+
// Bridge call itself failed (e.g. module missing). Synthesize an
|
|
262
|
+
// abnormal close so the instance doesn't get stuck in CLOSING and
|
|
263
|
+
// we still clean up sockets state.
|
|
264
|
+
this._dispatch({
|
|
265
|
+
id: this._id,
|
|
266
|
+
type: 'error',
|
|
267
|
+
data: err instanceof Error ? err.message : String(err),
|
|
268
|
+
});
|
|
269
|
+
this._dispatch({
|
|
270
|
+
id: this._id,
|
|
271
|
+
type: 'close',
|
|
272
|
+
code: 1006,
|
|
273
|
+
reason: '',
|
|
274
|
+
wasClean: false,
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
// -- EventTarget ---------------------------------------------------------
|
|
279
|
+
addEventListener(type, listener) {
|
|
280
|
+
var _a;
|
|
281
|
+
if (!listener)
|
|
282
|
+
return;
|
|
283
|
+
((_a = this._listeners)[type] ?? (_a[type] = new Set())).add(listener);
|
|
284
|
+
}
|
|
285
|
+
removeEventListener(type, listener) {
|
|
286
|
+
this._listeners[type]?.delete(listener);
|
|
287
|
+
}
|
|
288
|
+
dispatchEvent(event) {
|
|
289
|
+
this._invoke(event.type, event);
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
// -- Internal ------------------------------------------------------------
|
|
293
|
+
/** @internal — called by the shared global-event subscriber. */
|
|
294
|
+
_dispatch(evt) {
|
|
295
|
+
switch (evt.type) {
|
|
296
|
+
case 'open': {
|
|
297
|
+
this._readyState = OPEN;
|
|
298
|
+
if (typeof evt.protocol === 'string')
|
|
299
|
+
this.protocol = evt.protocol;
|
|
300
|
+
if (typeof evt.extensions === 'string')
|
|
301
|
+
this.extensions = evt.extensions;
|
|
302
|
+
this._invoke('open', {
|
|
303
|
+
type: 'open',
|
|
304
|
+
target: this,
|
|
305
|
+
currentTarget: this,
|
|
306
|
+
});
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
case 'message': {
|
|
310
|
+
if (this._readyState !== OPEN)
|
|
311
|
+
return;
|
|
312
|
+
let data;
|
|
313
|
+
if (evt.isBinary && typeof evt.binary === 'string') {
|
|
314
|
+
data = base64ToArrayBuffer(evt.binary);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
data = evt.data ?? '';
|
|
318
|
+
}
|
|
319
|
+
this._invoke('message', {
|
|
320
|
+
type: 'message',
|
|
321
|
+
target: this,
|
|
322
|
+
currentTarget: this,
|
|
323
|
+
data,
|
|
324
|
+
});
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
case 'error': {
|
|
328
|
+
this._invoke('error', {
|
|
329
|
+
type: 'error',
|
|
330
|
+
target: this,
|
|
331
|
+
currentTarget: this,
|
|
332
|
+
message: evt.data,
|
|
333
|
+
});
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
case 'close': {
|
|
337
|
+
if (this._readyState === CLOSED)
|
|
338
|
+
return;
|
|
339
|
+
this._readyState = CLOSED;
|
|
340
|
+
sockets.delete(this._id);
|
|
341
|
+
this._invoke('close', {
|
|
342
|
+
type: 'close',
|
|
343
|
+
target: this,
|
|
344
|
+
currentTarget: this,
|
|
345
|
+
code: evt.code ?? 1006,
|
|
346
|
+
reason: evt.reason ?? '',
|
|
347
|
+
wasClean: evt.wasClean ?? false,
|
|
348
|
+
});
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
_invoke(type, event) {
|
|
354
|
+
const handler = this[`on${type}`];
|
|
355
|
+
if (typeof handler === 'function') {
|
|
356
|
+
try {
|
|
357
|
+
handler.call(this, event);
|
|
358
|
+
}
|
|
359
|
+
catch (e) {
|
|
360
|
+
console.warn(`[WebSocket] on${type} handler threw:`, e);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
const set = this._listeners[type];
|
|
364
|
+
if (set) {
|
|
365
|
+
for (const listener of set) {
|
|
366
|
+
try {
|
|
367
|
+
if (typeof listener === 'function')
|
|
368
|
+
listener.call(this, event);
|
|
369
|
+
else
|
|
370
|
+
listener.handleEvent(event);
|
|
371
|
+
}
|
|
372
|
+
catch (e) {
|
|
373
|
+
console.warn(`[WebSocket] '${type}' listener threw:`, e);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
WebSocket.CONNECTING = CONNECTING;
|
|
380
|
+
WebSocket.OPEN = OPEN;
|
|
381
|
+
WebSocket.CLOSING = CLOSING;
|
|
382
|
+
WebSocket.CLOSED = CLOSED;
|
|
383
|
+
/** Whether the native WebSocket module is registered in this build. */
|
|
384
|
+
export function isWebSocketAvailable() {
|
|
385
|
+
return isModuleAvailable(MODULE);
|
|
386
|
+
}
|
|
387
|
+
// ---------------------------------------------------------------------------
|
|
388
|
+
// Byte-length helpers (kept local to avoid pulling a dep).
|
|
389
|
+
function utf8ByteLength(s) {
|
|
390
|
+
let n = 0;
|
|
391
|
+
for (let i = 0; i < s.length; i++) {
|
|
392
|
+
const c = s.charCodeAt(i);
|
|
393
|
+
if (c < 0x80)
|
|
394
|
+
n += 1;
|
|
395
|
+
else if (c < 0x800)
|
|
396
|
+
n += 2;
|
|
397
|
+
else if (c >= 0xd800 && c <= 0xdbff) {
|
|
398
|
+
n += 4;
|
|
399
|
+
i++; // surrogate pair
|
|
400
|
+
}
|
|
401
|
+
else
|
|
402
|
+
n += 3;
|
|
403
|
+
}
|
|
404
|
+
return n;
|
|
405
|
+
}
|
|
406
|
+
function base64ByteLength(b64) {
|
|
407
|
+
const padding = b64.endsWith('==') ? 2 : b64.endsWith('=') ? 1 : 0;
|
|
408
|
+
return ((b64.length * 3) >> 2) - padding;
|
|
409
|
+
}
|
|
410
|
+
// Test-only escape hatch: exported under a stable name with a leading
|
|
411
|
+
// underscore so it's tree-shakeable but reachable from unit tests.
|
|
412
|
+
/** @internal */
|
|
413
|
+
export const __internal = {
|
|
414
|
+
deliver(evt) {
|
|
415
|
+
const ws = sockets.get(evt.id);
|
|
416
|
+
if (ws)
|
|
417
|
+
ws._dispatch(evt);
|
|
418
|
+
},
|
|
419
|
+
reset() {
|
|
420
|
+
sockets.clear();
|
|
421
|
+
nextId = 1;
|
|
422
|
+
subscribed = false;
|
|
423
|
+
cachedEmitter = null;
|
|
424
|
+
},
|
|
425
|
+
get cachedEmitter() {
|
|
426
|
+
return cachedEmitter;
|
|
427
|
+
},
|
|
428
|
+
};
|
|
429
|
+
//# sourceMappingURL=websocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sigx/lynx-websocket",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Browser-standard WebSocket client for sigx-lynx",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,12 +19,12 @@
|
|
|
19
19
|
"signalx-module.json"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@sigx/lynx-core": "^0.4.
|
|
22
|
+
"@sigx/lynx-core": "^0.4.2"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
+
"@typescript/native-preview": "7.0.0-dev.20260521.1",
|
|
25
26
|
"typescript": "^6.0.3",
|
|
26
|
-
"vitest": "^4.1.
|
|
27
|
-
"@sigx/vite": "^0.4.3"
|
|
27
|
+
"vitest": "^4.1.7"
|
|
28
28
|
},
|
|
29
29
|
"author": "Andreas Ekdahl",
|
|
30
30
|
"license": "MIT",
|
|
@@ -52,8 +52,9 @@
|
|
|
52
52
|
"realtime"
|
|
53
53
|
],
|
|
54
54
|
"scripts": {
|
|
55
|
-
"build": "
|
|
56
|
-
"dev": "
|
|
57
|
-
"test": "vitest run"
|
|
55
|
+
"build": "node ../../scripts/clean.mjs dist && tsgo",
|
|
56
|
+
"dev": "tsgo --watch",
|
|
57
|
+
"test": "vitest run",
|
|
58
|
+
"clean": "node ../../scripts/clean.mjs dist .turbo"
|
|
58
59
|
}
|
|
59
60
|
}
|