You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
5.8 KiB
197 lines
5.8 KiB
'use strict';
|
|
|
|
var inspect = require('util').inspect;
|
|
|
|
function assert(value, message) {
|
|
if (!value)
|
|
throw new ERR_INTERNAL_ASSERTION(message);
|
|
}
|
|
assert.fail = function fail(message) {
|
|
throw new ERR_INTERNAL_ASSERTION(message);
|
|
};
|
|
|
|
// Only use this for integers! Decimal numbers do not work with this function.
|
|
function addNumericalSeparator(val) {
|
|
var res = '';
|
|
var i = val.length;
|
|
var start = val[0] === '-' ? 1 : 0;
|
|
for (; i >= start + 4; i -= 3)
|
|
res = `_${val.slice(i - 3, i)}${res}`;
|
|
return `${val.slice(0, i)}${res}`;
|
|
}
|
|
|
|
function oneOf(expected, thing) {
|
|
assert(typeof thing === 'string', '`thing` has to be of type string');
|
|
if (Array.isArray(expected)) {
|
|
var len = expected.length;
|
|
assert(len > 0, 'At least one expected value needs to be specified');
|
|
expected = expected.map((i) => String(i));
|
|
if (len > 2) {
|
|
return `one of ${thing} ${expected.slice(0, len - 1).join(', ')}, or `
|
|
+ expected[len - 1];
|
|
} else if (len === 2) {
|
|
return `one of ${thing} ${expected[0]} or ${expected[1]}`;
|
|
} else {
|
|
return `of ${thing} ${expected[0]}`;
|
|
}
|
|
} else {
|
|
return `of ${thing} ${String(expected)}`;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
exports.ERR_INTERNAL_ASSERTION = class ERR_INTERNAL_ASSERTION extends Error {
|
|
constructor(message) {
|
|
super();
|
|
Error.captureStackTrace(this, ERR_INTERNAL_ASSERTION);
|
|
|
|
var suffix = 'This is caused by either a bug in ssh2-streams '
|
|
+ 'or incorrect usage of ssh2-streams internals.\n'
|
|
+ 'Please open an issue with this stack trace at '
|
|
+ 'https://github.com/mscdex/ssh2-streams/issues\n';
|
|
|
|
this.message = (message === undefined ? suffix : `${message}\n${suffix}`);
|
|
}
|
|
};
|
|
|
|
var MAX_32BIT_INT = Math.pow(2, 32);
|
|
var MAX_32BIT_BIGINT = (function() {
|
|
try {
|
|
return new Function('return 2n ** 32n')();
|
|
} catch (ex) {}
|
|
})();
|
|
exports.ERR_OUT_OF_RANGE = class ERR_OUT_OF_RANGE extends RangeError {
|
|
constructor(str, range, input, replaceDefaultBoolean) {
|
|
super();
|
|
Error.captureStackTrace(this, ERR_OUT_OF_RANGE);
|
|
|
|
assert(range, 'Missing "range" argument');
|
|
var msg = (replaceDefaultBoolean
|
|
? str
|
|
: `The value of "${str}" is out of range.`);
|
|
var received;
|
|
if (Number.isInteger(input) && Math.abs(input) > MAX_32BIT_INT) {
|
|
received = addNumericalSeparator(String(input));
|
|
} else if (typeof input === 'bigint') {
|
|
received = String(input);
|
|
if (input > MAX_32BIT_BIGINT || input < -MAX_32BIT_BIGINT)
|
|
received = addNumericalSeparator(received);
|
|
received += 'n';
|
|
} else {
|
|
received = inspect(input);
|
|
}
|
|
msg += ` It must be ${range}. Received ${received}`;
|
|
|
|
this.message = msg;
|
|
}
|
|
};
|
|
|
|
exports.ERR_INVALID_ARG_TYPE = class ERR_INVALID_ARG_TYPE extends TypeError {
|
|
constructor(name, expected, actual) {
|
|
super();
|
|
Error.captureStackTrace(this, ERR_INVALID_ARG_TYPE);
|
|
|
|
assert(typeof name === 'string', `'name' must be a string`);
|
|
|
|
// determiner: 'must be' or 'must not be'
|
|
var determiner;
|
|
if (typeof expected === 'string' && expected.startsWith('not ')) {
|
|
determiner = 'must not be';
|
|
expected = expected.replace(/^not /, '');
|
|
} else {
|
|
determiner = 'must be';
|
|
}
|
|
|
|
var msg;
|
|
if (name.endsWith(' argument')) {
|
|
// For cases like 'first argument'
|
|
msg = `The ${name} ${determiner} ${oneOf(expected, 'type')}`;
|
|
} else {
|
|
var type = (name.includes('.') ? 'property' : 'argument');
|
|
msg = `The "${name}" ${type} ${determiner} ${oneOf(expected, 'type')}`;
|
|
}
|
|
|
|
msg += `. Received type ${typeof actual}`;
|
|
|
|
this.message = msg;
|
|
}
|
|
};
|
|
|
|
exports.validateNumber = function validateNumber(value, name) {
|
|
if (typeof value !== 'number')
|
|
throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
|
|
};
|
|
|
|
|
|
// =============================================================================
|
|
// Following code is only needed to support node v6.x ....
|
|
|
|
// Undocumented cb() API, needed for core, not for public API
|
|
exports.destroyImpl = function destroy(err, cb) {
|
|
const readableDestroyed = this._readableState &&
|
|
this._readableState.destroyed;
|
|
const writableDestroyed = this._writableState &&
|
|
this._writableState.destroyed;
|
|
|
|
if (readableDestroyed || writableDestroyed) {
|
|
if (cb) {
|
|
cb(err);
|
|
} else if (err) {
|
|
if (!this._writableState) {
|
|
process.nextTick(emitErrorNT, this, err);
|
|
} else if (!this._writableState.errorEmitted) {
|
|
this._writableState.errorEmitted = true;
|
|
process.nextTick(emitErrorNT, this, err);
|
|
}
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
// We set destroyed to true before firing error callbacks in order
|
|
// to make it re-entrance safe in case destroy() is called within callbacks
|
|
|
|
if (this._readableState) {
|
|
this._readableState.destroyed = true;
|
|
}
|
|
|
|
// If this is a duplex stream mark the writable part as destroyed as well
|
|
if (this._writableState) {
|
|
this._writableState.destroyed = true;
|
|
}
|
|
|
|
this._destroy(err || null, (err) => {
|
|
if (!cb && err) {
|
|
if (!this._writableState) {
|
|
process.nextTick(emitErrorAndCloseNT, this, err);
|
|
} else if (!this._writableState.errorEmitted) {
|
|
this._writableState.errorEmitted = true;
|
|
process.nextTick(emitErrorAndCloseNT, this, err);
|
|
} else {
|
|
process.nextTick(emitCloseNT, this);
|
|
}
|
|
} else if (cb) {
|
|
process.nextTick(emitCloseNT, this);
|
|
cb(err);
|
|
} else {
|
|
process.nextTick(emitCloseNT, this);
|
|
}
|
|
});
|
|
|
|
return this;
|
|
};
|
|
|
|
function emitErrorAndCloseNT(self, err) {
|
|
emitErrorNT(self, err);
|
|
emitCloseNT(self);
|
|
}
|
|
|
|
function emitCloseNT(self) {
|
|
if (self._writableState && !self._writableState.emitClose)
|
|
return;
|
|
if (self._readableState && !self._readableState.emitClose)
|
|
return;
|
|
self.emit('close');
|
|
}
|
|
// =============================================================================
|
|
|