Skip to content

Commit cb2b04e

Browse files
authored
fix(ws) onSocketClose being called multiple times (#4632)
1 parent a3166d3 commit cb2b04e

File tree

3 files changed

+32
-10
lines changed

3 files changed

+32
-10
lines changed

lib/web/websocket/connection.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict'
22

33
const { uid, states, sentCloseFrameState, emptyBuffer, opcodes } = require('./constants')
4-
const { parseExtensions, isClosed, isClosing, isEstablished, validateCloseCodeAndReason } = require('./util')
4+
const { parseExtensions, isClosed, isClosing, isEstablished, isConnecting, validateCloseCodeAndReason } = require('./util')
55
const { makeRequest } = require('../fetch/request')
66
const { fetching } = require('../fetch/index')
77
const { Headers, getHeadersList } = require('../fetch/headers')
@@ -91,12 +91,6 @@ function establishWebSocketConnection (url, protocols, client, handler, options)
9191
useParallelQueue: true,
9292
dispatcher: options.dispatcher,
9393
processResponse (response) {
94-
if (response.type === 'error') {
95-
// If the WebSocket connection could not be established, it is also said
96-
// that _The WebSocket Connection is Closed_, but not _cleanly_.
97-
handler.readyState = states.CLOSED
98-
}
99-
10094
// 1. If response is a network error or its status is not 101,
10195
// fail the WebSocket connection.
10296
if (response.type === 'error' || response.status !== 101) {
@@ -299,10 +293,10 @@ function failWebsocketConnection (handler, code, reason, cause) {
299293

300294
handler.controller.abort()
301295

302-
if (!handler.socket) {
296+
if (isConnecting(handler.readyState)) {
303297
// If the connection was not established, we must still emit an 'error' and 'close' events
304298
handler.onSocketClose()
305-
} else if (handler.socket.destroyed === false) {
299+
} else if (handler.socket?.destroyed === false) {
306300
handler.socket.destroy()
307301
}
308302
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
"@matteo.collina/tspl": "^0.2.0",
114114
"@metcoder95/https-pem": "^1.0.0",
115115
"@sinonjs/fake-timers": "^12.0.0",
116-
"@types/node": "^18.19.50",
116+
"@types/node": "^20.19.22",
117117
"abort-controller": "^3.0.0",
118118
"borp": "^0.20.0",
119119
"c8": "^10.0.0",

test/websocket/issue-4628.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict'
2+
3+
const assert = require('node:assert')
4+
const { test } = require('node:test')
5+
const { WebSocket } = require('../..')
6+
7+
test('closing before connection is established should only fire error and close events once', (t) => {
8+
t.plan(2)
9+
10+
t.after(() => assert.deepStrictEqual(events, ['error', 'close']))
11+
12+
const events = []
13+
const ws = new WebSocket('wss://example.com/')
14+
15+
ws.onopen = t.assert.fail
16+
17+
ws.addEventListener('error', () => {
18+
t.assert.ok(true, 'error event fired')
19+
events.push('error')
20+
})
21+
22+
ws.addEventListener('close', () => {
23+
t.assert.ok(true, 'close event fired')
24+
events.push('close')
25+
})
26+
27+
ws.close()
28+
})

0 commit comments

Comments
 (0)