Skip to content

Commit d9b8954

Browse files
authored
[fix] Change the ready state after validating the arguments (#2337)
`Sender.prototype.close()` validates `code` and `data` and throws if they are invalid. Do not change the ready state before it returns, otherwise the state is set to `CLOSING` with no close frame sent and no close timer set, and any subsequent `WebSocket.prototype.close()` call becomes a noop because the state is already `CLOSING`.
1 parent c791e70 commit d9b8954

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

lib/websocket.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,6 @@ class WebSocket extends EventEmitter {
318318
return;
319319
}
320320

321-
this._readyState = WebSocket.CLOSING;
322321
this._sender.close(code, data, !this._isServer, (err) => {
323322
//
324323
// This error is handled by the `'error'` listener on the socket. We only
@@ -336,6 +335,7 @@ class WebSocket extends EventEmitter {
336335
}
337336
});
338337

338+
this._readyState = WebSocket.CLOSING;
339339
setCloseTimer(this);
340340
}
341341

test/websocket.test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3451,6 +3451,32 @@ describe('WebSocket', () => {
34513451
wss.on('connection', (ws) => ws.close());
34523452
});
34533453

3454+
it('keeps `readyState` unchanged if the arguments are invalid', (done) => {
3455+
const wss = new WebSocket.Server({ port: 0 }, () => {
3456+
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
3457+
3458+
ws.on('open', () => {
3459+
assert.throws(
3460+
() => ws.close(1000, 'a'.repeat(124)),
3461+
/^RangeError: The message must not be greater than 123 bytes$/
3462+
);
3463+
3464+
//
3465+
// The ready state must not be changed to `CLOSING` and a subsequent
3466+
// valid `websocket.close()` call must still work.
3467+
//
3468+
assert.strictEqual(ws.readyState, WebSocket.OPEN);
3469+
3470+
ws.on('close', (code) => {
3471+
assert.strictEqual(code, 1000);
3472+
wss.close(done);
3473+
});
3474+
3475+
ws.close(1000, 'ok');
3476+
});
3477+
});
3478+
});
3479+
34543480
it('sets a timer for the closing handshake to complete', (done) => {
34553481
const wss = new WebSocket.Server({ port: 0 }, () => {
34563482
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

0 commit comments

Comments
 (0)