Skip to content

Commit

Permalink
fs: refactor to use more primordials
Browse files Browse the repository at this point in the history
PR-URL: #36196
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
aduh95 authored and danielleadams committed Dec 7, 2020
1 parent a9ac86d commit c04a2df
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 68 deletions.
51 changes: 30 additions & 21 deletions lib/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,22 @@ const kIoMaxLength = 2 ** 31 - 1;
// in case they are created but never used due to an exception.

const {
Map,
ArrayPrototypePush,
BigIntPrototypeToString,
MathMax,
Number,
NumberIsSafeInteger,
ObjectCreate,
ObjectDefineProperties,
ObjectDefineProperty,
Promise,
ReflectApply,
RegExpPrototypeExec,
SafeMap,
String,
StringPrototypeCharCodeAt,
StringPrototypeIndexOf,
StringPrototypeSlice,
} = primordials;

const { fs: constants } = internalBinding('constants');
Expand Down Expand Up @@ -329,7 +336,7 @@ function readFile(path, options, callback) {
}
if (context.isUserFd) {
process.nextTick(function tick(context) {
readFileAfterOpen.call({ context }, null, path);
ReflectApply(readFileAfterOpen, { context }, [null, path]);
}, context);
return;
}
Expand Down Expand Up @@ -414,7 +421,7 @@ function readFileSync(path, options) {
buffer = Buffer.allocUnsafe(8192);
bytesRead = tryReadSync(fd, isUserFd, buffer, 0, 8192);
if (bytesRead !== 0) {
buffers.push(buffer.slice(0, bytesRead));
ArrayPrototypePush(buffers, buffer.slice(0, bytesRead));
}
pos += bytesRead;
} while (bytesRead !== 0);
Expand Down Expand Up @@ -1580,7 +1587,7 @@ function watch(filename, options, listener) {
}


const statWatchers = new Map();
const statWatchers = new SafeMap();

function watchFile(filename, options, listener) {
filename = getValidatedPath(filename);
Expand Down Expand Up @@ -1652,13 +1659,13 @@ if (isWindows) {
// slash.
const splitRootRe = /^(?:[a-zA-Z]:|[\\/]{2}[^\\/]+[\\/][^\\/]+)?[\\/]*/;
splitRoot = function splitRoot(str) {
return splitRootRe.exec(str)[0];
return RegExpPrototypeExec(splitRootRe, str)[0];
};
} else {
splitRoot = function splitRoot(str) {
for (let i = 0; i < str.length; ++i) {
if (str.charCodeAt(i) !== CHAR_FORWARD_SLASH)
return str.slice(0, i);
if (StringPrototypeCharCodeAt(str, i) !== CHAR_FORWARD_SLASH)
return StringPrototypeSlice(str, 0, i);
}
return str;
};
Expand All @@ -1679,7 +1686,7 @@ let nextPart;
if (isWindows) {
nextPart = function nextPart(p, i) {
for (; i < p.length; ++i) {
const ch = p.charCodeAt(i);
const ch = StringPrototypeCharCodeAt(p, i);

// Check for a separator character
if (ch === CHAR_BACKWARD_SLASH || ch === CHAR_FORWARD_SLASH)
Expand All @@ -1688,7 +1695,9 @@ if (isWindows) {
return -1;
};
} else {
nextPart = function nextPart(p, i) { return p.indexOf('/', i); };
nextPart = function nextPart(p, i) {
return StringPrototypeIndexOf(p, '/', i);
};
}

const emptyObj = ObjectCreate(null);
Expand Down Expand Up @@ -1740,13 +1749,13 @@ function realpathSync(p, options) {
const result = nextPart(p, pos);
previous = current;
if (result === -1) {
const last = p.slice(pos);
const last = StringPrototypeSlice(p, pos);
current += last;
base = previous + last;
pos = p.length;
} else {
current += p.slice(pos, result + 1);
base = previous + p.slice(pos, result);
current += StringPrototypeSlice(p, pos, result + 1);
base = previous + StringPrototypeSlice(p, pos, result);
pos = result + 1;
}

Expand Down Expand Up @@ -1783,8 +1792,8 @@ function realpathSync(p, options) {
let linkTarget = null;
let id;
if (!isWindows) {
const dev = stats[0].toString(32);
const ino = stats[7].toString(32);
const dev = BigIntPrototypeToString(stats[0], 32);
const ino = BigIntPrototypeToString(stats[7], 32);
id = `${dev}:${ino}`;
if (seenLinks[id]) {
linkTarget = seenLinks[id];
Expand All @@ -1804,7 +1813,7 @@ function realpathSync(p, options) {
}

// Resolve the link, then start over
p = pathModule.resolve(resolvedLink, p.slice(pos));
p = pathModule.resolve(resolvedLink, StringPrototypeSlice(p, pos));

// Skip over roots
current = base = splitRoot(p);
Expand Down Expand Up @@ -1883,13 +1892,13 @@ function realpath(p, options, callback) {
const result = nextPart(p, pos);
previous = current;
if (result === -1) {
const last = p.slice(pos);
const last = StringPrototypeSlice(p, pos);
current += last;
base = previous + last;
pos = p.length;
} else {
current += p.slice(pos, result + 1);
base = previous + p.slice(pos, result);
current += StringPrototypeSlice(p, pos, result + 1);
base = previous + StringPrototypeSlice(p, pos, result);
pos = result + 1;
}

Expand Down Expand Up @@ -1919,8 +1928,8 @@ function realpath(p, options, callback) {
// `dev`/`ino` always return 0 on windows, so skip the check.
let id;
if (!isWindows) {
const dev = stats.dev.toString(32);
const ino = stats.ino.toString(32);
const dev = BigIntPrototypeToString(stats.dev, 32);
const ino = BigIntPrototypeToString(stats.ino, 32);
id = `${dev}:${ino}`;
if (seenLinks[id]) {
return gotTarget(null, seenLinks[id]);
Expand All @@ -1944,7 +1953,7 @@ function realpath(p, options, callback) {

function gotResolvedLink(resolvedLink) {
// Resolve the link, then start over
p = pathModule.resolve(resolvedLink, p.slice(pos));
p = pathModule.resolve(resolvedLink, StringPrototypeSlice(p, pos));
current = base = splitRoot(p);
pos = current.length;

Expand Down
23 changes: 15 additions & 8 deletions lib/internal/fs/dir.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
'use strict';

const {
ArrayPrototypePush,
ArrayPrototypeSlice,
ArrayPrototypeSplice,
FunctionPrototypeBind,
ObjectDefineProperty,
Symbol,
SymbolAsyncIterator,
Expand Down Expand Up @@ -61,9 +65,10 @@ class Dir {

validateUint32(this[kDirOptions].bufferSize, 'options.bufferSize', true);

this[kDirReadPromisified] =
internalUtil.promisify(this[kDirReadImpl]).bind(this, false);
this[kDirClosePromisified] = internalUtil.promisify(this.close).bind(this);
this[kDirReadPromisified] = FunctionPrototypeBind(
internalUtil.promisify(this[kDirReadImpl]), this, false);
this[kDirClosePromisified] = FunctionPrototypeBind(
internalUtil.promisify(this.close), this);
}

get path() {
Expand All @@ -86,14 +91,15 @@ class Dir {
}

if (this[kDirOperationQueue] !== null) {
this[kDirOperationQueue].push(() => {
ArrayPrototypePush(this[kDirOperationQueue], () => {
this[kDirReadImpl](maybeSync, callback);
});
return;
}

if (this[kDirBufferedEntries].length > 0) {
const [ name, type ] = this[kDirBufferedEntries].splice(0, 2);
const [ name, type ] =
ArrayPrototypeSplice(this[kDirBufferedEntries], 0, 2);
if (maybeSync)
process.nextTick(getDirent, this[kDirPath], name, type, callback);
else
Expand All @@ -113,7 +119,7 @@ class Dir {
return callback(err, result);
}

this[kDirBufferedEntries] = result.slice(2);
this[kDirBufferedEntries] = ArrayPrototypeSlice(result, 2);
getDirent(this[kDirPath], result[0], result[1], callback);
};

Expand All @@ -135,7 +141,8 @@ class Dir {
}

if (this[kDirBufferedEntries].length > 0) {
const [ name, type ] = this[kDirBufferedEntries].splice(0, 2);
const [ name, type ] =
ArrayPrototypeSplice(this[kDirBufferedEntries], 0, 2);
return getDirent(this[kDirPath], name, type);
}

Expand All @@ -152,7 +159,7 @@ class Dir {
return result;
}

this[kDirBufferedEntries] = result.slice(2);
this[kDirBufferedEntries] = ArrayPrototypeSlice(result, 2);
return getDirent(this[kDirPath], result[0], result[1]);
}

Expand Down
37 changes: 22 additions & 15 deletions lib/internal/fs/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ const kReadFileMaxChunkSize = 2 ** 14;
const kWriteFileMaxChunkSize = 2 ** 14;

const {
ArrayPrototypePush,
Error,
MathMax,
MathMin,
NumberIsSafeInteger,
Promise,
PromisePrototypeFinally,
PromisePrototypeThen,
PromiseResolve,
Symbol,
Uint8Array,
Expand Down Expand Up @@ -178,18 +180,21 @@ class FileHandle extends JSTransferable {
this[kRefs]--;
if (this[kRefs] === 0) {
this[kFd] = -1;
this[kClosePromise] = this[kHandle].close().finally(() => {
this[kClosePromise] = undefined;
});
this[kClosePromise] = PromisePrototypeFinally(
this[kHandle].close(),
() => { this[kClosePromise] = undefined; }
);
} else {
this[kClosePromise] = new Promise((resolve, reject) => {
this[kCloseResolve] = resolve;
this[kCloseReject] = reject;
}).finally(() => {
this[kClosePromise] = undefined;
this[kCloseReject] = undefined;
this[kCloseResolve] = undefined;
});
this[kClosePromise] = PromisePrototypeFinally(
new Promise((resolve, reject) => {
this[kCloseResolve] = resolve;
this[kCloseReject] = reject;
}), () => {
this[kClosePromise] = undefined;
this[kCloseReject] = undefined;
this[kCloseResolve] = undefined;
}
);
}

return this[kClosePromise];
Expand Down Expand Up @@ -243,9 +248,11 @@ async function fsCall(fn, handle, ...args) {
handle[kRefs]--;
if (handle[kRefs] === 0) {
handle[kFd] = -1;
handle[kHandle]
.close()
.then(handle[kCloseResolve], handle[kCloseReject]);
PromisePrototypeThen(
handle[kHandle].close(),
handle[kCloseResolve],
handle[kCloseReject]
);
}
}
}
Expand Down Expand Up @@ -307,7 +314,7 @@ async function readFileHandle(filehandle, options) {
await read(filehandle, buf, 0, chunkSize, -1);
endOfFile = bytesRead === 0;
if (bytesRead > 0)
chunks.push(buffer.slice(0, bytesRead));
ArrayPrototypePush(chunks, buffer.slice(0, bytesRead));
} while (!endOfFile);

const result = Buffer.concat(chunks);
Expand Down
6 changes: 4 additions & 2 deletions lib/internal/fs/read_file_context.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
'use strict';

const {
ArrayPrototypePush,
MathMin,
ReflectApply,
} = primordials;

const { Buffer } = require('buffer');
Expand Down Expand Up @@ -42,7 +44,7 @@ function readFileAfterRead(err, bytesRead) {
// Unknown size, just read until we don't get bytes.
const buffer = bytesRead === kReadFileUnknownBufferLength ?
context.buffer : context.buffer.slice(0, bytesRead);
context.buffers.push(buffer);
ArrayPrototypePush(context.buffers, buffer);
}
context.read();
}
Expand Down Expand Up @@ -118,7 +120,7 @@ class ReadFileContext {
close(err) {
if (this.isUserFd) {
process.nextTick(function tick(context) {
readFileAfterClose.call({ context }, null);
ReflectApply(readFileAfterClose, { context }, [null]);
}, this);
return;
}
Expand Down
11 changes: 6 additions & 5 deletions lib/internal/fs/rimraf.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
'use strict';

const {
ArrayPrototypeForEach,
Promise,
Set,
SafeSet,
} = primordials;

const { Buffer } = require('buffer');
Expand All @@ -30,8 +31,8 @@ const {
const { sep } = require('path');
const { setTimeout } = require('timers');
const { sleep } = require('internal/util');
const notEmptyErrorCodes = new Set(['ENOTEMPTY', 'EEXIST', 'EPERM']);
const retryErrorCodes = new Set(
const notEmptyErrorCodes = new SafeSet(['ENOTEMPTY', 'EEXIST', 'EPERM']);
const retryErrorCodes = new SafeSet(
['EBUSY', 'EMFILE', 'ENFILE', 'ENOTEMPTY', 'EPERM']);
const isWindows = process.platform === 'win32';
const epermHandler = isWindows ? fixWinEPERM : _rmdir;
Expand Down Expand Up @@ -139,7 +140,7 @@ function _rmchildren(path, options, callback) {

let done = false;

files.forEach((child) => {
ArrayPrototypeForEach(files, (child) => {
const childPath = Buffer.concat([pathBuf, separator, child]);

rimraf(childPath, options, (err) => {
Expand Down Expand Up @@ -240,7 +241,7 @@ function _rmdirSync(path, options, originalErr) {
// around that issue by retrying on Windows.
const pathBuf = Buffer.from(path);

readdirSync(pathBuf, readdirEncoding).forEach((child) => {
ArrayPrototypeForEach(readdirSync(pathBuf, readdirEncoding), (child) => {
const childPath = Buffer.concat([pathBuf, separator, child]);

rimrafSync(childPath, options);
Expand Down
Loading

0 comments on commit c04a2df

Please sign in to comment.