Node updated. Some todos.

This commit is contained in:
Norm Rasmussen
2024-09-23 20:52:09 -04:00
parent 8bfaca8375
commit f25622067f
2041 changed files with 124145 additions and 110445 deletions

View File

@ -1,4 +1,4 @@
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex|Readable$" }] */
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex|Readable$", "caughtErrors": "none" }] */
'use strict';
@ -14,6 +14,8 @@ const { URL } = require('url');
const PerMessageDeflate = require('./permessage-deflate');
const Receiver = require('./receiver');
const Sender = require('./sender');
const { isBlob } = require('./validation');
const {
BINARY_TYPES,
EMPTY_BUFFER,
@ -58,6 +60,7 @@ class WebSocket extends EventEmitter {
this._closeFrameSent = false;
this._closeMessage = EMPTY_BUFFER;
this._closeTimer = null;
this._errorEmitted = false;
this._extensions = {};
this._paused = false;
this._protocol = '';
@ -90,9 +93,8 @@ class WebSocket extends EventEmitter {
}
/**
* This deviates from the WHATWG interface since ws doesn't support the
* required default "blob" type (instead we define a custom "nodebuffer"
* type).
* For historical reasons, the custom "nodebuffer" type is used by the default
* instead of "blob".
*
* @type {String}
*/
@ -213,11 +215,14 @@ class WebSocket extends EventEmitter {
skipUTF8Validation: options.skipUTF8Validation
});
this._sender = new Sender(socket, this._extensions, options.generateMask);
const sender = new Sender(socket, this._extensions, options.generateMask);
this._receiver = receiver;
this._sender = sender;
this._socket = socket;
receiver[kWebSocket] = this;
sender[kWebSocket] = this;
socket[kWebSocket] = this;
receiver.on('conclude', receiverOnConclude);
@ -227,6 +232,8 @@ class WebSocket extends EventEmitter {
receiver.on('ping', receiverOnPing);
receiver.on('pong', receiverOnPong);
sender.onerror = senderOnError;
//
// These methods may not be available if `socket` is just a `Duplex`.
//
@ -322,13 +329,7 @@ class WebSocket extends EventEmitter {
}
});
//
// Specify a timeout for the closing handshake to complete.
//
this._closeTimer = setTimeout(
this._socket.destroy.bind(this._socket),
closeTimeout
);
setCloseTimer(this);
}
/**
@ -623,7 +624,7 @@ module.exports = WebSocket;
* @param {(String|URL)} address The URL to which to connect
* @param {Array} protocols The subprotocols
* @param {Object} [options] Connection options
* @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether any
* @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether any
* of the `'message'`, `'ping'`, and `'pong'` events can be emitted multiple
* times in the same tick
* @param {Boolean} [options.autoPong=true] Specifies whether or not to
@ -652,7 +653,7 @@ module.exports = WebSocket;
*/
function initAsClient(websocket, address, protocols, options) {
const opts = {
allowSynchronousEvents: false,
allowSynchronousEvents: true,
autoPong: true,
protocolVersion: protocolVersions[1],
maxPayload: 100 * 1024 * 1024,
@ -661,7 +662,6 @@ function initAsClient(websocket, address, protocols, options) {
followRedirects: false,
maxRedirects: 10,
...options,
createConnection: undefined,
socketPath: undefined,
hostname: undefined,
protocol: undefined,
@ -732,7 +732,8 @@ function initAsClient(websocket, address, protocols, options) {
const protocolSet = new Set();
let perMessageDeflate;
opts.createConnection = isSecure ? tlsConnect : netConnect;
opts.createConnection =
opts.createConnection || (isSecure ? tlsConnect : netConnect);
opts.defaultPort = opts.defaultPort || defaultPort;
opts.port = parsedUrl.port || defaultPort;
opts.host = parsedUrl.hostname.startsWith('[')
@ -928,7 +929,9 @@ function initAsClient(websocket, address, protocols, options) {
req = websocket._req = null;
if (res.headers.upgrade.toLowerCase() !== 'websocket') {
const upgrade = res.headers.upgrade;
if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {
abortHandshake(websocket, socket, 'Invalid Upgrade header');
return;
}
@ -1030,6 +1033,11 @@ function initAsClient(websocket, address, protocols, options) {
*/
function emitErrorAndClose(websocket, err) {
websocket._readyState = WebSocket.CLOSING;
//
// The following assignment is practically useless and is done only for
// consistency.
//
websocket._errorEmitted = true;
websocket.emit('error', err);
websocket.emitClose();
}
@ -1110,7 +1118,7 @@ function abortHandshake(websocket, stream, message) {
*/
function sendAfterClose(websocket, data, cb) {
if (data) {
const length = toBuffer(data).length;
const length = isBlob(data) ? data.size : toBuffer(data).length;
//
// The `_bufferedAmount` property is used only when the peer is a client and
@ -1186,7 +1194,10 @@ function receiverOnError(err) {
websocket.close(err[kStatusCode]);
}
websocket.emit('error', err);
if (!websocket._errorEmitted) {
websocket._errorEmitted = true;
websocket.emit('error', err);
}
}
/**
@ -1242,6 +1253,47 @@ function resume(stream) {
stream.resume();
}
/**
* The `Sender` error event handler.
*
* @param {Error} The error
* @private
*/
function senderOnError(err) {
const websocket = this[kWebSocket];
if (websocket.readyState === WebSocket.CLOSED) return;
if (websocket.readyState === WebSocket.OPEN) {
websocket._readyState = WebSocket.CLOSING;
setCloseTimer(websocket);
}
//
// `socket.end()` is used instead of `socket.destroy()` to allow the other
// peer to finish sending queued data. There is no need to set a timer here
// because `CLOSING` means that it is already set or not needed.
//
this._socket.end();
if (!websocket._errorEmitted) {
websocket._errorEmitted = true;
websocket.emit('error', err);
}
}
/**
* Set a timer to destroy the underlying raw socket of a WebSocket.
*
* @param {WebSocket} websocket The WebSocket instance
* @private
*/
function setCloseTimer(websocket) {
websocket._closeTimer = setTimeout(
websocket._socket.destroy.bind(websocket._socket),
closeTimeout
);
}
/**
* The listener of the socket `'close'` event.
*