@gjsify/webrtc 0.4.35 → 0.4.37

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/globals.mjs ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Re-exports native WebRTC globals for browser builds.
3
+ *
4
+ * `RTCPeerConnection` and the related RTP/media hierarchy are universal
5
+ * in modern browsers (Chrome 28+, Firefox 22+, Safari 11+).
6
+ *
7
+ * The dynamic resolver in `@gjsify/resolve-npm/runtime-aliases.mjs` routes
8
+ * `@gjsify/webrtc` here when `package.json#gjsify.runtimes.browser === "native"`.
9
+ *
10
+ * NOT used on Node — Node has no RTCPeerConnection global.
11
+ */
12
+
13
+ export const RTCPeerConnection = globalThis.RTCPeerConnection;
14
+ export const RTCDataChannel = globalThis.RTCDataChannel;
15
+ export const RTCRtpSender = globalThis.RTCRtpSender;
16
+ export const RTCRtpReceiver = globalThis.RTCRtpReceiver;
17
+ export const RTCRtpTransceiver = globalThis.RTCRtpTransceiver;
18
+ export const RTCSessionDescription = globalThis.RTCSessionDescription;
19
+ export const RTCIceCandidate = globalThis.RTCIceCandidate;
20
+ export const RTCCertificate = globalThis.RTCCertificate;
21
+ export const RTCStatsReport = globalThis.RTCStatsReport;
22
+ export const RTCDTMFSender = globalThis.RTCDTMFSender;
23
+ export const MediaStream = globalThis.MediaStream;
24
+ export const MediaStreamTrack = globalThis.MediaStreamTrack;
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{RTCError as e}from"./rtc-error.js";import{RTCErrorEvent as t}from"./rtc-events.js";import{DOMException as n}from"@gjsify/dom-exception";import r from"gi://GLib?version=2.0";import{DataChannelBridge as i}from"@gjsify/webrtc-native";import{Blob as a}from"@gjsify/buffer";const o={1:`connecting`,2:`open`,3:`closing`,4:`closed`};function toGBytes(e){let t;return t=ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):new Uint8Array(e),new r.Bytes(t)}function bytesToArrayBuffer(e){let t=e,n=t.toArray?.();if(n instanceof Uint8Array)return n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);let r=t.get_data?.();return r instanceof Uint8Array?r.buffer.slice(r.byteOffset,r.byteOffset+r.byteLength):new ArrayBuffer(0)}var RTCDataChannel=class extends EventTarget{_native;_bridge;_binaryType=`arraybuffer`;_bufferedAmount=0;_closed=!1;_onopen=null;_onclose=null;_onerror=null;_onmessage=null;_onbufferedamountlow=null;_onclosing=null;constructor(e){super();let t=e;t.channel!==void 0&&typeof t.dispose_bridge==`function`?(this._bridge=e,this._native=this._bridge.channel):(this._native=e,this._bridge=new i({channel:this._native})),this._bridge.connect(`opened`,()=>this._handleOpen()),this._bridge.connect(`closed`,()=>this._handleClose()),this._bridge.connect(`error-occurred`,(e,t)=>this._handleError(t)),this._bridge.connect(`message-string`,(e,t)=>this._handleString(t)),this._bridge.connect(`message-data`,(e,t)=>this._handleData(t)),this._bridge.connect(`buffered-amount-low`,()=>this._handleBufferedAmountLow()),this._bridge.connect(`ready-state-changed`,()=>this._handleReadyStateChange())}get label(){return this._native.label}get ordered(){return this._native.ordered}get protocol(){return this._native.protocol}get negotiated(){return this._native.negotiated}get id(){return this._native.id>=0?this._native.id:null}get maxPacketLifeTime(){let e=this._native.max_packet_lifetime;return e>=0?e:null}get maxRetransmits(){let e=this._native.max_retransmits;return e>=0?e:null}get readyState(){return this._closed?`closed`:o[this._native.ready_state]??`connecting`}get bufferedAmount(){try{return Number(this._native.buffered_amount)||this._bufferedAmount}catch{return this._bufferedAmount}}get bufferedAmountLowThreshold(){return Number(this._native.buffered_amount_low_threshold)||0}set bufferedAmountLowThreshold(e){this._native.buffered_amount_low_threshold=e}get binaryType(){return this._binaryType}set binaryType(e){e!==`arraybuffer`&&e!==`blob`||(this._binaryType=e)}get onopen(){return this._onopen}set onopen(e){this._onopen=e}get onclose(){return this._onclose}set onclose(e){this._onclose=e}get onclosing(){return this._onclosing}set onclosing(e){this._onclosing=e}get onerror(){return this._onerror}set onerror(e){this._onerror=e}get onmessage(){return this._onmessage}set onmessage(e){this._onmessage=e}get onbufferedamountlow(){return this._onbufferedamountlow}set onbufferedamountlow(e){this._onbufferedamountlow=e}send(e){let t=this.readyState;if(t!==`open`)throw new n(`RTCDataChannel.send: readyState is '${t}', expected 'open'`,`InvalidStateError`);if(typeof e==`string`){this._native.send_string(e),this._bufferedAmount+=new TextEncoder().encode(e).byteLength;return}if(e instanceof a){e.arrayBuffer().then(e=>{try{this._native.send_data(toGBytes(e)),this._bufferedAmount+=e.byteLength}catch{}});return}if(ArrayBuffer.isView(e)){let t=toGBytes(e);this._native.send_data(t),this._bufferedAmount+=e.byteLength;return}if(e instanceof ArrayBuffer){let t=toGBytes(e);this._native.send_data(t),this._bufferedAmount+=e.byteLength;return}throw TypeError(`RTCDataChannel.send: unsupported data type`)}close(){if(!this._closed){try{this._native.close()}catch{}this._disconnectSignals(),this._closed=!0}}_disconnectSignals(){try{this._bridge.dispose_bridge()}catch{}}_handleOpen(){let e=new Event(`open`);this._onopen?.call(this,e),this.dispatchEvent(e)}_handleClose(){this._closed=!0;let e=new Event(`close`);this._onclose?.call(this,e),this.dispatchEvent(e)}_handleError(n){let r=new t(`error`,{error:new e({errorDetail:`data-channel-failure`},n||`RTCDataChannel error`)});this._onerror?.call(this,r),this.dispatchEvent(r)}_handleString(e){let t=new MessageEvent(`message`,{data:e});this._onmessage?.call(this,t),this.dispatchEvent(t)}_handleData(e){if(!e)return;let t=bytesToArrayBuffer(e),n=this._binaryType===`blob`?new a([t]):t,r=new MessageEvent(`message`,{data:n});this._onmessage?.call(this,r),this.dispatchEvent(r)}_handleBufferedAmountLow(){this._bufferedAmount=Number(this._native.buffered_amount)||0;let e=new Event(`bufferedamountlow`);this._onbufferedamountlow?.call(this,e),this.dispatchEvent(e)}_handleReadyStateChange(){if(this.readyState===`closing`){let e=new Event(`closing`);this._onclosing?.call(this,e),this.dispatchEvent(e)}}};export{RTCDataChannel};
1
+ import"./_virtual/_rolldown/runtime.js";import{RTCError as e}from"./rtc-error.js";import{RTCErrorEvent as t}from"./rtc-events.js";import{DOMException as n}from"@gjsify/dom-exception";import r from"gi://GLib?version=2.0";import{DataChannelBridge as i}from"@gjsify/webrtc-native";import{Blob as a}from"@gjsify/buffer";const o={1:`connecting`,2:`open`,3:`closing`,4:`closed`};function toGBytes(e){let t;return t=ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):new Uint8Array(e),new r.Bytes(t)}function bytesToArrayBuffer(e){let t=e,n=t.toArray?.();if(n instanceof Uint8Array)return n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);let r=t.get_data?.();return r instanceof Uint8Array?r.buffer.slice(r.byteOffset,r.byteOffset+r.byteLength):new ArrayBuffer(0)}var RTCDataChannel=class extends EventTarget{_native;_bridge;_binaryType=`arraybuffer`;_bufferedAmount=0;_closed=!1;_onopen=null;_onclose=null;_onerror=null;_onmessage=null;_onbufferedamountlow=null;_onclosing=null;_sctpTransport=null;constructor(e,t){super(),this._sctpTransport=t??null;let n=e;n.channel!==void 0&&typeof n.dispose_bridge==`function`?(this._bridge=e,this._native=this._bridge.channel):(this._native=e,this._bridge=new i({channel:this._native})),this._bridge.connect(`opened`,()=>this._handleOpen()),this._bridge.connect(`closed`,()=>this._handleClose()),this._bridge.connect(`error-occurred`,(e,t)=>this._handleError(t)),this._bridge.connect(`message-string`,(e,t)=>this._handleString(t)),this._bridge.connect(`message-data`,(e,t)=>this._handleData(t)),this._bridge.connect(`buffered-amount-low`,()=>this._handleBufferedAmountLow()),this._bridge.connect(`ready-state-changed`,()=>this._handleReadyStateChange())}get label(){return this._native.label}get ordered(){return this._native.ordered}get protocol(){return this._native.protocol}get negotiated(){return this._native.negotiated}get id(){return this._native.id>=0?this._native.id:null}get maxPacketLifeTime(){let e=this._native.max_packet_lifetime;return e>=0?e:null}get maxRetransmits(){let e=this._native.max_retransmits;return e>=0?e:null}get readyState(){return this._closed?`closed`:o[this._native.ready_state]??`connecting`}get bufferedAmount(){try{return Number(this._native.buffered_amount)||this._bufferedAmount}catch{return this._bufferedAmount}}get bufferedAmountLowThreshold(){return Number(this._native.buffered_amount_low_threshold)||0}set bufferedAmountLowThreshold(e){this._native.buffered_amount_low_threshold=e}get binaryType(){return this._binaryType}set binaryType(e){e!==`arraybuffer`&&e!==`blob`||(this._binaryType=e)}get onopen(){return this._onopen}set onopen(e){this._onopen=e}get onclose(){return this._onclose}set onclose(e){this._onclose=e}get onclosing(){return this._onclosing}set onclosing(e){this._onclosing=e}get onerror(){return this._onerror}set onerror(e){this._onerror=e}get onmessage(){return this._onmessage}set onmessage(e){this._onmessage=e}get onbufferedamountlow(){return this._onbufferedamountlow}set onbufferedamountlow(e){this._onbufferedamountlow=e}send(e){let t=this.readyState;if(t!==`open`)throw new n(`RTCDataChannel.send: readyState is '${t}', expected 'open'`,`InvalidStateError`);if(typeof e==`string`){let t=new TextEncoder().encode(e).byteLength;this._enforceMaxMessageSize(t),this._native.send_string(e),this._bufferedAmount+=t;return}if(e instanceof a){e.arrayBuffer().then(e=>{try{this._enforceMaxMessageSize(e.byteLength)}catch(e){this._handleError(e instanceof Error?e.message:String(e));return}try{this._native.send_data(toGBytes(e)),this._bufferedAmount+=e.byteLength}catch{}});return}if(ArrayBuffer.isView(e)){this._enforceMaxMessageSize(e.byteLength);let t=toGBytes(e);this._native.send_data(t),this._bufferedAmount+=e.byteLength;return}if(e instanceof ArrayBuffer){this._enforceMaxMessageSize(e.byteLength);let t=toGBytes(e);this._native.send_data(t),this._bufferedAmount+=e.byteLength;return}throw TypeError(`RTCDataChannel.send: unsupported data type`)}_enforceMaxMessageSize(e){if(!this._sctpTransport)return;let t=this._sctpTransport.maxMessageSize;if(!(t<=0)&&e>t)throw new n(`RTCDataChannel.send: data (${e} bytes) exceeds the SCTP max-message-size of ${t} bytes. Split into smaller frames before sending.`,`OperationError`)}close(){if(!this._closed){try{this._native.close()}catch{}this._disconnectSignals(),this._closed=!0}}_disconnectSignals(){try{this._bridge.dispose_bridge()}catch{}}_handleOpen(){let e=new Event(`open`);this._onopen?.call(this,e),this.dispatchEvent(e)}_handleClose(){this._closed=!0;let e=new Event(`close`);this._onclose?.call(this,e),this.dispatchEvent(e)}_handleError(n){let r=new t(`error`,{error:new e({errorDetail:`data-channel-failure`},n||`RTCDataChannel error`)});this._onerror?.call(this,r),this.dispatchEvent(r)}_handleString(e){let t=new MessageEvent(`message`,{data:e});this._onmessage?.call(this,t),this.dispatchEvent(t)}_handleData(e){if(!e)return;let t=bytesToArrayBuffer(e),n=this._binaryType===`blob`?new a([t]):t,r=new MessageEvent(`message`,{data:n});this._onmessage?.call(this,r),this.dispatchEvent(r)}_handleBufferedAmountLow(){this._bufferedAmount=Number(this._native.buffered_amount)||0;let e=new Event(`bufferedamountlow`);this._onbufferedamountlow?.call(this,e),this.dispatchEvent(e)}_handleReadyStateChange(){if(this.readyState===`closing`){let e=new Event(`closing`);this._onclosing?.call(this,e),this.dispatchEvent(e)}}};export{RTCDataChannel};
@@ -1 +1 @@
1
- import"../_virtual/_rolldown/runtime.js";import{Gst as e}from"../gst-init.js";import{RTCDataChannel as t}from"../rtc-data-channel.js";import{DOMException as n}from"@gjsify/dom-exception";function coerceUnsignedShort(e,t){let n=Number(t);if(!Number.isFinite(n))throw TypeError(`createDataChannel: ${e} must be a finite number, got ${String(t)}`);let r=Math.trunc(n);if(r<0||r>65535)throw TypeError(`createDataChannel: ${e}=${r} is outside the [0, 65535] range`);return r}const r={createDataChannel(r,i={}){if(this._closed)throw new n(`Cannot create a data channel on a closed RTCPeerConnection`,`InvalidStateError`);if(typeof r!=`string`)throw TypeError(`createDataChannel: label must be a string`);if(new TextEncoder().encode(r).byteLength>65535)throw TypeError(`createDataChannel: label too long (> 65535 bytes)`);let a=i.maxPacketLifeTime==null?void 0:coerceUnsignedShort(`maxPacketLifeTime`,i.maxPacketLifeTime),o=i.maxRetransmits==null?void 0:coerceUnsignedShort(`maxRetransmits`,i.maxRetransmits),s=i.id==null?void 0:coerceUnsignedShort(`id`,i.id);if(a!==void 0&&o!==void 0)throw TypeError(`createDataChannel: maxPacketLifeTime and maxRetransmits are mutually exclusive`);if(i.negotiated===!0&&s===void 0)throw TypeError(`createDataChannel: negotiated=true requires an id`);if(s===65535)throw TypeError(`createDataChannel: id 65535 is reserved`);let c=e.Structure.new_empty(`data-channel-opts`);this._setStructureField(c,`ordered`,`boolean`,i.ordered),this._setStructureField(c,`max-packet-lifetime`,`int`,a),this._setStructureField(c,`max-retransmits`,`int`,o),this._setStructureField(c,`protocol`,`string`,i.protocol),this._setStructureField(c,`negotiated`,`boolean`,i.negotiated),this._setStructureField(c,`id`,`int`,s);let l=null;try{l=this._webrtcbin.emit(`create-data-channel`,r,c)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`create-data-channel failed: ${t}`)}if(!l)throw Error(`webrtcbin returned null data channel (check id/label/options)`);this._ensureSctpTransport();let u=new t(l);return this._dataChannels.set(l,u),u.addEventListener(`close`,()=>{this._dataChannels.delete(l)}),u}};function installDataChannelMethods(e){Object.assign(e,r)}export{installDataChannelMethods};
1
+ import"../_virtual/_rolldown/runtime.js";import{Gst as e}from"../gst-init.js";import{RTCDataChannel as t}from"../rtc-data-channel.js";import{DOMException as n}from"@gjsify/dom-exception";function coerceUnsignedShort(e,t){let n=Number(t);if(!Number.isFinite(n))throw TypeError(`createDataChannel: ${e} must be a finite number, got ${String(t)}`);let r=Math.trunc(n);if(r<0||r>65535)throw TypeError(`createDataChannel: ${e}=${r} is outside the [0, 65535] range`);return r}const r={createDataChannel(r,i={}){if(this._closed)throw new n(`Cannot create a data channel on a closed RTCPeerConnection`,`InvalidStateError`);if(typeof r!=`string`)throw TypeError(`createDataChannel: label must be a string`);if(new TextEncoder().encode(r).byteLength>65535)throw TypeError(`createDataChannel: label too long (> 65535 bytes)`);let a=i.maxPacketLifeTime==null?void 0:coerceUnsignedShort(`maxPacketLifeTime`,i.maxPacketLifeTime),o=i.maxRetransmits==null?void 0:coerceUnsignedShort(`maxRetransmits`,i.maxRetransmits),s=i.id==null?void 0:coerceUnsignedShort(`id`,i.id);if(a!==void 0&&o!==void 0)throw TypeError(`createDataChannel: maxPacketLifeTime and maxRetransmits are mutually exclusive`);if(i.negotiated===!0&&s===void 0)throw TypeError(`createDataChannel: negotiated=true requires an id`);if(s===65535)throw TypeError(`createDataChannel: id 65535 is reserved`);let c=e.Structure.new_empty(`data-channel-opts`);this._setStructureField(c,`ordered`,`boolean`,i.ordered),this._setStructureField(c,`max-packet-lifetime`,`int`,a),this._setStructureField(c,`max-retransmits`,`int`,o),this._setStructureField(c,`protocol`,`string`,i.protocol),this._setStructureField(c,`negotiated`,`boolean`,i.negotiated),this._setStructureField(c,`id`,`int`,s);let l=null;try{l=this._webrtcbin.emit(`create-data-channel`,r,c)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`create-data-channel failed: ${t}`)}if(!l)throw Error(`webrtcbin returned null data channel (check id/label/options)`);this._ensureSctpTransport();let u=new t(l,this.sctp??void 0);return this._dataChannels.set(l,u),u.addEventListener(`close`,()=>{this._dataChannels.delete(l)}),u}};function installDataChannelMethods(e){Object.assign(e,r)}export{installDataChannelMethods};
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{Gst as e,ensureWebrtcbinAvailable as t}from"./gst-init.js";import{MediaStream as n}from"./media-stream.js";import{gstToConnectionState as r,gstToIceConnectionState as i,gstToIceGatheringState as a,gstToSignalingState as o}from"./gst-enum-maps.js";import{asWebRtcBin as s,asWebRtcSrcPad as c}from"./internal/gst-types.js";import{RTCSessionDescription as l}from"./rtc-session-description.js";import{RTCIceCandidate as u}from"./rtc-ice-candidate.js";import{RTCDataChannelEvent as d,RTCPeerConnectionIceEvent as f}from"./rtc-events.js";import{RTCDataChannel as p}from"./rtc-data-channel.js";import{RTCRtpSender as m}from"./rtc-rtp-sender.js";import{RTCRtpReceiver as h}from"./rtc-rtp-receiver.js";import{RTCRtpTransceiver as g}from"./rtc-rtp-transceiver.js";import{RTCTrackEvent as _}from"./rtc-track-event.js";import{RTCIceTransport as v}from"./rtc-ice-transport.js";import{RTCDtlsTransport as y}from"./rtc-dtls-transport.js";import{RTCSctpTransport as b}from"./rtc-sctp-transport.js";import{RTCCertificate as x,generateCertificate as S}from"./rtc-certificate.js";import{installSdpNegotiationMethods as C}from"./rtc-peer-connection/sdp-negotiation.js";import{installDataChannelMethods as w}from"./rtc-peer-connection/data-channel.js";import{installTransceiverMethods as T}from"./rtc-peer-connection/transceivers.js";import{installTrackMethods as E}from"./rtc-peer-connection/tracks.js";import{installStatsAndConfigMethods as D}from"./rtc-peer-connection/stats-and-config.js";import{DOMException as O}from"@gjsify/dom-exception";import k from"gi://GLib?version=2.0";import A from"gi://GstWebRTC?version=1.0";import{WebrtcbinBridge as j}from"@gjsify/webrtc-native";import M from"gi://GObject?version=2.0";let N=0;var RTCPeerConnection=class extends EventTarget{_pipeline;_webrtcbin;_bridge;_conf;_closed=!1;_iceRestartNeeded=!1;_hasNegotiated=!1;_dataChannels=new Map;_transceivers=new Map;_senders=[];_receivers=[];_iceTransport=null;_dtlsTransport=null;_sctpTransport=null;canTrickleIceCandidates=!0;constructor(n){super(),t();let[r,i]=e.version();if(r<1||r===1&&i<20)throw new O(`@gjsify/webrtc requires GStreamer >= 1.20 (you have ${r}.${i}). webrtcbin is only stable from 1.20 onward.`,`NotSupportedError`);let a=++N;this._pipeline=new e.Pipeline({name:`gjsify-webrtc-pipeline-${a}`});let o=e.ElementFactory.make(`webrtcbin`,`gjsify-webrtcbin-${a}`);if(!o)throw Error(`Failed to create webrtcbin element`);if(this._webrtcbin=o,this._conf={...n},n?.certificates){for(let e of n.certificates)if(e instanceof x&&e.expires<=Date.now())throw new O(`RTCPeerConnection: one of the provided certificates has expired`,`InvalidAccessError`)}this._applyIceServers(n?.iceServers??[]),this._applyIceTransportPolicy(n?.iceTransportPolicy),this._applyBundlePolicy(n?.bundlePolicy),this._pipeline.add(this._webrtcbin),this._bridge=new j({bin:this._webrtcbin}),this._bridge.connect(`negotiation-needed`,()=>this._handleNegotiationNeeded()),this._bridge.connect(`icecandidate`,(e,t,n)=>this._handleIceCandidate(t,n)),this._bridge.connect(`datachannel`,(e,t)=>this._handleDataChannel(t)),this._bridge.connect(`new-transceiver`,(e,t)=>this._handleNewTransceiver(t)),this._bridge.connect(`pad-added`,(e,t)=>this._handlePadAdded(t)),this._bridge.connect(`connection-state-changed`,()=>this._dispatchStateChange(`connectionstatechange`)),this._bridge.connect(`ice-connection-state-changed`,()=>this._dispatchStateChange(`iceconnectionstatechange`)),this._bridge.connect(`ice-gathering-state-changed`,()=>this._dispatchStateChange(`icegatheringstatechange`)),this._bridge.connect(`signaling-state-changed`,()=>this._dispatchStateChange(`signalingstatechange`)),this._pipeline.set_state(e.State.PLAYING)}_applyIceServers(e){let t=!1;for(let n of e){let e=Array.isArray(n.urls)?n.urls:[n.urls];if(e.length===0)throw SyntaxError(`RTCIceServer.urls must not be empty`);for(let r of e){if(typeof r!=`string`||r.length===0)throw TypeError(`RTCIceServer.urls entries must be non-empty strings`);let e=r.indexOf(`:`);if(e<0)throw TypeError(`Invalid ICE server URL "${r}"`);let i=r.slice(0,e+1),a=r.slice(e+1);if(i===`stun:`||i===`stuns:`){if(t)continue;s(this._webrtcbin).stun_server=`${i}//${a}`,t=!0}else if(i===`turn:`||i===`turns:`){if(typeof n.username!=`string`||typeof n.credential!=`string`)throw TypeError(`TURN server credential for ${r} missing`);let e=`${i}//${encodeURIComponent(n.username)}:${encodeURIComponent(n.credential)}@${a}`;try{this._webrtcbin.emit(`add-turn-server`,e)}catch{s(this._webrtcbin).turn_server=e}}else throw TypeError(`Unsupported ICE server protocol "${i}"`)}}}_applyIceTransportPolicy(e){if(!e)return;let t=e===`relay`?A.WebRTCICETransportPolicy.RELAY:A.WebRTCICETransportPolicy.ALL;try{s(this._webrtcbin).ice_transport_policy=t}catch{}}_applyBundlePolicy(e){if(!e)return;let t;switch(e){case`balanced`:t=A.WebRTCBundlePolicy.BALANCED;break;case`max-compat`:t=A.WebRTCBundlePolicy.MAX_COMPAT;break;case`max-bundle`:t=A.WebRTCBundlePolicy.MAX_BUNDLE;break;default:return}try{s(this._webrtcbin).bundle_policy=t}catch{}}get signalingState(){if(this._closed)return`closed`;try{return o(s(this._webrtcbin).signaling_state)}catch{return`stable`}}get connectionState(){if(this._closed)return`closed`;try{return r(s(this._webrtcbin).connection_state)}catch{return`new`}}get iceConnectionState(){if(this._closed)return`closed`;try{return i(s(this._webrtcbin).ice_connection_state)}catch{return`new`}}get iceGatheringState(){try{return a(s(this._webrtcbin).ice_gathering_state)}catch{return`new`}}_descProp(e){try{let t=s(this._webrtcbin)[e];return t?l.fromGstDesc(t):null}catch{return null}}get localDescription(){return this._descProp(`local_description`)}get remoteDescription(){return this._descProp(`remote_description`)}get currentLocalDescription(){return this._descProp(`current_local_description`)}get currentRemoteDescription(){return this._descProp(`current_remote_description`)}get pendingLocalDescription(){return this._descProp(`pending_local_description`)}get pendingRemoteDescription(){return this._descProp(`pending_remote_description`)}get sctp(){return this._sctpTransport}get peerIdentity(){return Promise.reject(TypeError(`peerIdentity assertions are not implemented`))}get idpErrorInfo(){return null}get idpLoginUrl(){return null}_rejectIfClosed(e){if(this._closed)throw new O(`RTCPeerConnection.${e}: connection is closed`,`InvalidStateError`)}_setStructureField(e,t,n,r){if(r==null)return;let i=new M.Value;n===`boolean`?(i.init(M.TYPE_BOOLEAN),i.set_boolean(!!r)):n===`int`?(i.init(M.TYPE_INT),i.set_int(Number(r))):n===`string`&&(i.init(M.TYPE_STRING),i.set_string(String(r))),e.set_value(t,i),i.unset()}close(){this._closed||(this._closed=!0,k.idle_add(k.PRIORITY_DEFAULT,()=>{try{this._pipeline.set_state(e.State.NULL)}catch{}for(let e of this._dataChannels.values())try{e._disconnectSignals()}catch{}this._dataChannels.clear();for(let e of this._senders)try{e._teardownPipeline()}catch{}for(let e of this._receivers)try{e._dispose()}catch{}this._transceivers.clear(),this._senders.length=0,this._receivers.length=0,this._dtlsTransport&&this._dtlsTransport._setState(`closed`),this._iceTransport&&this._iceTransport._setState(`closed`),this._sctpTransport&&this._sctpTransport._setState(`closed`);try{this._bridge.dispose_bridge()}catch{}return k.SOURCE_REMOVE}))}getIdentityAssertion(){return Promise.reject(Error(`getIdentityAssertion is not implemented`))}_findNewGstTransceiver(){for(let e=0;;e++){let t=this._webrtcbin.emit(`get-transceiver`,e);if(!t)return null;if(!this._transceivers.has(t))return t}}_ensureTransports(){return this._dtlsTransport||=(this._iceTransport=new v,new y(this._iceTransport)),this._dtlsTransport}_ensureSctpTransport(){if(this._sctpTransport)return;let e=this._ensureTransports();this._sctpTransport=new b(e)}_createTransceiverWrapper(e){let t=`audio`;try{e.kind===A.WebRTCKind.VIDEO&&(t=`video`)}catch{}let n=e.receiver??null,r=e.sender??null,i=new h(t,n,this._pipeline),a=new m(r,this._pipeline,this._webrtcbin);a._kind=t,a._onPipelineChanged=e=>{this._pipeline=e};let statsDelegate=e=>this.getStats(e);a._getStatsForTrack=statsDelegate,i._getStatsForTrack=statsDelegate;let o=this._ensureTransports();a._transport=o,i._transport=o;try{let t=e.mlineindex;typeof t==`number`&&t>=0&&a._setMlineIndex(t)}catch{}let s=new g(e,a,i);return a._transceiver=s,this._transceivers.set(e,s),this._senders.push(a),this._receivers.push(i),s}_handleNegotiationNeeded(){let e=new Event(`negotiationneeded`);this._onnegotiationneeded?.call(this,e),this.dispatchEvent(e)}_handleIceCandidate(e,t){let n=new f(`icecandidate`,{candidate:new u({candidate:t,sdpMLineIndex:e})});this._onicecandidate?.call(this,n),this.dispatchEvent(n)}_handleNewTransceiver(e){this._closed||this._transceivers.has(e)||this._createTransceiverWrapper(e)}_handlePadAdded(t){if(this._closed||t.direction!==e.PadDirection.SRC)return;let r=c(t).transceiver;if(!r)return;let i=this._transceivers.get(r);i||=this._createTransceiverWrapper(r),i.receiver._connectToPad(t);let a=new n([i.receiver.track]),o=new _(`track`,{receiver:i.receiver,track:i.receiver.track,streams:[a],transceiver:i});this._ontrack?.call(this,o),this.dispatchEvent(o)}_handleDataChannel(e){this._ensureSctpTransport();let t=e.channel,n=this._dataChannels.get(t);n||(n=new p(e),this._dataChannels.set(t,n),n.addEventListener(`close`,()=>{this._dataChannels.delete(t)}));let r=new d(`datachannel`,{channel:n});this._ondatachannel?.call(this,r),this.dispatchEvent(r)}_dispatchStateChange(e){e===`connectionstatechange`?this._syncDtlsState():e===`iceconnectionstatechange`?this._syncIceState():e===`icegatheringstatechange`&&this._syncIceGatheringState();let t=new Event(e);switch(e){case`connectionstatechange`:this._onconnectionstatechange?.call(this,t);break;case`iceconnectionstatechange`:this._oniceconnectionstatechange?.call(this,t);break;case`icegatheringstatechange`:this._onicegatheringstatechange?.call(this,t);break;case`signalingstatechange`:this._onsignalingstatechange?.call(this,t);break}this.dispatchEvent(t)}_syncDtlsState(){if(!this._dtlsTransport)return;let e=this.connectionState;this._dtlsTransport._setState({new:`new`,connecting:`connecting`,connected:`connected`,disconnected:`connected`,failed:`failed`,closed:`closed`}[e]??`new`),e===`connected`&&this._sctpTransport&&this._sctpTransport._setState(`connected`)}_syncIceState(){if(!this._iceTransport)return;let e=this.iceConnectionState;this._iceTransport._setState(e)}_syncIceGatheringState(){if(!this._iceTransport)return;let e=this.iceGatheringState;this._iceTransport._setGatheringState(e)}_onconnectionstatechange=null;_ondatachannel=null;_onicecandidate=null;_oniceconnectionstatechange=null;_onicegatheringstatechange=null;_onnegotiationneeded=null;_onsignalingstatechange=null;get onconnectionstatechange(){return this._onconnectionstatechange}set onconnectionstatechange(e){this._onconnectionstatechange=e}get ondatachannel(){return this._ondatachannel}set ondatachannel(e){this._ondatachannel=e}get onicecandidate(){return this._onicecandidate}set onicecandidate(e){this._onicecandidate=e}get oniceconnectionstatechange(){return this._oniceconnectionstatechange}set oniceconnectionstatechange(e){this._oniceconnectionstatechange=e}get onicegatheringstatechange(){return this._onicegatheringstatechange}set onicegatheringstatechange(e){this._onicegatheringstatechange=e}get onnegotiationneeded(){return this._onnegotiationneeded}set onnegotiationneeded(e){this._onnegotiationneeded=e}get onsignalingstatechange(){return this._onsignalingstatechange}set onsignalingstatechange(e){this._onsignalingstatechange=e}_ontrack=null;get ontrack(){return this._ontrack}set ontrack(e){this._ontrack=e}get onicecandidateerror(){return null}set onicecandidateerror(e){}static generateCertificate(e){return S(e)}};C(RTCPeerConnection.prototype),w(RTCPeerConnection.prototype),T(RTCPeerConnection.prototype),E(RTCPeerConnection.prototype),D(RTCPeerConnection.prototype);export{RTCPeerConnection};
1
+ import"./_virtual/_rolldown/runtime.js";import{Gst as e,ensureWebrtcbinAvailable as t}from"./gst-init.js";import{MediaStream as n}from"./media-stream.js";import{gstToConnectionState as r,gstToIceConnectionState as i,gstToIceGatheringState as a,gstToSignalingState as o}from"./gst-enum-maps.js";import{asWebRtcBin as s,asWebRtcSrcPad as c}from"./internal/gst-types.js";import{RTCSessionDescription as l}from"./rtc-session-description.js";import{RTCIceCandidate as u}from"./rtc-ice-candidate.js";import{RTCDataChannelEvent as d,RTCPeerConnectionIceEvent as f}from"./rtc-events.js";import{RTCDataChannel as p}from"./rtc-data-channel.js";import{RTCRtpSender as m}from"./rtc-rtp-sender.js";import{RTCRtpReceiver as h}from"./rtc-rtp-receiver.js";import{RTCRtpTransceiver as g}from"./rtc-rtp-transceiver.js";import{RTCTrackEvent as _}from"./rtc-track-event.js";import{RTCIceTransport as v}from"./rtc-ice-transport.js";import{RTCDtlsTransport as y}from"./rtc-dtls-transport.js";import{RTCSctpTransport as b}from"./rtc-sctp-transport.js";import{RTCCertificate as x,generateCertificate as S}from"./rtc-certificate.js";import{installSdpNegotiationMethods as C}from"./rtc-peer-connection/sdp-negotiation.js";import{installDataChannelMethods as w}from"./rtc-peer-connection/data-channel.js";import{installTransceiverMethods as T}from"./rtc-peer-connection/transceivers.js";import{installTrackMethods as E}from"./rtc-peer-connection/tracks.js";import{installStatsAndConfigMethods as D}from"./rtc-peer-connection/stats-and-config.js";import{DOMException as O}from"@gjsify/dom-exception";import k from"gi://GLib?version=2.0";import A from"gi://GstWebRTC?version=1.0";import{WebrtcbinBridge as j}from"@gjsify/webrtc-native";import M from"gi://GObject?version=2.0";let N=0;var RTCPeerConnection=class extends EventTarget{_pipeline;_webrtcbin;_bridge;_conf;_closed=!1;_iceRestartNeeded=!1;_hasNegotiated=!1;_dataChannels=new Map;_transceivers=new Map;_senders=[];_receivers=[];_iceTransport=null;_dtlsTransport=null;_sctpTransport=null;canTrickleIceCandidates=!0;constructor(n){super(),t();let[r,i]=e.version();if(r<1||r===1&&i<20)throw new O(`@gjsify/webrtc requires GStreamer >= 1.20 (you have ${r}.${i}). webrtcbin is only stable from 1.20 onward.`,`NotSupportedError`);let a=++N;this._pipeline=new e.Pipeline({name:`gjsify-webrtc-pipeline-${a}`});let o=e.ElementFactory.make(`webrtcbin`,`gjsify-webrtcbin-${a}`);if(!o)throw Error(`Failed to create webrtcbin element`);if(this._webrtcbin=o,this._conf={...n},n?.certificates){for(let e of n.certificates)if(e instanceof x&&e.expires<=Date.now())throw new O(`RTCPeerConnection: one of the provided certificates has expired`,`InvalidAccessError`)}this._applyIceServers(n?.iceServers??[]),this._applyIceTransportPolicy(n?.iceTransportPolicy),this._applyBundlePolicy(n?.bundlePolicy),this._pipeline.add(this._webrtcbin),this._bridge=new j({bin:this._webrtcbin}),this._bridge.connect(`negotiation-needed`,()=>this._handleNegotiationNeeded()),this._bridge.connect(`icecandidate`,(e,t,n)=>this._handleIceCandidate(t,n)),this._bridge.connect(`datachannel`,(e,t)=>this._handleDataChannel(t)),this._bridge.connect(`new-transceiver`,(e,t)=>this._handleNewTransceiver(t)),this._bridge.connect(`pad-added`,(e,t)=>this._handlePadAdded(t)),this._bridge.connect(`connection-state-changed`,()=>this._dispatchStateChange(`connectionstatechange`)),this._bridge.connect(`ice-connection-state-changed`,()=>this._dispatchStateChange(`iceconnectionstatechange`)),this._bridge.connect(`ice-gathering-state-changed`,()=>this._dispatchStateChange(`icegatheringstatechange`)),this._bridge.connect(`signaling-state-changed`,()=>this._dispatchStateChange(`signalingstatechange`)),this._pipeline.set_state(e.State.PLAYING)}_applyIceServers(e){let t=!1;for(let n of e){let e=Array.isArray(n.urls)?n.urls:[n.urls];if(e.length===0)throw SyntaxError(`RTCIceServer.urls must not be empty`);for(let r of e){if(typeof r!=`string`||r.length===0)throw TypeError(`RTCIceServer.urls entries must be non-empty strings`);let e=r.indexOf(`:`);if(e<0)throw TypeError(`Invalid ICE server URL "${r}"`);let i=r.slice(0,e+1),a=r.slice(e+1);if(i===`stun:`||i===`stuns:`){if(t)continue;s(this._webrtcbin).stun_server=`${i}//${a}`,t=!0}else if(i===`turn:`||i===`turns:`){if(typeof n.username!=`string`||typeof n.credential!=`string`)throw TypeError(`TURN server credential for ${r} missing`);let e=`${i}//${encodeURIComponent(n.username)}:${encodeURIComponent(n.credential)}@${a}`;try{this._webrtcbin.emit(`add-turn-server`,e)}catch{s(this._webrtcbin).turn_server=e}}else throw TypeError(`Unsupported ICE server protocol "${i}"`)}}}_applyIceTransportPolicy(e){if(!e)return;let t=e===`relay`?A.WebRTCICETransportPolicy.RELAY:A.WebRTCICETransportPolicy.ALL;try{s(this._webrtcbin).ice_transport_policy=t}catch{}}_applyBundlePolicy(e){if(!e)return;let t;switch(e){case`balanced`:t=A.WebRTCBundlePolicy.BALANCED;break;case`max-compat`:t=A.WebRTCBundlePolicy.MAX_COMPAT;break;case`max-bundle`:t=A.WebRTCBundlePolicy.MAX_BUNDLE;break;default:return}try{s(this._webrtcbin).bundle_policy=t}catch{}}get signalingState(){if(this._closed)return`closed`;try{return o(s(this._webrtcbin).signaling_state)}catch{return`stable`}}get connectionState(){if(this._closed)return`closed`;try{return r(s(this._webrtcbin).connection_state)}catch{return`new`}}get iceConnectionState(){if(this._closed)return`closed`;try{return i(s(this._webrtcbin).ice_connection_state)}catch{return`new`}}get iceGatheringState(){try{return a(s(this._webrtcbin).ice_gathering_state)}catch{return`new`}}_descProp(e){try{let t=s(this._webrtcbin)[e];return t?l.fromGstDesc(t):null}catch{return null}}get localDescription(){return this._descProp(`local_description`)}get remoteDescription(){return this._descProp(`remote_description`)}get currentLocalDescription(){return this._descProp(`current_local_description`)}get currentRemoteDescription(){return this._descProp(`current_remote_description`)}get pendingLocalDescription(){return this._descProp(`pending_local_description`)}get pendingRemoteDescription(){return this._descProp(`pending_remote_description`)}get sctp(){return this._sctpTransport}get peerIdentity(){return Promise.reject(TypeError(`peerIdentity assertions are not implemented`))}get idpErrorInfo(){return null}get idpLoginUrl(){return null}_rejectIfClosed(e){if(this._closed)throw new O(`RTCPeerConnection.${e}: connection is closed`,`InvalidStateError`)}_setStructureField(e,t,n,r){if(r==null)return;let i=new M.Value;n===`boolean`?(i.init(M.TYPE_BOOLEAN),i.set_boolean(!!r)):n===`int`?(i.init(M.TYPE_INT),i.set_int(Number(r))):n===`string`&&(i.init(M.TYPE_STRING),i.set_string(String(r))),e.set_value(t,i),i.unset()}close(){this._closed||(this._closed=!0,k.idle_add(k.PRIORITY_DEFAULT,()=>{try{this._pipeline.set_state(e.State.NULL)}catch{}for(let e of this._dataChannels.values())try{e._disconnectSignals()}catch{}this._dataChannels.clear();for(let e of this._senders)try{e._teardownPipeline()}catch{}for(let e of this._receivers)try{e._dispose()}catch{}this._transceivers.clear(),this._senders.length=0,this._receivers.length=0,this._dtlsTransport&&this._dtlsTransport._setState(`closed`),this._iceTransport&&this._iceTransport._setState(`closed`),this._sctpTransport&&this._sctpTransport._setState(`closed`);try{this._bridge.dispose_bridge()}catch{}return k.SOURCE_REMOVE}))}getIdentityAssertion(){return Promise.reject(Error(`getIdentityAssertion is not implemented`))}_findNewGstTransceiver(){for(let e=0;;e++){let t=this._webrtcbin.emit(`get-transceiver`,e);if(!t)return null;if(!this._transceivers.has(t))return t}}_ensureTransports(){return this._dtlsTransport||=(this._iceTransport=new v,new y(this._iceTransport)),this._dtlsTransport}_ensureSctpTransport(){if(this._sctpTransport)return;let e=this._ensureTransports();this._sctpTransport=new b(e)}_createTransceiverWrapper(e){let t=`audio`;try{e.kind===A.WebRTCKind.VIDEO&&(t=`video`)}catch{}let n=e.receiver??null,r=e.sender??null,i=new h(t,n,this._pipeline),a=new m(r,this._pipeline,this._webrtcbin);a._kind=t,a._onPipelineChanged=e=>{this._pipeline=e};let statsDelegate=e=>this.getStats(e);a._getStatsForTrack=statsDelegate,i._getStatsForTrack=statsDelegate;let o=this._ensureTransports();a._transport=o,i._transport=o;try{let t=e.mlineindex;typeof t==`number`&&t>=0&&a._setMlineIndex(t)}catch{}let s=new g(e,a,i);return a._transceiver=s,this._transceivers.set(e,s),this._senders.push(a),this._receivers.push(i),s}_handleNegotiationNeeded(){let e=new Event(`negotiationneeded`);this._onnegotiationneeded?.call(this,e),this.dispatchEvent(e)}_handleIceCandidate(e,t){let n=new f(`icecandidate`,{candidate:new u({candidate:t,sdpMLineIndex:e})});this._onicecandidate?.call(this,n),this.dispatchEvent(n)}_handleNewTransceiver(e){this._closed||this._transceivers.has(e)||this._createTransceiverWrapper(e)}_handlePadAdded(t){if(this._closed||t.direction!==e.PadDirection.SRC)return;let r=c(t).transceiver;if(!r)return;let i=this._transceivers.get(r);i||=this._createTransceiverWrapper(r),i.receiver._connectToPad(t);let a=new n([i.receiver.track]),o=new _(`track`,{receiver:i.receiver,track:i.receiver.track,streams:[a],transceiver:i});this._ontrack?.call(this,o),this.dispatchEvent(o)}_handleDataChannel(e){this._ensureSctpTransport();let t=e.channel,n=this._dataChannels.get(t);n||(n=new p(e,this._sctpTransport??void 0),this._dataChannels.set(t,n),n.addEventListener(`close`,()=>{this._dataChannels.delete(t)}));let r=new d(`datachannel`,{channel:n});this._ondatachannel?.call(this,r),this.dispatchEvent(r)}_dispatchStateChange(e){e===`connectionstatechange`?this._syncDtlsState():e===`iceconnectionstatechange`?this._syncIceState():e===`icegatheringstatechange`&&this._syncIceGatheringState();let t=new Event(e);switch(e){case`connectionstatechange`:this._onconnectionstatechange?.call(this,t);break;case`iceconnectionstatechange`:this._oniceconnectionstatechange?.call(this,t);break;case`icegatheringstatechange`:this._onicegatheringstatechange?.call(this,t);break;case`signalingstatechange`:this._onsignalingstatechange?.call(this,t);break}this.dispatchEvent(t)}_syncDtlsState(){if(!this._dtlsTransport)return;let e=this.connectionState;this._dtlsTransport._setState({new:`new`,connecting:`connecting`,connected:`connected`,disconnected:`connected`,failed:`failed`,closed:`closed`}[e]??`new`),e===`connected`&&this._sctpTransport&&this._sctpTransport._setState(`connected`)}_syncIceState(){if(!this._iceTransport)return;let e=this.iceConnectionState;this._iceTransport._setState(e)}_syncIceGatheringState(){if(!this._iceTransport)return;let e=this.iceGatheringState;this._iceTransport._setGatheringState(e)}_onconnectionstatechange=null;_ondatachannel=null;_onicecandidate=null;_oniceconnectionstatechange=null;_onicegatheringstatechange=null;_onnegotiationneeded=null;_onsignalingstatechange=null;get onconnectionstatechange(){return this._onconnectionstatechange}set onconnectionstatechange(e){this._onconnectionstatechange=e}get ondatachannel(){return this._ondatachannel}set ondatachannel(e){this._ondatachannel=e}get onicecandidate(){return this._onicecandidate}set onicecandidate(e){this._onicecandidate=e}get oniceconnectionstatechange(){return this._oniceconnectionstatechange}set oniceconnectionstatechange(e){this._oniceconnectionstatechange=e}get onicegatheringstatechange(){return this._onicegatheringstatechange}set onicegatheringstatechange(e){this._onicegatheringstatechange=e}get onnegotiationneeded(){return this._onnegotiationneeded}set onnegotiationneeded(e){this._onnegotiationneeded=e}get onsignalingstatechange(){return this._onsignalingstatechange}set onsignalingstatechange(e){this._onsignalingstatechange=e}_ontrack=null;get ontrack(){return this._ontrack}set ontrack(e){this._ontrack=e}get onicecandidateerror(){return null}set onicecandidateerror(e){}static generateCertificate(e){return S(e)}};C(RTCPeerConnection.prototype),w(RTCPeerConnection.prototype),T(RTCPeerConnection.prototype),E(RTCPeerConnection.prototype),D(RTCPeerConnection.prototype);export{RTCPeerConnection};
@@ -1,6 +1,7 @@
1
1
  import type GstWebRTC from 'gi://GstWebRTC?version=1.0';
2
2
  import { type DataChannelBridge as DataChannelBridgeType } from '@gjsify/webrtc-native';
3
3
  import { RTCErrorEvent } from './rtc-events.js';
4
+ import type { RTCSctpTransport } from './rtc-sctp-transport.js';
4
5
  export type RTCDataChannelState = 'connecting' | 'open' | 'closing' | 'closed';
5
6
  export type BinaryType = 'blob' | 'arraybuffer';
6
7
  type EventHandler<E extends Event = Event> = ((this: RTCDataChannel, ev: E) => any) | null;
@@ -16,14 +17,30 @@ export declare class RTCDataChannel extends EventTarget {
16
17
  private _onmessage;
17
18
  private _onbufferedamountlow;
18
19
  private _onclosing;
20
+ /**
21
+ * Reference to the parent peer connection's SCTP transport. Used
22
+ * by {@link send} to enforce the W3C `maxMessageSize` ceiling
23
+ * per WebRTC § 5.6.5 step 4 — `OperationError` is thrown when a
24
+ * send would exceed the negotiated SCTP `max-message-size`.
25
+ *
26
+ * Optional for backwards compatibility with the
27
+ * `new RTCDataChannel(rawGstChannel)` factory shape used by
28
+ * downstream tooling that hasn't been updated yet. When omitted,
29
+ * size validation is skipped — matching pre-2026-06-01 behaviour.
30
+ * Production peer connections always pass it.
31
+ */
32
+ private readonly _sctpTransport;
19
33
  /**
20
34
  * @internal
21
35
  * Accepts either a raw GstWebRTCDataChannel (for locally-created channels)
22
36
  * or a pre-made DataChannelBridge (for remotely-originated channels that
23
37
  * the WebrtcbinBridge already wrapped on the streaming thread to avoid
24
38
  * missing early messages).
39
+ *
40
+ * `sctpTransport` enables W3C-spec `maxMessageSize` validation in
41
+ * {@link send}. Optional for backwards-compat — see field doc.
25
42
  */
26
- constructor(source: GstWebRTC.WebRTCDataChannel | DataChannelBridgeType);
43
+ constructor(source: GstWebRTC.WebRTCDataChannel | DataChannelBridgeType, sctpTransport?: RTCSctpTransport);
27
44
  get label(): string;
28
45
  get ordered(): boolean;
29
46
  get protocol(): string;
@@ -50,6 +67,23 @@ export declare class RTCDataChannel extends EventTarget {
50
67
  get onbufferedamountlow(): EventHandler;
51
68
  set onbufferedamountlow(h: EventHandler);
52
69
  send(data: string | ArrayBuffer | ArrayBufferView | Blob): void;
70
+ /**
71
+ * W3C WebRTC § 5.6.5 step 4 — "If the length of data in bytes is
72
+ * greater than transport's [[MaxMessageSize]] internal slot,
73
+ * throw an OperationError DOMException."
74
+ *
75
+ * Pre-fix (2026-06-01) the underlying webrtcbin / SCTP layer
76
+ * silently dropped any single `send_message` above the
77
+ * `max-message-size` ceiling (RFC 8841 default 64 KiB on most
78
+ * peers). Application code saw "send returned, frame never
79
+ * arrived" — debugged for hours in pixel-rpg/map-editor's
80
+ * Pair-Editing hand-test before tracing it back here. Post-fix,
81
+ * the bound peer connection passes its `RTCSctpTransport` into
82
+ * the data channel; oversize sends throw immediately, surfacing
83
+ * the framing limit as a typed JS error like every browser
84
+ * implementation does.
85
+ */
86
+ private _enforceMaxMessageSize;
53
87
  close(): void;
54
88
  /** @internal */
55
89
  _disconnectSignals(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/webrtc",
3
- "version": "0.4.35",
3
+ "version": "0.4.37",
4
4
  "description": "W3C WebRTC API for GJS using GStreamer webrtcbin as the peer-connection backend",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -28,14 +28,17 @@
28
28
  },
29
29
  "./register/media-devices": {
30
30
  "default": "./lib/esm/register/media-devices.js"
31
- }
31
+ },
32
+ "./globals": "./globals.mjs"
32
33
  },
33
34
  "files": [
34
- "lib"
35
+ "lib",
36
+ "globals.mjs"
35
37
  ],
36
38
  "sideEffects": [
37
39
  "./lib/esm/register.js",
38
- "./lib/esm/register/*.js"
40
+ "./lib/esm/register/*.js",
41
+ "./globals.mjs"
39
42
  ],
40
43
  "scripts": {
41
44
  "clear": "rm -rf lib tsconfig.tsbuildinfo tsconfig.types.tsbuildinfo test.gjs.mjs || exit 0",
@@ -58,28 +61,39 @@
58
61
  "peer-connection"
59
62
  ],
60
63
  "dependencies": {
61
- "@gjsify/buffer": "^0.4.35",
62
- "@gjsify/dom-events": "^0.4.35",
63
- "@gjsify/dom-exception": "^0.4.35",
64
- "@gjsify/webrtc-native": "^0.4.35"
64
+ "@gjsify/buffer": "^0.4.37",
65
+ "@gjsify/dom-events": "^0.4.37",
66
+ "@gjsify/dom-exception": "^0.4.37",
67
+ "@gjsify/webrtc-native": "^0.4.37"
65
68
  },
66
69
  "devDependencies": {
67
- "@girs/gjs": "4.0.1",
68
- "@girs/glib-2.0": "2.88.0-4.0.1",
69
- "@girs/gobject-2.0": "2.88.0-4.0.1",
70
- "@girs/gst-1.0": "1.28.1-4.0.1",
71
- "@girs/gstsdp-1.0": "1.0.0-4.0.1",
72
- "@girs/gstwebrtc-1.0": "1.0.0-4.0.1",
73
- "@gjsify/cli": "^0.4.35",
74
- "@gjsify/unit": "^0.4.35",
70
+ "@girs/gjs": "4.0.4",
71
+ "@girs/glib-2.0": "2.88.0-4.0.4",
72
+ "@girs/gobject-2.0": "2.88.0-4.0.4",
73
+ "@girs/gst-1.0": "1.28.1-4.0.4",
74
+ "@girs/gstsdp-1.0": "1.0.0-4.0.4",
75
+ "@girs/gstwebrtc-1.0": "1.0.0-4.0.4",
76
+ "@gjsify/cli": "^0.4.37",
77
+ "@gjsify/unit": "^0.4.37",
75
78
  "@types/node": "^25.9.1",
76
- "typescript": "^6.0.3"
79
+ "typescript": "^5.9.3"
77
80
  },
78
81
  "gjsify": {
79
82
  "runtimes": {
80
83
  "gjs": "polyfill",
81
84
  "node": "none",
82
- "browser": "none"
85
+ "browser": "native",
86
+ "nativescript": "none"
83
87
  }
84
- }
88
+ },
89
+ "license": "MIT",
90
+ "repository": {
91
+ "type": "git",
92
+ "url": "git+https://github.com/gjsify/gjsify.git",
93
+ "directory": "packages/web/webrtc"
94
+ },
95
+ "bugs": {
96
+ "url": "https://github.com/gjsify/gjsify/issues"
97
+ },
98
+ "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/web/webrtc#readme"
85
99
  }