1'use strict'; 2 3const common = require('../common'); 4 5const assert = require('assert'); 6const fs = require('fs'); 7const path = require('path'); 8 9const rootDir = path.resolve(__dirname, '..', '..'); 10const cliMd = path.join(rootDir, 'doc', 'api', 'cli.md'); 11const cliText = fs.readFileSync(cliMd, { encoding: 'utf8' }); 12 13const parseSection = (text, startMarker, endMarker) => { 14 const regExp = new RegExp(`${startMarker}\r?\n([^]*)\r?\n${endMarker}`); 15 const match = text.match(regExp); 16 assert(match, 17 `Unable to locate text between '${startMarker}' and '${endMarker}'.`); 18 return match[1] 19 .split(/\r?\n/) 20 .filter((val) => val.trim() !== ''); 21}; 22 23const nodeOptionsLines = parseSection(cliText, 24 '<!-- node-options-node start -->', 25 '<!-- node-options-node end -->'); 26const v8OptionsLines = parseSection(cliText, 27 '<!-- node-options-v8 start -->', 28 '<!-- node-options-v8 end -->'); 29 30// Check the options are documented in alphabetical order. 31assert.deepStrictEqual(nodeOptionsLines, [...nodeOptionsLines].sort()); 32assert.deepStrictEqual(v8OptionsLines, [...v8OptionsLines].sort()); 33 34const documented = new Set(); 35for (const line of [...nodeOptionsLines, ...v8OptionsLines]) { 36 for (const match of line.matchAll(/`(-[^`]+)`/g)) { 37 // Remove negation from the option's name. 38 const option = match[1].replace('--no-', '--'); 39 assert(!documented.has(option), 40 `Option '${option}' was documented more than once as an ` + 41 `allowed option for NODE_OPTIONS in ${cliMd}.`); 42 documented.add(option); 43 } 44} 45 46if (!common.hasOpenSSL3) { 47 documented.delete('--openssl-legacy-provider'); 48 documented.delete('--openssl-shared-config'); 49} 50 51// Filter out options that are conditionally present. 52const conditionalOpts = [ 53 { 54 include: common.hasCrypto, 55 filter: (opt) => { 56 return [ 57 '--openssl-config', 58 common.hasOpenSSL3 ? '--openssl-legacy-provider' : '', 59 common.hasOpenSSL3 ? '--openssl-shared-config' : '', 60 '--tls-cipher-list', 61 '--use-bundled-ca', 62 '--use-openssl-ca', 63 '--secure-heap', 64 '--secure-heap-min', 65 '--enable-fips', 66 '--force-fips', 67 ].includes(opt); 68 } 69 }, { 70 include: common.hasIntl, 71 filter: (opt) => opt === '--icu-data-dir' 72 }, { 73 include: process.features.inspector, 74 filter: (opt) => opt.startsWith('--inspect') || opt === '--debug-port' 75 }, 76]; 77documented.forEach((opt) => { 78 conditionalOpts.forEach(({ include, filter }) => { 79 if (!include && filter(opt)) { 80 documented.delete(opt); 81 } 82 }); 83}); 84 85const difference = (setA, setB) => { 86 return new Set([...setA].filter((x) => !setB.has(x))); 87}; 88 89const overdocumented = difference(documented, 90 process.allowedNodeEnvironmentFlags); 91assert.strictEqual(overdocumented.size, 0, 92 'The following options are documented as allowed in ' + 93 `NODE_OPTIONS in ${cliMd}: ` + 94 `${[...overdocumented].join(' ')} ` + 95 'but are not in process.allowedNodeEnvironmentFlags'); 96const undocumented = difference(process.allowedNodeEnvironmentFlags, 97 documented); 98// Remove intentionally undocumented options. 99assert(undocumented.delete('--debug-arraybuffer-allocations')); 100assert(undocumented.delete('--no-debug-arraybuffer-allocations')); 101assert(undocumented.delete('--es-module-specifier-resolution')); 102assert(undocumented.delete('--experimental-report')); 103assert(undocumented.delete('--experimental-worker')); 104assert(undocumented.delete('--node-snapshot')); 105assert(undocumented.delete('--no-node-snapshot')); 106assert(undocumented.delete('--loader')); 107assert(undocumented.delete('--verify-base-objects')); 108assert(undocumented.delete('--no-verify-base-objects')); 109 110// Remove negated versions of the flags. 111for (const flag of undocumented) { 112 if (flag.startsWith('--no-')) { 113 assert(documented.has(`--${flag.slice(5)}`), flag); 114 undocumented.delete(flag); 115 } 116} 117 118assert.strictEqual(undocumented.size, 0, 119 'The following options are not documented as allowed in ' + 120 `NODE_OPTIONS in ${cliMd}: ${[...undocumented].join(' ')}`); 121