Skip to content

Commit

Permalink
fix: actually add dispose Symbols to Node globals (#14909)
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB authored Feb 20, 2024
1 parent dcc4bc3 commit 9914dc4
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 42 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
- `[@jest/core, @jest/test-sequencer]` [**BREAKING**] Exposes `globalConfig` & `contexts` to `TestSequencer` ([#14535](https://github.com/jestjs/jest/pull/14535), & [#14543](https://github.com/jestjs/jest/pull/14543))
- `[jest-environment-jsdom]` [**BREAKING**] Upgrade JSDOM to v22 ([#13825](https://github.com/jestjs/jest/pull/13825))
- `[@jest/environment-jsdom-abstract]` Introduce new package which abstracts over the `jsdom` environment, allowing usage of custom versions of JSDOM ([#14717](https://github.com/jestjs/jest/pull/14717))
- `[jest-environment-node]` Update jest environment with dispose symbols `Symbol` ([#14888](https://github.com/jestjs/jest/pull/14888))
- `[jest-environment-node]` Update jest environment with dispose symbols `Symbol` ([#14888](https://github.com/jestjs/jest/pull/14888) & [#14909](https://github.com/jestjs/jest/pull/14909))
- `[@jest/fake-timers]` [**BREAKING**] Upgrade `@sinonjs/fake-timers` to v11 ([#14544](https://github.com/jestjs/jest/pull/14544))
- `[@jest/fake-timers]` Exposing new modern timers function `advanceTimersToFrame()` which advances all timers by the needed milliseconds to execute callbacks currently scheduled with `requestAnimationFrame` ([#14598](https://github.com/jestjs/jest/pull/14598))
- `[jest-runtime]` Exposing new modern timers function `jest.advanceTimersToFrame()` from `@jest/fake-timers` ([#14598](https://github.com/jestjs/jest/pull/14598))
Expand Down
13 changes: 13 additions & 0 deletions e2e/__tests__/__snapshots__/globals.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,19 @@ Time: <<REPLACED>>
Ran all test suites."
`;
exports[`on node ^18.18.0 || >=20.4.0 Symbol's \`dispose\` are available 1`] = `
"PASS __tests__/symbolDispose.test.js
✓ test"
`;
exports[`on node ^18.18.0 || >=20.4.0 Symbol's \`dispose\` are available 2`] = `
"Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: <<REPLACED>>
Ran all test suites."
`;
exports[`only 1`] = `
"PASS __tests__/onlyConstructs.test.js
✓ test.only
Expand Down
21 changes: 21 additions & 0 deletions e2e/__tests__/globals.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import {tmpdir} from 'os';
import * as path from 'path';
import {onNodeVersions} from '@jest/test-utils';
import {
cleanup,
createEmptyPackage,
Expand Down Expand Up @@ -295,3 +296,23 @@ test('function as it() descriptor', () => {
expect(summary).toMatchSnapshot();
expect(exitCode).toBe(0);
});

onNodeVersions('^18.18.0 || >=20.4.0', () => {
test("Symbol's `dispose` are available", () => {
const filename = 'symbolDispose.test.js';
const content = `
it('test', () => {
expect(Symbol.dispose).toBeDefined();
expect(Symbol.asyncDispose).toBeDefined();
});
`;

writeFiles(TEST_DIR, {[filename]: content});
const {stderr, exitCode} = runJest(DIR);

const {summary, rest} = extractSummary(stderr);
expect(rest).toMatchSnapshot();
expect(summary).toMatchSnapshot();
expect(exitCode).toBe(0);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -72,28 +72,6 @@ describe('NodeEnvironment', () => {
}
});

it('should configure dispose symbols', () => {
const env = new NodeEnvironment(
{
globalConfig: makeGlobalConfig(),
projectConfig: makeProjectConfig(),
},
context,
);

if ('asyncDispose' in Symbol) {
expect(env.global.Symbol).toHaveProperty('asyncDispose');
} else {
expect(env.global.Symbol).not.toHaveProperty('asyncDispose');
}

if ('dispose' in Symbol) {
expect(env.global.Symbol).toHaveProperty('dispose');
} else {
expect(env.global.Symbol).not.toHaveProperty('dispose');
}
});

it('has modern fake timers implementation', () => {
const env = new NodeEnvironment(
{
Expand Down
26 changes: 8 additions & 18 deletions packages/jest-environment-node/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,6 @@ function isString(value: unknown): value is string {
return typeof value === 'string';
}

function setDisposeSymbols(context: Context): void {
if ('asyncDispose' in Symbol) {
runInContext(
'if (!"asyncDispose" in Symbol) { Symbol.asyncDispose = Symbol.for("nodejs.asyncDispose") }',
context,
);
}

if ('dispose' in Symbol) {
runInContext(
'if (!"dispose" in Symbol) { Symbol.dispose = Symbol.for("nodejs.dispose") }',
context,
);
}
}

const timerIdToRef = (id: number) => ({
id,
ref() {
Expand All @@ -102,8 +86,6 @@ export default class NodeEnvironment implements JestEnvironment<Timer> {
const {projectConfig} = config;
this.context = createContext();

setDisposeSymbols(this.context);

const global = runInContext(
'this',
Object.assign(this.context, projectConfig.testEnvironmentOptions),
Expand Down Expand Up @@ -170,6 +152,14 @@ export default class NodeEnvironment implements JestEnvironment<Timer> {

installCommonGlobals(global, projectConfig.globals);

if ('asyncDispose' in Symbol && !('asyncDispose' in global.Symbol)) {
const globalSymbol = global.Symbol as unknown as SymbolConstructor;
// @ts-expect-error - it's readonly - but we have checked above that it's not there
globalSymbol.asyncDispose = globalSymbol('nodejs.asyncDispose');
// @ts-expect-error - it's readonly - but we have checked above that it's not there
globalSymbol.dispose = globalSymbol('nodejs.dispose');
}

// Node's error-message stack size is limited at 10, but it's pretty useful
// to see more than that when a test fails.
global.Error.stackTraceLimit = 100;
Expand Down
3 changes: 2 additions & 1 deletion packages/jest-environment-node/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "build",
"rootDir": "src"
"rootDir": "src",
"lib": ["es2021", "ESNext.Disposable"]
},
"include": ["./src/**/*"],
"exclude": ["./**/__tests__/**/*"],
Expand Down

0 comments on commit 9914dc4

Please sign in to comment.