1
0
mirror of https://github.com/S2-/minifyfromhtml.git synced 2025-08-04 04:40:05 +02:00

update node modules

This commit is contained in:
s2
2019-03-29 15:56:41 +01:00
parent f114871153
commit 89c32fb4e6
8347 changed files with 390123 additions and 159877 deletions

509
node_modules/ws/lib/receiver.js generated vendored
View File

@@ -1,13 +1,16 @@
'use strict';
const safeBuffer = require('safe-buffer');
const { Writable } = require('stream');
const PerMessageDeflate = require('./permessage-deflate');
const bufferUtil = require('./buffer-util');
const validation = require('./validation');
const constants = require('./constants');
const Buffer = safeBuffer.Buffer;
const {
BINARY_TYPES,
EMPTY_BUFFER,
kStatusCode,
kWebSocket
} = require('./constants');
const { concat, toArrayBuffer, unmask } = require('./buffer-util');
const { isValidStatusCode, isValidUTF8 } = require('./validation');
const GET_INFO = 0;
const GET_PAYLOAD_LENGTH_16 = 1;
@@ -18,17 +21,22 @@ const INFLATING = 5;
/**
* HyBi Receiver implementation.
*
* @extends stream.Writable
*/
class Receiver {
class Receiver extends Writable {
/**
* Creates a Receiver instance.
*
* @param {String} binaryType The type for binary data
* @param {Object} extensions An object containing the negotiated extensions
* @param {Number} maxPayload The maximum allowed message length
* @param {String} binaryType The type for binary data
*/
constructor (extensions, maxPayload, binaryType) {
this._binaryType = binaryType || constants.BINARY_TYPES[0];
constructor(binaryType, extensions, maxPayload) {
super();
this._binaryType = binaryType || BINARY_TYPES[0];
this[kWebSocket] = undefined;
this._extensions = extensions || {};
this._maxPayload = maxPayload | 0;
@@ -37,46 +45,43 @@ class Receiver {
this._compressed = false;
this._payloadLength = 0;
this._mask = undefined;
this._fragmented = 0;
this._masked = false;
this._fin = false;
this._mask = null;
this._opcode = 0;
this._totalPayloadLength = 0;
this._messageLength = 0;
this._fragments = [];
this._cleanupCallback = null;
this._isCleaningUp = false;
this._hadError = false;
this._loop = false;
this.add = this.add.bind(this);
this.onmessage = null;
this.onclose = null;
this.onerror = null;
this.onping = null;
this.onpong = null;
this._state = GET_INFO;
this._loop = false;
}
/**
* Consumes `n` bytes from the buffered data, calls `cleanup` if necessary.
* 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
*/
_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|null)} The consumed bytes or `null` if `n` bytes are not
* available
* @return {Buffer} The consumed bytes
* @private
*/
consume (n) {
if (this._bufferedBytes < n) {
this._loop = false;
if (this._isCleaningUp) this.cleanup(this._cleanupCallback);
return null;
}
consume(n) {
this._bufferedBytes -= n;
if (n === this._buffers[0].length) return this._buffers.shift();
@@ -105,74 +110,67 @@ class Receiver {
return dst;
}
/**
* Adds new data to the parser.
*
* @param {Buffer} chunk A chunk of data
* @public
*/
add (chunk) {
this._bufferedBytes += chunk.length;
this._buffers.push(chunk);
this.startLoop();
}
/**
* Starts the parsing loop.
*
* @param {Function} cb Callback
* @private
*/
startLoop () {
startLoop(cb) {
var err;
this._loop = true;
do {
switch (this._state) {
case GET_INFO:
this.getInfo();
err = this.getInfo();
break;
case GET_PAYLOAD_LENGTH_16:
this.getPayloadLength16();
err = this.getPayloadLength16();
break;
case GET_PAYLOAD_LENGTH_64:
this.getPayloadLength64();
err = this.getPayloadLength64();
break;
case GET_MASK:
this.getMask();
break;
case GET_DATA:
this.getData();
err = this.getData(cb);
break;
default: // `INFLATING`
default:
// `INFLATING`
this._loop = false;
return;
}
} while (this._loop);
cb(err);
}
/**
* Reads the first two bytes of a frame.
*
* @return {(RangeError|undefined)} A possible error
* @private
*/
getInfo () {
getInfo() {
if (this._bufferedBytes < 2) {
this._loop = false;
return;
}
const buf = this.consume(2);
if (buf === null) return;
if ((buf[0] & 0x30) !== 0x00) {
this.error(
new RangeError('Invalid WebSocket frame: RSV2 and RSV3 must be clear'),
1002
);
return;
this._loop = false;
return error(RangeError, 'RSV2 and RSV3 must be clear', true, 1002);
}
const compressed = (buf[0] & 0x40) === 0x40;
if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {
this.error(
new RangeError('Invalid WebSocket frame: RSV1 must be clear'),
1002
);
return;
this._loop = false;
return error(RangeError, 'RSV1 must be clear', true, 1002);
}
this._fin = (buf[0] & 0x80) === 0x80;
@@ -181,130 +179,118 @@ class Receiver {
if (this._opcode === 0x00) {
if (compressed) {
this.error(
new RangeError('Invalid WebSocket frame: RSV1 must be clear'),
1002
);
return;
this._loop = false;
return error(RangeError, 'RSV1 must be clear', true, 1002);
}
if (!this._fragmented) {
this.error(
new RangeError('Invalid WebSocket frame: invalid opcode 0'),
1002
);
return;
} else {
this._opcode = this._fragmented;
this._loop = false;
return error(RangeError, 'invalid opcode 0', true, 1002);
}
this._opcode = this._fragmented;
} else if (this._opcode === 0x01 || this._opcode === 0x02) {
if (this._fragmented) {
this.error(
new RangeError(
`Invalid WebSocket frame: invalid opcode ${this._opcode}`
),
1002
);
return;
this._loop = false;
return error(RangeError, `invalid opcode ${this._opcode}`, true, 1002);
}
this._compressed = compressed;
} else if (this._opcode > 0x07 && this._opcode < 0x0b) {
if (!this._fin) {
this.error(
new RangeError('Invalid WebSocket frame: FIN must be set'),
1002
);
return;
this._loop = false;
return error(RangeError, 'FIN must be set', true, 1002);
}
if (compressed) {
this.error(
new RangeError('Invalid WebSocket frame: RSV1 must be clear'),
1002
);
return;
this._loop = false;
return error(RangeError, 'RSV1 must be clear', true, 1002);
}
if (this._payloadLength > 0x7d) {
this.error(
new RangeError(
`Invalid WebSocket frame: invalid payload length ` +
`${this._payloadLength}`
),
this._loop = false;
return error(
RangeError,
`invalid payload length ${this._payloadLength}`,
true,
1002
);
return;
}
} else {
this.error(
new RangeError(
`Invalid WebSocket frame: invalid opcode ${this._opcode}`
),
1002
);
return;
this._loop = false;
return error(RangeError, `invalid opcode ${this._opcode}`, true, 1002);
}
if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
this._masked = (buf[1] & 0x80) === 0x80;
if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;
else this.haveLength();
else return this.haveLength();
}
/**
* Gets extended payload length (7+16).
*
* @return {(RangeError|undefined)} A possible error
* @private
*/
getPayloadLength16 () {
const buf = this.consume(2);
if (buf === null) return;
getPayloadLength16() {
if (this._bufferedBytes < 2) {
this._loop = false;
return;
}
this._payloadLength = buf.readUInt16BE(0, true);
this.haveLength();
this._payloadLength = this.consume(2).readUInt16BE(0);
return this.haveLength();
}
/**
* Gets extended payload length (7+64).
*
* @return {(RangeError|undefined)} A possible error
* @private
*/
getPayloadLength64 () {
const buf = this.consume(8);
if (buf === null) return;
getPayloadLength64() {
if (this._bufferedBytes < 8) {
this._loop = false;
return;
}
const num = buf.readUInt32BE(0, true);
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) {
this.error(
new RangeError(
'Unsupported WebSocket frame: payload length > 2^53 - 1'
),
this._loop = false;
return error(
RangeError,
'Unsupported WebSocket frame: payload length > 2^53 - 1',
false,
1009
);
return;
}
this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4, true);
this.haveLength();
this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);
return this.haveLength();
}
/**
* Payload length has been read.
*
* @return {(RangeError|undefined)} A possible error
* @private
*/
haveLength () {
if (this._opcode < 0x08 && this.maxPayloadExceeded(this._payloadLength)) {
return;
haveLength() {
if (this._payloadLength && this._opcode < 0x08) {
this._totalPayloadLength += this._payloadLength;
if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
this._loop = false;
return error(RangeError, 'Max payload size exceeded', false, 1009);
}
}
if (this._masked) this._state = GET_MASK;
@@ -316,64 +302,94 @@ class Receiver {
*
* @private
*/
getMask () {
this._mask = this.consume(4);
if (this._mask === null) return;
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
* @return {(Error|RangeError|undefined)} A possible error
* @private
*/
getData () {
var data = constants.EMPTY_BUFFER;
getData(cb) {
var data = EMPTY_BUFFER;
if (this._payloadLength) {
if (this._bufferedBytes < this._payloadLength) {
this._loop = false;
return;
}
data = this.consume(this._payloadLength);
if (data === null) return;
if (this._masked) bufferUtil.unmask(data, this._mask);
if (this._masked) unmask(data, this._mask);
}
if (this._opcode > 0x07) {
this.controlMessage(data);
} else if (this._compressed) {
if (this._opcode > 0x07) return this.controlMessage(data);
if (this._compressed) {
this._state = INFLATING;
this.decompress(data);
} else if (this.pushFragment(data)) {
this.dataMessage();
this.decompress(data, cb);
return;
}
if (data.length) {
//
// This message is not compressed so its lenght is the sum of the payload
// length of all fragments.
//
this._messageLength = this._totalPayloadLength;
this._fragments.push(data);
}
return this.dataMessage();
}
/**
* Decompresses data.
*
* @param {Buffer} data Compressed data
* @param {Function} cb Callback
* @private
*/
decompress (data) {
decompress(data, cb) {
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
perMessageDeflate.decompress(data, this._fin, (err, buf) => {
if (err) {
this.error(err, err.closeCode === 1009 ? 1009 : 1007);
return;
if (err) return cb(err);
if (buf.length) {
this._messageLength += buf.length;
if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
return cb(
error(RangeError, 'Max payload size exceeded', false, 1009)
);
}
this._fragments.push(buf);
}
if (this.pushFragment(buf)) this.dataMessage();
this.startLoop();
const er = this.dataMessage();
if (er) return cb(er);
this.startLoop(cb);
});
}
/**
* Handles a data message.
*
* @return {(Error|undefined)} A possible error
* @private
*/
dataMessage () {
dataMessage() {
if (this._fin) {
const messageLength = this._messageLength;
const fragments = this._fragments;
@@ -387,26 +403,23 @@ class Receiver {
var data;
if (this._binaryType === 'nodebuffer') {
data = toBuffer(fragments, messageLength);
data = concat(fragments, messageLength);
} else if (this._binaryType === 'arraybuffer') {
data = toArrayBuffer(toBuffer(fragments, messageLength));
data = toArrayBuffer(concat(fragments, messageLength));
} else {
data = fragments;
}
this.onmessage(data);
this.emit('message', data);
} else {
const buf = toBuffer(fragments, messageLength);
const buf = concat(fragments, messageLength);
if (!validation.isValidUTF8(buf)) {
this.error(
new Error('Invalid WebSocket frame: invalid UTF-8 sequence'),
1007
);
return;
if (!isValidUTF8(buf)) {
this._loop = false;
return error(Error, 'invalid UTF-8 sequence', true, 1007);
}
this.onmessage(buf.toString());
this.emit('message', buf.toString());
}
}
@@ -417,173 +430,63 @@ class Receiver {
* Handles a control message.
*
* @param {Buffer} data Data to handle
* @return {(Error|RangeError|undefined)} A possible error
* @private
*/
controlMessage (data) {
controlMessage(data) {
if (this._opcode === 0x08) {
if (data.length === 0) {
this._loop = false;
this.onclose(1005, '');
this.cleanup(this._cleanupCallback);
} else if (data.length === 1) {
this.error(
new RangeError('Invalid WebSocket frame: invalid payload length 1'),
1002
);
} else {
const code = data.readUInt16BE(0, true);
this._loop = false;
if (!validation.isValidStatusCode(code)) {
this.error(
new RangeError(
`Invalid WebSocket frame: invalid status code ${code}`
),
1002
);
return;
if (data.length === 0) {
this.emit('conclude', 1005, '');
this.end();
} else if (data.length === 1) {
return error(RangeError, 'invalid payload length 1', true, 1002);
} else {
const code = data.readUInt16BE(0);
if (!isValidStatusCode(code)) {
return error(RangeError, `invalid status code ${code}`, true, 1002);
}
const buf = data.slice(2);
if (!validation.isValidUTF8(buf)) {
this.error(
new Error('Invalid WebSocket frame: invalid UTF-8 sequence'),
1007
);
return;
if (!isValidUTF8(buf)) {
return error(Error, 'invalid UTF-8 sequence', true, 1007);
}
this._loop = false;
this.onclose(code, buf.toString());
this.cleanup(this._cleanupCallback);
this.emit('conclude', code, buf.toString());
this.end();
}
return;
} else if (this._opcode === 0x09) {
this.emit('ping', data);
} else {
this.emit('pong', data);
}
if (this._opcode === 0x09) this.onping(data);
else this.onpong(data);
this._state = GET_INFO;
}
/**
* Handles an error.
*
* @param {Error} err The error
* @param {Number} code Close code
* @private
*/
error (err, code) {
this._hadError = true;
this._loop = false;
this.onerror(err, code);
this.cleanup(this._cleanupCallback);
}
/**
* Checks payload size, disconnects socket when it exceeds `maxPayload`.
*
* @param {Number} length Payload length
* @private
*/
maxPayloadExceeded (length) {
if (length === 0 || this._maxPayload < 1) return false;
const fullLength = this._totalPayloadLength + length;
if (fullLength <= this._maxPayload) {
this._totalPayloadLength = fullLength;
return false;
}
this.error(new RangeError('Max payload size exceeded'), 1009);
return true;
}
/**
* Appends a fragment in the fragments array after checking that the sum of
* fragment lengths does not exceed `maxPayload`.
*
* @param {Buffer} fragment The fragment to add
* @return {Boolean} `true` if `maxPayload` is not exceeded, else `false`
* @private
*/
pushFragment (fragment) {
if (fragment.length === 0) return true;
const totalLength = this._messageLength + fragment.length;
if (this._maxPayload < 1 || totalLength <= this._maxPayload) {
this._messageLength = totalLength;
this._fragments.push(fragment);
return true;
}
this.error(new RangeError('Max payload size exceeded'), 1009);
return false;
}
/**
* Releases resources used by the receiver.
*
* @param {Function} cb Callback
* @public
*/
cleanup (cb) {
if (this._extensions === null) {
if (cb) cb();
return;
}
if (!this._hadError && (this._loop || this._state === INFLATING)) {
this._cleanupCallback = cb;
this._isCleaningUp = true;
return;
}
this._extensions = null;
this._fragments = null;
this._buffers = null;
this._mask = null;
this._cleanupCallback = null;
this.onmessage = null;
this.onclose = null;
this.onerror = null;
this.onping = null;
this.onpong = null;
if (cb) cb();
}
}
module.exports = Receiver;
/**
* Makes a buffer from a list of fragments.
* Builds an error object.
*
* @param {Buffer[]} fragments The list of fragments composing the message
* @param {Number} messageLength The length of the message
* @return {Buffer}
* @param {(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
* @return {(Error|RangeError)} The error
* @private
*/
function toBuffer (fragments, messageLength) {
if (fragments.length === 1) return fragments[0];
if (fragments.length > 1) return bufferUtil.concat(fragments, messageLength);
return constants.EMPTY_BUFFER;
}
function error(ErrorCtor, message, prefix, statusCode) {
const err = new ErrorCtor(
prefix ? `Invalid WebSocket frame: ${message}` : message
);
/**
* Converts a buffer to an `ArrayBuffer`.
*
* @param {Buffer} The buffer to convert
* @return {ArrayBuffer} Converted buffer
*/
function toArrayBuffer (buf) {
if (buf.byteOffset === 0 && buf.byteLength === buf.buffer.byteLength) {
return buf.buffer;
}
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
Error.captureStackTrace(err, error);
err[kStatusCode] = statusCode;
return err;
}