UNPKG

5.13 kBJavaScriptView Raw
1var fs = require('fs');
2var path = require('path');
3var commander = require('commander');
4var mkdirp = require('mkdirp');
5var meta = require('../package.json');
6var continuation = require('../continuation');
7
8var options = {
9 compileMark: false
10};
11
12//Try to load CoffeeScript
13try {
14 var coffee = require('coffee-script');
15} catch (e) {
16 coffee = null;
17}
18//Try to load LiveScript
19try {
20 var live = require('LiveScript');
21} catch (e) {
22 live = null;
23}
24
25var cacheDefaultPath = '/tmp/continuation';
26
27var initialize = function () {
28 commander.version(meta.version);
29 commander.usage('[options] <file.js/file.coffee> [arguments]');
30 commander.option('-p, --print', 'compile script file and print it');
31 commander.option('-o, --output <filename>', 'compile script file and save as <filename>');
32 commander.option('-e, --explicit', 'compile only if "use continuation" is explicitly declared');
33 commander.option('-c, --cache [directory]', 'run and cache compiled sources to [directory], by default [directory] is ' + cacheDefaultPath);
34 commander.option('-v, --verbose', 'print verbosal information to stderr');
35 commander.parse(process.argv);
36};
37
38var main = exports.main = function () {
39 initialize();
40
41 var filename = commander.args[0];
42 if (commander.explicit) {
43 options.compileMark = true;
44 }
45 if (commander.cache) {
46 options.cache = commander.cache;
47 if (options.cache === true) {
48 options.cache = cacheDefaultPath;
49 }
50 }
51 if (commander.verbose) {
52 options.verbose = true;
53 }
54
55 try {
56 if (!filename) throw new Error('You should specify a script file.');
57 filename = fs.realpathSync(filename);
58 } catch (e) {
59 console.error(e.toString());
60 console.error(commander.helpInformation());
61 process.exit(-1);
62 }
63 var code = readAndCompile(filename);
64
65 var print = false;
66 if (commander.print)
67 print = true;
68 if (commander.output)
69 print = true;
70
71 if (print) {
72 outputCode(code);
73 } else {
74 runCode(code, filename);
75 }
76};
77
78var outputCode = function (code) {
79 if (commander.output) {
80 fs.writeFile(commander.output, code, function (err) {
81 if (err) throw err;
82 });
83 } else {
84 console.log(code);
85 }
86};
87
88var runCode = function (code, filename) {
89 //Set current module information
90 var mainModule = require.main;
91 mainModule.filename = filename;
92 mainModule.moduleCache = {};
93 mainModule.children = [];
94 mainModule.paths = calculatePaths(filename);
95
96 //Register require handler
97 require.extensions['.js'] = compileAndRun;
98 if (coffee !== null) {
99 require.extensions['.coffee'] = compileAndRun;
100 }
101
102 //Generate program arguments
103 var args = commander.args.slice(1);
104 process.argv = [process.argv[0], filename].concat(args);
105
106 //Run
107 mainModule._compile(code, filename);
108};
109
110var readAndCompile = function (filename) {
111 if (options.verbose) {
112 console.error('Load ' + filename);
113 }
114
115 if (options.cache) {
116 code = readCache(filename);
117 if (code !== null) {
118 if (options.verbose) {
119 console.error('Cache hit');
120 }
121 return code;
122 }
123 }
124
125 var code = fs.readFileSync(filename, 'utf-8');
126
127 try {
128 var ext = path.extname(filename);
129 if (ext === '.coffee') {
130 //Coffee-script support
131 if (coffee !== null) {
132 code = coffee.compile(code);
133 } else {
134 throw new Error('Can not find CoffeeScript module');
135 }
136 } else if (ext === '.ls') {
137 //LiveScript support
138 if (live !== null) {
139 code = live.compile(code);
140 } else {
141 throw new Error('Can not find LiveScript module');
142 }
143 }
144 code = continuation.compile(code, options);
145 } catch (err) {
146 console.error('In file', filename);
147 console.error(err.stack);
148 process.exit(-1);
149 }
150
151 if (options.cache) {
152 if (options.verbose) {
153 console.error('Cache updated');
154 }
155 writeCache(filename, code);
156 }
157
158 return code;
159};
160
161var compileAndRun = function (module, filename) {
162 global.currentFilename = filename;
163 var code = readAndCompile(filename);
164 module._compile(code, filename);
165};
166
167var calculatePaths = function (filename) {
168 var paths = [];
169 var pathSec = path.dirname(filename).split(path.sep);
170 while (pathSec.length > 0) {
171 var modulePath = pathSec.join(path.sep);
172 modulePath += path.sep + 'node_modules';
173 paths.push(modulePath);
174 pathSec.pop();
175 }
176 return paths;
177};
178
179var getCachedFilePath = function (filename) {
180 return path.join(options.cache, filename + '_c.js');
181};
182
183var readCache = function (filename) {
184 var cachedFilePath = getCachedFilePath(filename);
185 var exists = fs.existsSync(cachedFilePath);
186 if (!exists) {
187 return null;
188 }
189
190 var stat = fs.lstatSync(cachedFilePath);
191 var cacheMtime = stat.mtime;
192 var stat = fs.lstatSync(filename);
193 var sourceMtime = stat.mtime;
194
195 if (sourceMtime > cacheMtime) {
196 return null;
197 }
198
199 return fs.readFileSync(cachedFilePath, 'utf-8');
200};
201
202var writeCache = function (filename, code) {
203 var cachedFilePath = getCachedFilePath(filename);
204 mkdirp.sync(path.dirname(cachedFilePath), 0777);
205 fs.writeFileSync(cachedFilePath, code);
206};