From 563d9c565c7e00ae6d13307737da63df99e68b9b Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 23 Apr 2020 09:05:18 +0200 Subject: [PATCH] fix: pass custom cached realpath function to `resolve` --- CHANGELOG.md | 1 + packages/jest-resolve/src/defaultResolver.ts | 49 ++++++++++++++------ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f1165f46273..1b51d48e0c9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Fixes +- `[jest-resolve]` Pass custom cached `realpath` function to `resolve` ([#9873](https://github.com/facebook/jest/pull/9873)) - `[jest-runtime]` Support importing CJS from ESM using `import` statements ([#9850](https://github.com/facebook/jest/pull/9850)) - `[jest-runtime]` Support importing parallel dynamic `import`s ([#9858](https://github.com/facebook/jest/pull/9858)) diff --git a/packages/jest-resolve/src/defaultResolver.ts b/packages/jest-resolve/src/defaultResolver.ts index 30a7d7948881..0d796e88abe2 100644 --- a/packages/jest-resolve/src/defaultResolver.ts +++ b/packages/jest-resolve/src/defaultResolver.ts @@ -42,26 +42,17 @@ export default function defaultResolver( paths: options.paths, preserveSymlinks: false, // @ts-ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/44137 - realpathSync: realpath, + realpathSync, }); - try { - // Dereference symlinks to ensure we don't create a separate - // module instance depending on how it was referenced. - const resolved = realpath(result); - - if (resolved) { - return resolved; - } - } catch { - // ignore - } - - return result; + // Dereference symlinks to ensure we don't create a separate + // module instance depending on how it was referenced. + return realpathSync(result); } export function clearDefaultResolverCache(): void { checkedPaths.clear(); + checkedRealpathPaths.clear(); } enum IPathType { @@ -99,6 +90,32 @@ function statSyncCached(path: string): IPathType { return IPathType.OTHER; } +const checkedRealpathPaths = new Map(); +function realpathCached(path: Config.Path): Config.Path { + let result = checkedRealpathPaths.get(path); + + if (result !== undefined) { + return result; + } + + try { + result = realpath(path); + } catch { + // ignore + } + + if (!result) { + result = path; + } + + checkedRealpathPaths.set(path, result); + + // also cache the result in case it's ever referenced directly - no reason to `realpath` that as well + checkedRealpathPaths.set(result, result); + + return result; +} + /* * helper functions */ @@ -109,3 +126,7 @@ function isFile(file: Config.Path): boolean { function isDirectory(dir: Config.Path): boolean { return statSyncCached(dir) === IPathType.DIRECTORY; } + +function realpathSync(file: Config.Path): Config.Path { + return realpathCached(file); +}