@@ -44,6 +44,8 @@ const {
4444 StringPrototypeCharCodeAt,
4545 StringPrototypeIndexOf,
4646 StringPrototypeSlice,
47+ SymbolAsyncIterator,
48+ SymbolIterator,
4749} = primordials ;
4850
4951const { fs : constants } = internalBinding ( 'constants' ) ;
@@ -85,6 +87,7 @@ const {
8587const { FSReqCallback } = binding ;
8688const { toPathIfFileURL } = require ( 'internal/url' ) ;
8789const internalUtil = require ( 'internal/util' ) ;
90+ const { isCustomIterable } = require ( 'internal/streams/utils' ) ;
8891const {
8992 constants : {
9093 kIoMaxLength,
@@ -828,12 +831,12 @@ function write(fd, buffer, offset, length, position, callback) {
828831 } else {
829832 position = length ;
830833 }
831- length = 'utf8' ;
834+ length = length || 'utf8' ;
832835 }
833836
834837 const str = String ( buffer ) ;
835838 validateEncoding ( str , length ) ;
836- callback = maybeCallback ( position ) ;
839+ callback = maybeCallback ( callback || position ) ;
837840
838841 const req = new FSReqCallback ( ) ;
839842 req . oncomplete = wrapper ;
@@ -2039,7 +2042,8 @@ function lutimesSync(path, atime, mtime) {
20392042 handleErrorFromBinding ( ctx ) ;
20402043}
20412044
2042- function writeAll ( fd , isUserFd , buffer , offset , length , signal , callback ) {
2045+ function writeAll (
2046+ fd , isUserFd , buffer , offset , length , signal , encoding , callback ) {
20432047 if ( signal ?. aborted ) {
20442048 const abortError = new AbortError ( ) ;
20452049 if ( isUserFd ) {
@@ -2051,16 +2055,16 @@ function writeAll(fd, isUserFd, buffer, offset, length, signal, callback) {
20512055 }
20522056 return ;
20532057 }
2054- // write(fd, buffer, offset, length, position, callback)
2058+
2059+ if ( isCustomIterable ( buffer ) ) {
2060+ writeAllCustomIterable (
2061+ fd , isUserFd , buffer , offset , length , signal , encoding , callback )
2062+ . catch ( reason => { throw reason } ) ;
2063+ return ;
2064+ }
20552065 fs . write ( fd , buffer , offset , length , null , ( writeErr , written ) => {
20562066 if ( writeErr ) {
2057- if ( isUserFd ) {
2058- callback ( writeErr ) ;
2059- } else {
2060- fs . close ( fd , ( err ) => {
2061- callback ( aggregateTwoErrors ( err , writeErr ) ) ;
2062- } ) ;
2063- }
2067+ handleWriteAllErrorCallback ( fd , isUserFd , writeErr , callback ) ;
20642068 } else if ( written === length ) {
20652069 if ( isUserFd ) {
20662070 callback ( null ) ;
@@ -2070,11 +2074,43 @@ function writeAll(fd, isUserFd, buffer, offset, length, signal, callback) {
20702074 } else {
20712075 offset += written ;
20722076 length -= written ;
2073- writeAll ( fd , isUserFd , buffer , offset , length , signal , callback ) ;
2077+ writeAll (
2078+ fd , isUserFd , buffer , offset , length , signal , encoding , callback ) ;
20742079 }
20752080 } ) ;
20762081}
20772082
2083+ async function writeAllCustomIterable (
2084+ fd , isUserFd , buffer , offset , length , signal , encoding , callback ) {
2085+ const result = await buffer . next ( ) ;
2086+ if ( result . done ) {
2087+ fs . close ( fd , callback ) ;
2088+ return ;
2089+ }
2090+ const resultValue = result . value . toString ( ) ;
2091+ fs . write ( fd , resultValue , undefined ,
2092+ isArrayBufferView ( buffer ) ? resultValue . byteLength : encoding ,
2093+ null , ( writeErr , _ ) => {
2094+ if ( writeErr ) {
2095+ handleWriteAllErrorCallback ( fd , isUserFd , writeErr , callback ) ;
2096+ } else {
2097+ writeAll ( fd , isUserFd , buffer , offset ,
2098+ length , signal , encoding , callback ) ;
2099+ }
2100+ }
2101+ ) ;
2102+ }
2103+
2104+ function handleWriteAllErrorCallback ( fd , isUserFd , writeErr , callback ) {
2105+ if ( isUserFd ) {
2106+ callback ( writeErr ) ;
2107+ } else {
2108+ fs . close ( fd , ( err ) => {
2109+ callback ( aggregateTwoErrors ( err , writeErr ) ) ;
2110+ } ) ;
2111+ }
2112+ }
2113+
20782114/**
20792115 * Asynchronously writes data to the file.
20802116 * @param {string | Buffer | URL | number } path
@@ -2093,15 +2129,20 @@ function writeFile(path, data, options, callback) {
20932129 options = getOptions ( options , { encoding : 'utf8' , mode : 0o666 , flag : 'w' } ) ;
20942130 const flag = options . flag || 'w' ;
20952131
2096- if ( ! isArrayBufferView ( data ) ) {
2132+ if ( ! isArrayBufferView ( data ) && ! isCustomIterable ( data ) ) {
20972133 validateStringAfterArrayBufferView ( data , 'data' ) ;
20982134 data = Buffer . from ( String ( data ) , options . encoding || 'utf8' ) ;
20992135 }
21002136
2137+ if ( isCustomIterable ( data ) ) {
2138+ data = data [ SymbolIterator ] ?. ( ) ?? data [ SymbolAsyncIterator ] ?. ( ) ;
2139+ }
2140+
21012141 if ( isFd ( path ) ) {
21022142 const isUserFd = true ;
21032143 const signal = options . signal ;
2104- writeAll ( path , isUserFd , data , 0 , data . byteLength , signal , callback ) ;
2144+ writeAll ( path , isUserFd , data ,
2145+ 0 , data . byteLength , signal , options . encoding , callback ) ;
21052146 return ;
21062147 }
21072148
@@ -2114,7 +2155,8 @@ function writeFile(path, data, options, callback) {
21142155 } else {
21152156 const isUserFd = false ;
21162157 const signal = options . signal ;
2117- writeAll ( fd , isUserFd , data , 0 , data . byteLength , signal , callback ) ;
2158+ writeAll ( fd , isUserFd , data ,
2159+ 0 , data . byteLength , signal , options . encoding , callback ) ;
21182160 }
21192161 } ) ;
21202162}
0 commit comments