v157 · web bluetooth
Handling a size change mid-transfer
The write size is a property of the connection, and the connection can renegotiate. Read it once into a variable, chunk a queue with it, and a mid-transfer drop leaves you writing packets the link can no longer carry. Run both handlers against the same forced renegotiation and see which one corrupts the image.
Same transfer, two handlers
Both lanes send a 64 KB image. Partway through, the simulated link renegotiates from 182 bytes down to 65 — a real event when a second device connects or the radio conditions change. The left handler cached the size at connect time. The right one listens for maxwritewithoutresponsesizechanged and re-chunks what is left.
Cached size at connect
- Writing
- 182 B
- Delivered
- 0
- Truncated
- 0
Listening for the change
- Writing
- 182 B
- Delivered
- 0
- Truncated
- 0
Event log
- Nothing yet.
code path
// Wrong: the size is read once and captured in the closure.
const size = server.maxWriteWithoutResponseSize;
for (const chunk of chunkBy(image, size)) await write(chunk);
// Right: read it per write, and re-chunk what is left when it changes.
server.addEventListener("maxwritewithoutresponsesizechanged", () => {
console.log("[ble] renegotiated to", server.maxWriteWithoutResponseSize);
});
let offset = 0;
while (offset < image.byteLength) {
const size = server.maxWriteWithoutResponseSize ?? 20;
await write(image.subarray(offset, offset + size));
offset += size;
}
A write that exceeds the negotiated size is rejected on some platforms and silently truncated on others. The truncating case is the dangerous one: the transfer reports success and the device is left holding a corrupt image.