1// Flags: --preserve-symlinks 2'use strict'; 3const common = require('../common'); 4 5if (!common.canCreateSymLink()) 6 common.skip('insufficient privileges'); 7if (!common.isMainThread) 8 common.skip('process.chdir is not available in Workers'); 9 10const assert = require('assert'); 11const { spawn } = require('child_process'); 12const fs = require('fs'); 13const path = require('path'); 14const process = require('process'); 15const { Worker } = require('worker_threads'); 16 17// Setup: Copy fixtures to tmp directory. 18 19const fixtures = require('../common/fixtures'); 20const tmpdir = require('../common/tmpdir'); 21const dirName = 'module-require-symlink'; 22const fixtureSource = fixtures.path(dirName); 23const tmpDirTarget = path.join(tmpdir.path, dirName); 24 25// Copy fixtureSource to linkTarget recursively. 26tmpdir.refresh(); 27 28function copyDir(source, target) { 29 fs.mkdirSync(target); 30 fs.readdirSync(source).forEach((entry) => { 31 const fullPathSource = path.join(source, entry); 32 const fullPathTarget = path.join(target, entry); 33 const stats = fs.statSync(fullPathSource); 34 if (stats.isDirectory()) { 35 copyDir(fullPathSource, fullPathTarget); 36 } else { 37 fs.copyFileSync(fullPathSource, fullPathTarget); 38 } 39 }); 40} 41 42copyDir(fixtureSource, tmpDirTarget); 43 44// Move to tmp dir and do everything with relative paths there so that the test 45// doesn't incorrectly fail due to a symlink somewhere else in the absolute 46// path. 47process.chdir(tmpdir.path); 48 49const linkDir = path.join(dirName, 50 'node_modules', 51 'dep1', 52 'node_modules', 53 'dep2'); 54 55const linkTarget = path.join('..', '..', 'dep2'); 56 57const linkScript = './linkscript.js'; 58 59const linkScriptTarget = path.join(dirName, 'symlinked.js'); 60 61test(); 62 63function test() { 64 fs.symlinkSync(linkTarget, linkDir, 'dir'); 65 fs.symlinkSync(linkScriptTarget, linkScript); 66 67 // Load symlinked-module 68 const fooModule = require(path.join(tmpDirTarget, 'foo.js')); 69 assert.strictEqual(fooModule.dep1.bar.version, 'CORRECT_VERSION'); 70 assert.strictEqual(fooModule.dep2.bar.version, 'CORRECT_VERSION'); 71 72 // Load symlinked-script as main 73 const node = process.execPath; 74 const child = spawn(node, ['--preserve-symlinks', linkScript]); 75 child.on('close', function(code, signal) { 76 assert.strictEqual(code, 0); 77 assert(!signal); 78 }); 79 80 // Also verify that symlinks works for setting preserve via env variables 81 const childEnv = spawn(node, [linkScript], { 82 env: { ...process.env, NODE_PRESERVE_SYMLINKS: '1' } 83 }); 84 childEnv.on('close', function(code, signal) { 85 assert.strictEqual(code, 0); 86 assert(!signal); 87 }); 88 89 // Also verify that symlinks works for setting preserve via env variables in 90 // Workers. 91 const worker = new Worker(linkScript, { 92 env: { ...process.env, NODE_PRESERVE_SYMLINKS: '1' } 93 }); 94 worker.on('error', (err) => { 95 console.log('Worker failed'); 96 throw err; 97 }); 98 worker.on('exit', common.mustCall((code) => { 99 assert.strictEqual(code, 0); 100 })); 101 102 // Also verify that symlinks works for setting preserve via env variables in 103 // Workers with explicit execArgv. 104 const workerArgv = new Worker(linkScript, { 105 execArgv: [], 106 env: { ...process.env, NODE_PRESERVE_SYMLINKS: '1' } 107 }); 108 workerArgv.on('error', (err) => { 109 console.log('Worker with execArgv failed'); 110 throw err; 111 }); 112 workerArgv.on('exit', common.mustCall((code) => { 113 assert.strictEqual(code, 0); 114 })); 115} 116