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

import.meta.resolve support #14930

Merged
merged 11 commits into from
Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- `[jest-mock]` Add support for the Explicit Resource Management proposal to use the `using` keyword with `jest.spyOn(object, methodName)` ([#14895](https://github.com/jestjs/jest/pull/14895))
- `[jest-runtime]` Exposing new modern timers function `jest.advanceTimersToFrame()` from `@jest/fake-timers` ([#14598](https://github.com/jestjs/jest/pull/14598))
- `[jest-runtime]` Support `import.meta.filename` and `import.meta.dirname` (available from [Node 20.11](https://nodejs.org/en/blog/release/v20.11.0)) ([#14854](https://github.com/jestjs/jest/pull/14854))
- `[jest-runtime]` Support `import.meta.resolve` ([#14930](https://github.com/jestjs/jest/pull/14930))
- `[@jest/schemas]` Upgrade `@sinclair/typebox` to v0.31 ([#14072](https://github.com/jestjs/jest/pull/14072))
- `[@jest/types]` `test.each()`: Accept a readonly (`as const`) table properly ([#14565](https://github.com/jestjs/jest/pull/14565))
- `[jest-snapshot]` [**BREAKING**] Add support for [Error causes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause) in snapshots ([#13965](https://github.com/facebook/jest/pull/13965))
Expand Down
12 changes: 12 additions & 0 deletions e2e/native-esm/__tests__/native-esm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ test('should have correct import.meta', () => {
dirname: expect.any(String),
filename: expect.any(String),
jest: expect.anything(),
resolve: expect.any(Function),
url: expect.any(String),
});
expect(import.meta.jest).toBe(jestObject);
Expand All @@ -56,6 +57,16 @@ test('should have correct import.meta', () => {
true,
);
}
expect(
import.meta
.resolve('colors')
.endsWith('jest/e2e/native-esm/node_modules/colors/lib/index.js'),
).toBe(true);
expect(
import.meta
.resolve('./native-esm.test')
.endsWith('jest/e2e/native-esm/__tests__/native-esm.test.js'),
).toBe(true);
});

test('should double stuff', () => {
Expand All @@ -68,6 +79,7 @@ test('should support importing node core modules', () => {

expect(JSON.parse(readFileSync(packageJsonPath, 'utf8'))).toEqual({
devDependencies: {
colors: '^1.4.0',
'discord.js': '14.3.0',
'iso-constants': '^0.1.2',
yargs: '^17.5.1',
Expand Down
1 change: 1 addition & 0 deletions e2e/native-esm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"isolated-vm": "^4.6.0"
},
"devDependencies": {
"colors": "^1.4.0",
"discord.js": "14.3.0",
"iso-constants": "^0.1.2",
"yargs": "^17.5.1"
Expand Down
8 changes: 8 additions & 0 deletions e2e/native-esm/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,13 @@ __metadata:
languageName: node
linkType: hard

"colors@npm:^1.4.0":
version: 1.4.0
resolution: "colors@npm:1.4.0"
checksum: 98aa2c2418ad87dedf25d781be69dc5fc5908e279d9d30c34d8b702e586a0474605b3a189511482b9d5ed0d20c867515d22749537f7bc546256c6014f3ebdcec
languageName: node
linkType: hard

"cross-spawn@npm:^7.0.0":
version: 7.0.3
resolution: "cross-spawn@npm:7.0.3"
Expand Down Expand Up @@ -1087,6 +1094,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "root-workspace-0b6124@workspace:."
dependencies:
colors: ^1.4.0
discord.js: 14.3.0
iso-constants: ^0.1.2
isolated-vm: ^4.6.0
Expand Down
57 changes: 34 additions & 23 deletions packages/jest-runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -518,12 +518,26 @@ export default class Runtime {
return this.linkAndEvaluateModule(module);
},
initializeImportMeta: (meta: JestImportMeta) => {
meta.url = pathToFileURL(modulePath).href;
const metaUrl = pathToFileURL(modulePath).href;
meta.url = metaUrl;

// @ts-expect-error Jest uses @types/node@16. Will be fixed when updated to @types/node@20.11.0
meta.filename = fileURLToPath(meta.url);
meta.filename = modulePath;
// @ts-expect-error Jest uses @types/node@16. Will be fixed when updated to @types/node@20.11.0
meta.dirname = path.dirname(meta.filename);
meta.dirname = path.dirname(modulePath);

// @ts-expect-error It should not be async. Will be fixed when updated to @types/node@20.11.0
meta.resolve = (specifier, parent = metaUrl) => {
const parentPath = fileURLToPath(parent);

const resolvedPath = this._resolver.resolveModule(
parentPath,
specifier,
{conditions: this.esmConditions},
);

return pathToFileURL(resolvedPath).href;
};

let jest = this.jestObjectCaches.get(modulePath);

Expand Down Expand Up @@ -1466,28 +1480,25 @@ export default class Runtime {
if (module) {
return module;
}
} else {
const {paths} = options;
if (paths) {
for (const p of paths) {
const absolutePath = path.resolve(from, '..', p);
const module = this._resolver.resolveModuleFromDirIfExists(
absolutePath,
moduleName,
// required to also resolve files without leading './' directly in the path
{conditions: this.cjsConditions, paths: [absolutePath]},
);
if (module) {
return module;
}
}

throw new Resolver.ModuleNotFoundError(
`Cannot resolve module '${moduleName}' from paths ['${paths.join(
"', '",
)}'] from ${from}`,
} else if (options.paths) {
for (const p of options.paths) {
const absolutePath = path.resolve(from, '..', p);
const module = this._resolver.resolveModuleFromDirIfExists(
absolutePath,
moduleName,
// required to also resolve files without leading './' directly in the path
{conditions: this.cjsConditions, paths: [absolutePath]},
);
if (module) {
return module;
}
}

throw new Resolver.ModuleNotFoundError(
`Cannot resolve module '${moduleName}' from paths ['${options.paths.join(
"', '",
)}'] from ${from}`,
);
}

try {
Expand Down
Loading