@@ -656,8 +656,8 @@ export class FileSystem {
656656 if ( isDirectory ( node ) ) throw createIOError ( "EISDIR" ) ;
657657 if ( ! isFile ( node ) ) throw createIOError ( "EBADF" ) ;
658658
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 ;
661661 }
662662
663663 /**
@@ -681,8 +681,11 @@ export class FileSystem {
681681
682682 if ( isDirectory ( node ) ) throw createIOError ( "EISDIR" ) ;
683683 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 ;
686689 node . mtimeMs = time ;
687690 node . ctimeMs = time ;
688691 }
@@ -700,6 +703,7 @@ export class FileSystem {
700703 return hasDifferences ? differences : undefined ;
701704 }
702705
706+ public static defaultEncoding : BufferEncoding | undefined = "utf8" ;
703707 /**
704708 * Generates a `FileSet` patch containing all the entries in `changed` that are not in `base`.
705709 */
@@ -800,24 +804,28 @@ export class FileSystem {
800804 baseNode . resolver === changedNode . resolver && baseNode . source === changedNode . source
801805 ) return false ;
802806
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 ) ;
805810
806811 // no difference if both buffers are the same reference
807812 if ( changedBuffer === baseBuffer ) {
808813 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 } ) ;
810815 return true ;
811816 }
812817
813818 // 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+ ) {
815823 if ( ! options . includeChangedFileWithSameContent ) return false ;
816- container [ basename ] = new SameFileContentFile ( changedBuffer ) ;
824+ container [ basename ] = new SameFileContentFile ( changedBuffer . data , { encoding : changedBuffer . encoding } ) ;
817825 return true ;
818826 }
819827
820- container [ basename ] = new File ( changedBuffer ) ;
828+ container [ basename ] = new File ( changedBuffer . data , { encoding : changedBuffer . encoding } ) ;
821829 return true ;
822830 }
823831
@@ -838,7 +846,8 @@ export class FileSystem {
838846 container [ basename ] = new Symlink ( node . symlink ) ;
839847 }
840848 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 } ) ;
842851 }
843852 return true ;
844853 }
@@ -984,14 +993,14 @@ export class FileSystem {
984993 }
985994
986995 private _getSize ( node : FileInode ) : number {
987- if ( node . buffer ) return node . buffer . byteLength ;
996+ if ( node . buffer ) return Buffer . byteLength ( node . buffer . data ) ;
988997 if ( node . size !== undefined ) return node . size ;
989998 if ( node . source && node . resolver ) return node . size = node . resolver . statSync ( node . source ) . size ;
990999 if ( this . _shadowRoot && node . shadowRoot ) return node . size = this . _shadowRoot . _getSize ( node . shadowRoot ) ;
9911000 return 0 ;
9921001 }
9931002
994- private _getBuffer ( node : FileInode ) : Buffer {
1003+ private _getBuffer ( node : FileInode , encoding : BufferEncoding | undefined ) : FileDataBuffer {
9951004 if ( ! node . buffer ) {
9961005 const { source, resolver } = node ;
9971006 if ( source && resolver ) {
@@ -1001,12 +1010,13 @@ export class FileSystem {
10011010 node . buffer = resolver . readFileSync ( source ) ;
10021011 }
10031012 else if ( this . _shadowRoot && node . shadowRoot ) {
1004- node . buffer = this . _shadowRoot . _getBuffer ( node . shadowRoot ) ;
1013+ node . buffer = this . _shadowRoot . _getBuffer ( node . shadowRoot , encoding ) ;
10051014 }
10061015 else {
1007- node . buffer = Buffer . allocUnsafe ( 0 ) ;
1016+ node . buffer = { encoding : undefined , data : Buffer . allocUnsafe ( 0 ) } ;
10081017 }
10091018 }
1019+ ensureBufferEncoding ( node . buffer , encoding ) ;
10101020 return node . buffer ;
10111021 }
10121022
@@ -1189,7 +1199,7 @@ export interface Traversal {
11891199export interface FileSystemResolver {
11901200 statSync ( path : string ) : { mode : number ; size : number ; } ;
11911201 readdirSync ( path : string ) : string [ ] ;
1192- readFileSync ( path : string ) : Buffer ;
1202+ readFileSync ( path : string ) : FileDataBuffer ;
11931203}
11941204
11951205export interface FileSystemResolverHost {
@@ -1219,8 +1229,8 @@ export function createResolver(host: FileSystemResolverHost): FileSystemResolver
12191229 throw new Error ( "ENOENT: path does not exist" ) ;
12201230 }
12211231 } ,
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 ) ! } ;
12241234 } ,
12251235 } ;
12261236}
@@ -1444,6 +1454,17 @@ export class Mount {
14441454// a generic POSIX inode
14451455type Inode = FileInode | DirectoryInode | SymlinkInode ;
14461456
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+
14471468interface FileInode {
14481469 dev : number ; // device id
14491470 ino : number ; // inode id
@@ -1454,7 +1475,7 @@ interface FileInode {
14541475 birthtimeMs : number ; // creation time
14551476 nlink : number ; // number of hard links
14561477 size ?: number ;
1457- buffer ?: Buffer ;
1478+ buffer ?: FileDataBuffer ;
14581479 source ?: string ;
14591480 resolver ?: FileSystemResolver ;
14601481 shadowRoot ?: FileInode ;
0 commit comments