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 81function expectNoWorker(opt, want, command, wantsError) { 82 expect(opt, want, command, wantsError, false); 83} 84 85function expect( 86 opt, want, command = 'console.log("B")', wantsError = false, testWorker = true 87) { 88 const argv = ['-e', command]; 89 const opts = { 90 cwd: tmpdir.path, 91 env: Object.assign({}, process.env, { NODE_OPTIONS: opt }), 92 maxBuffer: 1e6, 93 }; 94 if (typeof want === 'string') 95 want = new RegExp(want); 96 97 const test = (type) => common.mustCall((err, stdout) => { 98 const o = JSON.stringify(opt); 99 if (wantsError) { 100 assert.ok(err, `${type}: expected error for ${o}`); 101 stdout = err.stack; 102 } else { 103 assert.ifError(err, `${type}: failed for ${o}`); 104 } 105 if (want.test(stdout)) return; 106 107 assert.fail( 108 `${type}: for ${o}, failed to find ${want} in: <\n${stdout}\n>` 109 ); 110 }); 111 112 exec(process.execPath, argv, opts, test('child process')); 113 if (testWorker) 114 workerTest(opts, command, wantsError, test('worker')); 115} 116 117async function collectStream(readable) { 118 readable.setEncoding('utf8'); 119 let data = ''; 120 for await (const chunk of readable) { 121 data += chunk; 122 } 123 return data; 124} 125 126function workerTest(opts, command, wantsError, test) { 127 let workerError = null; 128 const worker = new Worker(command, { 129 ...opts, 130 execArgv: [], 131 eval: true, 132 stdout: true, 133 stderr: true 134 }); 135 worker.on('error', (err) => { 136 workerError = err; 137 }); 138 worker.on('exit', common.mustCall((code) => { 139 assert.strictEqual(code, wantsError ? 1 : 0); 140 collectStream(worker.stdout).then((stdout) => { 141 test(workerError, stdout); 142 }); 143 })); 144} 145