版博士V2.0程序
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

163 строки
4.9 KiB

  1. // this entire module is depressing. i should have spent my time learning
  2. // how to patch v8 so that these options would just be available on the
  3. // process object.
  4. var os = require('os');
  5. var fs = require('fs');
  6. var path = require('path');
  7. var crypto = require('crypto');
  8. var execFile = require('child_process').execFile;
  9. var configPath = require('./config-path.js')(process.platform);
  10. var env = process.env;
  11. var user = env.LOGNAME || env.USER || env.LNAME || env.USERNAME || '';
  12. var exclusions = ['--help', '--completion-bash'];
  13. // This number must be incremented whenever the generated cache file changes.
  14. var CACHE_VERSION = 3;
  15. var configfile =
  16. '.v8flags-' +
  17. CACHE_VERSION +
  18. '-' +
  19. process.versions.v8 +
  20. '.' +
  21. crypto.createHash('sha256').update(user).digest('hex') +
  22. '.json';
  23. var failureMessage = [
  24. 'Unable to cache a config file for v8flags to your home directory',
  25. 'or a temporary folder. To fix this problem, please correct your',
  26. 'environment by setting HOME=/path/to/home or TEMP=/path/to/temp.',
  27. 'NOTE: the user running this must be able to access provided path.',
  28. 'If all else fails, please open an issue here:',
  29. 'http://github.com/tkellen/js-v8flags',
  30. ].join('\n');
  31. function fail(err) {
  32. err.message += '\n\n' + failureMessage;
  33. return err;
  34. }
  35. function openConfig(cb) {
  36. fs.mkdir(configPath, function () {
  37. tryOpenConfig(path.join(configPath, configfile), function (err, fd) {
  38. if (err) {
  39. return tryOpenConfig(path.join(os.tmpdir(), configfile), cb);
  40. }
  41. return cb(null, fd);
  42. });
  43. });
  44. }
  45. function tryOpenConfig(configpath, cb) {
  46. try {
  47. // if the config file is valid, it should be json and therefore
  48. // node should be able to require it directly. if this doesn't
  49. // throw, we're done!
  50. var content = require(configpath);
  51. process.nextTick(function () {
  52. cb(null, content);
  53. });
  54. } catch (e) {
  55. // if requiring the config file failed, maybe it doesn't exist, or
  56. // perhaps it has become corrupted. instead of calling back with the
  57. // content of the file, call back with a file descriptor that we can
  58. // write the cached data to
  59. fs.open(configpath, 'w+', function (err, fd) {
  60. if (err) {
  61. return cb(err);
  62. }
  63. return cb(null, fd);
  64. });
  65. }
  66. }
  67. function normalizeFlagName(flag) {
  68. return flag.trim();
  69. }
  70. // i can't wait for the day this whole module is obsolete because these
  71. // options are available on the process object. this executes node with
  72. // `--v8-options` and parses the result, returning an array of command
  73. // line flags.
  74. function getFlags(cb) {
  75. var flags = Array.from(process.allowedNodeEnvironmentFlags);
  76. execFile(process.execPath, ['--v8-options'], function (execErr, result) {
  77. if (execErr) {
  78. cb(execErr);
  79. return;
  80. }
  81. var index = result.indexOf('\nOptions:');
  82. if (index >= 0) {
  83. var regexp = /^\s\s--[\w-]+/gm;
  84. regexp.lastIndex = index;
  85. var matchedFlags = result.match(regexp);
  86. if (matchedFlags) {
  87. flags = flags.concat(
  88. matchedFlags.map(normalizeFlagName).filter(function (name) {
  89. return exclusions.indexOf(name) === -1;
  90. })
  91. );
  92. }
  93. }
  94. cb(null, flags);
  95. });
  96. }
  97. // write some json to a file descriptor. if this fails, call back
  98. // with both the error and the data that was meant to be written.
  99. function writeConfig(fd, flags, cb) {
  100. var json = JSON.stringify(flags);
  101. var buf = Buffer.from(json);
  102. return fs.write(fd, buf, 0, buf.length, 0, function (writeErr) {
  103. fs.close(fd, function (closeErr) {
  104. var err = writeErr || closeErr;
  105. if (err) {
  106. return cb(fail(err), flags);
  107. }
  108. return cb(null, flags);
  109. });
  110. });
  111. }
  112. module.exports = function (cb) {
  113. // bail early if this is not node
  114. var isElectron = process.versions && process.versions.electron;
  115. if (isElectron) {
  116. return process.nextTick(function () {
  117. cb(null, []);
  118. });
  119. }
  120. // attempt to open/read cache file
  121. openConfig(function (openErr, result) {
  122. if (!openErr && typeof result !== 'number') {
  123. return cb(null, result);
  124. }
  125. // if the result is not an array, we need to go fetch
  126. // the flags by invoking node with `--v8-options`
  127. getFlags(function (flagsErr, flags) {
  128. // if there was an error fetching the flags, bail immediately
  129. if (flagsErr) {
  130. return cb(flagsErr);
  131. }
  132. // if there was a problem opening the config file for writing
  133. // throw an error but include the flags anyway so that users
  134. // can continue to execute (at the expense of having to fetch
  135. // flags on every run until they fix the underyling problem).
  136. if (openErr) {
  137. return cb(fail(openErr), flags);
  138. }
  139. // write the config file to disk so subsequent runs can read
  140. // flags out of a cache file.
  141. return writeConfig(result, flags, cb);
  142. });
  143. });
  144. };
  145. module.exports.configfile = configfile;
  146. module.exports.configPath = configPath;