@@ -16,7 +16,7 @@ const {
1616
1717const { lstatSync, readdirSync } = require ( 'fs' ) ;
1818const { lstat, readdir } = require ( 'fs/promises' ) ;
19- const { join, resolve } = require ( 'path' ) ;
19+ const { join, resolve, basename , isAbsolute } = require ( 'path' ) ;
2020
2121const {
2222 kEmptyObject,
@@ -27,6 +27,7 @@ const {
2727 validateString,
2828 validateStringArray,
2929} = require ( 'internal/validators' ) ;
30+ const { DirentFromStats } = require ( 'internal/fs/utils' ) ;
3031
3132let minimatch ;
3233function lazyMinimatch ( ) {
@@ -37,6 +38,14 @@ function lazyMinimatch() {
3738const isWindows = process . platform === 'win32' ;
3839const isOSX = process . platform === 'darwin' ;
3940
41+ async function getDirent ( path ) {
42+ return new DirentFromStats ( basename ( path ) , await lstat ( path ) , path ) ;
43+ }
44+
45+ function getDirentSync ( path ) {
46+ return new DirentFromStats ( basename ( path ) , lstatSync ( path ) , path ) ;
47+ }
48+
4049class Cache {
4150 #cache = new SafeMap ( ) ;
4251 #statsCache = new SafeMap ( ) ;
@@ -47,7 +56,7 @@ class Cache {
4756 if ( cached ) {
4857 return cached ;
4958 }
50- const promise = PromisePrototypeThen ( lstat ( path ) , null , ( ) => null ) ;
59+ const promise = PromisePrototypeThen ( getDirent ( path ) , null , ( ) => null ) ;
5160 this . #statsCache. set ( path , promise ) ;
5261 return promise ;
5362 }
@@ -58,7 +67,7 @@ class Cache {
5867 }
5968 let val ;
6069 try {
61- val = lstatSync ( path ) ;
70+ val = getDirentSync ( path ) ;
6271 } catch {
6372 val = null ;
6473 }
@@ -175,14 +184,16 @@ class Glob {
175184 #queue = [ ] ;
176185 #subpatterns = new SafeMap ( ) ;
177186 #patterns;
187+ #withFileTypes;
178188 constructor ( pattern , options = kEmptyObject ) {
179189 validateObject ( options , 'options' ) ;
180- const { exclude, cwd } = options ;
190+ const { exclude, cwd, withFileTypes } = options ;
181191 if ( exclude != null ) {
182192 validateFunction ( exclude , 'options.exclude' ) ;
183193 }
184194 this . #root = cwd ?? '.' ;
185195 this . #exclude = exclude ;
196+ this . #withFileTypes = ! ! withFileTypes ;
186197 let patterns ;
187198 if ( typeof pattern === 'object' ) {
188199 validateStringArray ( pattern , 'patterns' ) ;
@@ -222,7 +233,14 @@ class Glob {
222233 . forEach ( ( patterns , path ) => ArrayPrototypePush ( this . #queue, { __proto__ : null , path, patterns } ) ) ;
223234 this . #subpatterns. clear ( ) ;
224235 }
225- return ArrayFrom ( this . #results) ;
236+ return ArrayFrom (
237+ this . #results,
238+ this . #withFileTypes ? ( path ) => this . #cache. statSync (
239+ isAbsolute ( path ) ?
240+ path :
241+ join ( this . #root, path ) ,
242+ ) : undefined ,
243+ ) ;
226244 }
227245 #addSubpattern( path , pattern ) {
228246 if ( ! this . #subpatterns. has ( path ) ) {
@@ -317,7 +335,7 @@ class Glob {
317335 const fromSymlink = pattern . symlinks . has ( index ) ;
318336
319337 if ( current === lazyMinimatch ( ) . GLOBSTAR ) {
320- if ( entry . name [ 0 ] === '.' || ( this . #exclude && this . #exclude( entry . name ) ) ) {
338+ if ( entry . name [ 0 ] === '.' || ( this . #exclude && this . #exclude( this . #withFileTypes ? entry : entry . name ) ) ) {
321339 continue ;
322340 }
323341 if ( ! fromSymlink && entry . isDirectory ( ) ) {
@@ -460,7 +478,7 @@ class Glob {
460478 const result = join ( path , p ) ;
461479 if ( ! this . #results. has ( result ) ) {
462480 this . #results. add ( result ) ;
463- yield result ;
481+ yield this . #withFileTypes ? stat : result ;
464482 }
465483 }
466484 if ( pattern . indexes . size === 1 && pattern . indexes . has ( last ) ) {
@@ -472,7 +490,7 @@ class Glob {
472490 // if path is ".", add it only if pattern starts with "." or pattern is exactly "**"
473491 if ( ! this . #results. has ( path ) ) {
474492 this . #results. add ( path ) ;
475- yield path ;
493+ yield this . #withFileTypes ? stat : path ;
476494 }
477495 }
478496
@@ -522,7 +540,7 @@ class Glob {
522540 // If ** is last, add to results
523541 if ( ! this . #results. has ( entryPath ) ) {
524542 this . #results. add ( entryPath ) ;
525- yield entryPath ;
543+ yield this . #withFileTypes ? entry : entryPath ;
526544 }
527545 }
528546
@@ -533,7 +551,7 @@ class Glob {
533551 // If next pattern is the last one, add to results
534552 if ( ! this . #results. has ( entryPath ) ) {
535553 this . #results. add ( entryPath ) ;
536- yield entryPath ;
554+ yield this . #withFileTypes ? entry : entryPath ;
537555 }
538556 } else if ( nextMatches && entry . isDirectory ( ) ) {
539557 // Pattern mached, meaning two patterns forward
@@ -569,14 +587,14 @@ class Glob {
569587 this . #cache. add ( path , pattern . child ( new SafeSet ( ) . add ( nextIndex ) ) ) ;
570588 if ( ! this . #results. has ( path ) ) {
571589 this . #results. add ( path ) ;
572- yield path ;
590+ yield this . #withFileTypes ? this . #cache . statSync ( fullpath ) : path ;
573591 }
574592 }
575593 if ( ! this . #cache. seen ( path , pattern , nextIndex ) || ! this . #cache. seen ( parent , pattern , nextIndex ) ) {
576594 this . #cache. add ( parent , pattern . child ( new SafeSet ( ) . add ( nextIndex ) ) ) ;
577595 if ( ! this . #results. has ( parent ) ) {
578596 this . #results. add ( parent ) ;
579- yield parent ;
597+ yield this . #withFileTypes ? this . #cache . statSync ( join ( this . #root , parent ) ) : parent ;
580598 }
581599 }
582600 }
@@ -592,7 +610,7 @@ class Glob {
592610 if ( nextIndex === last ) {
593611 if ( ! this . #results. has ( entryPath ) ) {
594612 this . #results. add ( entryPath ) ;
595- yield entryPath ;
613+ yield this . #withFileTypes ? entry : entryPath ;
596614 }
597615 } else {
598616 subPatterns . add ( nextIndex + 1 ) ;
@@ -605,7 +623,7 @@ class Glob {
605623 if ( index === last ) {
606624 if ( ! this . #results. has ( entryPath ) ) {
607625 this . #results. add ( entryPath ) ;
608- yield entryPath ;
626+ yield this . #withFileTypes ? entry : entryPath ;
609627 }
610628 } else if ( entry . isDirectory ( ) ) {
611629 subPatterns . add ( nextIndex ) ;
0 commit comments