1'use strict'; 2const common = require('../common'); 3if (process.config.variables.node_without_node_options) 4 common.skip('missing NODE_OPTIONS support'); 5 6// Test options specified by env variable. 7 8const assert = require('assert'); 9const exec = require('child_process').execFile; 10const { Worker } = require('worker_threads'); 11 12const tmpdir = require('../common/tmpdir'); 13tmpdir.refresh(); 14 15const printA = require.resolve('../fixtures/printA.js'); 16const printSpaceA = require.resolve('../fixtures/print A.js'); 17 18expectNoWorker(` -r ${printA} `, 'A\nB\n'); 19expectNoWorker(`-r ${printA}`, 'A\nB\n'); 20expectNoWorker(`-r ${JSON.stringify(printA)}`, 'A\nB\n'); 21expectNoWorker(`-r ${JSON.stringify(printSpaceA)}`, 'A\nB\n'); 22expectNoWorker(`-r ${printA} -r ${printA}`, 'A\nB\n'); 23expectNoWorker(` -r ${printA} -r ${printA}`, 'A\nB\n'); 24expectNoWorker(` --require ${printA} --require ${printA}`, 'A\nB\n'); 25expect('--no-deprecation', 'B\n'); 26expect('--no-warnings', 'B\n'); 27expect('--no_warnings', 'B\n'); 28expect('--trace-warnings', 'B\n'); 29expect('--redirect-warnings=_', 'B\n'); 30expect('--trace-deprecation', 'B\n'); 31expect('--trace-sync-io', 'B\n'); 32expectNoWorker('--trace-events-enabled', 'B\n'); 33expect('--track-heap-objects', 'B\n'); 34expect('--throw-deprecation', 35 /.*DeprecationWarning: Buffer\(\) is deprecated due to security and usability issues.*/, 36 'new Buffer(42)', 37 true); 38expectNoWorker('--zero-fill-buffers', 'B\n'); 39expectNoWorker('--v8-pool-size=10', 'B\n'); 40expectNoWorker('--trace-event-categories node', 'B\n'); 41expectNoWorker( 42 // eslint-disable-next-line no-template-curly-in-string 43 '--trace-event-file-pattern {pid}-${rotation}.trace_events', 44 'B\n' 45); 46// eslint-disable-next-line no-template-curly-in-string 47expectNoWorker('--trace-event-file-pattern {pid}-${rotation}.trace_events ' + 48 '--trace-event-categories node.async_hooks', 'B\n'); 49expect('--unhandled-rejections=none', 'B\n'); 50 51if (common.isLinux) { 52 expect('--perf-basic-prof', 'B\n'); 53 expect('--perf-basic-prof-only-functions', 'B\n'); 54 55 if (['arm', 'x64'].includes(process.arch)) { 56 expect('--perf-prof', 'B\n'); 57 expect('--perf-prof-unwinding-info', 'B\n'); 58 } 59} 60 61if (common.hasCrypto) { 62 expectNoWorker('--use-openssl-ca', 'B\n'); 63 expectNoWorker('--use-bundled-ca', 'B\n'); 64 expectNoWorker('--openssl-config=_ossl_cfg', 'B\n'); 65} 66 67// V8 options 68expect('--abort_on-uncaught_exception', 'B\n'); 69expect('--disallow-code-generation-from-strings', 'B\n'); 70expect('--huge-max-old-generation-size', 'B\n'); 71expect('--jitless', 'B\n'); 72expect('--max-old-space-size=0', 'B\n'); 73expect('--stack-trace-limit=100', 74 /(\s*at f \(\[(eval|worker eval)\]:1:\d*\)\r?\n)/, 75 '(function f() { f(); })();', 76 true); 77// Unsupported on arm. See https://crbug.com/v8/8713. 78if (!['arm', 'arm64'].includes(process.arch)) 79 expect('--interpreted-frames-native-stack', 'B\n'); 80 81// Workers can't eval as ES Modules. https://github.com/nodejs/node/issues/30682 82expectNoWorker('--input-type=module', 83 'B\n', 'console.log(await "B")'); 84 85function expectNoWorker(opt, want, command, wantsError) { 86 expect(opt, want, command, wantsError, false); 87} 88 89function expect( 90 opt, want, command = 'console.log("B")', wantsError = false, testWorker = true 91) { 92 const argv = ['-e', command]; 93 const opts = { 94 cwd: tmpdir.path, 95 env: Object.assign({}, process.env, { NODE_OPTIONS: opt }), 96 maxBuffer: 1e6, 97 }; 98 if (typeof want === 'string') 99 want = new RegExp(want); 100 101 const test = (type) => common.mustCall((err, stdout) => { 102 const o = JSON.stringify(opt); 103 if (wantsError) { 104 assert.ok(err, `${type}: expected error for ${o}`); 105 stdout = err.stack; 106 } else { 107 assert.ifError(err, `${type}: failed for ${o}`); 108 } 109 if (want.test(stdout)) return; 110 111 assert.fail( 112 `${type}: for ${o}, failed to find ${want} in: <\n${stdout}\n>` 113 ); 114 }); 115 116 exec(process.execPath, argv, opts, test('child process')); 117 if (testWorker) 118 workerTest(opts, command, wantsError, test('worker')); 119} 120 121async function collectStream(readable) { 122 readable.setEncoding('utf8'); 123 let data = ''; 124 for await (const chunk of readable) { 125 data += chunk; 126 } 127 return data; 128} 129 130function workerTest(opts, command, wantsError, test) { 131 let workerError = null; 132 const worker = new Worker(command, { 133 ...opts, 134 execArgv: [], 135 eval: true, 136 stdout: true, 137 stderr: true 138 }); 139 worker.on('error', (err) => { 140 workerError = err; 141 }); 142 worker.on('exit', common.mustCall((code) => { 143 assert.strictEqual(code, wantsError ? 1 : 0); 144 collectStream(worker.stdout).then((stdout) => { 145 test(workerError, stdout); 146 }); 147 })); 148} 149