index.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /**
  2. * Copyright (c) 2017-present, Facebook, Inc. All rights reserved.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. *
  7. *
  8. */
  9. 'use strict';
  10. Object.defineProperty(exports, '__esModule', {
  11. value: true
  12. });
  13. var _prettyFormat;
  14. function _load_prettyFormat() {
  15. return (_prettyFormat = _interopRequireDefault(require('pretty-format')));
  16. }
  17. var _v;
  18. function _load_v() {
  19. return (_v = _interopRequireDefault(require('v8')));
  20. }
  21. var _vm;
  22. function _load_vm() {
  23. return (_vm = _interopRequireDefault(require('vm')));
  24. }
  25. function _interopRequireDefault(obj) {
  26. return obj && obj.__esModule ? obj : {default: obj};
  27. }
  28. exports.default = class {
  29. constructor(value) {
  30. if (this._isPrimitive(value)) {
  31. throw new TypeError(
  32. [
  33. 'Primitives cannot leak memory.',
  34. 'You passed a ' +
  35. typeof value +
  36. ': <' +
  37. (0, (_prettyFormat || _load_prettyFormat()).default)(value) +
  38. '>'
  39. ].join(' ')
  40. );
  41. }
  42. let weak;
  43. try {
  44. // eslint-disable-next-line import/no-extraneous-dependencies
  45. weak = require('weak');
  46. } catch (err) {
  47. if (!err || err.code !== 'MODULE_NOT_FOUND') {
  48. throw err;
  49. }
  50. throw new Error(
  51. 'The leaking detection mechanism requires the "weak" package to be installed and work. ' +
  52. 'Please install it as a dependency on your main project'
  53. );
  54. }
  55. weak(value, () => (this._isReferenceBeingHeld = false));
  56. this._isReferenceBeingHeld = true;
  57. // Ensure value is not leaked by the closure created by the "weak" callback.
  58. value = null;
  59. }
  60. isLeaking() {
  61. this._runGarbageCollector();
  62. return this._isReferenceBeingHeld;
  63. }
  64. _runGarbageCollector() {
  65. const isGarbageCollectorHidden = !global.gc;
  66. // GC is usually hidden, so we have to expose it before running.
  67. (_v || _load_v()).default.setFlagsFromString('--expose-gc');
  68. (_vm || _load_vm()).default.runInNewContext('gc')();
  69. // The GC was not initially exposed, so let's hide it again.
  70. if (isGarbageCollectorHidden) {
  71. (_v || _load_v()).default.setFlagsFromString('--no-expose-gc');
  72. }
  73. }
  74. _isPrimitive(value) {
  75. return value !== Object(value);
  76. }
  77. };