Skip to content

Commit 2620358

Browse files
committed
fs: move utility functions to internal/fs
PR-URL: #18777 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
1 parent 6c9774f commit 2620358

File tree

2 files changed

+340
-294
lines changed

2 files changed

+340
-294
lines changed

lib/fs.js

Lines changed: 18 additions & 291 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,29 @@ const { Buffer } = require('buffer');
3737
const errors = require('internal/errors');
3838
const { Readable, Writable } = require('stream');
3939
const EventEmitter = require('events');
40-
const { FSReqWrap } = binding;
40+
const { FSReqWrap, statValues } = binding;
4141
const { FSEvent } = process.binding('fs_event_wrap');
4242
const internalFS = require('internal/fs');
4343
const { getPathFromURL } = require('internal/url');
4444
const internalUtil = require('internal/util');
4545
const {
46-
assertEncoding,
47-
stringToFlags
46+
copyObject,
47+
getOptions,
48+
isUint32,
49+
modeNum,
50+
nullCheck,
51+
preprocessSymlinkDestination,
52+
Stats,
53+
statsFromValues,
54+
stringToFlags,
55+
stringToSymlinkType,
56+
toUnixTimestamp,
57+
validateBuffer,
58+
validateLen,
59+
validateOffsetLengthRead,
60+
validateOffsetLengthWrite,
61+
validatePath,
62+
validateUint32
4863
} = internalFS;
4964
const {
5065
CHAR_FORWARD_SLASH,
@@ -70,9 +85,6 @@ const errnoException = errors.errnoException;
7085

7186
let truncateWarn = true;
7287

73-
function isInt32(n) { return n === (n | 0); }
74-
function isUint32(n) { return n === (n >>> 0); }
75-
7688
function showTruncateDeprecation() {
7789
if (truncateWarn) {
7890
process.emitWarning(
@@ -83,35 +95,6 @@ function showTruncateDeprecation() {
8395
}
8496
}
8597

86-
function getOptions(options, defaultOptions) {
87-
if (options === null || options === undefined ||
88-
typeof options === 'function') {
89-
return defaultOptions;
90-
}
91-
92-
if (typeof options === 'string') {
93-
defaultOptions = util._extend({}, defaultOptions);
94-
defaultOptions.encoding = options;
95-
options = defaultOptions;
96-
} else if (typeof options !== 'object') {
97-
throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
98-
'options',
99-
['string', 'Object'],
100-
options);
101-
}
102-
103-
if (options.encoding !== 'buffer')
104-
assertEncoding(options.encoding);
105-
return options;
106-
}
107-
108-
function copyObject(source) {
109-
var target = {};
110-
for (var key in source)
111-
target[key] = source[key];
112-
return target;
113-
}
114-
11598
function handleErrorFromBinding(ctx) {
11699
if (ctx.errno !== undefined) { // libuv error numbers
117100
const err = errors.uvException(ctx);
@@ -175,117 +158,6 @@ function makeCallback(cb) {
175158
};
176159
}
177160

178-
function validateBuffer(buffer) {
179-
if (!isUint8Array(buffer)) {
180-
const err = new errors.TypeError('ERR_INVALID_ARG_TYPE', 'buffer',
181-
['Buffer', 'Uint8Array']);
182-
Error.captureStackTrace(err, validateBuffer);
183-
throw err;
184-
}
185-
}
186-
187-
function validateLen(len) {
188-
let err;
189-
190-
if (!isInt32(len))
191-
err = new errors.TypeError('ERR_INVALID_ARG_TYPE', 'len', 'integer');
192-
193-
if (err !== undefined) {
194-
Error.captureStackTrace(err, validateLen);
195-
throw err;
196-
}
197-
}
198-
199-
function validateOffsetLengthRead(offset, length, bufferLength) {
200-
let err;
201-
202-
if (offset < 0 || offset >= bufferLength) {
203-
err = new errors.RangeError('ERR_OUT_OF_RANGE', 'offset');
204-
} else if (length < 0 || offset + length > bufferLength) {
205-
err = new errors.RangeError('ERR_OUT_OF_RANGE', 'length');
206-
}
207-
208-
if (err !== undefined) {
209-
Error.captureStackTrace(err, validateOffsetLengthRead);
210-
throw err;
211-
}
212-
}
213-
214-
function validateOffsetLengthWrite(offset, length, byteLength) {
215-
let err;
216-
217-
if (offset > byteLength) {
218-
err = new errors.RangeError('ERR_OUT_OF_RANGE', 'offset');
219-
} else if (offset + length > byteLength || offset + length > kMaxLength) {
220-
err = new errors.RangeError('ERR_OUT_OF_RANGE', 'length');
221-
}
222-
223-
if (err !== undefined) {
224-
Error.captureStackTrace(err, validateOffsetLengthWrite);
225-
throw err;
226-
}
227-
}
228-
229-
// Check if the path contains null types if it is a string nor Uint8Array,
230-
// otherwise return silently.
231-
function nullCheck(path, propName, throwError = true) {
232-
const pathIsString = typeof path === 'string';
233-
const pathIsUint8Array = isUint8Array(path);
234-
235-
// We can only perform meaningful checks on strings and Uint8Arrays.
236-
if (!pathIsString && !pathIsUint8Array) {
237-
return;
238-
}
239-
240-
if (pathIsString && path.indexOf('\u0000') === -1) {
241-
return;
242-
} else if (pathIsUint8Array && path.indexOf(0) === -1) {
243-
return;
244-
}
245-
246-
const err = new errors.Error(
247-
'ERR_INVALID_ARG_VALUE', propName, path,
248-
'must be a string or Uint8Array without null bytes');
249-
250-
if (throwError) {
251-
Error.captureStackTrace(err, nullCheck);
252-
throw err;
253-
}
254-
return err;
255-
}
256-
257-
function validatePath(path, propName) {
258-
let err;
259-
260-
if (propName === undefined) {
261-
propName = 'path';
262-
}
263-
264-
if (typeof path !== 'string' && !isUint8Array(path)) {
265-
err = new errors.TypeError('ERR_INVALID_ARG_TYPE', propName,
266-
['string', 'Buffer', 'URL']);
267-
} else {
268-
err = nullCheck(path, propName, false);
269-
}
270-
271-
if (err !== undefined) {
272-
Error.captureStackTrace(err, validatePath);
273-
throw err;
274-
}
275-
}
276-
277-
function validateUint32(value, propName) {
278-
let err;
279-
280-
if (!isUint32(value))
281-
err = new errors.TypeError('ERR_INVALID_ARG_TYPE', propName, 'integer');
282-
283-
if (err !== undefined) {
284-
Error.captureStackTrace(err, validateUint32);
285-
throw err;
286-
}
287-
}
288-
289161
// Special case of `makeCallback()` that is specific to async `*stat()` calls as
290162
// an optimization, since the data passed back to the callback needs to be
291163
// transformed anyway.
@@ -308,85 +180,8 @@ function isFd(path) {
308180
return (path >>> 0) === path;
309181
}
310182

311-
// Constructor for file stats.
312-
function Stats(
313-
dev,
314-
mode,
315-
nlink,
316-
uid,
317-
gid,
318-
rdev,
319-
blksize,
320-
ino,
321-
size,
322-
blocks,
323-
atim_msec,
324-
mtim_msec,
325-
ctim_msec,
326-
birthtim_msec
327-
) {
328-
this.dev = dev;
329-
this.mode = mode;
330-
this.nlink = nlink;
331-
this.uid = uid;
332-
this.gid = gid;
333-
this.rdev = rdev;
334-
this.blksize = blksize;
335-
this.ino = ino;
336-
this.size = size;
337-
this.blocks = blocks;
338-
this.atimeMs = atim_msec;
339-
this.mtimeMs = mtim_msec;
340-
this.ctimeMs = ctim_msec;
341-
this.birthtimeMs = birthtim_msec;
342-
this.atime = new Date(atim_msec + 0.5);
343-
this.mtime = new Date(mtim_msec + 0.5);
344-
this.ctime = new Date(ctim_msec + 0.5);
345-
this.birthtime = new Date(birthtim_msec + 0.5);
346-
}
347183
fs.Stats = Stats;
348184

349-
Stats.prototype._checkModeProperty = function(property) {
350-
return ((this.mode & S_IFMT) === property);
351-
};
352-
353-
Stats.prototype.isDirectory = function() {
354-
return this._checkModeProperty(constants.S_IFDIR);
355-
};
356-
357-
Stats.prototype.isFile = function() {
358-
return this._checkModeProperty(S_IFREG);
359-
};
360-
361-
Stats.prototype.isBlockDevice = function() {
362-
return this._checkModeProperty(constants.S_IFBLK);
363-
};
364-
365-
Stats.prototype.isCharacterDevice = function() {
366-
return this._checkModeProperty(constants.S_IFCHR);
367-
};
368-
369-
Stats.prototype.isSymbolicLink = function() {
370-
return this._checkModeProperty(S_IFLNK);
371-
};
372-
373-
Stats.prototype.isFIFO = function() {
374-
return this._checkModeProperty(S_IFIFO);
375-
};
376-
377-
Stats.prototype.isSocket = function() {
378-
return this._checkModeProperty(S_IFSOCK);
379-
};
380-
381-
const statValues = binding.statValues;
382-
383-
function statsFromValues(stats = statValues) {
384-
return new Stats(stats[0], stats[1], stats[2], stats[3], stats[4], stats[5],
385-
stats[6] < 0 ? undefined : stats[6], stats[7], stats[8],
386-
stats[9] < 0 ? undefined : stats[9], stats[10], stats[11],
387-
stats[12], stats[13]);
388-
}
389-
390185
// Don't allow mode to accidentally be overwritten.
391186
Object.defineProperties(fs, {
392187
F_OK: { enumerable: true, value: constants.F_OK || 0 },
@@ -760,16 +555,6 @@ fs.closeSync = function(fd) {
760555
handleErrorFromBinding(ctx);
761556
};
762557

763-
function modeNum(m, def) {
764-
if (typeof m === 'number')
765-
return m;
766-
if (typeof m === 'string')
767-
return parseInt(m, 8);
768-
if (def)
769-
return modeNum(def);
770-
return undefined;
771-
}
772-
773558
fs.open = function(path, flags, mode, callback_) {
774559
var callback = makeCallback(arguments[arguments.length - 1]);
775560
mode = modeNum(mode, 0o666);
@@ -1162,42 +947,6 @@ fs.readlinkSync = function(path, options) {
1162947
return result;
1163948
};
1164949

1165-
function preprocessSymlinkDestination(path, type, linkPath) {
1166-
if (!isWindows) {
1167-
// No preprocessing is needed on Unix.
1168-
return path;
1169-
} else if (type === 'junction') {
1170-
// Junctions paths need to be absolute and \\?\-prefixed.
1171-
// A relative target is relative to the link's parent directory.
1172-
path = pathModule.resolve(linkPath, '..', path);
1173-
return pathModule.toNamespacedPath(path);
1174-
} else {
1175-
// Windows symlinks don't tolerate forward slashes.
1176-
return ('' + path).replace(/\//g, '\\');
1177-
}
1178-
}
1179-
1180-
function stringToSymlinkType(type) {
1181-
let flags = 0;
1182-
if (typeof type === 'string') {
1183-
switch (type) {
1184-
case 'dir':
1185-
flags |= constants.UV_FS_SYMLINK_DIR;
1186-
break;
1187-
case 'junction':
1188-
flags |= constants.UV_FS_SYMLINK_JUNCTION;
1189-
break;
1190-
case 'file':
1191-
break;
1192-
default:
1193-
const err = new errors.Error('ERR_FS_INVALID_SYMLINK_TYPE', type);
1194-
Error.captureStackTrace(err, stringToSymlinkType);
1195-
throw err;
1196-
}
1197-
}
1198-
return flags;
1199-
}
1200-
1201950
fs.symlink = function(target, path, type_, callback_) {
1202951
var type = (typeof type_ === 'string' ? type_ : null);
1203952
var callback = makeCallback(arguments[arguments.length - 1]);
@@ -1421,28 +1170,6 @@ fs.chownSync = function(path, uid, gid) {
14211170
return binding.chown(pathModule.toNamespacedPath(path), uid, gid);
14221171
};
14231172

1424-
// converts Date or number to a fractional UNIX timestamp
1425-
function toUnixTimestamp(time, name = 'time') {
1426-
// eslint-disable-next-line eqeqeq
1427-
if (typeof time === 'string' && +time == time) {
1428-
return +time;
1429-
}
1430-
if (Number.isFinite(time)) {
1431-
if (time < 0) {
1432-
return Date.now() / 1000;
1433-
}
1434-
return time;
1435-
}
1436-
if (util.isDate(time)) {
1437-
// convert to 123.456 UNIX timestamp
1438-
return time.getTime() / 1000;
1439-
}
1440-
throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
1441-
name,
1442-
['Date', 'Time in seconds'],
1443-
time);
1444-
}
1445-
14461173
// exported for unit tests, not for public consumption
14471174
fs._toUnixTimestamp = toUnixTimestamp;
14481175

0 commit comments

Comments
 (0)