Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make Watchman existence check lazy and async
Summary: (This is a change I originally made "upstream" to `jest-haste-map` in jestjs/jest#12675) Currently, `metro-file-map` checks for Watchman existence at import time (top level) with a blocking `execSync` call. This has a few downsides: - Blocking at the top level holds up main thread (by 20-200ms) at a time when there's CPU work to be done. - `execSync` spawns a shell, which isn't necessary here - `execFile` is more efficient. - The exec happens totally unnecessarily even if the consumer specifies `useWatchman: false`. This diff extracts this to an async utility function, executed lazily and memoized by the core class. Reviewed By: huntie Differential Revision: D39772133 fbshipit-source-id: 7f7d5acd3506cb0c27a8f67e8813e867f25a83ba
- Loading branch information
1 parent
ab58166
commit 76c9307
Showing
4 changed files
with
93 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
packages/metro-file-map/src/lib/__tests__/canUseWatchman-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** | ||
* 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. | ||
* | ||
* @format | ||
* @flow strict | ||
*/ | ||
|
||
import canUseWatchman from '../canUseWatchman'; | ||
|
||
const mockExecFile = jest.fn(); | ||
jest.mock('child_process', () => ({ | ||
execFile: (...args) => mockExecFile(...args), | ||
})); | ||
|
||
describe('canUseWatchman', () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('executes watchman --version and returns true on success', async () => { | ||
mockExecFile.mockImplementation((file, args, cb) => { | ||
expect(file).toBe('watchman'); | ||
expect(args).toStrictEqual(['--version']); | ||
cb(null, {stdout: 'v123'}); | ||
}); | ||
expect(await canUseWatchman()).toBe(true); | ||
expect(mockExecFile).toHaveBeenCalledWith( | ||
'watchman', | ||
['--version'], | ||
expect.any(Function), | ||
); | ||
}); | ||
|
||
it('returns false when execFile fails', async () => { | ||
mockExecFile.mockImplementation((file, args, cb) => { | ||
cb(new Error()); | ||
}); | ||
expect(await canUseWatchman()).toBe(false); | ||
expect(mockExecFile).toHaveBeenCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* 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. | ||
* | ||
* @format | ||
* @flow strict | ||
*/ | ||
|
||
import {execFile} from 'child_process'; | ||
import {promisify} from 'util'; | ||
|
||
export default async function canUseWatchman(): Promise<boolean> { | ||
try { | ||
await promisify(execFile)('watchman', ['--version']); | ||
return true; | ||
} catch { | ||
return false; | ||
} | ||
} |