Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: isolate esm async import bug #14397

Merged
merged 15 commits into from Aug 21, 2023
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,8 @@

### Fixes

- `[jest-runtime]` Fix dynamic esm import module bug when loaded module through `jest.isolateModulesAsync` ([14397](https://github.com/jestjs/jest/pull/14397))
eryue0220 marked this conversation as resolved.
Show resolved Hide resolved

### Chore & Maintenance

### Performance
Expand Down
9 changes: 9 additions & 0 deletions e2e/__tests__/__snapshots__/asyncESMImport.test.ts.snap
@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`runs test with async ESM import 1`] = `
"Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: <<REPLACED>>
Ran all test suites."
`;
20 changes: 20 additions & 0 deletions e2e/__tests__/asyncESMImport.test.ts
eryue0220 marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,20 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {extractSummary} from '../Utils';
import runJest from '../runJest';

test('runs test with async ESM import', () => {
const {exitCode, stderr} = runJest('async-esm-import', [], {
nodeOptions: '--experimental-vm-modules --no-warnings',
});

const {summary} = extractSummary(stderr);

expect(summary).toMatchSnapshot();

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-ubuntu / Node v18.x on ubuntu-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / Node LTS on Ubuntu with coverage (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-ubuntu / Node v14.x on ubuntu-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19) at runMicrotasks (<anonymous>)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-ubuntu / Node v16.x on ubuntu-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19) at runMicrotasks (<anonymous>)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-ubuntu / Node v20.x on ubuntu-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-ubuntu / Node LTS on ubuntu-latest using jest-jasmine2 (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-macos / Node v14.x on macos-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-windows / Node LTS on windows-latest using jest-jasmine2 (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-windows / Node v16.x on windows-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-windows / Node v14.x on windows-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19) at runMicrotasks (<anonymous>)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-macos / Node v16.x on macos-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-macos / Node v18.x on macos-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-windows / Node v18.x on windows-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-ubuntu / Node v19.x on ubuntu-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-windows / Node v19.x on windows-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-windows / Node v20.x on windows-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-macos / Node v19.x on macos-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-macos / Node v20.x on macos-latest (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)

Check failure on line 18 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-macos / Node LTS on macos-latest using jest-jasmine2 (3/4)

runs test with async ESM import

expect(received).toMatchSnapshot() Snapshot name: `runs test with async ESM import 1` - Snapshot - 2 + Received + 2 - Test Suites: 1 passed, 1 total + Test Suites: 1 failed, 1 total - Tests: 1 passed, 1 total + Tests: 0 total Snapshots: 0 total Time: <<REPLACED>> Ran all test suites. at Object.toMatchSnapshot (e2e/__tests__/asyncESMImport.test.ts:18:19)
expect(exitCode).toBe(0);

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-ubuntu / Node v18.x on ubuntu-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / Node LTS on Ubuntu with coverage (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-ubuntu / Node v14.x on ubuntu-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20) at runMicrotasks (<anonymous>)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-ubuntu / Node v16.x on ubuntu-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20) at runMicrotasks (<anonymous>)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-ubuntu / Node v20.x on ubuntu-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-macos / Node v14.x on macos-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-windows / Node v16.x on windows-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-windows / Node v14.x on windows-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20) at runMicrotasks (<anonymous>)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-macos / Node v16.x on macos-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-macos / Node v18.x on macos-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-windows / Node v18.x on windows-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-ubuntu / Node v19.x on ubuntu-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-windows / Node v19.x on windows-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-windows / Node v20.x on windows-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-macos / Node v19.x on macos-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)

Check failure on line 19 in e2e/__tests__/asyncESMImport.test.ts

View workflow job for this annotation

GitHub Actions / test-macos / Node v20.x on macos-latest (3/4)

runs test with async ESM import

expect(received).toBe(expected) // Object.is equality Expected: 0 Received: 1 at Object.toBe (e2e/__tests__/asyncESMImport.test.ts:19:20)
});
22 changes: 22 additions & 0 deletions e2e/async-esm-import/__tests__/test.js
@@ -0,0 +1,22 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {jest} from '@jest/globals';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import {jest} from '@jest/globals';

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import could not remove, because the next code will use the api jest. isolateModulesAsync


test('should have a fresh module state in each isolateModulesAsync context', async () => {
await jest.isolateModulesAsync(async () => {
const {getState, incState} = await import('../main.js');
eryue0220 marked this conversation as resolved.
Show resolved Hide resolved
expect(getState()).toBe(0);
incState();
expect(getState()).toBe(1);
});
await jest.isolateModulesAsync(async () => {
const {getState, incState} = await import('../main.js');
eryue0220 marked this conversation as resolved.
Show resolved Hide resolved
expect(getState()).toBe(0);
incState();
expect(getState()).toBe(1);
});
});
15 changes: 15 additions & 0 deletions e2e/async-esm-import/main.js
@@ -0,0 +1,15 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
let myState = 0;

export function incState() {
myState += 1;
}

export function getState() {
return myState;
}
6 changes: 6 additions & 0 deletions e2e/async-esm-import/package.json
@@ -0,0 +1,6 @@
{
"name": "async-esm-import",
"jest": {
"testEnvironment": "node"
}
}
1 change: 0 additions & 1 deletion e2e/resolve-async/package.json
@@ -1,5 +1,4 @@
{
"type": "module",
eryue0220 marked this conversation as resolved.
Show resolved Hide resolved
"jest": {
"resolver": "<rootDir>/resolver.cjs",
"transform": {}
Expand Down
38 changes: 27 additions & 11 deletions packages/jest-runtime/src/index.ts
Expand Up @@ -179,6 +179,7 @@ export default class Runtime {
private readonly _moduleMockFactories: Map<string, () => unknown>;
private readonly _moduleMocker: ModuleMocker;
private _isolatedModuleRegistry: ModuleRegistry | null;
private _isolatedESMModuleRegistry: ModuleRegistry | null;
private _moduleRegistry: ModuleRegistry;
private readonly _esmoduleRegistry: Map<string, VMModule>;
private readonly _cjsNamedExports: Map<string, Set<string>>;
Expand Down Expand Up @@ -242,6 +243,7 @@ export default class Runtime {
this._moduleMocker = this._environment.moduleMocker;
this._isolatedModuleRegistry = null;
this._isolatedMockRegistry = null;
this._isolatedESMModuleRegistry = null;
this._moduleRegistry = new Map();
this._esmoduleRegistry = new Map();
this._cjsNamedExports = new Map();
Expand Down Expand Up @@ -416,12 +418,15 @@ export default class Runtime {
query = '',
): Promise<VMModule> {
const cacheKey = modulePath + query;
const registry = this._isolatedESMModuleRegistry
? this._isolatedESMModuleRegistry
: this._esmoduleRegistry;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm.. Isn’t it enough to use the same _isolatedMockRegistry? Did you try that?

It was my idea about missing _isolatedESMModuleRegistry, but it can I was wrong. Here we can see that _isolatedMockRegistry was simply not used while loading ES modules. Sorry about slow thinking. Could you try to _isolatedMockRegistry everywhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course, it is possible. I originally thought it was intentionally differentiated because I saw that there was already an existing _isolatedModuleRegistry, moreover, I think it seems more appropriate.


if (this._fileTransformsMutex.has(cacheKey)) {
await this._fileTransformsMutex.get(cacheKey);
}

if (!this._esmoduleRegistry.has(cacheKey)) {
if (!registry.has(cacheKey)) {
invariant(
typeof this._environment.getVmContext === 'function',
'ES Modules are only supported if your test environment has the `getVmContext` function',
Expand Down Expand Up @@ -454,15 +459,15 @@ export default class Runtime {
context,
);

this._esmoduleRegistry.set(cacheKey, wasm);
registry.set(cacheKey, wasm);

transformResolve();
return wasm;
}

if (this._resolver.isCoreModule(modulePath)) {
const core = this._importCoreModule(modulePath, context);
this._esmoduleRegistry.set(cacheKey, core);
registry.set(cacheKey, core);

transformResolve();

Expand Down Expand Up @@ -526,11 +531,11 @@ export default class Runtime {
}

invariant(
!this._esmoduleRegistry.has(cacheKey),
!registry.has(cacheKey),
`Module cache already has entry ${cacheKey}. This is a bug in Jest, please report it!`,
);

this._esmoduleRegistry.set(cacheKey, module);
registry.set(cacheKey, module);

transformResolve();
} catch (error) {
Expand All @@ -539,7 +544,7 @@ export default class Runtime {
}
}

const module = this._esmoduleRegistry.get(cacheKey);
const module = registry.get(cacheKey);

invariant(
module,
Expand All @@ -563,14 +568,18 @@ export default class Runtime {
return;
}

const registry = this._isolatedESMModuleRegistry
? this._isolatedESMModuleRegistry
: this._esmoduleRegistry;

if (specifier === '@jest/globals') {
const fromCache = this._esmoduleRegistry.get('@jest/globals');
const fromCache = registry.get('@jest/globals');

if (fromCache) {
return fromCache;
}
const globals = this.getGlobalsForEsm(referencingIdentifier, context);
this._esmoduleRegistry.set('@jest/globals', globals);
registry.set('@jest/globals', globals);

return globals;
}
Expand All @@ -586,7 +595,7 @@ export default class Runtime {
return this.importMock(referencingIdentifier, specifier, context);
}

const fromCache = this._esmoduleRegistry.get(specifier);
const fromCache = registry.get(specifier);

if (fromCache) {
return fromCache;
Expand Down Expand Up @@ -662,7 +671,7 @@ export default class Runtime {
}
}

this._esmoduleRegistry.set(specifier, module);
registry.set(specifier, module);
return module;
}

Expand Down Expand Up @@ -1164,21 +1173,28 @@ export default class Runtime {
}

async isolateModulesAsync(fn: () => Promise<void>): Promise<void> {
if (this._isolatedModuleRegistry || this._isolatedMockRegistry) {
if (
this._isolatedModuleRegistry ||
this._isolatedMockRegistry ||
this._isolatedESMModuleRegistry
) {
throw new Error(
'isolateModulesAsync cannot be nested inside another isolateModulesAsync or isolateModules.',
);
}
this._isolatedModuleRegistry = new Map();
this._isolatedMockRegistry = new Map();
this._isolatedESMModuleRegistry = new Map();
try {
await fn();
} finally {
// might be cleared within the callback
this._isolatedModuleRegistry?.clear();
this._isolatedMockRegistry?.clear();
this._isolatedESMModuleRegistry?.clear();
this._isolatedModuleRegistry = null;
this._isolatedMockRegistry = null;
this._isolatedESMModuleRegistry = null;
}
}

eryue0220 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down