collectHandles.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true
  4. });
  5. exports.default = collectHandles;
  6. exports.formatHandleErrors = formatHandleErrors;
  7. function _jestMessageUtil() {
  8. const data = require('jest-message-util');
  9. _jestMessageUtil = function _jestMessageUtil() {
  10. return data;
  11. };
  12. return data;
  13. }
  14. function _jestUtil() {
  15. const data = require('jest-util');
  16. _jestUtil = function _jestUtil() {
  17. return data;
  18. };
  19. return data;
  20. }
  21. function _stripAnsi() {
  22. const data = _interopRequireDefault(require('strip-ansi'));
  23. _stripAnsi = function _stripAnsi() {
  24. return data;
  25. };
  26. return data;
  27. }
  28. function _interopRequireDefault(obj) {
  29. return obj && obj.__esModule ? obj : {default: obj};
  30. }
  31. /**
  32. * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
  33. *
  34. * This source code is licensed under the MIT license found in the
  35. * LICENSE file in the root directory of this source tree.
  36. */
  37. function stackIsFromUser(stack) {
  38. // Either the test file, or something required by it
  39. if (stack.includes('Runtime.requireModule')) {
  40. return true;
  41. } // jest-jasmine it or describe call
  42. if (stack.includes('asyncJestTest') || stack.includes('asyncJestLifecycle')) {
  43. return true;
  44. } // An async function call from within circus
  45. if (stack.includes('callAsyncCircusFn')) {
  46. // jest-circus it or describe call
  47. return (
  48. stack.includes('_callCircusTest') || stack.includes('_callCircusHook')
  49. );
  50. }
  51. return false;
  52. } // Inspired by https://github.com/mafintosh/why-is-node-running/blob/master/index.js
  53. // Extracted as we want to format the result ourselves
  54. function collectHandles() {
  55. const activeHandles = new Map();
  56. let hook;
  57. try {
  58. const asyncHooks = require('async_hooks');
  59. hook = asyncHooks.createHook({
  60. destroy(asyncId) {
  61. activeHandles.delete(asyncId);
  62. },
  63. init: function initHook(asyncId, type) {
  64. if (type === 'PROMISE' || type === 'TIMERWRAP') {
  65. return;
  66. }
  67. const error = new (_jestUtil()).ErrorWithStack(type, initHook);
  68. if (stackIsFromUser(error.stack || '')) {
  69. activeHandles.set(asyncId, error);
  70. }
  71. }
  72. });
  73. hook.enable();
  74. } catch (e) {
  75. const nodeMajor = Number(process.versions.node.split('.')[0]);
  76. if (e.code === 'MODULE_NOT_FOUND' && nodeMajor < 8) {
  77. throw new Error(
  78. 'You can only use --detectOpenHandles on Node 8 and newer.'
  79. );
  80. } else {
  81. throw e;
  82. }
  83. }
  84. return () => {
  85. hook.disable();
  86. const result = Array.from(activeHandles.values());
  87. activeHandles.clear();
  88. return result;
  89. };
  90. }
  91. function formatHandleErrors(errors, config) {
  92. const stacks = new Set();
  93. return (
  94. errors
  95. .map(err =>
  96. (0, _jestMessageUtil().formatExecError)(
  97. err,
  98. config,
  99. {
  100. noStackTrace: false
  101. },
  102. undefined,
  103. true
  104. )
  105. ) // E.g. timeouts might give multiple traces to the same line of code
  106. // This hairy filtering tries to remove entries with duplicate stack traces
  107. .filter(handle => {
  108. const ansiFree = (0, _stripAnsi().default)(handle);
  109. const match = ansiFree.match(/\s+at(.*)/);
  110. if (!match || match.length < 2) {
  111. return true;
  112. }
  113. const stack = ansiFree.substr(ansiFree.indexOf(match[1])).trim();
  114. if (stacks.has(stack)) {
  115. return false;
  116. }
  117. stacks.add(stack);
  118. return true;
  119. })
  120. );
  121. }