node-datachannel 0.26.0 → 0.28.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.
Files changed (103) hide show
  1. package/.eslintrc.json +25 -25
  2. package/.prettierignore +4 -0
  3. package/.prettierrc +1 -0
  4. package/API.md +4 -4
  5. package/BULDING.md +11 -2
  6. package/CMakeLists.txt +37 -13
  7. package/README.md +22 -18
  8. package/dist/cjs/index.cjs.map +1 -1
  9. package/dist/cjs/lib/datachannel-stream.cjs +13 -13
  10. package/dist/cjs/lib/datachannel-stream.cjs.map +1 -1
  11. package/dist/cjs/lib/index.cjs +1 -3
  12. package/dist/cjs/lib/index.cjs.map +1 -1
  13. package/dist/cjs/lib/websocket-server.cjs.map +1 -1
  14. package/dist/cjs/lib/websocket.cjs.map +1 -1
  15. package/dist/cjs/polyfill/Events.cjs +52 -3
  16. package/dist/cjs/polyfill/Events.cjs.map +1 -1
  17. package/dist/cjs/polyfill/Exception.cjs.map +1 -1
  18. package/dist/cjs/polyfill/RTCCertificate.cjs +5 -2
  19. package/dist/cjs/polyfill/RTCCertificate.cjs.map +1 -1
  20. package/dist/cjs/polyfill/RTCDataChannel.cjs +27 -19
  21. package/dist/cjs/polyfill/RTCDataChannel.cjs.map +1 -1
  22. package/dist/cjs/polyfill/RTCDtlsTransport.cjs +6 -5
  23. package/dist/cjs/polyfill/RTCDtlsTransport.cjs.map +1 -1
  24. package/dist/cjs/polyfill/RTCError.cjs +9 -2
  25. package/dist/cjs/polyfill/RTCError.cjs.map +1 -1
  26. package/dist/cjs/polyfill/RTCIceCandidate.cjs +13 -8
  27. package/dist/cjs/polyfill/RTCIceCandidate.cjs.map +1 -1
  28. package/dist/cjs/polyfill/RTCIceTransport.cjs +26 -16
  29. package/dist/cjs/polyfill/RTCIceTransport.cjs.map +1 -1
  30. package/dist/cjs/polyfill/RTCPeerConnection.cjs +80 -70
  31. package/dist/cjs/polyfill/RTCPeerConnection.cjs.map +1 -1
  32. package/dist/cjs/polyfill/RTCSctpTransport.cjs +9 -11
  33. package/dist/cjs/polyfill/RTCSctpTransport.cjs.map +1 -1
  34. package/dist/cjs/polyfill/RTCSessionDescription.cjs +10 -2
  35. package/dist/cjs/polyfill/RTCSessionDescription.cjs.map +1 -1
  36. package/dist/cjs/polyfill/index.cjs.map +1 -1
  37. package/dist/esm/index.mjs.map +1 -1
  38. package/dist/esm/lib/datachannel-stream.mjs.map +1 -1
  39. package/dist/esm/lib/index.mjs +1 -3
  40. package/dist/esm/lib/index.mjs.map +1 -1
  41. package/dist/esm/lib/websocket-server.mjs.map +1 -1
  42. package/dist/esm/lib/websocket.mjs.map +1 -1
  43. package/dist/esm/polyfill/Events.mjs +52 -4
  44. package/dist/esm/polyfill/Events.mjs.map +1 -1
  45. package/dist/esm/polyfill/Exception.mjs.map +1 -1
  46. package/dist/esm/polyfill/RTCCertificate.mjs +5 -2
  47. package/dist/esm/polyfill/RTCCertificate.mjs.map +1 -1
  48. package/dist/esm/polyfill/RTCDataChannel.mjs +27 -19
  49. package/dist/esm/polyfill/RTCDataChannel.mjs.map +1 -1
  50. package/dist/esm/polyfill/RTCDtlsTransport.mjs +6 -5
  51. package/dist/esm/polyfill/RTCDtlsTransport.mjs.map +1 -1
  52. package/dist/esm/polyfill/RTCError.mjs +9 -2
  53. package/dist/esm/polyfill/RTCError.mjs.map +1 -1
  54. package/dist/esm/polyfill/RTCIceCandidate.mjs +13 -8
  55. package/dist/esm/polyfill/RTCIceCandidate.mjs.map +1 -1
  56. package/dist/esm/polyfill/RTCIceTransport.mjs +26 -17
  57. package/dist/esm/polyfill/RTCIceTransport.mjs.map +1 -1
  58. package/dist/esm/polyfill/RTCPeerConnection.mjs +80 -70
  59. package/dist/esm/polyfill/RTCPeerConnection.mjs.map +1 -1
  60. package/dist/esm/polyfill/RTCSctpTransport.mjs +9 -11
  61. package/dist/esm/polyfill/RTCSctpTransport.mjs.map +1 -1
  62. package/dist/esm/polyfill/RTCSessionDescription.mjs +10 -2
  63. package/dist/esm/polyfill/RTCSessionDescription.mjs.map +1 -1
  64. package/dist/esm/polyfill/index.mjs.map +1 -1
  65. package/dist/types/lib/index.d.ts +5 -2
  66. package/dist/types/lib/types.d.ts +6 -6
  67. package/dist/types/polyfill/Events.d.ts +3 -3
  68. package/dist/types/polyfill/RTCCertificate.d.ts +1 -0
  69. package/dist/types/polyfill/RTCDataChannel.d.ts +6 -6
  70. package/dist/types/polyfill/RTCDtlsTransport.d.ts +4 -6
  71. package/dist/types/polyfill/RTCError.d.ts +1 -0
  72. package/dist/types/polyfill/RTCIceCandidate.d.ts +1 -1
  73. package/dist/types/polyfill/RTCIceTransport.d.ts +16 -10
  74. package/dist/types/polyfill/RTCPeerConnection.d.ts +29 -22
  75. package/dist/types/polyfill/RTCSctpTransport.d.ts +2 -4
  76. package/dist/types/polyfill/RTCSessionDescription.d.ts +1 -0
  77. package/jest.config.ts +8 -8
  78. package/package.json +114 -112
  79. package/rollup.config.mjs +1 -1
  80. package/src/cpp/data-channel-wrapper.cpp +11 -0
  81. package/src/cpp/main.cpp +14 -0
  82. package/src/cpp/peer-connection-wrapper.cpp +9 -1
  83. package/src/cpp/peer-connection-wrapper.h +5 -1
  84. package/src/cpp/rtc-wrapper.cpp +18 -0
  85. package/src/index.ts +0 -1
  86. package/src/lib/datachannel-stream.ts +83 -84
  87. package/src/lib/index.ts +165 -139
  88. package/src/lib/types.ts +97 -72
  89. package/src/lib/websocket-server.ts +25 -25
  90. package/src/lib/websocket.ts +19 -19
  91. package/src/polyfill/Events.ts +65 -19
  92. package/src/polyfill/Exception.ts +24 -24
  93. package/src/polyfill/README.md +8 -8
  94. package/src/polyfill/RTCCertificate.ts +16 -12
  95. package/src/polyfill/RTCDataChannel.ts +198 -192
  96. package/src/polyfill/RTCDtlsTransport.ts +38 -39
  97. package/src/polyfill/RTCError.ts +63 -56
  98. package/src/polyfill/RTCIceCandidate.ts +120 -116
  99. package/src/polyfill/RTCIceTransport.ts +71 -64
  100. package/src/polyfill/RTCPeerConnection.ts +436 -420
  101. package/src/polyfill/RTCSctpTransport.ts +43 -47
  102. package/src/polyfill/RTCSessionDescription.ts +26 -17
  103. package/src/polyfill/index.ts +22 -22
@@ -1,33 +1,79 @@
1
1
  import RTCDataChannel from './RTCDataChannel';
2
- import RTCIceCandidate from './RTCIceCandidate';
3
-
2
+ import RTCError from './RTCError';
4
3
 
5
4
  export class RTCPeerConnectionIceEvent extends Event implements globalThis.RTCPeerConnectionIceEvent {
6
- #candidate: RTCIceCandidate;
5
+ #candidate: globalThis.RTCIceCandidate;
6
+
7
+ constructor(candidate: globalThis.RTCIceCandidate) {
8
+ super('icecandidate');
7
9
 
8
- constructor(candidate: RTCIceCandidate) {
9
- super('icecandidate');
10
+ this.#candidate = candidate;
11
+ }
10
12
 
11
- this.#candidate = candidate;
12
- }
13
+ get candidate(): globalThis.RTCIceCandidate {
14
+ return this.#candidate;
15
+ }
13
16
 
14
- get candidate(): RTCIceCandidate {
15
- return this.#candidate;
16
- }
17
+ get url(): string {
18
+ return '';
19
+ }
17
20
  }
18
21
 
19
22
  export class RTCDataChannelEvent extends Event implements globalThis.RTCDataChannelEvent {
20
- #channel: RTCDataChannel;
23
+ #channel: RTCDataChannel;
24
+
25
+ constructor(type: string = 'datachannel', eventInitDict: globalThis.RTCDataChannelEventInit) {
26
+ super(type);
21
27
 
22
- constructor(type: string, eventInitDict: globalThis.RTCDataChannelEventInit) {
23
- super(type);
28
+ if (arguments.length === 0)
29
+ throw new TypeError(
30
+ `Failed to construct 'RTCDataChannelEvent': 2 arguments required, but only ${arguments.length} present.`,
31
+ );
32
+ if (typeof eventInitDict !== 'object')
33
+ throw new TypeError(
34
+ "Failed to construct 'RTCDataChannelEvent': The provided value is not of type 'RTCDataChannelEventInit'.",
35
+ );
36
+ if (!eventInitDict.channel)
37
+ throw new TypeError(
38
+ "Failed to construct 'RTCDataChannelEvent': Failed to read the 'channel' property from 'RTCDataChannelEventInit': Required member is undefined.",
39
+ );
40
+ if (eventInitDict.channel.constructor !== RTCDataChannel)
41
+ throw new TypeError(
42
+ "Failed to construct 'RTCDataChannelEvent': Failed to read the 'channel' property from 'RTCDataChannelEventInit': Failed to convert value to 'RTCDataChannel'.",
43
+ );
24
44
 
25
- if (type && !eventInitDict.channel) throw new TypeError('channel member is required');
45
+ this.#channel = eventInitDict?.channel;
46
+ }
47
+
48
+ get channel(): RTCDataChannel {
49
+ return this.#channel;
50
+ }
51
+ }
26
52
 
27
- this.#channel = eventInitDict?.channel as RTCDataChannel;
28
- }
53
+ export class RTCErrorEvent extends Event implements globalThis.RTCErrorEvent {
54
+ #error: RTCError;
55
+ constructor(type: string, init: globalThis.RTCErrorEventInit) {
56
+ if (arguments.length < 2)
57
+ throw new TypeError(
58
+ `Failed to construct 'RTCErrorEvent': 2 arguments required, but only ${arguments.length} present.`,
59
+ );
60
+ if (typeof init !== 'object')
61
+ throw new TypeError(
62
+ "Failed to construct 'RTCErrorEvent': The provided value is not of type 'RTCErrorEventInit'.",
63
+ );
64
+ if (!init.error)
65
+ throw new TypeError(
66
+ "Failed to construct 'RTCErrorEvent': Failed to read the 'error' property from 'RTCErrorEventInit': Required member is undefined.",
67
+ );
68
+ if (init.error.constructor !== RTCError)
69
+ throw new TypeError(
70
+ "Failed to construct 'RTCErrorEvent': Failed to read the 'error' property from 'RTCErrorEventInit': Failed to convert value to 'RTCError'.",
71
+ );
72
+ super(type || 'error');
73
+ this.#error = init.error;
74
+ }
29
75
 
30
- get channel(): RTCDataChannel {
31
- return this.#channel;
32
- }
76
+ get error(): RTCError {
77
+ return this.#error;
78
+ }
33
79
  }
@@ -1,37 +1,37 @@
1
1
  /// <reference lib="dom" />
2
2
 
3
3
  export class InvalidStateError extends DOMException {
4
- constructor(msg: string) {
5
- super(msg, 'InvalidStateError');
6
- }
7
- };
4
+ constructor(msg: string) {
5
+ super(msg, 'InvalidStateError');
6
+ }
7
+ }
8
8
 
9
9
  export class TypeError extends DOMException {
10
- constructor(msg: string) {
11
- super(msg, 'TypeError');
12
- }
13
- };
10
+ constructor(msg: string) {
11
+ super(msg, 'TypeError');
12
+ }
13
+ }
14
14
 
15
15
  export class OperationError extends DOMException {
16
- constructor(msg: string) {
17
- super(msg, 'OperationError');
18
- }
19
- };
16
+ constructor(msg: string) {
17
+ super(msg, 'OperationError');
18
+ }
19
+ }
20
20
 
21
21
  export class NotFoundError extends DOMException {
22
- constructor(msg: string) {
23
- super(msg, 'NotFoundError');
24
- }
25
- };
22
+ constructor(msg: string) {
23
+ super(msg, 'NotFoundError');
24
+ }
25
+ }
26
26
 
27
27
  export class InvalidAccessError extends DOMException {
28
- constructor(msg: string) {
29
- super(msg, 'InvalidAccessError');
30
- }
31
- };
28
+ constructor(msg: string) {
29
+ super(msg, 'InvalidAccessError');
30
+ }
31
+ }
32
32
 
33
33
  export class SyntaxError extends DOMException {
34
- constructor(msg: string) {
35
- super(msg, 'SyntaxError');
36
- }
37
- };
34
+ constructor(msg: string) {
35
+ super(msg, 'SyntaxError');
36
+ }
37
+ }
@@ -20,22 +20,22 @@ var peer1 = new Peer({ initiator: true, wrtc: nodeDatachannelPolyfill });
20
20
  var peer2 = new Peer({ wrtc: nodeDatachannelPolyfill });
21
21
 
22
22
  peer1.on('signal', (data) => {
23
- // when peer1 has signaling data, give it to peer2 somehow
24
- peer2.signal(data);
23
+ // when peer1 has signaling data, give it to peer2 somehow
24
+ peer2.signal(data);
25
25
  });
26
26
 
27
27
  peer2.on('signal', (data) => {
28
- // when peer2 has signaling data, give it to peer1 somehow
29
- peer1.signal(data);
28
+ // when peer2 has signaling data, give it to peer1 somehow
29
+ peer1.signal(data);
30
30
  });
31
31
 
32
32
  peer1.on('connect', () => {
33
- // wait for 'connect' event before using the data channel
34
- peer1.send('hey peer2, how is it going?');
33
+ // wait for 'connect' event before using the data channel
34
+ peer1.send('hey peer2, how is it going?');
35
35
  });
36
36
 
37
37
  peer2.on('data', (data) => {
38
- // got a data channel message
39
- console.log('got a message from peer1: ' + data);
38
+ // got a data channel message
39
+ console.log('got a message from peer1: ' + data);
40
40
  });
41
41
  ```
@@ -1,17 +1,21 @@
1
1
  export default class RTCCertificate implements globalThis.RTCCertificate {
2
- #expires: number;
3
- #fingerprints: globalThis.RTCDtlsFingerprint[];
2
+ #expires: number = 0;
3
+ #fingerprints: globalThis.RTCDtlsFingerprint[] = [];
4
4
 
5
- constructor() {
6
- this.#expires = null;
7
- this.#fingerprints = [];
8
- }
5
+ constructor() {
6
+ this.#expires = null;
7
+ this.#fingerprints = [];
8
+ }
9
9
 
10
- get expires(): number {
11
- return this.#expires;
12
- }
10
+ get expires(): number {
11
+ return this.#expires;
12
+ }
13
13
 
14
- getFingerprints(): globalThis.RTCDtlsFingerprint[] {
15
- return this.#fingerprints;
16
- }
14
+ getFingerprints(): globalThis.RTCDtlsFingerprint[] {
15
+ return this.#fingerprints;
16
+ }
17
+
18
+ getAlgorithm(): string {
19
+ return '';
20
+ }
17
21
  }
@@ -1,200 +1,206 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import * as exceptions from './Exception';
3
3
  import { DataChannel } from '../lib/index';
4
+ import { RTCErrorEvent } from './Events';
4
5
 
5
6
  export default class RTCDataChannel extends EventTarget implements globalThis.RTCDataChannel {
6
- #dataChannel: DataChannel;
7
- #readyState: RTCDataChannelState;
8
- #bufferedAmountLowThreshold: number;
9
- #binaryType: BinaryType;
10
- #maxPacketLifeTime: number | null;
11
- #maxRetransmits: number | null;
12
- #negotiated: boolean;
13
- #ordered: boolean;
14
-
15
- #closeRequested = false;
16
-
17
- // events
18
- onbufferedamountlow: ((this: RTCDataChannel, ev: Event) => any) | null;
19
- onclose: ((this: RTCDataChannel, ev: Event) => any) | null;
20
- onclosing: ((this: RTCDataChannel, ev: Event) => any) | null;
21
- onerror: ((this: RTCDataChannel, ev: Event) => any) | null;
22
- onmessage: ((this: RTCDataChannel, ev: MessageEvent) => any) | null;
23
- onopen: ((this: RTCDataChannel, ev: Event) => any) | null;
24
-
25
- constructor(dataChannel: DataChannel, opts: globalThis.RTCDataChannelInit = {}) {
26
- super();
27
-
28
- this.#dataChannel = dataChannel;
29
- this.#binaryType = 'blob';
30
- this.#readyState = this.#dataChannel.isOpen() ? 'open' : 'connecting';
31
- this.#bufferedAmountLowThreshold = 0;
32
- this.#maxPacketLifeTime = opts.maxPacketLifeTime || null;
33
- this.#maxRetransmits = opts.maxRetransmits || null;
34
- this.#negotiated = opts.negotiated || false;
35
- this.#ordered = opts.ordered || true;
36
-
37
- // forward dataChannel events
38
- this.#dataChannel.onOpen(() => {
39
- this.#readyState = 'open';
40
- this.dispatchEvent(new Event('open', {}));
41
- });
42
-
43
- this.#dataChannel.onClosed(() => {
44
- // Simulate closing event
45
- if (!this.#closeRequested) {
46
- this.#readyState = 'closing';
47
- this.dispatchEvent(new Event('closing'));
48
- }
49
-
50
- setImmediate(() => {
51
- this.#readyState = 'closed';
52
- this.dispatchEvent(new Event('close'));
53
- });
54
- });
55
-
56
- this.#dataChannel.onError((msg) => {
57
- this.dispatchEvent(
58
- new globalThis.RTCErrorEvent('error', {
59
- error: new RTCError(
60
- {
61
- errorDetail: 'data-channel-failure',
62
- },
63
- msg,
64
- ),
65
- }),
66
- );
67
- });
68
-
69
- this.#dataChannel.onBufferedAmountLow(() => {
70
- this.dispatchEvent(new Event('bufferedamountlow'));
71
- });
72
-
73
- this.#dataChannel.onMessage((data) => {
74
- if (ArrayBuffer.isView(data)) {
75
- if (this.binaryType == 'arraybuffer')
76
- data = data.buffer;
77
- else
78
- data = Buffer.from(data.buffer);
79
- }
80
-
81
- this.dispatchEvent(new MessageEvent('message', { data }));
82
- });
83
-
84
- // forward events to properties
85
- this.addEventListener('message', (e) => {
86
- if (this.onmessage) this.onmessage(e as MessageEvent);
87
- });
88
- this.addEventListener('bufferedamountlow', (e) => {
89
- if (this.onbufferedamountlow) this.onbufferedamountlow(e);
90
- });
91
- this.addEventListener('error', (e) => {
92
- if (this.onerror) this.onerror(e);
93
- });
94
- this.addEventListener('close', (e) => {
95
- if (this.onclose) this.onclose(e);
96
- });
97
- this.addEventListener('closing', (e) => {
98
- if (this.onclosing) this.onclosing(e);
99
- });
100
- this.addEventListener('open', (e) => {
101
- if (this.onopen) this.onopen(e);
102
- });
103
- }
104
-
105
- set binaryType(type) {
106
- if (type !== 'blob' && type !== 'arraybuffer') {
107
- throw new DOMException(
108
- "Failed to set the 'binaryType' property on 'RTCDataChannel': Unknown binary type : " + type,
109
- 'TypeMismatchError',
110
- );
111
- }
112
- this.#binaryType = type;
113
- }
114
-
115
- get binaryType(): BinaryType {
116
- return this.#binaryType;
117
- }
118
-
119
- get bufferedAmount(): number {
120
- return this.#dataChannel.bufferedAmount();
121
- }
122
-
123
- get bufferedAmountLowThreshold(): number {
124
- return this.#bufferedAmountLowThreshold;
125
- }
126
-
127
- set bufferedAmountLowThreshold(value) {
128
- const number = Number(value) || 0;
129
- this.#bufferedAmountLowThreshold = number;
130
- this.#dataChannel.setBufferedAmountLowThreshold(number);
131
- }
132
-
133
- get id(): number | null {
134
- return this.#dataChannel.getId();
135
- }
136
-
137
- get label(): string {
138
- return this.#dataChannel.getLabel();
139
- }
140
-
141
- get maxPacketLifeTime(): number | null {
142
- return this.#maxPacketLifeTime;
143
- }
144
-
145
- get maxRetransmits(): number | null {
146
- return this.#maxRetransmits;
147
- }
148
-
149
- get negotiated(): boolean {
150
- return this.#negotiated;
151
- }
152
-
153
- get ordered(): boolean {
154
- return this.#ordered;
155
- }
156
-
157
- get protocol(): string {
158
- return this.#dataChannel.getProtocol();
159
- }
160
-
161
- get readyState(): globalThis.RTCDataChannelState {
162
- return this.#readyState;
163
- }
164
-
165
- send(data): void {
166
- if (this.#readyState !== 'open') {
167
- throw new exceptions.InvalidStateError(
168
- "Failed to execute 'send' on 'RTCDataChannel': RTCDataChannel.readyState is not 'open'",
169
- );
170
- }
171
-
172
- // Needs network error, type error implemented
173
- if (typeof data === 'string') {
174
- this.#dataChannel.sendMessage(data);
175
- } else if (data instanceof Blob) {
176
- data.arrayBuffer().then((ab) => {
177
- if (process?.versions?.bun) {
178
- this.#dataChannel.sendMessageBinary(Buffer.from(ab));
179
- } else {
180
- this.#dataChannel.sendMessageBinary(new Uint8Array(ab));
181
- }
182
- });
183
- } else if (data instanceof Uint8Array) {
184
- this.#dataChannel.sendMessageBinary(data);
7
+ #dataChannel: DataChannel;
8
+ #readyState: globalThis.RTCDataChannelState;
9
+ #bufferedAmountLowThreshold: number;
10
+ #binaryType: BinaryType;
11
+ #maxPacketLifeTime: number | null;
12
+ #maxRetransmits: number | null;
13
+ #negotiated: boolean;
14
+ #ordered: boolean;
15
+ #id: number;
16
+ #label: string;
17
+ #protocol: string;
18
+
19
+ #closeRequested = false;
20
+
21
+ // events
22
+ onbufferedamountlow: globalThis.RTCDataChannel['onbufferedamountlow'] = null;
23
+ onclose: globalThis.RTCDataChannel['onclose'] = null;
24
+ onclosing: globalThis.RTCDataChannel['onclosing'] = null;
25
+ onerror: globalThis.RTCDataChannel['onerror'] = null;
26
+ onmessage: globalThis.RTCDataChannel['onmessage'] = null;
27
+ onopen: globalThis.RTCDataChannel['onopen'] = null;
28
+
29
+ constructor(dataChannel: DataChannel, opts: globalThis.RTCDataChannelInit = {}) {
30
+ super();
31
+
32
+ this.#dataChannel = dataChannel;
33
+ this.#binaryType = 'blob';
34
+ this.#readyState = this.#dataChannel.isOpen() ? 'open' : 'connecting';
35
+ this.#bufferedAmountLowThreshold = 0;
36
+ this.#maxPacketLifeTime = opts.maxPacketLifeTime ?? null;
37
+ this.#maxRetransmits = opts.maxRetransmits ?? null;
38
+ this.#negotiated = opts.negotiated ?? false;
39
+ this.#ordered = opts.ordered ?? true;
40
+ this.#id = this.#dataChannel.getId();
41
+ this.#label = this.#dataChannel.getLabel();
42
+ this.#protocol = this.#dataChannel.getProtocol();
43
+
44
+ // forward dataChannel events
45
+ this.#dataChannel.onOpen(() => {
46
+ this.#readyState = 'open';
47
+ this.dispatchEvent(new Event('open', {}));
48
+ });
49
+
50
+ this.#dataChannel.onClosed(() => {
51
+ // Simulate closing event
52
+ if (!this.#closeRequested) {
53
+ this.#readyState = 'closing';
54
+ this.dispatchEvent(new Event('closing'));
55
+ }
56
+
57
+ setImmediate(() => {
58
+ this.#readyState = 'closed';
59
+ this.dispatchEvent(new Event('close'));
60
+ });
61
+ });
62
+
63
+ this.#dataChannel.onError((msg) => {
64
+ this.dispatchEvent(
65
+ new RTCErrorEvent('error', {
66
+ error: new RTCError(
67
+ {
68
+ errorDetail: 'data-channel-failure',
69
+ },
70
+ msg,
71
+ ),
72
+ }),
73
+ );
74
+ });
75
+
76
+ this.#dataChannel.onBufferedAmountLow(() => {
77
+ this.dispatchEvent(new Event('bufferedamountlow'));
78
+ });
79
+
80
+ this.#dataChannel.onMessage((data) => {
81
+ if (ArrayBuffer.isView(data)) {
82
+ if (this.binaryType == 'arraybuffer') data = data.buffer;
83
+ else data = Buffer.from(data.buffer);
84
+ }
85
+
86
+ this.dispatchEvent(new MessageEvent('message', { data }));
87
+ });
88
+
89
+ // forward events to properties
90
+ this.addEventListener('message', (e) => {
91
+ if (this.onmessage) this.onmessage(e as MessageEvent);
92
+ });
93
+ this.addEventListener('bufferedamountlow', (e) => {
94
+ if (this.onbufferedamountlow) this.onbufferedamountlow(e);
95
+ });
96
+ this.addEventListener('error', (e) => {
97
+ if (this.onerror) this.onerror(e as RTCErrorEvent);
98
+ });
99
+ this.addEventListener('close', (e) => {
100
+ if (this.onclose) this.onclose(e);
101
+ });
102
+ this.addEventListener('closing', (e) => {
103
+ if (this.onclosing) this.onclosing(e);
104
+ });
105
+ this.addEventListener('open', (e) => {
106
+ if (this.onopen) this.onopen(e);
107
+ });
108
+ }
109
+
110
+ set binaryType(type) {
111
+ if (type !== 'blob' && type !== 'arraybuffer') {
112
+ throw new DOMException(
113
+ "Failed to set the 'binaryType' property on 'RTCDataChannel': Unknown binary type : " +
114
+ type,
115
+ 'TypeMismatchError',
116
+ );
117
+ }
118
+ this.#binaryType = type;
119
+ }
120
+
121
+ get binaryType(): BinaryType {
122
+ return this.#binaryType;
123
+ }
124
+
125
+ get bufferedAmount(): number {
126
+ return this.#dataChannel.bufferedAmount();
127
+ }
128
+
129
+ get bufferedAmountLowThreshold(): number {
130
+ return this.#bufferedAmountLowThreshold;
131
+ }
132
+
133
+ set bufferedAmountLowThreshold(value) {
134
+ const number = Number(value) || 0;
135
+ this.#bufferedAmountLowThreshold = number;
136
+ this.#dataChannel.setBufferedAmountLowThreshold(number);
137
+ }
138
+
139
+ get id(): number | null {
140
+ return this.#id;
141
+ }
142
+
143
+ get label(): string {
144
+ return this.#label;
145
+ }
146
+
147
+ get maxPacketLifeTime(): number | null {
148
+ return this.#maxPacketLifeTime;
149
+ }
150
+
151
+ get maxRetransmits(): number | null {
152
+ return this.#maxRetransmits;
153
+ }
154
+
155
+ get negotiated(): boolean {
156
+ return this.#negotiated;
157
+ }
158
+
159
+ get ordered(): boolean {
160
+ return this.#ordered;
161
+ }
162
+
163
+ get protocol(): string {
164
+ return this.#protocol;
165
+ }
166
+
167
+ get readyState(): globalThis.RTCDataChannelState {
168
+ return this.#readyState;
169
+ }
170
+
171
+ send(data): void {
172
+ if (this.#readyState !== 'open') {
173
+ throw new exceptions.InvalidStateError(
174
+ "Failed to execute 'send' on 'RTCDataChannel': RTCDataChannel.readyState is not 'open'",
175
+ );
176
+ }
177
+
178
+ // Needs network error, type error implemented
179
+ if (typeof data === 'string') {
180
+ this.#dataChannel.sendMessage(data);
181
+ } else if (data instanceof Blob) {
182
+ data.arrayBuffer().then((ab) => {
183
+ if (process?.versions?.bun) {
184
+ this.#dataChannel.sendMessageBinary(Buffer.from(ab));
185
185
  } else {
186
- if (process?.versions?.bun) {
187
- this.#dataChannel.sendMessageBinary(Buffer.from(data));
188
- } else {
189
- this.#dataChannel.sendMessageBinary(new Uint8Array(data));
190
- }
186
+ this.#dataChannel.sendMessageBinary(new Uint8Array(ab));
191
187
  }
192
- }
193
-
194
- close(): void {
195
- this.#closeRequested = true;
196
- setImmediate(() => {
197
- this.#dataChannel.close();
198
- });
199
- }
188
+ });
189
+ } else if (data instanceof Uint8Array) {
190
+ this.#dataChannel.sendMessageBinary(data);
191
+ } else {
192
+ if (process?.versions?.bun) {
193
+ this.#dataChannel.sendMessageBinary(Buffer.from(data));
194
+ } else {
195
+ this.#dataChannel.sendMessageBinary(new Uint8Array(data));
196
+ }
197
+ }
198
+ }
199
+
200
+ close(): void {
201
+ this.#closeRequested = true;
202
+ setImmediate(() => {
203
+ this.#dataChannel.close();
204
+ });
205
+ }
200
206
  }