From 7bb0120cec3690243f86e3eaafd9371aaaeb306a Mon Sep 17 00:00:00 2001 From: Lam Wei Li Date: Sun, 17 Apr 2022 01:00:15 +0800 Subject: [PATCH] Check and warn for the absence of fs.realpath.native (#953) * Revert "Remove check for fs.realpath.native support, since it's everywhere (#887)" This reverts commit f4a880d29c3a699c0695755fe8533d786c55f65f. * Added warning and fallback support for missing fs.realpath.native Signed-off-by: Lam Wei Li * Removed NodeJS check and fs.realpath.native fallback Signed-off-by: Lam Wei Li * Leaving original listener intact during test and better phasing for warning Signed-off-by: Lam Wei Li * Using done() for proper async test Signed-off-by: Lam Wei Li * Updated comments for clarity Co-authored-by: Ryan Zimmerman <17342435+RyanZim@users.noreply.github.com> Co-authored-by: Ryan Zimmerman <17342435+RyanZim@users.noreply.github.com> --- lib/fs/__tests__/realpath.test.js | 58 ++++++++++++++++++++++++++++++- lib/fs/index.js | 11 +++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/lib/fs/__tests__/realpath.test.js b/lib/fs/__tests__/realpath.test.js index 93068593d..b03249b2a 100644 --- a/lib/fs/__tests__/realpath.test.js +++ b/lib/fs/__tests__/realpath.test.js @@ -1,11 +1,67 @@ '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 warningListener = error => { + if (error.name === 'Warning') { + if (error.code.startsWith('fs-extra-WARN0003')) { + warning = 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.on('warning', warningListener) + + // clear existing require.cache + clearFseCache() + + // simulate fs monkey-patch + delete fs.realpath.native + }) + + after(() => { + process.off('warning', warningListener) + + // clear stubbed require.cache + clearFseCache() + + // reinstate fs.realpath.native + fs.realpath.native = realpathNativeBackup + }) + + 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) + }) +}) + 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 e460b747c..7b025e294 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,13 @@ if (typeof fs.writev === 'function') { }) } } + +// 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 { + process.emitWarning( + 'fs.realpath.native is not a function. Is fs being monkey-patched?', + 'Warning', 'fs-extra-WARN0003' + ) +}