• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
15const common = require('../common');
16const assert = require('assert');
17const path = require('path');
18const 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
32const tmpdir = require('../common/tmpdir');
33tmpdir.refresh();
34const tmpDir = tmpdir.path;
35
36const node_modules = path.join(tmpDir, 'node_modules');
37const moduleA = path.join(node_modules, 'moduleA');
38const moduleB = path.join(node_modules, 'moduleB');
39const moduleA_link = path.join(moduleB, 'node_modules', 'moduleA');
40const moduleB_link = path.join(moduleA, 'node_modules', 'moduleB');
41
42fs.mkdirSync(node_modules);
43fs.mkdirSync(moduleA);
44fs.mkdirSync(moduleB);
45fs.mkdirSync(path.join(moduleA, 'node_modules'));
46fs.mkdirSync(path.join(moduleB, 'node_modules'));
47
48try {
49  fs.symlinkSync(moduleA, moduleA_link);
50  fs.symlinkSync(moduleB, moduleB_link);
51} catch (err) {
52  if (err.code !== 'EPERM') throw err;
53  common.skip('insufficient privileges for symlinks');
54}
55
56fs.writeFileSync(path.join(tmpDir, 'index.js'),
57                 'module.exports = require(\'moduleA\');', 'utf8');
58fs.writeFileSync(path.join(moduleA, 'index.js'),
59                 'module.exports = {b: require(\'moduleB\')};', 'utf8');
60fs.writeFileSync(path.join(moduleB, 'index.js'),
61                 'module.exports = {a: require(\'moduleA\')};', 'utf8');
62
63// Ensure that the symlinks are not followed forever...
64const obj = require(path.join(tmpDir, 'index'));
65assert.ok(obj);
66assert.ok(obj.b);
67assert.ok(obj.b.a);
68assert.ok(!obj.b.a.b);
69