@@ -656,8 +656,8 @@ export class FileSystem {
656
656
if ( isDirectory ( node ) ) throw createIOError ( "EISDIR" ) ;
657
657
if ( ! isFile ( node ) ) throw createIOError ( "EBADF" ) ;
658
658
659
- const buffer = this . _getBuffer ( node ) . slice ( ) ;
660
- return encoding ? buffer . toString ( encoding ) : buffer ;
659
+ const fileBuffer = this . _getBuffer ( node , encoding ?? undefined ) ;
660
+ return ! fileBuffer . encoding ? fileBuffer . data . slice ( ) : fileBuffer . data ;
661
661
}
662
662
663
663
/**
@@ -681,8 +681,11 @@ export class FileSystem {
681
681
682
682
if ( isDirectory ( node ) ) throw createIOError ( "EISDIR" ) ;
683
683
if ( ! isFile ( node ) ) throw createIOError ( "EBADF" ) ;
684
- node . buffer = Buffer . isBuffer ( data ) ? data . slice ( ) : ts . sys . bufferFrom ! ( "" + data , encoding || "utf8" ) as Buffer ;
685
- node . size = node . buffer . byteLength ;
684
+ node . buffer = Buffer . isBuffer ( data ) ?
685
+ { encoding : undefined , data : data . slice ( ) } :
686
+ { encoding : ( encoding ?? "utf8" ) as BufferEncoding , data } ;
687
+ // Updated the size if it's easy to get, otherwise set to undefined. _getSize will compute the correct size
688
+ node . size = ! node . buffer . encoding ? node . buffer . data . byteLength : undefined ;
686
689
node . mtimeMs = time ;
687
690
node . ctimeMs = time ;
688
691
}
@@ -700,6 +703,7 @@ export class FileSystem {
700
703
return hasDifferences ? differences : undefined ;
701
704
}
702
705
706
+ public static defaultEncoding : BufferEncoding | undefined = "utf8" ;
703
707
/**
704
708
* Generates a `FileSet` patch containing all the entries in `changed` that are not in `base`.
705
709
*/
@@ -800,24 +804,28 @@ export class FileSystem {
800
804
baseNode . resolver === changedNode . resolver && baseNode . source === changedNode . source
801
805
) return false ;
802
806
803
- const changedBuffer = changed . _getBuffer ( changedNode ) ;
804
- const baseBuffer = base . _getBuffer ( baseNode ) ;
807
+ const encoding = changedNode . buffer ?. encoding ?? baseNode . buffer ?. encoding ?? FileSystem . defaultEncoding ;
808
+ const changedBuffer = changed . _getBuffer ( changedNode , encoding ) ;
809
+ const baseBuffer = base . _getBuffer ( baseNode , encoding ) ;
805
810
806
811
// no difference if both buffers are the same reference
807
812
if ( changedBuffer === baseBuffer ) {
808
813
if ( ! options . includeChangedFileWithSameContent || changedNode . mtimeMs === baseNode . mtimeMs ) return false ;
809
- container [ basename ] = new SameFileWithModifiedTime ( changedBuffer ) ;
814
+ container [ basename ] = new SameFileWithModifiedTime ( changedBuffer . data , { encoding : changedBuffer . encoding } ) ;
810
815
return true ;
811
816
}
812
817
813
818
// no difference if both buffers are identical
814
- if ( Buffer . compare ( changedBuffer , baseBuffer ) === 0 ) {
819
+ if (
820
+ ! changedBuffer . encoding && ! baseBuffer . encoding && Buffer . compare ( changedBuffer . data , baseBuffer . data ) === 0 // same buffer content
821
+ || changedBuffer . encoding === baseBuffer . encoding && changedBuffer . data === baseBuffer . data // same string content
822
+ ) {
815
823
if ( ! options . includeChangedFileWithSameContent ) return false ;
816
- container [ basename ] = new SameFileContentFile ( changedBuffer ) ;
824
+ container [ basename ] = new SameFileContentFile ( changedBuffer . data , { encoding : changedBuffer . encoding } ) ;
817
825
return true ;
818
826
}
819
827
820
- container [ basename ] = new File ( changedBuffer ) ;
828
+ container [ basename ] = new File ( changedBuffer . data , { encoding : changedBuffer . encoding } ) ;
821
829
return true ;
822
830
}
823
831
@@ -838,7 +846,8 @@ export class FileSystem {
838
846
container [ basename ] = new Symlink ( node . symlink ) ;
839
847
}
840
848
else {
841
- container [ basename ] = new File ( changed . _getBuffer ( node ) ) ;
849
+ const buffer = changed . _getBuffer ( node , FileSystem . defaultEncoding ) ;
850
+ container [ basename ] = new File ( buffer . data , { encoding : buffer . encoding ?? undefined } ) ;
842
851
}
843
852
return true ;
844
853
}
@@ -984,14 +993,14 @@ export class FileSystem {
984
993
}
985
994
986
995
private _getSize ( node : FileInode ) : number {
987
- if ( node . buffer ) return node . buffer . byteLength ;
996
+ if ( node . buffer ) return Buffer . byteLength ( node . buffer . data ) ;
988
997
if ( node . size !== undefined ) return node . size ;
989
998
if ( node . source && node . resolver ) return node . size = node . resolver . statSync ( node . source ) . size ;
990
999
if ( this . _shadowRoot && node . shadowRoot ) return node . size = this . _shadowRoot . _getSize ( node . shadowRoot ) ;
991
1000
return 0 ;
992
1001
}
993
1002
994
- private _getBuffer ( node : FileInode ) : Buffer {
1003
+ private _getBuffer ( node : FileInode , encoding : BufferEncoding | undefined ) : FileDataBuffer {
995
1004
if ( ! node . buffer ) {
996
1005
const { source, resolver } = node ;
997
1006
if ( source && resolver ) {
@@ -1001,12 +1010,13 @@ export class FileSystem {
1001
1010
node . buffer = resolver . readFileSync ( source ) ;
1002
1011
}
1003
1012
else if ( this . _shadowRoot && node . shadowRoot ) {
1004
- node . buffer = this . _shadowRoot . _getBuffer ( node . shadowRoot ) ;
1013
+ node . buffer = this . _shadowRoot . _getBuffer ( node . shadowRoot , encoding ) ;
1005
1014
}
1006
1015
else {
1007
- node . buffer = Buffer . allocUnsafe ( 0 ) ;
1016
+ node . buffer = { encoding : undefined , data : Buffer . allocUnsafe ( 0 ) } ;
1008
1017
}
1009
1018
}
1019
+ ensureBufferEncoding ( node . buffer , encoding ) ;
1010
1020
return node . buffer ;
1011
1021
}
1012
1022
@@ -1189,7 +1199,7 @@ export interface Traversal {
1189
1199
export interface FileSystemResolver {
1190
1200
statSync ( path : string ) : { mode : number ; size : number ; } ;
1191
1201
readdirSync ( path : string ) : string [ ] ;
1192
- readFileSync ( path : string ) : Buffer ;
1202
+ readFileSync ( path : string ) : FileDataBuffer ;
1193
1203
}
1194
1204
1195
1205
export interface FileSystemResolverHost {
@@ -1219,8 +1229,8 @@ export function createResolver(host: FileSystemResolverHost): FileSystemResolver
1219
1229
throw new Error ( "ENOENT: path does not exist" ) ;
1220
1230
}
1221
1231
} ,
1222
- readFileSync ( path : string ) : Buffer {
1223
- return ts . sys . bufferFrom ! ( host . readFile ( path ) ! , "utf8" ) as Buffer ; // TODO: GH#18217
1232
+ readFileSync ( path : string ) : FileDataBuffer {
1233
+ return { encoding : "utf8" , data : host . readFile ( path ) ! } ;
1224
1234
} ,
1225
1235
} ;
1226
1236
}
@@ -1444,6 +1454,17 @@ export class Mount {
1444
1454
// a generic POSIX inode
1445
1455
type Inode = FileInode | DirectoryInode | SymlinkInode ;
1446
1456
1457
+ type FileDataBuffer = { encoding ?: undefined ; data : Buffer ; } | { encoding : BufferEncoding ; data : string ; } ;
1458
+
1459
+ function ensureBufferEncoding ( fileBuffer : FileDataBuffer , encoding : BufferEncoding | undefined ) {
1460
+ if ( fileBuffer . encoding === encoding ) return ;
1461
+
1462
+ const buffer = ! fileBuffer . encoding ? fileBuffer . data : ts . sys . bufferFrom ! ( fileBuffer . data , fileBuffer . encoding ) ;
1463
+
1464
+ fileBuffer . encoding = encoding ;
1465
+ fileBuffer . data = ! encoding ? buffer as Buffer : buffer . toString ( encoding ) ;
1466
+ }
1467
+
1447
1468
interface FileInode {
1448
1469
dev : number ; // device id
1449
1470
ino : number ; // inode id
@@ -1454,7 +1475,7 @@ interface FileInode {
1454
1475
birthtimeMs : number ; // creation time
1455
1476
nlink : number ; // number of hard links
1456
1477
size ?: number ;
1457
- buffer ?: Buffer ;
1478
+ buffer ?: FileDataBuffer ;
1458
1479
source ?: string ;
1459
1480
resolver ?: FileSystemResolver ;
1460
1481
shadowRoot ?: FileInode ;
0 commit comments