@@ -36,9 +36,24 @@ const isWindows = process.platform === 'win32';
3636const DEBUG = process . env . NODE_DEBUG && / f s / . test ( process . env . NODE_DEBUG ) ;
3737const errnoException = util . _errnoException ;
3838
39- function throwOptionsError ( options ) {
40- throw new TypeError ( 'Expected options to be either an object or a string, ' +
41- 'but got ' + typeof options + ' instead' ) ;
39+ function getOptions ( options , defaultOptions ) {
40+ if ( options === null || options === undefined ||
41+ typeof options === 'function' ) {
42+ return defaultOptions ;
43+ }
44+
45+ if ( typeof options === 'string' ) {
46+ defaultOptions = util . _extend ( { } , defaultOptions ) ;
47+ defaultOptions . encoding = options ;
48+ options = defaultOptions ;
49+ } else if ( typeof options !== 'object' ) {
50+ throw new TypeError ( '"options" must be a string or an object, got ' +
51+ typeof options + ' instead.' ) ;
52+ }
53+
54+ if ( options . encoding !== 'buffer' )
55+ assertEncoding ( options . encoding ) ;
56+ return options ;
4257}
4358
4459function rethrow ( ) {
@@ -228,26 +243,14 @@ fs.existsSync = function(path) {
228243 }
229244} ;
230245
231- fs . readFile = function ( path , options , callback_ ) {
232- var callback = maybeCallback ( arguments [ arguments . length - 1 ] ) ;
233-
234- if ( ! options || typeof options === 'function' ) {
235- options = { encoding : null , flag : 'r' } ;
236- } else if ( typeof options === 'string' ) {
237- options = { encoding : options , flag : 'r' } ;
238- } else if ( typeof options !== 'object' ) {
239- throwOptionsError ( options ) ;
240- }
241-
242- var encoding = options . encoding ;
243- assertEncoding ( encoding ) ;
244-
245- var flag = options . flag || 'r' ;
246+ fs . readFile = function ( path , options , callback ) {
247+ callback = maybeCallback ( arguments [ arguments . length - 1 ] ) ;
248+ options = getOptions ( options , { flag : 'r' } ) ;
246249
247250 if ( ! nullCheck ( path , callback ) )
248251 return ;
249252
250- var context = new ReadFileContext ( callback , encoding ) ;
253+ var context = new ReadFileContext ( callback , options . encoding ) ;
251254 context . isUserFd = isFd ( path ) ; // file descriptor ownership
252255 var req = new FSReqWrap ( ) ;
253256 req . context = context ;
@@ -261,7 +264,7 @@ fs.readFile = function(path, options, callback_) {
261264 }
262265
263266 binding . open ( pathModule . _makeLong ( path ) ,
264- stringToFlags ( flag ) ,
267+ stringToFlags ( options . flag || 'r' ) ,
265268 0o666 ,
266269 req ) ;
267270} ;
@@ -452,20 +455,9 @@ function tryReadSync(fd, isUserFd, buffer, pos, len) {
452455}
453456
454457fs . readFileSync = function ( path , options ) {
455- if ( ! options ) {
456- options = { encoding : null , flag : 'r' } ;
457- } else if ( typeof options === 'string' ) {
458- options = { encoding : options , flag : 'r' } ;
459- } else if ( typeof options !== 'object' ) {
460- throwOptionsError ( options ) ;
461- }
462-
463- var encoding = options . encoding ;
464- assertEncoding ( encoding ) ;
465-
466- var flag = options . flag || 'r' ;
458+ options = getOptions ( options , { flag : 'r' } ) ;
467459 var isUserFd = isFd ( path ) ; // file descriptor ownership
468- var fd = isUserFd ? path : fs . openSync ( path , flag , 0o666 ) ;
460+ var fd = isUserFd ? path : fs . openSync ( path , options . flag || 'r' , 0o666 ) ;
469461
470462 var st = tryStatSync ( fd , isUserFd ) ;
471463 var size = st . isFile ( ) ? st . size : 0 ;
@@ -509,7 +501,7 @@ fs.readFileSync = function(path, options) {
509501 buffer = buffer . slice ( 0 , pos ) ;
510502 }
511503
512- if ( encoding ) buffer = buffer . toString ( encoding ) ;
504+ if ( options . encoding ) buffer = buffer . toString ( options . encoding ) ;
513505 return buffer ;
514506} ;
515507
@@ -849,29 +841,16 @@ fs.mkdirSync = function(path, mode) {
849841} ;
850842
851843fs . readdir = function ( path , options , callback ) {
852- options = options || { } ;
853- if ( typeof options === 'function' ) {
854- callback = options ;
855- options = { } ;
856- } else if ( typeof options === 'string' ) {
857- options = { encoding : options } ;
858- }
859- if ( typeof options !== 'object' )
860- throw new TypeError ( '"options" must be a string or an object' ) ;
861-
862- callback = makeCallback ( callback ) ;
844+ callback = makeCallback ( typeof options === 'function' ? options : callback ) ;
845+ options = getOptions ( options , { } ) ;
863846 if ( ! nullCheck ( path , callback ) ) return ;
864847 var req = new FSReqWrap ( ) ;
865848 req . oncomplete = callback ;
866849 binding . readdir ( pathModule . _makeLong ( path ) , options . encoding , req ) ;
867850} ;
868851
869852fs . readdirSync = function ( path , options ) {
870- options = options || { } ;
871- if ( typeof options === 'string' )
872- options = { encoding : options } ;
873- if ( typeof options !== 'object' )
874- throw new TypeError ( '"options" must be a string or an object' ) ;
853+ options = getOptions ( options , { } ) ;
875854 nullCheck ( path ) ;
876855 return binding . readdir ( pathModule . _makeLong ( path ) , options . encoding ) ;
877856} ;
@@ -913,28 +892,16 @@ fs.statSync = function(path) {
913892} ;
914893
915894fs . readlink = function ( path , options , callback ) {
916- options = options || { } ;
917- if ( typeof options === 'function' ) {
918- callback = options ;
919- options = { } ;
920- } else if ( typeof options === 'string' ) {
921- options = { encoding : options } ;
922- }
923- if ( typeof options !== 'object' )
924- throw new TypeError ( '"options" must be a string or an object' ) ;
925- callback = makeCallback ( callback ) ;
895+ callback = makeCallback ( typeof options === 'function' ? options : callback ) ;
896+ options = getOptions ( options , { } ) ;
926897 if ( ! nullCheck ( path , callback ) ) return ;
927898 var req = new FSReqWrap ( ) ;
928899 req . oncomplete = callback ;
929900 binding . readlink ( pathModule . _makeLong ( path ) , options . encoding , req ) ;
930901} ;
931902
932903fs . readlinkSync = function ( path , options ) {
933- options = options || { } ;
934- if ( typeof options === 'string' )
935- options = { encoding : options } ;
936- if ( typeof options !== 'object' )
937- throw new TypeError ( '"options" must be a string or an object' ) ;
904+ options = getOptions ( options , { } ) ;
938905 nullCheck ( path ) ;
939906 return binding . readlink ( pathModule . _makeLong ( path ) , options . encoding ) ;
940907} ;
@@ -1205,20 +1172,10 @@ function writeAll(fd, isUserFd, buffer, offset, length, position, callback_) {
12051172 } ) ;
12061173}
12071174
1208- fs . writeFile = function ( path , data , options , callback_ ) {
1209- var callback = maybeCallback ( arguments [ arguments . length - 1 ] ) ;
1210-
1211- if ( ! options || typeof options === 'function' ) {
1212- options = { encoding : 'utf8' , mode : 0o666 , flag : 'w' } ;
1213- } else if ( typeof options === 'string' ) {
1214- options = { encoding : options , mode : 0o666 , flag : 'w' } ;
1215- } else if ( typeof options !== 'object' ) {
1216- throwOptionsError ( options ) ;
1217- }
1218-
1219- assertEncoding ( options . encoding ) ;
1220-
1221- var flag = options . flag || 'w' ;
1175+ fs . writeFile = function ( path , data , options , callback ) {
1176+ callback = maybeCallback ( arguments [ arguments . length - 1 ] ) ;
1177+ options = getOptions ( options , { encoding : 'utf8' , mode : 0o666 , flag : 'w' } ) ;
1178+ const flag = options . flag || 'w' ;
12221179
12231180 if ( isFd ( path ) ) {
12241181 writeFd ( path , true ) ;
@@ -1243,17 +1200,9 @@ fs.writeFile = function(path, data, options, callback_) {
12431200} ;
12441201
12451202fs . writeFileSync = function ( path , data , options ) {
1246- if ( ! options ) {
1247- options = { encoding : 'utf8' , mode : 0o666 , flag : 'w' } ;
1248- } else if ( typeof options === 'string' ) {
1249- options = { encoding : options , mode : 0o666 , flag : 'w' } ;
1250- } else if ( typeof options !== 'object' ) {
1251- throwOptionsError ( options ) ;
1252- }
1253-
1254- assertEncoding ( options . encoding ) ;
1203+ options = getOptions ( options , { encoding : 'utf8' , mode : 0o666 , flag : 'w' } ) ;
1204+ const flag = options . flag || 'w' ;
12551205
1256- var flag = options . flag || 'w' ;
12571206 var isUserFd = isFd ( path ) ; // file descriptor ownership
12581207 var fd = isUserFd ? path : fs . openSync ( path , flag , options . mode ) ;
12591208
@@ -1277,16 +1226,9 @@ fs.writeFileSync = function(path, data, options) {
12771226 }
12781227} ;
12791228
1280- fs . appendFile = function ( path , data , options , callback_ ) {
1281- var callback = maybeCallback ( arguments [ arguments . length - 1 ] ) ;
1282-
1283- if ( ! options || typeof options === 'function' ) {
1284- options = { encoding : 'utf8' , mode : 0o666 , flag : 'a' } ;
1285- } else if ( typeof options === 'string' ) {
1286- options = { encoding : options , mode : 0o666 , flag : 'a' } ;
1287- } else if ( typeof options !== 'object' ) {
1288- throwOptionsError ( options ) ;
1289- }
1229+ fs . appendFile = function ( path , data , options , callback ) {
1230+ callback = maybeCallback ( arguments [ arguments . length - 1 ] ) ;
1231+ options = getOptions ( options , { encoding : 'utf8' , mode : 0o666 , flag : 'a' } ) ;
12901232
12911233 if ( ! options . flag )
12921234 options = util . _extend ( { flag : 'a' } , options ) ;
@@ -1299,13 +1241,7 @@ fs.appendFile = function(path, data, options, callback_) {
12991241} ;
13001242
13011243fs . appendFileSync = function ( path , data , options ) {
1302- if ( ! options ) {
1303- options = { encoding : 'utf8' , mode : 0o666 , flag : 'a' } ;
1304- } else if ( typeof options === 'string' ) {
1305- options = { encoding : options , mode : 0o666 , flag : 'a' } ;
1306- } else if ( typeof options !== 'object' ) {
1307- throwOptionsError ( options ) ;
1308- }
1244+ options = getOptions ( options , { encoding : 'utf8' , mode : 0o666 , flag : 'a' } ) ;
13091245
13101246 if ( ! options . flag )
13111247 options = util . _extend ( { flag : 'a' } , options ) ;
@@ -1364,15 +1300,10 @@ FSWatcher.prototype.close = function() {
13641300fs . watch = function ( filename , options , listener ) {
13651301 nullCheck ( filename ) ;
13661302
1367- options = options || { } ;
13681303 if ( typeof options === 'function' ) {
13691304 listener = options ;
1370- options = { } ;
1371- } else if ( typeof options === 'string' ) {
1372- options = { encoding : options } ;
13731305 }
1374- if ( typeof options !== 'object' )
1375- throw new TypeError ( '"options" must be a string or an object' ) ;
1306+ options = getOptions ( options , { } ) ;
13761307
13771308 if ( options . persistent === undefined ) options . persistent = true ;
13781309 if ( options . recursive === undefined ) options . recursive = false ;
@@ -1519,12 +1450,7 @@ function encodeRealpathResult(result, options, err) {
15191450const realpathCacheKey = fs . realpathCacheKey = Symbol ( 'realpathCacheKey' ) ;
15201451
15211452fs . realpathSync = function realpathSync ( p , options ) {
1522- if ( ! options )
1523- options = { } ;
1524- else if ( typeof options === 'string' )
1525- options = { encoding : options } ;
1526- else if ( typeof options !== 'object' )
1527- throw new TypeError ( '"options" must be a string or an object' ) ;
1453+ options = getOptions ( options , { } ) ;
15281454 nullCheck ( p ) ;
15291455
15301456 p = p . toString ( 'utf8' ) ;
@@ -1625,20 +1551,8 @@ fs.realpathSync = function realpathSync(p, options) {
16251551
16261552
16271553fs . realpath = function realpath ( p , options , callback ) {
1628- if ( typeof callback !== 'function' ) {
1629- callback = maybeCallback ( options ) ;
1630- options = { } ;
1631- }
1632-
1633- if ( ! options ) {
1634- options = { } ;
1635- } else if ( typeof options === 'function' ) {
1636- options = { } ;
1637- } else if ( typeof options === 'string' ) {
1638- options = { encoding : options } ;
1639- } else if ( typeof options !== 'object' ) {
1640- throw new TypeError ( '"options" must be a string or an object' ) ;
1641- }
1554+ callback = maybeCallback ( typeof options === 'function' ? options : callback ) ;
1555+ options = getOptions ( options , { } ) ;
16421556 if ( ! nullCheck ( p , callback ) )
16431557 return ;
16441558
@@ -1747,20 +1661,10 @@ fs.realpath = function realpath(p, options, callback) {
17471661} ;
17481662
17491663fs . mkdtemp = function ( prefix , options , callback ) {
1664+ callback = makeCallback ( typeof options === 'function' ? options : callback ) ;
1665+ options = getOptions ( options , { } ) ;
17501666 if ( ! prefix || typeof prefix !== 'string' )
17511667 throw new TypeError ( 'filename prefix is required' ) ;
1752-
1753- options = options || { } ;
1754- if ( typeof options === 'function' ) {
1755- callback = options ;
1756- options = { } ;
1757- } else if ( typeof options === 'string' ) {
1758- options = { encoding : options } ;
1759- }
1760- if ( typeof options !== 'object' )
1761- throw new TypeError ( '"options" must be a string or an object' ) ;
1762-
1763- callback = makeCallback ( callback ) ;
17641668 if ( ! nullCheck ( prefix , callback ) ) {
17651669 return ;
17661670 }
@@ -1775,14 +1679,8 @@ fs.mkdtemp = function(prefix, options, callback) {
17751679fs . mkdtempSync = function ( prefix , options ) {
17761680 if ( ! prefix || typeof prefix !== 'string' )
17771681 throw new TypeError ( 'filename prefix is required' ) ;
1778-
1779- options = options || { } ;
1780- if ( typeof options === 'string' )
1781- options = { encoding : options } ;
1782- if ( typeof options !== 'object' )
1783- throw new TypeError ( '"options" must be a string or an object' ) ;
1682+ options = getOptions ( options , { } ) ;
17841683 nullCheck ( prefix ) ;
1785-
17861684 return binding . mkdtemp ( prefix + 'XXXXXX' , options . encoding ) ;
17871685} ;
17881686
@@ -1806,15 +1704,8 @@ function ReadStream(path, options) {
18061704 if ( ! ( this instanceof ReadStream ) )
18071705 return new ReadStream ( path , options ) ;
18081706
1809- if ( options === undefined )
1810- options = { } ;
1811- else if ( typeof options === 'string' )
1812- options = { encoding : options } ;
1813- else if ( options === null || typeof options !== 'object' )
1814- throw new TypeError ( '"options" argument must be a string or an object' ) ;
1815-
18161707 // a little bit bigger buffer and water marks by default
1817- options = Object . create ( options ) ;
1708+ options = Object . create ( getOptions ( options , { } ) ) ;
18181709 if ( options . highWaterMark === undefined )
18191710 options . highWaterMark = 64 * 1024 ;
18201711
@@ -1980,14 +1871,7 @@ function WriteStream(path, options) {
19801871 if ( ! ( this instanceof WriteStream ) )
19811872 return new WriteStream ( path , options ) ;
19821873
1983- if ( options === undefined )
1984- options = { } ;
1985- else if ( typeof options === 'string' )
1986- options = { encoding : options } ;
1987- else if ( options === null || typeof options !== 'object' )
1988- throw new TypeError ( '"options" argument must be a string or an object' ) ;
1989-
1990- options = Object . create ( options ) ;
1874+ options = Object . create ( getOptions ( options , { } ) ) ;
19911875
19921876 Writable . call ( this , options ) ;
19931877
0 commit comments