util.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.unixify = exports.getWriteSyncArgs = exports.getWriteArgs = exports.bufToUint8 = exports.isWin = void 0;
  4. exports.promisify = promisify;
  5. exports.validateCallback = validateCallback;
  6. exports.modeToNumber = modeToNumber;
  7. exports.nullCheck = nullCheck;
  8. exports.pathToFilename = pathToFilename;
  9. exports.createError = createError;
  10. exports.genRndStr6 = genRndStr6;
  11. exports.flagsToNumber = flagsToNumber;
  12. exports.isFd = isFd;
  13. exports.validateFd = validateFd;
  14. exports.streamToBuffer = streamToBuffer;
  15. exports.dataToBuffer = dataToBuffer;
  16. exports.bufferToEncoding = bufferToEncoding;
  17. exports.isReadableStream = isReadableStream;
  18. const constants_1 = require("./constants");
  19. const errors = require("../internal/errors");
  20. const buffer_1 = require("../internal/buffer");
  21. const encoding_1 = require("../encoding");
  22. const buffer_2 = require("../internal/buffer");
  23. const queueMicrotask_1 = require("../queueMicrotask");
  24. exports.isWin = process.platform === 'win32';
  25. function promisify(fs, fn, getResult = input => input) {
  26. return (...args) => new Promise((resolve, reject) => {
  27. fs[fn].bind(fs)(...args, (error, result) => {
  28. if (error)
  29. return reject(error);
  30. return resolve(getResult(result));
  31. });
  32. });
  33. }
  34. function validateCallback(callback) {
  35. if (typeof callback !== 'function')
  36. throw TypeError(constants_1.ERRSTR.CB);
  37. return callback;
  38. }
  39. function _modeToNumber(mode, def) {
  40. if (typeof mode === 'number')
  41. return mode;
  42. if (typeof mode === 'string')
  43. return parseInt(mode, 8);
  44. if (def)
  45. return modeToNumber(def);
  46. return undefined;
  47. }
  48. function modeToNumber(mode, def) {
  49. const result = _modeToNumber(mode, def);
  50. if (typeof result !== 'number' || isNaN(result))
  51. throw new TypeError(constants_1.ERRSTR.MODE_INT);
  52. return result;
  53. }
  54. function nullCheck(path, callback) {
  55. if (('' + path).indexOf('\u0000') !== -1) {
  56. const er = new Error('Path must be a string without null bytes');
  57. er.code = 'ENOENT';
  58. if (typeof callback !== 'function')
  59. throw er;
  60. (0, queueMicrotask_1.default)(() => {
  61. callback(er);
  62. });
  63. return false;
  64. }
  65. return true;
  66. }
  67. function getPathFromURLPosix(url) {
  68. if (url.hostname !== '') {
  69. throw new errors.TypeError('ERR_INVALID_FILE_URL_HOST', process.platform);
  70. }
  71. const pathname = url.pathname;
  72. for (let n = 0; n < pathname.length; n++) {
  73. if (pathname[n] === '%') {
  74. const third = pathname.codePointAt(n + 2) | 0x20;
  75. if (pathname[n + 1] === '2' && third === 102) {
  76. throw new errors.TypeError('ERR_INVALID_FILE_URL_PATH', 'must not include encoded / characters');
  77. }
  78. }
  79. }
  80. return decodeURIComponent(pathname);
  81. }
  82. function pathToFilename(path) {
  83. if (path instanceof Uint8Array) {
  84. path = (0, buffer_2.bufferFrom)(path);
  85. }
  86. if (typeof path !== 'string' && !buffer_1.Buffer.isBuffer(path)) {
  87. try {
  88. if (!(path instanceof require('url').URL))
  89. throw new TypeError(constants_1.ERRSTR.PATH_STR);
  90. }
  91. catch (err) {
  92. throw new TypeError(constants_1.ERRSTR.PATH_STR);
  93. }
  94. path = getPathFromURLPosix(path);
  95. }
  96. const pathString = String(path);
  97. nullCheck(pathString);
  98. // return slash(pathString);
  99. return pathString;
  100. }
  101. const ENOENT = 'ENOENT';
  102. const EBADF = 'EBADF';
  103. const EINVAL = 'EINVAL';
  104. const EPERM = 'EPERM';
  105. const EPROTO = 'EPROTO';
  106. const EEXIST = 'EEXIST';
  107. const ENOTDIR = 'ENOTDIR';
  108. const EMFILE = 'EMFILE';
  109. const EACCES = 'EACCES';
  110. const EISDIR = 'EISDIR';
  111. const ENOTEMPTY = 'ENOTEMPTY';
  112. const ENOSYS = 'ENOSYS';
  113. const ERR_FS_EISDIR = 'ERR_FS_EISDIR';
  114. const ERR_OUT_OF_RANGE = 'ERR_OUT_OF_RANGE';
  115. function formatError(errorCode, func = '', path = '', path2 = '') {
  116. let pathFormatted = '';
  117. if (path)
  118. pathFormatted = ` '${path}'`;
  119. if (path2)
  120. pathFormatted += ` -> '${path2}'`;
  121. switch (errorCode) {
  122. case ENOENT:
  123. return `ENOENT: no such file or directory, ${func}${pathFormatted}`;
  124. case EBADF:
  125. return `EBADF: bad file descriptor, ${func}${pathFormatted}`;
  126. case EINVAL:
  127. return `EINVAL: invalid argument, ${func}${pathFormatted}`;
  128. case EPERM:
  129. return `EPERM: operation not permitted, ${func}${pathFormatted}`;
  130. case EPROTO:
  131. return `EPROTO: protocol error, ${func}${pathFormatted}`;
  132. case EEXIST:
  133. return `EEXIST: file already exists, ${func}${pathFormatted}`;
  134. case ENOTDIR:
  135. return `ENOTDIR: not a directory, ${func}${pathFormatted}`;
  136. case EISDIR:
  137. return `EISDIR: illegal operation on a directory, ${func}${pathFormatted}`;
  138. case EACCES:
  139. return `EACCES: permission denied, ${func}${pathFormatted}`;
  140. case ENOTEMPTY:
  141. return `ENOTEMPTY: directory not empty, ${func}${pathFormatted}`;
  142. case EMFILE:
  143. return `EMFILE: too many open files, ${func}${pathFormatted}`;
  144. case ENOSYS:
  145. return `ENOSYS: function not implemented, ${func}${pathFormatted}`;
  146. case ERR_FS_EISDIR:
  147. return `[ERR_FS_EISDIR]: Path is a directory: ${func} returned EISDIR (is a directory) ${path}`;
  148. case ERR_OUT_OF_RANGE:
  149. return `[ERR_OUT_OF_RANGE]: value out of range, ${func}${pathFormatted}`;
  150. default:
  151. return `${errorCode}: error occurred, ${func}${pathFormatted}`;
  152. }
  153. }
  154. function createError(errorCode, func = '', path = '', path2 = '', Constructor = Error) {
  155. const error = new Constructor(formatError(errorCode, func, path, path2));
  156. error.code = errorCode;
  157. if (path) {
  158. error.path = path;
  159. }
  160. return error;
  161. }
  162. function genRndStr6() {
  163. const str = (Math.random() + 1).toString(36).substring(2, 8);
  164. if (str.length === 6)
  165. return str;
  166. else
  167. return genRndStr6();
  168. }
  169. function flagsToNumber(flags) {
  170. if (typeof flags === 'number')
  171. return flags;
  172. if (typeof flags === 'string') {
  173. const flagsNum = constants_1.FLAGS[flags];
  174. if (typeof flagsNum !== 'undefined')
  175. return flagsNum;
  176. }
  177. // throw new TypeError(formatError(ERRSTR_FLAG(flags)));
  178. throw new errors.TypeError('ERR_INVALID_OPT_VALUE', 'flags', flags);
  179. }
  180. function isFd(path) {
  181. return path >>> 0 === path;
  182. }
  183. function validateFd(fd) {
  184. if (!isFd(fd))
  185. throw TypeError(constants_1.ERRSTR.FD);
  186. }
  187. function streamToBuffer(stream) {
  188. const chunks = [];
  189. return new Promise((resolve, reject) => {
  190. stream.on('data', chunk => chunks.push(chunk));
  191. stream.on('end', () => resolve(buffer_1.Buffer.concat(chunks)));
  192. stream.on('error', reject);
  193. });
  194. }
  195. function dataToBuffer(data, encoding = encoding_1.ENCODING_UTF8) {
  196. if (buffer_1.Buffer.isBuffer(data))
  197. return data;
  198. else if (data instanceof Uint8Array)
  199. return (0, buffer_2.bufferFrom)(data);
  200. else
  201. return (0, buffer_2.bufferFrom)(String(data), encoding);
  202. }
  203. const bufToUint8 = (buf) => new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
  204. exports.bufToUint8 = bufToUint8;
  205. const getWriteArgs = (fd, a, b, c, d, e) => {
  206. validateFd(fd);
  207. let offset = 0;
  208. let length;
  209. let position = null;
  210. let encoding;
  211. let callback;
  212. const tipa = typeof a;
  213. const tipb = typeof b;
  214. const tipc = typeof c;
  215. const tipd = typeof d;
  216. if (tipa !== 'string') {
  217. if (tipb === 'function') {
  218. callback = b;
  219. }
  220. else if (tipc === 'function') {
  221. offset = b | 0;
  222. callback = c;
  223. }
  224. else if (tipd === 'function') {
  225. offset = b | 0;
  226. length = c;
  227. callback = d;
  228. }
  229. else {
  230. offset = b | 0;
  231. length = c;
  232. position = d;
  233. callback = e;
  234. }
  235. }
  236. else {
  237. if (tipb === 'function') {
  238. callback = b;
  239. }
  240. else if (tipc === 'function') {
  241. position = b;
  242. callback = c;
  243. }
  244. else if (tipd === 'function') {
  245. position = b;
  246. encoding = c;
  247. callback = d;
  248. }
  249. }
  250. const buf = dataToBuffer(a, encoding);
  251. if (tipa !== 'string') {
  252. if (typeof length === 'undefined')
  253. length = buf.length;
  254. }
  255. else {
  256. offset = 0;
  257. length = buf.length;
  258. }
  259. const cb = validateCallback(callback);
  260. return [fd, tipa === 'string', buf, offset, length, position, cb];
  261. };
  262. exports.getWriteArgs = getWriteArgs;
  263. const getWriteSyncArgs = (fd, a, b, c, d) => {
  264. validateFd(fd);
  265. let encoding;
  266. let offset;
  267. let length;
  268. let position;
  269. const isBuffer = typeof a !== 'string';
  270. if (isBuffer) {
  271. offset = (b || 0) | 0;
  272. length = c;
  273. position = d;
  274. }
  275. else {
  276. position = b;
  277. encoding = c;
  278. }
  279. const buf = dataToBuffer(a, encoding);
  280. if (isBuffer) {
  281. if (typeof length === 'undefined') {
  282. length = buf.length;
  283. }
  284. }
  285. else {
  286. offset = 0;
  287. length = buf.length;
  288. }
  289. return [fd, buf, offset || 0, length, position];
  290. };
  291. exports.getWriteSyncArgs = getWriteSyncArgs;
  292. function bufferToEncoding(buffer, encoding) {
  293. if (!encoding || encoding === 'buffer')
  294. return buffer;
  295. else
  296. return buffer.toString(encoding);
  297. }
  298. function isReadableStream(stream) {
  299. return (stream !== null &&
  300. typeof stream === 'object' &&
  301. typeof stream.pipe === 'function' &&
  302. typeof stream.on === 'function' &&
  303. stream.readable === true);
  304. }
  305. const isSeparator = (str, i) => {
  306. let char = str[i];
  307. return i > 0 && (char === '/' || (exports.isWin && char === '\\'));
  308. };
  309. const removeTrailingSeparator = (str) => {
  310. let i = str.length - 1;
  311. if (i < 2)
  312. return str;
  313. while (isSeparator(str, i))
  314. i--;
  315. return str.substr(0, i + 1);
  316. };
  317. const normalizePath = (str, stripTrailing) => {
  318. if (typeof str !== 'string')
  319. throw new TypeError('expected a string');
  320. str = str.replace(/[\\\/]+/g, '/');
  321. if (stripTrailing !== false)
  322. str = removeTrailingSeparator(str);
  323. return str;
  324. };
  325. const unixify = (filepath, stripTrailing = true) => {
  326. if (exports.isWin) {
  327. filepath = normalizePath(filepath, stripTrailing);
  328. return filepath.replace(/^([a-zA-Z]+:|\.\/)/, '');
  329. }
  330. return filepath;
  331. };
  332. exports.unixify = unixify;
  333. //# sourceMappingURL=util.js.map