From 9d15da813e619f4568ec4557dff8da01a6618612 Mon Sep 17 00:00:00 2001 From: Xia Chao <236466140+bun-unsafe@users.noreply.github.com> Date: Wed, 26 Aug 2026 18:09:04 +0800 Subject: [PATCH 1/2] fix(res.send): preserve bytes when sending DataView DataView is an ArrayBuffer view but has no .length, so the binary path produced an empty body with HTTP 200. Copy via byteOffset/byteLength. --- lib/response.js | 3 +++ test/res.send.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/lib/response.js b/lib/response.js index bc672434890..1848bbed8e5 100644 --- a/lib/response.js +++ b/lib/response.js @@ -149,6 +149,9 @@ res.send = function send(body) { if (chunk === null) { chunk = ''; } else if (ArrayBuffer.isView(chunk)) { + if (!Buffer.isBuffer(chunk)) { + chunk = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength) + } if (!this.get('Content-Type')) { this.type('bin'); } diff --git a/test/res.send.js b/test/res.send.js index f38ffde9776..51607533214 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -217,6 +217,38 @@ describe('res', function(){ .expect(200, "hey", done); }) + it('should accept DataView', function (done) { + var app = express() + var ab = new ArrayBuffer(4) + new Uint8Array(ab).set([1, 2, 3, 4]) + + app.use(function (req, res) { + res.send(new DataView(ab)) + }) + + request(app) + .get('/') + .expect('Content-Type', 'application/octet-stream') + .expect(utils.shouldHaveBody(Buffer.from([1, 2, 3, 4]))) + .end(done) + }) + + it('should honor DataView byteOffset and byteLength', function (done) { + var app = express() + var ab = new ArrayBuffer(6) + new Uint8Array(ab).set([9, 1, 2, 3, 4, 8]) + + app.use(function (req, res) { + res.send(new DataView(ab, 1, 4)) + }) + + request(app) + .get('/') + .expect('Content-Type', 'application/octet-stream') + .expect(utils.shouldHaveBody(Buffer.from([1, 2, 3, 4]))) + .end(done) + }) + it('should not override ETag', function (done) { var app = express() From f9330f13a6b0d9cd65e9974a4fbcadc514ff51c9 Mon Sep 17 00:00:00 2001 From: Xia Chao <236466140+bun-unsafe@users.noreply.github.com> Date: Mon, 31 Aug 2026 01:22:14 +0800 Subject: [PATCH 2/2] fix(res.send): limit backing-buffer copy to DataView Keep the existing typed-array path so Uint16Array and similar views still send one byte per element. Add a regression test. --- lib/response.js | 2 +- test/res.send.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/response.js b/lib/response.js index 1848bbed8e5..d2f2294ca46 100644 --- a/lib/response.js +++ b/lib/response.js @@ -149,7 +149,7 @@ res.send = function send(body) { if (chunk === null) { chunk = ''; } else if (ArrayBuffer.isView(chunk)) { - if (!Buffer.isBuffer(chunk)) { + if (typeof DataView === 'function' && chunk instanceof DataView) { chunk = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength) } if (!this.get('Content-Type')) { diff --git a/test/res.send.js b/test/res.send.js index 51607533214..169e73a7131 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -249,6 +249,21 @@ describe('res', function(){ .end(done) }) + it('should keep existing non-byte typed array payload', function (done) { + var app = express() + + app.use(function (req, res) { + res.send(new Uint16Array([0x0102, 0x0304])) + }) + + request(app) + .get('/') + .expect('Content-Type', 'application/octet-stream') + .expect('Content-Length', '2') + .expect(utils.shouldHaveBody(Buffer.from([0x02, 0x04]))) + .end(done) + }) + it('should not override ETag', function (done) { var app = express()