@gjsify/webrtc 0.3.13 → 0.3.14

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 (36) hide show
  1. package/lib/esm/get-user-media.js +95 -80
  2. package/lib/esm/gst-enum-maps.js +55 -59
  3. package/lib/esm/gst-init.js +19 -22
  4. package/lib/esm/gst-stats-parser.js +94 -67
  5. package/lib/esm/gst-utils.js +24 -13
  6. package/lib/esm/index.js +13 -43
  7. package/lib/esm/media-device-info.js +23 -22
  8. package/lib/esm/media-devices.js +150 -139
  9. package/lib/esm/media-stream-track.js +136 -139
  10. package/lib/esm/media-stream.js +76 -75
  11. package/lib/esm/register/data-channel.js +7 -3
  12. package/lib/esm/register/error.js +6 -2
  13. package/lib/esm/register/media-devices.js +6 -2
  14. package/lib/esm/register/media.js +8 -4
  15. package/lib/esm/register/peer-connection.js +9 -5
  16. package/lib/esm/rtc-certificate.js +62 -66
  17. package/lib/esm/rtc-data-channel.js +240 -251
  18. package/lib/esm/rtc-dtls-transport.js +40 -39
  19. package/lib/esm/rtc-dtmf-sender.js +92 -100
  20. package/lib/esm/rtc-error.js +24 -22
  21. package/lib/esm/rtc-events.js +33 -33
  22. package/lib/esm/rtc-ice-candidate.js +71 -72
  23. package/lib/esm/rtc-ice-transport.js +95 -94
  24. package/lib/esm/rtc-peer-connection.js +796 -845
  25. package/lib/esm/rtc-rtp-receiver.js +89 -87
  26. package/lib/esm/rtc-rtp-sender.js +282 -290
  27. package/lib/esm/rtc-rtp-transceiver.js +92 -93
  28. package/lib/esm/rtc-sctp-transport.js +38 -38
  29. package/lib/esm/rtc-session-description.js +47 -51
  30. package/lib/esm/rtc-stats-report.js +39 -34
  31. package/lib/esm/rtc-track-event.js +29 -27
  32. package/lib/esm/rtp-capabilities.js +81 -35
  33. package/lib/esm/tee-multiplexer.js +58 -60
  34. package/lib/esm/wpt-helpers.js +128 -112
  35. package/package.json +13 -13
  36. package/tsconfig.tsbuildinfo +1 -1
@@ -1,70 +1,66 @@
1
1
  import GLib from "gi://GLib?version=2.0";
2
+
3
+ //#region src/rtc-certificate.ts
2
4
  const DEFAULT_EXPIRY_MS = 30 * 24 * 60 * 60 * 1e3;
3
- class RTCCertificate {
4
- expires;
5
- // DOMTimeStamp (ms since epoch)
6
- _fingerprints;
7
- _algorithm;
8
- /** @internal — use RTCPeerConnection.generateCertificate() */
9
- constructor(algorithm, expires, fingerprints) {
10
- this._algorithm = algorithm;
11
- this.expires = expires;
12
- this._fingerprints = fingerprints;
13
- }
14
- getFingerprints() {
15
- return [...this._fingerprints];
16
- }
17
- /** @internal — the algorithm name for debugging/inspection */
18
- get _algorithmName() {
19
- return this._algorithm;
20
- }
21
- }
5
+ var RTCCertificate = class {
6
+ expires;
7
+ _fingerprints;
8
+ _algorithm;
9
+ /** @internal — use RTCPeerConnection.generateCertificate() */
10
+ constructor(algorithm, expires, fingerprints) {
11
+ this._algorithm = algorithm;
12
+ this.expires = expires;
13
+ this._fingerprints = fingerprints;
14
+ }
15
+ getFingerprints() {
16
+ return [...this._fingerprints];
17
+ }
18
+ /** @internal — the algorithm name for debugging/inspection */
19
+ get _algorithmName() {
20
+ return this._algorithm;
21
+ }
22
+ };
23
+ /**
24
+ * Generate a self-signed certificate for use with RTCPeerConnection.
25
+ * Supports ECDSA P-256 and RSASSA-PKCS1-v1_5 with SHA-256.
26
+ *
27
+ * The actual DTLS certificate used by webrtcbin is generated internally
28
+ * by GStreamer — this provides the spec-compliant JS API surface.
29
+ */
22
30
  async function generateCertificate(keygenAlgorithm) {
23
- let name;
24
- if (typeof keygenAlgorithm === "string") {
25
- name = keygenAlgorithm.toLowerCase();
26
- } else if (keygenAlgorithm && typeof keygenAlgorithm === "object" && typeof keygenAlgorithm.name === "string") {
27
- name = keygenAlgorithm.name.toLowerCase();
28
- } else {
29
- throw new DOMException(
30
- "generateCertificate: algorithm must have a name property",
31
- "NotSupportedError"
32
- );
33
- }
34
- if (name === "ecdsa") {
35
- const curve = keygenAlgorithm.namedCurve;
36
- if (curve && curve !== "P-256") {
37
- throw new DOMException(
38
- `generateCertificate: unsupported ECDSA curve '${curve}'`,
39
- "NotSupportedError"
40
- );
41
- }
42
- } else if (name === "rsassa-pkcs1-v1_5") {
43
- const hash = keygenAlgorithm.hash;
44
- const hashName = typeof hash === "string" ? hash : hash?.name;
45
- if (hashName && hashName.toUpperCase() === "SHA-1") {
46
- throw new DOMException(
47
- "generateCertificate: SHA-1 is not supported for RSA certificates",
48
- "NotSupportedError"
49
- );
50
- }
51
- } else {
52
- throw new DOMException(
53
- `generateCertificate: unsupported algorithm '${name}'`,
54
- "NotSupportedError"
55
- );
56
- }
57
- const uuid = GLib.uuid_string_random();
58
- const checksum = GLib.Checksum.new(GLib.ChecksumType.SHA256);
59
- checksum.update(new TextEncoder().encode(uuid + Date.now()));
60
- const fingerprintHex = checksum.get_string();
61
- const formatted = fingerprintHex.slice(0, 64).match(/.{2}/g).join(":").toUpperCase();
62
- const expires = Date.now() + DEFAULT_EXPIRY_MS;
63
- return new RTCCertificate(name, expires, [
64
- { algorithm: "sha-256", value: formatted }
65
- ]);
31
+ let name;
32
+ if (typeof keygenAlgorithm === "string") {
33
+ name = keygenAlgorithm.toLowerCase();
34
+ } else if (keygenAlgorithm && typeof keygenAlgorithm === "object" && typeof keygenAlgorithm.name === "string") {
35
+ name = keygenAlgorithm.name.toLowerCase();
36
+ } else {
37
+ throw new DOMException("generateCertificate: algorithm must have a name property", "NotSupportedError");
38
+ }
39
+ if (name === "ecdsa") {
40
+ const curve = keygenAlgorithm.namedCurve;
41
+ if (curve && curve !== "P-256") {
42
+ throw new DOMException(`generateCertificate: unsupported ECDSA curve '${curve}'`, "NotSupportedError");
43
+ }
44
+ } else if (name === "rsassa-pkcs1-v1_5") {
45
+ const hash = keygenAlgorithm.hash;
46
+ const hashName = typeof hash === "string" ? hash : hash?.name;
47
+ if (hashName && hashName.toUpperCase() === "SHA-1") {
48
+ throw new DOMException("generateCertificate: SHA-1 is not supported for RSA certificates", "NotSupportedError");
49
+ }
50
+ } else {
51
+ throw new DOMException(`generateCertificate: unsupported algorithm '${name}'`, "NotSupportedError");
52
+ }
53
+ const uuid = GLib.uuid_string_random();
54
+ const checksum = GLib.Checksum.new(GLib.ChecksumType.SHA256);
55
+ checksum.update(new TextEncoder().encode(uuid + Date.now()));
56
+ const fingerprintHex = checksum.get_string();
57
+ const formatted = fingerprintHex.slice(0, 64).match(/.{2}/g).join(":").toUpperCase();
58
+ const expires = Date.now() + DEFAULT_EXPIRY_MS;
59
+ return new RTCCertificate(name, expires, [{
60
+ algorithm: "sha-256",
61
+ value: formatted
62
+ }]);
66
63
  }
67
- export {
68
- RTCCertificate,
69
- generateCertificate
70
- };
64
+
65
+ //#endregion
66
+ export { RTCCertificate, generateCertificate };
@@ -1,261 +1,250 @@
1
+ import { RTCError } from "./rtc-error.js";
2
+ import { RTCErrorEvent } from "./rtc-events.js";
3
+ import { DOMException } from "@gjsify/dom-exception";
1
4
  import GLib from "gi://GLib?version=2.0";
2
5
  import { DataChannelBridge } from "@gjsify/webrtc-native";
3
- import { DOMException } from "@gjsify/dom-exception";
4
6
  import { Blob } from "@gjsify/buffer";
5
- import { RTCError } from "./rtc-error.js";
6
- import { RTCErrorEvent } from "./rtc-events.js";
7
+
8
+ //#region src/rtc-data-channel.ts
7
9
  const STATE_MAP = {
8
- 1: "connecting",
9
- 2: "open",
10
- 3: "closing",
11
- 4: "closed"
10
+ 1: "connecting",
11
+ 2: "open",
12
+ 3: "closing",
13
+ 4: "closed"
12
14
  };
15
+ /** Convert a JS typed array / ArrayBuffer to a GLib.Bytes. */
13
16
  function toGBytes(buffer) {
14
- let view;
15
- if (ArrayBuffer.isView(buffer)) {
16
- view = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
17
- } else {
18
- view = new Uint8Array(buffer);
19
- }
20
- return new GLib.Bytes(view);
17
+ let view;
18
+ if (ArrayBuffer.isView(buffer)) {
19
+ view = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
20
+ } else {
21
+ view = new Uint8Array(buffer);
22
+ }
23
+ return new GLib.Bytes(view);
21
24
  }
25
+ /** Convert a GLib.Bytes payload to an ArrayBuffer. */
22
26
  function bytesToArrayBuffer(bytes) {
23
- const arr = bytes.toArray?.();
24
- if (arr instanceof Uint8Array) {
25
- return arr.buffer.slice(arr.byteOffset, arr.byteOffset + arr.byteLength);
26
- }
27
- const data = bytes.get_data?.();
28
- if (data instanceof Uint8Array) {
29
- return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
30
- }
31
- return new ArrayBuffer(0);
32
- }
33
- class RTCDataChannel extends EventTarget {
34
- _native;
35
- _bridge;
36
- _binaryType = "arraybuffer";
37
- _bufferedAmount = 0;
38
- _closed = false;
39
- // `on<event>` attribute handlers — W3C requires both addEventListener and on*.
40
- _onopen = null;
41
- _onclose = null;
42
- _onerror = null;
43
- _onmessage = null;
44
- _onbufferedamountlow = null;
45
- _onclosing = null;
46
- /**
47
- * @internal
48
- * Accepts either a raw GstWebRTCDataChannel (for locally-created channels)
49
- * or a pre-made DataChannelBridge (for remotely-originated channels that
50
- * the WebrtcbinBridge already wrapped on the streaming thread to avoid
51
- * missing early messages).
52
- */
53
- constructor(source) {
54
- super();
55
- if (source.channel !== void 0 && source.dispose_bridge) {
56
- this._bridge = source;
57
- this._native = this._bridge.channel;
58
- } else {
59
- this._native = source;
60
- this._bridge = new DataChannelBridge({ channel: this._native });
61
- }
62
- this._bridge.connect("opened", () => this._handleOpen());
63
- this._bridge.connect("closed", () => this._handleClose());
64
- this._bridge.connect("error-occurred", (_b, message) => this._handleError(message));
65
- this._bridge.connect("message-string", (_b, data) => this._handleString(data));
66
- this._bridge.connect("message-data", (_b, data) => this._handleData(data));
67
- this._bridge.connect("buffered-amount-low", () => this._handleBufferedAmountLow());
68
- this._bridge.connect("ready-state-changed", () => this._handleReadyStateChange());
69
- }
70
- // ---- Properties --------------------------------------------------------
71
- get label() {
72
- return this._native.label;
73
- }
74
- get ordered() {
75
- return this._native.ordered;
76
- }
77
- get protocol() {
78
- return this._native.protocol;
79
- }
80
- get negotiated() {
81
- return this._native.negotiated;
82
- }
83
- get id() {
84
- return this._native.id >= 0 ? this._native.id : null;
85
- }
86
- get maxPacketLifeTime() {
87
- const v = this._native.max_packet_lifetime;
88
- return v >= 0 ? v : null;
89
- }
90
- get maxRetransmits() {
91
- const v = this._native.max_retransmits;
92
- return v >= 0 ? v : null;
93
- }
94
- get readyState() {
95
- if (this._closed) return "closed";
96
- return STATE_MAP[this._native.ready_state] ?? "connecting";
97
- }
98
- get bufferedAmount() {
99
- try {
100
- return Number(this._native.buffered_amount) || this._bufferedAmount;
101
- } catch {
102
- return this._bufferedAmount;
103
- }
104
- }
105
- get bufferedAmountLowThreshold() {
106
- return Number(this._native.buffered_amount_low_threshold) || 0;
107
- }
108
- set bufferedAmountLowThreshold(v) {
109
- this._native.buffered_amount_low_threshold = v;
110
- }
111
- get binaryType() {
112
- return this._binaryType;
113
- }
114
- set binaryType(v) {
115
- if (v !== "arraybuffer" && v !== "blob") return;
116
- this._binaryType = v;
117
- }
118
- // ---- on<event> attribute accessors -------------------------------------
119
- get onopen() {
120
- return this._onopen;
121
- }
122
- set onopen(h) {
123
- this._onopen = h;
124
- }
125
- get onclose() {
126
- return this._onclose;
127
- }
128
- set onclose(h) {
129
- this._onclose = h;
130
- }
131
- get onclosing() {
132
- return this._onclosing;
133
- }
134
- set onclosing(h) {
135
- this._onclosing = h;
136
- }
137
- get onerror() {
138
- return this._onerror;
139
- }
140
- set onerror(h) {
141
- this._onerror = h;
142
- }
143
- get onmessage() {
144
- return this._onmessage;
145
- }
146
- set onmessage(h) {
147
- this._onmessage = h;
148
- }
149
- get onbufferedamountlow() {
150
- return this._onbufferedamountlow;
151
- }
152
- set onbufferedamountlow(h) {
153
- this._onbufferedamountlow = h;
154
- }
155
- // ---- Methods -----------------------------------------------------------
156
- send(data) {
157
- const state = this.readyState;
158
- if (state !== "open") {
159
- throw new DOMException(
160
- `RTCDataChannel.send: readyState is '${state}', expected 'open'`,
161
- "InvalidStateError"
162
- );
163
- }
164
- if (typeof data === "string") {
165
- this._native.send_string(data);
166
- this._bufferedAmount += new TextEncoder().encode(data).byteLength;
167
- return;
168
- }
169
- if (data instanceof Blob) {
170
- const blob = data;
171
- blob.arrayBuffer().then((buf) => {
172
- try {
173
- this._native.send_data(toGBytes(buf));
174
- this._bufferedAmount += buf.byteLength;
175
- } catch {
176
- }
177
- });
178
- return;
179
- }
180
- if (ArrayBuffer.isView(data)) {
181
- const bytes = toGBytes(data);
182
- this._native.send_data(bytes);
183
- this._bufferedAmount += data.byteLength;
184
- return;
185
- }
186
- if (data instanceof ArrayBuffer) {
187
- const bytes = toGBytes(data);
188
- this._native.send_data(bytes);
189
- this._bufferedAmount += data.byteLength;
190
- return;
191
- }
192
- throw new TypeError("RTCDataChannel.send: unsupported data type");
193
- }
194
- close() {
195
- if (this._closed) return;
196
- try {
197
- this._native.close();
198
- } catch {
199
- }
200
- this._disconnectSignals();
201
- this._closed = true;
202
- }
203
- /** @internal */
204
- _disconnectSignals() {
205
- try {
206
- this._bridge.dispose_bridge();
207
- } catch {
208
- }
209
- }
210
- // ---- Signal → event translators ---------------------------------------
211
- // Already running on the main context (DataChannelBridge did the hop).
212
- _handleOpen() {
213
- const ev = new Event("open");
214
- this._onopen?.call(this, ev);
215
- this.dispatchEvent(ev);
216
- }
217
- _handleClose() {
218
- this._closed = true;
219
- const ev = new Event("close");
220
- this._onclose?.call(this, ev);
221
- this.dispatchEvent(ev);
222
- }
223
- _handleError(message) {
224
- const rtcErr = new RTCError(
225
- { errorDetail: "data-channel-failure" },
226
- message || "RTCDataChannel error"
227
- );
228
- const ev = new RTCErrorEvent("error", { error: rtcErr });
229
- this._onerror?.call(this, ev);
230
- this.dispatchEvent(ev);
231
- }
232
- _handleString(data) {
233
- const ev = new MessageEvent("message", { data });
234
- this._onmessage?.call(this, ev);
235
- this.dispatchEvent(ev);
236
- }
237
- _handleData(bytes) {
238
- if (!bytes) return;
239
- const buf = bytesToArrayBuffer(bytes);
240
- const data = this._binaryType === "blob" ? new Blob([buf]) : buf;
241
- const ev = new MessageEvent("message", { data });
242
- this._onmessage?.call(this, ev);
243
- this.dispatchEvent(ev);
244
- }
245
- _handleBufferedAmountLow() {
246
- this._bufferedAmount = Number(this._native.buffered_amount) || 0;
247
- const ev = new Event("bufferedamountlow");
248
- this._onbufferedamountlow?.call(this, ev);
249
- this.dispatchEvent(ev);
250
- }
251
- _handleReadyStateChange() {
252
- if (this.readyState === "closing") {
253
- const ev = new Event("closing");
254
- this._onclosing?.call(this, ev);
255
- this.dispatchEvent(ev);
256
- }
257
- }
27
+ const arr = bytes.toArray?.();
28
+ if (arr instanceof Uint8Array) {
29
+ return arr.buffer.slice(arr.byteOffset, arr.byteOffset + arr.byteLength);
30
+ }
31
+ const data = bytes.get_data?.();
32
+ if (data instanceof Uint8Array) {
33
+ return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
34
+ }
35
+ return new ArrayBuffer(0);
258
36
  }
259
- export {
260
- RTCDataChannel
37
+ var RTCDataChannel = class extends EventTarget {
38
+ _native;
39
+ _bridge;
40
+ _binaryType = "arraybuffer";
41
+ _bufferedAmount = 0;
42
+ _closed = false;
43
+ _onopen = null;
44
+ _onclose = null;
45
+ _onerror = null;
46
+ _onmessage = null;
47
+ _onbufferedamountlow = null;
48
+ _onclosing = null;
49
+ /**
50
+ * @internal
51
+ * Accepts either a raw GstWebRTCDataChannel (for locally-created channels)
52
+ * or a pre-made DataChannelBridge (for remotely-originated channels that
53
+ * the WebrtcbinBridge already wrapped on the streaming thread to avoid
54
+ * missing early messages).
55
+ */
56
+ constructor(source) {
57
+ super();
58
+ if (source.channel !== undefined && source.dispose_bridge) {
59
+ this._bridge = source;
60
+ this._native = this._bridge.channel;
61
+ } else {
62
+ this._native = source;
63
+ this._bridge = new DataChannelBridge({ channel: this._native });
64
+ }
65
+ this._bridge.connect("opened", () => this._handleOpen());
66
+ this._bridge.connect("closed", () => this._handleClose());
67
+ this._bridge.connect("error-occurred", (_b, message) => this._handleError(message));
68
+ this._bridge.connect("message-string", (_b, data) => this._handleString(data));
69
+ this._bridge.connect("message-data", (_b, data) => this._handleData(data));
70
+ this._bridge.connect("buffered-amount-low", () => this._handleBufferedAmountLow());
71
+ this._bridge.connect("ready-state-changed", () => this._handleReadyStateChange());
72
+ }
73
+ get label() {
74
+ return this._native.label;
75
+ }
76
+ get ordered() {
77
+ return this._native.ordered;
78
+ }
79
+ get protocol() {
80
+ return this._native.protocol;
81
+ }
82
+ get negotiated() {
83
+ return this._native.negotiated;
84
+ }
85
+ get id() {
86
+ return this._native.id >= 0 ? this._native.id : null;
87
+ }
88
+ get maxPacketLifeTime() {
89
+ const v = this._native.max_packet_lifetime;
90
+ return v >= 0 ? v : null;
91
+ }
92
+ get maxRetransmits() {
93
+ const v = this._native.max_retransmits;
94
+ return v >= 0 ? v : null;
95
+ }
96
+ get readyState() {
97
+ if (this._closed) return "closed";
98
+ return STATE_MAP[this._native.ready_state] ?? "connecting";
99
+ }
100
+ get bufferedAmount() {
101
+ try {
102
+ return Number(this._native.buffered_amount) || this._bufferedAmount;
103
+ } catch {
104
+ return this._bufferedAmount;
105
+ }
106
+ }
107
+ get bufferedAmountLowThreshold() {
108
+ return Number(this._native.buffered_amount_low_threshold) || 0;
109
+ }
110
+ set bufferedAmountLowThreshold(v) {
111
+ this._native.buffered_amount_low_threshold = v;
112
+ }
113
+ get binaryType() {
114
+ return this._binaryType;
115
+ }
116
+ set binaryType(v) {
117
+ if (v !== "arraybuffer" && v !== "blob") return;
118
+ this._binaryType = v;
119
+ }
120
+ get onopen() {
121
+ return this._onopen;
122
+ }
123
+ set onopen(h) {
124
+ this._onopen = h;
125
+ }
126
+ get onclose() {
127
+ return this._onclose;
128
+ }
129
+ set onclose(h) {
130
+ this._onclose = h;
131
+ }
132
+ get onclosing() {
133
+ return this._onclosing;
134
+ }
135
+ set onclosing(h) {
136
+ this._onclosing = h;
137
+ }
138
+ get onerror() {
139
+ return this._onerror;
140
+ }
141
+ set onerror(h) {
142
+ this._onerror = h;
143
+ }
144
+ get onmessage() {
145
+ return this._onmessage;
146
+ }
147
+ set onmessage(h) {
148
+ this._onmessage = h;
149
+ }
150
+ get onbufferedamountlow() {
151
+ return this._onbufferedamountlow;
152
+ }
153
+ set onbufferedamountlow(h) {
154
+ this._onbufferedamountlow = h;
155
+ }
156
+ send(data) {
157
+ const state = this.readyState;
158
+ if (state !== "open") {
159
+ throw new DOMException(`RTCDataChannel.send: readyState is '${state}', expected 'open'`, "InvalidStateError");
160
+ }
161
+ if (typeof data === "string") {
162
+ this._native.send_string(data);
163
+ this._bufferedAmount += new TextEncoder().encode(data).byteLength;
164
+ return;
165
+ }
166
+ if (data instanceof Blob) {
167
+ const blob = data;
168
+ blob.arrayBuffer().then((buf) => {
169
+ try {
170
+ this._native.send_data(toGBytes(buf));
171
+ this._bufferedAmount += buf.byteLength;
172
+ } catch {}
173
+ });
174
+ return;
175
+ }
176
+ if (ArrayBuffer.isView(data)) {
177
+ const bytes = toGBytes(data);
178
+ this._native.send_data(bytes);
179
+ this._bufferedAmount += data.byteLength;
180
+ return;
181
+ }
182
+ if (data instanceof ArrayBuffer) {
183
+ const bytes = toGBytes(data);
184
+ this._native.send_data(bytes);
185
+ this._bufferedAmount += data.byteLength;
186
+ return;
187
+ }
188
+ throw new TypeError("RTCDataChannel.send: unsupported data type");
189
+ }
190
+ close() {
191
+ if (this._closed) return;
192
+ try {
193
+ this._native.close();
194
+ } catch {}
195
+ this._disconnectSignals();
196
+ this._closed = true;
197
+ }
198
+ /** @internal */
199
+ _disconnectSignals() {
200
+ try {
201
+ this._bridge.dispose_bridge();
202
+ } catch {}
203
+ }
204
+ _handleOpen() {
205
+ const ev = new Event("open");
206
+ this._onopen?.call(this, ev);
207
+ this.dispatchEvent(ev);
208
+ }
209
+ _handleClose() {
210
+ this._closed = true;
211
+ const ev = new Event("close");
212
+ this._onclose?.call(this, ev);
213
+ this.dispatchEvent(ev);
214
+ }
215
+ _handleError(message) {
216
+ const rtcErr = new RTCError({ errorDetail: "data-channel-failure" }, message || "RTCDataChannel error");
217
+ const ev = new RTCErrorEvent("error", { error: rtcErr });
218
+ this._onerror?.call(this, ev);
219
+ this.dispatchEvent(ev);
220
+ }
221
+ _handleString(data) {
222
+ const ev = new MessageEvent("message", { data });
223
+ this._onmessage?.call(this, ev);
224
+ this.dispatchEvent(ev);
225
+ }
226
+ _handleData(bytes) {
227
+ if (!bytes) return;
228
+ const buf = bytesToArrayBuffer(bytes);
229
+ const data = this._binaryType === "blob" ? new Blob([buf]) : buf;
230
+ const ev = new MessageEvent("message", { data });
231
+ this._onmessage?.call(this, ev);
232
+ this.dispatchEvent(ev);
233
+ }
234
+ _handleBufferedAmountLow() {
235
+ this._bufferedAmount = Number(this._native.buffered_amount) || 0;
236
+ const ev = new Event("bufferedamountlow");
237
+ this._onbufferedamountlow?.call(this, ev);
238
+ this.dispatchEvent(ev);
239
+ }
240
+ _handleReadyStateChange() {
241
+ if (this.readyState === "closing") {
242
+ const ev = new Event("closing");
243
+ this._onclosing?.call(this, ev);
244
+ this.dispatchEvent(ev);
245
+ }
246
+ }
261
247
  };
248
+
249
+ //#endregion
250
+ export { RTCDataChannel };