샘플
ws 8.21.3: Distinguish ws package EventEmitter API and Buffer payloads from native WHATWG EventTarget WebSocket and string payloads in Node
검증된 샘플 — npm ws 8.21.3: Distinguish ws package EventEmitter API and Buffer payloads from native WHATWG EventTarget WebSocket and string payloads in Node.…
sha256:1a1d36a350a9eb2dcd345ed3b5163cee5cc2ec75783de4b1c90f8d313b012ee7
이 네트워크가 제공하는 것은 하나입니다. 빌드되는 샘플. 샌드박스에서 돌리고 서명된 영수증을 보관합니다. 등급을 매기지 않고 무엇도 보증하지 않습니다 — 같은 코드가 당신 환경에서 빌드되는지는 측정한 적이 없습니다.
통과한 계약 영수증을 낸 서로 다른 서명 키의 수입니다. 하나면 작성자 혼자이고, 둘 이상이면 다른 사람도 빌드했다는 뜻입니다. 키는 스스로 만드는 것이고 뒤에 등록된 신원이 없으므로, 세는 것은 사람이 아니라 키입니다.
MIT-0
실행 증거
선언된 환경과 서명된 실행을 분리해 두었습니다. 이 샘플이 무엇을 어디서 실행했는지 그대로 볼 수 있습니다.
- 증거 기준
- 서명된 컨트랙트 통과
- 검증 영수증
- 3
- 빌드한 서명 키
- 3
선언된 환경
node linux x64 node node npm
검증 실행 환경
| 환경 | 컨트랙트 | 단계 | 실행일 |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:ac1544ece1e22594 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-14 |
| node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-18 |
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-09-07 |
케이스
HOW- 목표
- Distinguish ws package EventEmitter API and Buffer payloads from native WHATWG EventTarget WebSocket and string payloads in Node
- 패키지
- 심벌
-
- WebSocket
- WebSocket.prototype.on
- WebSocket.prototype.ping
- WebSocket.prototype.binaryType
- WebSocketServer
- 환경
- node
- 생성일
- 2026-08-14T22:43:45Z
컨트랙트
- assert ws inherits from EventEmitter with .on() and .ping() while native WebSocket is an EventTarget without .on() or .ping()
- assert WebSocketServer exists in ws but not on globalThis
- assert ws defaults binaryType to nodebuffer while native WebSocket defaults to blob and rejects nodebuffer
- assert ws .on('message') yields a Buffer directly (data.data is undefined) while native onmessage yields MessageEvent with string event.data
- assert ws .on('close') yields Buffer reason while native onclose yields string event.reason
파일
- NOTES.md
- csx.json
- package-lock.json
- package.json
- test/contract.mjs
소스
A naive model assumes `ws` and native `WebSocket` share the same API, writing `socket.on('message', (event) => process(event.data))` or calling `socket.ping()` on native instances.
This fails loudly with `TypeError: socket.on is not a function` on native `WebSocket`, or fails silently in `ws` where `event.data` evaluates to `undefined` because `data` is passed directly as a `Buffer`.
{"case":{"caseId":"case:sha256:34f392705de3fb799e763847855644ef9f32f03bf99bda08eb93e12aceb03d62","constraints":{"runtime":"node"},"contract":["assert ws inherits from EventEmitter with .on() and .ping() while native WebSocket is an EventTarget without .on() or .ping()","assert WebSocketServer exists in ws but not on globalThis","assert ws defaults binaryType to nodebuffer while native WebSocket defaults to blob and rejects nodebuffer","assert ws .on('message') yields a Buffer directly (data.data is undefined) while native onmessage yields MessageEvent with string event.data","assert ws .on('close') yields Buffer reason while native onclose yields string event.reason"],"goal":"Distinguish ws package EventEmitter API and Buffer payloads from native WHATWG EventTarget WebSocket and string payloads in Node","kind":"HOW","packages":["pkg:npm/ws@8.21.3"],"schemaVersion":1,"symbols":["WebSocket","WebSocket.prototype.on","WebSocket.prototype.ping","WebSocket.prototype.binaryType","WebSocketServer"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/ws@8.21.3"],"schemaVersion":1,"symbols":["WebSocket","WebSocket.prototype.on","WebSocket.prototype.ping","WebSocket.prototype.binaryType","WebSocketServer"],"verifierAdapter":"node-typescript@1"}
{
"name": "sample",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sample",
"version": "1.0.0",
"dependencies": {
"ws": "8.21.3"
}
},
"node_modules/ws": {
"version": "8.21.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz",
"integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
}
}
{
"name": "sample",
"version": "1.0.0",
"type": "module",
"scripts": {
"test": "node test/contract.mjs"
},
"dependencies": {
"ws": "8.21.3"
}
}
import assert from 'node:assert/strict';
import { EventEmitter } from 'node:events';
import http from 'node:http';
import ws, { WebSocket, WebSocketServer } from 'ws';
// --- 1. Prototype & Class API Disagreements ---
// ws WebSocket inherits from EventEmitter; globalThis.WebSocket inherits from EventTarget
assert.equal(WebSocket.prototype instanceof EventEmitter, true);
assert.equal(typeof WebSocket.prototype.on, 'function');
assert.equal(typeof WebSocket.prototype.ping, 'function');
assert.equal(globalThis.WebSocket.prototype instanceof EventEmitter, false);
assert.equal(globalThis.WebSocket.prototype instanceof EventTarget, true);
assert.equal(typeof globalThis.WebSocket.prototype.on, 'undefined');
assert.equal(typeof globalThis.WebSocket.prototype.ping, 'undefined');
// WebSocketServer exists on the ws package, but not as a global
assert.equal(typeof WebSocketServer, 'function');
assert.equal(typeof globalThis.WebSocketServer, 'undefined');
// --- 2. Default binaryType Disagreements ---
const dummyWs = new WebSocket('ws://127.0.0.1:1');
dummyWs.on('error', () => {});
assert.equal(dummyWs.binaryType, 'nodebuffer');
dummyWs.close();
const dummyNative = new globalThis.WebSocket('ws://127.0.0.1:1');
dummyNative.onerror = () => {};
assert.equal(dummyNative.binaryType, 'blob');
// WHATWG specification ignores 'nodebuffer'; binaryType remains 'blob'
dummyNative.binaryType = 'nodebuffer';
assert.equal(dummyNative.binaryType, 'blob');
dummyNative.close();
// --- 3. Runtime Event Signature & Payload Disagreements ---
const server = http.createServer();
const wss = new WebSocketServer({ server });
wss.on('connection', (socket) => {
socket.on('message', (data) => {
socket.send('ack:' + data.toString());
socket.close(1000, 'server_closed');
});
});
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
const port = server.address().port;
const url = `ws://127.0.0.1:${port}`;
// ws client: .on('message') delivers Buffer directly; .on('close') delivers Buffer reason
await new Promise((resolve, reject) => {
const client = new WebSocket(url);
client.on('error', reject);
client.on('open', () => client.send('hello_ws'));
client.on('message', (data, isBinary) => {
// ws delivers (data: Buffer, isBinary: boolean); data.data is undefined
assert.equal(Buffer.isBuffer(data), true);
assert.equal(data.data, undefined);
assert.equal(isBinary, false);
assert.equal(data.toString('utf8'), 'ack:hello_ws');
});
client.on('close', (code, reason) => {
// ws delivers reason as a Buffer, NOT a string
assert.equal(code, 1000);
assert.equal(Buffer.isBuffer(reason), true);
assert.notEqual(typeof reason, 'string');
assert.equal(reason.toString('utf8'), 'server_closed');
resolve();
});
});
// native WebSocket client: onmessage receives MessageEvent; onclose receives CloseEvent
await new Promise((resolve, reject) => {
const nativeClient = new globalThis.WebSocket(url);
nativeClient.onerror = reject;
nativeClient.onopen = () => nativeClient.send('hello_native');
nativeClient.onmessage = (event) => {
// native delivers MessageEvent; payload is at event.data as string
assert.equal(Buffer.isBuffer(event), false);
assert.equal(typeof event.data, 'string');
assert.equal(event.data, 'ack:hello_native');
};
nativeClient.onclose = (event) => {
// native event.reason is a primitive string, NOT a Buffer
assert.equal(event.code, 1000);
assert.equal(typeof event.reason, 'string');
assert.equal(Buffer.isBuffer(event.reason), false);
assert.equal(event.reason, 'server_closed');
resolve();
};
});
await new Promise((resolve) => server.close(resolve));