|
| 1 | +'use strict'; |
| 2 | + |
| 3 | +// This tests to make sure that modules with symlinked circular dependencies |
| 4 | +// do not blow out the module cache and recurse forever. See issue |
| 5 | +// https://github.com/nodejs/node/pull/5950 for context. PR #5950 attempted |
| 6 | +// to solve a problem with symlinked peer dependencies by caching using the |
| 7 | +// symlink path. Unfortunately, that breaks the case tested in this module |
| 8 | +// because each symlinked module, despite pointing to the same code on disk, |
| 9 | +// is loaded and cached as a separate module instance, which blows up the |
| 10 | +// cache and leads to a recursion bug. |
| 11 | + |
| 12 | +// This test should pass in Node.js v4 and v5. It should pass in Node.js v6 |
| 13 | +// after https://github.com/nodejs/node/pull/5950 has been reverted. |
| 14 | + |
| 15 | +const common = require('../common'); |
| 16 | +const assert = require('assert'); |
| 17 | +const path = require('path'); |
| 18 | +const fs = require('fs'); |
| 19 | + |
| 20 | +// {tmpDir} |
| 21 | +// ├── index.js |
| 22 | +// └── node_modules |
| 23 | +// ├── moduleA |
| 24 | +// │ ├── index.js |
| 25 | +// │ └── node_modules |
| 26 | +// │ └── moduleB -> {tmpDir}/node_modules/moduleB |
| 27 | +// └── moduleB |
| 28 | +// ├── index.js |
| 29 | +// └── node_modules |
| 30 | +// └── moduleA -> {tmpDir}/node_modules/moduleA |
| 31 | + |
| 32 | +common.refreshTmpDir(); |
| 33 | +const tmpDir = common.tmpDir; |
| 34 | + |
| 35 | +const node_modules = path.join(tmpDir, 'node_modules'); |
| 36 | +const moduleA = path.join(node_modules, 'moduleA'); |
| 37 | +const moduleB = path.join(node_modules, 'moduleB'); |
| 38 | +const moduleA_link = path.join(moduleB, 'node_modules', 'moduleA'); |
| 39 | +const moduleB_link = path.join(moduleA, 'node_modules', 'moduleB'); |
| 40 | + |
| 41 | +fs.mkdirSync(node_modules); |
| 42 | +fs.mkdirSync(moduleA); |
| 43 | +fs.mkdirSync(moduleB); |
| 44 | +fs.mkdirSync(path.join(moduleA, 'node_modules')); |
| 45 | +fs.mkdirSync(path.join(moduleB, 'node_modules')); |
| 46 | + |
| 47 | +try { |
| 48 | + fs.symlinkSync(moduleA, moduleA_link); |
| 49 | + fs.symlinkSync(moduleB, moduleB_link); |
| 50 | +} catch (err) { |
| 51 | + if (err.code !== 'EPERM') throw err; |
| 52 | + common.skip('insufficient privileges for symlinks'); |
| 53 | + return; |
| 54 | +} |
| 55 | + |
| 56 | +fs.writeFileSync(path.join(tmpDir, 'index.js'), |
| 57 | + 'module.exports = require(\'moduleA\');', 'utf8'); |
| 58 | +fs.writeFileSync(path.join(moduleA, 'index.js'), |
| 59 | + 'module.exports = {b: require(\'moduleB\')};', 'utf8'); |
| 60 | +fs.writeFileSync(path.join(moduleB, 'index.js'), |
| 61 | + 'module.exports = {a: require(\'moduleA\')};', 'utf8'); |
| 62 | + |
| 63 | +// Ensure that the symlinks are not followed forever... |
| 64 | +const obj = require(path.join(tmpDir, 'index')); |
| 65 | +assert.ok(obj); |
| 66 | +assert.ok(obj.b); |
| 67 | +assert.ok(obj.b.a); |
| 68 | +assert.ok(!obj.b.a.b); |
0 commit comments