From 8a6dcd040f35b023f0cc0208c4bc553fcc7e6a4d Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 26 Mar 2019 16:28:53 +0100 Subject: [PATCH] module: fix repl require calling the same file again This makes sure multiple require calls will not fail in case a file was created after the first attempt. PR-URL: https://github.com/nodejs/node/pull/26928 Fixes: https://github.com/nodejs/node/issues/26926 Reviewed-By: Guy Bedford Reviewed-By: Jan Krems --- lib/internal/modules/cjs/loader.js | 16 ++++++------ .../parallel/test-repl-require-after-write.js | 25 +++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 test/parallel/test-repl-require-after-write.js diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 2f06d355460125..e03cece3adb792 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -78,14 +78,15 @@ const { const isWindows = process.platform === 'win32'; let requireDepth = 0; -let statCache = new Map(); +let statCache = null; function stat(filename) { filename = path.toNamespacedPath(filename); - if (statCache === null) statCache = new Map(); - let result = statCache.get(filename); - if (result !== undefined) return result; - result = internalModuleStat(filename); - statCache.set(filename, result); + if (statCache !== null) { + const result = statCache.get(filename); + if (result !== undefined) return result; + } + const result = internalModuleStat(filename); + if (statCache !== null) statCache.set(filename, result); return result; } @@ -188,7 +189,7 @@ Module._debug = deprecate(debug, 'Module._debug is deprecated.', 'DEP0077'); // -> a. // -> a/index. -// check if the directory is a package.json dir +// Check if the directory is a package.json dir. const packageMainCache = Object.create(null); function readPackage(requestPath) { @@ -794,6 +795,7 @@ Module.prototype._compile = function(content, filename) { const exports = this.exports; const thisValue = exports; const module = this; + if (requireDepth === 0) statCache = new Map(); if (inspectorWrapper) { result = inspectorWrapper(compiledWrapper, thisValue, exports, require, module, filename, dirname); diff --git a/test/parallel/test-repl-require-after-write.js b/test/parallel/test-repl-require-after-write.js new file mode 100644 index 00000000000000..e4d9b2f5a024dc --- /dev/null +++ b/test/parallel/test-repl-require-after-write.js @@ -0,0 +1,25 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); + +const spawn = require('child_process').spawn; +// Use -i to force node into interactive mode, despite stdout not being a TTY +const child = spawn(process.execPath, ['-i']); + +let out = ''; +const input = "try { require('./non-existent.json'); } catch {} " + + "require('fs').writeFileSync('./non-existent.json', '1');" + + "require('./non-existent.json');"; + +child.stderr.on('data', common.mustNotCall()); + +child.stdout.setEncoding('utf8'); +child.stdout.on('data', (c) => { + out += c; +}); +child.stdout.on('end', common.mustCall(() => { + assert.strictEqual(out, '> 1\n> '); +})); + +child.stdin.end(input);