diff --git a/test/known_issues/test-symlinked-peer-modules.js b/test/known_issues/test-symlinked-peer-modules.js new file mode 100644 index 00000000000000..ea03963671869e --- /dev/null +++ b/test/known_issues/test-symlinked-peer-modules.js @@ -0,0 +1,60 @@ +/* eslint no-irregular-whitespace: 0 */ +'use strict'; +// Refs: https://github.com/nodejs/node/pull/5950 + +// This test illustrates the problem that symlinked modules are unable +// to find their peer dependencies. This was fixed in #5950 but that is +// reverted because that particular way of fixing it causes too much +// breakage (breakage that was not caught by either CI or CITGM on multiple +// runs. + +const common = require('../common'); +const fs = require('fs'); +const path = require('path'); +const assert = require('assert'); + +common.refreshTmpDir(); + +const tmpDir = common.tmpDir; + +// Creates the following structure +// {tmpDir} +// ├── app +// │   ├── index.js +// │   └── node_modules +// │   ├── moduleA -> {tmpDir}/moduleA +// │   └── moduleB +// │   ├── index.js +// │   └── package.json +// └── moduleA +// ├── index.js +// └── package.json + +const moduleA = path.join(tmpDir, 'moduleA'); +const app = path.join(tmpDir, 'app'); +const moduleB = path.join(app, 'node_modules', 'moduleB'); +const moduleA_link = path.join(app, 'node_modules', 'moduleA'); + +fs.mkdirSync(moduleA); +fs.writeFileSync(path.join(moduleA, 'package.json'), + JSON.stringify({name: 'moduleA', main: 'index.js'}), 'utf8'); +fs.writeFileSync(path.join(moduleA, 'index.js'), + 'module.exports = require(\'moduleB\');'); + +fs.mkdirSync(app); +fs.writeFileSync(path.join(app, 'index.js'), + '\'use strict\'; require(\'moduleA\');'); +fs.mkdirSync(path.join(app, 'node_modules')); + +fs.mkdirSync(moduleB); +fs.writeFileSync(path.join(moduleB, 'package.json'), + JSON.stringify({name: 'moduleB', main: 'index.js'}), 'utf8'); +fs.writeFileSync(path.join(moduleB, 'index.js'), + 'module.exports = 1;'); + +fs.symlinkSync(moduleA, moduleA_link); + +// This should not throw, but it does +assert.doesNotThrow(() => { + console.log(require(path.join(app, 'index'))); +}); diff --git a/test/sequential/test-module-circular-symlinks.js b/test/sequential/test-module-circular-symlinks.js new file mode 100644 index 00000000000000..8de68291bc2b93 --- /dev/null +++ b/test/sequential/test-module-circular-symlinks.js @@ -0,0 +1,49 @@ +/* eslint no-irregular-whitespace: 0 */ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const path = require('path'); +const fs = require('fs'); + +// {tmpDir} +// ├── index.js +// └── node_modules +// ├── moduleA +// │   ├── index.js +// │   └── node_modules +// │   └── moduleB -> {tmpDir}/node_modules/moduleB +// └── moduleB +// ├── index.js +// └── node_modules +// └── moduleA -> {tmpDir}/node_modules/moduleA + +common.refreshTmpDir(); +const tmpDir = common.tmpDir; + +const node_modules = path.join(tmpDir, 'node_modules'); +const moduleA = path.join(node_modules, 'moduleA'); +const moduleB = path.join(node_modules, 'moduleB'); +const moduleA_link = path.join(moduleB, 'node_modules', 'moduleA'); +const moduleB_link = path.join(moduleA, 'node_modules', 'moduleB'); + +fs.writeFileSync(path.join(tmpDir, 'index.js'), + 'module.exports = require(\'moduleA\');', 'utf8'); +fs.mkdirSync(node_modules); +fs.mkdirSync(moduleA); +fs.mkdirSync(moduleB); +fs.writeFileSync(path.join(moduleA, 'index.js'), + 'module.exports = {b: require(\'moduleB\')};', 'utf8'); +fs.writeFileSync(path.join(moduleB, 'index.js'), + 'module.exports = {a: require(\'moduleA\')};', 'utf8'); +fs.mkdirSync(path.join(moduleA, 'node_modules')); +fs.mkdirSync(path.join(moduleB, 'node_modules')); +fs.symlinkSync(moduleA, moduleA_link); +fs.symlinkSync(moduleB, moduleB_link); + +// Ensure that the symlinks are not followed forever... +const obj = require(path.join(tmpDir, 'index')); +assert.ok(obj); +assert.ok(obj.b); +assert.ok(obj.b.a); +assert.ok(!obj.b.a.b);