mocha-compat 3.6.4 → 10.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +61 -110
  3. package/bin/_mocha +10 -0
  4. package/bin/mocha.js +142 -0
  5. package/browser-entry.js +61 -22
  6. package/lib/browser/highlight-tags.js +39 -0
  7. package/lib/browser/parse-query.js +24 -0
  8. package/lib/{template.html → browser/template.html} +7 -5
  9. package/lib/cli/cli.js +89 -0
  10. package/lib/cli/collect-files.js +137 -0
  11. package/lib/cli/commands.js +14 -0
  12. package/lib/cli/config.js +100 -0
  13. package/lib/cli/index.js +3 -0
  14. package/lib/cli/init.js +36 -0
  15. package/lib/cli/lookup-files.js +150 -0
  16. package/lib/cli/node-flags.js +85 -0
  17. package/lib/cli/one-and-dones.js +69 -0
  18. package/lib/cli/options.js +284 -0
  19. package/lib/cli/run-helpers.js +304 -0
  20. package/lib/cli/run-option-metadata.js +116 -0
  21. package/lib/cli/run.js +380 -0
  22. package/lib/cli/watch-run.js +377 -0
  23. package/lib/context.js +16 -42
  24. package/lib/errors.js +563 -0
  25. package/lib/hook.js +50 -9
  26. package/lib/interfaces/bdd.js +28 -29
  27. package/lib/interfaces/common.js +56 -21
  28. package/lib/interfaces/exports.js +4 -7
  29. package/lib/interfaces/qunit.js +10 -11
  30. package/lib/interfaces/tdd.js +15 -15
  31. package/lib/mocha.js +1073 -292
  32. package/lib/mocharc.json +10 -0
  33. package/lib/nodejs/buffered-worker-pool.js +188 -0
  34. package/lib/nodejs/esm-utils.js +106 -0
  35. package/lib/nodejs/file-unloader.js +15 -0
  36. package/lib/nodejs/parallel-buffered-runner.js +433 -0
  37. package/lib/nodejs/reporters/parallel-buffered.js +165 -0
  38. package/lib/nodejs/serializer.js +414 -0
  39. package/lib/nodejs/worker.js +151 -0
  40. package/lib/pending.js +3 -3
  41. package/lib/plugin-loader.js +286 -0
  42. package/lib/reporters/base.js +305 -205
  43. package/lib/reporters/doc.js +52 -21
  44. package/lib/reporters/dot.js +31 -18
  45. package/lib/reporters/html.js +153 -81
  46. package/lib/reporters/json-stream.js +53 -24
  47. package/lib/reporters/json.js +88 -18
  48. package/lib/reporters/landing.js +38 -16
  49. package/lib/reporters/list.js +34 -19
  50. package/lib/reporters/markdown.js +28 -15
  51. package/lib/reporters/min.js +22 -8
  52. package/lib/reporters/nyan.js +62 -58
  53. package/lib/reporters/progress.js +32 -19
  54. package/lib/reporters/spec.js +41 -23
  55. package/lib/reporters/tap.js +255 -32
  56. package/lib/reporters/xunit.js +89 -39
  57. package/lib/runnable.js +233 -148
  58. package/lib/runner.js +679 -380
  59. package/lib/stats-collector.js +83 -0
  60. package/lib/suite.js +376 -112
  61. package/lib/test.js +82 -21
  62. package/lib/utils.js +364 -477
  63. package/mocha.css +183 -54
  64. package/mocha.js +19840 -15846
  65. package/mocha.js.map +1 -0
  66. package/package.json +163 -336
  67. package/{lib/to-iso-string → vendor/serialize-javascript}/LICENSE +8 -6
  68. package/vendor/serialize-javascript/README.md +10 -0
  69. package/vendor/serialize-javascript/index.js +349 -0
  70. package/bin/_mocha-compat +0 -572
  71. package/bin/mocha-compat +0 -87
  72. package/bin/options.js +0 -41
  73. package/bower.json +0 -38
  74. package/images/error.png +0 -0
  75. package/images/ok.png +0 -0
  76. package/lib/browser/.eslintrc.yaml +0 -4
  77. package/lib/browser/debug.js +0 -7
  78. package/lib/browser/events.js +0 -195
  79. package/lib/browser/progress.js +0 -119
  80. package/lib/browser/tty.js +0 -13
  81. package/lib/ms.js +0 -130
  82. package/lib/to-iso-string/index.js +0 -37
  83. package/vendor/glob/LICENSE +0 -15
  84. package/vendor/glob/README.md +0 -399
  85. package/vendor/glob/common.js +0 -244
  86. package/vendor/glob/glob.js +0 -788
  87. package/vendor/glob/package.json +0 -55
  88. package/vendor/glob/sync.js +0 -486
  89. package/vendor/inflight/LICENSE +0 -15
  90. package/vendor/inflight/README.md +0 -37
  91. package/vendor/inflight/inflight.js +0 -54
  92. package/vendor/inflight/package.json +0 -29
package/lib/utils.js CHANGED
@@ -1,62 +1,45 @@
1
1
  'use strict';
2
2
 
3
- /* eslint-env browser */
3
+ /**
4
+ * Various utility functions used throughout Mocha's codebase.
5
+ * @module utils
6
+ */
4
7
 
5
8
  /**
6
9
  * Module dependencies.
7
10
  */
8
-
9
- var JSON = require('json3');
10
- var basename = require('path').basename;
11
- var debug = require('debug')('mocha:watch');
12
- var exists = require('fs').existsSync || require('path').existsSync;
13
- var glob = require('../vendor/glob/glob.js');
14
11
  var path = require('path');
15
- var join = path.join;
16
- var readdirSync = require('fs').readdirSync;
17
- var statSync = require('fs').statSync;
18
- var watchFile = require('fs').watchFile;
19
- var lstatSync = require('fs').lstatSync;
20
- var toISOString = require('./to-iso-string');
12
+ var util = require('util');
21
13
  var he = require('he');
22
14
 
15
+ const MOCHA_ID_PROP_NAME = '__mocha_id__';
16
+
23
17
  /**
24
- * Ignored directories.
18
+ * Inherit the prototype methods from one constructor into another.
19
+ *
20
+ * @param {function} ctor - Constructor function which needs to inherit the
21
+ * prototype.
22
+ * @param {function} superCtor - Constructor function to inherit prototype from.
23
+ * @throws {TypeError} if either constructor is null, or if super constructor
24
+ * lacks a prototype.
25
25
  */
26
-
27
- var ignore = ['node_modules', '.git'];
28
-
29
- exports.inherits = require('util').inherits;
26
+ exports.inherits = util.inherits;
30
27
 
31
28
  /**
32
29
  * Escape special characters in the given string of html.
33
30
  *
34
- * @api private
31
+ * @private
35
32
  * @param {string} html
36
33
  * @return {string}
37
34
  */
38
35
  exports.escape = function (html) {
39
- return he.encode(String(html), { useNamedReferences: false });
40
- };
41
-
42
- /**
43
- * Array#forEach (<=IE8)
44
- *
45
- * @api private
46
- * @param {Array} arr
47
- * @param {Function} fn
48
- * @param {Object} scope
49
- */
50
- exports.forEach = function (arr, fn, scope) {
51
- for (var i = 0, l = arr.length; i < l; i++) {
52
- fn.call(scope, arr[i], i);
53
- }
36
+ return he.encode(String(html), {useNamedReferences: false});
54
37
  };
55
38
 
56
39
  /**
57
40
  * Test if the given obj is type of string.
58
41
  *
59
- * @api private
42
+ * @private
60
43
  * @param {Object} obj
61
44
  * @return {boolean}
62
45
  */
@@ -64,214 +47,19 @@ exports.isString = function (obj) {
64
47
  return typeof obj === 'string';
65
48
  };
66
49
 
67
- /**
68
- * Array#map (<=IE8)
69
- *
70
- * @api private
71
- * @param {Array} arr
72
- * @param {Function} fn
73
- * @param {Object} scope
74
- * @return {Array}
75
- */
76
- exports.map = function (arr, fn, scope) {
77
- var result = [];
78
- for (var i = 0, l = arr.length; i < l; i++) {
79
- result.push(fn.call(scope, arr[i], i, arr));
80
- }
81
- return result;
82
- };
83
-
84
- /**
85
- * Array#indexOf (<=IE8)
86
- *
87
- * @api private
88
- * @param {Array} arr
89
- * @param {Object} obj to find index of
90
- * @param {number} start
91
- * @return {number}
92
- */
93
- var indexOf = exports.indexOf = function (arr, obj, start) {
94
- for (var i = start || 0, l = arr.length; i < l; i++) {
95
- if (arr[i] === obj) {
96
- return i;
97
- }
98
- }
99
- return -1;
100
- };
101
-
102
- /**
103
- * Array#reduce (<=IE8)
104
- *
105
- * @api private
106
- * @param {Array} arr
107
- * @param {Function} fn
108
- * @param {Object} val Initial value.
109
- * @return {*}
110
- */
111
- var reduce = exports.reduce = function (arr, fn, val) {
112
- var rval = val;
113
-
114
- for (var i = 0, l = arr.length; i < l; i++) {
115
- rval = fn(rval, arr[i], i, arr);
116
- }
117
-
118
- return rval;
119
- };
120
-
121
- /**
122
- * Array#filter (<=IE8)
123
- *
124
- * @api private
125
- * @param {Array} arr
126
- * @param {Function} fn
127
- * @return {Array}
128
- */
129
- exports.filter = function (arr, fn) {
130
- var ret = [];
131
-
132
- for (var i = 0, l = arr.length; i < l; i++) {
133
- var val = arr[i];
134
- if (fn(val, i, arr)) {
135
- ret.push(val);
136
- }
137
- }
138
-
139
- return ret;
140
- };
141
-
142
- /**
143
- * Array#some (<=IE8)
144
- *
145
- * @api private
146
- * @param {Array} arr
147
- * @param {Function} fn
148
- * @return {Array}
149
- */
150
- exports.some = function (arr, fn) {
151
- for (var i = 0, l = arr.length; i < l; i++) {
152
- if (fn(arr[i])) {
153
- return true;
154
- }
155
- }
156
- return false;
157
- };
158
-
159
- /**
160
- * Object.keys (<=IE8)
161
- *
162
- * @api private
163
- * @param {Object} obj
164
- * @return {Array} keys
165
- */
166
- exports.keys = typeof Object.keys === 'function' ? Object.keys : function (obj) {
167
- var keys = [];
168
- var has = Object.prototype.hasOwnProperty; // for `window` on <=IE8
169
-
170
- for (var key in obj) {
171
- if (has.call(obj, key)) {
172
- keys.push(key);
173
- }
174
- }
175
-
176
- return keys;
177
- };
178
-
179
- /**
180
- * Watch the given `files` for changes
181
- * and invoke `fn(file)` on modification.
182
- *
183
- * @api private
184
- * @param {Array} files
185
- * @param {Function} fn
186
- */
187
- exports.watch = function (files, fn) {
188
- var options = { interval: 100 };
189
- files.forEach(function (file) {
190
- debug('file %s', file);
191
- watchFile(file, options, function (curr, prev) {
192
- if (prev.mtime < curr.mtime) {
193
- fn(file);
194
- }
195
- });
196
- });
197
- };
198
-
199
- /**
200
- * Array.isArray (<=IE8)
201
- *
202
- * @api private
203
- * @param {Object} obj
204
- * @return {Boolean}
205
- */
206
- var isArray = typeof Array.isArray === 'function' ? Array.isArray : function (obj) {
207
- return Object.prototype.toString.call(obj) === '[object Array]';
208
- };
209
-
210
- exports.isArray = isArray;
211
-
212
- /**
213
- * Buffer.prototype.toJSON polyfill.
214
- *
215
- * @type {Function}
216
- */
217
- if (typeof Buffer !== 'undefined' && Buffer.prototype) {
218
- Buffer.prototype.toJSON = Buffer.prototype.toJSON || function () {
219
- return Array.prototype.slice.call(this, 0);
220
- };
221
- }
222
-
223
- /**
224
- * Ignored files.
225
- *
226
- * @api private
227
- * @param {string} path
228
- * @return {boolean}
229
- */
230
- function ignored (path) {
231
- return !~ignore.indexOf(path);
232
- }
233
-
234
- /**
235
- * Lookup files in the given `dir`.
236
- *
237
- * @api private
238
- * @param {string} dir
239
- * @param {string[]} [ext=['.js']]
240
- * @param {Array} [ret=[]]
241
- * @return {Array}
242
- */
243
- exports.files = function (dir, ext, ret) {
244
- ret = ret || [];
245
- ext = ext || ['js'];
246
-
247
- var re = new RegExp('\\.(' + ext.join('|') + ')$');
248
-
249
- readdirSync(dir)
250
- .filter(ignored)
251
- .forEach(function (path) {
252
- path = join(dir, path);
253
- if (lstatSync(path).isDirectory()) {
254
- exports.files(path, ext, ret);
255
- } else if (path.match(re)) {
256
- ret.push(path);
257
- }
258
- });
259
-
260
- return ret;
261
- };
262
-
263
50
  /**
264
51
  * Compute a slug from the given `str`.
265
52
  *
266
- * @api private
53
+ * @private
267
54
  * @param {string} str
268
55
  * @return {string}
269
56
  */
270
57
  exports.slug = function (str) {
271
58
  return str
272
59
  .toLowerCase()
273
- .replace(/ +/g, '-')
274
- .replace(/[^-\w]/g, '');
60
+ .replace(/\s+/g, '-')
61
+ .replace(/[^-\w]/g, '')
62
+ .replace(/-{2,}/g, '-');
275
63
  };
276
64
 
277
65
  /**
@@ -282,80 +70,24 @@ exports.slug = function (str) {
282
70
  */
283
71
  exports.clean = function (str) {
284
72
  str = str
285
- .replace(/\r\n?|[\n\u2028\u2029]/g, '\n').replace(/^\uFEFF/, '')
73
+ .replace(/\r\n?|[\n\u2028\u2029]/g, '\n')
74
+ .replace(/^\uFEFF/, '')
286
75
  // (traditional)-> space/name parameters body (lambda)-> parameters body multi-statement/single keep body content
287
- .replace(/^function(?:\s*|\s+[^(]*)\([^)]*\)\s*\{((?:.|\n)*?)\s*\}$|^\([^)]*\)\s*=>\s*(?:\{((?:.|\n)*?)\s*\}|((?:.|\n)*))$/, '$1$2$3');
76
+ .replace(
77
+ /^function(?:\s*|\s[^(]*)\([^)]*\)\s*\{((?:.|\n)*?)\}$|^\([^)]*\)\s*=>\s*(?:\{((?:.|\n)*?)\}|((?:.|\n)*))$/,
78
+ '$1$2$3'
79
+ );
288
80
 
289
81
  var spaces = str.match(/^\n?( *)/)[1].length;
290
82
  var tabs = str.match(/^\n?(\t*)/)[1].length;
291
- var re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs || spaces) + '}', 'gm');
83
+ var re = new RegExp(
84
+ '^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs || spaces) + '}',
85
+ 'gm'
86
+ );
292
87
 
293
88
  str = str.replace(re, '');
294
89
 
295
- return exports.trim(str);
296
- };
297
-
298
- /**
299
- * Trim the given `str`.
300
- *
301
- * @api private
302
- * @param {string} str
303
- * @return {string}
304
- */
305
- exports.trim = function (str) {
306
- return str.replace(/^\s+|\s+$/g, '');
307
- };
308
-
309
- /**
310
- * Parse the given `qs`.
311
- *
312
- * @api private
313
- * @param {string} qs
314
- * @return {Object}
315
- */
316
- exports.parseQuery = function (qs) {
317
- return reduce(qs.replace('?', '').split('&'), function (obj, pair) {
318
- var i = pair.indexOf('=');
319
- var key = pair.slice(0, i);
320
- var val = pair.slice(++i);
321
-
322
- // Due to how the URLSearchParams API treats spaces
323
- obj[key] = decodeURIComponent(val.replace(/\+/g, '%20'));
324
-
325
- return obj;
326
- }, {});
327
- };
328
-
329
- /**
330
- * Highlight the given string of `js`.
331
- *
332
- * @api private
333
- * @param {string} js
334
- * @return {string}
335
- */
336
- function highlight (js) {
337
- return js
338
- .replace(/</g, '&lt;')
339
- .replace(/>/g, '&gt;')
340
- .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
341
- .replace(/('.*?')/gm, '<span class="string">$1</span>')
342
- .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
343
- .replace(/(\d+)/gm, '<span class="number">$1</span>')
344
- .replace(/\bnew[ \t]+(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
345
- .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>');
346
- }
347
-
348
- /**
349
- * Highlight the contents of tag `name`.
350
- *
351
- * @api private
352
- * @param {string} name
353
- */
354
- exports.highlightTags = function (name) {
355
- var code = document.getElementById('mocha').getElementsByTagName(name);
356
- for (var i = 0, len = code.length; i < len; ++i) {
357
- code[i].innerHTML = highlight(code[i].innerHTML);
358
- }
90
+ return str.trim();
359
91
  };
360
92
 
361
93
  /**
@@ -367,12 +99,12 @@ exports.highlightTags = function (name) {
367
99
  * Objects w/ no properties return `'{}'`
368
100
  * All else: return result of `value.toString()`
369
101
  *
370
- * @api private
102
+ * @private
371
103
  * @param {*} value The value to inspect.
372
104
  * @param {string} typeHint The type of the value
373
105
  * @returns {string}
374
106
  */
375
- function emptyRepresentation (value, typeHint) {
107
+ function emptyRepresentation(value, typeHint) {
376
108
  switch (typeHint) {
377
109
  case 'function':
378
110
  return '[Function]';
@@ -389,34 +121,81 @@ function emptyRepresentation (value, typeHint) {
389
121
  * Takes some variable and asks `Object.prototype.toString()` what it thinks it
390
122
  * is.
391
123
  *
392
- * @api private
124
+ * @private
393
125
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
394
126
  * @param {*} value The value to test.
395
127
  * @returns {string} Computed type
396
128
  * @example
397
- * type({}) // 'object'
398
- * type([]) // 'array'
399
- * type(1) // 'number'
400
- * type(false) // 'boolean'
401
- * type(Infinity) // 'number'
402
- * type(null) // 'null'
403
- * type(new Date()) // 'date'
404
- * type(/foo/) // 'regexp'
405
- * type('type') // 'string'
406
- * type(global) // 'global'
407
- * type(new String('foo') // 'object'
408
- */
409
- var type = exports.type = function type (value) {
129
+ * canonicalType({}) // 'object'
130
+ * canonicalType([]) // 'array'
131
+ * canonicalType(1) // 'number'
132
+ * canonicalType(false) // 'boolean'
133
+ * canonicalType(Infinity) // 'number'
134
+ * canonicalType(null) // 'null'
135
+ * canonicalType(new Date()) // 'date'
136
+ * canonicalType(/foo/) // 'regexp'
137
+ * canonicalType('type') // 'string'
138
+ * canonicalType(global) // 'global'
139
+ * canonicalType(new String('foo') // 'object'
140
+ * canonicalType(async function() {}) // 'asyncfunction'
141
+ * canonicalType(Object.create(null)) // 'null-prototype'
142
+ */
143
+ var canonicalType = (exports.canonicalType = function canonicalType(value) {
410
144
  if (value === undefined) {
411
145
  return 'undefined';
412
146
  } else if (value === null) {
413
147
  return 'null';
414
- } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
148
+ } else if (Buffer.isBuffer(value)) {
415
149
  return 'buffer';
150
+ } else if (Object.getPrototypeOf(value) === null) {
151
+ return 'null-prototype';
416
152
  }
417
- return Object.prototype.toString.call(value)
153
+
154
+ return Object.prototype.toString
155
+ .call(value)
418
156
  .replace(/^\[.+\s(.+?)]$/, '$1')
419
157
  .toLowerCase();
158
+ });
159
+
160
+ /**
161
+ *
162
+ * Returns a general type or data structure of a variable
163
+ * @private
164
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures
165
+ * @param {*} value The value to test.
166
+ * @returns {string} One of undefined, boolean, number, string, bigint, symbol, object
167
+ * @example
168
+ * type({}) // 'object'
169
+ * type([]) // 'array'
170
+ * type(1) // 'number'
171
+ * type(false) // 'boolean'
172
+ * type(Infinity) // 'number'
173
+ * type(null) // 'null'
174
+ * type(new Date()) // 'object'
175
+ * type(/foo/) // 'object'
176
+ * type('type') // 'string'
177
+ * type(global) // 'object'
178
+ * type(new String('foo') // 'string'
179
+ */
180
+ exports.type = function type(value) {
181
+ // Null is special
182
+ if (value === null) return 'null';
183
+ const primitives = new Set([
184
+ 'undefined',
185
+ 'boolean',
186
+ 'number',
187
+ 'string',
188
+ 'bigint',
189
+ 'symbol'
190
+ ]);
191
+ const _type = typeof value;
192
+ if (_type === 'function') return _type;
193
+ if (primitives.has(_type)) return _type;
194
+ if (value instanceof String) return 'string';
195
+ if (value instanceof Error) return 'error';
196
+ if (Array.isArray(value)) return 'array';
197
+
198
+ return _type;
420
199
  };
421
200
 
422
201
  /**
@@ -429,26 +208,28 @@ var type = exports.type = function type (value) {
429
208
  * - If `value` has properties, call {@link exports.canonicalize} on it, then return result of
430
209
  * JSON.stringify().
431
210
  *
432
- * @api private
211
+ * @private
433
212
  * @see exports.type
434
213
  * @param {*} value
435
214
  * @return {string}
436
215
  */
437
216
  exports.stringify = function (value) {
438
- var typeHint = type(value);
217
+ var typeHint = canonicalType(value);
439
218
 
440
- if (!~indexOf(['object', 'array', 'function'], typeHint)) {
219
+ if (!~['object', 'array', 'function', 'null-prototype'].indexOf(typeHint)) {
441
220
  if (typeHint === 'buffer') {
442
- var json = value.toJSON();
221
+ var json = Buffer.prototype.toJSON.call(value);
443
222
  // Based on the toJSON result
444
- return jsonStringify(json.data && json.type ? json.data : json, 2)
445
- .replace(/,(\n|$)/g, '$1');
223
+ return jsonStringify(
224
+ json.data && json.type ? json.data : json,
225
+ 2
226
+ ).replace(/,(\n|$)/g, '$1');
446
227
  }
447
228
 
448
229
  // IE7/IE8 has a bizarre String constructor; needs to be coerced
449
230
  // into an array and back to obj.
450
231
  if (typeHint === 'string' && typeof value === 'object') {
451
- value = reduce(value.split(''), function (acc, char, idx) {
232
+ value = value.split('').reduce(function (acc, char, idx) {
452
233
  acc[idx] = char;
453
234
  return acc;
454
235
  }, {});
@@ -460,7 +241,10 @@ exports.stringify = function (value) {
460
241
 
461
242
  for (var prop in value) {
462
243
  if (Object.prototype.hasOwnProperty.call(value, prop)) {
463
- return jsonStringify(exports.canonicalize(value, null, typeHint), 2).replace(/,(\n|$)/g, '$1');
244
+ return jsonStringify(
245
+ exports.canonicalize(value, null, typeHint),
246
+ 2
247
+ ).replace(/,(\n|$)/g, '$1');
464
248
  }
465
249
  }
466
250
 
@@ -470,13 +254,13 @@ exports.stringify = function (value) {
470
254
  /**
471
255
  * like JSON.stringify but more sense.
472
256
  *
473
- * @api private
257
+ * @private
474
258
  * @param {Object} object
475
259
  * @param {number=} spaces
476
260
  * @param {number=} depth
477
261
  * @returns {*}
478
262
  */
479
- function jsonStringify (object, spaces, depth) {
263
+ function jsonStringify(object, spaces, depth) {
480
264
  if (typeof spaces === 'undefined') {
481
265
  // primitive types
482
266
  return _stringify(object);
@@ -484,16 +268,19 @@ function jsonStringify (object, spaces, depth) {
484
268
 
485
269
  depth = depth || 1;
486
270
  var space = spaces * depth;
487
- var str = isArray(object) ? '[' : '{';
488
- var end = isArray(object) ? ']' : '}';
489
- var length = typeof object.length === 'number' ? object.length : exports.keys(object).length;
271
+ var str = Array.isArray(object) ? '[' : '{';
272
+ var end = Array.isArray(object) ? ']' : '}';
273
+ var length =
274
+ typeof object.length === 'number'
275
+ ? object.length
276
+ : Object.keys(object).length;
490
277
  // `.repeat()` polyfill
491
- function repeat (s, n) {
278
+ function repeat(s, n) {
492
279
  return new Array(n).join(s);
493
280
  }
494
281
 
495
- function _stringify (val) {
496
- switch (type(val)) {
282
+ function _stringify(val) {
283
+ switch (canonicalType(val)) {
497
284
  case 'null':
498
285
  case 'undefined':
499
286
  val = '[' + val + ']';
@@ -506,17 +293,16 @@ function jsonStringify (object, spaces, depth) {
506
293
  case 'regexp':
507
294
  case 'symbol':
508
295
  case 'number':
509
- val = val === 0 && (1 / val) === -Infinity // `-0`
510
- ? '-0'
511
- : val.toString();
296
+ val =
297
+ val === 0 && 1 / val === -Infinity // `-0`
298
+ ? '-0'
299
+ : val.toString();
300
+ break;
301
+ case 'bigint':
302
+ val = val.toString() + 'n';
512
303
  break;
513
304
  case 'date':
514
- var sDate;
515
- if (isNaN(val.getTime())) { // Invalid date
516
- sDate = val.toString();
517
- } else {
518
- sDate = val.toISOString ? val.toISOString() : toISOString(val);
519
- }
305
+ var sDate = isNaN(val.getTime()) ? val.toString() : val.toISOString();
520
306
  val = '[Date: ' + sDate + ']';
521
307
  break;
522
308
  case 'buffer':
@@ -526,9 +312,10 @@ function jsonStringify (object, spaces, depth) {
526
312
  val = '[Buffer: ' + jsonStringify(json, 2, depth + 1) + ']';
527
313
  break;
528
314
  default:
529
- val = (val === '[Function]' || val === '[Circular]')
530
- ? val
531
- : JSON.stringify(val); // string
315
+ val =
316
+ val === '[Function]' || val === '[Circular]'
317
+ ? val
318
+ : JSON.stringify(val); // string
532
319
  }
533
320
  return val;
534
321
  }
@@ -538,28 +325,21 @@ function jsonStringify (object, spaces, depth) {
538
325
  continue; // not my business
539
326
  }
540
327
  --length;
541
- str += '\n ' + repeat(' ', space) +
542
- (isArray(object) ? '' : '"' + i + '": ') + // key
543
- _stringify(object[i]) + // value
544
- (length ? ',' : ''); // comma
328
+ str +=
329
+ '\n ' +
330
+ repeat(' ', space) +
331
+ (Array.isArray(object) ? '' : '"' + i + '": ') + // key
332
+ _stringify(object[i]) + // value
333
+ (length ? ',' : ''); // comma
545
334
  }
546
335
 
547
- return str +
336
+ return (
337
+ str +
548
338
  // [], {}
549
- (str.length !== 1 ? '\n' + repeat(' ', --space) + end : end);
339
+ (str.length !== 1 ? '\n' + repeat(' ', --space) + end : end)
340
+ );
550
341
  }
551
342
 
552
- /**
553
- * Test if a value is a buffer.
554
- *
555
- * @api private
556
- * @param {*} value The value to test.
557
- * @return {boolean} True if `value` is a buffer, otherwise false
558
- */
559
- exports.isBuffer = function (value) {
560
- return typeof Buffer !== 'undefined' && Buffer.isBuffer(value);
561
- };
562
-
563
343
  /**
564
344
  * Return a new Thing that has the keys in sorted order. Recursive.
565
345
  *
@@ -572,20 +352,20 @@ exports.isBuffer = function (value) {
572
352
  * - is a non-empty `Array`, `Object`, or `Function`, return the result of calling this function again.
573
353
  * - is an empty `Array`, `Object`, or `Function`, return the result of calling `emptyRepresentation()`
574
354
  *
575
- * @api private
355
+ * @private
576
356
  * @see {@link exports.stringify}
577
357
  * @param {*} value Thing to inspect. May or may not have properties.
578
358
  * @param {Array} [stack=[]] Stack of seen values
579
359
  * @param {string} [typeHint] Type hint
580
360
  * @return {(Object|Array|Function|string|undefined)}
581
361
  */
582
- exports.canonicalize = function canonicalize (value, stack, typeHint) {
362
+ exports.canonicalize = function canonicalize(value, stack, typeHint) {
583
363
  var canonicalizedObj;
584
364
  /* eslint-disable no-unused-vars */
585
365
  var prop;
586
366
  /* eslint-enable no-unused-vars */
587
- typeHint = typeHint || type(value);
588
- function withStack (value, fn) {
367
+ typeHint = typeHint || canonicalType(value);
368
+ function withStack(value, fn) {
589
369
  stack.push(value);
590
370
  fn();
591
371
  stack.pop();
@@ -593,7 +373,7 @@ exports.canonicalize = function canonicalize (value, stack, typeHint) {
593
373
 
594
374
  stack = stack || [];
595
375
 
596
- if (indexOf(stack, value) !== -1) {
376
+ if (stack.indexOf(value) !== -1) {
597
377
  return '[Circular]';
598
378
  }
599
379
 
@@ -605,13 +385,13 @@ exports.canonicalize = function canonicalize (value, stack, typeHint) {
605
385
  break;
606
386
  case 'array':
607
387
  withStack(value, function () {
608
- canonicalizedObj = exports.map(value, function (item) {
388
+ canonicalizedObj = value.map(function (item) {
609
389
  return exports.canonicalize(item, stack);
610
390
  });
611
391
  });
612
392
  break;
613
393
  case 'function':
614
- /* eslint-disable guard-for-in */
394
+ /* eslint-disable-next-line no-unused-vars, no-unreachable-loop */
615
395
  for (prop in value) {
616
396
  canonicalizedObj = {};
617
397
  break;
@@ -622,12 +402,18 @@ exports.canonicalize = function canonicalize (value, stack, typeHint) {
622
402
  break;
623
403
  }
624
404
  /* falls through */
405
+ case 'null-prototype':
625
406
  case 'object':
626
407
  canonicalizedObj = canonicalizedObj || {};
408
+ if (typeHint === 'null-prototype' && Symbol.toStringTag in value) {
409
+ canonicalizedObj['[Symbol.toStringTag]'] = value[Symbol.toStringTag];
410
+ }
627
411
  withStack(value, function () {
628
- exports.forEach(exports.keys(value).sort(), function (key) {
629
- canonicalizedObj[key] = exports.canonicalize(value[key], stack);
630
- });
412
+ Object.keys(value)
413
+ .sort()
414
+ .forEach(function (key) {
415
+ canonicalizedObj[key] = exports.canonicalize(value[key], stack);
416
+ });
631
417
  });
632
418
  break;
633
419
  case 'date':
@@ -644,85 +430,6 @@ exports.canonicalize = function canonicalize (value, stack, typeHint) {
644
430
  return canonicalizedObj;
645
431
  };
646
432
 
647
- /**
648
- * Lookup file names at the given `path`.
649
- *
650
- * @api public
651
- * @param {string} path Base path to start searching from.
652
- * @param {string[]} extensions File extensions to look for.
653
- * @param {boolean} recursive Whether or not to recurse into subdirectories.
654
- * @return {string[]} An array of paths.
655
- */
656
- exports.lookupFiles = function lookupFiles (path, extensions, recursive) {
657
- var files = [];
658
- var re = new RegExp('\\.(' + extensions.join('|') + ')$');
659
-
660
- if (!exists(path)) {
661
- if (exists(path + '.js')) {
662
- path += '.js';
663
- } else {
664
- files = glob.sync(path);
665
- if (!files.length) {
666
- throw new Error("cannot resolve path (or pattern) '" + path + "'");
667
- }
668
- return files;
669
- }
670
- }
671
-
672
- try {
673
- var stat = statSync(path);
674
- if (stat.isFile()) {
675
- return path;
676
- }
677
- } catch (err) {
678
- // ignore error
679
- return;
680
- }
681
-
682
- readdirSync(path).forEach(function (file) {
683
- file = join(path, file);
684
- try {
685
- var stat = statSync(file);
686
- if (stat.isDirectory()) {
687
- if (recursive) {
688
- files = files.concat(lookupFiles(file, extensions, recursive));
689
- }
690
- return;
691
- }
692
- } catch (err) {
693
- // ignore error
694
- return;
695
- }
696
- if (!stat.isFile() || !re.test(file) || basename(file)[0] === '.') {
697
- return;
698
- }
699
- files.push(file);
700
- });
701
-
702
- return files;
703
- };
704
-
705
- /**
706
- * Generate an undefined error with a message warning the user.
707
- *
708
- * @return {Error}
709
- */
710
-
711
- exports.undefinedError = function () {
712
- return new Error('Caught undefined error, did you throw without specifying what?');
713
- };
714
-
715
- /**
716
- * Generate an undefined error if `err` is not defined.
717
- *
718
- * @param {Error} err
719
- * @return {Error}
720
- */
721
-
722
- exports.getError = function (err) {
723
- return err || exports.undefinedError();
724
- };
725
-
726
433
  /**
727
434
  * @summary
728
435
  * This Filter based on `mocha-clean` module.(see: `github.com/rstacruz/mocha-clean`)
@@ -734,38 +441,41 @@ exports.getError = function (err) {
734
441
  */
735
442
  exports.stackTraceFilter = function () {
736
443
  // TODO: Replace with `process.browser`
737
- var is = typeof document === 'undefined' ? { node: true } : { browser: true };
444
+ var is = typeof document === 'undefined' ? {node: true} : {browser: true};
738
445
  var slash = path.sep;
739
446
  var cwd;
740
447
  if (is.node) {
741
- cwd = process.cwd() + slash;
448
+ cwd = exports.cwd() + slash;
742
449
  } else {
743
- cwd = (typeof location === 'undefined'
744
- ? window.location
745
- : location).href.replace(/\/[^/]*$/, '/');
450
+ cwd = (
451
+ typeof location === 'undefined' ? window.location : location
452
+ ).href.replace(/\/[^/]*$/, '/');
746
453
  slash = '/';
747
454
  }
748
455
 
749
- function isMochaInternal (line) {
750
- return (~line.indexOf('node_modules' + slash + 'mocha' + slash)) ||
751
- (~line.indexOf('node_modules' + slash + 'mocha.js')) ||
752
- (~line.indexOf('bower_components' + slash + 'mocha.js')) ||
753
- (~line.indexOf(slash + 'mocha.js'));
456
+ function isMochaInternal(line) {
457
+ return (
458
+ ~line.indexOf('node_modules' + slash + 'mocha' + slash) ||
459
+ ~line.indexOf(slash + 'mocha.js') ||
460
+ ~line.indexOf(slash + 'mocha.min.js')
461
+ );
754
462
  }
755
463
 
756
- function isNodeInternal (line) {
757
- return (~line.indexOf('(timers.js:')) ||
758
- (~line.indexOf('(events.js:')) ||
759
- (~line.indexOf('(node.js:')) ||
760
- (~line.indexOf('(module.js:')) ||
761
- (~line.indexOf('GeneratorFunctionPrototype.next (native)')) ||
762
- false;
464
+ function isNodeInternal(line) {
465
+ return (
466
+ ~line.indexOf('(timers.js:') ||
467
+ ~line.indexOf('(events.js:') ||
468
+ ~line.indexOf('(node.js:') ||
469
+ ~line.indexOf('(module.js:') ||
470
+ ~line.indexOf('GeneratorFunctionPrototype.next (native)') ||
471
+ false
472
+ );
763
473
  }
764
474
 
765
475
  return function (stack) {
766
476
  stack = stack.split('\n');
767
477
 
768
- stack = reduce(stack, function (list, line) {
478
+ stack = stack.reduce(function (list, line) {
769
479
  if (isMochaInternal(line)) {
770
480
  return list;
771
481
  }
@@ -775,8 +485,8 @@ exports.stackTraceFilter = function () {
775
485
  }
776
486
 
777
487
  // Clean up cwd(absolute)
778
- if (/\(?.+:\d+:\d+\)?$/.test(line)) {
779
- line = line.replace(cwd, '');
488
+ if (/:\d+:\d+\)?$/.test(line)) {
489
+ line = line.replace('(' + cwd, '(');
780
490
  }
781
491
 
782
492
  list.push(line);
@@ -789,16 +499,193 @@ exports.stackTraceFilter = function () {
789
499
 
790
500
  /**
791
501
  * Crude, but effective.
792
- * @api
502
+ * @public
793
503
  * @param {*} value
794
504
  * @returns {boolean} Whether or not `value` is a Promise
795
505
  */
796
- exports.isPromise = function isPromise (value) {
797
- return typeof value === 'object' && typeof value.then === 'function';
506
+ exports.isPromise = function isPromise(value) {
507
+ return (
508
+ typeof value === 'object' &&
509
+ value !== null &&
510
+ typeof value.then === 'function'
511
+ );
512
+ };
513
+
514
+ /**
515
+ * Clamps a numeric value to an inclusive range.
516
+ *
517
+ * @param {number} value - Value to be clamped.
518
+ * @param {number[]} range - Two element array specifying [min, max] range.
519
+ * @returns {number} clamped value
520
+ */
521
+ exports.clamp = function clamp(value, range) {
522
+ return Math.min(Math.max(value, range[0]), range[1]);
798
523
  };
799
524
 
800
525
  /**
801
526
  * It's a noop.
802
- * @api
527
+ * @public
803
528
  */
804
529
  exports.noop = function () {};
530
+
531
+ /**
532
+ * Creates a map-like object.
533
+ *
534
+ * @description
535
+ * A "map" is an object with no prototype, for our purposes. In some cases
536
+ * this would be more appropriate than a `Map`, especially if your environment
537
+ * doesn't support it. Recommended for use in Mocha's public APIs.
538
+ *
539
+ * @public
540
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Custom_and_Null_objects|MDN:Map}
541
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Custom_and_Null_objects|MDN:Object.create - Custom objects}
542
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Custom_and_Null_objects|MDN:Object.assign}
543
+ * @param {...*} [obj] - Arguments to `Object.assign()`.
544
+ * @returns {Object} An object with no prototype, having `...obj` properties
545
+ */
546
+ exports.createMap = function (obj) {
547
+ return Object.assign.apply(
548
+ null,
549
+ [Object.create(null)].concat(Array.prototype.slice.call(arguments))
550
+ );
551
+ };
552
+
553
+ /**
554
+ * Creates a read-only map-like object.
555
+ *
556
+ * @description
557
+ * This differs from {@link module:utils.createMap createMap} only in that
558
+ * the argument must be non-empty, because the result is frozen.
559
+ *
560
+ * @see {@link module:utils.createMap createMap}
561
+ * @param {...*} [obj] - Arguments to `Object.assign()`.
562
+ * @returns {Object} A frozen object with no prototype, having `...obj` properties
563
+ * @throws {TypeError} if argument is not a non-empty object.
564
+ */
565
+ exports.defineConstants = function (obj) {
566
+ if (canonicalType(obj) !== 'object' || !Object.keys(obj).length) {
567
+ throw new TypeError('Invalid argument; expected a non-empty object');
568
+ }
569
+ return Object.freeze(exports.createMap(obj));
570
+ };
571
+
572
+ /**
573
+ * Returns current working directory
574
+ *
575
+ * Wrapper around `process.cwd()` for isolation
576
+ * @private
577
+ */
578
+ exports.cwd = function cwd() {
579
+ return process.cwd();
580
+ };
581
+
582
+ /**
583
+ * Returns `true` if Mocha is running in a browser.
584
+ * Checks for `process.browser`.
585
+ * @returns {boolean}
586
+ * @private
587
+ */
588
+ exports.isBrowser = function isBrowser() {
589
+ return Boolean(process.browser);
590
+ };
591
+
592
+ /*
593
+ * Casts `value` to an array; useful for optionally accepting array parameters
594
+ *
595
+ * It follows these rules, depending on `value`. If `value` is...
596
+ * 1. `undefined`: return an empty Array
597
+ * 2. `null`: return an array with a single `null` element
598
+ * 3. Any other object: return the value of `Array.from()` _if_ the object is iterable
599
+ * 4. otherwise: return an array with a single element, `value`
600
+ * @param {*} value - Something to cast to an Array
601
+ * @returns {Array<*>}
602
+ */
603
+ exports.castArray = function castArray(value) {
604
+ if (value === undefined) {
605
+ return [];
606
+ }
607
+ if (value === null) {
608
+ return [null];
609
+ }
610
+ if (
611
+ typeof value === 'object' &&
612
+ (typeof value[Symbol.iterator] === 'function' || value.length !== undefined)
613
+ ) {
614
+ return Array.from(value);
615
+ }
616
+ return [value];
617
+ };
618
+
619
+ exports.constants = exports.defineConstants({
620
+ MOCHA_ID_PROP_NAME
621
+ });
622
+
623
+ const uniqueIDBase =
624
+ 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_';
625
+
626
+ /**
627
+ * Creates a new unique identifier
628
+ * Does not create cryptographically safe ids.
629
+ * Trivial copy of nanoid/non-secure
630
+ * @returns {string} Unique identifier
631
+ */
632
+ exports.uniqueID = () => {
633
+ let id = '';
634
+ for (let i = 0; i < 21; i++) {
635
+ id += uniqueIDBase[(Math.random() * 64) | 0];
636
+ }
637
+ return id;
638
+ };
639
+
640
+ exports.assignNewMochaID = obj => {
641
+ const id = exports.uniqueID();
642
+ Object.defineProperty(obj, MOCHA_ID_PROP_NAME, {
643
+ get() {
644
+ return id;
645
+ }
646
+ });
647
+ return obj;
648
+ };
649
+
650
+ /**
651
+ * Retrieves a Mocha ID from an object, if present.
652
+ * @param {*} [obj] - Object
653
+ * @returns {string|void}
654
+ */
655
+ exports.getMochaID = obj =>
656
+ obj && typeof obj === 'object' ? obj[MOCHA_ID_PROP_NAME] : undefined;
657
+
658
+ /**
659
+ * Replaces any detected circular dependency with the string '[Circular]'
660
+ * Mutates original object
661
+ * @param inputObj {*}
662
+ * @returns {*}
663
+ */
664
+ exports.breakCircularDeps = inputObj => {
665
+ const seen = new Set();
666
+
667
+ function _breakCircularDeps(obj) {
668
+ if (obj && typeof obj !== 'object') {
669
+ return obj;
670
+ }
671
+
672
+ if (seen.has(obj)) {
673
+ return '[Circular]';
674
+ }
675
+
676
+ seen.add(obj);
677
+ for (const k in obj) {
678
+ const descriptor = Object.getOwnPropertyDescriptor(obj, k);
679
+
680
+ if (descriptor && descriptor.writable) {
681
+ obj[k] = _breakCircularDeps(obj[k], k);
682
+ }
683
+ }
684
+
685
+ // deleting means only a seen object that is its own child will be detected
686
+ seen.delete(obj);
687
+ return obj;
688
+ }
689
+
690
+ return _breakCircularDeps(inputObj);
691
+ };