| 'use strict'; |
| |
| // This tests to make sure that modules with symlinked circular dependencies |
| // do not blow out the module cache and recurse forever. See issue |
| // https://github.com/nodejs/node/pull/5950 for context. PR #5950 attempted |
| // to solve a problem with symlinked peer dependencies by caching using the |
| // symlink path. Unfortunately, that breaks the case tested in this module |
| // because each symlinked module, despite pointing to the same code on disk, |
| // is loaded and cached as a separate module instance, which blows up the |
| // cache and leads to a recursion bug. |
| |
| // This test should pass in Node.js v4 and v5. It should pass in Node.js v6 |
| // after https://github.com/nodejs/node/pull/5950 has been reverted. |
| |
| 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 |
| |
| const tmpdir = require('../common/tmpdir'); |
| tmpdir.refresh(); |
| const tmpDir = tmpdir.path; |
| |
| 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.mkdirSync(node_modules); |
| fs.mkdirSync(moduleA); |
| fs.mkdirSync(moduleB); |
| fs.mkdirSync(path.join(moduleA, 'node_modules')); |
| fs.mkdirSync(path.join(moduleB, 'node_modules')); |
| |
| try { |
| fs.symlinkSync(moduleA, moduleA_link); |
| fs.symlinkSync(moduleB, moduleB_link); |
| } catch (err) { |
| if (err.code !== 'EPERM') throw err; |
| common.skip('insufficient privileges for symlinks'); |
| } |
| |
| fs.writeFileSync(path.join(tmpDir, 'index.js'), |
| 'module.exports = require(\'moduleA\');', 'utf8'); |
| 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'); |
| |
| // 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); |