JAVASCRIPT   16

util.js

Guest on 15th May 2021 10:19:33 AM

  1. 'use strict';
  2.  
  3. const errors = require('internal/errors');
  4. const binding = process.binding('util');
  5. const { signals } = process.binding('constants').os;
  6.  
  7. const { createPromise, promiseResolve, promiseReject } = binding;
  8.  
  9. const kArrowMessagePrivateSymbolIndex = binding.arrow_message_private_symbol;
  10. const kDecoratedPrivateSymbolIndex = binding.decorated_private_symbol;
  11. const noCrypto = !process.versions.openssl;
  12.  
  13. const experimentalWarnings = new Set();
  14.  
  15. function isError(e) {
  16.   return objectToString(e) === '[object Error]' || e instanceof Error;
  17. }
  18.  
  19. function objectToString(o) {
  20.   return Object.prototype.toString.call(o);
  21. }
  22.  
  23. // Mark that a method should not be used.
  24. // Returns a modified function which warns once by default.
  25. // If --no-deprecation is set, then it is a no-op.
  26. function deprecate(fn, msg, code) {
  27.   if (process.noDeprecation === true) {
  28.     return fn;
  29.   }
  30.  
  31.   if (code !== undefined && typeof code !== 'string')
  32.     throw new TypeError('`code` argument must be a string');
  33.  
  34.   var warned = false;
  35.   function deprecated(...args) {
  36.     if (!warned) {
  37.       warned = true;
  38.       if (code !== undefined) {
  39.         process.emitWarning(msg, 'DeprecationWarning', code, deprecated);
  40.       } else {
  41.         process.emitWarning(msg, 'DeprecationWarning', deprecated);
  42.       }
  43.     }
  44.     if (new.target) {
  45.       return Reflect.construct(fn, args, new.target);
  46.     }
  47.     return fn.apply(this, args);
  48.   }
  49.  
  50.   // The wrapper will keep the same prototype as fn to maintain prototype chain
  51.   Object.setPrototypeOf(deprecated, fn);
  52.   if (fn.prototype) {
  53.     // Setting this (rather than using Object.setPrototype, as above) ensures
  54.     // that calling the unwrapped constructor gives an instanceof the wrapped
  55.     // constructor.
  56.     deprecated.prototype = fn.prototype;
  57.   }
  58.  
  59.   return deprecated;
  60. }
  61.  
  62. function decorateErrorStack(err) {
  63.   if (!(isError(err) && err.stack) ||
  64.       binding.getHiddenValue(err, kDecoratedPrivateSymbolIndex) === true)
  65.     return;
  66.  
  67.   const arrow = binding.getHiddenValue(err, kArrowMessagePrivateSymbolIndex);
  68.  
  69.   if (arrow) {
  70.     err.stack = arrow + err.stack;
  71.     binding.setHiddenValue(err, kDecoratedPrivateSymbolIndex, true);
  72.   }
  73. }
  74.  
  75. function assertCrypto() {
  76.   if (noCrypto)
  77.     throw new Error('Node.js is not compiled with openssl crypto support');
  78. }
  79.  
  80. // The loop should only run at most twice, retrying with lowercased enc
  81. // if there is no match in the first pass.
  82. // We use a loop instead of branching to retry with a helper
  83. // function in order to avoid the performance hit.
  84. // Return undefined if there is no match.
  85. function normalizeEncoding(enc) {
  86.   if (!enc) return 'utf8';
  87.   var retried;
  88.   while (true) {
  89.     switch (enc) {
  90.       case 'utf8':
  91.       case 'utf-8':
  92.         return 'utf8';
  93.       case 'ucs2':
  94.       case 'ucs-2':
  95.       case 'utf16le':
  96.       case 'utf-16le':
  97.         return 'utf16le';
  98.       case 'latin1':
  99.       case 'binary':
  100.         return 'latin1';
  101.       case 'base64':
  102.       case 'ascii':
  103.       case 'hex':
  104.         return enc;
  105.       default:
  106.         if (retried) return; // undefined
  107.         enc = ('' + enc).toLowerCase();
  108.         retried = true;
  109.     }
  110.   }
  111. }
  112.  
  113. function emitExperimentalWarning(feature) {
  114.   if (experimentalWarnings.has(feature)) return;
  115.   const msg = `${feature} is an experimental feature. This feature could ` +
  116.        'change at any time';
  117.   experimentalWarnings.add(feature);
  118.   process.emitWarning(msg, 'ExperimentalWarning');
  119. }
  120.  
  121. function filterDuplicateStrings(items, low) {
  122.   const map = new Map();
  123.   for (var i = 0; i < items.length; i++) {
  124.     const item = items[i];
  125.     const key = item.toLowerCase();
  126.     if (low) {
  127.       map.set(key, key);
  128.     } else {
  129.       map.set(key, item);
  130.     }
  131.   }
  132.   return Array.from(map.values()).sort();
  133. }
  134.  
  135. function cachedResult(fn) {
  136.   var result;
  137.   return () => {
  138.     if (result === undefined)
  139.       result = fn();
  140.     return result.slice();
  141.   };
  142. }
  143.  
  144. // Useful for Wrapping an ES6 Class with a constructor Function that
  145. // does not require the new keyword. For instance:
  146. //   class A { constructor(x) {this.x = x;}}
  147. //   const B = createClassWrapper(A);
  148. //   B() instanceof A // true
  149. //   B() instanceof B // true
  150. function createClassWrapper(type) {
  151.   function fn(...args) {
  152.     return Reflect.construct(type, args, new.target || type);
  153.   }
  154.   // Mask the wrapper function name and length values
  155.   Object.defineProperties(fn, {
  156.     name: { value: type.name },
  157.     length: { value: type.length }
  158.   });
  159.   Object.setPrototypeOf(fn, type);
  160.   fn.prototype = type.prototype;
  161.   return fn;
  162. }
  163.  
  164. let signalsToNamesMapping;
  165. function getSignalsToNamesMapping() {
  166.   if (signalsToNamesMapping !== undefined)
  167.     return signalsToNamesMapping;
  168.  
  169.   signalsToNamesMapping = Object.create(null);
  170.   for (var key in signals) {
  171.     signalsToNamesMapping[signals[key]] = key;
  172.   }
  173.  
  174.   return signalsToNamesMapping;
  175. }
  176.  
  177. function convertToValidSignal(signal) {
  178.   if (typeof signal === 'number' && getSignalsToNamesMapping()[signal])
  179.     return signal;
  180.  
  181.   if (typeof signal === 'string') {
  182.     const signalName = signals[signal.toUpperCase()];
  183.     if (signalName) return signalName;
  184.   }
  185.  
  186.   throw new errors.Error('ERR_UNKNOWN_SIGNAL', signal);
  187. }
  188.  
  189. function getConstructorOf(obj) {
  190.   while (obj) {
  191.     var descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor');
  192.     if (descriptor !== undefined &&
  193.         typeof descriptor.value === 'function' &&
  194.         descriptor.value.name !== '') {
  195.       return descriptor.value;
  196.     }
  197.  
  198.     obj = Object.getPrototypeOf(obj);
  199.   }
  200.  
  201.   return null;
  202. }
  203.  
  204. const kCustomPromisifiedSymbol = Symbol('util.promisify.custom');
  205. const kCustomPromisifyArgsSymbol = Symbol('customPromisifyArgs');
  206.  
  207. function promisify(orig) {
  208.   if (typeof orig !== 'function')
  209.     throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'original', 'function');
  210.  
  211.   if (orig[kCustomPromisifiedSymbol]) {
  212.     const fn = orig[kCustomPromisifiedSymbol];
  213.     if (typeof fn !== 'function') {
  214.       throw new TypeError('The [util.promisify.custom] property must be ' +
  215.                           'a function');
  216.     }
  217.     Object.defineProperty(fn, kCustomPromisifiedSymbol, {
  218.       value: fn, enumerable: false, writable: false, configurable: true
  219.     });
  220.     return fn;
  221.   }
  222.  
  223.   // Names to create an object from in case the callback receives multiple
  224.   // arguments, e.g. ['stdout', 'stderr'] for child_process.exec.
  225.   const argumentNames = orig[kCustomPromisifyArgsSymbol];
  226.  
  227.   function fn(...args) {
  228.     const promise = createPromise();
  229.     try {
  230.       orig.call(this, ...args, (err, ...values) => {
  231.         if (err) {
  232.           promiseReject(promise, err);
  233.         } else if (argumentNames !== undefined && values.length > 1) {
  234.           const obj = {};
  235.           for (var i = 0; i < argumentNames.length; i++)
  236.             obj[argumentNames[i]] = values[i];
  237.           promiseResolve(promise, obj);
  238.         } else {
  239.           promiseResolve(promise, values[0]);
  240.         }
  241.       });
  242.     } catch (err) {
  243.       promiseReject(promise, err);
  244.     }
  245.     return promise;
  246.   }
  247.  
  248.   Object.setPrototypeOf(fn, Object.getPrototypeOf(orig));
  249.  
  250.   Object.defineProperty(fn, kCustomPromisifiedSymbol, {
  251.     value: fn, enumerable: false, writable: false, configurable: true
  252.   });
  253.   return Object.defineProperties(fn, Object.getOwnPropertyDescriptors(orig));
  254. }
  255.  
  256. promisify.custom = kCustomPromisifiedSymbol;
  257.  
  258. // The build-in Array#join is slower in v8 6.0
  259. function join(output, separator) {
  260.   var str = '';
  261.   if (output.length !== 0) {
  262.     for (var i = 0; i < output.length - 1; i++) {
  263.       // It is faster not to use a template string here
  264.       str += output[i];
  265.       str += separator;
  266.     }
  267.     str += output[i];
  268.   }
  269.   return str;
  270. }
  271.  
  272. // About 1.5x faster than the two-arg version of Array#splice().
  273. function spliceOne(list, index) {
  274.   for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
  275.     list[i] = list[k];
  276.   list.pop();
  277. }
  278.  
  279. module.exports = {
  280.   assertCrypto,
  281.   cachedResult,
  282.   convertToValidSignal,
  283.   createClassWrapper,
  284.   decorateErrorStack,
  285.   deprecate,
  286.   emitExperimentalWarning,
  287.   filterDuplicateStrings,
  288.   getConstructorOf,
  289.   isError,
  290.   join,
  291.   normalizeEncoding,
  292.   objectToString,
  293.   promisify,
  294.   spliceOne,
  295.  
  296.   // Symbol used to customize promisify conversion
  297.   customPromisifyArgs: kCustomPromisifyArgsSymbol,
  298.  
  299.   // Symbol used to provide a custom inspect function for an object as an
  300.   // alternative to using 'inspect'
  301.   customInspectSymbol: Symbol('util.inspect.custom'),
  302.  
  303.   // Used by the buffer module to capture an internal reference to the
  304.   // default isEncoding implementation, just in case userland overrides it.
  305.   kIsEncodingSymbol: Symbol('node.isEncoding')
  306. };

Raw Paste


Login or Register to edit or fork this paste. It's free.