yjs/y-webrtc

Problem with firefox and y-webrtc

dmkk3r opened this issue · 4 comments

dmkk3r commented

Describe the bug
I am currently building a collab whiteboard using SyncedStore (wrapper for yjs) and Sveltekit. So far everything works normally in Chrome. I use the y-webrtc provider for the SyncedStore and the connection is established successfully. However, if I use Firefox initially, no connection to the room is established. If I use a Chrome in parallel (Firefox next door still open in the non-synced tab) and establish the connection, Firefox also establishes the connection in parallel and synchronizes the document. I have attached a video below, which shows the exact procedure.

Expected behavior
Firefox connects to the y-webrtc provider just like Chrome when you open the page and synchronizes the document.

Environment Information

  • Firefox 116.0.3
  • Chrome 116.0.5845.111

Additional context

import { syncedStore, getYjsDoc } from '@syncedstore/core';
import { svelteSyncedStore } from '@syncedstore/svelte';
import { env } from '$env/dynamic/public';
import type { RetroBoard } from '$lib/types';
import { WebrtcProvider } from 'y-webrtc';

export const store = syncedStore({
	board: {} as RetroBoard
});
export const svelteStore = svelteSyncedStore(store);

const doc = getYjsDoc(store);

const provider = new WebrtcProvider('retrorealm-room', doc, {
	signaling: [env.PUBLIC_SIGNALING_SERVER],
	filterBcConns: false
});

export const awareness = provider.awareness;
webrtc_firefox_bug.mp4

I am experiencing similar behaviour, firefox is not able to sync and if you turn on the y-webrtc logs, you'd see that it just log infinitely

I don't have a fix for this but I think that the source of the error is that Firefox WebRTC peers don't deliver ArrayBuffer data by default. They deliver blobs. Thus new UInt8Array(data) has a length of 0 and it fails. In the onmessage handler we'll need something like:

      // https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/binaryType
      const buffer = peer.channel.binaryType === "arraybuffer" ? event.data : await event.data.arrayBuffer()

@jeffrafter where is this onmessage handler, I can't find it in src/y-webrtc.js or you meant this?

@ikezedev ah, sorry I was referencing the buffered fork from @disarticulate. In the default y-webrtc the starting point is

const answer = readPeerMessage(this, data)
(which is passed into readPeerMessage and then readMessage as you pointed out). The type hints in the signature claim that a UInt8Array is expected but it is a blob. (There is another spot in the broadcast channel handling and I am not sure if that is another spot where this happens). I think the fix in the default would be to put this into the peer handler, convert the data and then pass the appropriate buffer into readPeerMessage.