index.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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) { return obj && obj.__esModule ? obj : { default: obj }; }
  26. const PRIMITIVE_TYPES = new Set(['undefined', 'boolean', 'number', 'string', 'symbol']);
  27. exports.default = class {
  28. constructor(value) {
  29. if (this._isPrimitive(value)) {
  30. throw new TypeError(['Primitives cannot leak memory.', 'You passed a ' + typeof value + ': <' + (0, (_prettyFormat || _load_prettyFormat()).default)(value) + '>'].join(' '));
  31. }
  32. let weak;
  33. try {
  34. // eslint-disable-next-line import/no-extraneous-dependencies
  35. weak = require('weak');
  36. } catch (err) {
  37. if (!err || err.code !== 'MODULE_NOT_FOUND') {
  38. throw err;
  39. }
  40. throw new Error('The leaking detection mechanism requires the "weak" package to be installed and work. ' + 'Please install it as a dependency on your main project');
  41. }
  42. weak(value, () => this._isReferenceBeingHeld = false);
  43. this._isReferenceBeingHeld = true;
  44. // Ensure value is not leaked by the closure created by the "weak" callback.
  45. value = null;
  46. }
  47. isLeaking() {
  48. this._runGarbageCollector();
  49. return this._isReferenceBeingHeld;
  50. }
  51. _runGarbageCollector() {
  52. const isGarbageCollectorHidden = !global.gc;
  53. // GC is usually hidden, so we have to expose it before running.
  54. (_v || _load_v()).default.setFlagsFromString('--expose-gc');
  55. (_vm || _load_vm()).default.runInNewContext('gc')();
  56. // The GC was not initially exposed, so let's hide it again.
  57. if (isGarbageCollectorHidden) {
  58. (_v || _load_v()).default.setFlagsFromString('--no-expose-gc');
  59. }
  60. }
  61. _isPrimitive(value) {
  62. return value === null || PRIMITIVE_TYPES.has(typeof value);
  63. }
  64. };