diff --git a/lib/websocket/frame.js b/lib/websocket/frame.js index f9115fc6ecc..1df5e16934b 100644 --- a/lib/websocket/frame.js +++ b/lib/websocket/frame.js @@ -45,7 +45,8 @@ class WebsocketFrameSend { if (payloadLength === 126) { new DataView(buffer.buffer).setUint16(2, bodyLength) } else if (payloadLength === 127) { - // TODO: optimize this once tests are added for payloads >= 2^16 bytes + // Clear extended payload length + buffer[2] = buffer[3] = 0 buffer.writeUIntBE(bodyLength, 4, 6) } diff --git a/lib/websocket/receiver.js b/lib/websocket/receiver.js index e532366d640..cd6e8bc4f7f 100644 --- a/lib/websocket/receiver.js +++ b/lib/websocket/receiver.js @@ -196,10 +196,10 @@ class ByteParser extends Writable { } const buffer = this.consume(8) + const upper = buffer.readUInt32BE(0) + const lower = buffer.readUInt32BE(4) - // TODO: optimize this - // TODO: this likely doesn't work because it returns a bigint - this.#info.payloadLength = buffer.readBigUint64BE(0) + this.#info.payloadLength = (upper << 8) + lower this.#state = parserStates.READ_DATA } else if (this.#state === parserStates.READ_DATA) { if (this.#byteOffset < this.#info.payloadLength) { diff --git a/lib/websocket/websocket.js b/lib/websocket/websocket.js index a5fa94f623d..3955b5664cf 100644 --- a/lib/websocket/websocket.js +++ b/lib/websocket/websocket.js @@ -314,7 +314,14 @@ class WebSocket extends EventTarget { // by the length of data’s buffer in bytes. const ab = new ArrayBuffer(data.byteLength) - new data.constructor(ab).set(data) + + if (Buffer.isBuffer(data)) { + // new Buffer signature is deprecated + Buffer.from(ab).set(data) + } else { + new data.constructor(ab).set(data) + } + const value = Buffer.from(ab) const frame = new WebsocketFrameSend(value) diff --git a/test/websocket/send.js b/test/websocket/send.js new file mode 100644 index 00000000000..3fa4b342bfe --- /dev/null +++ b/test/websocket/send.js @@ -0,0 +1,35 @@ +'use strict' + +const { test } = require('tap') +const { WebSocketServer } = require('ws') +const { Blob } = require('buffer') +const { WebSocket } = require('../..') + +test('Sending > 2^16 bytes', (t) => { + t.plan(3) + + const server = new WebSocketServer({ port: 0 }) + + server.on('connection', (ws) => { + ws.on('message', (m, isBinary) => { + ws.send(m, { binary: isBinary }) + }) + }) + + const payload = Buffer.allocUnsafe(2 ** 16).fill('Hello') + + const ws = new WebSocket(`ws://localhost:${server.address().port}`) + + ws.addEventListener('open', () => { + ws.send(payload) + }) + + ws.addEventListener('message', async ({ data }) => { + t.type(data, Blob) + t.equal(data.size, payload.length) + t.same(Buffer.from(await data.arrayBuffer()), payload) + + ws.close() + server.close() + }) +})