node-options.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // Replacement for node's internal 'internal/options' module
  2. exports.getOptionValue = getOptionValue;
  3. function getOptionValue(opt) {
  4. parseOptions();
  5. return options[opt];
  6. }
  7. let options;
  8. function parseOptions() {
  9. if (!options) {
  10. options = {
  11. '--preserve-symlinks': false,
  12. '--preserve-symlinks-main': false,
  13. '--input-type': undefined,
  14. '--experimental-specifier-resolution': 'explicit',
  15. '--experimental-policy': undefined,
  16. '--conditions': [],
  17. '--pending-deprecation': false,
  18. ...parseArgv(getNodeOptionsEnvArgv()),
  19. ...parseArgv(process.execArgv),
  20. ...getOptionValuesFromOtherEnvVars()
  21. }
  22. }
  23. }
  24. function parseArgv(argv) {
  25. return require('arg')({
  26. '--preserve-symlinks': Boolean,
  27. '--preserve-symlinks-main': Boolean,
  28. '--input-type': String,
  29. '--experimental-specifier-resolution': String,
  30. // Legacy alias for node versions prior to 12.16
  31. '--es-module-specifier-resolution': '--experimental-specifier-resolution',
  32. '--experimental-policy': String,
  33. '--conditions': [String],
  34. '--pending-deprecation': Boolean
  35. }, {
  36. argv,
  37. permissive: true
  38. });
  39. }
  40. function getNodeOptionsEnvArgv() {
  41. const errors = [];
  42. const envArgv = ParseNodeOptionsEnvVar(process.env.NODE_OPTIONS || '', errors);
  43. if (errors.length !== 0) {
  44. // TODO: handle errors somehow
  45. }
  46. return envArgv;
  47. }
  48. // Direct JS port of C implementation: https://github.com/nodejs/node/blob/67ba825037b4082d5d16f922fb9ce54516b4a869/src/node_options.cc#L1024-L1063
  49. function ParseNodeOptionsEnvVar(node_options, errors) {
  50. const env_argv = [];
  51. let is_in_string = false;
  52. let will_start_new_arg = true;
  53. for (let index = 0; index < node_options.length; ++index) {
  54. let c = node_options[index];
  55. // Backslashes escape the following character
  56. if (c === '\\' && is_in_string) {
  57. if (index + 1 === node_options.length) {
  58. errors.push("invalid value for NODE_OPTIONS " +
  59. "(invalid escape)\n");
  60. return env_argv;
  61. } else {
  62. c = node_options[++index];
  63. }
  64. } else if (c === ' ' && !is_in_string) {
  65. will_start_new_arg = true;
  66. continue;
  67. } else if (c === '"') {
  68. is_in_string = !is_in_string;
  69. continue;
  70. }
  71. if (will_start_new_arg) {
  72. env_argv.push(c);
  73. will_start_new_arg = false;
  74. } else {
  75. env_argv[env_argv.length - 1] += c;
  76. }
  77. }
  78. if (is_in_string) {
  79. errors.push("invalid value for NODE_OPTIONS " +
  80. "(unterminated string)\n");
  81. }
  82. return env_argv;
  83. }
  84. // Get option values that can be specified via env vars besides NODE_OPTIONS
  85. function getOptionValuesFromOtherEnvVars() {
  86. const options = {};
  87. if(process.env.NODE_PENDING_DEPRECATION === '1') {
  88. options['--pending-deprecation'] = true;
  89. }
  90. return options;
  91. }