UNPKG

@hyperlane-xyz/cli

Version:

A command-line utility for common Hyperlane operations

1,998 lines (1,712 loc) 132 kB
export const id = 214; export const ids = [214]; export const modules = { /***/ 76302: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const { EMPTY_BUFFER } = __webpack_require__(74306); const FastBuffer = Buffer[Symbol.species]; /** * Merges an array of buffers into a new buffer. * * @param {Buffer[]} list The array of buffers to concat * @param {Number} totalLength The total length of buffers in the list * @return {Buffer} The resulting buffer * @public */ function concat(list, totalLength) { if (list.length === 0) return EMPTY_BUFFER; if (list.length === 1) return list[0]; const target = Buffer.allocUnsafe(totalLength); let offset = 0; for (let i = 0; i < list.length; i++) { const buf = list[i]; target.set(buf, offset); offset += buf.length; } if (offset < totalLength) { return new FastBuffer(target.buffer, target.byteOffset, offset); } return target; } /** * Masks a buffer using the given mask. * * @param {Buffer} source The buffer to mask * @param {Buffer} mask The mask to use * @param {Buffer} output The buffer where to store the result * @param {Number} offset The offset at which to start writing * @param {Number} length The number of bytes to mask. * @public */ function _mask(source, mask, output, offset, length) { for (let i = 0; i < length; i++) { output[offset + i] = source[i] ^ mask[i & 3]; } } /** * Unmasks a buffer using the given mask. * * @param {Buffer} buffer The buffer to unmask * @param {Buffer} mask The mask to use * @public */ function _unmask(buffer, mask) { for (let i = 0; i < buffer.length; i++) { buffer[i] ^= mask[i & 3]; } } /** * Converts a buffer to an `ArrayBuffer`. * * @param {Buffer} buf The buffer to convert * @return {ArrayBuffer} Converted buffer * @public */ function toArrayBuffer(buf) { if (buf.length === buf.buffer.byteLength) { return buf.buffer; } return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length); } /** * Converts `data` to a `Buffer`. * * @param {*} data The data to convert * @return {Buffer} The buffer * @throws {TypeError} * @public */ function toBuffer(data) { toBuffer.readOnly = true; if (Buffer.isBuffer(data)) return data; let buf; if (data instanceof ArrayBuffer) { buf = new FastBuffer(data); } else if (ArrayBuffer.isView(data)) { buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength); } else { buf = Buffer.from(data); toBuffer.readOnly = false; } return buf; } module.exports = { concat, mask: _mask, toArrayBuffer, toBuffer, unmask: _unmask }; /* istanbul ignore else */ if (!process.env.WS_NO_BUFFER_UTIL) { try { const bufferUtil = __webpack_require__(50784); module.exports.mask = function (source, mask, output, offset, length) { if (length < 48) _mask(source, mask, output, offset, length); else bufferUtil.mask(source, mask, output, offset, length); }; module.exports.unmask = function (buffer, mask) { if (buffer.length < 32) _unmask(buffer, mask); else bufferUtil.unmask(buffer, mask); }; } catch (e) { // Continue regardless of the error. } } /***/ }), /***/ 74306: /***/ ((module) => { const BINARY_TYPES = ['nodebuffer', 'arraybuffer', 'fragments']; const hasBlob = typeof Blob !== 'undefined'; if (hasBlob) BINARY_TYPES.push('blob'); module.exports = { BINARY_TYPES, EMPTY_BUFFER: Buffer.alloc(0), GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', hasBlob, kForOnEventAttribute: Symbol('kIsForOnEventAttribute'), kListener: Symbol('kListener'), kStatusCode: Symbol('status-code'), kWebSocket: Symbol('websocket'), NOOP: () => {} }; /***/ }), /***/ 69441: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const { kForOnEventAttribute, kListener } = __webpack_require__(74306); const kCode = Symbol('kCode'); const kData = Symbol('kData'); const kError = Symbol('kError'); const kMessage = Symbol('kMessage'); const kReason = Symbol('kReason'); const kTarget = Symbol('kTarget'); const kType = Symbol('kType'); const kWasClean = Symbol('kWasClean'); /** * Class representing an event. */ class Event { /** * Create a new `Event`. * * @param {String} type The name of the event * @throws {TypeError} If the `type` argument is not specified */ constructor(type) { this[kTarget] = null; this[kType] = type; } /** * @type {*} */ get target() { return this[kTarget]; } /** * @type {String} */ get type() { return this[kType]; } } Object.defineProperty(Event.prototype, 'target', { enumerable: true }); Object.defineProperty(Event.prototype, 'type', { enumerable: true }); /** * Class representing a close event. * * @extends Event */ class CloseEvent extends Event { /** * Create a new `CloseEvent`. * * @param {String} type The name of the event * @param {Object} [options] A dictionary object that allows for setting * attributes via object members of the same name * @param {Number} [options.code=0] The status code explaining why the * connection was closed * @param {String} [options.reason=''] A human-readable string explaining why * the connection was closed * @param {Boolean} [options.wasClean=false] Indicates whether or not the * connection was cleanly closed */ constructor(type, options = {}) { super(type); this[kCode] = options.code === undefined ? 0 : options.code; this[kReason] = options.reason === undefined ? '' : options.reason; this[kWasClean] = options.wasClean === undefined ? false : options.wasClean; } /** * @type {Number} */ get code() { return this[kCode]; } /** * @type {String} */ get reason() { return this[kReason]; } /** * @type {Boolean} */ get wasClean() { return this[kWasClean]; } } Object.defineProperty(CloseEvent.prototype, 'code', { enumerable: true }); Object.defineProperty(CloseEvent.prototype, 'reason', { enumerable: true }); Object.defineProperty(CloseEvent.prototype, 'wasClean', { enumerable: true }); /** * Class representing an error event. * * @extends Event */ class ErrorEvent extends Event { /** * Create a new `ErrorEvent`. * * @param {String} type The name of the event * @param {Object} [options] A dictionary object that allows for setting * attributes via object members of the same name * @param {*} [options.error=null] The error that generated this event * @param {String} [options.message=''] The error message */ constructor(type, options = {}) { super(type); this[kError] = options.error === undefined ? null : options.error; this[kMessage] = options.message === undefined ? '' : options.message; } /** * @type {*} */ get error() { return this[kError]; } /** * @type {String} */ get message() { return this[kMessage]; } } Object.defineProperty(ErrorEvent.prototype, 'error', { enumerable: true }); Object.defineProperty(ErrorEvent.prototype, 'message', { enumerable: true }); /** * Class representing a message event. * * @extends Event */ class MessageEvent extends Event { /** * Create a new `MessageEvent`. * * @param {String} type The name of the event * @param {Object} [options] A dictionary object that allows for setting * attributes via object members of the same name * @param {*} [options.data=null] The message content */ constructor(type, options = {}) { super(type); this[kData] = options.data === undefined ? null : options.data; } /** * @type {*} */ get data() { return this[kData]; } } Object.defineProperty(MessageEvent.prototype, 'data', { enumerable: true }); /** * This provides methods for emulating the `EventTarget` interface. It's not * meant to be used directly. * * @mixin */ const EventTarget = { /** * Register an event listener. * * @param {String} type A string representing the event type to listen for * @param {(Function|Object)} handler The listener to add * @param {Object} [options] An options object specifies characteristics about * the event listener * @param {Boolean} [options.once=false] A `Boolean` indicating that the * listener should be invoked at most once after being added. If `true`, * the listener would be automatically removed when invoked. * @public */ addEventListener(type, handler, options = {}) { for (const listener of this.listeners(type)) { if ( !options[kForOnEventAttribute] && listener[kListener] === handler && !listener[kForOnEventAttribute] ) { return; } } let wrapper; if (type === 'message') { wrapper = function onMessage(data, isBinary) { const event = new MessageEvent('message', { data: isBinary ? data : data.toString() }); event[kTarget] = this; callListener(handler, this, event); }; } else if (type === 'close') { wrapper = function onClose(code, message) { const event = new CloseEvent('close', { code, reason: message.toString(), wasClean: this._closeFrameReceived && this._closeFrameSent }); event[kTarget] = this; callListener(handler, this, event); }; } else if (type === 'error') { wrapper = function onError(error) { const event = new ErrorEvent('error', { error, message: error.message }); event[kTarget] = this; callListener(handler, this, event); }; } else if (type === 'open') { wrapper = function onOpen() { const event = new Event('open'); event[kTarget] = this; callListener(handler, this, event); }; } else { return; } wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute]; wrapper[kListener] = handler; if (options.once) { this.once(type, wrapper); } else { this.on(type, wrapper); } }, /** * Remove an event listener. * * @param {String} type A string representing the event type to remove * @param {(Function|Object)} handler The listener to remove * @public */ removeEventListener(type, handler) { for (const listener of this.listeners(type)) { if (listener[kListener] === handler && !listener[kForOnEventAttribute]) { this.removeListener(type, listener); break; } } } }; module.exports = { CloseEvent, ErrorEvent, Event, EventTarget, MessageEvent }; /** * Call an event listener * * @param {(Function|Object)} listener The listener to call * @param {*} thisArg The value to use as `this`` when calling the listener * @param {Event} event The event to pass to the listener * @private */ function callListener(listener, thisArg, event) { if (typeof listener === 'object' && listener.handleEvent) { listener.handleEvent.call(listener, event); } else { listener.call(thisArg, event); } } /***/ }), /***/ 97674: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const { tokenChars } = __webpack_require__(51076); /** * Adds an offer to the map of extension offers or a parameter to the map of * parameters. * * @param {Object} dest The map of extension offers or parameters * @param {String} name The extension or parameter name * @param {(Object|Boolean|String)} elem The extension parameters or the * parameter value * @private */ function push(dest, name, elem) { if (dest[name] === undefined) dest[name] = [elem]; else dest[name].push(elem); } /** * Parses the `Sec-WebSocket-Extensions` header into an object. * * @param {String} header The field value of the header * @return {Object} The parsed object * @public */ function parse(header) { const offers = Object.create(null); let params = Object.create(null); let mustUnescape = false; let isEscaping = false; let inQuotes = false; let extensionName; let paramName; let start = -1; let code = -1; let end = -1; let i = 0; for (; i < header.length; i++) { code = header.charCodeAt(i); if (extensionName === undefined) { if (end === -1 && tokenChars[code] === 1) { if (start === -1) start = i; } else if ( i !== 0 && (code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */ ) { if (end === -1 && start !== -1) end = i; } else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) { if (start === -1) { throw new SyntaxError(`Unexpected character at index ${i}`); } if (end === -1) end = i; const name = header.slice(start, end); if (code === 0x2c) { push(offers, name, params); params = Object.create(null); } else { extensionName = name; } start = end = -1; } else { throw new SyntaxError(`Unexpected character at index ${i}`); } } else if (paramName === undefined) { if (end === -1 && tokenChars[code] === 1) { if (start === -1) start = i; } else if (code === 0x20 || code === 0x09) { if (end === -1 && start !== -1) end = i; } else if (code === 0x3b || code === 0x2c) { if (start === -1) { throw new SyntaxError(`Unexpected character at index ${i}`); } if (end === -1) end = i; push(params, header.slice(start, end), true); if (code === 0x2c) { push(offers, extensionName, params); params = Object.create(null); extensionName = undefined; } start = end = -1; } else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) { paramName = header.slice(start, i); start = end = -1; } else { throw new SyntaxError(`Unexpected character at index ${i}`); } } else { // // The value of a quoted-string after unescaping must conform to the // token ABNF, so only token characters are valid. // Ref: https://tools.ietf.org/html/rfc6455#section-9.1 // if (isEscaping) { if (tokenChars[code] !== 1) { throw new SyntaxError(`Unexpected character at index ${i}`); } if (start === -1) start = i; else if (!mustUnescape) mustUnescape = true; isEscaping = false; } else if (inQuotes) { if (tokenChars[code] === 1) { if (start === -1) start = i; } else if (code === 0x22 /* '"' */ && start !== -1) { inQuotes = false; end = i; } else if (code === 0x5c /* '\' */) { isEscaping = true; } else { throw new SyntaxError(`Unexpected character at index ${i}`); } } else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) { inQuotes = true; } else if (end === -1 && tokenChars[code] === 1) { if (start === -1) start = i; } else if (start !== -1 && (code === 0x20 || code === 0x09)) { if (end === -1) end = i; } else if (code === 0x3b || code === 0x2c) { if (start === -1) { throw new SyntaxError(`Unexpected character at index ${i}`); } if (end === -1) end = i; let value = header.slice(start, end); if (mustUnescape) { value = value.replace(/\\/g, ''); mustUnescape = false; } push(params, paramName, value); if (code === 0x2c) { push(offers, extensionName, params); params = Object.create(null); extensionName = undefined; } paramName = undefined; start = end = -1; } else { throw new SyntaxError(`Unexpected character at index ${i}`); } } } if (start === -1 || inQuotes || code === 0x20 || code === 0x09) { throw new SyntaxError('Unexpected end of input'); } if (end === -1) end = i; const token = header.slice(start, end); if (extensionName === undefined) { push(offers, token, params); } else { if (paramName === undefined) { push(params, token, true); } else if (mustUnescape) { push(params, paramName, token.replace(/\\/g, '')); } else { push(params, paramName, token); } push(offers, extensionName, params); } return offers; } /** * Builds the `Sec-WebSocket-Extensions` header field value. * * @param {Object} extensions The map of extensions and parameters to format * @return {String} A string representing the given object * @public */ function format(extensions) { return Object.keys(extensions) .map((extension) => { let configurations = extensions[extension]; if (!Array.isArray(configurations)) configurations = [configurations]; return configurations .map((params) => { return [extension] .concat( Object.keys(params).map((k) => { let values = params[k]; if (!Array.isArray(values)) values = [values]; return values .map((v) => (v === true ? k : `${k}=${v}`)) .join('; '); }) ) .join('; '); }) .join(', '); }) .join(', '); } module.exports = { format, parse }; /***/ }), /***/ 8459: /***/ ((module) => { const kDone = Symbol('kDone'); const kRun = Symbol('kRun'); /** * A very simple job queue with adjustable concurrency. Adapted from * https://github.com/STRML/async-limiter */ class Limiter { /** * Creates a new `Limiter`. * * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed * to run concurrently */ constructor(concurrency) { this[kDone] = () => { this.pending--; this[kRun](); }; this.concurrency = concurrency || Infinity; this.jobs = []; this.pending = 0; } /** * Adds a job to the queue. * * @param {Function} job The job to run * @public */ add(job) { this.jobs.push(job); this[kRun](); } /** * Removes a job from the queue and runs it if possible. * * @private */ [kRun]() { if (this.pending === this.concurrency) return; if (this.jobs.length) { const job = this.jobs.shift(); this.pending++; job(this[kDone]); } } } module.exports = Limiter; /***/ }), /***/ 8599: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const zlib = __webpack_require__(43106); const bufferUtil = __webpack_require__(76302); const Limiter = __webpack_require__(8459); const { kStatusCode } = __webpack_require__(74306); const FastBuffer = Buffer[Symbol.species]; const TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]); const kPerMessageDeflate = Symbol('permessage-deflate'); const kTotalLength = Symbol('total-length'); const kCallback = Symbol('callback'); const kBuffers = Symbol('buffers'); const kError = Symbol('error'); // // We limit zlib concurrency, which prevents severe memory fragmentation // as documented in https://github.com/nodejs/node/issues/8871#issuecomment-250915913 // and https://github.com/websockets/ws/issues/1202 // // Intentionally global; it's the global thread pool that's an issue. // let zlibLimiter; /** * permessage-deflate implementation. */ class PerMessageDeflate { /** * Creates a PerMessageDeflate instance. * * @param {Object} [options] Configuration options * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support * for, or request, a custom client window size * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/ * acknowledge disabling of client context takeover * @param {Number} [options.concurrencyLimit=10] The number of concurrent * calls to zlib * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the * use of a custom server window size * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept * disabling of server context takeover * @param {Number} [options.threshold=1024] Size (in bytes) below which * messages should not be compressed if context takeover is disabled * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on * deflate * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on * inflate * @param {Boolean} [isServer=false] Create the instance in either server or * client mode * @param {Number} [maxPayload=0] The maximum allowed message length */ constructor(options, isServer, maxPayload) { this._maxPayload = maxPayload | 0; this._options = options || {}; this._threshold = this._options.threshold !== undefined ? this._options.threshold : 1024; this._isServer = !!isServer; this._deflate = null; this._inflate = null; this.params = null; if (!zlibLimiter) { const concurrency = this._options.concurrencyLimit !== undefined ? this._options.concurrencyLimit : 10; zlibLimiter = new Limiter(concurrency); } } /** * @type {String} */ static get extensionName() { return 'permessage-deflate'; } /** * Create an extension negotiation offer. * * @return {Object} Extension parameters * @public */ offer() { const params = {}; if (this._options.serverNoContextTakeover) { params.server_no_context_takeover = true; } if (this._options.clientNoContextTakeover) { params.client_no_context_takeover = true; } if (this._options.serverMaxWindowBits) { params.server_max_window_bits = this._options.serverMaxWindowBits; } if (this._options.clientMaxWindowBits) { params.client_max_window_bits = this._options.clientMaxWindowBits; } else if (this._options.clientMaxWindowBits == null) { params.client_max_window_bits = true; } return params; } /** * Accept an extension negotiation offer/response. * * @param {Array} configurations The extension negotiation offers/reponse * @return {Object} Accepted configuration * @public */ accept(configurations) { configurations = this.normalizeParams(configurations); this.params = this._isServer ? this.acceptAsServer(configurations) : this.acceptAsClient(configurations); return this.params; } /** * Releases all resources used by the extension. * * @public */ cleanup() { if (this._inflate) { this._inflate.close(); this._inflate = null; } if (this._deflate) { const callback = this._deflate[kCallback]; this._deflate.close(); this._deflate = null; if (callback) { callback( new Error( 'The deflate stream was closed while data was being processed' ) ); } } } /** * Accept an extension negotiation offer. * * @param {Array} offers The extension negotiation offers * @return {Object} Accepted configuration * @private */ acceptAsServer(offers) { const opts = this._options; const accepted = offers.find((params) => { if ( (opts.serverNoContextTakeover === false && params.server_no_context_takeover) || (params.server_max_window_bits && (opts.serverMaxWindowBits === false || (typeof opts.serverMaxWindowBits === 'number' && opts.serverMaxWindowBits > params.server_max_window_bits))) || (typeof opts.clientMaxWindowBits === 'number' && !params.client_max_window_bits) ) { return false; } return true; }); if (!accepted) { throw new Error('None of the extension offers can be accepted'); } if (opts.serverNoContextTakeover) { accepted.server_no_context_takeover = true; } if (opts.clientNoContextTakeover) { accepted.client_no_context_takeover = true; } if (typeof opts.serverMaxWindowBits === 'number') { accepted.server_max_window_bits = opts.serverMaxWindowBits; } if (typeof opts.clientMaxWindowBits === 'number') { accepted.client_max_window_bits = opts.clientMaxWindowBits; } else if ( accepted.client_max_window_bits === true || opts.clientMaxWindowBits === false ) { delete accepted.client_max_window_bits; } return accepted; } /** * Accept the extension negotiation response. * * @param {Array} response The extension negotiation response * @return {Object} Accepted configuration * @private */ acceptAsClient(response) { const params = response[0]; if ( this._options.clientNoContextTakeover === false && params.client_no_context_takeover ) { throw new Error('Unexpected parameter "client_no_context_takeover"'); } if (!params.client_max_window_bits) { if (typeof this._options.clientMaxWindowBits === 'number') { params.client_max_window_bits = this._options.clientMaxWindowBits; } } else if ( this._options.clientMaxWindowBits === false || (typeof this._options.clientMaxWindowBits === 'number' && params.client_max_window_bits > this._options.clientMaxWindowBits) ) { throw new Error( 'Unexpected or invalid parameter "client_max_window_bits"' ); } return params; } /** * Normalize parameters. * * @param {Array} configurations The extension negotiation offers/reponse * @return {Array} The offers/response with normalized parameters * @private */ normalizeParams(configurations) { configurations.forEach((params) => { Object.keys(params).forEach((key) => { let value = params[key]; if (value.length > 1) { throw new Error(`Parameter "${key}" must have only a single value`); } value = value[0]; if (key === 'client_max_window_bits') { if (value !== true) { const num = +value; if (!Number.isInteger(num) || num < 8 || num > 15) { throw new TypeError( `Invalid value for parameter "${key}": ${value}` ); } value = num; } else if (!this._isServer) { throw new TypeError( `Invalid value for parameter "${key}": ${value}` ); } } else if (key === 'server_max_window_bits') { const num = +value; if (!Number.isInteger(num) || num < 8 || num > 15) { throw new TypeError( `Invalid value for parameter "${key}": ${value}` ); } value = num; } else if ( key === 'client_no_context_takeover' || key === 'server_no_context_takeover' ) { if (value !== true) { throw new TypeError( `Invalid value for parameter "${key}": ${value}` ); } } else { throw new Error(`Unknown parameter "${key}"`); } params[key] = value; }); }); return configurations; } /** * Decompress data. Concurrency limited. * * @param {Buffer} data Compressed data * @param {Boolean} fin Specifies whether or not this is the last fragment * @param {Function} callback Callback * @public */ decompress(data, fin, callback) { zlibLimiter.add((done) => { this._decompress(data, fin, (err, result) => { done(); callback(err, result); }); }); } /** * Compress data. Concurrency limited. * * @param {(Buffer|String)} data Data to compress * @param {Boolean} fin Specifies whether or not this is the last fragment * @param {Function} callback Callback * @public */ compress(data, fin, callback) { zlibLimiter.add((done) => { this._compress(data, fin, (err, result) => { done(); callback(err, result); }); }); } /** * Decompress data. * * @param {Buffer} data Compressed data * @param {Boolean} fin Specifies whether or not this is the last fragment * @param {Function} callback Callback * @private */ _decompress(data, fin, callback) { const endpoint = this._isServer ? 'client' : 'server'; if (!this._inflate) { const key = `${endpoint}_max_window_bits`; const windowBits = typeof this.params[key] !== 'number' ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key]; this._inflate = zlib.createInflateRaw({ ...this._options.zlibInflateOptions, windowBits }); this._inflate[kPerMessageDeflate] = this; this._inflate[kTotalLength] = 0; this._inflate[kBuffers] = []; this._inflate.on('error', inflateOnError); this._inflate.on('data', inflateOnData); } this._inflate[kCallback] = callback; this._inflate.write(data); if (fin) this._inflate.write(TRAILER); this._inflate.flush(() => { const err = this._inflate[kError]; if (err) { this._inflate.close(); this._inflate = null; callback(err); return; } const data = bufferUtil.concat( this._inflate[kBuffers], this._inflate[kTotalLength] ); if (this._inflate._readableState.endEmitted) { this._inflate.close(); this._inflate = null; } else { this._inflate[kTotalLength] = 0; this._inflate[kBuffers] = []; if (fin && this.params[`${endpoint}_no_context_takeover`]) { this._inflate.reset(); } } callback(null, data); }); } /** * Compress data. * * @param {(Buffer|String)} data Data to compress * @param {Boolean} fin Specifies whether or not this is the last fragment * @param {Function} callback Callback * @private */ _compress(data, fin, callback) { const endpoint = this._isServer ? 'server' : 'client'; if (!this._deflate) { const key = `${endpoint}_max_window_bits`; const windowBits = typeof this.params[key] !== 'number' ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key]; this._deflate = zlib.createDeflateRaw({ ...this._options.zlibDeflateOptions, windowBits }); this._deflate[kTotalLength] = 0; this._deflate[kBuffers] = []; this._deflate.on('data', deflateOnData); } this._deflate[kCallback] = callback; this._deflate.write(data); this._deflate.flush(zlib.Z_SYNC_FLUSH, () => { if (!this._deflate) { // // The deflate stream was closed while data was being processed. // return; } let data = bufferUtil.concat( this._deflate[kBuffers], this._deflate[kTotalLength] ); if (fin) { data = new FastBuffer(data.buffer, data.byteOffset, data.length - 4); } // // Ensure that the callback will not be called again in // `PerMessageDeflate#cleanup()`. // this._deflate[kCallback] = null; this._deflate[kTotalLength] = 0; this._deflate[kBuffers] = []; if (fin && this.params[`${endpoint}_no_context_takeover`]) { this._deflate.reset(); } callback(null, data); }); } } module.exports = PerMessageDeflate; /** * The listener of the `zlib.DeflateRaw` stream `'data'` event. * * @param {Buffer} chunk A chunk of data * @private */ function deflateOnData(chunk) { this[kBuffers].push(chunk); this[kTotalLength] += chunk.length; } /** * The listener of the `zlib.InflateRaw` stream `'data'` event. * * @param {Buffer} chunk A chunk of data * @private */ function inflateOnData(chunk) { this[kTotalLength] += chunk.length; if ( this[kPerMessageDeflate]._maxPayload < 1 || this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload ) { this[kBuffers].push(chunk); return; } this[kError] = new RangeError('Max payload size exceeded'); this[kError].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'; this[kError][kStatusCode] = 1009; this.removeListener('data', inflateOnData); // // The choice to employ `zlib.reset()` over `zlib.close()` is dictated by the // fact that in Node.js versions prior to 13.10.0, the callback for // `zlib.flush()` is not called if `zlib.close()` is used. Utilizing // `zlib.reset()` ensures that either the callback is invoked or an error is // emitted. // this.reset(); } /** * The listener of the `zlib.InflateRaw` stream `'error'` event. * * @param {Error} err The emitted error * @private */ function inflateOnError(err) { // // There is no need to call `Zlib#close()` as the handle is automatically // closed when an error is emitted. // this[kPerMessageDeflate]._inflate = null; if (this[kError]) { this[kCallback](this[kError]); return; } err[kStatusCode] = 1007; this[kCallback](err); } /***/ }), /***/ 39962: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const { Writable } = __webpack_require__(2203); const PerMessageDeflate = __webpack_require__(8599); const { BINARY_TYPES, EMPTY_BUFFER, kStatusCode, kWebSocket } = __webpack_require__(74306); const { concat, toArrayBuffer, unmask } = __webpack_require__(76302); const { isValidStatusCode, isValidUTF8 } = __webpack_require__(51076); const FastBuffer = Buffer[Symbol.species]; const GET_INFO = 0; const GET_PAYLOAD_LENGTH_16 = 1; const GET_PAYLOAD_LENGTH_64 = 2; const GET_MASK = 3; const GET_DATA = 4; const INFLATING = 5; const DEFER_EVENT = 6; /** * HyBi Receiver implementation. * * @extends Writable */ class Receiver extends Writable { /** * Creates a Receiver instance. * * @param {Object} [options] Options object * @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 {String} [options.binaryType=nodebuffer] The type for binary data * @param {Object} [options.extensions] An object containing the negotiated * extensions * @param {Boolean} [options.isServer=false] Specifies whether to operate in * client or server mode * @param {Number} [options.maxPayload=0] The maximum allowed message length * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or * not to skip UTF-8 validation for text and close messages */ constructor(options = {}) { super(); this._allowSynchronousEvents = options.allowSynchronousEvents !== undefined ? options.allowSynchronousEvents : true; this._binaryType = options.binaryType || BINARY_TYPES[0]; this._extensions = options.extensions || {}; this._isServer = !!options.isServer; this._maxPayload = options.maxPayload | 0; this._skipUTF8Validation = !!options.skipUTF8Validation; this[kWebSocket] = undefined; this._bufferedBytes = 0; this._buffers = []; this._compressed = false; this._payloadLength = 0; this._mask = undefined; this._fragmented = 0; this._masked = false; this._fin = false; this._opcode = 0; this._totalPayloadLength = 0; this._messageLength = 0; this._fragments = []; this._errored = false; this._loop = false; this._state = GET_INFO; } /** * Implements `Writable.prototype._write()`. * * @param {Buffer} chunk The chunk of data to write * @param {String} encoding The character encoding of `chunk` * @param {Function} cb Callback * @private */ _write(chunk, encoding, cb) { if (this._opcode === 0x08 && this._state == GET_INFO) return cb(); this._bufferedBytes += chunk.length; this._buffers.push(chunk); this.startLoop(cb); } /** * Consumes `n` bytes from the buffered data. * * @param {Number} n The number of bytes to consume * @return {Buffer} The consumed bytes * @private */ consume(n) { this._bufferedBytes -= n; if (n === this._buffers[0].length) return this._buffers.shift(); if (n < this._buffers[0].length) { const buf = this._buffers[0]; this._buffers[0] = new FastBuffer( buf.buffer, buf.byteOffset + n, buf.length - n ); return new FastBuffer(buf.buffer, buf.byteOffset, n); } const dst = Buffer.allocUnsafe(n); do { const buf = this._buffers[0]; const offset = dst.length - n; if (n >= buf.length) { dst.set(this._buffers.shift(), offset); } else { dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset); this._buffers[0] = new FastBuffer( buf.buffer, buf.byteOffset + n, buf.length - n ); } n -= buf.length; } while (n > 0); return dst; } /** * Starts the parsing loop. * * @param {Function} cb Callback * @private */ startLoop(cb) { this._loop = true; do { switch (this._state) { case GET_INFO: this.getInfo(cb); break; case GET_PAYLOAD_LENGTH_16: this.getPayloadLength16(cb); break; case GET_PAYLOAD_LENGTH_64: this.getPayloadLength64(cb); break; case GET_MASK: this.getMask(); break; case GET_DATA: this.getData(cb); break; case INFLATING: case DEFER_EVENT: this._loop = false; return; } } while (this._loop); if (!this._errored) cb(); } /** * Reads the first two bytes of a frame. * * @param {Function} cb Callback * @private */ getInfo(cb) { if (this._bufferedBytes < 2) { this._loop = false; return; } const buf = this.consume(2); if ((buf[0] & 0x30) !== 0x00) { const error = this.createError( RangeError, 'RSV2 and RSV3 must be clear', true, 1002, 'WS_ERR_UNEXPECTED_RSV_2_3' ); cb(error); return; } const compressed = (buf[0] & 0x40) === 0x40; if (compressed && !this._extensions[PerMessageDeflate.extensionName]) { const error = this.createError( RangeError, 'RSV1 must be clear', true, 1002, 'WS_ERR_UNEXPECTED_RSV_1' ); cb(error); return; } this._fin = (buf[0] & 0x80) === 0x80; this._opcode = buf[0] & 0x0f; this._payloadLength = buf[1] & 0x7f; if (this._opcode === 0x00) { if (compressed) { const error = this.createError( RangeError, 'RSV1 must be clear', true, 1002, 'WS_ERR_UNEXPECTED_RSV_1' ); cb(error); return; } if (!this._fragmented) { const error = this.createError( RangeError, 'invalid opcode 0', true, 1002, 'WS_ERR_INVALID_OPCODE' ); cb(error); return; } this._opcode = this._fragmented; } else if (this._opcode === 0x01 || this._opcode === 0x02) { if (this._fragmented) { const error = this.createError( RangeError, `invalid opcode ${this._opcode}`, true, 1002, 'WS_ERR_INVALID_OPCODE' ); cb(error); return; } this._compressed = compressed; } else if (this._opcode > 0x07 && this._opcode < 0x0b) { if (!this._fin) { const error = this.createError( RangeError, 'FIN must be set', true, 1002, 'WS_ERR_EXPECTED_FIN' ); cb(error); return; } if (compressed) { const error = this.createError( RangeError, 'RSV1 must be clear', true, 1002, 'WS_ERR_UNEXPECTED_RSV_1' ); cb(error); return; } if ( this._payloadLength > 0x7d || (this._opcode === 0x08 && this._payloadLength === 1) ) { const error = this.createError( RangeError, `invalid payload length ${this._payloadLength}`, true, 1002, 'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH' ); cb(error); return; } } else { const error = this.createError( RangeError, `invalid opcode ${this._opcode}`, true, 1002, 'WS_ERR_INVALID_OPCODE' ); cb(error); return; } if (!this._fin && !this._fragmented) this._fragmented = this._opcode; this._masked = (buf[1] & 0x80) === 0x80; if (this._isServer) { if (!this._masked) { const error = this.createError( RangeError, 'MASK must be set', true, 1002, 'WS_ERR_EXPECTED_MASK' ); cb(error); return; } } else if (this._masked) { const error = this.createError( RangeError, 'MASK must be clear', true, 1002, 'WS_ERR_UNEXPECTED_MASK' ); cb(error); return; } if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16; else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64; else this.haveLength(cb); } /** * Gets extended payload length (7+16). * * @param {Function} cb Callback * @private */ getPayloadLength16(cb) { if (this._bufferedBytes < 2) { this._loop = false; return; } this._payloadLength = this.consume(2).readUInt16BE(0); this.haveLength(cb); } /** * Gets extended payload length (7+64). * * @param {Function} cb Callback * @private */ getPayloadLength64(cb) { if (this._bufferedBytes < 8) { this._loop = false; return; } const buf = this.consume(8); const num = buf.readUInt32BE(0); // // The maximum safe integer in JavaScript is 2^53 - 1. An error is returned // if payload length is greater than this number. // if (num > Math.pow(2, 53 - 32) - 1) { const error = this.createError( RangeError, 'Unsupported WebSocket frame: payload length > 2^53 - 1', false, 1009, 'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH' ); cb(error); return; } this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4); this.haveLength(cb); } /** * Payload length has been read. * * @param {Function} cb Callback * @private */ haveLength(cb) { if (this._payloadLength && this._opcode < 0x08) { this._totalPayloadLength += this._payloadLength; if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) { const error = this.createError( RangeError, 'Max payload size exceeded', false, 1009, 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH' ); cb(error); return; } } if (this._masked) this._state = GET_MASK; else this._state = GET_DATA; } /** * Reads mask bytes. * * @private */ getMask() { if (this._bufferedBytes < 4) { this._loop = false; return; } this._mask = this.consume(4); this._state = GET_DATA; } /** * Reads data bytes. * * @param {Function} cb Callback * @private */ getData(cb) { let data = EMPTY_BUFFER; if (this._payloadLength) { if (this._bufferedBytes < this._payloadLength) { this._loop = false; return; } data = this.consume(this._payloadLength); if ( this._masked && (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0 ) { unmask(data, this._mask); } } if (this._opcode > 0x07) { this.controlMessage(data, cb); return; } if (this._compressed) { this._state = INFLATING; this.decompress(data, cb); return; } if (data.length) { // // This message is not compressed so its length is the sum of the payload // length of all fragments. // this._messageLength = this._totalPayloadLength; this._fragments.push(data); } this.dataMessage(cb); } /** * Decompresses data. * * @param {Buffer} data Compressed data * @param {Function} cb Callback * @private */ decompress(data, cb) { const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; perMessageDeflate.decompress(data, this._fin, (err, buf) => { if (err) return cb(err); if (buf.length) { this._messageLength += buf.length; if (this._messageLength > this._maxPayload && this._maxPayload > 0) { const error = this.createError( RangeError, 'Max payload size exceeded', false, 1009, 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH' ); cb(error); return; } this._fragments.push(buf); } this.dataMessage(cb); if (this._state === GET_INFO) this.startLoop(cb); }); } /** * Handles a data message. * * @param {Function} cb Callback * @private */ dataMessage(cb) { if (!this._fin) { this._state = GET_INFO; return; } const messageLength = this._messageLength; const fragments = this._fragments; this._totalPayloadLength = 0; this._messageLength = 0; this._fragmented = 0; this._fragments = []; if (this._opcode === 2) { let data; if (this._binaryType === 'nodebuffer') { data = concat(fragments, messageLength); } else if (this._binaryType === 'arraybuffer') { data = toArrayBuffer(concat(fragments, messageLength)); } else if (this._binaryType === 'blob') { data = new Blob(fragments); } else { data = fragments; } if (this._allowSynchronousEvents) { this.emit('message', data, true); this._state = GET_INFO; } else { this._state = DEFER_EVENT; setImmediate(() => { this.emit('message', data, true); this._state = GET_INFO; this.startLoop(cb); }); } } else { const buf = concat(fragments, messageLength); if (!this._skipUTF8Validation && !isValidUTF8(buf)) { const error = this.createError( Error, 'invalid UTF-8 sequence', true, 1007, 'WS_ERR_INVALID_UTF8' ); cb(error); return; } if (this._state === INFLATING || this._allowSynchronousEvents) { this.emit('message', buf, false); this._state = GET_INFO; } else { this._state = DEFER_EVENT; setImmediate(() => { this.emit('message', buf, false); this._state = GET_INFO; this.startLoop(cb); }); } } } /** * Handles a control message. * * @param {Buffer} data Data to handle * @return {(Error|RangeError|undefined)} A possible error * @private */ controlMessage(data, cb) { if (this._opcode === 0x08) { if (data.length === 0) { this._loop = false; this.emit('conclude', 1005, EMPTY_BUFFER); this.end(); } else { const code = data.readUInt16BE(0); if (!isValidStatusCode(code)) { const error = this.createError( RangeError, `invalid status code ${code}`, true, 1002, 'WS_ERR_INVALID_CLOSE_CODE' ); cb(error); return; } const buf = new FastBuffer( data.buffer, data.byteOffset + 2, data.length - 2 ); if (!this._skipUTF8Validation && !isValidUTF8(buf)) { const error = this.createError( Error, 'invalid UTF-8 sequence', true, 1007, 'WS_ERR_INVALID_UTF8' ); cb(error); return; } this._loop = false; this.emit('conclude', code, buf); this.end(); } this._state = GET_INFO; return; } if (this._allowSynchronousEvents) { this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data); this._state = GET_INFO; } else { this._state = DEFER_EVENT; setImmediate(() => { this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data); this._state = GET_INFO; this.startLoop(cb); }); } } /** * Builds an error object. * * @param {function(new:Error|RangeError)} ErrorCtor The error constructor * @param {String} message The error message * @param {Boolean} prefix Specifies whether or not to add a default prefix to * `message` * @param {Number} statusCode The status code * @param {String} errorCode The exposed error code * @return {(Error|RangeError)} The error * @private */ createError(ErrorCtor, message, prefix, statusCode, errorCode) { this._loop = false; this._errored = true; const err = new ErrorCtor( prefix ? `Invalid WebSocket frame: ${message}` : message ); Error.captureStackTrace(err, this.createError); err.code = errorCode; err[kStatusCode] = statusCode; return err; } } module.exports = Receiver; /***/ }), /***/ 73998: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex" }] */ const { Duplex } = __webpack_require__(2203); const { randomFillSync } = __webpack_require__(76982); const PerMessageDeflate = __webpack_require__(8599); const { EMPTY_BUFFER, kWebSocket, NOOP }