* @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.4
()
| 573 | * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.4 |
| 574 | */ |
| 575 | #onSocketClose () { |
| 576 | // If the TCP connection was closed after the |
| 577 | // WebSocket closing handshake was completed, the WebSocket connection |
| 578 | // is said to have been closed _cleanly_. |
| 579 | const wasClean = |
| 580 | this.#handler.closeState.has(sentCloseFrameState.SENT) && |
| 581 | this.#handler.closeState.has(sentCloseFrameState.RECEIVED) |
| 582 | |
| 583 | let code = 1005 |
| 584 | let reason = '' |
| 585 | |
| 586 | const result = this.#parser?.closingInfo |
| 587 | |
| 588 | if (result && !result.error) { |
| 589 | code = result.code ?? 1005 |
| 590 | reason = result.reason |
| 591 | } |
| 592 | |
| 593 | // 1. Change the ready state to CLOSED (3). |
| 594 | this.#handler.readyState = states.CLOSED |
| 595 | |
| 596 | // 2. If the user agent was required to fail the WebSocket |
| 597 | // connection, or if the WebSocket connection was closed |
| 598 | // after being flagged as full, fire an event named error |
| 599 | // at the WebSocket object. |
| 600 | if (!this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { |
| 601 | // If _The WebSocket |
| 602 | // Connection is Closed_ and no Close control frame was received by the |
| 603 | // endpoint (such as could occur if the underlying transport connection |
| 604 | // is lost), _The WebSocket Connection Close Code_ is considered to be |
| 605 | // 1006. |
| 606 | code = 1006 |
| 607 | |
| 608 | fireEvent('error', this, (type, init) => new ErrorEvent(type, init), { |
| 609 | error: new TypeError(reason) |
| 610 | }) |
| 611 | } |
| 612 | |
| 613 | // 3. Fire an event named close at the WebSocket object, |
| 614 | // using CloseEvent, with the wasClean attribute |
| 615 | // initialized to true if the connection closed cleanly |
| 616 | // and false otherwise, the code attribute initialized to |
| 617 | // the WebSocket connection close code, and the reason |
| 618 | // attribute initialized to the result of applying UTF-8 |
| 619 | // decode without BOM to the WebSocket connection close |
| 620 | // reason. |
| 621 | // TODO: process.nextTick |
| 622 | fireEvent('close', this, (type, init) => new CloseEvent(type, init), { |
| 623 | wasClean, code, reason |
| 624 | }) |
| 625 | |
| 626 | if (channels.close.hasSubscribers) { |
| 627 | channels.close.publish({ |
| 628 | websocket: this, |
| 629 | code, |
| 630 | reason |
| 631 | }) |
| 632 | } |