diff --git a/packages/metro-file-map/package.json b/packages/metro-file-map/package.json index a97dea57d..726c2e374 100644 --- a/packages/metro-file-map/package.json +++ b/packages/metro-file-map/package.json @@ -13,7 +13,6 @@ }, "license": "MIT", "dependencies": { - "anymatch": "^3.0.3", "debug": "^2.2.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", diff --git a/packages/metro-file-map/src/watchers/FSEventsWatcher.js b/packages/metro-file-map/src/watchers/FSEventsWatcher.js index fe3e16bbe..67962a042 100644 --- a/packages/metro-file-map/src/watchers/FSEventsWatcher.js +++ b/packages/metro-file-map/src/watchers/FSEventsWatcher.js @@ -14,8 +14,6 @@ import type {ChangeEventMetadata} from '../flow-types'; import type {FSEvents} from 'fsevents'; import {isIncluded, recReaddir, typeFromStat} from './common'; -// $FlowFixMe[untyped-import] - anymatch -import anymatch from 'anymatch'; import EventEmitter from 'events'; import {promises as fsPromises} from 'fs'; import * as path from 'path'; @@ -63,7 +61,11 @@ export default class FSEventsWatcher extends EventEmitter { constructor( dir: string, - opts: $ReadOnly<{ + { + ignored, + glob, + dot, + }: $ReadOnly<{ ignored: ?RegExp, glob: string | $ReadOnlyArray, dot: boolean, @@ -78,10 +80,14 @@ export default class FSEventsWatcher extends EventEmitter { super(); - this.dot = opts.dot || false; - this.ignored = opts.ignored; - this.glob = Array.isArray(opts.glob) ? opts.glob : [opts.glob]; - this.doIgnore = opts.ignored ? anymatch(opts.ignored) : () => false; + this.dot = dot || false; + this.ignored = ignored; + this.glob = Array.isArray(glob) ? glob : [glob]; + this.doIgnore = ignored + ? // No need to normalise Windows paths to posix because this backend + // only runs on macOS, and backends always emit system-native paths. + (filePath: string) => ignored.test(filePath) + : () => false; this.root = path.resolve(dir); diff --git a/packages/metro-file-map/src/watchers/common.js b/packages/metro-file-map/src/watchers/common.js index 099ba1626..f65631bce 100644 --- a/packages/metro-file-map/src/watchers/common.js +++ b/packages/metro-file-map/src/watchers/common.js @@ -19,8 +19,6 @@ import type {ChangeEventMetadata} from '../flow-types'; import type {Stats} from 'fs'; -// $FlowFixMe[untyped-import] - Write libdefs for `anymatch` -const anymatch = require('anymatch'); // $FlowFixMe[untyped-import] - Write libdefs for `micromatch` const micromatch = require('micromatch'); const platform = require('os').platform(); @@ -74,8 +72,10 @@ export const assignOptions = function ( if (!Array.isArray(watcher.globs)) { watcher.globs = [watcher.globs]; } - watcher.doIgnore = - opts.ignored != null ? anymatch(opts.ignored) : () => false; + const ignored = watcher.ignored; + watcher.doIgnore = ignored + ? filePath => posixPathMatchesPattern(ignored, filePath) + : () => false; if (opts.watchman == true && opts.watchmanPath != null) { watcher.watchmanPath = opts.watchmanPath; @@ -105,6 +105,21 @@ export function isIncluded( return micromatch.some(relativePath, globs, {dot}); } +/** + * Whether the given filePath matches the given RegExp, after converting + * (on Windows only) system separators to posix separators. + * + * Conversion to posix is for backwards compatibility with the previous + * anymatch matcher, which normlises all inputs[1]. This may not be consistent + * with other parts of metro-file-map. + * + * [1]: https://github.com/micromatch/anymatch/blob/3.1.1/index.js#L50 + */ +const posixPathMatchesPattern: (pattern: RegExp, filePath: string) => boolean = + path.sep === '/' + ? (pattern, filePath) => pattern.test(filePath) + : (pattern, filePath) => pattern.test(filePath.replaceAll(path.sep, '/')); + /** * Traverse a directory recursively calling `callback` on every directory. */ @@ -117,8 +132,13 @@ export function recReaddir( errorCallback: Error => void, ignored: ?RegExp, ) { - walker(dir) - .filterDir(currentDir => !anymatch(ignored, currentDir)) + const walk = walker(dir); + if (ignored) { + walk.filterDir( + (currentDir: string) => !posixPathMatchesPattern(ignored, currentDir), + ); + } + walk .on('dir', normalizeProxy(dirCallback)) .on('file', normalizeProxy(fileCallback)) .on('symlink', normalizeProxy(symlinkCallback))