Skip to content

fs: implement glob natively - #65392

Open
avivkeller wants to merge 1 commit into
nodejs:mainfrom
avivkeller:native-glob
Open

fs: implement glob natively#65392
avivkeller wants to merge 1 commit into
nodejs:mainfrom
avivkeller:native-glob

Conversation

@avivkeller

@avivkeller avivkeller commented Aug 18, 2026

Copy link
Copy Markdown
Member

Ref: https://openjs-foundation.slack.com/archives/C019Y2T6STH/p1787069174254509

(AI assistance used to help port minimatch to C++ and take improvements from other implementations, e.g. Rust's fast-glob [oxc] and picomatch, etc).

I'd love some pretty pedantic reviews since this is substantial. It's 1:1 with the existing glob, so it's non-breaking, but please tear this apart just in case.

Benchmarks below (major speedup, yay!):

fs/bench-glob.js (12 runs, --set n=100):

improvement significant   p.value  configuration
+   10.32 %  **     5.52e-3  fs/bench-glob.js recursive='false' mode='callback' pattern='*.js' dir='lib' n=100
   -2.04 %         2.67e-1  fs/bench-glob.js recursive='false' mode='callback' pattern='**/*' dir='lib' n=100
+    1.07 %         5.72e-1  fs/bench-glob.js recursive='false' mode='callback' pattern='**/**.js' dir='lib' n=100
   -0.64 %         7.64e-1  fs/bench-glob.js recursive='false' mode='promise' pattern='*.js' dir='lib' n=100
+    3.38 %         9.43e-2  fs/bench-glob.js recursive='false' mode='promise' pattern='**/*' dir='lib' n=100
   -0.69 %         7.77e-1  fs/bench-glob.js recursive='false' mode='promise' pattern='**/**.js' dir='lib' n=100
+  148.00 %  ***   1.85e-14  fs/bench-glob.js recursive='false' mode='sync' pattern='*.js' dir='lib' n=100
+   44.13 %  ***   2.43e-10  fs/bench-glob.js recursive='false' mode='sync' pattern='**/*' dir='lib' n=100
+   41.05 %  ***    7.99e-9  fs/bench-glob.js recursive='false' mode='sync' pattern='**/**.js' dir='lib' n=100
+    9.83 %  ***    4.52e-7  fs/bench-glob.js recursive='true' mode='callback' pattern='*.js' dir='lib' n=100
   -2.90 %         2.51e-1  fs/bench-glob.js recursive='true' mode='callback' pattern='**/*' dir='lib' n=100
+    1.08 %         5.87e-1  fs/bench-glob.js recursive='true' mode='callback' pattern='**/**.js' dir='lib' n=100
+    2.64 %         3.99e-1  fs/bench-glob.js recursive='true' mode='promise' pattern='*.js' dir='lib' n=100
+    8.98 %         5.71e-2  fs/bench-glob.js recursive='true' mode='promise' pattern='**/*' dir='lib' n=100
+    1.05 %         6.15e-1  fs/bench-glob.js recursive='true' mode='promise' pattern='**/**.js' dir='lib' n=100
+  148.31 %  ***   3.39e-20  fs/bench-glob.js recursive='true' mode='sync' pattern='*.js' dir='lib' n=100
+   40.73 %  ***    5.65e-9  fs/bench-glob.js recursive='true' mode='sync' pattern='**/*' dir='lib' n=100
+   42.54 %  ***    1.88e-9  fs/bench-glob.js recursive='true' mode='sync' pattern='**/**.js' dir='lib' n=100

path/matchesglob.js (20 runs):

improvement significant   p.value  configuration
+   73.02 %  ***   4.91e-34  path/matchesglob.js n=100000 platform='posix' pathpat='foo/bar/baz/asdf/quux.html|**/*.html'
+  167.15 %  ***   3.83e-35  path/matchesglob.js n=100000 platform='posix' pathpat='foo/bar/baz/asdf/quux.html|foo/[bc]ar/baz/**'
+  110.05 %  ***   4.82e-35  path/matchesglob.js n=100000 platform='posix' pathpat='foo/bar/baz/asdf/quux.html|foo/+(bar|baz)/**/*.{html,js}'
+   85.66 %  ***   6.01e-16  path/matchesglob.js n=100000 platform='posix' pathpat='foo/bar/baz/asdf/quux.html|foo/bar/baz/asdf/quux.html'
+   28.09 %  ***   2.66e-11  path/matchesglob.js n=100000 platform='posix' pathpat='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|*'
+   95.93 %  ***   4.08e-17  path/matchesglob.js n=100000 platform='win32' pathpat='foo/bar/baz/asdf/quux.html|**/*.html'
+  209.61 %  ***   9.82e-22  path/matchesglob.js n=100000 platform='win32' pathpat='foo/bar/baz/asdf/quux.html|foo/[bc]ar/baz/**'
+  150.69 %  ***   4.41e-35  path/matchesglob.js n=100000 platform='win32' pathpat='foo/bar/baz/asdf/quux.html|foo/+(bar|baz)/**/*.{html,js}'
+  139.18 %  ***   7.56e-48  path/matchesglob.js n=100000 platform='win32' pathpat='foo/bar/baz/asdf/quux.html|foo/bar/baz/asdf/quux.html'
+   51.60 %  ***   1.69e-23  path/matchesglob.js n=100000 platform='win32' pathpat='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|*'

AI-Assisted-By: Claude Fable 5

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/actions
  • @nodejs/performance
  • @nodejs/security-wg
  • @nodejs/tsc

@nodejs-github-bot nodejs-github-bot added dependencies Pull requests that update a dependency file. meta Issues and PRs related to the general management of the project. needs-ci PRs that need a full CI run. labels Aug 18, 2026
@avivkeller avivkeller added fs Issues and PRs related to the fs subsystem / file system. discuss Issues opened for discussions and feedbacks. performance Issues and PRs related to the performance of Node.js. labels Aug 18, 2026
@avivkeller

Copy link
Copy Markdown
Member Author

cc @isaacs @nodejs/fs

Signed-off-by: avivkeller <me@aviv.sh>
@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 74.33728% with 455 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.01%. Comparing base (13fcd6f) to head (8bedc81).
⚠️ Report is 13 commits behind head on main.

Files with missing lines Patch % Lines
src/node_glob.cc 71.78% 219 Missing and 231 partials ⚠️
lib/internal/fs/glob.js 96.93% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #65392      +/-   ##
==========================================
- Coverage   91.85%   90.01%   -1.84%     
==========================================
  Files         400      754     +354     
  Lines      178855   253323   +74468     
  Branches    27319    47817   +20498     
==========================================
+ Hits       164283   228024   +63741     
- Misses      14243    16400    +2157     
- Partials      329     8899    +8570     
Files with missing lines Coverage Δ
lib/internal/fs/watchers.js 88.16% <100.00%> (+0.08%) ⬆️
src/node_binding.cc 82.42% <ø> (ø)
src/node_external_reference.h 100.00% <ø> (ø)
src/node_glob.h 100.00% <100.00%> (ø)
lib/internal/fs/glob.js 91.64% <96.93%> (+3.69%) ⬆️
src/node_glob.cc 71.78% <71.78%> (ø)

... and 482 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aduh95

aduh95 commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

take improvements from other implementations, e.g. Rust's fast-glob [oxc] and picomatch, etc

I would feel more comfortable adopting one of those instead of having to maintain our own, have you explored that route?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file. discuss Issues opened for discussions and feedbacks. fs Issues and PRs related to the fs subsystem / file system. meta Issues and PRs related to the general management of the project. needs-ci PRs that need a full CI run. performance Issues and PRs related to the performance of Node.js.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants