From bd9aae2868fc1e3568546036836ddf4f3d4e6c96 Mon Sep 17 00:00:00 2001 From: gonzaloriestra <14979109+gonzaloriestra@users.noreply.github.com> Date: Thu, 2 Jul 2026 01:12:50 +0000 Subject: [PATCH] [Performance] Memoize cwd() in path.ts --- packages/cli-kit/src/public/node/path.test.ts | 33 +++++++++++++++++-- packages/cli-kit/src/public/node/path.ts | 17 +++++++++- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/packages/cli-kit/src/public/node/path.test.ts b/packages/cli-kit/src/public/node/path.test.ts index 4972b3ac276..3c8844ed3d4 100644 --- a/packages/cli-kit/src/public/node/path.test.ts +++ b/packages/cli-kit/src/public/node/path.test.ts @@ -1,5 +1,5 @@ -import {relativizePath, normalizePath, cwd, sniffForPath, commonParentDirectory} from './path.js' -import {describe, test, expect} from 'vitest' +import {relativizePath, normalizePath, cwd, sniffForPath, commonParentDirectory, _resetCwd} from './path.js' +import {describe, test, expect, vi, beforeEach} from 'vitest' describe('relativize', () => { test('relativizes the path', () => { @@ -16,6 +16,10 @@ describe('relativize', () => { }) describe('cwd', () => { + beforeEach(() => { + _resetCwd() + }) + test.runIf(process.env.INIT_CWD)('returns the initial cwd where the command has been called', () => { // Given const path = cwd() @@ -23,6 +27,31 @@ describe('cwd', () => { // Then expect(path).toStrictEqual(normalizePath(process.env.INIT_CWD!)) }) + + test('memoizes the result', () => { + // Given + const processCwdSpy = vi.spyOn(process, 'cwd').mockReturnValue('/computed/path') + const originalInitCwd = process.env.INIT_CWD + delete process.env.INIT_CWD + + // When + const firstCall = cwd() + const secondCall = cwd() + + // Then + expect(firstCall).toBe(normalizePath('/computed/path')) + expect(secondCall).toBe(normalizePath('/computed/path')) + expect(processCwdSpy).toHaveBeenCalledTimes(1) + + // Resetting + _resetCwd() + cwd() + expect(processCwdSpy).toHaveBeenCalledTimes(2) + + // Restore + process.env.INIT_CWD = originalInitCwd + processCwdSpy.mockRestore() + }) }) describe('commonParentDirectory', () => { diff --git a/packages/cli-kit/src/public/node/path.ts b/packages/cli-kit/src/public/node/path.ts index f3721780110..b191f76376a 100644 --- a/packages/cli-kit/src/public/node/path.ts +++ b/packages/cli-kit/src/public/node/path.ts @@ -165,6 +165,11 @@ export function moduleDirectory(moduleURL: string | URL): string { return dirname(fileURLToPath(moduleURL)) } +/** + * Memoized value for the current working directory. + */ +let memoizedCwd: string | undefined + /** * When running a script using `npm run`, something interesting happens. If the current * folder does not have a `package.json` or a `node_modules` folder, npm will traverse @@ -175,8 +180,18 @@ export function moduleDirectory(moduleURL: string | URL): string { * @returns The path to the current working directory. */ export function cwd(): string { + if (memoizedCwd) return memoizedCwd // eslint-disable-next-line @shopify/cli/no-process-cwd - return normalize(process.env.INIT_CWD || process.cwd()) // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty env var should fall through + memoizedCwd = normalize(process.env.INIT_CWD || process.cwd()) // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty env var should fall through + return memoizedCwd +} + +/** + * Resets the memoized value of the current working directory. + * This is useful for testing purposes. + */ +export function _resetCwd(): void { + memoizedCwd = undefined } /**