s this feature or erroring with a message like "Voice/Video
 * calling is not supported on this browser".
 *
 * These webpages rely on the older Chrome-only createEncodedStreams()
 * API instead of the standard RTCRtpScriptTransform API now available
 * in all browsers. The following shims the former using the latter.
 *
 * Note: this shim has inherent performance limitations being on
 * main thread. Websites are encouraged to upgrade to the standard
 * worker-based API directly for optimal performance in Firefox.
 */

/* globals exportFunction, cloneInto */

console.info(
  "createEncodedStreams() is being shimmed for compatibility reasons. Please consider updating to the RTCRtpScriptTransform API for optimal performance! See https://bugzil.la/1913599 for details."
);

const win = window.wrappedJSObject;
if (!win.RTCRtpSender.prototype.createEncodedStreams) {
  win.RTCRtpSender.prototype.createEncodedStreams =
    win.RTCRtpReceiver.prototype.createEncodedStreams = exportFunction(
      function createEncodedStreams() {
        let onrtctransform; // appease linter
        function work() {
          const originals = [];
          onrtctransform = async ({ transformer: { readable, writable } }) => {
            const diverter = new TransformStream({
              transform: (original, controller) => {
                originals.push(original);
                controller.enqueue(original);
              },
            });
            const reinserter = new TransformStream({
              transform: (frame, controller) => {
                const original = originals.shift();
                original.data = frame.data;
                controller.enqueue(original);
              },
            });
            self.postMessage(
              { readable: diverter.readable, writable: reinserter.writable },
              { transfer: [diverter.readable, reinserter.writable] }
            );
            await readable
              .pipeThrough({
                writable: diverter.writable,
                readable: reinserter.readable,
              })
              .pipeTo(writable);
          };
        }
        this._worker = new Worker(
          `data:text/javascript,(${work.toString()})()`
        );
        this.transform = new window.RTCRtpScriptTransform(this._worker);
        this._dummy = onrtctransform; // appease linter
        const readableNow = new TransformStream();
        const writableNow = new TransformStream();
        const haveData = new Promise(
          r => (this._worker.onmessage = e => r(e.data))
        );
        haveData
          .then(({ readable }) => readable.pipeTo(readableNow.writable))
          .catch(e => readableNow.writable.abort(e));
        haveData
          .then(({ writable }) => writableNow.readable.pipeTo(writable))
          .catch(e => writableNow.readable.cancel(e));

        const result = new win.Object();
        result.readable = cloneInto(readableNow.readable, window, {
          wrapReflectors: true,
        });
        result.writable = cloneInto(writableNow.writable, window, {
          wrapReflectors: true,
        });
        return result;
      },
      window
    );
}
PK