diff --git a/lib/module.js b/lib/module.js index ae6f4ff453ccc7..339a228da91bdf 100644 --- a/lib/module.js +++ b/lib/module.js @@ -46,15 +46,17 @@ function stat(filename) { } stat.cache = null; +function updateChildren(parent, child, scan) { + var children = parent && parent.children; + if (children && !(scan && children.includes(child))) + children.push(child); +} function Module(id, parent) { this.id = id; this.exports = {}; this.parent = parent; - if (parent && parent.children) { - parent.children.push(this); - } - + updateChildren(parent, this, false); this.filename = null; this.loaded = false; this.children = []; @@ -438,6 +440,7 @@ Module._load = function(request, parent, isMain) { var cachedModule = Module._cache[filename]; if (cachedModule) { + updateChildren(parent, cachedModule, true); return cachedModule.exports; } @@ -446,6 +449,7 @@ Module._load = function(request, parent, isMain) { return NativeModule.require(filename); } + // Don't call updateChildren(), Module constructor already does. var module = new Module(filename, parent); if (isMain) { diff --git a/test/fixtures/GH-7131/a.js b/test/fixtures/GH-7131/a.js new file mode 100644 index 00000000000000..8c386a4d6188eb --- /dev/null +++ b/test/fixtures/GH-7131/a.js @@ -0,0 +1,5 @@ +'use strict'; +require('sys'); // Builtin should not show up in module.children array. +require('./b'); // This should. +require('./b'); // This should not. +module.exports = module.children.slice(); diff --git a/test/fixtures/GH-7131/b.js b/test/fixtures/GH-7131/b.js new file mode 100644 index 00000000000000..0e7caf36630277 --- /dev/null +++ b/test/fixtures/GH-7131/b.js @@ -0,0 +1,2 @@ +'use strict'; +module.exports = module.children.slice(); diff --git a/test/parallel/test-module-children.js b/test/parallel/test-module-children.js new file mode 100644 index 00000000000000..9eec14fda6ed9e --- /dev/null +++ b/test/parallel/test-module-children.js @@ -0,0 +1,13 @@ +// Flags: --no-deprecation +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const path = require('path'); + +const dir = path.join(common.fixturesDir, 'GH-7131'); +const b = require(path.join(dir, 'b')); +const a = require(path.join(dir, 'a')); + +assert.strictEqual(a.length, 1); +assert.strictEqual(b.length, 0); +assert.deepStrictEqual(a[0].exports, b); diff --git a/test/sequential/test-module-loading.js b/test/sequential/test-module-loading.js index b117555a22cb2b..e59ec247828944 100644 --- a/test/sequential/test-module-loading.js +++ b/test/sequential/test-module-loading.js @@ -237,7 +237,10 @@ try { // modules that we've required, and that all of them contain // the appropriate children, and so on. + const visited = new Set(); const children = module.children.reduce(function red(set, child) { + if (visited.has(child)) return set; + visited.add(child); let id = path.relative(path.dirname(__dirname), child.id); id = id.replace(backslash, '/'); set[id] = child.children.reduce(red, {});