@droppedcode/eslint-plugin-jasmine-memoryleak-linter

中文文档
1.0.13发布于 2024/11/17MITTypeScriptCommonJS零依赖近 30 天下载 3026

An ESLint extension to detect and fix Jasmine / Mocha related memory leaks.

原始使用文档
文档目录11 节
  1. Configuration
  2. Rules
  3. declaration-in-describe (There are declarations in a descri…
  4. assignment-in-describe (There are assignments in a describe…
  5. no-cleanup-before-each-rule (There is assignment in "before…
  6. no-cleanup-before-all-rule (There is assignment in "beforeA…
  7. no-cleanup-it-rule (There is assignment in "it" but no clea…
  8. How to build
  9. How to debug
  10. Samples
  11. Known issues

ESLint plugin to find and fix jasmine memory leaks

This plugin for eslint looks for errors with the usage of jasmine (or mocha but that is just a coincidence based on the same naming conventions).

Configuration

To configure the ESLint use the usual way:

  • add as a plugin
  • add the rules you want to use (or use the recommended ruleset)
{
  // ...
  "plugins": [
    // ...
    "@droppedcode/eslint-plugin-jasmine-memoryleak-linter"
  ],
  "rules": {
    // ...
    "@droppedcode/jasmine-memoryleak-linter/describe-declarations": "error",
    "@droppedcode/jasmine-memoryleak-linter/no-cleanup-before-each-rule": "error",
    "@droppedcode/jasmine-memoryleak-linter/no-cleanup-before-all-rule": "error"
  }
}

or use predefined configuration

{
  // ...
  "extends": [
    // ...
    "@droppedcode/eslint-plugin-jasmine-memoryleak-linter/recommended"
  ]
}

Rules

All rules has a built in fix, but usually gives multiple suggestions to how to solve the issue.

declaration-in-describe (There are declarations in a describe.)

Looks for cases where variables are declared and initialized within a "describe" method:

describe('test-describe-let', () => {
  let a = {}; // This will trigger it

  it('test', () => {
    // use a...
  });
});

This can be fixed in multiple ways:

Move declarations to the "it" block(s)

Moves the declaration logic to the "it" blocks. This will cause the variable to be local and GC will clean it up.

describe('test-describe-let', () => {
  it('test', () => {
    let a = {};
    // use a...
  });
});

Initialize values in "beforeEach" and unreference in "afterEach"

(This is the default fix.)

describe('test-describe-let', () => {
  let a;

  beforeEach(() => {
    a = {};
  });

  afterEach(() => {
    a = undefined;
  });

  it('test', () => {
    // use a...
  });
});

Initialize values in "beforeAll" and unreference in "afterAll"

describe('test-describe-let', () => {
  let a;

  beforeAll(() => {
    a = {};
  });

  afterAll(() => {
    a = undefined;
  });

  it('test', () => {
    // use a...
  });
});

declaration-in-describe (There are declarations in a describe which is used for initialization, but captured.)

Looks for cases where variables are declared and initialized within a "describe" method, but used only for initialization in an other describe:

describe('test-describe-let', () => {
  let a = [1, 2]; // This will trigger it

  describe('inner', () => {
    a.forEach(() => {});
  });
});
describe('test-describe-let', () => {
  describe('inner', () => {
    let a = [1, 2];

    a.forEach(() => {});
  });
});

Options

export type InDescribeRuleOptions = {
  /** Names of the functions that the rule is looking for. */
  functionNames: string[];
  /** Names of the functions that can initialize values before all tests. */
  initializationAllFunctionNames: string[];
  /** Names of the functions that can initialize values before each test. */
  initializationEachFunctionNames: string[];
  /** Names of the functions that can unreference values before all tests. */
  unreferenceAllFunctionNames: string[];
  /** Names of the functions that can unreference values before each test. */
  unreferenceEachFunctionNames: string[];
  /** Names of the functions that can use the values. */
  testFunctionNames: string[];
  /** Prefer using initialization in all function. */
  preferAll: boolean;
};

The default options are a merge of jasmine and mocha naming convention, but there are separate configurations if that is preferred.

export const defaultJasmineInDescribeRuleOptions: InDescribeRuleOptions = {
  functionNames: ['describe', 'fdescribe', 'xdescribe'],
  initializationEachFunctionNames: ['beforeEach'],
  initializationAllFunctionNames: ['beforeAll'],
  unreferenceEachFunctionNames: ['afterEach'],
  unreferenceAllFunctionNames: ['afterAll'],
  testFunctionNames: ['it', 'fit', 'xit'],
  preferAll: false,
};

export const defaultMochaInDescribeRuleOptions: InDescribeRuleOptions = {
  functionNames: ['describe', 'fdescribe', 'xdescribe'],
  initializationEachFunctionNames: ['beforeEach'],
  initializationAllFunctionNames: ['before'],
  unreferenceEachFunctionNames: ['afterEach'],
  unreferenceAllFunctionNames: ['after'],
  testFunctionNames: ['it', 'test', 'fit', 'xit'],
  preferAll: false,
};

export const defaultInDescribeRuleOptions = {
  functionNames: ['describe', 'fdescribe', 'xdescribe'],
  initializationEachFunctionNames: ['beforeEach'],
  initializationAllFunctionNames: ['beforeAll', 'before'],
  unreferenceEachFunctionNames: ['afterEach'],
  unreferenceAllFunctionNames: ['afterAll', 'after'],
  testFunctionNames: ['it', 'test', 'fit', 'xit'],
  preferAll: false,
};

assignment-in-describe (There are assignments in a describe.)

Looks for cases when assignment to a variable happens in a describe but not within a declaration.

describe('test-describe-let', () => {
  let a;
  a = {}; // This will trigger it

  it('test', () => {
    // use a...
  });
});

Initialize values in "beforeEach" and unreference in "afterEach"

(This is the default fix.)

describe('test-describe-let', () => {
  let a;

  beforeEach(() => {
    a = {};
  });

  afterEach(() => {
    a = undefined;
  });

  it('test', () => {
    // use a...
  });
});

Initialize values in "beforeAll" and unreference in "afterAll"

describe('test-describe-let', () => {
  let a;

  beforeAll(() => {
    a = {};
  });

  afterAll(() => {
    a = undefined;
  });

  it('test', () => {
    // use a...
  });
});

Options

Same as declaration-in-describe rule.

no-cleanup-before-each-rule (There is assignment in "beforeEach" but no cleanup in "afterEach".)

Looks for cases when we assign a value to a variable in a beforeEach call, but there is no or the last assignment is not a dereference.

If we dereference it in an afterAll, this rule will still trigger (initialization and cleanup should happen in the same level).

describe('test-describe-let', () => {
  let a;

  beforeEach(() => {
    a = {}; // This will trigger it
  });
});

The fix for this will unreference the variable in a afterEach call.

describe('test-describe-let', () => {
  let a;

  beforeEach(() => {
    a = {};
  });

  afterEach(() => {
    a = undefined;
  });
});

Options

export const defaultNoCleanupEachOptions = {
    initializationFunctionNames: ['beforeEach'],
    unreferenceFunctionNames: ['afterEach']
};

There are mocha and jasmine variant of the options.

no-cleanup-before-all-rule (There is assignment in "beforeAll" but no cleanup in "afterAll".)

Looks for cases when we assign a value to a variable in a beforeAll call, but there is no or the last assignment is not a dereference.

If we dereference it in an afterEach, this rule will still trigger (initialization and cleanup should happen in the same level).

describe('test-describe-let', () => {
  let a;

  beforeAll(() => {
    a = {}; // This will trigger it
  });
});

The fix for this will unreference the variable in a afterEach call.

describe('test-describe-let', () => {
  let a;

  beforeAll(() => {
    a = {};
  });

  afterAll(() => {
    a = undefined;
  });
});

Options

export const defaultNoCleanupAllOptions = {
    initializationFunctionNames: ['beforeAll', 'before'],
    unreferenceFunctionNames: ['afterAll', 'after']
};

There are mocha and jasmine variant of the options.

no-cleanup-it-rule (There is assignment in "it" but no cleanup in "it".)

Looks for cases when we assign a value to a variable in a beforeAll call, but there is no or the last assignment is not a dereference.

If we dereference it in an afterEach, this rule will still trigger (initialization and cleanup should happen in the same level).

describe('test-describe-let', () => {
  let a;

  beforeAll(() => {
    a = {}; // This will trigger it
  });
});

The fix for this will unreference the variable in a afterEach call.

describe('test-describe-let', () => {
  let a;

  beforeAll(() => {
    a = {};
  });

  afterAll(() => {
    a = undefined;
  });
});

Options

export const defaultNoCleanupTestOptions = {
    initializationFunctionNames: ['it', 'fit', 'xit', 'test'],
    unreferenceFunctionNames: ['it', 'afterEach', 'afterAll', 'after'],
};

There are mocha and jasmine variant of the options.

How to build

  • download the source or clone it
  • npm i
  • npm run build (or build:samples to check out in the samples)

How to debug

  • vscode F5 (or debug) (on the selected jest test file) or run npm test

Samples

The samples are a configured mini project that uses only these rules, so you can see it in action. To try it out open the samples folder, do not run it from the main folder, because ESLint will have false results.

Known issues

  • "var" declarations in certain situations (when it is not used like a "let") can break some logics.
  • Mocha method suffixes are not supported e.g. describe.only.
  • Variable captures outside test methods can be problematic, e.g. using forEach in a describe to go through test data and call it on each members, or using test data in the names of it, describe blocks.

版本与发布记录

@droppedcode/eslint-plugin-jasmine-memoryleak-linter 共发布 14 个版本,首次发布于 2023/07/09;过去 12 个月发布了 0 个版本。

版本发布日期距今
1.0.13latest2024/11/172 年前
1.0.122024/03/312 年前
1.0.112023/10/013 年前
1.0.102023/08/253 年前
1.0.92023/08/193 年前
1.0.82023/08/143 年前

关于 @droppedcode/eslint-plugin-jasmine-memoryleak-linter 的常见问题

@droppedcode/eslint-plugin-jasmine-memoryleak-linter 是什么?

An ESLint extension to detect and fix Jasmine / Mocha related memory leaks.

如何安装 @droppedcode/eslint-plugin-jasmine-memoryleak-linter?

在项目目录运行 npm install @droppedcode/eslint-plugin-jasmine-memoryleak-linter,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@typescript-eslint/utils(^8.14.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@droppedcode/eslint-plugin-jasmine-memoryleak-linter 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@droppedcode/eslint-plugin-jasmine-memoryleak-linter 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@droppedcode/eslint-plugin-jasmine-memoryleak-linter 可以商用吗?

@droppedcode/eslint-plugin-jasmine-memoryleak-linter 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@droppedcode/eslint-plugin-jasmine-memoryleak-linter 的下载量有多少?

根据 npm 官方下载统计,@droppedcode/eslint-plugin-jasmine-memoryleak-linter 在 2026/10/13 – 2026/11/11 这 30 天内被下载 3,026 次,日均约 101 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@droppedcode/eslint-plugin-jasmine-memoryleak-linter 还在维护吗?

最新版本 1.0.13 发布于 2024/11/17(2 年前);至今共发布 14 个版本,其中过去 12 个月发布了 0 个;首次发布于 2023/07/09。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。