mocha 8.2.0 → 8.2.1

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.
package/CHANGELOG.md CHANGED
@@ -1,4 +1,15 @@
1
- # 8.2.0 / 2020-10-15
1
+ # 8.2.1 / 2020-11-02
2
+
3
+ Fixed stuff.
4
+
5
+ ## :bug: Fixes
6
+
7
+ - [#4489](https://github.com/mochajs/mocha/issues/4489): Fix problematic handling of otherwise-unhandled `Promise` rejections and erroneous "`done()` called twice" errors ([**@boneskull**](https://github.com/boneskull))
8
+ - [#4496](https://github.com/mochajs/mocha/issues/4496): Avoid `MaxListenersExceededWarning` in watch mode ([**@boneskull**](https://github.com/boneskull))
9
+
10
+ Also thanks to [**@akeating**](https://github.com/akeating) for a documentation fix!
11
+
12
+ # 8.2.0 / 2020-10-16
2
13
 
3
14
  The major feature added in v8.2.0 is addition of support for [_global fixtures_](https://mochajs.org/#global-fixtures).
4
15
 
@@ -41,6 +41,9 @@ exports.watchParallelRun = (
41
41
  // I don't know why we're cloning the root suite.
42
42
  const rootSuite = mocha.suite.clone();
43
43
 
44
+ // ensure we aren't leaking event listeners
45
+ mocha.dispose();
46
+
44
47
  // this `require` is needed because the require cache has been cleared. the dynamic
45
48
  // exports set via the below call to `mocha.ui()` won't work properly if a
46
49
  // test depends on this module (see `required-tokens.spec.js`).
@@ -100,6 +103,9 @@ exports.watchRun = (mocha, {watchFiles, watchIgnore}, fileCollectParams) => {
100
103
  // I don't know why we're cloning the root suite.
101
104
  const rootSuite = mocha.suite.clone();
102
105
 
106
+ // ensure we aren't leaking event listeners
107
+ mocha.dispose();
108
+
103
109
  // this `require` is needed because the require cache has been cleared. the dynamic
104
110
  // exports set via the below call to `mocha.ui()` won't work properly if a
105
111
  // test depends on this module (see `required-tokens.spec.js`).
package/lib/errors.js CHANGED
@@ -129,6 +129,8 @@ var constants = {
129
129
  INVALID_PLUGIN_DEFINITION: 'ERR_MOCHA_INVALID_PLUGIN_DEFINITION'
130
130
  };
131
131
 
132
+ const MOCHA_ERRORS = new Set(Object.values(constants));
133
+
132
134
  /**
133
135
  * Creates an error object to be thrown when no files to be tested could be found using specified pattern.
134
136
  *
@@ -419,6 +421,16 @@ function createInvalidPluginImplementationError(
419
421
  return err;
420
422
  }
421
423
 
424
+ /**
425
+ * Returns `true` if an error came out of Mocha.
426
+ * _Can suffer from false negatives, but not false positives._
427
+ * @public
428
+ * @param {*} err - Error, or anything
429
+ * @returns {boolean}
430
+ */
431
+ const isMochaError = err =>
432
+ Boolean(err && typeof err === 'object' && MOCHA_ERRORS.has(err.code));
433
+
422
434
  module.exports = {
423
435
  constants,
424
436
  createFatalError,
@@ -439,5 +451,6 @@ module.exports = {
439
451
  createNoFilesMatchPatternError,
440
452
  createUnsupportedError,
441
453
  deprecate,
454
+ isMochaError,
442
455
  warn
443
456
  };
package/lib/runner.js CHANGED
@@ -24,10 +24,13 @@ var sQuote = utils.sQuote;
24
24
  var stackFilter = utils.stackTraceFilter();
25
25
  var stringify = utils.stringify;
26
26
 
27
- var errors = require('./errors');
28
- var createInvalidExceptionError = errors.createInvalidExceptionError;
29
- var createUnsupportedError = errors.createUnsupportedError;
30
- var createFatalError = errors.createFatalError;
27
+ const {
28
+ createInvalidExceptionError,
29
+ createUnsupportedError,
30
+ createFatalError,
31
+ isMochaError,
32
+ constants: errorConstants
33
+ } = require('./errors');
31
34
 
32
35
  /**
33
36
  * Non-enumerable globals.
@@ -179,6 +182,29 @@ class Runner extends EventEmitter {
179
182
  this.globals(this.globalProps());
180
183
 
181
184
  this.uncaught = this._uncaught.bind(this);
185
+ this.unhandled = (reason, promise) => {
186
+ if (isMochaError(reason)) {
187
+ debug(
188
+ 'trapped unhandled rejection coming out of Mocha; forwarding to uncaught handler:',
189
+ reason
190
+ );
191
+ this.uncaught(reason);
192
+ } else {
193
+ debug(
194
+ 'trapped unhandled rejection from (probably) user code; re-emitting on process'
195
+ );
196
+ this._removeEventListener(
197
+ process,
198
+ 'unhandledRejection',
199
+ this.unhandled
200
+ );
201
+ try {
202
+ process.emit('unhandledRejection', reason, promise);
203
+ } finally {
204
+ this._addEventListener(process, 'unhandledRejection', this.unhandled);
205
+ }
206
+ }
207
+ };
182
208
  }
183
209
  }
184
210
 
@@ -414,7 +440,7 @@ Runner.prototype.fail = function(test, err, force) {
414
440
  return;
415
441
  }
416
442
  if (this.state === constants.STATE_STOPPED) {
417
- if (err.code === errors.constants.MULTIPLE_DONE) {
443
+ if (err.code === errorConstants.MULTIPLE_DONE) {
418
444
  throw err;
419
445
  }
420
446
  throw createFatalError(
@@ -1025,9 +1051,7 @@ Runner.prototype.run = function(fn, opts = {}) {
1025
1051
  this.emit(constants.EVENT_RUN_BEGIN);
1026
1052
  debug('run(): emitted %s', constants.EVENT_RUN_BEGIN);
1027
1053
 
1028
- this.runSuite(rootSuite, async () => {
1029
- end();
1030
- });
1054
+ this.runSuite(rootSuite, end);
1031
1055
  };
1032
1056
 
1033
1057
  const prepare = () => {
@@ -1061,9 +1085,9 @@ Runner.prototype.run = function(fn, opts = {}) {
1061
1085
  });
1062
1086
 
1063
1087
  this._removeEventListener(process, 'uncaughtException', this.uncaught);
1064
- this._removeEventListener(process, 'unhandledRejection', this.uncaught);
1088
+ this._removeEventListener(process, 'unhandledRejection', this.unhandled);
1065
1089
  this._addEventListener(process, 'uncaughtException', this.uncaught);
1066
- this._addEventListener(process, 'unhandledRejection', this.uncaught);
1090
+ this._addEventListener(process, 'unhandledRejection', this.unhandled);
1067
1091
 
1068
1092
  if (this._delay) {
1069
1093
  // for reporters, I guess.
package/mocha.js CHANGED
@@ -19749,6 +19749,46 @@
19749
19749
  })(commonjsGlobal);
19750
19750
  });
19751
19751
 
19752
+ var propertyIsEnumerable = objectPropertyIsEnumerable.f;
19753
+
19754
+ // `Object.{ entries, values }` methods implementation
19755
+ var createMethod$5 = function (TO_ENTRIES) {
19756
+ return function (it) {
19757
+ var O = toIndexedObject(it);
19758
+ var keys = objectKeys(O);
19759
+ var length = keys.length;
19760
+ var i = 0;
19761
+ var result = [];
19762
+ var key;
19763
+ while (length > i) {
19764
+ key = keys[i++];
19765
+ if (!descriptors || propertyIsEnumerable.call(O, key)) {
19766
+ result.push(TO_ENTRIES ? [key, O[key]] : O[key]);
19767
+ }
19768
+ }
19769
+ return result;
19770
+ };
19771
+ };
19772
+
19773
+ var objectToArray = {
19774
+ // `Object.entries` method
19775
+ // https://tc39.github.io/ecma262/#sec-object.entries
19776
+ entries: createMethod$5(true),
19777
+ // `Object.values` method
19778
+ // https://tc39.github.io/ecma262/#sec-object.values
19779
+ values: createMethod$5(false)
19780
+ };
19781
+
19782
+ var $values = objectToArray.values;
19783
+
19784
+ // `Object.values` method
19785
+ // https://tc39.github.io/ecma262/#sec-object.values
19786
+ _export({ target: 'Object', stat: true }, {
19787
+ values: function values(O) {
19788
+ return $values(O);
19789
+ }
19790
+ });
19791
+
19752
19792
  var format$1 = util.format;
19753
19793
  /**
19754
19794
  * Contains error codes, factory functions to create throwable error objects,
@@ -19881,6 +19921,7 @@
19881
19921
  */
19882
19922
  INVALID_PLUGIN_DEFINITION: 'ERR_MOCHA_INVALID_PLUGIN_DEFINITION'
19883
19923
  };
19924
+ var MOCHA_ERRORS = new Set(Object.values(constants));
19884
19925
  /**
19885
19926
  * Creates an error object to be thrown when no files to be tested could be found using specified pattern.
19886
19927
  *
@@ -20183,6 +20224,18 @@
20183
20224
  err.pluginImpl = pluginImpl;
20184
20225
  return err;
20185
20226
  }
20227
+ /**
20228
+ * Returns `true` if an error came out of Mocha.
20229
+ * _Can suffer from false negatives, but not false positives._
20230
+ * @public
20231
+ * @param {*} err - Error, or anything
20232
+ * @returns {boolean}
20233
+ */
20234
+
20235
+
20236
+ var isMochaError = function isMochaError(err) {
20237
+ return Boolean(err && _typeof(err) === 'object' && MOCHA_ERRORS.has(err.code));
20238
+ };
20186
20239
 
20187
20240
  var errors = {
20188
20241
  constants: constants,
@@ -20204,6 +20257,7 @@
20204
20257
  createNoFilesMatchPatternError: createNoFilesMatchPatternError,
20205
20258
  createUnsupportedError: createUnsupportedError,
20206
20259
  deprecate: deprecate$1,
20260
+ isMochaError: isMochaError,
20207
20261
  warn: warn
20208
20262
  };
20209
20263
 
@@ -22724,9 +22778,11 @@
22724
22778
  var sQuote = utils.sQuote;
22725
22779
  var stackFilter = utils.stackTraceFilter();
22726
22780
  var stringify = utils.stringify;
22727
- var createInvalidExceptionError$2 = errors.createInvalidExceptionError;
22728
- var createUnsupportedError$1 = errors.createUnsupportedError;
22729
- var createFatalError$1 = errors.createFatalError;
22781
+ var createInvalidExceptionError$2 = errors.createInvalidExceptionError,
22782
+ createUnsupportedError$1 = errors.createUnsupportedError,
22783
+ createFatalError$1 = errors.createFatalError,
22784
+ isMochaError$1 = errors.isMochaError,
22785
+ errorConstants = errors.constants;
22730
22786
  /**
22731
22787
  * Non-enumerable globals.
22732
22788
  * @private
@@ -22901,6 +22957,25 @@
22901
22957
  _this.globals(_this.globalProps());
22902
22958
 
22903
22959
  _this.uncaught = _this._uncaught.bind(_assertThisInitialized(_this));
22960
+
22961
+ _this.unhandled = function (reason, promise) {
22962
+ if (isMochaError$1(reason)) {
22963
+ debug$2('trapped unhandled rejection coming out of Mocha; forwarding to uncaught handler:', reason);
22964
+
22965
+ _this.uncaught(reason);
22966
+ } else {
22967
+ debug$2('trapped unhandled rejection from (probably) user code; re-emitting on process');
22968
+
22969
+ _this._removeEventListener(process$1, 'unhandledRejection', _this.unhandled);
22970
+
22971
+ try {
22972
+ process$1.emit('unhandledRejection', reason, promise);
22973
+ } finally {
22974
+ _this._addEventListener(process$1, 'unhandledRejection', _this.unhandled);
22975
+ }
22976
+ }
22977
+ };
22978
+
22904
22979
  return _this;
22905
22980
  }
22906
22981
 
@@ -23141,7 +23216,7 @@
23141
23216
  }
23142
23217
 
23143
23218
  if (this.state === constants$3.STATE_STOPPED) {
23144
- if (err.code === errors.constants.MULTIPLE_DONE) {
23219
+ if (err.code === errorConstants.MULTIPLE_DONE) {
23145
23220
  throw err;
23146
23221
  }
23147
23222
 
@@ -23777,20 +23852,7 @@
23777
23852
 
23778
23853
  debug$2('run(): emitted %s', constants$3.EVENT_RUN_BEGIN);
23779
23854
 
23780
- _this2.runSuite(rootSuite, /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
23781
- return regeneratorRuntime.wrap(function _callee$(_context) {
23782
- while (1) {
23783
- switch (_context.prev = _context.next) {
23784
- case 0:
23785
- end();
23786
-
23787
- case 1:
23788
- case "end":
23789
- return _context.stop();
23790
- }
23791
- }
23792
- }, _callee);
23793
- })));
23855
+ _this2.runSuite(rootSuite, end);
23794
23856
  };
23795
23857
 
23796
23858
  var prepare = function prepare() {
@@ -23828,11 +23890,11 @@
23828
23890
 
23829
23891
  this._removeEventListener(process$1, 'uncaughtException', this.uncaught);
23830
23892
 
23831
- this._removeEventListener(process$1, 'unhandledRejection', this.uncaught);
23893
+ this._removeEventListener(process$1, 'unhandledRejection', this.unhandled);
23832
23894
 
23833
23895
  this._addEventListener(process$1, 'uncaughtException', this.uncaught);
23834
23896
 
23835
- this._addEventListener(process$1, 'unhandledRejection', this.uncaught);
23897
+ this._addEventListener(process$1, 'unhandledRejection', this.unhandled);
23836
23898
 
23837
23899
  if (this._delay) {
23838
23900
  // for reporters, I guess.
@@ -23885,26 +23947,26 @@
23885
23947
 
23886
23948
 
23887
23949
  Runner.prototype.runAsync = /*#__PURE__*/function () {
23888
- var _runAsync = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
23950
+ var _runAsync = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
23889
23951
  var _this3 = this;
23890
23952
 
23891
23953
  var opts,
23892
- _args2 = arguments;
23893
- return regeneratorRuntime.wrap(function _callee2$(_context2) {
23954
+ _args = arguments;
23955
+ return regeneratorRuntime.wrap(function _callee$(_context) {
23894
23956
  while (1) {
23895
- switch (_context2.prev = _context2.next) {
23957
+ switch (_context.prev = _context.next) {
23896
23958
  case 0:
23897
- opts = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : {};
23898
- return _context2.abrupt("return", new Promise(function (resolve) {
23959
+ opts = _args.length > 0 && _args[0] !== undefined ? _args[0] : {};
23960
+ return _context.abrupt("return", new Promise(function (resolve) {
23899
23961
  _this3.run(resolve, opts);
23900
23962
  }));
23901
23963
 
23902
23964
  case 2:
23903
23965
  case "end":
23904
- return _context2.stop();
23966
+ return _context.stop();
23905
23967
  }
23906
23968
  }
23907
- }, _callee2);
23969
+ }, _callee);
23908
23970
  }));
23909
23971
 
23910
23972
  function runAsync() {
@@ -26838,7 +26900,7 @@
26838
26900
  });
26839
26901
 
26840
26902
  var name = "mocha";
26841
- var version$2 = "8.2.0";
26903
+ var version$2 = "8.2.1";
26842
26904
  var homepage = "https://mochajs.org/";
26843
26905
  var notifyLogo = "https://ibin.co/4QuRuGjXvl36.png";
26844
26906
  var _package = {