diff --git a/benchmark/path/matchesGlob-posix.js b/benchmark/path/matchesGlob-posix.js new file mode 100644 index 00000000000000..2cc30ca8ace1fb --- /dev/null +++ b/benchmark/path/matchesGlob-posix.js @@ -0,0 +1,28 @@ +'use strict'; +const common = require('../common.js'); +const { posix } = require('path'); +const assert = require('assert'); + +const bench = common.createBenchmark(main, { + path: [ + 'src/index.ts', + 'src/index.test.ts', + 'src/foo/bar/biz/baz/index.test.ts', + ], + pattern: [ + 'src/**/baz/*.test.ts', + 'src/**/baz/*.ts', + 'test/**/*.ts', + ], + n: [1e5], +}); + +function main({ path, pattern, n }) { + bench.start(); + let a; + for (let i = 0; i < n; i++) { + a = posix.matchesGlob(path, pattern); + } + bench.end(n); + assert(a + 'a'); +} diff --git a/benchmark/path/matchesGlob-win32.js b/benchmark/path/matchesGlob-win32.js new file mode 100644 index 00000000000000..3ef3c6b4434445 --- /dev/null +++ b/benchmark/path/matchesGlob-win32.js @@ -0,0 +1,29 @@ +'use strict'; +const common = require('../common.js'); +const { win32 } = require('path'); +const assert = require('assert'); + +const bench = common.createBenchmark(main, { + path: [ + 'src/index.ts', + 'src\\index.ts', + 'src/foo/bar/biz/baz/index.test.ts', + 'src\\foo\\bar\\biz\\baz\\index.test.ts', + ], + pattern: [ + 'src/**/baz/*.test.ts', + 'src/**/baz/*.ts', + 'test/**/*.ts', + ], + n: [1e5], +}); + +function main({ path, pattern, n }) { + bench.start(); + let a; + for (let i = 0; i < n; i++) { + a = win32.matchesGlob(path, pattern); + } + bench.end(n); + assert(a + 'a'); +} diff --git a/lib/internal/fs/glob.js b/lib/internal/fs/glob.js index 6cda2c9e6da073..44aff39627fde5 100644 --- a/lib/internal/fs/glob.js +++ b/lib/internal/fs/glob.js @@ -922,6 +922,8 @@ class Glob { } } +let patternFnCache; + /** * Check if a path matches a glob pattern * @param {string} path the path to check @@ -932,16 +934,25 @@ class Glob { function matchGlobPattern(path, pattern, windows = isWindows) { validateString(path, 'path'); validateString(pattern, 'pattern'); - return lazyMinimatch().minimatch(path, pattern, { - kEmptyObject, - nocase: isMacOS || isWindows, - windowsPathsNoEscape: true, - nonegate: true, - nocomment: true, - optimizationLevel: 2, - platform: windows ? 'win32' : 'posix', - nocaseMagicOnly: true, - }); + + patternFnCache ??= new SafeMap(); + + let matcher; + if (patternFnCache.has(pattern)) { + matcher = patternFnCache.get(pattern); + } else { + matcher = createMatcher(pattern, { + kEmptyObject, + platform: windows ? 'win32' : 'posix', + }); + patternFnCache.set(pattern, matcher); + + if (patternFnCache.size >= 250) { + patternFnCache.delete(patternFnCache.keys().next().value); + } + } + + return matcher.match(path); } module.exports = {