Skip to content

Commit 1d574ae

Browse files
committed
feat: US-179 - Add ws (WebSocket) project-matrix fixture
1 parent 8927e07 commit 1d574ae

4 files changed

Lines changed: 102 additions & 0 deletions

File tree

docs/nodejs-compatibility.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ The [project-matrix test suite](https://github.com/rivet-dev/secure-exec/tree/ma
7777
| [ssh2-sftp-client](https://npmjs.com/package/ssh2-sftp-client) | Networking | SFTP client, file transfer APIs over SSH |
7878
| [pg](https://npmjs.com/package/pg) | Database | PostgreSQL client, Pool/Client classes, type parsers |
7979
| [drizzle-orm](https://npmjs.com/package/drizzle-orm) | Database | ORM schema definition, query building, ESM module graph |
80+
| [ws](https://npmjs.com/package/ws) | Networking | WebSocket client/server, HTTP upgrade, events |
8081
| [rivetkit](https://npmjs.com/package/rivetkit) | SDK | Local vendor package resolution |
8182
| crypto (builtin) | Crypto | `crypto.randomBytes`, `randomUUID`, `getRandomValues` |
8283
| fs-metadata-rename | Filesystem | `stat` metadata, `rename` semantics |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"entry": "src/index.js",
3+
"expectation": "pass"
4+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "project-matrix-ws-pass",
3+
"private": true,
4+
"type": "commonjs",
5+
"dependencies": {
6+
"ws": "8.18.0"
7+
}
8+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
"use strict";
2+
3+
const { WebSocket, WebSocketServer, Receiver, Sender } = require("ws");
4+
5+
const result = {
6+
webSocketExists: typeof WebSocket === "function",
7+
webSocketServerExists: typeof WebSocketServer === "function",
8+
receiverExists: typeof Receiver === "function",
9+
senderExists: typeof Sender === "function",
10+
};
11+
12+
// Verify WebSocket prototype methods
13+
result.wsMethods = [
14+
"close",
15+
"ping",
16+
"pong",
17+
"send",
18+
"terminate",
19+
"addEventListener",
20+
"removeEventListener",
21+
].filter((m) => typeof WebSocket.prototype[m] === "function");
22+
23+
// Verify WebSocketServer prototype methods
24+
result.wssMethods = [
25+
"close",
26+
"handleUpgrade",
27+
"shouldHandle",
28+
"address",
29+
].filter((m) => typeof WebSocketServer.prototype[m] === "function");
30+
31+
// Verify WebSocket constants
32+
result.constants = {
33+
CONNECTING: WebSocket.CONNECTING,
34+
OPEN: WebSocket.OPEN,
35+
CLOSING: WebSocket.CLOSING,
36+
CLOSED: WebSocket.CLOSED,
37+
};
38+
39+
// Test Receiver: parse a minimal text frame
40+
const receiver = new Receiver();
41+
const received = [];
42+
receiver.on("message", (data, isBinary) => {
43+
received.push({ data: data.toString(), isBinary });
44+
});
45+
receiver.on("conclude", () => {});
46+
47+
// Construct an unmasked text frame for "hello" (client-side receiver expects no mask)
48+
const payload = Buffer.from("hello");
49+
const frame = Buffer.alloc(2 + payload.length);
50+
frame[0] = 0x81; // FIN + text opcode
51+
frame[1] = payload.length; // no MASK bit
52+
payload.copy(frame, 2);
53+
receiver.write(frame);
54+
55+
result.receiverParsed = received.length === 1;
56+
result.receiverData = received.length > 0 ? received[0].data : null;
57+
result.receiverIsBinary = received.length > 0 ? received[0].isBinary : null;
58+
59+
// Test Sender: frame a text message using a mock socket with cork/uncork
60+
const chunks = [];
61+
const mockSocket = {
62+
cork() {},
63+
uncork() {},
64+
write(chunk) {
65+
chunks.push(Buffer.from(chunk));
66+
return true;
67+
},
68+
};
69+
const sender = new Sender(mockSocket, { "permessage-deflate": false });
70+
71+
sender.send(Buffer.from("world"), { fin: true, opcode: 0x01, mask: false, compress: false }, (err) => {
72+
if (err) chunks.length = 0;
73+
});
74+
75+
result.senderFramed = chunks.length > 0;
76+
if (chunks.length > 0) {
77+
const f = Buffer.concat(chunks);
78+
result.senderOpcode = f[0] & 0x0f;
79+
result.senderPayload = f.slice(2).toString();
80+
}
81+
82+
// Create a WebSocketServer instance (noServer mode, no TCP needed)
83+
const wss = new WebSocketServer({ noServer: true });
84+
result.noServerCreated = true;
85+
result.wssHasClients = wss.clients instanceof Set;
86+
result.wssClientsSize = wss.clients.size;
87+
wss.close();
88+
89+
console.log(JSON.stringify(result));

0 commit comments

Comments
 (0)