-
-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: polyfill W3C compatibility #324
base: master
Are you sure you want to change the base?
Conversation
if (arguments.length === 0) throw new TypeError(`Failed to construct 'RTCDataChannelEvent': 2 arguments required, but only ${arguments.length} present.`) | ||
if (typeof init !== 'object') throw new TypeError("Failed to construct 'RTCDataChannelEvent': The provided value is not of type 'RTCDataChannelEventInit'.") | ||
if (!init.channel) throw new TypeError("Failed to construct 'RTCDataChannelEvent': Failed to read the 'channel' property from 'RTCDataChannelEventInit': Required member is undefined.") | ||
if (init.channel.constructor !== RTCDataChannel) throw new TypeError("Failed to construct 'RTCDataChannelEvent': Failed to read the 'channel' property from 'RTCDataChannelEventInit': Failed to convert value to 'RTCDataChannel'.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
required by spec
onclosing: globalThis.RTCDataChannel['onclosing']; | ||
onerror: globalThis.RTCDataChannel['onerror']; | ||
onmessage: globalThis.RTCDataChannel['onmessage']; | ||
onopen: globalThis.RTCDataChannel['onopen'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bettter to let the types define it, rather than manually declare any, a typed event target implementation would be prefered however
}); | ||
// we need updated connectionstate, so this is delayed by a single event loop tick | ||
// this is fucked and wonky, needs to be made better | ||
this.#dataChannel.onClosed(() => setTimeout(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the spec is very assine about how and when datachannels should close, this is the closest i was able to bring it inline with said spec, the order of events in peer, ice and dc on closing is important for some libraries
if (!ArrayBuffer.isView(message)) { | ||
data = message | ||
} else if (this.#binaryType === 'blob') { | ||
data = new Blob([message]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't explicitly use buffer, also cast to Blob when the type requires it, this wasn't even done before
this.#dataChannel.sendMessage(data); | ||
} else if (data instanceof Blob) { | ||
} else if ('arrayBuffer' in data) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we're not actually interested in blob, but its ab method, this is important for Blob-like libraries
state = 'closed'; | ||
} | ||
return state; | ||
if (this.#pc.connectionState === 'disconnected') return 'closed' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pc is always defined
@@ -58,7 +58,7 @@ export default class RTCIceCandidate implements globalThis.RTCIceCandidate { | |||
} | |||
|
|||
get address(): string | null { | |||
return this.#address || null; | |||
return this.#address ?? null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|| was incorrect to use here!!! we want null checking, not falsy checking
}); | ||
} | ||
|
||
get component(): globalThis.RTCIceComponent { | ||
const cp = this.getSelectedCandidatePair(); | ||
if (!cp) return null; | ||
if (!cp?.local) return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
didnt verify local!
getRemoteParameters(): any { | ||
/** */ | ||
getRemoteParameters(): RTCIceParameters | null { | ||
return new RTCIceParameters(new RTCIceCandidate({ candidate: this.#pc.getSelectedCandidatePair().remote.candidate, sdpMLineIndex: 0 })) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RTCIceParams were completely missing, these still dont have password/ufrag, need to wait for upstream to expose that
} | ||
|
||
get maxMessageSize(): number { | ||
if (this.state !== 'connected') return null; | ||
return this.#pc ? this.#extraFunctions.maxMessageSize() : 0; | ||
return this.#pc.maxMessageSize ?? 65536; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should never be 0
this.#type = init ? init.type : null; | ||
this.#sdp = init ? init.sdp : null; | ||
constructor(init: globalThis.RTCSessionDescriptionInit | null | undefined) { | ||
this.#type = init?.type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worked for the library, but not as a global exposed constructor
// length of urls can not be 0 | ||
if (config.iceServers[i].urls?.length === 0) | ||
throw new exceptions.SyntaxError('IceServers urls cannot be empty'); | ||
setConfiguration(config: RTCConfiguration): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I for the most part removed the old implementation, because by default a lot of fallbacks are used, this is correct for W3C, but i'm not certain this is correct for NDC, this needs to be verified
}); | ||
|
||
this.#peerConnection.onLocalDescription((sdp, type) => { | ||
if (type === 'offer') { | ||
this.#localOffer.resolve({ sdp, type }); | ||
this.#localOffer.resolve(new RTCSessionDescription({ sdp, type })); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was incorrect!
this.ontrack?.(e as RTCTrackEvent) | ||
}) | ||
|
||
this.addEventListener('negotiationneeded', e => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was never implemented, and is required for polite-peer libs
} | ||
|
||
createOffer(): Promise<globalThis.RTCSessionDescriptionInit | any> { | ||
createOffer(): Promise<globalThis.RTCSessionDescriptionInit> & Promise<void> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there are some annoying deprecated overloads for some of these methods, we shouldn't support them
Hello and thank you for the PR. I think it will be good in all cases to separate this PR into small PRs. Especially RTCRtp part.
|
I assumed you use some manual commands, because rollup isn't even installable as you include a package-lock, and removing it, causes version conflict errors, so I couldn't even run rollup to try compiling it |
you can feel free to split up this PR, I kinda lost my will to live after implementing the video/audio track shenanigans, mainly because of how they are exposed, I think the bindings need to do it a bit better than what we currently have, but that's honestly above what I'm willing to do, so I tried somewhat finishing it, even tho I don't think it actually works correctly as I couldn't find how to properly create and consume tracks and transceivers |
I didn't understand what you mean. for others you can check |
Unfortunately, I can not split the PR. About the tracks, we need definitely a separate PR and work and of course some test cases. |
this PR aims to fix all the critical W3C compatibility issues in the polyfill
it also implements rudimentary MediaStreams [WIP]
I'll add comments to the PR explaining things