Skip to content

fix(res.send): preserve bytes when sending DataView - #7433

Open
bun-unsafe wants to merge 2 commits into
expressjs:masterfrom
bun-unsafe:fix/res-send-dataview
Open

fix(res.send): preserve bytes when sending DataView#7433
bun-unsafe wants to merge 2 commits into
expressjs:masterfrom
bun-unsafe:fix/res-send-dataview

Conversation

@bun-unsafe

Copy link
Copy Markdown

res.send(new DataView(buffer)) returned HTTP 200 with Content-Length: 0 and an empty body. res.send(new Uint8Array(buffer)) on the same bytes sent the payload.

ArrayBuffer.isView is true for DataView, so the value is treated as binary. The length path then uses chunk.length / Buffer.from(chunk, encoding). DataView has no .length (only .byteLength), and Buffer.from(dataView) is an empty Buffer.

This copies non-Buffer views with Buffer.from(view.buffer, view.byteOffset, view.byteLength). Existing Buffer and Uint8Array behavior is unchanged.

This does not change bare ArrayBuffer (still sent as {} JSON). That is covered by #7362.

Tests: test/res.send.js for a full DataView and a sliced 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.
kilisamemarisaaa

This comment was marked as outdated.

@kilisamemarisaaa kilisamemarisaaa left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting correction for my previous review: the CLI escaped its Markdown and truncated the important comparison. The complete finding is below.

I reproduced the DataView bug and confirmed that the two new tests pass. The full suite also passes (1,262 tests) and lint is clean on Node 24.12.0.

There is one compatibility issue with applying this conversion to every non-Buffer view. Buffer.from(typedArray) uses the typed array's elements, while Buffer.from(view.buffer, view.byteOffset, view.byteLength) uses all backing bytes. For example:

res.send(new Uint16Array([0x0102, 0x0304]))

On Windows x64 / Node 24.12.0, Express 5.2.1 sends Content-Length: 2 with hex body 0204. This PR head sends Content-Length: 4 with hex body 02010403. That changes existing observable behavior for a view unrelated to the DataView bug.

Could the backing-buffer conversion be scoped to DataView (or otherwise preserve the existing typed-array path), with a regression test for a non-Uint8Array typed array? The current DataView tests can remain as-is.

Keep the existing typed-array path so Uint16Array and similar views
still send one byte per element. Add a regression test.
@bun-unsafe

Copy link
Copy Markdown
Author

recheck

@kilisamemarisaaa kilisamemarisaaa left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rechecked at f9330f13a6b0d9cd65e9974a4fbcadc514ff51c9. Scoping the backing-buffer conversion to DataView fully addresses my earlier compatibility concern: DataView payloads now preserve their byte ranges, while Uint16Array retains the existing two-byte 0204 response.

Validation on Windows with Node 24.12.0:

  • test/res.send.js: 78/78 passed
  • full npm test: 1,263/1,263 passed
  • npm run lint: passed

The added non-byte typed-array regression test covers the behavior from the review. I found no remaining blocking issue in this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants