Skip to content

Commit f492b05

Browse files
committed
fix: use binaryType correctly
The `.binaryType` field on the `RTCDataChannel` class defines what type the `.data` field on emitted `MessageEvent`s will be. It's either `arraybuffer` (the default) or `blob`. Docs: https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/binaryType 1. Switches the default to `arraybuffer` 2. Converts incoming data to the correct type based on the `binaryType` I've done my best to assert the right types/values in the "P2P test" in `polyfill.test.ts`. Because getting the binary data out of a `Blob` is an async operation I had to make the test async, but it doesn't fit very well with the current nature of the test. TBH that test is very complicated and would be much better off split into multiple smaller tests, each testing one thing.
1 parent 5eee147 commit f492b05

File tree

2 files changed

+243
-202
lines changed

2 files changed

+243
-202
lines changed

src/polyfill/RTCDataChannel.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import * as exceptions from './Exception';
33
import { DataChannel } from '../lib/index';
44

5+
const encoder = new TextEncoder()
6+
57
export default class RTCDataChannel extends EventTarget implements globalThis.RTCDataChannel {
68
#dataChannel: DataChannel;
79
#readyState: globalThis.RTCDataChannelState;
@@ -26,7 +28,7 @@ export default class RTCDataChannel extends EventTarget implements globalThis.RT
2628
super();
2729

2830
this.#dataChannel = dataChannel;
29-
this.#binaryType = 'blob';
31+
this.#binaryType = 'arraybuffer';
3032
this.#readyState = this.#dataChannel.isOpen() ? 'open' : 'connecting';
3133
this.#bufferedAmountLowThreshold = 0;
3234
this.#maxPacketLifeTime = opts.maxPacketLifeTime || null;
@@ -70,15 +72,33 @@ export default class RTCDataChannel extends EventTarget implements globalThis.RT
7072
this.dispatchEvent(new Event('bufferedamountlow'));
7173
});
7274

73-
this.#dataChannel.onMessage((data) => {
74-
if (ArrayBuffer.isView(data)) {
75-
if (this.binaryType == 'arraybuffer')
76-
data = data.buffer;
77-
else
78-
data = Buffer.from(data.buffer);
75+
this.#dataChannel.onMessage((message) => {
76+
if (typeof message === 'string') {
77+
message = encoder.encode(message);
78+
}
79+
80+
let data: Blob | ArrayBuffer;
81+
82+
if (message instanceof ArrayBuffer) {
83+
data = message;
84+
} else {
85+
data = message.buffer;
86+
87+
if (message.byteOffset !== 0 || message.byteLength !== message.buffer.byteLength) {
88+
// message is view on underlying buffer, must create new
89+
// ArrayBuffer that only contains message data
90+
data = new ArrayBuffer(message.byteLength)
91+
new Uint8Array(data, 0, message.byteLength).set(message)
92+
}
93+
}
94+
95+
if (this.#binaryType === 'blob') {
96+
data = new Blob([data]);
7997
}
8098

81-
this.dispatchEvent(new MessageEvent('message', { data }));
99+
this.dispatchEvent(new MessageEvent('message', {
100+
data
101+
}));
82102
});
83103

84104
// forward events to properties

0 commit comments

Comments
 (0)