node-fs-compat.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. 'use strict';
  2. const assert = require('assert');
  3. const { inspect } = require('util');
  4. // Only use this for integers! Decimal numbers do not work with this function.
  5. function addNumericalSeparator(val) {
  6. let res = '';
  7. let i = val.length;
  8. const start = val[0] === '-' ? 1 : 0;
  9. for (; i >= start + 4; i -= 3)
  10. res = `_${val.slice(i - 3, i)}${res}`;
  11. return `${val.slice(0, i)}${res}`;
  12. }
  13. function oneOf(expected, thing) {
  14. assert(typeof thing === 'string', '`thing` has to be of type string');
  15. if (Array.isArray(expected)) {
  16. const len = expected.length;
  17. assert(len > 0, 'At least one expected value needs to be specified');
  18. expected = expected.map((i) => String(i));
  19. if (len > 2) {
  20. return `one of ${thing} ${expected.slice(0, len - 1).join(', ')}, or `
  21. + expected[len - 1];
  22. } else if (len === 2) {
  23. return `one of ${thing} ${expected[0]} or ${expected[1]}`;
  24. }
  25. return `of ${thing} ${expected[0]}`;
  26. }
  27. return `of ${thing} ${String(expected)}`;
  28. }
  29. exports.ERR_INTERNAL_ASSERTION = class ERR_INTERNAL_ASSERTION extends Error {
  30. constructor(message) {
  31. super();
  32. Error.captureStackTrace(this, ERR_INTERNAL_ASSERTION);
  33. const suffix = 'This is caused by either a bug in ssh2 '
  34. + 'or incorrect usage of ssh2 internals.\n'
  35. + 'Please open an issue with this stack trace at '
  36. + 'https://github.com/mscdex/ssh2/issues\n';
  37. this.message = (message === undefined ? suffix : `${message}\n${suffix}`);
  38. }
  39. };
  40. const MAX_32BIT_INT = 2 ** 32;
  41. const MAX_32BIT_BIGINT = (() => {
  42. try {
  43. return new Function('return 2n ** 32n')();
  44. } catch {}
  45. })();
  46. exports.ERR_OUT_OF_RANGE = class ERR_OUT_OF_RANGE extends RangeError {
  47. constructor(str, range, input, replaceDefaultBoolean) {
  48. super();
  49. Error.captureStackTrace(this, ERR_OUT_OF_RANGE);
  50. assert(range, 'Missing "range" argument');
  51. let msg = (replaceDefaultBoolean
  52. ? str
  53. : `The value of "${str}" is out of range.`);
  54. let received;
  55. if (Number.isInteger(input) && Math.abs(input) > MAX_32BIT_INT) {
  56. received = addNumericalSeparator(String(input));
  57. } else if (typeof input === 'bigint') {
  58. received = String(input);
  59. if (input > MAX_32BIT_BIGINT || input < -MAX_32BIT_BIGINT)
  60. received = addNumericalSeparator(received);
  61. received += 'n';
  62. } else {
  63. received = inspect(input);
  64. }
  65. msg += ` It must be ${range}. Received ${received}`;
  66. this.message = msg;
  67. }
  68. };
  69. class ERR_INVALID_ARG_TYPE extends TypeError {
  70. constructor(name, expected, actual) {
  71. super();
  72. Error.captureStackTrace(this, ERR_INVALID_ARG_TYPE);
  73. assert(typeof name === 'string', `'name' must be a string`);
  74. // determiner: 'must be' or 'must not be'
  75. let determiner;
  76. if (typeof expected === 'string' && expected.startsWith('not ')) {
  77. determiner = 'must not be';
  78. expected = expected.replace(/^not /, '');
  79. } else {
  80. determiner = 'must be';
  81. }
  82. let msg;
  83. if (name.endsWith(' argument')) {
  84. // For cases like 'first argument'
  85. msg = `The ${name} ${determiner} ${oneOf(expected, 'type')}`;
  86. } else {
  87. const type = (name.includes('.') ? 'property' : 'argument');
  88. msg = `The "${name}" ${type} ${determiner} ${oneOf(expected, 'type')}`;
  89. }
  90. msg += `. Received type ${typeof actual}`;
  91. this.message = msg;
  92. }
  93. }
  94. exports.ERR_INVALID_ARG_TYPE = ERR_INVALID_ARG_TYPE;
  95. exports.validateNumber = function validateNumber(value, name) {
  96. if (typeof value !== 'number')
  97. throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
  98. };