Conversation
|
Review requested:
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #66335 +/- ##
==========================================
- Coverage 90.36% 90.35% -0.02%
==========================================
Files 792 792
Lines 275398 275578 +180
Branches 52776 52819 +43
==========================================
+ Hits 248877 249011 +134
- Misses 16937 16976 +39
- Partials 9584 9591 +7
🚀 New features to boost your workflow:
|
|
First off: I like it! (LGTM) Question: unmask is just |
|
I kept it as a separate function to keep the API shape the same as bufferutil. Happy to coalesce but would like to see what @lpinca thinks |
|
The discussion about whether to add this feature to the Node.js core dates back to 2015 (#1010 (comment), #1010 (comment), #1202) and I think it would be a valuable addition. Every WebSocket implementation would benefit from this just like I don't have a strong option about Some tests are hard to follow. |
|
I think there's value in matching the current API so that there's just less for someone migrating from |
03fe080 to
ae2229e
Compare
ae2229e to
dc5a1d7
Compare
|
As a consumer of this API I would be extremely surprised to find that it requires the mask to be exactly 4 bytes. Nothing about the name If it's only a specialized utility for WebSocket, I don't think |
Fair enough, but even though I'm not sure that exposing it via |
|
Unrelated, is AI assistance disclosure needed? It seems it was used at least for tests. Feel free to ignore this comment if I'm wrong. |
... Can it? That name is fairly obvious about what it does, and it's useful for a wide variety of things. Not so here. Anyway I'd also be ok with simply calling it something that makes it clearer that this is not actually a generic mask utility. |
|
I actually don't think it needs to be specific to WebSocket, it's just that currently it's generally the only usage and the impl is optimized for that. It could be made generically useful if someone came up with the usecase. I think, tho, it likely needs to be on either
Ah, totally forgot to add it. Yeah, the AI agent did the tests and the docs. |
|
Took the "author ready" and "commit queue" labels back off while we figure out the naming and where to expose it. To be clear, I'm ambivalent on the color of this particular bikeshed so more than happy to go with whatever people dislike the least :-) |
Add buffer.mask(source, mask, output[, offset[, length]]) and buffer.unmask(buffer, mask), which XOR data with a repeating 4-byte key. This is the masking that WebSocket clients apply to every frame they send (RFC 6455, Section 5.3), and that servers undo on every frame they receive. Userland WebSocket implementations do this either with a byte-by-byte JS loop (undici, and ws without optional dependencies) or with the bufferutil native addon. bufferutil is installed for only about 3% of ws downloads and has no linux-arm64 prebuild, so almost all users run the JS loop. The signature matches bufferutil, so existing users can switch with a feature check, as ws did for buffer.isUtf8(). The implementation uses a V8 fast API call and processes 8-byte words, which the compiler vectorizes. It handles overlapping source and output views, and treats every view type as raw bytes. It is about 20x faster than the JS loop at 1 KiB and 40x faster at 64 KiB, and faster than bufferutil at every size from 32 bytes up. Signed-off-by: James M Snell <jasnell@gmail.com> Assisted-by: Opencode
dc5a1d7 to
3c3b67f
Compare
I agree, my point is that it is exposed via Using |
|
|
That would actually be a much worse name, since a WebSocketFrame consists of much more stuff. There’s a whole header section with all kinds of flags (type, flags, size, extended size, whether it is actually masked). So that would be quite misleading. |
|
I did almost immediately edit from |
|
If it's going to be |
|
wfm |
Add buffer.mask(source, mask, output[, offset[, length]]) and buffer.unmask(buffer, mask), which XOR data with a repeating 4-byte key. This is the masking that WebSocket clients apply to every frame they send (RFC 6455, Section 5.3), and that servers undo on every frame they receive.
undiciandws(without optional dependencies) both need mask and unmask. Thebufferutilnative addon makes it faster but it's an optional dependency that appears to only be installed withwsabout 3% of the time. So almost all users run the JS loop.Since we're shipping
undiciandWebSocketnow, it's worth making this faster.I put this on
bufferbecause it's an operation on a buffer but it's likely only useful forWebSocket, so we could just as easily expose it viahttp. I have no particular preference.For inputs < 24, the JS loop is still faster because we hit the floor of the C++ binding, even with fast apis. There's not much we can do about that. At larger sizes the perf boost is significant.