diff --git a/lib/web/websocket/connection.js b/lib/web/websocket/connection.js index 45f68e1de93..4bab0190731 100644 --- a/lib/web/websocket/connection.js +++ b/lib/web/websocket/connection.js @@ -7,7 +7,7 @@ const { kByteParser, kReceivedClose } = require('./symbols') -const { fireEvent, failWebsocketConnection } = require('./util') +const { fireEvent, failWebsocketConnection, hasSentClosingHandshake } = require('./util') const { channels } = require('../../core/diagnostics') const { CloseEvent } = require('./events') const { makeRequest } = require('../fetch/request') @@ -239,7 +239,7 @@ function onSocketClose () { if (result) { code = result.code ?? 1005 reason = result.reason - } else if (!ws[kSentClose]) { + } else if (!hasSentClosingHandshake(ws)) { // If _The WebSocket // Connection is Closed_ and no Close control frame was received by the // endpoint (such as could occur if the underlying transport connection diff --git a/lib/web/websocket/receiver.js b/lib/web/websocket/receiver.js index 18dc474f16e..d4440bd2ed1 100644 --- a/lib/web/websocket/receiver.js +++ b/lib/web/websocket/receiver.js @@ -4,7 +4,7 @@ const { Writable } = require('node:stream') const { parserStates, opcodes, states, emptyBuffer } = require('./constants') const { kReadyState, kSentClose, kResponse, kReceivedClose } = require('./symbols') const { channels } = require('../../core/diagnostics') -const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived } = require('./util') +const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived, hasSentClosingHandshake } = require('./util') const { WebsocketFrameSend } = require('./frame') // This code was influenced by ws released under the MIT license. @@ -104,7 +104,7 @@ class ByteParser extends Writable { this.#info.closeInfo = this.parseCloseBody(false, body) - if (!this.ws[kSentClose]) { + if (!hasSentClosingHandshake(this.ws)) { // If an endpoint receives a Close frame and did not previously send a // Close frame, the endpoint MUST send a Close frame in response. (When // sending a Close frame in response, the endpoint typically echos the diff --git a/lib/web/websocket/util.js b/lib/web/websocket/util.js index 8abe73c83e3..9f0a0c1ded5 100644 --- a/lib/web/websocket/util.js +++ b/lib/web/websocket/util.js @@ -1,6 +1,6 @@ 'use strict' -const { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = require('./symbols') +const { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL, kSentClose } = require('./symbols') const { states, opcodes } = require('./constants') const { MessageEvent, ErrorEvent } = require('./events') @@ -8,6 +8,7 @@ const { MessageEvent, ErrorEvent } = require('./events') /** * @param {import('./websocket').WebSocket} ws + * @returns {boolean} */ function isEstablished (ws) { // If the server's response is validated as provided for above, it is @@ -18,6 +19,7 @@ function isEstablished (ws) { /** * @param {import('./websocket').WebSocket} ws + * @returns {boolean} */ function isClosing (ws) { // Upon either sending or receiving a Close control frame, it is said @@ -28,6 +30,15 @@ function isClosing (ws) { /** * @param {import('./websocket').WebSocket} ws + * @returns {boolean} + */ +function hasSentClosingHandshake (ws) { + return ws[kSentClose] === true +} + +/** + * @param {import('./websocket').WebSocket} ws + * @returns {boolean} */ function isClosed (ws) { return ws[kReadyState] === states.CLOSED @@ -193,6 +204,7 @@ module.exports = { isEstablished, isClosing, isClosed, + hasSentClosingHandshake, fireEvent, isValidSubprotocol, isValidStatusCode, diff --git a/lib/web/websocket/websocket.js b/lib/web/websocket/websocket.js index 0072da48193..b4d2c82fe80 100644 --- a/lib/web/websocket/websocket.js +++ b/lib/web/websocket/websocket.js @@ -13,7 +13,7 @@ const { kSentClose, kByteParser } = require('./symbols') -const { isEstablished, isClosing, isValidSubprotocol, failWebsocketConnection, fireEvent } = require('./util') +const { isEstablished, isClosing, isValidSubprotocol, failWebsocketConnection, fireEvent, isClosed, hasSentClosingHandshake } = require('./util') const { establishWebSocketConnection } = require('./connection') const { WebsocketFrameSend } = require('./frame') const { ByteParser } = require('./receiver') @@ -184,7 +184,7 @@ class WebSocket extends EventTarget { } // 3. Run the first matching steps from the following list: - if (this[kReadyState] === WebSocket.CLOSING || this[kReadyState] === WebSocket.CLOSED) { + if (isClosing(this) || isClosed(this)) { // If this's ready state is CLOSING (2) or CLOSED (3) // Do nothing. } else if (!isEstablished(this)) { @@ -193,7 +193,7 @@ class WebSocket extends EventTarget { // to CLOSING (2). failWebsocketConnection(this, 'Connection was closed before it was established.') this[kReadyState] = WebSocket.CLOSING - } else if (!isClosing(this)) { + } else if (!(hasSentClosingHandshake(this))) { // If the WebSocket closing handshake has not yet been started // Start the WebSocket closing handshake and set this's ready // state to CLOSING (2).