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