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..a0e9d7f70 100644 --- a/packages/metro-file-map/src/watchers/FSEventsWatcher.js +++ b/packages/metro-file-map/src/watchers/FSEventsWatcher.js @@ -13,9 +13,12 @@ import type {ChangeEventMetadata} from '../flow-types'; // $FlowFixMe[untyped-type-import] import type {FSEvents} from 'fsevents'; -import {isIncluded, recReaddir, typeFromStat} from './common'; -// $FlowFixMe[untyped-import] - anymatch -import anymatch from 'anymatch'; +import { + isIncluded, + posixPathMatchesPattern, + recReaddir, + typeFromStat, +} from './common'; import EventEmitter from 'events'; import {promises as fsPromises} from 'fs'; import * as path from 'path'; @@ -63,7 +66,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 +85,12 @@ 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 + ? (filePath: string) => posixPathMatchesPattern(ignored, 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..5bfc97b81 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 => ignored.test(toPosixSeparators(filePath)) + : () => false; if (opts.watchman == true && opts.watchmanPath != null) { watcher.watchmanPath = opts.watchmanPath; @@ -105,6 +105,26 @@ export function isIncluded( return micromatch.some(relativePath, globs, {dot}); } +const toPosixSeparators: (filePath: string) => string = + path.sep === '/' + ? filePath => filePath + : filePath => filePath.replaceAll(path.sep, '/'); + +/** + * 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 + */ +export const posixPathMatchesPattern = ( + pattern: RegExp, + filePath: string, +): boolean => pattern.test(toPosixSeparators(filePath)); + /** * Traverse a directory recursively calling `callback` on every directory. */ @@ -117,8 +137,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))