@@ -309,7 +309,7 @@ export class Volume implements FsCallbackApi, FsSynchronousApi {
309
309
this . props = Object . assign ( { Node, Link, File } , props ) ;
310
310
311
311
const root = this . createLink ( ) ;
312
- root . setNode ( this . createNode ( true ) ) ;
312
+ root . setNode ( this . createNode ( constants . S_IFDIR | 0o777 ) ) ;
313
313
314
314
const self = this ; // tslint:disable-line no-this-assignment
315
315
@@ -349,8 +349,8 @@ export class Volume implements FsCallbackApi, FsSynchronousApi {
349
349
}
350
350
351
351
createLink ( ) : Link ;
352
- createLink ( parent : Link , name : string , isDirectory ?: boolean , perm ?: number ) : Link ;
353
- createLink ( parent ?: Link , name ?: string , isDirectory : boolean = false , perm ?: number ) : Link {
352
+ createLink ( parent : Link , name : string , isDirectory ?: boolean , mode ?: number ) : Link ;
353
+ createLink ( parent ?: Link , name ?: string , isDirectory : boolean = false , mode ?: number ) : Link {
354
354
if ( ! parent ) {
355
355
return new this . props . Link ( this , null , '' ) ;
356
356
}
@@ -359,7 +359,14 @@ export class Volume implements FsCallbackApi, FsSynchronousApi {
359
359
throw new Error ( 'createLink: name cannot be empty' ) ;
360
360
}
361
361
362
- return parent . createChild ( name , this . createNode ( isDirectory , perm ) ) ;
362
+ // If no explicit permission is provided, use defaults based on type
363
+ const finalPerm = mode ?? ( isDirectory ? 0o777 : 0o666 ) ;
364
+ // To prevent making a breaking change, `mode` can also just be a permission number
365
+ // and the file type is set based on `isDirectory`
366
+ const hasFileType = mode && mode & constants . S_IFMT ;
367
+ const modeType = hasFileType ? mode & constants . S_IFMT : isDirectory ? constants . S_IFDIR : constants . S_IFREG ;
368
+ const finalMode = ( finalPerm & ~ constants . S_IFMT ) | modeType ;
369
+ return parent . createChild ( name , this . createNode ( finalMode ) ) ;
363
370
}
364
371
365
372
deleteLink ( link : Link ) : boolean {
@@ -387,10 +394,8 @@ export class Volume implements FsCallbackApi, FsSynchronousApi {
387
394
return typeof releasedFd === 'number' ? releasedFd : Volume . fd -- ;
388
395
}
389
396
390
- createNode ( isDirectory : boolean = false , perm ?: number ) : Node {
391
- perm ??= isDirectory ? 0o777 : 0o666 ;
392
- const node = new this . props . Node ( this . newInoNumber ( ) , perm ) ;
393
- if ( isDirectory ) node . setIsDirectory ( ) ;
397
+ createNode ( mode : number ) : Node {
398
+ const node = new this . props . Node ( this . newInoNumber ( ) , mode ) ;
394
399
this . inodes [ node . ino ] = node ;
395
400
return node ;
396
401
}
@@ -685,7 +690,7 @@ export class Volume implements FsCallbackApi, FsSynchronousApi {
685
690
this . openFiles = 0 ;
686
691
687
692
this . root = this . createLink ( ) ;
688
- this . root . setNode ( this . createNode ( true ) ) ;
693
+ this . root . setNode ( this . createNode ( constants . S_IFDIR | 0o777 ) ) ;
689
694
}
690
695
691
696
// Legacy interface
@@ -1798,7 +1803,7 @@ export class Volume implements FsCallbackApi, FsSynchronousApi {
1798
1803
const node = dir . getNode ( ) ;
1799
1804
if ( ! node . canWrite ( ) || ! node . canExecute ( ) ) throw createError ( EACCES , 'mkdir' , filename ) ;
1800
1805
1801
- dir . createChild ( name , this . createNode ( true , modeNum ) ) ;
1806
+ dir . createChild ( name , this . createNode ( constants . S_IFDIR | modeNum ) ) ;
1802
1807
}
1803
1808
1804
1809
/**
@@ -1836,7 +1841,7 @@ export class Volume implements FsCallbackApi, FsSynchronousApi {
1836
1841
}
1837
1842
1838
1843
created = true ;
1839
- curr = curr . createChild ( steps [ i ] , this . createNode ( true , modeNum ) ) ;
1844
+ curr = curr . createChild ( steps [ i ] , this . createNode ( constants . S_IFDIR | modeNum ) ) ;
1840
1845
}
1841
1846
return created ? filename : undefined ;
1842
1847
}
0 commit comments