Prechádzať zdrojové kódy

fix: convert `Blob`s to `ArrayBuffer`s during `.send()`

As this is an `async` operation, we need to `await conn.send(..)` to
keep the order of transmitted files.

Closes #1137
Jonas Gloning 1 rok pred
rodič
commit
95bb0f7fa9

+ 21 - 0
e2e/datachannel/blobs.js

@@ -0,0 +1,21 @@
+import { commit_data } from "../data.js";
+import { expect } from "https://esm.sh/v126/chai@4.3.7/X-dHMvZXhwZWN0/es2021/chai.bundle.mjs";
+
+const Encoder = new TextEncoder();
+
+/** @param {unknown[]} received */
+export const check = (received) => {
+	expect(received).to.be.an("array").with.lengthOf(commit_data.length);
+	const commits_as_arraybuffer = commit_data.map(
+		(blob) => Encoder.encode(JSON.stringify(blob)).buffer,
+	);
+	expect(received).to.deep.equal(commits_as_arraybuffer);
+};
+/**
+ * @param {import("../peerjs").DataConnection} dataConnection
+ */
+export const send = async (dataConnection) => {
+	for (const commit of commit_data) {
+		await dataConnection.send(new Blob([JSON.stringify(commit)]));
+	}
+};

+ 25 - 0
e2e/datachannel/files.js

@@ -0,0 +1,25 @@
+import { commit_data } from "../data.js";
+import { expect } from "https://esm.sh/v126/chai@4.3.7/X-dHMvZXhwZWN0/es2021/chai.bundle.mjs";
+
+const Encoder = new TextEncoder();
+
+/** @param {unknown[]} received */
+export const check = (received) => {
+	expect(received).to.be.an("array").with.lengthOf(commit_data.length);
+	const commits_as_arraybuffer = commit_data.map(
+		(blob) => Encoder.encode(JSON.stringify(blob)).buffer,
+	);
+	expect(received).to.deep.equal(commits_as_arraybuffer);
+};
+/**
+ * @param {import("../peerjs").DataConnection} dataConnection
+ */
+export const send = async (dataConnection) => {
+	for (const commit of commit_data) {
+		await dataConnection.send(
+			new File([JSON.stringify(commit)], "commit.txt", {
+				type: "dummy/data",
+			}),
+		);
+	}
+};

+ 2 - 2
e2e/datachannel/serialization.js

@@ -82,11 +82,11 @@ const serialization = params.get("serialization");
 		}
 	});
 
-	sendBtn.addEventListener("click", () => {
+	sendBtn.addEventListener("click", async () => {
 		dataConnection.once("error", (err) => {
 			errorMessage.innerText = err.toString();
 		});
-		send(dataConnection);
+		await send(dataConnection);
 		dataConnection.close({ flush: true });
 		messages.textContent = "Sent!";
 	});

+ 12 - 0
e2e/datachannel/serialization_binary.spec.ts

@@ -32,6 +32,18 @@ describe("DataChannel:Binary", () => {
 		jasmine.DEFAULT_TIMEOUT_INTERVAL,
 		2,
 	);
+	it(
+		"should transfer Blobs",
+		serializationTest("./blobs", "binary"),
+		jasmine.DEFAULT_TIMEOUT_INTERVAL,
+		2,
+	);
+	it(
+		"should transfer Files",
+		serializationTest("./files", "binary"),
+		jasmine.DEFAULT_TIMEOUT_INTERVAL,
+		2,
+	);
 	it(
 		"should transfer arrays",
 		serializationTest("./arrays", "binary"),

+ 5 - 0
lib/dataconnection/BufferedConnection/BinaryPack.ts

@@ -79,6 +79,11 @@ export class BinaryPack extends BufferedConnection {
 		data: Packable,
 		chunked: boolean,
 	): void | Promise<void> {
+		if (data instanceof Blob) {
+			return data.arrayBuffer().then((buffer) => {
+				this._send(buffer, chunked);
+			});
+		}
 		const blob = pack(data);
 
 		if (!chunked && blob.byteLength > this.chunker.chunkedMTU) {

+ 1 - 1
lib/dataconnection/DataConnection.ts

@@ -124,7 +124,7 @@ export abstract class DataConnection extends BaseConnection<
 		super.emit("close");
 	}
 
-	protected abstract _send(data: any, chunked: boolean): void;
+	protected abstract _send(data: any, chunked: boolean): void | Promise<void>;
 
 	/** Allows user to send data. */
 	public send(data: any, chunked = false) {