From ceb22f5197223f68037fe99155f77f64aa44cfd1 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Wed, 12 Aug 2020 12:27:32 +0200 Subject: [PATCH 01/13] fs: guard against undefined behavior Calling close on a file description which is currently in use is undefined behavior due to implementation details in libuv. Add a guard against this when using FileHandle. --- lib/internal/fs/promises.js | 64 +++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 8a9c292056c59e..fcdea1d9bd2dd9 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -14,6 +14,7 @@ const { MathMin, NumberIsSafeInteger, Symbol, + Promise, } = primordials; const { @@ -64,6 +65,11 @@ const { promisify } = require('internal/util'); const kHandle = Symbol('kHandle'); const kFd = Symbol('kFd'); +const kRefs = Symbol('kRefs'); +const kClosePromise = Symbol('kClosePromise'); +const kCloseResolve = Symbol('kCloseResolve'); +const kCloseReject = Symbol('kCloseReject'); + const { kUsePromises } = binding; const { JSTransferable, kDeserialize, kTransfer, kTransferList @@ -71,11 +77,31 @@ const { const getDirectoryEntriesPromise = promisify(getDirents); +async function fsCall(fn, fileHandle, ...args) { + try { + fileHandle[kRefs]++; + return await fn(fileHandle, ...args); + } finally { + fileHandle[kRefs]--; + + if (fileHandle[kRefs] === 0) { + this[kFd] = -1; + this[kHandle].close().then(this[kCloseResolve], this[kCloseReject]); + } + } +} + class FileHandle extends JSTransferable { constructor(filehandle) { super(); this[kHandle] = filehandle; this[kFd] = filehandle ? filehandle.fd : -1; + + this[kRefs] = 1; + this[kClosePromise] = new Promise((resolve, reject) => { + this[kCloseResolve] = resolve; + this[kCloseReject] = reject; + }); } getAsyncId() { @@ -87,64 +113,70 @@ class FileHandle extends JSTransferable { } appendFile(data, options) { - return writeFile(this, data, options); + return fsCall(writeFile, this, data, options); } chmod(mode) { - return fchmod(this, mode); + return fsCall(fchmod, this, mode); } chown(uid, gid) { - return fchown(this, uid, gid); + return fsCall(fchown, this, uid, gid); } datasync() { - return fdatasync(this); + return fsCall(fdatasync, this); } sync() { - return fsync(this); + return fsCall(fsync, this); } read(buffer, offset, length, position) { - return read(this, buffer, offset, length, position); + return fsCall(read, this, buffer, offset, length, position); } readv(buffers, position) { - return readv(this, buffers, position); + return fsCall(readv, this, buffers, position); } readFile(options) { - return readFile(this, options); + return fsCall(readFile, this, options); } stat(options) { - return fstat(this, options); + return fsCall(fstat, this, options); } truncate(len = 0) { - return ftruncate(this, len); + return fsCall(ftruncate, this, len); } utimes(atime, mtime) { - return futimes(this, atime, mtime); + return fsCall(futimes, this, atime, mtime); } write(buffer, offset, length, position) { - return write(this, buffer, offset, length, position); + return fsCall(write, this, buffer, offset, length, position); } writev(buffers, position) { - return writev(this, buffers, position); + return fsCall(writev, this, buffers, position); } writeFile(data, options) { - return writeFile(this, data, options); + return fsCall(writeFile, this, data, options); } close = () => { - this[kFd] = -1; - return this[kHandle].close(); + this[kRefs]--; + + if (this[kRefs] === 0) { + this[kFd] = -1; + this[kHandle].close().then(this[kCloseResolve], this[kCloseReject]); + } + + return this[kClosePromise]; } [kTransfer]() { From e1380b9196ff5e7ff33189ee18710df5d9d323d1 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Wed, 12 Aug 2020 12:33:49 +0200 Subject: [PATCH 02/13] fixup --- lib/internal/fs/promises.js | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index fcdea1d9bd2dd9..425db978e63abe 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -62,6 +62,7 @@ const { } = require('internal/validators'); const pathModule = require('path'); const { promisify } = require('internal/util'); +const assert = require('assert'); const kHandle = Symbol('kHandle'); const kFd = Symbol('kFd'); @@ -77,20 +78,22 @@ const { const getDirectoryEntriesPromise = promisify(getDirents); -async function fsCall(fn, fileHandle, ...args) { +async function fsCall(fn, handle, ...args) { try { - fileHandle[kRefs]++; - return await fn(fileHandle, ...args); + handle[kRefs]++; + return await fn(handle, ...args); } finally { - fileHandle[kRefs]--; - - if (fileHandle[kRefs] === 0) { - this[kFd] = -1; - this[kHandle].close().then(this[kCloseResolve], this[kCloseReject]); - } + handle[kRefs]--; + fsClose(handle); } } +function fsClose (handle) { + assert(!handle[kRefs]); + handle[kFd] = -1; + handle[kHandle].close().then(handle[kCloseResolve], handle[kCloseReject]); +} + class FileHandle extends JSTransferable { constructor(filehandle) { super(); @@ -170,12 +173,7 @@ class FileHandle extends JSTransferable { close = () => { this[kRefs]--; - - if (this[kRefs] === 0) { - this[kFd] = -1; - this[kHandle].close().then(this[kCloseResolve], this[kCloseReject]); - } - + fsClose(this); return this[kClosePromise]; } From dc1dcff18bda9848a213d8462530110de29c0589 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Wed, 12 Aug 2020 12:58:58 +0200 Subject: [PATCH 03/13] fixup --- lib/internal/fs/promises.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 425db978e63abe..a316809b4da03b 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -88,10 +88,12 @@ async function fsCall(fn, handle, ...args) { } } -function fsClose (handle) { +function fsClose(handle) { assert(!handle[kRefs]); handle[kFd] = -1; - handle[kHandle].close().then(handle[kCloseResolve], handle[kCloseReject]); + handle[kHandle] + .close() + .then(handle[kCloseResolve], handle[kCloseReject]); } class FileHandle extends JSTransferable { From 0bed9defce7b1c61e9bf71644276fe604ff6f5c5 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Wed, 12 Aug 2020 13:02:15 +0200 Subject: [PATCH 04/13] fixup --- lib/internal/fs/promises.js | 70 +++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index a316809b4da03b..bfd019d1a444e6 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -62,7 +62,6 @@ const { } = require('internal/validators'); const pathModule = require('path'); const { promisify } = require('internal/util'); -const assert = require('assert'); const kHandle = Symbol('kHandle'); const kFd = Symbol('kFd'); @@ -78,24 +77,6 @@ const { const getDirectoryEntriesPromise = promisify(getDirents); -async function fsCall(fn, handle, ...args) { - try { - handle[kRefs]++; - return await fn(handle, ...args); - } finally { - handle[kRefs]--; - fsClose(handle); - } -} - -function fsClose(handle) { - assert(!handle[kRefs]); - handle[kFd] = -1; - handle[kHandle] - .close() - .then(handle[kCloseResolve], handle[kCloseReject]); -} - class FileHandle extends JSTransferable { constructor(filehandle) { super(); @@ -103,10 +84,7 @@ class FileHandle extends JSTransferable { this[kFd] = filehandle ? filehandle.fd : -1; this[kRefs] = 1; - this[kClosePromise] = new Promise((resolve, reject) => { - this[kCloseResolve] = resolve; - this[kCloseReject] = reject; - }); + this[kClosePromise] = null; } getAsyncId() { @@ -174,8 +152,22 @@ class FileHandle extends JSTransferable { } close = () => { + if (this[kClosePromise]) { + return this[kClosePromise]; + } + this[kRefs]--; - fsClose(this); + + if (this[kRefs]) { + this[kClosePromise] = new Promise((resolve, reject) => { + this[kCloseResolve] = resolve; + this[kCloseReject] = reject; + }); + } else { + this[kFd] = -1; + this[kClosePromise] = this[kHandle].close(); + } + return this[kClosePromise]; } @@ -200,9 +192,24 @@ class FileHandle extends JSTransferable { } } -function validateFileHandle(handle) { - if (!(handle instanceof FileHandle)) +async function fsCall(fn, handle, ...args) { + if (!(handle instanceof FileHandle) || + handle.fd === -1 || handle[kRefs] === 0) { throw new ERR_INVALID_ARG_TYPE('filehandle', 'FileHandle', handle); + } + + try { + handle[kRefs]++; + return await fn(handle, ...args); + } finally { + handle[kRefs]--; + if (handle[kRefs] === 0) { + handle[kFd] = -1; + handle[kHandle] + .close() + .then(handle[kCloseResolve], handle[kCloseReject]); + } + } } async function writeFileHandle(filehandle, data) { @@ -281,7 +288,6 @@ async function open(path, flags, mode) { } async function read(handle, buffer, offset, length, position) { - validateFileHandle(handle); validateBuffer(buffer); if (offset == null) { @@ -312,7 +318,6 @@ async function read(handle, buffer, offset, length, position) { } async function readv(handle, buffers, position) { - validateFileHandle(handle); validateBufferArray(buffers); if (typeof position !== 'number') @@ -324,8 +329,6 @@ async function readv(handle, buffers, position) { } async function write(handle, buffer, offset, length, position) { - validateFileHandle(handle); - if (buffer.length === 0) return { bytesWritten: 0, buffer }; @@ -353,7 +356,6 @@ async function write(handle, buffer, offset, length, position) { } async function writev(handle, buffers, position) { - validateFileHandle(handle); validateBufferArray(buffers); if (typeof position !== 'number') @@ -378,7 +380,6 @@ async function truncate(path, len = 0) { } async function ftruncate(handle, len = 0) { - validateFileHandle(handle); validateInteger(len, 'len'); len = MathMax(0, len); return binding.ftruncate(handle.fd, len, kUsePromises); @@ -396,12 +397,10 @@ async function rmdir(path, options) { } async function fdatasync(handle) { - validateFileHandle(handle); return binding.fdatasync(handle.fd, kUsePromises); } async function fsync(handle) { - validateFileHandle(handle); return binding.fsync(handle.fd, kUsePromises); } @@ -452,7 +451,6 @@ async function symlink(target, path, type_) { } async function fstat(handle, options = { bigint: false }) { - validateFileHandle(handle); const result = await binding.fstat(handle.fd, options.bigint, kUsePromises); return getStatsFromBinding(result); } @@ -513,7 +511,6 @@ async function lchown(path, uid, gid) { } async function fchown(handle, uid, gid) { - validateFileHandle(handle); validateUint32(uid, 'uid'); validateUint32(gid, 'gid'); return binding.fchown(handle.fd, uid, gid, kUsePromises); @@ -536,7 +533,6 @@ async function utimes(path, atime, mtime) { } async function futimes(handle, atime, mtime) { - validateFileHandle(handle); atime = toUnixTimestamp(atime, 'atime'); mtime = toUnixTimestamp(mtime, 'mtime'); return binding.futimes(handle.fd, atime, mtime, kUsePromises); From 6a3c7bb8273ca07b10f2fd466c25c163c1135e19 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Wed, 12 Aug 2020 13:14:42 +0200 Subject: [PATCH 05/13] fixup: ERR_FS_FILE_CLOSED --- doc/api/errors.md | 6 ++++++ lib/internal/errors.js | 1 + lib/internal/fs/promises.js | 9 ++++++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/doc/api/errors.md b/doc/api/errors.md index db3ea5af4be9b1..e26d1e0441e2f7 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -928,6 +928,12 @@ added: v14.0.0 Used when a feature that is not available to the current platform which is running Node.js is used. + +### `ERR_FS_FILE_CLOSED` + +An attempt has been made to use a +closed file handle. + ### `ERR_FS_FILE_TOO_LARGE` diff --git a/lib/internal/errors.js b/lib/internal/errors.js index a9c69eda7b0e6c..cff38031ad09d1 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -838,6 +838,7 @@ E('ERR_FEATURE_UNAVAILABLE_ON_PLATFORM', 'The feature %s is unavailable on the current platform' + ', which is being used to run Node.js', TypeError); +E('ERR_FS_FILE_CLOSED', 'File is closed', Error); E('ERR_FS_FILE_TOO_LARGE', 'File size (%s) is greater than 2 GB', RangeError); E('ERR_FS_INVALID_SYMLINK_TYPE', 'Symlink type must be one of "dir", "file", or "junction". Received "%s"', diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index bfd019d1a444e6..33576954b50db6 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -28,6 +28,7 @@ const binding = internalBinding('fs'); const { Buffer } = require('buffer'); const { ERR_FS_FILE_TOO_LARGE, + ERR_FS_FILE_CLOSED, ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_VALUE, ERR_METHOD_NOT_IMPLEMENTED @@ -193,11 +194,14 @@ class FileHandle extends JSTransferable { } async function fsCall(fn, handle, ...args) { - if (!(handle instanceof FileHandle) || - handle.fd === -1 || handle[kRefs] === 0) { + if (!(handle instanceof FileHandle)) { throw new ERR_INVALID_ARG_TYPE('filehandle', 'FileHandle', handle); } + if (handle.fd === -1 || handle[kRefs] === 0) { + throw new ERR_FS_FILE_CLOSED(); + } + try { handle[kRefs]++; return await fn(handle, ...args); @@ -483,7 +487,6 @@ async function unlink(path) { } async function fchmod(handle, mode) { - validateFileHandle(handle); mode = parseFileMode(mode, 'mode'); return binding.fchmod(handle.fd, mode, kUsePromises); } From fd5ca6044106d567cbdedc34c21086fce47eafdb Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Wed, 12 Aug 2020 23:03:11 +0200 Subject: [PATCH 06/13] fixup --- doc/api/errors.md | 6 ------ lib/internal/errors.js | 1 - lib/internal/fs/promises.js | 21 ++++++++++++--------- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/doc/api/errors.md b/doc/api/errors.md index e26d1e0441e2f7..db3ea5af4be9b1 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -928,12 +928,6 @@ added: v14.0.0 Used when a feature that is not available to the current platform which is running Node.js is used. - -### `ERR_FS_FILE_CLOSED` - -An attempt has been made to use a -closed file handle. - ### `ERR_FS_FILE_TOO_LARGE` diff --git a/lib/internal/errors.js b/lib/internal/errors.js index cff38031ad09d1..a9c69eda7b0e6c 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -838,7 +838,6 @@ E('ERR_FEATURE_UNAVAILABLE_ON_PLATFORM', 'The feature %s is unavailable on the current platform' + ', which is being used to run Node.js', TypeError); -E('ERR_FS_FILE_CLOSED', 'File is closed', Error); E('ERR_FS_FILE_TOO_LARGE', 'File size (%s) is greater than 2 GB', RangeError); E('ERR_FS_INVALID_SYMLINK_TYPE', 'Symlink type must be one of "dir", "file", or "junction". Received "%s"', diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 33576954b50db6..06d94e53ad00e2 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -14,6 +14,7 @@ const { MathMin, NumberIsSafeInteger, Symbol, + Error, Promise, } = primordials; @@ -28,7 +29,6 @@ const binding = internalBinding('fs'); const { Buffer } = require('buffer'); const { ERR_FS_FILE_TOO_LARGE, - ERR_FS_FILE_CLOSED, ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_VALUE, ERR_METHOD_NOT_IMPLEMENTED @@ -158,15 +158,14 @@ class FileHandle extends JSTransferable { } this[kRefs]--; - - if (this[kRefs]) { + if (this[kRefs] === 0) { + this[kFd] = -1; + this[kClosePromise] = this[kHandle].close(); + } else { this[kClosePromise] = new Promise((resolve, reject) => { this[kCloseResolve] = resolve; this[kCloseReject] = reject; }); - } else { - this[kFd] = -1; - this[kClosePromise] = this[kHandle].close(); } return this[kClosePromise]; @@ -194,12 +193,16 @@ class FileHandle extends JSTransferable { } async function fsCall(fn, handle, ...args) { - if (!(handle instanceof FileHandle)) { + if (handle[kRefs] === undefined) { throw new ERR_INVALID_ARG_TYPE('filehandle', 'FileHandle', handle); } - if (handle.fd === -1 || handle[kRefs] === 0) { - throw new ERR_FS_FILE_CLOSED(); + if (handle.fd === -1) { + // eslint-disable-next-line no-restricted-syntax + const err = new Error('file closed'); + err.code = 'EBADF'; + err.syscall = fn.name; + throw err; } try { From 44c40dc62afb59431da9b0f70d2a2ef41d978cf2 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Thu, 13 Aug 2020 20:47:19 +0200 Subject: [PATCH 07/13] fixup: transfer warning --- lib/internal/fs/promises.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 06d94e53ad00e2..268fd6d3372338 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -172,9 +172,16 @@ class FileHandle extends JSTransferable { } [kTransfer]() { + if (this[kClosePromise] || this[kRefs] > 1) { + const DOMException = internalBinding('messaging').DOMException; + throw new DOMException('Cannot transfer FileHandle while in use', + 'DataCloneError'); + } + const handle = this[kHandle]; this[kFd] = -1; this[kHandle] = null; + this[kRefs] = 0; return { data: { handle }, From 87f14edc3c35aaaac31a5667019791f3e656508e Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Thu, 13 Aug 2020 21:50:17 +0200 Subject: [PATCH 08/13] fixup --- ...worker-message-port-transfer-filehandle.js | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/parallel/test-worker-message-port-transfer-filehandle.js b/test/parallel/test-worker-message-port-transfer-filehandle.js index 2184ad575fa4a4..429fba03c18178 100644 --- a/test/parallel/test-worker-message-port-transfer-filehandle.js +++ b/test/parallel/test-worker-message-port-transfer-filehandle.js @@ -68,3 +68,36 @@ const { once } = require('events'); port1.postMessage('second message'); })().then(common.mustCall()); + +(async function() { + // Check that filehandles with a read in progress cannot be transferred. + const fh = await fs.open(__filename); + + const { port1 } = new MessageChannel(); + + const readPromise = fh.readFile(); + assert.throws(() => { + port1.postMessage(fh, [fh]); + }, { + message: 'Cannot transfer FileHandle while in use', + name: 'DataCloneError' + }); + + assert.deepStrictEqual(await readPromise, await fs.readFile(__filename)); +})().then(common.mustCall()); + +(async function() { + // Check that filehandles with a close in progress cannot be transferred. + const fh = await fs.open(__filename); + + const { port1 } = new MessageChannel(); + + const closePromise = fh.close(); + assert.throws(() => { + port1.postMessage(fh, [fh]); + }, { + message: 'Cannot transfer FileHandle while in use', + name: 'DataCloneError' + }); + await closePromise; +})().then(common.mustCall()); From c1f42457b188c09096693ca6f6ccb23c6304e4c7 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Thu, 13 Aug 2020 22:32:25 +0200 Subject: [PATCH 09/13] Update test/parallel/test-worker-message-port-transfer-filehandle.js Co-authored-by: James M Snell --- test/parallel/test-worker-message-port-transfer-filehandle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/parallel/test-worker-message-port-transfer-filehandle.js b/test/parallel/test-worker-message-port-transfer-filehandle.js index 429fba03c18178..9fabf01b604fc4 100644 --- a/test/parallel/test-worker-message-port-transfer-filehandle.js +++ b/test/parallel/test-worker-message-port-transfer-filehandle.js @@ -70,7 +70,7 @@ const { once } = require('events'); })().then(common.mustCall()); (async function() { - // Check that filehandles with a read in progress cannot be transferred. + // Check that a FileHandle with a read in progress cannot be transferred. const fh = await fs.open(__filename); const { port1 } = new MessageChannel(); From 8ebe12de8fd52e69f75c0e934c2873024032c371 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Thu, 13 Aug 2020 22:33:52 +0200 Subject: [PATCH 10/13] fixup: docs --- doc/api/fs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index 6ae3b18938036a..ffe182e3f2e9cb 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4548,7 +4548,8 @@ added: v10.0.0 file descriptor is closed, or will be rejected if an error occurs while closing. -Closes the file descriptor. +Closes the file handle. Will wait for any pending operation on the handle +to complete before closing the file descriptor. ```js const fsPromises = require('fs').promises; From dcd5ddb5a54efddfed577a6d8f1a459f72f574ee Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Thu, 13 Aug 2020 23:22:47 +0200 Subject: [PATCH 11/13] Apply suggestions from code review Co-authored-by: James M Snell --- lib/internal/fs/promises.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 268fd6d3372338..01f93fd3edd195 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -153,6 +153,10 @@ class FileHandle extends JSTransferable { } close = () => { + if (this[kFd] === -1) { + return Promise.resolve(); + } + if (this[kClosePromise]) { return this[kClosePromise]; } @@ -160,11 +164,17 @@ class FileHandle extends JSTransferable { this[kRefs]--; if (this[kRefs] === 0) { this[kFd] = -1; - this[kClosePromise] = this[kHandle].close(); + this[kClosePromise] = this[kHandle].close().finally(() => { + 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; }); } From b384f0862a6470c0dbf6601ed298a7a6e469b966 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Thu, 13 Aug 2020 23:32:47 +0200 Subject: [PATCH 12/13] fixup: docs --- doc/api/fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index ffe182e3f2e9cb..67f08805ef84ef 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4549,7 +4549,7 @@ added: v10.0.0 closing. Closes the file handle. Will wait for any pending operation on the handle -to complete before closing the file descriptor. +to complete before completing. ```js const fsPromises = require('fs').promises; From 69cc10b0db6cfaea7167b2d5dd2943eca86277c1 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Thu, 13 Aug 2020 23:33:34 +0200 Subject: [PATCH 13/13] fixup: linting --- lib/internal/fs/promises.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 01f93fd3edd195..a938b382eb1268 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -156,7 +156,7 @@ class FileHandle extends JSTransferable { if (this[kFd] === -1) { return Promise.resolve(); } - + if (this[kClosePromise]) { return this[kClosePromise]; }