Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fs: refactor to use more primordials #36196

Merged
merged 1 commit into from Nov 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 30 additions & 21 deletions lib/fs.js
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
@@ -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
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
@@ -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
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