@@ -1111,12 +1111,10 @@ REPLServer.prototype.complete = function() {
11111111 this . completer . apply ( this , arguments ) ;
11121112} ;
11131113
1114- function gracefulOperation ( fn , args , alternative ) {
1114+ function gracefulReaddir ( ... args ) {
11151115 try {
1116- return fn ( ...args ) ;
1117- } catch {
1118- return alternative ;
1119- }
1116+ return fs . readdirSync ( ...args ) ;
1117+ } catch { }
11201118}
11211119
11221120// Provide a list of completions for the given leading text. This is
@@ -1145,8 +1143,6 @@ function complete(line, callback) {
11451143 if ( completeOn . length ) {
11461144 filter = completeOn ;
11471145 }
1148-
1149- completionGroupsLoaded ( ) ;
11501146 } else if ( requireRE . test ( line ) ) {
11511147 // require('...<Tab>')
11521148 const extensions = ObjectKeys ( this . context . require . extensions ) ;
@@ -1173,11 +1169,7 @@ function complete(line, callback) {
11731169
11741170 for ( let dir of paths ) {
11751171 dir = path . resolve ( dir , subdir ) ;
1176- const dirents = gracefulOperation (
1177- fs . readdirSync ,
1178- [ dir , { withFileTypes : true } ] ,
1179- [ ]
1180- ) ;
1172+ const dirents = gracefulReaddir ( dir , { withFileTypes : true } ) || [ ] ;
11811173 for ( const dirent of dirents ) {
11821174 if ( versionedFileNamesRe . test ( dirent . name ) || dirent . name === '.npm' ) {
11831175 // Exclude versioned names that 'npm' installs.
@@ -1193,7 +1185,7 @@ function complete(line, callback) {
11931185 }
11941186 group . push ( `${ subdir } ${ dirent . name } /` ) ;
11951187 const absolute = path . resolve ( dir , dirent . name ) ;
1196- const subfiles = gracefulOperation ( fs . readdirSync , [ absolute ] , [ ] ) ;
1188+ const subfiles = gracefulReaddir ( absolute ) || [ ] ;
11971189 for ( const subfile of subfiles ) {
11981190 if ( indexes . includes ( subfile ) ) {
11991191 group . push ( `${ subdir } ${ dirent . name } ` ) ;
@@ -1209,31 +1201,22 @@ function complete(line, callback) {
12091201 if ( ! subdir ) {
12101202 completionGroups . push ( _builtinLibs ) ;
12111203 }
1212-
1213- completionGroupsLoaded ( ) ;
12141204 } else if ( fsAutoCompleteRE . test ( line ) ) {
1215- filter = '' ;
1205+ let baseName = '' ;
12161206 let filePath = line . match ( fsAutoCompleteRE ) [ 1 ] ;
1217- let fileList ;
1207+ let fileList = gracefulReaddir ( filePath , { withFileTypes : true } ) ;
12181208
1219- try {
1220- fileList = fs . readdirSync ( filePath , { withFileTypes : true } ) ;
1221- completionGroups . push ( fileList . map ( ( dirent ) => dirent . name ) ) ;
1222- completeOn = '' ;
1223- } catch {
1224- try {
1225- const baseName = path . basename ( filePath ) ;
1226- filePath = path . dirname ( filePath ) ;
1227- fileList = fs . readdirSync ( filePath , { withFileTypes : true } ) ;
1228- const filteredValue = fileList . filter ( ( d ) =>
1229- d . name . startsWith ( baseName ) )
1230- . map ( ( d ) => d . name ) ;
1231- completionGroups . push ( filteredValue ) ;
1232- completeOn = baseName ;
1233- } catch { }
1209+ if ( ! fileList ) {
1210+ baseName = path . basename ( filePath ) ;
1211+ filePath = path . dirname ( filePath ) ;
1212+ fileList = gracefulReaddir ( filePath , { withFileTypes : true } ) || [ ] ;
12341213 }
12351214
1236- completionGroupsLoaded ( ) ;
1215+ const filteredValue = fileList
1216+ . filter ( ( dirent ) => dirent . name . startsWith ( baseName ) )
1217+ . map ( ( d ) => d . name ) ;
1218+ completionGroups . push ( filteredValue ) ;
1219+ completeOn = baseName ;
12371220 // Handle variable member lookup.
12381221 // We support simple chained expressions like the following (no function
12391222 // calls, etc.). That is for simplicity and also because we *eval* that
@@ -1291,32 +1274,26 @@ function complete(line, callback) {
12911274
12921275 const evalExpr = `try { ${ expr } } catch {}` ;
12931276 this . eval ( evalExpr , this . context , 'repl' , ( e , obj ) => {
1294- if ( obj != null ) {
1295- if ( typeof obj === 'object' || typeof obj === 'function' ) {
1296- try {
1297- memberGroups . push ( filteredOwnPropertyNames ( obj ) ) ;
1298- } catch {
1299- // Probably a Proxy object without `getOwnPropertyNames` trap.
1300- // We simply ignore it here, as we don't want to break the
1301- // autocompletion. Fixes the bug
1302- // https://github.com/nodejs/node/issues/2119
1303- }
1277+ try {
1278+ let p ;
1279+ if ( ( typeof obj === 'object' && obj !== null ) ||
1280+ typeof obj === 'function' ) {
1281+ memberGroups . push ( filteredOwnPropertyNames ( obj ) ) ;
1282+ p = ObjectGetPrototypeOf ( obj ) ;
1283+ } else {
1284+ p = obj . constructor ? obj . constructor . prototype : null ;
13041285 }
1305- // Works for non-objects
1306- try {
1307- let p ;
1308- if ( typeof obj === 'object' || typeof obj === 'function' ) {
1309- p = ObjectGetPrototypeOf ( obj ) ;
1310- } else {
1311- p = obj . constructor ? obj . constructor . prototype : null ;
1312- }
1313- // Circular refs possible? Let's guard against that.
1314- let sentinel = 5 ;
1315- while ( p !== null && sentinel -- !== 0 ) {
1316- memberGroups . push ( filteredOwnPropertyNames ( p ) ) ;
1317- p = ObjectGetPrototypeOf ( p ) ;
1318- }
1319- } catch { }
1286+ // Circular refs possible? Let's guard against that.
1287+ let sentinel = 5 ;
1288+ while ( p !== null && sentinel -- !== 0 ) {
1289+ memberGroups . push ( filteredOwnPropertyNames ( p ) ) ;
1290+ p = ObjectGetPrototypeOf ( p ) ;
1291+ }
1292+ } catch {
1293+ // Maybe a Proxy object without `getOwnPropertyNames` trap.
1294+ // We simply ignore it here, as we don't want to break the
1295+ // autocompletion. Fixes the bug
1296+ // https://github.com/nodejs/node/issues/2119
13201297 }
13211298
13221299 if ( memberGroups . length ) {
@@ -1331,21 +1308,21 @@ function complete(line, callback) {
13311308
13321309 completionGroupsLoaded ( ) ;
13331310 } ) ;
1334- } else {
1335- completionGroupsLoaded ( ) ;
1311+ return ;
13361312 }
13371313
1314+ return completionGroupsLoaded ( ) ;
1315+
13381316 // Will be called when all completionGroups are in place
13391317 // Useful for async autocompletion
13401318 function completionGroupsLoaded ( ) {
13411319 // Filter, sort (within each group), uniq and merge the completion groups.
13421320 if ( completionGroups . length && filter ) {
13431321 const newCompletionGroups = [ ] ;
1344- for ( let i = 0 ; i < completionGroups . length ; i ++ ) {
1345- group = completionGroups [ i ]
1346- . filter ( ( elem ) => elem . indexOf ( filter ) === 0 ) ;
1347- if ( group . length ) {
1348- newCompletionGroups . push ( group ) ;
1322+ for ( const group of completionGroups ) {
1323+ const filteredGroup = group . filter ( ( e ) => e . indexOf ( filter ) === 0 ) ;
1324+ if ( filteredGroup . length ) {
1325+ newCompletionGroups . push ( filteredGroup ) ;
13491326 }
13501327 }
13511328 completionGroups = newCompletionGroups ;
0 commit comments