1 | #!/usr/bin/env node
|
2 |
|
3 | var spawn = require('child_process').spawn;
|
4 | var node = process.execPath || process.argv[0];
|
5 | var HG = '--harmony_generators';
|
6 |
|
7 | var regenerator = require('regenerator')
|
8 |
|
9 | // first check if the current node executable has "Generators".
|
10 | // if not, fall back to facebook/regenerator for Generators support.
|
11 | hasGenerators(function (err, has) {
|
12 | if (err) throw err;
|
13 |
|
14 | // build up the node(1) arguments for Generator support
|
15 | var argv = (process.execArgv || []).slice(0);
|
16 |
|
17 | // process the regular arguments. if any of them begin with a hyphen (-) then
|
18 | // it's a switch and should be added *before* the ENTRY_POINT in the argv...
|
19 | var argsStart = 2;
|
20 | for (var i = argsStart; i < process.argv.length; i++) {
|
21 | var arg = process.argv[i];
|
22 | var isFlag = '-' == arg[0];
|
23 | if (isFlag) {
|
24 | if (!/^--harmony[_-]generators$/.test(arg)) {
|
25 | argv.push(arg);
|
26 | }
|
27 |
|
28 | argsStart++;
|
29 |
|
30 | if (/^-[ep]$/.test(arg)) {
|
31 | // handle gnode -e|-p "console.log('script')"
|
32 | var code = process.argv[i + 1]
|
33 | if (!has) {
|
34 | code = regenerator.compile(code, {
|
35 | includeRuntime: true
|
36 | }).code;
|
37 | }
|
38 | argv.push(code)
|
39 | // skip arg, we just processed it
|
40 | i++
|
41 | }
|
42 | } else {
|
43 | // must be the script file
|
44 | break;
|
45 | }
|
46 | }
|
47 |
|
48 | if (has && -1 == argv.indexOf(HG) && -1 == argv.indexOf('--harmony-generators')) {
|
49 | // if the node process natively supports Generators,
|
50 | // then add the --harmony_generators flag
|
51 | argv.push(HG);
|
52 | }
|
53 |
|
54 | if (!has) {
|
55 | // no Generator support, then we need to load fallback.js first
|
56 | argv.push(require('path').resolve(__dirname, '..', 'fallback.js'));
|
57 |
|
58 | // store a reference to the entry point, so that fallback.js can pick it up
|
59 | if (process.argv.length > argsStart) {
|
60 | process.env.GNODE_ENTRY_POINT = process.argv[argsStart];
|
61 | }
|
62 |
|
63 | argsStart++;
|
64 | }
|
65 |
|
66 | // add the rest of the arguments specified by the user
|
67 | if (process.argv.length >= argsStart) {
|
68 | argv.push.apply(argv, process.argv.slice(argsStart));
|
69 | }
|
70 |
|
71 | if (parseInt(process.env.GNODE_PRINT_ARGS, 10)) {
|
72 | // print out the arguments that will be passed in for debugging purposes
|
73 | console.error(argv);
|
74 | }
|
75 |
|
76 | var opts = {
|
77 | customFds: [ 0, 1, 2 ],
|
78 | stdio: 'inherit'
|
79 | };
|
80 |
|
81 | // spawn a new node process with the necessary flags
|
82 | var child = spawn(node, argv, opts);
|
83 | child.on('exit', onexit);
|
84 | });
|
85 |
|
86 | /**
|
87 | * Main node subprocess "exit" event handler.
|
88 | * Proxies the exit code up to this process.
|
89 | *
|
90 | * @api private
|
91 | */
|
92 |
|
93 | function onexit(code, signal) {
|
94 | if (signal) {
|
95 | process.kill(process.pid, signal);
|
96 | } else if (0 !== code) {
|
97 | if (null == process.exitCode) {
|
98 | // old node, no `process.exitCode` support...
|
99 | process.exit(code);
|
100 | } else {
|
101 | // newer node, we can set `process.exitCode`
|
102 | // and let the process exit naturally
|
103 | process.exitCode = code;
|
104 | }
|
105 | }
|
106 | }
|
107 |
|
108 | /**
|
109 | * Async function that returns `true`/`false` for if Generators are
|
110 | * supported by V8.
|
111 | *
|
112 | * @api private
|
113 | */
|
114 |
|
115 | function hasGenerators (fn) {
|
116 | var cp = spawn(node, [ '--v8-options' ]);
|
117 | var data = '';
|
118 |
|
119 | function onerror (e) {
|
120 | fn(e);
|
121 | }
|
122 | function ondata (b) {
|
123 | data += b;
|
124 | }
|
125 | function onend () {
|
126 | cp.removeListener('error', onerror);
|
127 | var has = -1 != data.indexOf(HG);
|
128 | fn(null, has);
|
129 | }
|
130 |
|
131 | cp.on('error', onerror);
|
132 | cp.stdout.setEncoding('utf8');
|
133 | cp.stdout.on('data', ondata);
|
134 | cp.stdout.on('end', onend);
|
135 | }
|