From 8f942de5751120df3b0da254a4d2f4afa58d1fcd Mon Sep 17 00:00:00 2001 From: Lam Wei Li Date: Wed, 6 Apr 2022 21:19:55 +0800 Subject: [PATCH 1/6] Revert "Remove check for fs.realpath.native support, since it's everywhere (#887)" This reverts commit f4a880d29c3a699c0695755fe8533d786c55f65f. --- lib/fs/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/fs/index.js b/lib/fs/index.js index e460b747..3e5bd024 100644 --- a/lib/fs/index.js +++ b/lib/fs/index.js @@ -54,7 +54,6 @@ Object.assign(exports, fs) api.forEach(method => { exports[method] = u(fs[method]) }) -exports.realpath.native = u(fs.realpath.native) // We differ from mz/fs in that we still ship the old, broken, fs.exists() // since we are a drop-in replacement for the native module @@ -117,3 +116,8 @@ if (typeof fs.writev === 'function') { }) } } + +// fs.realpath.native only available in Node v9.2+ +if (typeof fs.realpath.native === 'function') { + exports.realpath.native = u(fs.realpath.native) +} From 07b0b24aa8ccc5216219051d5f9d906a4880c2ac Mon Sep 17 00:00:00 2001 From: Lam Wei Li Date: Fri, 8 Apr 2022 22:59:43 +0800 Subject: [PATCH 2/6] Added warning and fallback support for missing fs.realpath.native Signed-off-by: Lam Wei Li --- lib/fs/__tests__/realpath.test.js | 66 ++++++++++++++++++++++++++++++- lib/fs/index.js | 17 ++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/lib/fs/__tests__/realpath.test.js b/lib/fs/__tests__/realpath.test.js index 93068593..30664f73 100644 --- a/lib/fs/__tests__/realpath.test.js +++ b/lib/fs/__tests__/realpath.test.js @@ -1,11 +1,75 @@ 'use strict' -const fse = require('../..') +const fs = require('fs') +const path = require('path') const assert = require('assert') /* eslint-env mocha */ +describe('realpath.native does not exist', () => { + let warning + const originalListener = process.listeners('warning')[process.listeners('warning').length - 1] + const warningListener = error => { + if (error.name === 'Warning') { + if (error.code.startsWith('fs-extra-WARN0003')) { + warning = error + return + } + } + originalListener(error) + } + + const realpathNativeBackup = fs.realpath.native + const clearFseCache = () => { + const fsePath = path.dirname(require.resolve('../../..')) + for (const entry in require.cache) { + if (entry.startsWith(fsePath)) { + delete require.cache[entry] + } + } + } + + before(() => { + process.off('warning', originalListener) + process.on('warning', warningListener) + + // clear existing require.cache + clearFseCache() + + // mock stub + delete fs.realpath.native + }) + + after(() => { + process.off('warning', warningListener) + process.on('warning', originalListener) + + // clear stubbed require.cache + clearFseCache() + + // reinstate + fs.realpath.native = realpathNativeBackup + require('../..') + }) + + it('fse fallback to realpath internally', () => { + const fse = require(require.resolve('../..')) + + // next event loop to allow event emitter/listener to happen + setImmediate(() => { + assert(warning, 'fs-extra-WARN0003 should be emitted') + }) + + fse.realpath.native(__dirname, (err, path) => { + assert.ifError(err) + assert.strictEqual(path, __dirname) + }) + }) +}) + describe('realpath.native', () => { + const fse = require('../..') + it('works with callbacks', () => { fse.realpath.native(__dirname, (err, path) => { assert.ifError(err) diff --git a/lib/fs/index.js b/lib/fs/index.js index 3e5bd024..da9755d1 100644 --- a/lib/fs/index.js +++ b/lib/fs/index.js @@ -120,4 +120,21 @@ if (typeof fs.writev === 'function') { // fs.realpath.native only available in Node v9.2+ if (typeof fs.realpath.native === 'function') { exports.realpath.native = u(fs.realpath.native) +} else { + // fallback to a similar method signature that is present before Node v9.2 + exports.realpath.native = u(fs.realpath) + + // emit warning that fs.realpath.native is not a function (or undefined) + const nodeVer = process.version.match(/(\d+)\.(\d+)\.(\d+)/) + const [major, minor] = nodeVer.slice(1).map(_ => parseInt(_)) + process.emitWarning( + `fs.realpath.native is not a function: ${fs.realpath.native}.\n` + + '\tfs.realpath.native is now redirected to fs.realpath as a fallback measure.\n\n' + + ( + (major <= 9 || (major === 9 && minor < 2)) + ? `\tEnsure that NodeJS is at least v9.2.0. Detected: ${process.version}.` + : '\tEnsure that fs-extra is imported before other dependencies that can change fs.\n\n' + + '\tsee https://github.com/jprichardson/node-fs-extra/pull/953' + ), + 'Warning', 'fs-extra-WARN0003') } From d06854f91241abcc81f21472963096bfc36e2b7c Mon Sep 17 00:00:00 2001 From: Lam Wei Li Date: Sat, 9 Apr 2022 23:13:40 +0800 Subject: [PATCH 3/6] Removed NodeJS check and fs.realpath.native fallback Signed-off-by: Lam Wei Li --- lib/fs/__tests__/realpath.test.js | 7 ++----- lib/fs/index.js | 20 +++++--------------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/lib/fs/__tests__/realpath.test.js b/lib/fs/__tests__/realpath.test.js index 30664f73..a381f18a 100644 --- a/lib/fs/__tests__/realpath.test.js +++ b/lib/fs/__tests__/realpath.test.js @@ -52,7 +52,7 @@ describe('realpath.native does not exist', () => { require('../..') }) - it('fse fallback to realpath internally', () => { + it('fse should not export realpath.native', () => { const fse = require(require.resolve('../..')) // next event loop to allow event emitter/listener to happen @@ -60,10 +60,7 @@ describe('realpath.native does not exist', () => { assert(warning, 'fs-extra-WARN0003 should be emitted') }) - fse.realpath.native(__dirname, (err, path) => { - assert.ifError(err) - assert.strictEqual(path, __dirname) - }) + assert(!fse.realpath.native) }) }) diff --git a/lib/fs/index.js b/lib/fs/index.js index da9755d1..d11b51e8 100644 --- a/lib/fs/index.js +++ b/lib/fs/index.js @@ -121,20 +121,10 @@ if (typeof fs.writev === 'function') { if (typeof fs.realpath.native === 'function') { exports.realpath.native = u(fs.realpath.native) } else { - // fallback to a similar method signature that is present before Node v9.2 - exports.realpath.native = u(fs.realpath) - - // emit warning that fs.realpath.native is not a function (or undefined) - const nodeVer = process.version.match(/(\d+)\.(\d+)\.(\d+)/) - const [major, minor] = nodeVer.slice(1).map(_ => parseInt(_)) process.emitWarning( - `fs.realpath.native is not a function: ${fs.realpath.native}.\n` + - '\tfs.realpath.native is now redirected to fs.realpath as a fallback measure.\n\n' + - ( - (major <= 9 || (major === 9 && minor < 2)) - ? `\tEnsure that NodeJS is at least v9.2.0. Detected: ${process.version}.` - : '\tEnsure that fs-extra is imported before other dependencies that can change fs.\n\n' + - '\tsee https://github.com/jprichardson/node-fs-extra/pull/953' - ), - 'Warning', 'fs-extra-WARN0003') + 'fs.realpath.native is not a function. ' + + 'Ensure that fs-extra is imported before other dependencies that can change fs.\n\n' + + '\tsee https://github.com/jprichardson/node-fs-extra/pull/953', + 'Warning', 'fs-extra-WARN0003' + ) } From 38b85a08dc3b36db94bf93a889cc72fd8251d99f Mon Sep 17 00:00:00 2001 From: Lam Wei Li Date: Sun, 10 Apr 2022 02:35:29 +0800 Subject: [PATCH 4/6] Leaving original listener intact during test and better phasing for warning Signed-off-by: Lam Wei Li --- lib/fs/__tests__/realpath.test.js | 12 +++--------- lib/fs/index.js | 4 +--- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/lib/fs/__tests__/realpath.test.js b/lib/fs/__tests__/realpath.test.js index a381f18a..0d027977 100644 --- a/lib/fs/__tests__/realpath.test.js +++ b/lib/fs/__tests__/realpath.test.js @@ -8,15 +8,12 @@ const assert = require('assert') describe('realpath.native does not exist', () => { let warning - const originalListener = process.listeners('warning')[process.listeners('warning').length - 1] const warningListener = error => { if (error.name === 'Warning') { if (error.code.startsWith('fs-extra-WARN0003')) { warning = error - return } } - originalListener(error) } const realpathNativeBackup = fs.realpath.native @@ -30,30 +27,27 @@ describe('realpath.native does not exist', () => { } before(() => { - process.off('warning', originalListener) process.on('warning', warningListener) // clear existing require.cache clearFseCache() - // mock stub + // simulate fs monkey-patch delete fs.realpath.native }) after(() => { process.off('warning', warningListener) - process.on('warning', originalListener) // clear stubbed require.cache clearFseCache() - // reinstate + // reinstate fs.realpath.native fs.realpath.native = realpathNativeBackup - require('../..') }) it('fse should not export realpath.native', () => { - const fse = require(require.resolve('../..')) + const fse = require('../..') // next event loop to allow event emitter/listener to happen setImmediate(() => { diff --git a/lib/fs/index.js b/lib/fs/index.js index d11b51e8..7af118bb 100644 --- a/lib/fs/index.js +++ b/lib/fs/index.js @@ -122,9 +122,7 @@ if (typeof fs.realpath.native === 'function') { exports.realpath.native = u(fs.realpath.native) } else { process.emitWarning( - 'fs.realpath.native is not a function. ' + - 'Ensure that fs-extra is imported before other dependencies that can change fs.\n\n' + - '\tsee https://github.com/jprichardson/node-fs-extra/pull/953', + 'fs.realpath.native is not a function. Is fs being monkey-patched?', 'Warning', 'fs-extra-WARN0003' ) } From 782121f70c8dde5ea3ca9abe022c0f2ceaf7453a Mon Sep 17 00:00:00 2001 From: Lam Wei Li Date: Mon, 11 Apr 2022 23:00:24 +0800 Subject: [PATCH 5/6] Using done() for proper async test Signed-off-by: Lam Wei Li --- lib/fs/__tests__/realpath.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/fs/__tests__/realpath.test.js b/lib/fs/__tests__/realpath.test.js index 0d027977..b03249b2 100644 --- a/lib/fs/__tests__/realpath.test.js +++ b/lib/fs/__tests__/realpath.test.js @@ -46,12 +46,13 @@ describe('realpath.native does not exist', () => { fs.realpath.native = realpathNativeBackup }) - it('fse should not export realpath.native', () => { + it('fse should not export realpath.native', done => { const fse = require('../..') // next event loop to allow event emitter/listener to happen setImmediate(() => { assert(warning, 'fs-extra-WARN0003 should be emitted') + done() }) assert(!fse.realpath.native) From 882a00f82884247d153cdd2250a4ca6331d44a40 Mon Sep 17 00:00:00 2001 From: Lam Wei Li Date: Mon, 11 Apr 2022 23:05:05 +0800 Subject: [PATCH 6/6] Updated comments for clarity Co-authored-by: Ryan Zimmerman <17342435+RyanZim@users.noreply.github.com> --- lib/fs/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fs/index.js b/lib/fs/index.js index 7af118bb..7b025e29 100644 --- a/lib/fs/index.js +++ b/lib/fs/index.js @@ -117,7 +117,7 @@ if (typeof fs.writev === 'function') { } } -// fs.realpath.native only available in Node v9.2+ +// fs.realpath.native sometimes not available if fs is monkey-patched if (typeof fs.realpath.native === 'function') { exports.realpath.native = u(fs.realpath.native) } else {