11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciconst assert = require('assert'); 61cb0ef41Sopenharmony_ciconst fs = require('fs'); 71cb0ef41Sopenharmony_ciconst path = require('path'); 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciconst rootDir = path.resolve(__dirname, '..', '..'); 101cb0ef41Sopenharmony_ciconst cliMd = path.join(rootDir, 'doc', 'api', 'cli.md'); 111cb0ef41Sopenharmony_ciconst cliText = fs.readFileSync(cliMd, { encoding: 'utf8' }); 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ciconst parseSection = (text, startMarker, endMarker) => { 141cb0ef41Sopenharmony_ci const regExp = new RegExp(`${startMarker}\r?\n([^]*)\r?\n${endMarker}`); 151cb0ef41Sopenharmony_ci const match = text.match(regExp); 161cb0ef41Sopenharmony_ci assert(match, 171cb0ef41Sopenharmony_ci `Unable to locate text between '${startMarker}' and '${endMarker}'.`); 181cb0ef41Sopenharmony_ci return match[1] 191cb0ef41Sopenharmony_ci .split(/\r?\n/) 201cb0ef41Sopenharmony_ci .filter((val) => val.trim() !== ''); 211cb0ef41Sopenharmony_ci}; 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ciconst nodeOptionsLines = parseSection(cliText, 241cb0ef41Sopenharmony_ci '<!-- node-options-node start -->', 251cb0ef41Sopenharmony_ci '<!-- node-options-node end -->'); 261cb0ef41Sopenharmony_ciconst v8OptionsLines = parseSection(cliText, 271cb0ef41Sopenharmony_ci '<!-- node-options-v8 start -->', 281cb0ef41Sopenharmony_ci '<!-- node-options-v8 end -->'); 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci// Check the options are documented in alphabetical order. 311cb0ef41Sopenharmony_ciassert.deepStrictEqual(nodeOptionsLines, [...nodeOptionsLines].sort()); 321cb0ef41Sopenharmony_ciassert.deepStrictEqual(v8OptionsLines, [...v8OptionsLines].sort()); 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ciconst documented = new Set(); 351cb0ef41Sopenharmony_cifor (const line of [...nodeOptionsLines, ...v8OptionsLines]) { 361cb0ef41Sopenharmony_ci for (const match of line.matchAll(/`(-[^`]+)`/g)) { 371cb0ef41Sopenharmony_ci // Remove negation from the option's name. 381cb0ef41Sopenharmony_ci const option = match[1].replace('--no-', '--'); 391cb0ef41Sopenharmony_ci assert(!documented.has(option), 401cb0ef41Sopenharmony_ci `Option '${option}' was documented more than once as an ` + 411cb0ef41Sopenharmony_ci `allowed option for NODE_OPTIONS in ${cliMd}.`); 421cb0ef41Sopenharmony_ci documented.add(option); 431cb0ef41Sopenharmony_ci } 441cb0ef41Sopenharmony_ci} 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ciif (!common.hasOpenSSL3) { 471cb0ef41Sopenharmony_ci documented.delete('--openssl-legacy-provider'); 481cb0ef41Sopenharmony_ci documented.delete('--openssl-shared-config'); 491cb0ef41Sopenharmony_ci} 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci// Filter out options that are conditionally present. 521cb0ef41Sopenharmony_ciconst conditionalOpts = [ 531cb0ef41Sopenharmony_ci { 541cb0ef41Sopenharmony_ci include: common.hasCrypto, 551cb0ef41Sopenharmony_ci filter: (opt) => { 561cb0ef41Sopenharmony_ci return [ 571cb0ef41Sopenharmony_ci '--openssl-config', 581cb0ef41Sopenharmony_ci common.hasOpenSSL3 ? '--openssl-legacy-provider' : '', 591cb0ef41Sopenharmony_ci common.hasOpenSSL3 ? '--openssl-shared-config' : '', 601cb0ef41Sopenharmony_ci '--tls-cipher-list', 611cb0ef41Sopenharmony_ci '--use-bundled-ca', 621cb0ef41Sopenharmony_ci '--use-openssl-ca', 631cb0ef41Sopenharmony_ci '--secure-heap', 641cb0ef41Sopenharmony_ci '--secure-heap-min', 651cb0ef41Sopenharmony_ci '--enable-fips', 661cb0ef41Sopenharmony_ci '--force-fips', 671cb0ef41Sopenharmony_ci ].includes(opt); 681cb0ef41Sopenharmony_ci } 691cb0ef41Sopenharmony_ci }, { 701cb0ef41Sopenharmony_ci include: common.hasIntl, 711cb0ef41Sopenharmony_ci filter: (opt) => opt === '--icu-data-dir' 721cb0ef41Sopenharmony_ci }, { 731cb0ef41Sopenharmony_ci include: process.features.inspector, 741cb0ef41Sopenharmony_ci filter: (opt) => opt.startsWith('--inspect') || opt === '--debug-port' 751cb0ef41Sopenharmony_ci }, 761cb0ef41Sopenharmony_ci]; 771cb0ef41Sopenharmony_cidocumented.forEach((opt) => { 781cb0ef41Sopenharmony_ci conditionalOpts.forEach(({ include, filter }) => { 791cb0ef41Sopenharmony_ci if (!include && filter(opt)) { 801cb0ef41Sopenharmony_ci documented.delete(opt); 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci }); 831cb0ef41Sopenharmony_ci}); 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ciconst difference = (setA, setB) => { 861cb0ef41Sopenharmony_ci return new Set([...setA].filter((x) => !setB.has(x))); 871cb0ef41Sopenharmony_ci}; 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ciconst overdocumented = difference(documented, 901cb0ef41Sopenharmony_ci process.allowedNodeEnvironmentFlags); 911cb0ef41Sopenharmony_ciassert.strictEqual(overdocumented.size, 0, 921cb0ef41Sopenharmony_ci 'The following options are documented as allowed in ' + 931cb0ef41Sopenharmony_ci `NODE_OPTIONS in ${cliMd}: ` + 941cb0ef41Sopenharmony_ci `${[...overdocumented].join(' ')} ` + 951cb0ef41Sopenharmony_ci 'but are not in process.allowedNodeEnvironmentFlags'); 961cb0ef41Sopenharmony_ciconst undocumented = difference(process.allowedNodeEnvironmentFlags, 971cb0ef41Sopenharmony_ci documented); 981cb0ef41Sopenharmony_ci// Remove intentionally undocumented options. 991cb0ef41Sopenharmony_ciassert(undocumented.delete('--debug-arraybuffer-allocations')); 1001cb0ef41Sopenharmony_ciassert(undocumented.delete('--no-debug-arraybuffer-allocations')); 1011cb0ef41Sopenharmony_ciassert(undocumented.delete('--es-module-specifier-resolution')); 1021cb0ef41Sopenharmony_ciassert(undocumented.delete('--experimental-report')); 1031cb0ef41Sopenharmony_ciassert(undocumented.delete('--experimental-worker')); 1041cb0ef41Sopenharmony_ciassert(undocumented.delete('--node-snapshot')); 1051cb0ef41Sopenharmony_ciassert(undocumented.delete('--no-node-snapshot')); 1061cb0ef41Sopenharmony_ciassert(undocumented.delete('--loader')); 1071cb0ef41Sopenharmony_ciassert(undocumented.delete('--verify-base-objects')); 1081cb0ef41Sopenharmony_ciassert(undocumented.delete('--no-verify-base-objects')); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci// Remove negated versions of the flags. 1111cb0ef41Sopenharmony_cifor (const flag of undocumented) { 1121cb0ef41Sopenharmony_ci if (flag.startsWith('--no-')) { 1131cb0ef41Sopenharmony_ci assert(documented.has(`--${flag.slice(5)}`), flag); 1141cb0ef41Sopenharmony_ci undocumented.delete(flag); 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci} 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ciassert.strictEqual(undocumented.size, 0, 1191cb0ef41Sopenharmony_ci 'The following options are not documented as allowed in ' + 1201cb0ef41Sopenharmony_ci `NODE_OPTIONS in ${cliMd}: ${[...undocumented].join(' ')}`); 121