Skip to content

feat: return UTF-8 buffers from Node render#402

Merged
mohamedmansour merged 1 commit into
mainfrom
banl/node-addon-optimize
Jul 24, 2026
Merged

feat: return UTF-8 buffers from Node render#402
mohamedmansour merged 1 commit into
mainfrom
banl/node-addon-optimize

Conversation

@Qusic

@Qusic Qusic commented Jul 24, 2026

Copy link
Copy Markdown
Member

Summary

  • Make Protocol.render() return the canonical UTF-8 Node Buffer; remove the separate renderBuffer() API.
  • Reuse the existing decoded protocol, handler/plugin, and rendering pipeline; renderStream() remains unchanged.
  • Update Node callers, tests, examples, documentation, and benchmark semantics for the breaking return-type change.

Call .toString("utf8") explicitly when JavaScript string operations are required.

Local benchmark

The old String and new Buffer implementations were measured in the same release run on Linux x64 with Node 24.18.0. Canonical render() now uses the measured Buffer path.

The Buffer path avoids creating a V8 JavaScript string and lets napi-rs expose the rendered Rust allocation as an external Buffer, so the benefit grows with output size.

Contacts HTML bytes String P50 Buffer P50 Change
10 33,130 77.44 µs 77.83 µs ~0%
100 245,464 866.78 µs 770.04 µs 11.2% faster
1,000 2,370,550 9.08 ms 7.20 ms 20.7% faster

Output bytes are identical across buffered and streaming paths.

Validation

  • cargo xtask check
  • cargo xtask bench node-addon --baseline before-opt

Copilot AI review requested due to automatic review settings July 24, 2026 02:22

Copilot AI 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.

Pull request overview

This PR extends WebUI’s Node runtime rendering surface with a buffered API (Protocol.renderBuffer()) that returns UTF-8 output as a Node.js Buffer, enabling HTTP responses to write bytes directly without creating a JavaScript string. It reuses the existing protocol decode/index and render pipeline, keeps the existing string and streaming APIs unchanged, and updates docs/examples/benchmarks to validate equivalence and measure wins.

Changes:

  • Add Node-facing Protocol.renderBuffer() (TS wrapper + native addon export) returning a Buffer.
  • Add equivalence tests (UTF-8 buffer vs string) and extend the Node addon benchmark runner/README to include the new render path.
  • Update docs (DESIGN.md, package README, integrations guide, and examples) to document the new API and recommended usage.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/webui/test/integration.test.ts Adds an integration test asserting renderBuffer() returns UTF-8 bytes equivalent to render().
packages/webui/src/index.ts Adds the public Protocol.renderBuffer() wrapper and factors JSON serialization into serializeState().
packages/webui/README.md Documents protocol.renderBuffer() and updates wording around protocol ownership/byte-per-request APIs.
examples/integration/node/index.js Switches the example to emit a Buffer via renderBuffer() to stdout.
examples/integration/node-addon-bench/README.md Documents the new benchmark row and updates output-equivalence validation description.
examples/integration/node-addon-bench/bench.mjs Adds equivalence checks for buffer output and includes a new benchmark case for renderBuffer().
docs/guide/integrations/node.md Updates Node integration docs to recommend renderBuffer() for buffered HTTP writes and adds it to the API table/example.
DESIGN.md Updates the Node package API contract to include Protocol.renderBuffer() semantics.
crates/webui-node/src/lib.rs Implements the native render_buffer N-API method and adds a Rust-side equivalence test.
BENCHMARKS.md Updates node-addon benchmark description to include string vs buffer render paths.

Comment thread crates/webui-node/src/lib.rs Outdated
Copilot AI review requested due to automatic review settings July 24, 2026 02:46
@Qusic
Qusic force-pushed the banl/node-addon-optimize branch from 684f2ee to 8e81627 Compare July 24, 2026 02:46

Copilot AI 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.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Copy link
Copy Markdown
Contributor

Thanks for measuring this. I’m fine with a breaking change here, and I’d prefer the API to have one canonical buffered render method rather than both render() and renderBuffer() differing only by return representation.

Please change Protocol.render() to return a UTF-8 Buffer and remove Protocol.renderBuffer(). The byte-oriented result is the correct default for SSR/HTTP output and is equal or faster in these benchmarks; callers that specifically need a JavaScript string can explicitly use .toString("utf8"). renderStream() should remain separate because it has different streaming semantics.

Please update the docs, examples, tests, and benchmark naming to reflect that API.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Qusic
Qusic force-pushed the banl/node-addon-optimize branch from 8e81627 to 476d40f Compare July 24, 2026 18:12
Copilot AI review requested due to automatic review settings July 24, 2026 18:12
@Qusic Qusic changed the title feat: add UTF-8 buffer rendering for Node feat: return UTF-8 buffers from Node render Jul 24, 2026

Copilot AI 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.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

@mohamedmansour
mohamedmansour merged commit 0970cd4 into main Jul 24, 2026
22 checks passed
@mohamedmansour
mohamedmansour deleted the banl/node-addon-optimize branch July 24, 2026 21:04
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.

3 participants