werift 0.23.0 → 0.24.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 (145) hide show
  1. package/README.md +46 -0
  2. package/lib/common/src/transport.d.ts +22 -9
  3. package/lib/common/src/transport.js +152 -25
  4. package/lib/common/src/transport.js.map +1 -1
  5. package/lib/ice/src/candidate.d.ts +16 -1
  6. package/lib/ice/src/candidate.js +99 -15
  7. package/lib/ice/src/candidate.js.map +1 -1
  8. package/lib/ice/src/ice.d.ts +2 -0
  9. package/lib/ice/src/ice.js +171 -41
  10. package/lib/ice/src/ice.js.map +1 -1
  11. package/lib/ice/src/iceBase.d.ts +23 -2
  12. package/lib/ice/src/iceBase.js +63 -1
  13. package/lib/ice/src/iceBase.js.map +1 -1
  14. package/lib/ice/src/index.d.ts +2 -0
  15. package/lib/ice/src/index.js +2 -0
  16. package/lib/ice/src/index.js.map +1 -1
  17. package/lib/ice/src/stun/const.d.ts +1 -26
  18. package/lib/ice/src/stun/const.js +15 -54
  19. package/lib/ice/src/stun/const.js.map +1 -1
  20. package/lib/ice/src/stun/message.d.ts +1 -25
  21. package/lib/ice/src/stun/message.js +15 -149
  22. package/lib/ice/src/stun/message.js.map +1 -1
  23. package/lib/ice/src/stun/protocol.d.ts +1 -1
  24. package/lib/ice/src/stun/protocol.js +2 -2
  25. package/lib/ice/src/stun/protocol.js.map +1 -1
  26. package/lib/ice/src/stun/tcpFrame.d.ts +5 -0
  27. package/lib/ice/src/stun/tcpFrame.js +26 -0
  28. package/lib/ice/src/stun/tcpFrame.js.map +1 -0
  29. package/lib/ice/src/stun/tcpProtocol.d.ts +51 -0
  30. package/lib/ice/src/stun/tcpProtocol.js +326 -0
  31. package/lib/ice/src/stun/tcpProtocol.js.map +1 -0
  32. package/lib/ice/src/stun/transaction.d.ts +2 -1
  33. package/lib/ice/src/stun/transaction.js +9 -3
  34. package/lib/ice/src/stun/transaction.js.map +1 -1
  35. package/lib/ice/src/turn/frame.d.ts +1 -0
  36. package/lib/ice/src/turn/frame.js +18 -0
  37. package/lib/ice/src/turn/frame.js.map +1 -0
  38. package/lib/ice/src/turn/protocol.d.ts +9 -7
  39. package/lib/ice/src/turn/protocol.js +32 -44
  40. package/lib/ice/src/turn/protocol.js.map +1 -1
  41. package/lib/ice/src/types/model.d.ts +1 -1
  42. package/lib/ice/src/types/model.js.map +1 -1
  43. package/lib/{ice → ice-server}/src/stun/attributes.d.ts +12 -5
  44. package/lib/{ice → ice-server}/src/stun/attributes.js +60 -19
  45. package/lib/ice-server/src/stun/attributes.js.map +1 -0
  46. package/lib/ice-server/src/stun/const.d.ts +28 -0
  47. package/lib/ice-server/src/stun/const.js +88 -0
  48. package/lib/ice-server/src/stun/const.js.map +1 -0
  49. package/lib/ice-server/src/stun/message.d.ts +37 -0
  50. package/lib/ice-server/src/stun/message.js +190 -0
  51. package/lib/ice-server/src/stun/message.js.map +1 -0
  52. package/lib/ice-server/src/turn/auth.d.ts +1 -0
  53. package/lib/ice-server/src/turn/auth.js +10 -0
  54. package/lib/ice-server/src/turn/auth.js.map +1 -0
  55. package/lib/ice-server/src/turn/frame.d.ts +13 -0
  56. package/lib/ice-server/src/turn/frame.js +69 -0
  57. package/lib/ice-server/src/turn/frame.js.map +1 -0
  58. package/lib/index.mjs +2688 -855
  59. package/lib/nonstandard/index.mjs +1753 -403
  60. package/lib/rtp/src/extra/container/mp4/container.d.ts +9 -6
  61. package/lib/rtp/src/extra/container/mp4/container.js +258 -173
  62. package/lib/rtp/src/extra/container/mp4/container.js.map +1 -1
  63. package/lib/rtp/src/extra/container/mp4/h264.d.ts +1 -0
  64. package/lib/rtp/src/extra/container/mp4/h264.js +13 -0
  65. package/lib/rtp/src/extra/container/mp4/h264.js.map +1 -1
  66. package/lib/rtp/src/extra/processor/mp4.d.ts +11 -7
  67. package/lib/rtp/src/extra/processor/mp4.js +115 -60
  68. package/lib/rtp/src/extra/processor/mp4.js.map +1 -1
  69. package/lib/rtp/src/extra/processor/mp4Callback.d.ts +2 -3
  70. package/lib/rtp/src/extra/processor/mp4Callback.js +5 -3
  71. package/lib/rtp/src/extra/processor/mp4Callback.js.map +1 -1
  72. package/lib/webrtc/src/dataChannel.d.ts +3 -2
  73. package/lib/webrtc/src/dataChannel.js +9 -2
  74. package/lib/webrtc/src/dataChannel.js.map +1 -1
  75. package/lib/webrtc/src/errors.d.ts +3 -0
  76. package/lib/webrtc/src/errors.js +11 -0
  77. package/lib/webrtc/src/errors.js.map +1 -0
  78. package/lib/webrtc/src/helper.d.ts +5 -1
  79. package/lib/webrtc/src/helper.js +33 -1
  80. package/lib/webrtc/src/helper.js.map +1 -1
  81. package/lib/webrtc/src/media/receiver/statistics.d.ts +4 -1
  82. package/lib/webrtc/src/media/receiver/statistics.js +22 -0
  83. package/lib/webrtc/src/media/receiver/statistics.js.map +1 -1
  84. package/lib/webrtc/src/media/rtpReceiver.d.ts +15 -2
  85. package/lib/webrtc/src/media/rtpReceiver.js +135 -20
  86. package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
  87. package/lib/webrtc/src/media/rtpSender.d.ts +32 -7
  88. package/lib/webrtc/src/media/rtpSender.js +177 -28
  89. package/lib/webrtc/src/media/rtpSender.js.map +1 -1
  90. package/lib/webrtc/src/media/rtpTransceiver.d.ts +13 -4
  91. package/lib/webrtc/src/media/rtpTransceiver.js +26 -5
  92. package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
  93. package/lib/webrtc/src/media/stats.d.ts +15 -1
  94. package/lib/webrtc/src/media/stats.js +55 -1
  95. package/lib/webrtc/src/media/stats.js.map +1 -1
  96. package/lib/webrtc/src/media/track.d.ts +2 -1
  97. package/lib/webrtc/src/media/track.js +7 -1
  98. package/lib/webrtc/src/media/track.js.map +1 -1
  99. package/lib/webrtc/src/nonstandard/dummyMedia.d.ts +19 -0
  100. package/lib/webrtc/src/nonstandard/dummyMedia.js +157 -0
  101. package/lib/webrtc/src/nonstandard/dummyMedia.js.map +1 -0
  102. package/lib/webrtc/src/nonstandard/navigator.d.ts +18 -8
  103. package/lib/webrtc/src/nonstandard/navigator.js +96 -32
  104. package/lib/webrtc/src/nonstandard/navigator.js.map +1 -1
  105. package/lib/webrtc/src/nonstandard/userMedia/packetizer.d.ts +16 -0
  106. package/lib/webrtc/src/nonstandard/userMedia/packetizer.js +360 -0
  107. package/lib/webrtc/src/nonstandard/userMedia/packetizer.js.map +1 -0
  108. package/lib/webrtc/src/nonstandard/userMedia.d.ts +71 -31
  109. package/lib/webrtc/src/nonstandard/userMedia.js +454 -108
  110. package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -1
  111. package/lib/webrtc/src/peerConnection.d.ts +183 -50
  112. package/lib/webrtc/src/peerConnection.js +458 -109
  113. package/lib/webrtc/src/peerConnection.js.map +1 -1
  114. package/lib/webrtc/src/sctpManager.d.ts +1 -1
  115. package/lib/webrtc/src/sctpManager.js +27 -7
  116. package/lib/webrtc/src/sctpManager.js.map +1 -1
  117. package/lib/webrtc/src/sdp.d.ts +10 -7
  118. package/lib/webrtc/src/sdp.js +39 -9
  119. package/lib/webrtc/src/sdp.js.map +1 -1
  120. package/lib/webrtc/src/sdpManager.d.ts +4 -3
  121. package/lib/webrtc/src/sdpManager.js +50 -27
  122. package/lib/webrtc/src/sdpManager.js.map +1 -1
  123. package/lib/webrtc/src/secureTransportManager.d.ts +13 -4
  124. package/lib/webrtc/src/secureTransportManager.js +100 -22
  125. package/lib/webrtc/src/secureTransportManager.js.map +1 -1
  126. package/lib/webrtc/src/transceiverManager.d.ts +5 -4
  127. package/lib/webrtc/src/transceiverManager.js +61 -62
  128. package/lib/webrtc/src/transceiverManager.js.map +1 -1
  129. package/lib/webrtc/src/transport/dtls.d.ts +15 -4
  130. package/lib/webrtc/src/transport/dtls.js +91 -23
  131. package/lib/webrtc/src/transport/dtls.js.map +1 -1
  132. package/lib/webrtc/src/transport/ice.d.ts +21 -3
  133. package/lib/webrtc/src/transport/ice.js +159 -30
  134. package/lib/webrtc/src/transport/ice.js.map +1 -1
  135. package/lib/webrtc/src/transport/sctp.d.ts +1 -0
  136. package/lib/webrtc/src/transport/sctp.js +9 -6
  137. package/lib/webrtc/src/transport/sctp.js.map +1 -1
  138. package/lib/webrtc/src/utils.d.ts +12 -4
  139. package/lib/webrtc/src/utils.js +118 -16
  140. package/lib/webrtc/src/utils.js.map +1 -1
  141. package/package.json +7 -4
  142. package/lib/ice/src/stun/attributes.js.map +0 -1
  143. package/lib/rtp/src/extra/container/mp4/mp4box.d.ts +0 -5
  144. package/lib/rtp/src/extra/container/mp4/mp4box.js +0 -32
  145. package/lib/rtp/src/extra/container/mp4/mp4box.js.map +0 -1
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.defaultPeerConfig = exports.findCodecByMimeType = exports.RTCPeerConnection = void 0;
3
+ exports.RTCTrackEvent = exports.defaultPeerConfig = exports.findCodecByMimeType = exports.RTCPeerConnection = void 0;
4
4
  const crypto_1 = require("crypto");
5
+ const errors_1 = require("./errors");
5
6
  const helper_1 = require("./helper");
6
7
  const common_1 = require("./imports/common");
7
8
  const media_1 = require("./media");
@@ -13,9 +14,92 @@ const secureTransportManager_1 = require("./secureTransportManager");
13
14
  const sctp_1 = require("./transport/sctp");
14
15
  const utils_1 = require("./utils");
15
16
  const log = (0, common_1.debug)("werift:packages/webrtc/src/peerConnection.ts");
17
+ /**
18
+ * W3C compatibility notes kept near the public RTCPeerConnection surface so the
19
+ * reviewable diff does not depend on external PR text.
20
+ *
21
+ * - `current/pending*Description`, `canTrickleIceCandidates`, `sctp`,
22
+ * `addIceCandidate(null)`, and `RTCConfiguration` round-trip behavior are
23
+ * implemented here and covered by `tests/wpt/peerConnectionApiCompatibility.test.ts`.
24
+ * - `addIceCandidate()` also validates `sdpMid` / `sdpMLineIndex` /
25
+ * `usernameFragment` against the applied remote description and appends
26
+ * candidates or end-of-candidates markers to the corresponding m-section.
27
+ * The public API keeps werift's historical pre-SRD buffering behavior, while
28
+ * the WPT runner wraps the class to exercise strict spec rejection.
29
+ * - `bundlePolicy: "balanced"` is accepted for input compatibility but is
30
+ * normalized to werift's `"max-compat"` behavior, so `getConfiguration()`
31
+ * returns the normalized value.
32
+ * - `setLocalDescription()` keeps the historical `SessionDescription` return
33
+ * value for non-rollback calls, while `{ type: "rollback" }` resolves `void`
34
+ * to match the actual behavior without pretending to return a description.
35
+ * - API reference markdown is regenerated with `cd packages/webrtc && npm run doc`.
36
+ * The generated output lives under `packages/webrtc/doc/`; compatibility
37
+ * notes remain here and in the package README so review context is visible
38
+ * even when generated docs are not committed in the same change.
39
+ */
16
40
  class RTCPeerConnection extends helper_1.EventTarget {
41
+ get ondatachannel() {
42
+ return this.eventHandlers.ondatachannel ?? null;
43
+ }
44
+ set ondatachannel(value) {
45
+ this.eventHandlers.ondatachannel = value ?? undefined;
46
+ }
47
+ get onicecandidate() {
48
+ return this.eventHandlers.onicecandidate ?? null;
49
+ }
50
+ set onicecandidate(value) {
51
+ this.eventHandlers.onicecandidate = value ?? undefined;
52
+ }
53
+ get onicecandidateerror() {
54
+ return this.eventHandlers.onicecandidateerror ?? null;
55
+ }
56
+ set onicecandidateerror(value) {
57
+ this.eventHandlers.onicecandidateerror = value ?? undefined;
58
+ }
59
+ get onicegatheringstatechange() {
60
+ return this.eventHandlers.onicegatheringstatechange ?? null;
61
+ }
62
+ set onicegatheringstatechange(value) {
63
+ this.eventHandlers.onicegatheringstatechange = value ?? undefined;
64
+ }
65
+ get onnegotiationneeded() {
66
+ return this.eventHandlers.onnegotiationneeded ?? null;
67
+ }
68
+ set onnegotiationneeded(value) {
69
+ this.eventHandlers.onnegotiationneeded = value ?? undefined;
70
+ }
71
+ get onsignalingstatechange() {
72
+ return this.eventHandlers.onsignalingstatechange ?? null;
73
+ }
74
+ set onsignalingstatechange(value) {
75
+ this.eventHandlers.onsignalingstatechange = value ?? undefined;
76
+ }
77
+ get ontrack() {
78
+ return this.eventHandlers.ontrack ?? null;
79
+ }
80
+ set ontrack(value) {
81
+ this.eventHandlers.ontrack = value ?? undefined;
82
+ }
83
+ get onconnectionstatechange() {
84
+ return this.eventHandlers.onconnectionstatechange ?? null;
85
+ }
86
+ set onconnectionstatechange(value) {
87
+ this.eventHandlers.onconnectionstatechange = value ?? undefined;
88
+ }
89
+ get oniceconnectionstatechange() {
90
+ return this.eventHandlers.oniceconnectionstatechange ?? null;
91
+ }
92
+ set oniceconnectionstatechange(value) {
93
+ this.eventHandlers.oniceconnectionstatechange = value ?? undefined;
94
+ }
17
95
  constructor(config = {}) {
18
96
  super();
97
+ Object.defineProperty(this, "id", {
98
+ enumerable: true,
99
+ configurable: true,
100
+ writable: true,
101
+ value: (0, crypto_1.randomUUID)().toString()
102
+ });
19
103
  Object.defineProperty(this, "cname", {
20
104
  enumerable: true,
21
105
  configurable: true,
@@ -88,11 +172,23 @@ class RTCPeerConnection extends helper_1.EventTarget {
88
172
  writable: true,
89
173
  value: false
90
174
  });
91
- Object.defineProperty(this, "remoteBundleNegotiated", {
175
+ Object.defineProperty(this, "lastCreatedAnswer", {
92
176
  enumerable: true,
93
177
  configurable: true,
94
178
  writable: true,
95
- value: false
179
+ value: void 0
180
+ });
181
+ Object.defineProperty(this, "lastCreatedOffer", {
182
+ enumerable: true,
183
+ configurable: true,
184
+ writable: true,
185
+ value: void 0
186
+ });
187
+ Object.defineProperty(this, "pendingRemoteCandidates", {
188
+ enumerable: true,
189
+ configurable: true,
190
+ writable: true,
191
+ value: []
96
192
  });
97
193
  Object.defineProperty(this, "iceGatheringStateChange", {
98
194
  enumerable: true,
@@ -154,65 +250,18 @@ class RTCPeerConnection extends helper_1.EventTarget {
154
250
  writable: true,
155
251
  value: new common_1.Event()
156
252
  });
157
- Object.defineProperty(this, "ondatachannel", {
253
+ Object.defineProperty(this, "eventHandlers", {
158
254
  enumerable: true,
159
255
  configurable: true,
160
256
  writable: true,
161
- value: void 0
162
- });
163
- Object.defineProperty(this, "onicecandidate", {
164
- enumerable: true,
165
- configurable: true,
166
- writable: true,
167
- value: void 0
168
- });
169
- Object.defineProperty(this, "onicecandidateerror", {
170
- enumerable: true,
171
- configurable: true,
172
- writable: true,
173
- value: void 0
174
- });
175
- Object.defineProperty(this, "onicegatheringstatechange", {
176
- enumerable: true,
177
- configurable: true,
178
- writable: true,
179
- value: void 0
180
- });
181
- Object.defineProperty(this, "onnegotiationneeded", {
182
- enumerable: true,
183
- configurable: true,
184
- writable: true,
185
- value: void 0
186
- });
187
- Object.defineProperty(this, "onsignalingstatechange", {
188
- enumerable: true,
189
- configurable: true,
190
- writable: true,
191
- value: void 0
192
- });
193
- Object.defineProperty(this, "ontrack", {
194
- enumerable: true,
195
- configurable: true,
196
- writable: true,
197
- value: void 0
198
- });
199
- Object.defineProperty(this, "onconnectionstatechange", {
200
- enumerable: true,
201
- configurable: true,
202
- writable: true,
203
- value: void 0
204
- });
205
- Object.defineProperty(this, "oniceconnectionstatechange", {
206
- enumerable: true,
207
- configurable: true,
208
- writable: true,
209
- value: void 0
257
+ value: {}
210
258
  });
211
259
  Object.defineProperty(this, "needNegotiation", {
212
260
  enumerable: true,
213
261
  configurable: true,
214
262
  writable: true,
215
263
  value: async () => {
264
+ this.invalidateLastCreatedDescriptions();
216
265
  this.shouldNegotiationneeded = true;
217
266
  if (this.negotiationneeded || this.signalingState !== "stable") {
218
267
  return;
@@ -221,8 +270,10 @@ class RTCPeerConnection extends helper_1.EventTarget {
221
270
  setImmediate(() => {
222
271
  this.negotiationneeded = true;
223
272
  this.onNegotiationneeded.execute();
224
- if (this.onnegotiationneeded)
225
- this.onnegotiationneeded({});
273
+ if (this.onnegotiationneeded) {
274
+ this.onnegotiationneeded(new globalThis.Event("negotiationneeded"));
275
+ }
276
+ this.emit("negotiationneeded");
226
277
  });
227
278
  }
228
279
  });
@@ -234,13 +285,13 @@ class RTCPeerConnection extends helper_1.EventTarget {
234
285
  this.transceiverManager = new media_1.TransceiverManager(this.cname, this.config, this.router);
235
286
  this.transceiverManager.onTransceiverAdded.pipe(this.onTransceiverAdded);
236
287
  this.transceiverManager.onRemoteTransceiverAdded.pipe(this.onRemoteTransceiverAdded);
237
- this.transceiverManager.onTrack.subscribe(({ track, stream, transceiver }) => {
238
- const event = {
288
+ this.transceiverManager.onTrack.subscribe(({ track, streams, transceiver }) => {
289
+ const event = new RTCTrackEvent({
239
290
  track,
240
- streams: [stream],
291
+ streams,
241
292
  transceiver,
242
293
  receiver: transceiver.receiver,
243
- };
294
+ });
244
295
  this.onTrack.execute(track);
245
296
  this.emit("track", event);
246
297
  if (this.ontrack) {
@@ -251,7 +302,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
251
302
  this.sctpManager = new sctpManager_1.SctpTransportManager();
252
303
  this.sctpManager.onDataChannel.subscribe((channel) => {
253
304
  this.onDataChannel.execute(channel);
254
- const event = { channel };
305
+ const event = { type: "datachannel", channel };
255
306
  this.ondatachannel?.(event);
256
307
  this.emit("datachannel", event);
257
308
  });
@@ -260,12 +311,18 @@ class RTCPeerConnection extends helper_1.EventTarget {
260
311
  sctpManager: this.sctpManager,
261
312
  transceiverManager: this.transceiverManager,
262
313
  });
263
- this.secureManager.iceGatheringStateChange.pipe(this.iceGatheringStateChange);
314
+ this.secureManager.iceGatheringStateChange.subscribe((state) => {
315
+ this.iceGatheringStateChange.execute(state);
316
+ this.onicegatheringstatechange?.(new globalThis.Event("icegatheringstatechange"));
317
+ this.emit("icegatheringstatechange");
318
+ });
264
319
  this.secureManager.iceConnectionStateChange.subscribe((state) => {
265
320
  if (state === "closed") {
266
321
  this.close();
267
322
  }
268
323
  this.iceConnectionStateChange.execute(state);
324
+ this.oniceconnectionstatechange?.();
325
+ this.emit("iceconnectionstatechange");
269
326
  });
270
327
  this.secureManager.connectionStateChange.subscribe((state) => {
271
328
  this.connectionStateChange.execute(state);
@@ -275,8 +332,12 @@ class RTCPeerConnection extends helper_1.EventTarget {
275
332
  this.secureManager.onIceCandidate.subscribe((candidate) => {
276
333
  const iceCandidate = candidate ? candidate.toJSON() : undefined;
277
334
  this.onIceCandidate.execute(iceCandidate);
278
- this.onicecandidate?.({ candidate: iceCandidate });
279
- this.emit("icecandidate", { candidate: iceCandidate });
335
+ const event = {
336
+ type: "icecandidate",
337
+ candidate: iceCandidate,
338
+ };
339
+ this.onicecandidate?.(event);
340
+ this.emit("icecandidate", event);
280
341
  });
281
342
  }
282
343
  get connectionState() {
@@ -297,6 +358,9 @@ class RTCPeerConnection extends helper_1.EventTarget {
297
358
  get sctpTransport() {
298
359
  return this.sctpManager.sctpTransport;
299
360
  }
361
+ get sctp() {
362
+ return this.sctpTransport ?? null;
363
+ }
300
364
  get sctpRemotePort() {
301
365
  return this.sctpManager.sctpRemotePort;
302
366
  }
@@ -310,10 +374,35 @@ class RTCPeerConnection extends helper_1.EventTarget {
310
374
  return this.iceTransports[0].connection.generation;
311
375
  }
312
376
  get localDescription() {
313
- return this.sdpManager.localDescription;
377
+ return this.sdpManager.localDescription ?? null;
378
+ }
379
+ get currentLocalDescription() {
380
+ return this.sdpManager.currentLocalDescription?.toJSON() ?? null;
381
+ }
382
+ get pendingLocalDescription() {
383
+ return this.sdpManager.pendingLocalDescription?.toJSON() ?? null;
314
384
  }
315
385
  get remoteDescription() {
316
- return this.sdpManager.remoteDescription;
386
+ return this.sdpManager.remoteDescription ?? null;
387
+ }
388
+ get currentRemoteDescription() {
389
+ return this.sdpManager.currentRemoteDescription?.toJSON() ?? null;
390
+ }
391
+ get pendingRemoteDescription() {
392
+ return this.sdpManager.pendingRemoteDescription?.toJSON() ?? null;
393
+ }
394
+ get canTrickleIceCandidates() {
395
+ const remoteDescription = this.sdpManager._remoteDescription;
396
+ if (!remoteDescription) {
397
+ return null;
398
+ }
399
+ const iceOptions = [
400
+ remoteDescription.iceOptions,
401
+ ...remoteDescription.media.map((media) => media.iceOptions),
402
+ ]
403
+ .filter((value) => !!value)
404
+ .join(" ");
405
+ return iceOptions.split(/\s+/).includes("trickle");
317
406
  }
318
407
  get remoteIsBundled() {
319
408
  return this.sdpManager.remoteIsBundled;
@@ -336,7 +425,42 @@ class RTCPeerConnection extends helper_1.EventTarget {
336
425
  return this.transceiverManager.getReceivers();
337
426
  }
338
427
  setConfiguration(config) {
339
- (0, utils_1.deepMerge)(this.config, config);
428
+ const normalizedConfig = normalizePeerConfiguration(config);
429
+ const isReconfiguration = !!this.sdpManager;
430
+ if (normalizedConfig.rtcpMuxPolicy &&
431
+ normalizedConfig.rtcpMuxPolicy !== "require") {
432
+ throw new Error("rtcpMuxPolicy must be require");
433
+ }
434
+ if (normalizedConfig.iceCandidatePoolSize !== undefined &&
435
+ (!Number.isInteger(normalizedConfig.iceCandidatePoolSize) ||
436
+ normalizedConfig.iceCandidatePoolSize < 0)) {
437
+ throw new Error("iceCandidatePoolSize must be a non-negative integer");
438
+ }
439
+ if (isReconfiguration &&
440
+ normalizedConfig.bundlePolicy !== undefined &&
441
+ normalizedConfig.bundlePolicy !== this.config.bundlePolicy) {
442
+ throw new Error("bundlePolicy cannot be changed");
443
+ }
444
+ if (isReconfiguration &&
445
+ normalizedConfig.rtcpMuxPolicy !== undefined &&
446
+ normalizedConfig.rtcpMuxPolicy !== this.config.rtcpMuxPolicy) {
447
+ throw new Error("rtcpMuxPolicy cannot be changed");
448
+ }
449
+ if (isReconfiguration &&
450
+ normalizedConfig.certificates !== undefined &&
451
+ !hasSameCertificates(normalizedConfig.certificates, this.config.certificates)) {
452
+ throw new Error("certificates cannot be changed");
453
+ }
454
+ if (isReconfiguration &&
455
+ normalizedConfig.iceCandidatePoolSize !== undefined &&
456
+ this.localDescription &&
457
+ normalizedConfig.iceCandidatePoolSize !== this.config.iceCandidatePoolSize) {
458
+ throw new Error("iceCandidatePoolSize cannot be changed after setLocalDescription");
459
+ }
460
+ if ((normalizedConfig.iceCandidatePoolSize ?? 0) > 0) {
461
+ throw new Error("iceCandidatePoolSize > 0 is not supported");
462
+ }
463
+ (0, utils_1.deepMerge)(this.config, normalizedConfig);
340
464
  if (this.config.icePortRange) {
341
465
  const [min, max] = this.config.icePortRange;
342
466
  if (min === max)
@@ -385,7 +509,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
385
509
  });
386
510
  }
387
511
  getConfiguration() {
388
- return this.config;
512
+ return clonePeerConfiguration(this.config);
389
513
  }
390
514
  async createOffer({ iceRestart } = {}) {
391
515
  if (iceRestart || this.needRestart) {
@@ -403,7 +527,9 @@ class RTCPeerConnection extends helper_1.EventTarget {
403
527
  }
404
528
  }
405
529
  const description = this.sdpManager.buildOfferSdp(this.transceiverManager.getTransceivers(), this.sctpTransport);
406
- return description.toJSON();
530
+ const createdOffer = description.toJSON();
531
+ this.lastCreatedOffer = createdOffer;
532
+ return createdOffer;
407
533
  }
408
534
  createSctpTransport() {
409
535
  const sctp = this.sctpManager.createSctpTransport(this.config.maxMessageSize);
@@ -425,19 +551,29 @@ class RTCPeerConnection extends helper_1.EventTarget {
425
551
  }
426
552
  removeTrack(sender) {
427
553
  if (this.isClosed) {
428
- throw new Error("peer closed");
554
+ throw (0, errors_1.createWebRtcDomException)("InvalidStateError", "peer closed");
429
555
  }
430
556
  this.transceiverManager.removeTrack(sender);
431
557
  this.needNegotiation();
432
558
  }
559
+ invalidateLastCreatedDescriptions() {
560
+ this.lastCreatedAnswer = undefined;
561
+ this.lastCreatedOffer = undefined;
562
+ }
563
+ async waitForPendingDescriptionTask() {
564
+ this.assertNotClosed();
565
+ await Promise.resolve();
566
+ if (this.isClosed) {
567
+ await new Promise(() => undefined);
568
+ }
569
+ }
433
570
  findOrCreateTransport() {
434
571
  const existingDtlsTransport = this.dtlsTransports.find((transport) => transport.state !== "closed");
435
572
  const existing = existingDtlsTransport?.iceTransport;
436
573
  // Gather ICE candidates for only one track. If the remote endpoint is not bundle-aware, negotiate only one media track.
437
574
  // https://w3c.github.io/webrtc-pc/#rtcbundlepolicy-enum
438
575
  if (this.sdpManager.bundlePolicy === "max-bundle" ||
439
- (this.sdpManager.bundlePolicy !== "disable" &&
440
- (this.remoteIsBundled || this.remoteBundleNegotiated))) {
576
+ (this.sdpManager.bundlePolicy !== "disable" && this.remoteIsBundled)) {
441
577
  if (existingDtlsTransport) {
442
578
  return existingDtlsTransport;
443
579
  }
@@ -493,17 +629,48 @@ class RTCPeerConnection extends helper_1.EventTarget {
493
629
  "have-local-offer",
494
630
  "have-remote-pranswer",
495
631
  ];
496
- sessionDescription =
497
- sessionDescription ??
498
- (implicitOfferState.includes(this.signalingState)
499
- ? await this.createOffer()
500
- : await this.createAnswer());
632
+ await this.waitForPendingDescriptionTask();
633
+ if (sessionDescription?.type === "rollback") {
634
+ this.sdpManager.rollbackLocalDescription(this.signalingState);
635
+ this.setSignalingState("stable");
636
+ if (this.shouldNegotiationneeded) {
637
+ this.needNegotiation();
638
+ }
639
+ this.invalidateLastCreatedDescriptions();
640
+ return;
641
+ }
642
+ const needsGeneratedDescription = !sessionDescription?.type ||
643
+ !sessionDescription.sdp ||
644
+ sessionDescription.sdp.length === 0;
645
+ const generatedDescription = needsGeneratedDescription
646
+ ? sessionDescription?.type === "offer"
647
+ ? (this.lastCreatedOffer ?? (await this.createOffer()))
648
+ : sessionDescription?.type === "answer" ||
649
+ sessionDescription?.type === "pranswer"
650
+ ? (this.lastCreatedAnswer ?? (await this.createAnswer()))
651
+ : implicitOfferState.includes(this.signalingState)
652
+ ? (this.lastCreatedOffer ?? (await this.createOffer()))
653
+ : (this.lastCreatedAnswer ?? (await this.createAnswer()))
654
+ : undefined;
655
+ sessionDescription = {
656
+ type: sessionDescription?.type ?? generatedDescription.type,
657
+ sdp: sessionDescription?.sdp && sessionDescription.sdp.length > 0
658
+ ? sessionDescription.sdp
659
+ : generatedDescription.sdp,
660
+ };
661
+ if (sessionDescription.type === "offer" &&
662
+ this.lastCreatedOffer &&
663
+ sessionDescription.sdp !== this.lastCreatedOffer.sdp) {
664
+ throw (0, errors_1.createWebRtcDomException)("InvalidModificationError", "setLocalDescription must use the latest created offer");
665
+ }
501
666
  // # parse and validate description
667
+ const descriptionType = sessionDescription.type;
668
+ const descriptionSdp = sessionDescription.sdp;
502
669
  const description = this.sdpManager.parseSdp({
503
- sdp: sessionDescription.sdp,
670
+ sdp: descriptionSdp,
504
671
  isLocal: true,
505
672
  signalingState: this.signalingState,
506
- type: sessionDescription.type,
673
+ type: descriptionType,
507
674
  });
508
675
  // # update signaling state
509
676
  if (description.type === "offer") {
@@ -512,6 +679,9 @@ class RTCPeerConnection extends helper_1.EventTarget {
512
679
  else if (description.type === "answer") {
513
680
  this.setSignalingState("stable");
514
681
  }
682
+ else if (description.type === "pranswer") {
683
+ this.setSignalingState("have-local-pranswer");
684
+ }
515
685
  // # assign MID
516
686
  for (const [i, media] of (0, helper_1.enumerate)(description.media)) {
517
687
  const mid = media.rtp.muxId;
@@ -530,7 +700,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
530
700
  const role = description.media.find((media) => media.dtlsParams)?.dtlsParams
531
701
  ?.role;
532
702
  this.secureManager.setLocalRole({
533
- type: description.type,
703
+ type: description.type === "offer" ? "offer" : "answer",
534
704
  role,
535
705
  });
536
706
  // # configure direction
@@ -556,14 +726,56 @@ class RTCPeerConnection extends helper_1.EventTarget {
556
726
  if (this.shouldNegotiationneeded) {
557
727
  this.needNegotiation();
558
728
  }
729
+ this.invalidateLastCreatedDescriptions();
559
730
  return description;
560
731
  }
561
732
  async gatherCandidates() {
562
733
  await this.secureManager.gatherCandidates(!!this.sdpManager.remoteIsBundled);
563
734
  }
564
- async addIceCandidate(candidateMessage) {
565
- const sdp = this.sdpManager.buildOfferSdp(this.transceiverManager.getTransceivers(), this.sctpTransport);
566
- await this.secureManager.addIceCandidate(sdp, candidateMessage);
735
+ async addIceCandidate(candidateMessage = {}) {
736
+ if (this.isClosed) {
737
+ throw (0, errors_1.createWebRtcDomException)("InvalidStateError", "is closed");
738
+ }
739
+ if (!this.remoteDescription || !this.sdpManager._remoteDescription) {
740
+ this.pendingRemoteCandidates.push(candidateMessage);
741
+ return;
742
+ }
743
+ await this.applyRemoteIceCandidate(candidateMessage);
744
+ }
745
+ async applyRemoteIceCandidate(candidateMessage) {
746
+ const sdp = this.sdpManager._remoteDescription;
747
+ if (!sdp) {
748
+ return;
749
+ }
750
+ const appliedCandidate = await this.secureManager.addIceCandidate(sdp, candidateMessage);
751
+ const remoteDescription = this.sdpManager._remoteDescription;
752
+ if (!remoteDescription || !appliedCandidate) {
753
+ return;
754
+ }
755
+ if (appliedCandidate.kind === "end-of-candidates") {
756
+ for (const mediaIndex of appliedCandidate.mediaIndices) {
757
+ const media = remoteDescription.media[mediaIndex];
758
+ if (media) {
759
+ media.iceCandidatesComplete = true;
760
+ }
761
+ }
762
+ return;
763
+ }
764
+ for (const mediaIndex of appliedCandidate.mediaIndices) {
765
+ const media = remoteDescription.media[mediaIndex];
766
+ if (!media) {
767
+ continue;
768
+ }
769
+ media.iceCandidates.push(appliedCandidate.candidate);
770
+ }
771
+ }
772
+ async flushPendingRemoteCandidates() {
773
+ while (this.pendingRemoteCandidates.length > 0 &&
774
+ this.remoteDescription &&
775
+ this.sdpManager._remoteDescription) {
776
+ const candidate = this.pendingRemoteCandidates.shift();
777
+ await this.applyRemoteIceCandidate(candidate ?? null);
778
+ }
567
779
  }
568
780
  async connect() {
569
781
  log("start connect");
@@ -608,15 +820,29 @@ class RTCPeerConnection extends helper_1.EventTarget {
608
820
  if (sessionDescription instanceof sdp_1.SessionDescription) {
609
821
  sessionDescription = sessionDescription.toSdp();
610
822
  }
823
+ await this.waitForPendingDescriptionTask();
824
+ const needsImplicitLocalRollback = sessionDescription.type === "offer" &&
825
+ ["have-local-offer", "have-local-pranswer"].includes(this.signalingState);
826
+ if (needsImplicitLocalRollback) {
827
+ this.sdpManager.rollbackLocalDescription(this.signalingState);
828
+ this.shouldNegotiationneeded = true;
829
+ this.setSignalingState("stable");
830
+ await Promise.resolve();
831
+ }
611
832
  // # parse and validate description
612
833
  const remoteSdp = this.sdpManager.setRemoteDescription(sessionDescription, this.signalingState);
613
- if (remoteSdp.group.some((group) => group.semantic === "BUNDLE" && group.items.length > 0)) {
614
- this.remoteBundleNegotiated = true;
834
+ if (!remoteSdp) {
835
+ this.setSignalingState("stable");
836
+ if (this.shouldNegotiationneeded) {
837
+ this.needNegotiation();
838
+ }
839
+ this.invalidateLastCreatedDescriptions();
840
+ return;
615
841
  }
616
842
  let bundleTransport;
617
843
  // # apply description
618
844
  const matchTransceiverWithMedia = (transceiver, media) => transceiver.kind === media.kind &&
619
- [undefined, media.rtp.muxId].includes(transceiver.mid);
845
+ [null, media.rtp.muxId].includes(transceiver.mid);
620
846
  let transports = remoteSdp.media.map((remoteMedia, i) => {
621
847
  let dtlsTransport;
622
848
  if (["audio", "video"].includes(remoteMedia.kind)) {
@@ -628,7 +854,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
628
854
  transceiver = this.addTransceiver(remoteMedia.kind, {
629
855
  direction: "recvonly",
630
856
  });
631
- transceiver.mid = remoteMedia.rtp.muxId;
857
+ transceiver.mid = remoteMedia.rtp.muxId ?? null;
632
858
  this.onRemoteTransceiverAdded.execute(transceiver);
633
859
  }
634
860
  else {
@@ -677,7 +903,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
677
903
  iceTransport.setRemoteParams(remoteMedia.iceParams, renomination);
678
904
  // One agent full, one lite: The full agent MUST take the controlling role, and the lite agent MUST take the controlled role
679
905
  // RFC 8445 S6.1.1
680
- if (remoteMedia.iceParams?.iceLite) {
906
+ if (remoteMedia.iceParams.iceLite && !iceTransport.connection.iceLite) {
681
907
  iceTransport.connection.iceControlling = true;
682
908
  }
683
909
  }
@@ -716,6 +942,10 @@ class RTCPeerConnection extends helper_1.EventTarget {
716
942
  else if (remoteSdp.type === "answer") {
717
943
  this.setSignalingState("stable");
718
944
  }
945
+ else if (remoteSdp.type === "pranswer") {
946
+ this.setSignalingState("have-remote-pranswer");
947
+ }
948
+ await this.flushPendingRemoteCandidates();
719
949
  // connect transports
720
950
  if (remoteSdp.type === "answer") {
721
951
  log("caller start connect");
@@ -728,6 +958,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
728
958
  if (this.shouldNegotiationneeded) {
729
959
  this.needNegotiation();
730
960
  }
961
+ this.invalidateLastCreatedDescriptions();
731
962
  }
732
963
  addTransceiver(trackOrKind, options = {}) {
733
964
  const dtlsTransport = this.findOrCreateTransport();
@@ -737,13 +968,11 @@ class RTCPeerConnection extends helper_1.EventTarget {
737
968
  return transceiver;
738
969
  }
739
970
  // todo fix
740
- addTrack(track,
741
- /**todo impl */
742
- ms) {
971
+ addTrack(track, ...streams) {
743
972
  if (this.isClosed) {
744
- throw new Error("is closed");
973
+ throw (0, errors_1.createWebRtcDomException)("InvalidStateError", "is closed");
745
974
  }
746
- const transceiver = this.transceiverManager.addTrack(track, ms);
975
+ const transceiver = this.transceiverManager.addTrack(track, streams);
747
976
  if (!transceiver.dtlsTransport) {
748
977
  const dtlsTransport = this.findOrCreateTransport();
749
978
  transceiver.setDtlsTransport(dtlsTransport);
@@ -759,54 +988,61 @@ class RTCPeerConnection extends helper_1.EventTarget {
759
988
  sctpTransport: this.sctpTransport,
760
989
  signalingState: this.signalingState,
761
990
  });
762
- return description.toJSON();
991
+ const createdAnswer = description.toJSON();
992
+ this.lastCreatedAnswer = createdAnswer;
993
+ return createdAnswer;
763
994
  }
764
995
  assertNotClosed() {
765
996
  if (this.isClosed) {
766
- throw new Error("RTCPeerConnection is closed");
997
+ throw (0, errors_1.createWebRtcDomException)("InvalidStateError", "RTCPeerConnection is closed");
767
998
  }
768
999
  }
769
1000
  setSignalingState(state) {
1001
+ if (this.signalingState === state) {
1002
+ return;
1003
+ }
770
1004
  log("signalingStateChange", state);
771
1005
  this.signalingState = state;
772
1006
  this.signalingStateChange.execute(state);
773
1007
  if (this.onsignalingstatechange) {
774
- this.onsignalingstatechange({});
1008
+ this.onsignalingstatechange(new globalThis.Event("signalingstatechange"));
775
1009
  }
1010
+ this.emit("signalingstatechange");
776
1011
  }
777
- createPeerConnectionStats() {
778
- const timestamp = (0, stats_1.getStatsTimestamp)();
1012
+ createPeerConnectionStats(timestamp) {
779
1013
  return {
780
1014
  type: "peer-connection",
781
- id: (0, stats_1.generateStatsId)("peer-connection"),
1015
+ id: (0, stats_1.generateStatsId)("peer-connection", this.id),
782
1016
  timestamp,
783
1017
  dataChannelsOpened: this.sctpManager.dataChannelsOpened,
784
1018
  dataChannelsClosed: this.sctpManager.dataChannelsClosed,
785
1019
  };
786
1020
  }
787
1021
  async getStats(selector) {
1022
+ const timestamp = (0, stats_1.getStatsTimestamp)();
788
1023
  const stats = [];
789
- // Peer connection stats - always included regardless of selector
790
- stats.push(this.createPeerConnectionStats());
791
- // Get stats from transceivers
792
- const transceiverStats = await this.transceiverManager.getStats(selector);
793
- stats.push(...transceiverStats);
794
- // Get transport stats - always included regardless of selector
795
- const transportStats = await this.secureManager.getStats();
1024
+ if (!selector) {
1025
+ stats.push(this.createPeerConnectionStats(timestamp));
1026
+ }
1027
+ stats.push(...this.transceiverManager.collectStats(timestamp));
1028
+ const transportStats = await this.secureManager.getStats(timestamp);
796
1029
  stats.push(...transportStats);
797
- // Get data channel stats - always included regardless of selector
798
- if (this.sctpTransport) {
799
- const dataChannelStats = await this.sctpManager.getStats();
1030
+ if (!selector && this.sctpTransport) {
1031
+ const dataChannelStats = await this.sctpManager.getStats(timestamp);
800
1032
  if (dataChannelStats) {
801
1033
  stats.push(...dataChannelStats);
802
1034
  }
803
1035
  }
804
- return new stats_1.RTCStatsReport(stats);
1036
+ if (!selector) {
1037
+ return (0, stats_1.buildStatsReport)(stats);
1038
+ }
1039
+ return (0, stats_1.buildStatsReport)(stats, this.transceiverManager.getStatsRootIds(selector));
805
1040
  }
806
1041
  async close() {
807
1042
  if (this.isClosed)
808
1043
  return;
809
1044
  this.isClosed = true;
1045
+ this.pendingRemoteCandidates.length = 0;
810
1046
  this.setSignalingState("closed");
811
1047
  this.transceiverManager.close();
812
1048
  await this.secureManager.close();
@@ -837,18 +1073,25 @@ function generateDefaultPeerConfig() {
837
1073
  video: [],
838
1074
  },
839
1075
  iceTransportPolicy: "all",
1076
+ iceLite: false,
840
1077
  iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
841
1078
  icePortRange: undefined,
842
1079
  iceInterfaceAddresses: undefined,
843
1080
  iceAdditionalHostAddresses: undefined,
844
1081
  iceUseIpv4: true,
845
1082
  iceUseIpv6: true,
1083
+ iceUseTcp: false,
1084
+ turnTransport: undefined,
1085
+ turnTlsOptions: undefined,
846
1086
  iceFilterStunResponse: undefined,
847
1087
  iceFilterCandidatePair: undefined,
848
1088
  icePasswordPrefix: undefined,
849
1089
  iceUseLinkLocalAddress: undefined,
850
1090
  dtls: {},
851
1091
  bundlePolicy: "max-compat",
1092
+ rtcpMuxPolicy: "require",
1093
+ iceCandidatePoolSize: 0,
1094
+ certificates: [],
852
1095
  debug: {},
853
1096
  midSuffix: false,
854
1097
  forceTurnTCP: false,
@@ -856,4 +1099,110 @@ function generateDefaultPeerConfig() {
856
1099
  };
857
1100
  }
858
1101
  exports.defaultPeerConfig = generateDefaultPeerConfig();
1102
+ function normalizePeerConfiguration(config) {
1103
+ const input = Object(config ?? {});
1104
+ const normalizedConfig = { ...input };
1105
+ if (input.bundlePolicy === "balanced") {
1106
+ normalizedConfig.bundlePolicy = "max-compat";
1107
+ }
1108
+ if ("certificates" in input) {
1109
+ if (input.certificates === undefined) {
1110
+ normalizedConfig.certificates = undefined;
1111
+ }
1112
+ else if (!Array.isArray(input.certificates) ||
1113
+ input.certificates.some((certificate) => certificate == null)) {
1114
+ throw (0, errors_1.createWebRtcTypeError)("certificates must be an array of RTCCertificate");
1115
+ }
1116
+ else {
1117
+ normalizedConfig.certificates = [...input.certificates];
1118
+ }
1119
+ }
1120
+ if ("iceCandidatePoolSize" in input) {
1121
+ normalizedConfig.iceCandidatePoolSize = coerceUnsignedShort(input.iceCandidatePoolSize, "iceCandidatePoolSize");
1122
+ }
1123
+ return normalizedConfig;
1124
+ }
1125
+ function coerceUnsignedShort(value, name) {
1126
+ const coerced = Number(value);
1127
+ if (!Number.isFinite(coerced) ||
1128
+ !Number.isInteger(coerced) ||
1129
+ coerced < 0 ||
1130
+ coerced > 65535) {
1131
+ throw (0, errors_1.createWebRtcTypeError)(`${name} must be an unsigned short`);
1132
+ }
1133
+ return coerced;
1134
+ }
1135
+ function hasSameCertificates(left, right) {
1136
+ return (left.length === right.length &&
1137
+ left.every((certificate, index) => certificate === right[index]));
1138
+ }
1139
+ function clonePeerConfiguration(config) {
1140
+ return {
1141
+ ...config,
1142
+ codecs: {
1143
+ audio: config.codecs.audio ? [...config.codecs.audio] : undefined,
1144
+ video: config.codecs.video ? [...config.codecs.video] : undefined,
1145
+ },
1146
+ headerExtensions: {
1147
+ audio: config.headerExtensions.audio
1148
+ ? [...config.headerExtensions.audio]
1149
+ : undefined,
1150
+ video: config.headerExtensions.video
1151
+ ? [...config.headerExtensions.video]
1152
+ : undefined,
1153
+ },
1154
+ iceServers: config.iceServers.map((server) => ({
1155
+ ...server,
1156
+ urls: Array.isArray(server.urls) ? [...server.urls] : server.urls,
1157
+ })),
1158
+ icePortRange: config.icePortRange
1159
+ ? [...config.icePortRange]
1160
+ : undefined,
1161
+ iceAdditionalHostAddresses: config.iceAdditionalHostAddresses
1162
+ ? [...config.iceAdditionalHostAddresses]
1163
+ : undefined,
1164
+ dtls: { ...config.dtls },
1165
+ certificates: [...config.certificates],
1166
+ debug: { ...config.debug },
1167
+ };
1168
+ }
1169
+ class RTCTrackEvent {
1170
+ constructor(init) {
1171
+ Object.defineProperty(this, "type", {
1172
+ enumerable: true,
1173
+ configurable: true,
1174
+ writable: true,
1175
+ value: "track"
1176
+ });
1177
+ Object.defineProperty(this, "track", {
1178
+ enumerable: true,
1179
+ configurable: true,
1180
+ writable: true,
1181
+ value: void 0
1182
+ });
1183
+ Object.defineProperty(this, "streams", {
1184
+ enumerable: true,
1185
+ configurable: true,
1186
+ writable: true,
1187
+ value: void 0
1188
+ });
1189
+ Object.defineProperty(this, "transceiver", {
1190
+ enumerable: true,
1191
+ configurable: true,
1192
+ writable: true,
1193
+ value: void 0
1194
+ });
1195
+ Object.defineProperty(this, "receiver", {
1196
+ enumerable: true,
1197
+ configurable: true,
1198
+ writable: true,
1199
+ value: void 0
1200
+ });
1201
+ this.track = init.track;
1202
+ this.streams = [...init.streams];
1203
+ this.transceiver = init.transceiver;
1204
+ this.receiver = init.receiver;
1205
+ }
1206
+ }
1207
+ exports.RTCTrackEvent = RTCTrackEvent;
859
1208
  //# sourceMappingURL=peerConnection.js.map