@@ -10,6 +10,7 @@ const kReadFileMaxChunkSize = 2 ** 14;
1010const kWriteFileMaxChunkSize = 2 ** 14 ;
1111
1212const {
13+ ArrayIsArray,
1314 ArrayPrototypePush,
1415 Error,
1516 MathMax,
@@ -21,7 +22,9 @@ const {
2122 PromiseResolve,
2223 SafeArrayIterator,
2324 Symbol,
24- Uint8Array,
25+ SymbolAsyncIterator,
26+ SymbolIterator,
27+ Uint8Array
2528} = primordials ;
2629
2730const {
@@ -41,7 +44,7 @@ const {
4144 ERR_INVALID_ARG_VALUE ,
4245 ERR_METHOD_NOT_IMPLEMENTED ,
4346} = codes ;
44- const { isArrayBufferView } = require ( 'internal/util/types' ) ;
47+ const { isArrayBufferView, isTypedArray } = require ( 'internal/util/types' ) ;
4548const { rimrafPromises } = require ( 'internal/fs/rimraf' ) ;
4649const {
4750 copyObject,
@@ -663,19 +666,55 @@ async function writeFile(path, data, options) {
663666 options = getOptions ( options , { encoding : 'utf8' , mode : 0o666 , flag : 'w' } ) ;
664667 const flag = options . flag || 'w' ;
665668
666- if ( ! isArrayBufferView ( data ) ) {
667- validateStringAfterArrayBufferView ( data , 'data' ) ;
668- data = Buffer . from ( data , options . encoding || 'utf8' ) ;
669- }
669+ if ( isIterable ( data ) ) {
670+ if ( options . signal ?. aborted ) {
671+ throw lazyDOMException ( 'The operation was aborted' , 'AbortError' ) ;
672+ }
673+ const fd = await open ( path , flag , options . mode ) ;
674+ try {
675+ if ( options . signal ?. aborted ) {
676+ throw lazyDOMException ( 'The operation was aborted' , 'AbortError' ) ;
677+ }
678+ for await ( const buf of data ) {
679+ if ( options . signal ?. aborted ) {
680+ throw lazyDOMException ( 'The operation was aborted' , 'AbortError' ) ;
681+ }
682+ await fd . write ( buf ) ;
683+ if ( options . signal ?. aborted ) {
684+ throw lazyDOMException ( 'The operation was aborted' , 'AbortError' ) ;
685+ }
686+ }
687+ } finally {
688+ await fd . close ( ) ;
689+ }
690+ } else {
691+ if ( ! isArrayBufferView ( data ) ) {
692+ validateStringAfterArrayBufferView ( data , 'data' ) ;
693+ data = Buffer . from ( data , options . encoding || 'utf8' ) ;
694+ }
670695
671- if ( path instanceof FileHandle )
672- return writeFileHandle ( path , data , options . signal ) ;
696+ if ( path instanceof FileHandle ) {
697+ return writeFileHandle ( path , data , options . signal ) ;
698+ }
673699
674- const fd = await open ( path , flag , options . mode ) ;
675- if ( options . signal ?. aborted ) {
676- throw lazyDOMException ( 'The operation was aborted' , 'AbortError' ) ;
700+ const fd = await open ( path , flag , options . mode ) ;
701+ if ( options . signal ?. aborted ) {
702+ throw lazyDOMException ( 'The operation was aborted' , 'AbortError' ) ;
703+ }
704+ return PromisePrototypeFinally ( writeFileHandle ( fd , data ) , fd . close ) ;
677705 }
678- return PromisePrototypeFinally ( writeFileHandle ( fd , data ) , fd . close ) ;
706+ }
707+
708+ function isIterable ( obj ) {
709+ if ( obj == null ) {
710+ return false ;
711+ }
712+
713+ return SymbolAsyncIterator in obj || (
714+ SymbolIterator in obj &&
715+ typeof obj !== 'string' &&
716+ ! ArrayIsArray ( obj ) &&
717+ ! isTypedArray ( obj ) ) ;
679718}
680719
681720async function appendFile ( path , data , options ) {
0 commit comments