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