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.

307 lines
9.6 KiB

4 years ago
  1. var hasMap = typeof Map === 'function' && Map.prototype;
  2. var mapSizeDescriptor = Object.getOwnPropertyDescriptor && hasMap ? Object.getOwnPropertyDescriptor(Map.prototype, 'size') : null;
  3. var mapSize = hasMap && mapSizeDescriptor && typeof mapSizeDescriptor.get === 'function' ? mapSizeDescriptor.get : null;
  4. var mapForEach = hasMap && Map.prototype.forEach;
  5. var hasSet = typeof Set === 'function' && Set.prototype;
  6. var setSizeDescriptor = Object.getOwnPropertyDescriptor && hasSet ? Object.getOwnPropertyDescriptor(Set.prototype, 'size') : null;
  7. var setSize = hasSet && setSizeDescriptor && typeof setSizeDescriptor.get === 'function' ? setSizeDescriptor.get : null;
  8. var setForEach = hasSet && Set.prototype.forEach;
  9. var hasWeakMap = typeof WeakMap === 'function' && WeakMap.prototype;
  10. var weakMapHas = hasWeakMap ? WeakMap.prototype.has : null;
  11. var hasWeakSet = typeof WeakSet === 'function' && WeakSet.prototype;
  12. var weakSetHas = hasWeakSet ? WeakSet.prototype.has : null;
  13. var booleanValueOf = Boolean.prototype.valueOf;
  14. var objectToString = Object.prototype.toString;
  15. var match = String.prototype.match;
  16. var bigIntValueOf = typeof BigInt === 'function' ? BigInt.prototype.valueOf : null;
  17. var inspectCustom = require('./util.inspect').custom;
  18. var inspectSymbol = inspectCustom && isSymbol(inspectCustom) ? inspectCustom : null;
  19. module.exports = function inspect_(obj, options, depth, seen) {
  20. var opts = options || {};
  21. if (has(opts, 'quoteStyle') && (opts.quoteStyle !== 'single' && opts.quoteStyle !== 'double')) {
  22. throw new TypeError('option "quoteStyle" must be "single" or "double"');
  23. }
  24. if (typeof obj === 'undefined') {
  25. return 'undefined';
  26. }
  27. if (obj === null) {
  28. return 'null';
  29. }
  30. if (typeof obj === 'boolean') {
  31. return obj ? 'true' : 'false';
  32. }
  33. if (typeof obj === 'string') {
  34. return inspectString(obj, opts);
  35. }
  36. if (typeof obj === 'number') {
  37. if (obj === 0) {
  38. return Infinity / obj > 0 ? '0' : '-0';
  39. }
  40. return String(obj);
  41. }
  42. if (typeof obj === 'bigint') { // eslint-disable-line valid-typeof
  43. return String(obj) + 'n';
  44. }
  45. var maxDepth = typeof opts.depth === 'undefined' ? 5 : opts.depth;
  46. if (typeof depth === 'undefined') { depth = 0; }
  47. if (depth >= maxDepth && maxDepth > 0 && typeof obj === 'object') {
  48. return '[Object]';
  49. }
  50. if (typeof seen === 'undefined') {
  51. seen = [];
  52. } else if (indexOf(seen, obj) >= 0) {
  53. return '[Circular]';
  54. }
  55. function inspect(value, from) {
  56. if (from) {
  57. seen = seen.slice();
  58. seen.push(from);
  59. }
  60. return inspect_(value, opts, depth + 1, seen);
  61. }
  62. if (typeof obj === 'function') {
  63. var name = nameOf(obj);
  64. return '[Function' + (name ? ': ' + name : '') + ']';
  65. }
  66. if (isSymbol(obj)) {
  67. var symString = Symbol.prototype.toString.call(obj);
  68. return typeof obj === 'object' ? markBoxed(symString) : symString;
  69. }
  70. if (isElement(obj)) {
  71. var s = '<' + String(obj.nodeName).toLowerCase();
  72. var attrs = obj.attributes || [];
  73. for (var i = 0; i < attrs.length; i++) {
  74. s += ' ' + attrs[i].name + '=' + wrapQuotes(quote(attrs[i].value), 'double', opts);
  75. }
  76. s += '>';
  77. if (obj.childNodes && obj.childNodes.length) { s += '...'; }
  78. s += '</' + String(obj.nodeName).toLowerCase() + '>';
  79. return s;
  80. }
  81. if (isArray(obj)) {
  82. if (obj.length === 0) { return '[]'; }
  83. return '[ ' + arrObjKeys(obj, inspect).join(', ') + ' ]';
  84. }
  85. if (isError(obj)) {
  86. var parts = arrObjKeys(obj, inspect);
  87. if (parts.length === 0) { return '[' + String(obj) + ']'; }
  88. return '{ [' + String(obj) + '] ' + parts.join(', ') + ' }';
  89. }
  90. if (typeof obj === 'object') {
  91. if (inspectSymbol && typeof obj[inspectSymbol] === 'function') {
  92. return obj[inspectSymbol]();
  93. } else if (typeof obj.inspect === 'function') {
  94. return obj.inspect();
  95. }
  96. }
  97. if (isMap(obj)) {
  98. var mapParts = [];
  99. mapForEach.call(obj, function (value, key) {
  100. mapParts.push(inspect(key, obj) + ' => ' + inspect(value, obj));
  101. });
  102. return collectionOf('Map', mapSize.call(obj), mapParts);
  103. }
  104. if (isSet(obj)) {
  105. var setParts = [];
  106. setForEach.call(obj, function (value) {
  107. setParts.push(inspect(value, obj));
  108. });
  109. return collectionOf('Set', setSize.call(obj), setParts);
  110. }
  111. if (isWeakMap(obj)) {
  112. return weakCollectionOf('WeakMap');
  113. }
  114. if (isWeakSet(obj)) {
  115. return weakCollectionOf('WeakSet');
  116. }
  117. if (isNumber(obj)) {
  118. return markBoxed(inspect(Number(obj)));
  119. }
  120. if (isBigInt(obj)) {
  121. return markBoxed(inspect(bigIntValueOf.call(obj)));
  122. }
  123. if (isBoolean(obj)) {
  124. return markBoxed(booleanValueOf.call(obj));
  125. }
  126. if (isString(obj)) {
  127. return markBoxed(inspect(String(obj)));
  128. }
  129. if (!isDate(obj) && !isRegExp(obj)) {
  130. var xs = arrObjKeys(obj, inspect);
  131. if (xs.length === 0) { return '{}'; }
  132. return '{ ' + xs.join(', ') + ' }';
  133. }
  134. return String(obj);
  135. };
  136. function wrapQuotes(s, defaultStyle, opts) {
  137. var quoteChar = (opts.quoteStyle || defaultStyle) === 'double' ? '"' : "'";
  138. return quoteChar + s + quoteChar;
  139. }
  140. function quote(s) {
  141. return String(s).replace(/"/g, '&quot;');
  142. }
  143. function isArray(obj) { return toStr(obj) === '[object Array]'; }
  144. function isDate(obj) { return toStr(obj) === '[object Date]'; }
  145. function isRegExp(obj) { return toStr(obj) === '[object RegExp]'; }
  146. function isError(obj) { return toStr(obj) === '[object Error]'; }
  147. function isSymbol(obj) { return toStr(obj) === '[object Symbol]'; }
  148. function isString(obj) { return toStr(obj) === '[object String]'; }
  149. function isNumber(obj) { return toStr(obj) === '[object Number]'; }
  150. function isBigInt(obj) { return toStr(obj) === '[object BigInt]'; }
  151. function isBoolean(obj) { return toStr(obj) === '[object Boolean]'; }
  152. var hasOwn = Object.prototype.hasOwnProperty || function (key) { return key in this; };
  153. function has(obj, key) {
  154. return hasOwn.call(obj, key);
  155. }
  156. function toStr(obj) {
  157. return objectToString.call(obj);
  158. }
  159. function nameOf(f) {
  160. if (f.name) { return f.name; }
  161. var m = match.call(f, /^function\s*([\w$]+)/);
  162. if (m) { return m[1]; }
  163. return null;
  164. }
  165. function indexOf(xs, x) {
  166. if (xs.indexOf) { return xs.indexOf(x); }
  167. for (var i = 0, l = xs.length; i < l; i++) {
  168. if (xs[i] === x) { return i; }
  169. }
  170. return -1;
  171. }
  172. function isMap(x) {
  173. if (!mapSize || !x || typeof x !== 'object') {
  174. return false;
  175. }
  176. try {
  177. mapSize.call(x);
  178. try {
  179. setSize.call(x);
  180. } catch (s) {
  181. return true;
  182. }
  183. return x instanceof Map; // core-js workaround, pre-v2.5.0
  184. } catch (e) {}
  185. return false;
  186. }
  187. function isWeakMap(x) {
  188. if (!weakMapHas || !x || typeof x !== 'object') {
  189. return false;
  190. }
  191. try {
  192. weakMapHas.call(x, weakMapHas);
  193. try {
  194. weakSetHas.call(x, weakSetHas);
  195. } catch (s) {
  196. return true;
  197. }
  198. return x instanceof WeakMap; // core-js workaround, pre-v2.5.0
  199. } catch (e) {}
  200. return false;
  201. }
  202. function isSet(x) {
  203. if (!setSize || !x || typeof x !== 'object') {
  204. return false;
  205. }
  206. try {
  207. setSize.call(x);
  208. try {
  209. mapSize.call(x);
  210. } catch (m) {
  211. return true;
  212. }
  213. return x instanceof Set; // core-js workaround, pre-v2.5.0
  214. } catch (e) {}
  215. return false;
  216. }
  217. function isWeakSet(x) {
  218. if (!weakSetHas || !x || typeof x !== 'object') {
  219. return false;
  220. }
  221. try {
  222. weakSetHas.call(x, weakSetHas);
  223. try {
  224. weakMapHas.call(x, weakMapHas);
  225. } catch (s) {
  226. return true;
  227. }
  228. return x instanceof WeakSet; // core-js workaround, pre-v2.5.0
  229. } catch (e) {}
  230. return false;
  231. }
  232. function isElement(x) {
  233. if (!x || typeof x !== 'object') { return false; }
  234. if (typeof HTMLElement !== 'undefined' && x instanceof HTMLElement) {
  235. return true;
  236. }
  237. return typeof x.nodeName === 'string' && typeof x.getAttribute === 'function';
  238. }
  239. function inspectString(str, opts) {
  240. // eslint-disable-next-line no-control-regex
  241. var s = str.replace(/(['\\])/g, '\\$1').replace(/[\x00-\x1f]/g, lowbyte);
  242. return wrapQuotes(s, 'single', opts);
  243. }
  244. function lowbyte(c) {
  245. var n = c.charCodeAt(0);
  246. var x = {
  247. 8: 'b', 9: 't', 10: 'n', 12: 'f', 13: 'r'
  248. }[n];
  249. if (x) { return '\\' + x; }
  250. return '\\x' + (n < 0x10 ? '0' : '') + n.toString(16);
  251. }
  252. function markBoxed(str) {
  253. return 'Object(' + str + ')';
  254. }
  255. function weakCollectionOf(type) {
  256. return type + ' { ? }';
  257. }
  258. function collectionOf(type, size, entries) {
  259. return type + ' (' + size + ') {' + entries.join(', ') + '}';
  260. }
  261. function arrObjKeys(obj, inspect) {
  262. var isArr = isArray(obj);
  263. var xs = [];
  264. if (isArr) {
  265. xs.length = obj.length;
  266. for (var i = 0; i < obj.length; i++) {
  267. xs[i] = has(obj, i) ? inspect(obj[i], obj) : '';
  268. }
  269. }
  270. for (var key in obj) { // eslint-disable-line no-restricted-syntax
  271. if (!has(obj, key)) { continue; } // eslint-disable-line no-restricted-syntax, no-continue
  272. if (isArr && String(Number(key)) === key && key < obj.length) { continue; } // eslint-disable-line no-restricted-syntax, no-continue
  273. if ((/[^\w$]/).test(key)) {
  274. xs.push(inspect(key, obj) + ': ' + inspect(obj[key], obj));
  275. } else {
  276. xs.push(key + ': ' + inspect(obj[key], obj));
  277. }
  278. }
  279. return xs;
  280. }